📄 convolve.c
字号:
/* * Mesa 3-D graphics library * Version: 6.5.2 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//* * Image convolution functions. * * Notes: filter kernel elements are indexed by <n> and <m> as in * the GL spec. */#include "glheader.h"#include "bufferobj.h"#include "colormac.h"#include "convolve.h"#include "context.h"#include "image.h"#include "mtypes.h"#include "pixel.h"#include "state.h"/* * Given an internalFormat token passed to glConvolutionFilter * or glSeparableFilter, return the corresponding base format. * Return -1 if invalid token. */static GLintbase_filter_format( GLenum format ){ switch (format) { case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: return GL_ALPHA; case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: return GL_LUMINANCE; case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: return GL_LUMINANCE_ALPHA; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: return GL_INTENSITY; case GL_RGB: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: return GL_RGB; case 4: case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: return GL_RGBA; default: return -1; /* error */ }}void GLAPIENTRY_mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *image){ GLint baseFormat; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (target != GL_CONVOLUTION_1D) { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(target)"); return; } baseFormat = base_filter_format(internalFormat); if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(internalFormat)"); return; } if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter1D(width)"); return; } if (!_mesa_is_legal_format_and_type(ctx, format, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(format or type)"); return; } if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX || format == GL_DEPTH_COMPONENT || format == GL_INTENSITY || type == GL_BITMAP) { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(format or type)"); return; } ctx->Convolution1D.Format = format; ctx->Convolution1D.InternalFormat = internalFormat; ctx->Convolution1D.Width = width; ctx->Convolution1D.Height = 1; if (ctx->Unpack.BufferObj->Name) { /* unpack filter from PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, format, type, image)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(invalid PBO access)"); return; } buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, GL_READ_ONLY_ARB, ctx->Unpack.BufferObj); if (!buf) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(PBO is mapped)"); return; } image = ADD_POINTERS(buf, image); } else if (!image) { return; } _mesa_unpack_color_span_float(ctx, width, GL_RGBA, ctx->Convolution1D.Filter, format, type, image, &ctx->Unpack, 0); /* transferOps */ if (ctx->Unpack.BufferObj->Name) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } _mesa_scale_and_bias_rgba(width, (GLfloat (*)[4]) ctx->Convolution1D.Filter, ctx->Pixel.ConvolutionFilterScale[0][0], ctx->Pixel.ConvolutionFilterScale[0][1], ctx->Pixel.ConvolutionFilterScale[0][2], ctx->Pixel.ConvolutionFilterScale[0][3], ctx->Pixel.ConvolutionFilterBias[0][0], ctx->Pixel.ConvolutionFilterBias[0][1], ctx->Pixel.ConvolutionFilterBias[0][2], ctx->Pixel.ConvolutionFilterBias[0][3]); ctx->NewState |= _NEW_PIXEL;}void GLAPIENTRY_mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image){ GLint baseFormat; GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (target != GL_CONVOLUTION_2D) { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)"); return; } baseFormat = base_filter_format(internalFormat); if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)"); return; } if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)"); return; } if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)"); return; } if (!_mesa_is_legal_format_and_type(ctx, format, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(format or type)"); return; } if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX || format == GL_DEPTH_COMPONENT || format == GL_INTENSITY || type == GL_BITMAP) { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)"); return; } /* this should have been caught earlier */ assert(_mesa_components_in_format(format)); ctx->Convolution2D.Format = format; ctx->Convolution2D.InternalFormat = internalFormat; ctx->Convolution2D.Width = width; ctx->Convolution2D.Height = height; if (ctx->Unpack.BufferObj->Name) { /* unpack filter from PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, format, type, image)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(invalid PBO access)"); return; } buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, GL_READ_ONLY_ARB, ctx->Unpack.BufferObj); if (!buf) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(PBO is mapped)"); return; } image = ADD_POINTERS(buf, image); } else if (!image) { return; } /* Unpack filter image. We always store filters in RGBA format. */ for (i = 0; i < height; i++) { const GLvoid *src = _mesa_image_address2d(&ctx->Unpack, image, width, height, format, type, i, 0); GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4; _mesa_unpack_color_span_float(ctx, width, GL_RGBA, dst, format, type, src, &ctx->Unpack, 0); /* transferOps */ } if (ctx->Unpack.BufferObj->Name) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } _mesa_scale_and_bias_rgba(width * height, (GLfloat (*)[4]) ctx->Convolution2D.Filter, ctx->Pixel.ConvolutionFilterScale[1][0], ctx->Pixel.ConvolutionFilterScale[1][1], ctx->Pixel.ConvolutionFilterScale[1][2], ctx->Pixel.ConvolutionFilterScale[1][3], ctx->Pixel.ConvolutionFilterBias[1][0], ctx->Pixel.ConvolutionFilterBias[1][1], ctx->Pixel.ConvolutionFilterBias[1][2], ctx->Pixel.ConvolutionFilterBias[1][3]); ctx->NewState |= _NEW_PIXEL;}void GLAPIENTRY_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param){ GET_CURRENT_CONTEXT(ctx); GLuint c; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); switch (target) { case GL_CONVOLUTION_1D: c = 0; break; case GL_CONVOLUTION_2D: c = 1; break; case GL_SEPARABLE_2D: c = 2; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(target)"); return; } switch (pname) { case GL_CONVOLUTION_BORDER_MODE: if (param == (GLfloat) GL_REDUCE || param == (GLfloat) GL_CONSTANT_BORDER || param == (GLfloat) GL_REPLICATE_BORDER) { ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(params)"); return; } break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(pname)"); return; } ctx->NewState |= _NEW_PIXEL;}void GLAPIENTRY_mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params){ GET_CURRENT_CONTEXT(ctx); GLuint c; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); switch (target) { case GL_CONVOLUTION_1D: c = 0; break; case GL_CONVOLUTION_2D: c = 1; break; case GL_SEPARABLE_2D: c = 2; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(target)"); return; } switch (pname) { case GL_CONVOLUTION_BORDER_COLOR: COPY_4V(ctx->Pixel.ConvolutionBorderColor[c], params); break; case GL_CONVOLUTION_BORDER_MODE: if (params[0] == (GLfloat) GL_REDUCE || params[0] == (GLfloat) GL_CONSTANT_BORDER || params[0] == (GLfloat) GL_REPLICATE_BORDER) { ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0]; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(params)"); return; } break; case GL_CONVOLUTION_FILTER_SCALE: COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); break; case GL_CONVOLUTION_FILTER_BIAS: COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -