ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

convolve.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.