Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenconvolve.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 6.5.2 00004 * 00005 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 /* 00027 * Image convolution functions. 00028 * 00029 * Notes: filter kernel elements are indexed by <n> and <m> as in 00030 * the GL spec. 00031 */ 00032 00033 00034 #include "glheader.h" 00035 #include "bufferobj.h" 00036 #include "colormac.h" 00037 #include "convolve.h" 00038 #include "context.h" 00039 #include "image.h" 00040 #include "mtypes.h" 00041 #include "pixel.h" 00042 #include "state.h" 00043 00044 00045 /* 00046 * Given an internalFormat token passed to glConvolutionFilter 00047 * or glSeparableFilter, return the corresponding base format. 00048 * Return -1 if invalid token. 00049 */ 00050 static GLint 00051 base_filter_format( GLenum format ) 00052 { 00053 switch (format) { 00054 case GL_ALPHA: 00055 case GL_ALPHA4: 00056 case GL_ALPHA8: 00057 case GL_ALPHA12: 00058 case GL_ALPHA16: 00059 return GL_ALPHA; 00060 case GL_LUMINANCE: 00061 case GL_LUMINANCE4: 00062 case GL_LUMINANCE8: 00063 case GL_LUMINANCE12: 00064 case GL_LUMINANCE16: 00065 return GL_LUMINANCE; 00066 case GL_LUMINANCE_ALPHA: 00067 case GL_LUMINANCE4_ALPHA4: 00068 case GL_LUMINANCE6_ALPHA2: 00069 case GL_LUMINANCE8_ALPHA8: 00070 case GL_LUMINANCE12_ALPHA4: 00071 case GL_LUMINANCE12_ALPHA12: 00072 case GL_LUMINANCE16_ALPHA16: 00073 return GL_LUMINANCE_ALPHA; 00074 case GL_INTENSITY: 00075 case GL_INTENSITY4: 00076 case GL_INTENSITY8: 00077 case GL_INTENSITY12: 00078 case GL_INTENSITY16: 00079 return GL_INTENSITY; 00080 case GL_RGB: 00081 case GL_R3_G3_B2: 00082 case GL_RGB4: 00083 case GL_RGB5: 00084 case GL_RGB8: 00085 case GL_RGB10: 00086 case GL_RGB12: 00087 case GL_RGB16: 00088 return GL_RGB; 00089 case 4: 00090 case GL_RGBA: 00091 case GL_RGBA2: 00092 case GL_RGBA4: 00093 case GL_RGB5_A1: 00094 case GL_RGBA8: 00095 case GL_RGB10_A2: 00096 case GL_RGBA12: 00097 case GL_RGBA16: 00098 return GL_RGBA; 00099 default: 00100 return -1; /* error */ 00101 } 00102 } 00103 00104 00105 void GLAPIENTRY 00106 _mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) 00107 { 00108 GLint baseFormat; 00109 GET_CURRENT_CONTEXT(ctx); 00110 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00111 00112 if (target != GL_CONVOLUTION_1D) { 00113 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(target)"); 00114 return; 00115 } 00116 00117 baseFormat = base_filter_format(internalFormat); 00118 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { 00119 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(internalFormat)"); 00120 return; 00121 } 00122 00123 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { 00124 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter1D(width)"); 00125 return; 00126 } 00127 00128 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 00129 _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(format or type)"); 00130 return; 00131 } 00132 00133 if (format == GL_COLOR_INDEX || 00134 format == GL_STENCIL_INDEX || 00135 format == GL_DEPTH_COMPONENT || 00136 format == GL_INTENSITY || 00137 type == GL_BITMAP) { 00138 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(format or type)"); 00139 return; 00140 } 00141 00142 ctx->Convolution1D.Format = format; 00143 ctx->Convolution1D.InternalFormat = internalFormat; 00144 ctx->Convolution1D.Width = width; 00145 ctx->Convolution1D.Height = 1; 00146 00147 if (ctx->Unpack.BufferObj->Name) { 00148 /* unpack filter from PBO */ 00149 GLubyte *buf; 00150 if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, 00151 format, type, image)) { 00152 _mesa_error(ctx, GL_INVALID_OPERATION, 00153 "glConvolutionFilter1D(invalid PBO access)"); 00154 return; 00155 } 00156 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00157 GL_READ_ONLY_ARB, 00158 ctx->Unpack.BufferObj); 00159 if (!buf) { 00160 /* buffer is already mapped - that's an error */ 00161 _mesa_error(ctx, GL_INVALID_OPERATION, 00162 "glConvolutionFilter1D(PBO is mapped)"); 00163 return; 00164 } 00165 image = ADD_POINTERS(buf, image); 00166 } 00167 else if (!image) { 00168 return; 00169 } 00170 00171 _mesa_unpack_color_span_float(ctx, width, GL_RGBA, 00172 ctx->Convolution1D.Filter, 00173 format, type, image, &ctx->Unpack, 00174 0); /* transferOps */ 00175 00176 if (ctx->Unpack.BufferObj->Name) { 00177 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00178 ctx->Unpack.BufferObj); 00179 } 00180 00181 _mesa_scale_and_bias_rgba(width, 00182 (GLfloat (*)[4]) ctx->Convolution1D.Filter, 00183 ctx->Pixel.ConvolutionFilterScale[0][0], 00184 ctx->Pixel.ConvolutionFilterScale[0][1], 00185 ctx->Pixel.ConvolutionFilterScale[0][2], 00186 ctx->Pixel.ConvolutionFilterScale[0][3], 00187 ctx->Pixel.ConvolutionFilterBias[0][0], 00188 ctx->Pixel.ConvolutionFilterBias[0][1], 00189 ctx->Pixel.ConvolutionFilterBias[0][2], 00190 ctx->Pixel.ConvolutionFilterBias[0][3]); 00191 00192 ctx->NewState |= _NEW_PIXEL; 00193 } 00194 00195 00196 void GLAPIENTRY 00197 _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) 00198 { 00199 GLint baseFormat; 00200 GLint i; 00201 GET_CURRENT_CONTEXT(ctx); 00202 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00203 00204 if (target != GL_CONVOLUTION_2D) { 00205 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)"); 00206 return; 00207 } 00208 00209 baseFormat = base_filter_format(internalFormat); 00210 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { 00211 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)"); 00212 return; 00213 } 00214 00215 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { 00216 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)"); 00217 return; 00218 } 00219 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { 00220 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)"); 00221 return; 00222 } 00223 00224 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 00225 _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(format or type)"); 00226 return; 00227 } 00228 if (format == GL_COLOR_INDEX || 00229 format == GL_STENCIL_INDEX || 00230 format == GL_DEPTH_COMPONENT || 00231 format == GL_INTENSITY || 00232 type == GL_BITMAP) { 00233 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)"); 00234 return; 00235 } 00236 00237 /* this should have been caught earlier */ 00238 assert(_mesa_components_in_format(format)); 00239 00240 ctx->Convolution2D.Format = format; 00241 ctx->Convolution2D.InternalFormat = internalFormat; 00242 ctx->Convolution2D.Width = width; 00243 ctx->Convolution2D.Height = height; 00244 00245 if (ctx->Unpack.BufferObj->Name) { 00246 /* unpack filter from PBO */ 00247 GLubyte *buf; 00248 if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, 00249 format, type, image)) { 00250 _mesa_error(ctx, GL_INVALID_OPERATION, 00251 "glConvolutionFilter2D(invalid PBO access)"); 00252 return; 00253 } 00254 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00255 GL_READ_ONLY_ARB, 00256 ctx->Unpack.BufferObj); 00257 if (!buf) { 00258 /* buffer is already mapped - that's an error */ 00259 _mesa_error(ctx, GL_INVALID_OPERATION, 00260 "glConvolutionFilter2D(PBO is mapped)"); 00261 return; 00262 } 00263 image = ADD_POINTERS(buf, image); 00264 } 00265 else if (!image) { 00266 return; 00267 } 00268 00269 /* Unpack filter image. We always store filters in RGBA format. */ 00270 for (i = 0; i < height; i++) { 00271 const GLvoid *src = _mesa_image_address2d(&ctx->Unpack, image, width, 00272 height, format, type, i, 0); 00273 GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4; 00274 _mesa_unpack_color_span_float(ctx, width, GL_RGBA, dst, 00275 format, type, src, &ctx->Unpack, 00276 0); /* transferOps */ 00277 } 00278 00279 if (ctx->Unpack.BufferObj->Name) { 00280 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00281 ctx->Unpack.BufferObj); 00282 } 00283 00284 _mesa_scale_and_bias_rgba(width * height, 00285 (GLfloat (*)[4]) ctx->Convolution2D.Filter, 00286 ctx->Pixel.ConvolutionFilterScale[1][0], 00287 ctx->Pixel.ConvolutionFilterScale[1][1], 00288 ctx->Pixel.ConvolutionFilterScale[1][2], 00289 ctx->Pixel.ConvolutionFilterScale[1][3], 00290 ctx->Pixel.ConvolutionFilterBias[1][0], 00291 ctx->Pixel.ConvolutionFilterBias[1][1], 00292 ctx->Pixel.ConvolutionFilterBias[1][2], 00293 ctx->Pixel.ConvolutionFilterBias[1][3]); 00294 00295 ctx->NewState |= _NEW_PIXEL; 00296 } 00297 00298 00299 void GLAPIENTRY 00300 _mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param) 00301 { 00302 GET_CURRENT_CONTEXT(ctx); 00303 GLuint c; 00304 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00305 00306 switch (target) { 00307 case GL_CONVOLUTION_1D: 00308 c = 0; 00309 break; 00310 case GL_CONVOLUTION_2D: 00311 c = 1; 00312 break; 00313 case GL_SEPARABLE_2D: 00314 c = 2; 00315 break; 00316 default: 00317 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(target)"); 00318 return; 00319 } 00320 00321 switch (pname) { 00322 case GL_CONVOLUTION_BORDER_MODE: 00323 if (param == (GLfloat) GL_REDUCE || 00324 param == (GLfloat) GL_CONSTANT_BORDER || 00325 param == (GLfloat) GL_REPLICATE_BORDER) { 00326 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param; 00327 } 00328 else { 00329 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(params)"); 00330 return; 00331 } 00332 break; 00333 default: 00334 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(pname)"); 00335 return; 00336 } 00337 00338 ctx->NewState |= _NEW_PIXEL; 00339 } 00340 00341 00342 void GLAPIENTRY 00343 _mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params) 00344 { 00345 GET_CURRENT_CONTEXT(ctx); 00346 GLuint c; 00347 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00348 00349 switch (target) { 00350 case GL_CONVOLUTION_1D: 00351 c = 0; 00352 break; 00353 case GL_CONVOLUTION_2D: 00354 c = 1; 00355 break; 00356 case GL_SEPARABLE_2D: 00357 c = 2; 00358 break; 00359 default: 00360 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(target)"); 00361 return; 00362 } 00363 00364 switch (pname) { 00365 case GL_CONVOLUTION_BORDER_COLOR: 00366 COPY_4V(ctx->Pixel.ConvolutionBorderColor[c], params); 00367 break; 00368 case GL_CONVOLUTION_BORDER_MODE: 00369 if (params[0] == (GLfloat) GL_REDUCE || 00370 params[0] == (GLfloat) GL_CONSTANT_BORDER || 00371 params[0] == (GLfloat) GL_REPLICATE_BORDER) { 00372 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0]; 00373 } 00374 else { 00375 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(params)"); 00376 return; 00377 } 00378 break; 00379 case GL_CONVOLUTION_FILTER_SCALE: 00380 COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); 00381 break; 00382 case GL_CONVOLUTION_FILTER_BIAS: 00383 COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); 00384 break; 00385 default: 00386 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(pname)"); 00387 return; 00388 } 00389 00390 ctx->NewState |= _NEW_PIXEL; 00391 } 00392 00393 00394 void GLAPIENTRY 00395 _mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint param) 00396 { 00397 GET_CURRENT_CONTEXT(ctx); 00398 GLuint c; 00399 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00400 00401 switch (target) { 00402 case GL_CONVOLUTION_1D: 00403 c = 0; 00404 break; 00405 case GL_CONVOLUTION_2D: 00406 c = 1; 00407 break; 00408 case GL_SEPARABLE_2D: 00409 c = 2; 00410 break; 00411 default: 00412 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(target)"); 00413 return; 00414 } 00415 00416 switch (pname) { 00417 case GL_CONVOLUTION_BORDER_MODE: 00418 if (param == (GLint) GL_REDUCE || 00419 param == (GLint) GL_CONSTANT_BORDER || 00420 param == (GLint) GL_REPLICATE_BORDER) { 00421 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param; 00422 } 00423 else { 00424 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(params)"); 00425 return; 00426 } 00427 break; 00428 default: 00429 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(pname)"); 00430 return; 00431 } 00432 00433 ctx->NewState |= _NEW_PIXEL; 00434 } 00435 00436 00437 void GLAPIENTRY 00438 _mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params) 00439 { 00440 GET_CURRENT_CONTEXT(ctx); 00441 GLuint c; 00442 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00443 00444 switch (target) { 00445 case GL_CONVOLUTION_1D: 00446 c = 0; 00447 break; 00448 case GL_CONVOLUTION_2D: 00449 c = 1; 00450 break; 00451 case GL_SEPARABLE_2D: 00452 c = 2; 00453 break; 00454 default: 00455 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(target)"); 00456 return; 00457 } 00458 00459 switch (pname) { 00460 case GL_CONVOLUTION_BORDER_COLOR: 00461 ctx->Pixel.ConvolutionBorderColor[c][0] = INT_TO_FLOAT(params[0]); 00462 ctx->Pixel.ConvolutionBorderColor[c][1] = INT_TO_FLOAT(params[1]); 00463 ctx->Pixel.ConvolutionBorderColor[c][2] = INT_TO_FLOAT(params[2]); 00464 ctx->Pixel.ConvolutionBorderColor[c][3] = INT_TO_FLOAT(params[3]); 00465 break; 00466 case GL_CONVOLUTION_BORDER_MODE: 00467 if (params[0] == (GLint) GL_REDUCE || 00468 params[0] == (GLint) GL_CONSTANT_BORDER || 00469 params[0] == (GLint) GL_REPLICATE_BORDER) { 00470 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0]; 00471 } 00472 else { 00473 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(params)"); 00474 return; 00475 } 00476 break; 00477 case GL_CONVOLUTION_FILTER_SCALE: 00478 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */ 00479 /* need cast to prevent compiler warnings */ 00480 ctx->Pixel.ConvolutionFilterScale[c][0] = (GLfloat) params[0]; 00481 ctx->Pixel.ConvolutionFilterScale[c][1] = (GLfloat) params[1]; 00482 ctx->Pixel.ConvolutionFilterScale[c][2] = (GLfloat) params[2]; 00483 ctx->Pixel.ConvolutionFilterScale[c][3] = (GLfloat) params[3]; 00484 break; 00485 case GL_CONVOLUTION_FILTER_BIAS: 00486 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */ 00487 /* need cast to prevent compiler warnings */ 00488 ctx->Pixel.ConvolutionFilterBias[c][0] = (GLfloat) params[0]; 00489 ctx->Pixel.ConvolutionFilterBias[c][1] = (GLfloat) params[1]; 00490 ctx->Pixel.ConvolutionFilterBias[c][2] = (GLfloat) params[2]; 00491 ctx->Pixel.ConvolutionFilterBias[c][3] = (GLfloat) params[3]; 00492 break; 00493 default: 00494 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(pname)"); 00495 return; 00496 } 00497 00498 ctx->NewState |= _NEW_PIXEL; 00499 } 00500 00501 00502 void GLAPIENTRY 00503 _mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width) 00504 { 00505 GLint baseFormat; 00506 GET_CURRENT_CONTEXT(ctx); 00507 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00508 00509 if (target != GL_CONVOLUTION_1D) { 00510 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(target)"); 00511 return; 00512 } 00513 00514 baseFormat = base_filter_format(internalFormat); 00515 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { 00516 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(internalFormat)"); 00517 return; 00518 } 00519 00520 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { 00521 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter1D(width)"); 00522 return; 00523 } 00524 00525 ctx->Driver.CopyConvolutionFilter1D( ctx, target, 00526 internalFormat, x, y, width); 00527 } 00528 00529 00530 void GLAPIENTRY 00531 _mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height) 00532 { 00533 GLint baseFormat; 00534 GET_CURRENT_CONTEXT(ctx); 00535 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00536 00537 if (target != GL_CONVOLUTION_2D) { 00538 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(target)"); 00539 return; 00540 } 00541 00542 baseFormat = base_filter_format(internalFormat); 00543 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { 00544 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(internalFormat)"); 00545 return; 00546 } 00547 00548 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { 00549 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(width)"); 00550 return; 00551 } 00552 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { 00553 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(height)"); 00554 return; 00555 } 00556 00557 ctx->Driver.CopyConvolutionFilter2D( ctx, target, internalFormat, x, y, 00558 width, height ); 00559 } 00560 00561 00562 void GLAPIENTRY 00563 _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, 00564 GLvoid *image) 00565 { 00566 struct gl_convolution_attrib *filter; 00567 GLuint row; 00568 GET_CURRENT_CONTEXT(ctx); 00569 ASSERT_OUTSIDE_BEGIN_END(ctx); 00570 00571 if (ctx->NewState) { 00572 _mesa_update_state(ctx); 00573 } 00574 00575 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 00576 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)"); 00577 return; 00578 } 00579 00580 if (format == GL_COLOR_INDEX || 00581 format == GL_STENCIL_INDEX || 00582 format == GL_DEPTH_COMPONENT || 00583 format == GL_INTENSITY || 00584 type == GL_BITMAP) { 00585 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)"); 00586 return; 00587 } 00588 00589 switch (target) { 00590 case GL_CONVOLUTION_1D: 00591 filter = &(ctx->Convolution1D); 00592 break; 00593 case GL_CONVOLUTION_2D: 00594 filter = &(ctx->Convolution2D); 00595 break; 00596 default: 00597 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(target)"); 00598 return; 00599 } 00600 00601 if (ctx->Pack.BufferObj->Name) { 00602 /* Pack the filter into a PBO */ 00603 GLubyte *buf; 00604 if (!_mesa_validate_pbo_access(2, &ctx->Pack, 00605 filter->Width, filter->Height, 00606 1, format, type, image)) { 00607 _mesa_error(ctx, GL_INVALID_OPERATION, 00608 "glGetConvolutionFilter(invalid PBO access)"); 00609 return; 00610 } 00611 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 00612 GL_WRITE_ONLY_ARB, 00613 ctx->Pack.BufferObj); 00614 if (!buf) { 00615 /* buffer is already mapped - that's an error */ 00616 _mesa_error(ctx, GL_INVALID_OPERATION, 00617 "glGetConvolutionFilter(PBO is mapped)"); 00618 return; 00619 } 00620 image = ADD_POINTERS(image, buf); 00621 } 00622 00623 for (row = 0; row < filter->Height; row++) { 00624 GLvoid *dst = _mesa_image_address2d(&ctx->Pack, image, filter->Width, 00625 filter->Height, format, type, 00626 row, 0); 00627 GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + row * filter->Width * 4); 00628 _mesa_pack_rgba_span_float(ctx, filter->Width, src, 00629 format, type, dst, &ctx->Pack, 0x0); 00630 } 00631 00632 if (ctx->Pack.BufferObj->Name) { 00633 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 00634 ctx->Pack.BufferObj); 00635 } 00636 } 00637 00638 00639 void GLAPIENTRY 00640 _mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params) 00641 { 00642 GET_CURRENT_CONTEXT(ctx); 00643 const struct gl_convolution_attrib *conv; 00644 GLuint c; 00645 ASSERT_OUTSIDE_BEGIN_END(ctx); 00646 00647 switch (target) { 00648 case GL_CONVOLUTION_1D: 00649 c = 0; 00650 conv = &ctx->Convolution1D; 00651 break; 00652 case GL_CONVOLUTION_2D: 00653 c = 1; 00654 conv = &ctx->Convolution2D; 00655 break; 00656 case GL_SEPARABLE_2D: 00657 c = 2; 00658 conv = &ctx->Separable2D; 00659 break; 00660 default: 00661 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(target)"); 00662 return; 00663 } 00664 00665 switch (pname) { 00666 case GL_CONVOLUTION_BORDER_COLOR: 00667 COPY_4V(params, ctx->Pixel.ConvolutionBorderColor[c]); 00668 break; 00669 case GL_CONVOLUTION_BORDER_MODE: 00670 *params = (GLfloat) ctx->Pixel.ConvolutionBorderMode[c]; 00671 break; 00672 case GL_CONVOLUTION_FILTER_SCALE: 00673 COPY_4V(params, ctx->Pixel.ConvolutionFilterScale[c]); 00674 break; 00675 case GL_CONVOLUTION_FILTER_BIAS: 00676 COPY_4V(params, ctx->Pixel.ConvolutionFilterBias[c]); 00677 break; 00678 case GL_CONVOLUTION_FORMAT: 00679 *params = (GLfloat) conv->Format; 00680 break; 00681 case GL_CONVOLUTION_WIDTH: 00682 *params = (GLfloat) conv->Width; 00683 break; 00684 case GL_CONVOLUTION_HEIGHT: 00685 *params = (GLfloat) conv->Height; 00686 break; 00687 case GL_MAX_CONVOLUTION_WIDTH: 00688 *params = (GLfloat) ctx->Const.MaxConvolutionWidth; 00689 break; 00690 case GL_MAX_CONVOLUTION_HEIGHT: 00691 *params = (GLfloat) ctx->Const.MaxConvolutionHeight; 00692 break; 00693 default: 00694 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(pname)"); 00695 return; 00696 } 00697 } 00698 00699 00700 void GLAPIENTRY 00701 _mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params) 00702 { 00703 GET_CURRENT_CONTEXT(ctx); 00704 const struct gl_convolution_attrib *conv; 00705 GLuint c; 00706 ASSERT_OUTSIDE_BEGIN_END(ctx); 00707 00708 switch (target) { 00709 case GL_CONVOLUTION_1D: 00710 c = 0; 00711 conv = &ctx->Convolution1D; 00712 break; 00713 case GL_CONVOLUTION_2D: 00714 c = 1; 00715 conv = &ctx->Convolution2D; 00716 break; 00717 case GL_SEPARABLE_2D: 00718 c = 2; 00719 conv = &ctx->Separable2D; 00720 break; 00721 default: 00722 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(target)"); 00723 return; 00724 } 00725 00726 switch (pname) { 00727 case GL_CONVOLUTION_BORDER_COLOR: 00728 params[0] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][0]); 00729 params[1] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][1]); 00730 params[2] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][2]); 00731 params[3] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][3]); 00732 break; 00733 case GL_CONVOLUTION_BORDER_MODE: 00734 *params = (GLint) ctx->Pixel.ConvolutionBorderMode[c]; 00735 break; 00736 case GL_CONVOLUTION_FILTER_SCALE: 00737 params[0] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][0]; 00738 params[1] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][1]; 00739 params[2] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][2]; 00740 params[3] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][3]; 00741 break; 00742 case GL_CONVOLUTION_FILTER_BIAS: 00743 params[0] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][0]; 00744 params[1] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][1]; 00745 params[2] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][2]; 00746 params[3] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][3]; 00747 break; 00748 case GL_CONVOLUTION_FORMAT: 00749 *params = (GLint) conv->Format; 00750 break; 00751 case GL_CONVOLUTION_WIDTH: 00752 *params = (GLint) conv->Width; 00753 break; 00754 case GL_CONVOLUTION_HEIGHT: 00755 *params = (GLint) conv->Height; 00756 break; 00757 case GL_MAX_CONVOLUTION_WIDTH: 00758 *params = (GLint) ctx->Const.MaxConvolutionWidth; 00759 break; 00760 case GL_MAX_CONVOLUTION_HEIGHT: 00761 *params = (GLint) ctx->Const.MaxConvolutionHeight; 00762 break; 00763 default: 00764 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(pname)"); 00765 return; 00766 } 00767 } 00768 00769 00770 void GLAPIENTRY 00771 _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, 00772 GLvoid *row, GLvoid *column, GLvoid *span) 00773 { 00774 const GLint colStart = MAX_CONVOLUTION_WIDTH * 4; 00775 struct gl_convolution_attrib *filter; 00776 GET_CURRENT_CONTEXT(ctx); 00777 ASSERT_OUTSIDE_BEGIN_END(ctx); 00778 00779 if (ctx->NewState) { 00780 _mesa_update_state(ctx); 00781 } 00782 00783 if (target != GL_SEPARABLE_2D) { 00784 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter(target)"); 00785 return; 00786 } 00787 00788 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 00789 _mesa_error(ctx, GL_INVALID_OPERATION, 00790 "glGetConvolutionFilter(format or type)"); 00791 return; 00792 } 00793 00794 if (format == GL_COLOR_INDEX || 00795 format == GL_STENCIL_INDEX || 00796 format == GL_DEPTH_COMPONENT || 00797 format == GL_INTENSITY || 00798 type == GL_BITMAP) { 00799 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)"); 00800 return; 00801 } 00802 00803 filter = &ctx->Separable2D; 00804 00805 if (ctx->Pack.BufferObj->Name) { 00806 /* Pack filter into PBO */ 00807 GLubyte *buf; 00808 if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Width, 1, 1, 00809 format, type, row)) { 00810 _mesa_error(ctx, GL_INVALID_OPERATION, 00811 "glGetSeparableFilter(invalid PBO access, width)"); 00812 return; 00813 } 00814 if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Height, 1, 1, 00815 format, type, column)) { 00816 _mesa_error(ctx, GL_INVALID_OPERATION, 00817 "glGetSeparableFilter(invalid PBO access, height)"); 00818 return; 00819 } 00820 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 00821 GL_WRITE_ONLY_ARB, 00822 ctx->Pack.BufferObj); 00823 if (!buf) { 00824 /* buffer is already mapped - that's an error */ 00825 _mesa_error(ctx, GL_INVALID_OPERATION, 00826 "glGetSeparableFilter(PBO is mapped)"); 00827 return; 00828 } 00829 row = ADD_POINTERS(buf, row); 00830 column = ADD_POINTERS(buf, column); 00831 } 00832 00833 /* Row filter */ 00834 if (row) { 00835 GLvoid *dst = _mesa_image_address1d(&ctx->Pack, row, filter->Width, 00836 format, type, 0); 00837 _mesa_pack_rgba_span_float(ctx, filter->Width, 00838 (GLfloat (*)[4]) filter->Filter, 00839 format, type, dst, &ctx->Pack, 0x0); 00840 } 00841 00842 /* Column filter */ 00843 if (column) { 00844 GLvoid *dst = _mesa_image_address1d(&ctx->Pack, column, filter->Height, 00845 format, type, 0); 00846 GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + colStart); 00847 _mesa_pack_rgba_span_float(ctx, filter->Height, src, 00848 format, type, dst, &ctx->Pack, 0x0); 00849 } 00850 00851 (void) span; /* unused at this time */ 00852 00853 if (ctx->Pack.BufferObj->Name) { 00854 /* Pack filter into PBO */ 00855 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00856 ctx->Unpack.BufferObj); 00857 } 00858 } 00859 00860 00861 void GLAPIENTRY 00862 _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) 00863 { 00864 const GLint colStart = MAX_CONVOLUTION_WIDTH * 4; 00865 GLint baseFormat; 00866 GET_CURRENT_CONTEXT(ctx); 00867 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 00868 00869 if (target != GL_SEPARABLE_2D) { 00870 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(target)"); 00871 return; 00872 } 00873 00874 baseFormat = base_filter_format(internalFormat); 00875 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { 00876 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(internalFormat)"); 00877 return; 00878 } 00879 00880 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { 00881 _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(width)"); 00882 return; 00883 } 00884 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { 00885 _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(height)"); 00886 return; 00887 } 00888 00889 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 00890 _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(format or type)"); 00891 return; 00892 } 00893 00894 if (format == GL_COLOR_INDEX || 00895 format == GL_STENCIL_INDEX || 00896 format == GL_DEPTH_COMPONENT || 00897 format == GL_INTENSITY || 00898 type == GL_BITMAP) { 00899 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(format or type)"); 00900 return; 00901 } 00902 00903 ctx->Separable2D.Format = format; 00904 ctx->Separable2D.InternalFormat = internalFormat; 00905 ctx->Separable2D.Width = width; 00906 ctx->Separable2D.Height = height; 00907 00908 if (ctx->Unpack.BufferObj->Name) { 00909 /* unpack filter from PBO */ 00910 GLubyte *buf; 00911 if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, 00912 format, type, row)) { 00913 _mesa_error(ctx, GL_INVALID_OPERATION, 00914 "glSeparableFilter2D(invalid PBO access, width)"); 00915 return; 00916 } 00917 if (!_mesa_validate_pbo_access(1, &ctx->Unpack, height, 1, 1, 00918 format, type, column)) { 00919 _mesa_error(ctx, GL_INVALID_OPERATION, 00920 "glSeparableFilter2D(invalid PBO access, height)"); 00921 return; 00922 } 00923 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00924 GL_READ_ONLY_ARB, 00925 ctx->Unpack.BufferObj); 00926 if (!buf) { 00927 /* buffer is already mapped - that's an error */ 00928 _mesa_error(ctx, GL_INVALID_OPERATION, 00929 "glSeparableFilter2D(PBO is mapped)"); 00930 return; 00931 } 00932 row = ADD_POINTERS(buf, row); 00933 column = ADD_POINTERS(buf, column); 00934 } 00935 00936 /* unpack row filter */ 00937 if (row) { 00938 _mesa_unpack_color_span_float(ctx, width, GL_RGBA, 00939 ctx->Separable2D.Filter, 00940 format, type, row, &ctx->Unpack, 00941 0); /* transferOps */ 00942 00943 _mesa_scale_and_bias_rgba(width, 00944 (GLfloat (*)[4]) ctx->Separable2D.Filter, 00945 ctx->Pixel.ConvolutionFilterScale[2][0], 00946 ctx->Pixel.ConvolutionFilterScale[2][1], 00947 ctx->Pixel.ConvolutionFilterScale[2][2], 00948 ctx->Pixel.ConvolutionFilterScale[2][3], 00949 ctx->Pixel.ConvolutionFilterBias[2][0], 00950 ctx->Pixel.ConvolutionFilterBias[2][1], 00951 ctx->Pixel.ConvolutionFilterBias[2][2], 00952 ctx->Pixel.ConvolutionFilterBias[2][3]); 00953 } 00954 00955 /* unpack column filter */ 00956 if (column) { 00957 _mesa_unpack_color_span_float(ctx, height, GL_RGBA, 00958 &ctx->Separable2D.Filter[colStart], 00959 format, type, column, &ctx->Unpack, 00960 0); /* transferOps */ 00961 00962 _mesa_scale_and_bias_rgba(height, 00963 (GLfloat (*)[4]) (ctx->Separable2D.Filter + colStart), 00964 ctx->Pixel.ConvolutionFilterScale[2][0], 00965 ctx->Pixel.ConvolutionFilterScale[2][1], 00966 ctx->Pixel.ConvolutionFilterScale[2][2], 00967 ctx->Pixel.ConvolutionFilterScale[2][3], 00968 ctx->Pixel.ConvolutionFilterBias[2][0], 00969 ctx->Pixel.ConvolutionFilterBias[2][1], 00970 ctx->Pixel.ConvolutionFilterBias[2][2], 00971 ctx->Pixel.ConvolutionFilterBias[2][3]); 00972 } 00973 00974 if (ctx->Unpack.BufferObj->Name) { 00975 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00976 ctx->Unpack.BufferObj); 00977 } 00978 00979 ctx->NewState |= _NEW_PIXEL; 00980 } 00981 00982 00983 /**********************************************************************/ 00984 /*** image convolution functions ***/ 00985 /**********************************************************************/ 00986 00987 static void 00988 convolve_1d_reduce(GLint srcWidth, const GLfloat src[][4], 00989 GLint filterWidth, const GLfloat filter[][4], 00990 GLfloat dest[][4]) 00991 { 00992 GLint dstWidth; 00993 GLint i, n; 00994 00995 if (filterWidth >= 1) 00996 dstWidth = srcWidth - (filterWidth - 1); 00997 else 00998 dstWidth = srcWidth; 00999 01000 if (dstWidth <= 0) 01001 return; /* null result */ 01002 01003 for (i = 0; i < dstWidth; i++) { 01004 GLfloat sumR = 0.0; 01005 GLfloat sumG = 0.0; 01006 GLfloat sumB = 0.0; 01007 GLfloat sumA = 0.0; 01008 for (n = 0; n < filterWidth; n++) { 01009 sumR += src[i + n][RCOMP] * filter[n][RCOMP]; 01010 sumG += src[i + n][GCOMP] * filter[n][GCOMP]; 01011 sumB += src[i + n][BCOMP] * filter[n][BCOMP]; 01012 sumA += src[i + n][ACOMP] * filter[n][ACOMP]; 01013 } 01014 dest[i][RCOMP] = sumR; 01015 dest[i][GCOMP] = sumG; 01016 dest[i][BCOMP] = sumB; 01017 dest[i][ACOMP] = sumA; 01018 } 01019 } 01020 01021 01022 static void 01023 convolve_1d_constant(GLint srcWidth, const GLfloat src[][4], 01024 GLint filterWidth, const GLfloat filter[][4], 01025 GLfloat dest[][4], 01026 const GLfloat borderColor[4]) 01027 { 01028 const GLint halfFilterWidth = filterWidth / 2; 01029 GLint i, n; 01030 01031 for (i = 0; i < srcWidth; i++) { 01032 GLfloat sumR = 0.0; 01033 GLfloat sumG = 0.0; 01034 GLfloat sumB = 0.0; 01035 GLfloat sumA = 0.0; 01036 for (n = 0; n < filterWidth; n++) { 01037 if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) { 01038 sumR += borderColor[RCOMP] * filter[n][RCOMP]; 01039 sumG += borderColor[GCOMP] * filter[n][GCOMP]; 01040 sumB += borderColor[BCOMP] * filter[n][BCOMP]; 01041 sumA += borderColor[ACOMP] * filter[n][ACOMP]; 01042 } 01043 else { 01044 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP]; 01045 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP]; 01046 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP]; 01047 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP]; 01048 } 01049 } 01050 dest[i][RCOMP] = sumR; 01051 dest[i][GCOMP] = sumG; 01052 dest[i][BCOMP] = sumB; 01053 dest[i][ACOMP] = sumA; 01054 } 01055 } 01056 01057 01058 static void 01059 convolve_1d_replicate(GLint srcWidth, const GLfloat src[][4], 01060 GLint filterWidth, const GLfloat filter[][4], 01061 GLfloat dest[][4]) 01062 { 01063 const GLint halfFilterWidth = filterWidth / 2; 01064 GLint i, n; 01065 01066 for (i = 0; i < srcWidth; i++) { 01067 GLfloat sumR = 0.0; 01068 GLfloat sumG = 0.0; 01069 GLfloat sumB = 0.0; 01070 GLfloat sumA = 0.0; 01071 for (n = 0; n < filterWidth; n++) { 01072 if (i + n < halfFilterWidth) { 01073 sumR += src[0][RCOMP] * filter[n][RCOMP]; 01074 sumG += src[0][GCOMP] * filter[n][GCOMP]; 01075 sumB += src[0][BCOMP] * filter[n][BCOMP]; 01076 sumA += src[0][ACOMP] * filter[n][ACOMP]; 01077 } 01078 else if (i + n - halfFilterWidth >= srcWidth) { 01079 sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP]; 01080 sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP]; 01081 sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP]; 01082 sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP]; 01083 } 01084 else { 01085 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP]; 01086 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP]; 01087 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP]; 01088 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP]; 01089 } 01090 } 01091 dest[i][RCOMP] = sumR; 01092 dest[i][GCOMP] = sumG; 01093 dest[i][BCOMP] = sumB; 01094 dest[i][ACOMP] = sumA; 01095 } 01096 } 01097 01098 01099 static void 01100 convolve_2d_reduce(GLint srcWidth, GLint srcHeight, 01101 const GLfloat src[][4], 01102 GLint filterWidth, GLint filterHeight, 01103 const GLfloat filter[][4], 01104 GLfloat dest[][4]) 01105 { 01106 GLint dstWidth, dstHeight; 01107 GLint i, j, n, m; 01108 01109 if (filterWidth >= 1) 01110 dstWidth = srcWidth - (filterWidth - 1); 01111 else 01112 dstWidth = srcWidth; 01113 01114 if (filterHeight >= 1) 01115 dstHeight = srcHeight - (filterHeight - 1); 01116 else 01117 dstHeight = srcHeight; 01118 01119 if (dstWidth <= 0 || dstHeight <= 0) 01120 return; 01121 01122 for (j = 0; j < dstHeight; j++) { 01123 for (i = 0; i < dstWidth; i++) { 01124 GLfloat sumR = 0.0; 01125 GLfloat sumG = 0.0; 01126 GLfloat sumB = 0.0; 01127 GLfloat sumA = 0.0; 01128 for (m = 0; m < filterHeight; m++) { 01129 for (n = 0; n < filterWidth; n++) { 01130 const GLint k = (j + m) * srcWidth + i + n; 01131 const GLint f = m * filterWidth + n; 01132 sumR += src[k][RCOMP] * filter[f][RCOMP]; 01133 sumG += src[k][GCOMP] * filter[f][GCOMP]; 01134 sumB += src[k][BCOMP] * filter[f][BCOMP]; 01135 sumA += src[k][ACOMP] * filter[f][ACOMP]; 01136 } 01137 } 01138 dest[j * dstWidth + i][RCOMP] = sumR; 01139 dest[j * dstWidth + i][GCOMP] = sumG; 01140 dest[j * dstWidth + i][BCOMP] = sumB; 01141 dest[j * dstWidth + i][ACOMP] = sumA; 01142 } 01143 } 01144 } 01145 01146 01147 static void 01148 convolve_2d_constant(GLint srcWidth, GLint srcHeight, 01149 const GLfloat src[][4], 01150 GLint filterWidth, GLint filterHeight, 01151 const GLfloat filter[][4], 01152 GLfloat dest[][4], 01153 const GLfloat borderColor[4]) 01154 { 01155 const GLint halfFilterWidth = filterWidth / 2; 01156 const GLint halfFilterHeight = filterHeight / 2; 01157 GLint i, j, n, m; 01158 01159 for (j = 0; j < srcHeight; j++) { 01160 for (i = 0; i < srcWidth; i++) { 01161 GLfloat sumR = 0.0; 01162 GLfloat sumG = 0.0; 01163 GLfloat sumB = 0.0; 01164 GLfloat sumA = 0.0; 01165 for (m = 0; m < filterHeight; m++) { 01166 for (n = 0; n < filterWidth; n++) { 01167 const GLint f = m * filterWidth + n; 01168 const GLint is = i + n - halfFilterWidth; 01169 const GLint js = j + m - halfFilterHeight; 01170 if (is < 0 || is >= srcWidth || 01171 js < 0 || js >= srcHeight) { 01172 sumR += borderColor[RCOMP] * filter[f][RCOMP]; 01173 sumG += borderColor[GCOMP] * filter[f][GCOMP]; 01174 sumB += borderColor[BCOMP] * filter[f][BCOMP]; 01175 sumA += borderColor[ACOMP] * filter[f][ACOMP]; 01176 } 01177 else { 01178 const GLint k = js * srcWidth + is; 01179 sumR += src[k][RCOMP] * filter[f][RCOMP]; 01180 sumG += src[k][GCOMP] * filter[f][GCOMP]; 01181 sumB += src[k][BCOMP] * filter[f][BCOMP]; 01182 sumA += src[k][ACOMP] * filter[f][ACOMP]; 01183 } 01184 } 01185 } 01186 dest[j * srcWidth + i][RCOMP] = sumR; 01187 dest[j * srcWidth + i][GCOMP] = sumG; 01188 dest[j * srcWidth + i][BCOMP] = sumB; 01189 dest[j * srcWidth + i][ACOMP] = sumA; 01190 } 01191 } 01192 } 01193 01194 01195 static void 01196 convolve_2d_replicate(GLint srcWidth, GLint srcHeight, 01197 const GLfloat src[][4], 01198 GLint filterWidth, GLint filterHeight, 01199 const GLfloat filter[][4], 01200 GLfloat dest[][4]) 01201 { 01202 const GLint halfFilterWidth = filterWidth / 2; 01203 const GLint halfFilterHeight = filterHeight / 2; 01204 GLint i, j, n, m; 01205 01206 for (j = 0; j < srcHeight; j++) { 01207 for (i = 0; i < srcWidth; i++) { 01208 GLfloat sumR = 0.0; 01209 GLfloat sumG = 0.0; 01210 GLfloat sumB = 0.0; 01211 GLfloat sumA = 0.0; 01212 for (m = 0; m < filterHeight; m++) { 01213 for (n = 0; n < filterWidth; n++) { 01214 const GLint f = m * filterWidth + n; 01215 GLint is = i + n - halfFilterWidth; 01216 GLint js = j + m - halfFilterHeight; 01217 GLint k; 01218 if (is < 0) 01219 is = 0; 01220 else if (is >= srcWidth) 01221 is = srcWidth - 1; 01222 if (js < 0) 01223 js = 0; 01224 else if (js >= srcHeight) 01225 js = srcHeight - 1; 01226 k = js * srcWidth + is; 01227 sumR += src[k][RCOMP] * filter[f][RCOMP]; 01228 sumG += src[k][GCOMP] * filter[f][GCOMP]; 01229 sumB += src[k][BCOMP] * filter[f][BCOMP]; 01230 sumA += src[k][ACOMP] * filter[f][ACOMP]; 01231 } 01232 } 01233 dest[j * srcWidth + i][RCOMP] = sumR; 01234 dest[j * srcWidth + i][GCOMP] = sumG; 01235 dest[j * srcWidth + i][BCOMP] = sumB; 01236 dest[j * srcWidth + i][ACOMP] = sumA; 01237 } 01238 } 01239 } 01240 01241 01242 static void 01243 convolve_sep_reduce(GLint srcWidth, GLint srcHeight, 01244 const GLfloat src[][4], 01245 GLint filterWidth, GLint filterHeight, 01246 const GLfloat rowFilt[][4], 01247 const GLfloat colFilt[][4], 01248 GLfloat dest[][4]) 01249 { 01250 GLint dstWidth, dstHeight; 01251 GLint i, j, n, m; 01252 01253 if (filterWidth >= 1) 01254 dstWidth = srcWidth - (filterWidth - 1); 01255 else 01256 dstWidth = srcWidth; 01257 01258 if (filterHeight >= 1) 01259 dstHeight = srcHeight - (filterHeight - 1); 01260 else 01261 dstHeight = srcHeight; 01262 01263 if (dstWidth <= 0 || dstHeight <= 0) 01264 return; 01265 01266 for (j = 0; j < dstHeight; j++) { 01267 for (i = 0; i < dstWidth; i++) { 01268 GLfloat sumR = 0.0; 01269 GLfloat sumG = 0.0; 01270 GLfloat sumB = 0.0; 01271 GLfloat sumA = 0.0; 01272 for (m = 0; m < filterHeight; m++) { 01273 for (n = 0; n < filterWidth; n++) { 01274 GLint k = (j + m) * srcWidth + i + n; 01275 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; 01276 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; 01277 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; 01278 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; 01279 } 01280 } 01281 dest[j * dstWidth + i][RCOMP] = sumR; 01282 dest[j * dstWidth + i][GCOMP] = sumG; 01283 dest[j * dstWidth + i][BCOMP] = sumB; 01284 dest[j * dstWidth + i][ACOMP] = sumA; 01285 } 01286 } 01287 } 01288 01289 01290 static void 01291 convolve_sep_constant(GLint srcWidth, GLint srcHeight, 01292 const GLfloat src[][4], 01293 GLint filterWidth, GLint filterHeight, 01294 const GLfloat rowFilt[][4], 01295 const GLfloat colFilt[][4], 01296 GLfloat dest[][4], 01297 const GLfloat borderColor[4]) 01298 { 01299 const GLint halfFilterWidth = filterWidth / 2; 01300 const GLint halfFilterHeight = filterHeight / 2; 01301 GLint i, j, n, m; 01302 01303 for (j = 0; j < srcHeight; j++) { 01304 for (i = 0; i < srcWidth; i++) { 01305 GLfloat sumR = 0.0; 01306 GLfloat sumG = 0.0; 01307 GLfloat sumB = 0.0; 01308 GLfloat sumA = 0.0; 01309 for (m = 0; m < filterHeight; m++) { 01310 for (n = 0; n < filterWidth; n++) { 01311 const GLint is = i + n - halfFilterWidth; 01312 const GLint js = j + m - halfFilterHeight; 01313 if (is < 0 || is >= srcWidth || 01314 js < 0 || js >= srcHeight) { 01315 sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; 01316 sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; 01317 sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; 01318 sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; 01319 } 01320 else { 01321 GLint k = js * srcWidth + is; 01322 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; 01323 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; 01324 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; 01325 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; 01326 } 01327 01328 } 01329 } 01330 dest[j * srcWidth + i][RCOMP] = sumR; 01331 dest[j * srcWidth + i][GCOMP] = sumG; 01332 dest[j * srcWidth + i][BCOMP] = sumB; 01333 dest[j * srcWidth + i][ACOMP] = sumA; 01334 } 01335 } 01336 } 01337 01338 01339 static void 01340 convolve_sep_replicate(GLint srcWidth, GLint srcHeight, 01341 const GLfloat src[][4], 01342 GLint filterWidth, GLint filterHeight, 01343 const GLfloat rowFilt[][4], 01344 const GLfloat colFilt[][4], 01345 GLfloat dest[][4]) 01346 { 01347 const GLint halfFilterWidth = filterWidth / 2; 01348 const GLint halfFilterHeight = filterHeight / 2; 01349 GLint i, j, n, m; 01350 01351 for (j = 0; j < srcHeight; j++) { 01352 for (i = 0; i < srcWidth; i++) { 01353 GLfloat sumR = 0.0; 01354 GLfloat sumG = 0.0; 01355 GLfloat sumB = 0.0; 01356 GLfloat sumA = 0.0; 01357 for (m = 0; m < filterHeight; m++) { 01358 for (n = 0; n < filterWidth; n++) { 01359 GLint is = i + n - halfFilterWidth; 01360 GLint js = j + m - halfFilterHeight; 01361 GLint k; 01362 if (is < 0) 01363 is = 0; 01364 else if (is >= srcWidth) 01365 is = srcWidth - 1; 01366 if (js < 0) 01367 js = 0; 01368 else if (js >= srcHeight) 01369 js = srcHeight - 1; 01370 k = js * srcWidth + is; 01371 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; 01372 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; 01373 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; 01374 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; 01375 } 01376 } 01377 dest[j * srcWidth + i][RCOMP] = sumR; 01378 dest[j * srcWidth + i][GCOMP] = sumG; 01379 dest[j * srcWidth + i][BCOMP] = sumB; 01380 dest[j * srcWidth + i][ACOMP] = sumA; 01381 } 01382 } 01383 } 01384 01385 01386 01387 void 01388 _mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width, 01389 const GLfloat *srcImage, GLfloat *dstImage) 01390 { 01391 switch (ctx->Pixel.ConvolutionBorderMode[0]) { 01392 case GL_REDUCE: 01393 convolve_1d_reduce(*width, (const GLfloat (*)[4]) srcImage, 01394 ctx->Convolution1D.Width, 01395 (const GLfloat (*)[4]) ctx->Convolution1D.Filter, 01396 (GLfloat (*)[4]) dstImage); 01397 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1); 01398 break; 01399 case GL_CONSTANT_BORDER: 01400 convolve_1d_constant(*width, (const GLfloat (*)[4]) srcImage, 01401 ctx->Convolution1D.Width, 01402 (const GLfloat (*)[4]) ctx->Convolution1D.Filter, 01403 (GLfloat (*)[4]) dstImage, 01404 ctx->Pixel.ConvolutionBorderColor[0]); 01405 break; 01406 case GL_REPLICATE_BORDER: 01407 convolve_1d_replicate(*width, (const GLfloat (*)[4]) srcImage, 01408 ctx->Convolution1D.Width, 01409 (const GLfloat (*)[4]) ctx->Convolution1D.Filter, 01410 (GLfloat (*)[4]) dstImage); 01411 break; 01412 default: 01413 ; 01414 } 01415 } 01416 01417 01418 void 01419 _mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height, 01420 const GLfloat *srcImage, GLfloat *dstImage) 01421 { 01422 switch (ctx->Pixel.ConvolutionBorderMode[1]) { 01423 case GL_REDUCE: 01424 convolve_2d_reduce(*width, *height, 01425 (const GLfloat (*)[4]) srcImage, 01426 ctx->Convolution2D.Width, 01427 ctx->Convolution2D.Height, 01428 (const GLfloat (*)[4]) ctx->Convolution2D.Filter, 01429 (GLfloat (*)[4]) dstImage); 01430 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1); 01431 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1); 01432 break; 01433 case GL_CONSTANT_BORDER: 01434 convolve_2d_constant(*width, *height, 01435 (const GLfloat (*)[4]) srcImage, 01436 ctx->Convolution2D.Width, 01437 ctx->Convolution2D.Height, 01438 (const GLfloat (*)[4]) ctx->Convolution2D.Filter, 01439 (GLfloat (*)[4]) dstImage, 01440 ctx->Pixel.ConvolutionBorderColor[1]); 01441 break; 01442 case GL_REPLICATE_BORDER: 01443 convolve_2d_replicate(*width, *height, 01444 (const GLfloat (*)[4]) srcImage, 01445 ctx->Convolution2D.Width, 01446 ctx->Convolution2D.Height, 01447 (const GLfloat (*)[4])ctx->Convolution2D.Filter, 01448 (GLfloat (*)[4]) dstImage); 01449 break; 01450 default: 01451 ; 01452 } 01453 } 01454 01455 01456 void 01457 _mesa_convolve_sep_image(const GLcontext *ctx, 01458 GLsizei *width, GLsizei *height, 01459 const GLfloat *srcImage, GLfloat *dstImage) 01460 { 01461 const GLfloat *rowFilter = ctx->Separable2D.Filter; 01462 const GLfloat *colFilter = rowFilter + 4 * MAX_CONVOLUTION_WIDTH; 01463 01464 switch (ctx->Pixel.ConvolutionBorderMode[2]) { 01465 case GL_REDUCE: 01466 convolve_sep_reduce(*width, *height, 01467 (const GLfloat (*)[4]) srcImage, 01468 ctx->Separable2D.Width, 01469 ctx->Separable2D.Height, 01470 (const GLfloat (*)[4]) rowFilter, 01471 (const GLfloat (*)[4]) colFilter, 01472 (GLfloat (*)[4]) dstImage); 01473 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1); 01474 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1); 01475 break; 01476 case GL_CONSTANT_BORDER: 01477 convolve_sep_constant(*width, *height, 01478 (const GLfloat (*)[4]) srcImage, 01479 ctx->Separable2D.Width, 01480 ctx->Separable2D.Height, 01481 (const GLfloat (*)[4]) rowFilter, 01482 (const GLfloat (*)[4]) colFilter, 01483 (GLfloat (*)[4]) dstImage, 01484 ctx->Pixel.ConvolutionBorderColor[2]); 01485 break; 01486 case GL_REPLICATE_BORDER: 01487 convolve_sep_replicate(*width, *height, 01488 (const GLfloat (*)[4]) srcImage, 01489 ctx->Separable2D.Width, 01490 ctx->Separable2D.Height, 01491 (const GLfloat (*)[4]) rowFilter, 01492 (const GLfloat (*)[4]) colFilter, 01493 (GLfloat (*)[4]) dstImage); 01494 break; 01495 default: 01496 ; 01497 } 01498 } 01499 01500 01501 01502 /* 01503 * This function computes an image's size after convolution. 01504 * If the convolution border mode is GL_REDUCE, the post-convolution 01505 * image will be smaller than the original. 01506 */ 01507 void 01508 _mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions, 01509 GLsizei *width, GLsizei *height) 01510 { 01511 if (ctx->Pixel.Convolution1DEnabled 01512 && dimensions == 1 01513 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) { 01514 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1); 01515 } 01516 else if (ctx->Pixel.Convolution2DEnabled 01517 && dimensions > 1 01518 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) { 01519 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1); 01520 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1); 01521 } 01522 else if (ctx->Pixel.Separable2DEnabled 01523 && dimensions > 1 01524 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) { 01525 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1); 01526 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1); 01527 } 01528 } Generated on Fri May 25 2012 04:18:18 for ReactOS by
1.7.6.1
|