1 /* $Id: convolve.c,v 1.16 2000/12/10 19:23:19 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * Image convolution functions.
31 * Notes: filter kernel elements are indexed by <n> and <m> as in
46 #include "swrast/s_span.h" /* XXX SWRAST hack */
51 * Given an internalFormat token passed to glConvolutionFilter
52 * or glSeparableFilter, return the corresponding base format.
53 * Return -1 if invalid token.
56 base_filter_format( GLenum format
)
71 case GL_LUMINANCE_ALPHA
:
72 case GL_LUMINANCE4_ALPHA4
:
73 case GL_LUMINANCE6_ALPHA2
:
74 case GL_LUMINANCE8_ALPHA8
:
75 case GL_LUMINANCE12_ALPHA4
:
76 case GL_LUMINANCE12_ALPHA12
:
77 case GL_LUMINANCE16_ALPHA16
:
78 return GL_LUMINANCE_ALPHA
;
105 return -1; /* error */
111 _mesa_ConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*image
)
114 GET_CURRENT_CONTEXT(ctx
);
115 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionFilter1D");
117 if (target
!= GL_CONVOLUTION_1D
) {
118 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
122 baseFormat
= base_filter_format(internalFormat
);
123 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
124 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
128 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
129 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
133 if (!_mesa_is_legal_format_and_type(format
, type
)) {
134 gl_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter1D(format or type)");
138 if (format
== GL_COLOR_INDEX
||
139 format
== GL_STENCIL_INDEX
||
140 format
== GL_DEPTH_COMPONENT
||
141 format
== GL_INTENSITY
||
143 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(format or type)");
147 ctx
->Convolution1D
.Format
= format
;
148 ctx
->Convolution1D
.InternalFormat
= internalFormat
;
149 ctx
->Convolution1D
.Width
= width
;
150 ctx
->Convolution1D
.Height
= 1;
152 /* unpack filter image */
153 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
154 ctx
->Convolution1D
.Filter
,
155 format
, type
, image
, &ctx
->Unpack
,
158 /* apply scale and bias */
160 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[0];
161 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[0];
163 for (i
= 0; i
< width
; i
++) {
164 GLfloat r
= ctx
->Convolution1D
.Filter
[i
* 4 + 0];
165 GLfloat g
= ctx
->Convolution1D
.Filter
[i
* 4 + 1];
166 GLfloat b
= ctx
->Convolution1D
.Filter
[i
* 4 + 2];
167 GLfloat a
= ctx
->Convolution1D
.Filter
[i
* 4 + 3];
168 r
= r
* scale
[0] + bias
[0];
169 g
= g
* scale
[1] + bias
[1];
170 b
= b
* scale
[2] + bias
[2];
171 a
= a
* scale
[3] + bias
[3];
172 ctx
->Convolution1D
.Filter
[i
* 4 + 0] = r
;
173 ctx
->Convolution1D
.Filter
[i
* 4 + 1] = g
;
174 ctx
->Convolution1D
.Filter
[i
* 4 + 2] = b
;
175 ctx
->Convolution1D
.Filter
[i
* 4 + 3] = a
;
179 ctx
->NewState
|= _NEW_PIXEL
;
184 _mesa_ConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*image
)
188 GET_CURRENT_CONTEXT(ctx
);
189 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionFilter2D");
191 if (target
!= GL_CONVOLUTION_2D
) {
192 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
196 baseFormat
= base_filter_format(internalFormat
);
197 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
198 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
202 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
203 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
206 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
207 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
211 if (!_mesa_is_legal_format_and_type(format
, type
)) {
212 gl_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter2D(format or type)");
215 if (format
== GL_COLOR_INDEX
||
216 format
== GL_STENCIL_INDEX
||
217 format
== GL_DEPTH_COMPONENT
||
218 format
== GL_INTENSITY
||
220 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
224 components
= _mesa_components_in_format(format
);
225 assert(components
> 0); /* this should have been caught earlier */
227 ctx
->Convolution2D
.Format
= format
;
228 ctx
->Convolution2D
.InternalFormat
= internalFormat
;
229 ctx
->Convolution2D
.Width
= width
;
230 ctx
->Convolution2D
.Height
= height
;
232 /* Unpack filter image. We always store filters in RGBA format. */
233 for (i
= 0; i
< height
; i
++) {
234 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
, image
, width
,
235 height
, format
, type
, 0, i
, 0);
236 GLfloat
*dst
= ctx
->Convolution2D
.Filter
+ i
* width
* 4;
237 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, dst
,
238 format
, type
, src
, &ctx
->Unpack
,
242 /* apply scale and bias */
244 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[1];
245 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[1];
246 for (i
= 0; i
< width
* height
* 4; i
++) {
247 GLfloat r
= ctx
->Convolution2D
.Filter
[i
* 4 + 0];
248 GLfloat g
= ctx
->Convolution2D
.Filter
[i
* 4 + 1];
249 GLfloat b
= ctx
->Convolution2D
.Filter
[i
* 4 + 2];
250 GLfloat a
= ctx
->Convolution2D
.Filter
[i
* 4 + 3];
251 r
= r
* scale
[0] + bias
[0];
252 g
= g
* scale
[1] + bias
[1];
253 b
= b
* scale
[2] + bias
[2];
254 a
= a
* scale
[3] + bias
[3];
255 ctx
->Convolution2D
.Filter
[i
* 4 + 0] = r
;
256 ctx
->Convolution2D
.Filter
[i
* 4 + 1] = g
;
257 ctx
->Convolution2D
.Filter
[i
* 4 + 2] = b
;
258 ctx
->Convolution2D
.Filter
[i
* 4 + 3] = a
;
262 ctx
->NewState
|= _NEW_PIXEL
;
267 _mesa_ConvolutionParameterf(GLenum target
, GLenum pname
, GLfloat param
)
269 GET_CURRENT_CONTEXT(ctx
);
272 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameterf");
275 case GL_CONVOLUTION_1D
:
278 case GL_CONVOLUTION_2D
:
281 case GL_SEPARABLE_2D
:
285 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
290 case GL_CONVOLUTION_BORDER_MODE
:
291 if (param
== (GLfloat
) GL_REDUCE
||
292 param
== (GLfloat
) GL_CONSTANT_BORDER
||
293 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
294 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
297 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
302 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
306 ctx
->NewState
|= _NEW_PIXEL
;
311 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
313 GET_CURRENT_CONTEXT(ctx
);
314 struct gl_convolution_attrib
*conv
;
317 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameterfv");
320 case GL_CONVOLUTION_1D
:
322 conv
= &ctx
->Convolution1D
;
324 case GL_CONVOLUTION_2D
:
326 conv
= &ctx
->Convolution2D
;
328 case GL_SEPARABLE_2D
:
330 conv
= &ctx
->Separable2D
;
333 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
338 case GL_CONVOLUTION_BORDER_COLOR
:
339 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
341 case GL_CONVOLUTION_BORDER_MODE
:
342 if (params
[0] == (GLfloat
) GL_REDUCE
||
343 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
344 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
345 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
348 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
352 case GL_CONVOLUTION_FILTER_SCALE
:
353 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
355 case GL_CONVOLUTION_FILTER_BIAS
:
356 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
359 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
363 ctx
->NewState
|= _NEW_PIXEL
;
368 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
370 GET_CURRENT_CONTEXT(ctx
);
373 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameteri");
376 case GL_CONVOLUTION_1D
:
379 case GL_CONVOLUTION_2D
:
382 case GL_SEPARABLE_2D
:
386 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
391 case GL_CONVOLUTION_BORDER_MODE
:
392 if (param
== (GLint
) GL_REDUCE
||
393 param
== (GLint
) GL_CONSTANT_BORDER
||
394 param
== (GLint
) GL_REPLICATE_BORDER
) {
395 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
398 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
403 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
407 ctx
->NewState
|= _NEW_PIXEL
;
412 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
414 GET_CURRENT_CONTEXT(ctx
);
415 struct gl_convolution_attrib
*conv
;
418 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameteriv");
421 case GL_CONVOLUTION_1D
:
423 conv
= &ctx
->Convolution1D
;
425 case GL_CONVOLUTION_2D
:
427 conv
= &ctx
->Convolution2D
;
429 case GL_SEPARABLE_2D
:
431 conv
= &ctx
->Separable2D
;
434 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
439 case GL_CONVOLUTION_BORDER_COLOR
:
440 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
441 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
442 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
443 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
445 case GL_CONVOLUTION_BORDER_MODE
:
446 if (params
[0] == (GLint
) GL_REDUCE
||
447 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
448 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
449 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
452 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
456 case GL_CONVOLUTION_FILTER_SCALE
:
457 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
459 case GL_CONVOLUTION_FILTER_BIAS
:
460 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
463 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
467 ctx
->NewState
|= _NEW_PIXEL
;
472 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
475 GLchan rgba
[MAX_CONVOLUTION_WIDTH
][4];
476 GET_CURRENT_CONTEXT(ctx
);
477 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyConvolutionFilter1D");
479 if (target
!= GL_CONVOLUTION_1D
) {
480 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
484 baseFormat
= base_filter_format(internalFormat
);
485 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
486 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
490 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
491 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
495 /* read pixels from framebuffer */
497 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
, (GLchan (*)[4]) rgba
);
500 /* store as convolution filter */
501 _mesa_ConvolutionFilter1D(target
, internalFormat
, width
,
502 GL_RGBA
, CHAN_TYPE
, rgba
);
507 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
511 struct gl_pixelstore_attrib packSave
;
512 GLchan rgba
[MAX_CONVOLUTION_HEIGHT
][MAX_CONVOLUTION_WIDTH
][4];
513 GET_CURRENT_CONTEXT(ctx
);
514 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyConvolutionFilter2D");
516 if (target
!= GL_CONVOLUTION_2D
) {
517 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
521 baseFormat
= base_filter_format(internalFormat
);
522 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
523 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
527 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
528 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
531 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
532 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
536 /* read pixels from framebuffer */
538 for (i
= 0; i
< height
; i
++) {
539 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
540 (GLchan (*)[4]) rgba
[i
]);
545 * store as convolution filter
547 packSave
= ctx
->Unpack
; /* save pixel packing params */
549 ctx
->Unpack
.Alignment
= 1;
550 ctx
->Unpack
.RowLength
= MAX_CONVOLUTION_WIDTH
;
551 ctx
->Unpack
.SkipPixels
= 0;
552 ctx
->Unpack
.SkipRows
= 0;
553 ctx
->Unpack
.ImageHeight
= 0;
554 ctx
->Unpack
.SkipImages
= 0;
555 ctx
->Unpack
.SwapBytes
= GL_FALSE
;
556 ctx
->Unpack
.LsbFirst
= GL_FALSE
;
557 ctx
->NewState
|= _NEW_PACKUNPACK
;
559 _mesa_ConvolutionFilter2D(target
, internalFormat
, width
, height
,
560 GL_RGBA
, CHAN_TYPE
, rgba
);
562 ctx
->Unpack
= packSave
; /* restore pixel packing params */
563 ctx
->NewState
|= _NEW_PACKUNPACK
;
568 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
570 const struct gl_convolution_attrib
*filter
;
572 GET_CURRENT_CONTEXT(ctx
);
573 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionFilter");
576 gl_update_state(ctx
);
579 if (!_mesa_is_legal_format_and_type(format
, type
)) {
580 gl_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
584 if (format
== GL_COLOR_INDEX
||
585 format
== GL_STENCIL_INDEX
||
586 format
== GL_DEPTH_COMPONENT
||
587 format
== GL_INTENSITY
||
589 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
594 case GL_CONVOLUTION_1D
:
595 filter
= &(ctx
->Convolution1D
);
597 case GL_CONVOLUTION_2D
:
598 filter
= &(ctx
->Convolution2D
);
601 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
605 for (row
= 0; row
< filter
->Height
; row
++) {
606 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
607 filter
->Height
, format
, type
,
609 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
610 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
611 (const GLfloat (*)[4]) src
,
612 format
, type
, dst
, &ctx
->Pack
, 0);
618 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
620 GET_CURRENT_CONTEXT(ctx
);
621 const struct gl_convolution_attrib
*conv
;
624 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionParameterfv");
627 case GL_CONVOLUTION_1D
:
629 conv
= &ctx
->Convolution1D
;
631 case GL_CONVOLUTION_2D
:
633 conv
= &ctx
->Convolution2D
;
635 case GL_SEPARABLE_2D
:
637 conv
= &ctx
->Separable2D
;
640 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
645 case GL_CONVOLUTION_BORDER_COLOR
:
646 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
648 case GL_CONVOLUTION_BORDER_MODE
:
649 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
651 case GL_CONVOLUTION_FILTER_SCALE
:
652 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
654 case GL_CONVOLUTION_FILTER_BIAS
:
655 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
657 case GL_CONVOLUTION_FORMAT
:
658 *params
= (GLfloat
) conv
->Format
;
660 case GL_CONVOLUTION_WIDTH
:
661 *params
= (GLfloat
) conv
->Width
;
663 case GL_CONVOLUTION_HEIGHT
:
664 *params
= (GLfloat
) conv
->Height
;
666 case GL_MAX_CONVOLUTION_WIDTH
:
667 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
669 case GL_MAX_CONVOLUTION_HEIGHT
:
670 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
673 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
680 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
682 GET_CURRENT_CONTEXT(ctx
);
683 const struct gl_convolution_attrib
*conv
;
686 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionParameteriv");
689 case GL_CONVOLUTION_1D
:
691 conv
= &ctx
->Convolution1D
;
693 case GL_CONVOLUTION_2D
:
695 conv
= &ctx
->Convolution2D
;
697 case GL_SEPARABLE_2D
:
699 conv
= &ctx
->Separable2D
;
702 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
707 case GL_CONVOLUTION_BORDER_COLOR
:
708 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
709 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
710 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
711 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
713 case GL_CONVOLUTION_BORDER_MODE
:
714 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
716 case GL_CONVOLUTION_FILTER_SCALE
:
717 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
718 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
719 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
720 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
722 case GL_CONVOLUTION_FILTER_BIAS
:
723 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
724 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
725 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
726 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
728 case GL_CONVOLUTION_FORMAT
:
729 *params
= (GLint
) conv
->Format
;
731 case GL_CONVOLUTION_WIDTH
:
732 *params
= (GLint
) conv
->Width
;
734 case GL_CONVOLUTION_HEIGHT
:
735 *params
= (GLint
) conv
->Height
;
737 case GL_MAX_CONVOLUTION_WIDTH
:
738 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
740 case GL_MAX_CONVOLUTION_HEIGHT
:
741 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
744 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
751 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
753 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
754 const struct gl_convolution_attrib
*filter
;
755 GET_CURRENT_CONTEXT(ctx
);
756 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetSeparableFilter");
759 gl_update_state(ctx
);
762 if (target
!= GL_SEPARABLE_2D
) {
763 gl_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
767 if (!_mesa_is_legal_format_and_type(format
, type
)) {
768 gl_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
772 if (format
== GL_COLOR_INDEX
||
773 format
== GL_STENCIL_INDEX
||
774 format
== GL_DEPTH_COMPONENT
||
775 format
== GL_INTENSITY
||
777 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
781 filter
= &ctx
->Separable2D
;
785 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
786 filter
->Height
, format
, type
,
788 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
789 (const GLfloat (*)[4]) filter
->Filter
,
790 format
, type
, dst
, &ctx
->Pack
, 0);
795 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
798 const GLfloat
*src
= filter
->Filter
+ colStart
;
799 _mesa_pack_float_rgba_span(ctx
, filter
->Height
,
800 (const GLfloat (*)[4]) src
,
801 format
, type
, dst
, &ctx
->Pack
, 0);
804 (void) span
; /* unused at this time */
809 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
811 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
813 GET_CURRENT_CONTEXT(ctx
);
814 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glSeparableFilter2D");
816 if (target
!= GL_SEPARABLE_2D
) {
817 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
821 baseFormat
= base_filter_format(internalFormat
);
822 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
823 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
827 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
828 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
831 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
832 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
836 if (!_mesa_is_legal_format_and_type(format
, type
)) {
837 gl_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
841 if (format
== GL_COLOR_INDEX
||
842 format
== GL_STENCIL_INDEX
||
843 format
== GL_DEPTH_COMPONENT
||
844 format
== GL_INTENSITY
||
846 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
850 ctx
->Separable2D
.Format
= format
;
851 ctx
->Separable2D
.InternalFormat
= internalFormat
;
852 ctx
->Separable2D
.Width
= width
;
853 ctx
->Separable2D
.Height
= height
;
855 /* unpack row filter */
856 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
857 ctx
->Separable2D
.Filter
,
858 format
, type
, row
, &ctx
->Unpack
,
861 /* apply scale and bias */
863 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
864 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
866 for (i
= 0; i
< width
; i
++) {
867 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0];
868 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
869 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
870 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
871 r
= r
* scale
[0] + bias
[0];
872 g
= g
* scale
[1] + bias
[1];
873 b
= b
* scale
[2] + bias
[2];
874 a
= a
* scale
[3] + bias
[3];
875 ctx
->Separable2D
.Filter
[i
* 4 + 0] = r
;
876 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
877 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
878 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
882 /* unpack column filter */
883 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
884 &ctx
->Separable2D
.Filter
[colStart
],
885 format
, type
, column
, &ctx
->Unpack
,
888 /* apply scale and bias */
890 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
891 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
893 for (i
= 0; i
< width
; i
++) {
894 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
895 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
896 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
897 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
898 r
= r
* scale
[0] + bias
[0];
899 g
= g
* scale
[1] + bias
[1];
900 b
= b
* scale
[2] + bias
[2];
901 a
= a
* scale
[3] + bias
[3];
902 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
903 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
904 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
905 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
909 ctx
->NewState
|= _NEW_PIXEL
;
913 /**********************************************************************/
914 /*** image convolution functions ***/
915 /**********************************************************************/
918 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
919 GLint filterWidth
, const GLfloat filter
[][4],
925 if (filterWidth
>= 1)
926 dstWidth
= srcWidth
- (filterWidth
- 1);
931 return; /* null result */
933 for (i
= 0; i
< dstWidth
; i
++) {
938 for (n
= 0; n
< filterWidth
; n
++) {
939 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
940 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
941 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
942 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
944 dest
[i
][RCOMP
] = sumR
;
945 dest
[i
][GCOMP
] = sumG
;
946 dest
[i
][BCOMP
] = sumB
;
947 dest
[i
][ACOMP
] = sumA
;
953 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
954 GLint filterWidth
, const GLfloat filter
[][4],
956 const GLfloat borderColor
[4])
958 const GLint halfFilterWidth
= filterWidth
/ 2;
961 for (i
= 0; i
< srcWidth
; i
++) {
966 for (n
= 0; n
< filterWidth
; n
++) {
967 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
968 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
969 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
970 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
971 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
974 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
975 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
976 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
977 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
980 dest
[i
][RCOMP
] = sumR
;
981 dest
[i
][GCOMP
] = sumG
;
982 dest
[i
][BCOMP
] = sumB
;
983 dest
[i
][ACOMP
] = sumA
;
989 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
990 GLint filterWidth
, const GLfloat filter
[][4],
993 const GLint halfFilterWidth
= filterWidth
/ 2;
996 for (i
= 0; i
< srcWidth
; i
++) {
1001 for (n
= 0; n
< filterWidth
; n
++) {
1002 if (i
+ n
< halfFilterWidth
) {
1003 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
1004 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
1005 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
1006 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
1008 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
1009 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
1010 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
1011 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
1012 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
1015 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
1016 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
1017 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
1018 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
1021 dest
[i
][RCOMP
] = sumR
;
1022 dest
[i
][GCOMP
] = sumG
;
1023 dest
[i
][BCOMP
] = sumB
;
1024 dest
[i
][ACOMP
] = sumA
;
1030 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
1031 const GLfloat src
[][4],
1032 GLint filterWidth
, GLint filterHeight
,
1033 const GLfloat filter
[][4],
1036 GLint dstWidth
, dstHeight
;
1039 if (filterWidth
>= 1)
1040 dstWidth
= srcWidth
- (filterWidth
- 1);
1042 dstWidth
= srcWidth
;
1044 if (filterHeight
>= 1)
1045 dstHeight
= srcHeight
- (filterHeight
- 1);
1047 dstHeight
= srcHeight
;
1049 if (dstWidth
<= 0 || dstHeight
<= 0)
1052 for (j
= 0; j
< dstHeight
; j
++) {
1053 for (i
= 0; i
< dstWidth
; i
++) {
1058 for (m
= 0; m
< filterHeight
; m
++) {
1059 for (n
= 0; n
< filterWidth
; n
++) {
1060 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1061 const GLint f
= m
* filterWidth
+ n
;
1062 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1063 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1064 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1065 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1068 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1069 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1070 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1071 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1078 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1079 const GLfloat src
[][4],
1080 GLint filterWidth
, GLint filterHeight
,
1081 const GLfloat filter
[][4],
1083 const GLfloat borderColor
[4])
1085 const GLint halfFilterWidth
= filterWidth
/ 2;
1086 const GLint halfFilterHeight
= filterHeight
/ 2;
1089 for (j
= 0; j
< srcHeight
; j
++) {
1090 for (i
= 0; i
< srcWidth
; i
++) {
1095 for (m
= 0; m
< filterHeight
; m
++) {
1096 for (n
= 0; n
< filterWidth
; n
++) {
1097 const GLint f
= m
* filterWidth
+ n
;
1098 const GLint is
= i
+ n
- halfFilterWidth
;
1099 const GLint js
= j
+ m
- halfFilterHeight
;
1100 if (is
< 0 || is
>= srcWidth
||
1101 js
< 0 || js
>= srcHeight
) {
1102 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1103 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1104 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1105 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1108 const GLint k
= js
* srcWidth
+ is
;
1109 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1110 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1111 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1112 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1116 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1117 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1118 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1119 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1126 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1127 const GLfloat src
[][4],
1128 GLint filterWidth
, GLint filterHeight
,
1129 const GLfloat filter
[][4],
1132 const GLint halfFilterWidth
= filterWidth
/ 2;
1133 const GLint halfFilterHeight
= filterHeight
/ 2;
1136 for (j
= 0; j
< srcHeight
; j
++) {
1137 for (i
= 0; i
< srcWidth
; i
++) {
1142 for (m
= 0; m
< filterHeight
; m
++) {
1143 for (n
= 0; n
< filterWidth
; n
++) {
1144 const GLint f
= m
* filterWidth
+ n
;
1145 GLint is
= i
+ n
- halfFilterWidth
;
1146 GLint js
= j
+ m
- halfFilterHeight
;
1150 else if (is
>= srcWidth
)
1154 else if (js
>= srcHeight
)
1156 k
= js
* srcWidth
+ is
;
1157 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1158 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1159 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1160 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1163 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1164 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1165 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1166 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1173 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1174 const GLfloat src
[][4],
1175 GLint filterWidth
, GLint filterHeight
,
1176 const GLfloat rowFilt
[][4],
1177 const GLfloat colFilt
[][4],
1180 GLint dstWidth
, dstHeight
;
1183 if (filterWidth
>= 1)
1184 dstWidth
= srcWidth
- (filterWidth
- 1);
1186 dstWidth
= srcWidth
;
1188 if (filterHeight
>= 1)
1189 dstHeight
= srcHeight
- (filterHeight
- 1);
1191 dstHeight
= srcHeight
;
1193 if (dstWidth
<= 0 || dstHeight
<= 0)
1196 for (j
= 0; j
< dstHeight
; j
++) {
1197 for (i
= 0; i
< dstWidth
; i
++) {
1202 for (m
= 0; m
< filterHeight
; m
++) {
1203 for (n
= 0; n
< filterWidth
; n
++) {
1204 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1205 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1206 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1207 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1208 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1211 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1212 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1213 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1214 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1221 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1222 const GLfloat src
[][4],
1223 GLint filterWidth
, GLint filterHeight
,
1224 const GLfloat rowFilt
[][4],
1225 const GLfloat colFilt
[][4],
1227 const GLfloat borderColor
[4])
1229 const GLint halfFilterWidth
= filterWidth
/ 2;
1230 const GLint halfFilterHeight
= filterHeight
/ 2;
1233 for (j
= 0; j
< srcHeight
; j
++) {
1234 for (i
= 0; i
< srcWidth
; i
++) {
1239 for (m
= 0; m
< filterHeight
; m
++) {
1240 for (n
= 0; n
< filterWidth
; n
++) {
1241 const GLint is
= i
+ n
- halfFilterWidth
;
1242 const GLint js
= j
+ m
- halfFilterHeight
;
1243 if (is
< 0 || is
>= srcWidth
||
1244 js
< 0 || js
>= srcHeight
) {
1245 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1246 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1247 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1248 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1251 GLint k
= js
* srcWidth
+ is
;
1252 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1253 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1254 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1255 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1260 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1261 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1262 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1263 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1270 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1271 const GLfloat src
[][4],
1272 GLint filterWidth
, GLint filterHeight
,
1273 const GLfloat rowFilt
[][4],
1274 const GLfloat colFilt
[][4],
1277 const GLint halfFilterWidth
= filterWidth
/ 2;
1278 const GLint halfFilterHeight
= filterHeight
/ 2;
1281 for (j
= 0; j
< srcHeight
; j
++) {
1282 for (i
= 0; i
< srcWidth
; i
++) {
1287 for (m
= 0; m
< filterHeight
; m
++) {
1288 for (n
= 0; n
< filterWidth
; n
++) {
1289 GLint is
= i
+ n
- halfFilterWidth
;
1290 GLint js
= j
+ m
- halfFilterHeight
;
1294 else if (is
>= srcWidth
)
1298 else if (js
>= srcHeight
)
1300 k
= js
* srcWidth
+ is
;
1301 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1302 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1303 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1304 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1307 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1308 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1309 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1310 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1318 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1319 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1321 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1323 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1324 ctx
->Convolution1D
.Width
,
1325 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1326 (GLfloat (*)[4]) dstImage
);
1327 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1329 case GL_CONSTANT_BORDER
:
1330 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1331 ctx
->Convolution1D
.Width
,
1332 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1333 (GLfloat (*)[4]) dstImage
,
1334 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1336 case GL_REPLICATE_BORDER
:
1337 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1338 ctx
->Convolution1D
.Width
,
1339 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1340 (GLfloat (*)[4]) dstImage
);
1349 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1350 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1352 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1354 convolve_2d_reduce(*width
, *height
,
1355 (const GLfloat (*)[4]) srcImage
,
1356 ctx
->Convolution2D
.Width
,
1357 ctx
->Convolution2D
.Height
,
1358 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1359 (GLfloat (*)[4]) dstImage
);
1360 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1361 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1363 case GL_CONSTANT_BORDER
:
1364 convolve_2d_constant(*width
, *height
,
1365 (const GLfloat (*)[4]) srcImage
,
1366 ctx
->Convolution2D
.Width
,
1367 ctx
->Convolution2D
.Height
,
1368 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1369 (GLfloat (*)[4]) dstImage
,
1370 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1372 case GL_REPLICATE_BORDER
:
1373 convolve_2d_replicate(*width
, *height
,
1374 (const GLfloat (*)[4]) srcImage
,
1375 ctx
->Convolution2D
.Width
,
1376 ctx
->Convolution2D
.Height
,
1377 (const GLfloat (*)[4])ctx
->Convolution2D
.Filter
,
1378 (GLfloat (*)[4]) dstImage
);
1387 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1388 GLsizei
*width
, GLsizei
*height
,
1389 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1391 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1392 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1394 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1396 convolve_sep_reduce(*width
, *height
,
1397 (const GLfloat (*)[4]) srcImage
,
1398 ctx
->Separable2D
.Width
,
1399 ctx
->Separable2D
.Height
,
1400 (const GLfloat (*)[4]) rowFilter
,
1401 (const GLfloat (*)[4]) colFilter
,
1402 (GLfloat (*)[4]) dstImage
);
1403 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1404 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1406 case GL_CONSTANT_BORDER
:
1407 convolve_sep_constant(*width
, *height
,
1408 (const GLfloat (*)[4]) srcImage
,
1409 ctx
->Separable2D
.Width
,
1410 ctx
->Separable2D
.Height
,
1411 (const GLfloat (*)[4]) rowFilter
,
1412 (const GLfloat (*)[4]) colFilter
,
1413 (GLfloat (*)[4]) dstImage
,
1414 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1416 case GL_REPLICATE_BORDER
:
1417 convolve_sep_replicate(*width
, *height
,
1418 (const GLfloat (*)[4]) srcImage
,
1419 ctx
->Separable2D
.Width
,
1420 ctx
->Separable2D
.Height
,
1421 (const GLfloat (*)[4]) rowFilter
,
1422 (const GLfloat (*)[4]) colFilter
,
1423 (GLfloat (*)[4]) dstImage
);