📄 convolve.c
字号:
}void GLAPIENTRY_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span){ const GLint colStart = MAX_CONVOLUTION_WIDTH * 4; struct gl_convolution_attrib *filter; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (ctx->NewState) { _mesa_update_state(ctx); } if (target != GL_SEPARABLE_2D) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter(target)"); return; } if (!_mesa_is_legal_format_and_type(ctx, format, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(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, "glGetConvolutionFilter(format or type)"); return; } filter = &ctx->Separable2D; if (ctx->Pack.BufferObj->Name) { /* Pack filter into PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Width, 1, 1, format, type, row)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSeparableFilter(invalid PBO access, width)"); return; } if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Height, 1, 1, format, type, column)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSeparableFilter(invalid PBO access, height)"); return; } buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj); if (!buf) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSeparableFilter(PBO is mapped)"); return; } row = ADD_POINTERS(buf, row); column = ADD_POINTERS(buf, column); } /* Row filter */ if (row) { GLvoid *dst = _mesa_image_address1d(&ctx->Pack, row, filter->Width, format, type, 0); _mesa_pack_rgba_span_float(ctx, filter->Width, (GLfloat (*)[4]) filter->Filter, format, type, dst, &ctx->Pack, 0x0); } /* Column filter */ if (column) { GLvoid *dst = _mesa_image_address1d(&ctx->Pack, column, filter->Height, format, type, 0); GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + colStart); _mesa_pack_rgba_span_float(ctx, filter->Height, src, format, type, dst, &ctx->Pack, 0x0); } (void) span; /* unused at this time */ if (ctx->Pack.BufferObj->Name) { /* Pack filter into PBO */ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); }}void GLAPIENTRY_mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column){ const GLint colStart = MAX_CONVOLUTION_WIDTH * 4; GLint baseFormat; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (target != GL_SEPARABLE_2D) { _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(target)"); return; } baseFormat = base_filter_format(internalFormat); if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(internalFormat)"); return; } if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(width)"); return; } if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(height)"); return; } if (!_mesa_is_legal_format_and_type(ctx, format, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(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, "glSeparableFilter2D(format or type)"); return; } ctx->Separable2D.Format = format; ctx->Separable2D.InternalFormat = internalFormat; ctx->Separable2D.Width = width; ctx->Separable2D.Height = height; if (ctx->Unpack.BufferObj->Name) { /* unpack filter from PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, format, type, row)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(invalid PBO access, width)"); return; } if (!_mesa_validate_pbo_access(1, &ctx->Unpack, height, 1, 1, format, type, column)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(invalid PBO access, height)"); 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, "glSeparableFilter2D(PBO is mapped)"); return; } row = ADD_POINTERS(buf, row); column = ADD_POINTERS(buf, column); } /* unpack row filter */ if (row) { _mesa_unpack_color_span_float(ctx, width, GL_RGBA, ctx->Separable2D.Filter, format, type, row, &ctx->Unpack, 0); /* transferOps */ _mesa_scale_and_bias_rgba(width, (GLfloat (*)[4]) ctx->Separable2D.Filter, ctx->Pixel.ConvolutionFilterScale[2][0], ctx->Pixel.ConvolutionFilterScale[2][1], ctx->Pixel.ConvolutionFilterScale[2][2], ctx->Pixel.ConvolutionFilterScale[2][3], ctx->Pixel.ConvolutionFilterBias[2][0], ctx->Pixel.ConvolutionFilterBias[2][1], ctx->Pixel.ConvolutionFilterBias[2][2], ctx->Pixel.ConvolutionFilterBias[2][3]); } /* unpack column filter */ if (column) { _mesa_unpack_color_span_float(ctx, height, GL_RGBA, &ctx->Separable2D.Filter[colStart], format, type, column, &ctx->Unpack, 0); /* transferOps */ _mesa_scale_and_bias_rgba(height, (GLfloat (*)[4]) (ctx->Separable2D.Filter + colStart), ctx->Pixel.ConvolutionFilterScale[2][0], ctx->Pixel.ConvolutionFilterScale[2][1], ctx->Pixel.ConvolutionFilterScale[2][2], ctx->Pixel.ConvolutionFilterScale[2][3], ctx->Pixel.ConvolutionFilterBias[2][0], ctx->Pixel.ConvolutionFilterBias[2][1], ctx->Pixel.ConvolutionFilterBias[2][2], ctx->Pixel.ConvolutionFilterBias[2][3]); } if (ctx->Unpack.BufferObj->Name) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } ctx->NewState |= _NEW_PIXEL;}/**********************************************************************//*** image convolution functions ***//**********************************************************************/static voidconvolve_1d_reduce(GLint srcWidth, const GLfloat src[][4], GLint filterWidth, const GLfloat filter[][4], GLfloat dest[][4]){ GLint dstWidth; GLint i, n; if (filterWidth >= 1) dstWidth = srcWidth - (filterWidth - 1); else dstWidth = srcWidth; if (dstWidth <= 0) return; /* null result */ for (i = 0; i < dstWidth; i++) { GLfloat sumR = 0.0; GLfloat sumG = 0.0; GLfloat sumB = 0.0; GLfloat sumA = 0.0; for (n = 0; n < filterWidth; n++) { sumR += src[i + n][RCOMP] * filter[n][RCOMP]; sumG += src[i + n][GCOMP] * filter[n][GCOMP]; sumB += src[i + n][BCOMP] * filter[n][BCOMP]; sumA += src[i + n][ACOMP] * filter[n][ACOMP]; } dest[i][RCOMP] = sumR; dest[i][GCOMP] = sumG; dest[i][BCOMP] = sumB; dest[i][ACOMP] = sumA; }}static voidconvolve_1d_constant(GLint srcWidth, const GLfloat src[][4], GLint filterWidth, const GLfloat filter[][4], GLfloat dest[][4], const GLfloat borderColor[4]){ const GLint halfFilterWidth = filterWidth / 2; GLint i, n; for (i = 0; i < srcWidth; i++) { GLfloat sumR = 0.0; GLfloat sumG = 0.0; GLfloat sumB = 0.0; GLfloat sumA = 0.0; for (n = 0; n < filterWidth; n++) { if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) { sumR += borderColor[RCOMP] * filter[n][RCOMP]; sumG += borderColor[GCOMP] * filter[n][GCOMP]; sumB += borderColor[BCOMP] * filter[n][BCOMP]; sumA += borderColor[ACOMP] * filter[n][ACOMP]; } else { sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP]; sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP]; sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP]; sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP]; } } dest[i][RCOMP] = sumR; dest[i][GCOMP] = sumG; dest[i][BCOMP] = sumB; dest[i][ACOMP] = sumA; }}static voidconvolve_1d_replicate(GLint srcWidth, const GLfloat src[][4], GLint filterWidth, const GLfloat filter[][4], GLfloat dest[][4]){ const GLint halfFilterWidth = filterWidth / 2; GLint i, n; for (i = 0; i < srcWidth; i++) { GLfloat sumR = 0.0; GLfloat sumG = 0.0; GLfloat sumB = 0.0; GLfloat sumA = 0.0; for (n = 0; n < filterWidth; n++) { if (i + n < halfFilterWidth) { sumR += src[0][RCOMP] * filter[n][RCOMP]; sumG += src[0][GCOMP] * filter[n][GCOMP]; sumB += src[0][BCOMP] * filter[n][BCOMP]; sumA += src[0][ACOMP] * filter[n][ACOMP]; } else if (i + n - halfFilterWidth >= srcWidth) { sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP]; sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP]; sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP]; sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP]; } else { sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP]; sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP]; sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP]; sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP]; } } dest[i][RCOMP] = sumR; dest[i][GCOMP] = sumG; dest[i][BCOMP] = sumB; dest[i][ACOMP] = sumA; }}static voidconvolve_2d_reduce(GLint srcWidth, GLint srcHeight, const GLfloat src[][4], GLint filterWidth, GLint filterHeight, const GLfloat filter[][4], GLfloat dest[][4]){ GLint dstWidth, dstHeight; GLint i, j, n, m; if (filterWidth >= 1) dstWidth = srcWidth - (filterWidth - 1); else dstWidth = srcWidth; if (filterHeight >= 1) dstHeight = srcHeight - (filterHeight - 1); else dstHeight = srcHeight; if (dstWidth <= 0 || dstHeight <= 0) return; for (j = 0; j < dstHeight; j++) { for (i = 0; i < dstWidth; i++) { GLfloat sumR = 0.0; GLfloat sumG = 0.0; GLfloat sumB = 0.0; GLfloat sumA = 0.0; for (m = 0; m < filterHeight; m++) { for (n = 0; n < filterWidth; n++) { const GLint k = (j + m) * srcWidth + i + n; const GLint f = m * filterWidth + n; sumR += src[k][RCOMP] * filter[f][RCOMP]; sumG += src[k][GCOMP] * filter[f][GCOMP]; sumB += src[k][BCOMP] * filter[f][BCOMP]; sumA += src[k][ACOMP] * filter[f][ACOMP]; } } dest[j * dstWidth + i][RCOMP] = sumR; dest[j * dstWidth + i][GCOMP] = sumG; dest[j * dstWidth + i][BCOMP] = sumB; dest[j * dstWidth + i][ACOMP] = sumA; } }}static voidconvolve_2d_constant(GLint srcWidth, GLint srcHeight, const GLfloat src[][4],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -