1 /* $Id: convolve.c,v 1.17 2000/12/26 05:09:28 keithw 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
);
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
);
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
);
271 ASSERT_OUTSIDE_BEGIN_END(ctx
);
274 case GL_CONVOLUTION_1D
:
277 case GL_CONVOLUTION_2D
:
280 case GL_SEPARABLE_2D
:
284 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
289 case GL_CONVOLUTION_BORDER_MODE
:
290 if (param
== (GLfloat
) GL_REDUCE
||
291 param
== (GLfloat
) GL_CONSTANT_BORDER
||
292 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
293 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
296 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
301 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
305 ctx
->NewState
|= _NEW_PIXEL
;
310 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
312 GET_CURRENT_CONTEXT(ctx
);
313 struct gl_convolution_attrib
*conv
;
315 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
318 case GL_CONVOLUTION_1D
:
320 conv
= &ctx
->Convolution1D
;
322 case GL_CONVOLUTION_2D
:
324 conv
= &ctx
->Convolution2D
;
326 case GL_SEPARABLE_2D
:
328 conv
= &ctx
->Separable2D
;
331 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
336 case GL_CONVOLUTION_BORDER_COLOR
:
337 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
339 case GL_CONVOLUTION_BORDER_MODE
:
340 if (params
[0] == (GLfloat
) GL_REDUCE
||
341 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
342 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
343 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
346 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
350 case GL_CONVOLUTION_FILTER_SCALE
:
351 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
353 case GL_CONVOLUTION_FILTER_BIAS
:
354 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
357 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
361 ctx
->NewState
|= _NEW_PIXEL
;
366 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
368 GET_CURRENT_CONTEXT(ctx
);
370 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
373 case GL_CONVOLUTION_1D
:
376 case GL_CONVOLUTION_2D
:
379 case GL_SEPARABLE_2D
:
383 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
388 case GL_CONVOLUTION_BORDER_MODE
:
389 if (param
== (GLint
) GL_REDUCE
||
390 param
== (GLint
) GL_CONSTANT_BORDER
||
391 param
== (GLint
) GL_REPLICATE_BORDER
) {
392 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
395 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
400 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
404 ctx
->NewState
|= _NEW_PIXEL
;
409 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
411 GET_CURRENT_CONTEXT(ctx
);
412 struct gl_convolution_attrib
*conv
;
414 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
417 case GL_CONVOLUTION_1D
:
419 conv
= &ctx
->Convolution1D
;
421 case GL_CONVOLUTION_2D
:
423 conv
= &ctx
->Convolution2D
;
425 case GL_SEPARABLE_2D
:
427 conv
= &ctx
->Separable2D
;
430 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
435 case GL_CONVOLUTION_BORDER_COLOR
:
436 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
437 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
438 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
439 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
441 case GL_CONVOLUTION_BORDER_MODE
:
442 if (params
[0] == (GLint
) GL_REDUCE
||
443 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
444 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
445 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
448 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
452 case GL_CONVOLUTION_FILTER_SCALE
:
453 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
455 case GL_CONVOLUTION_FILTER_BIAS
:
456 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
459 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
463 ctx
->NewState
|= _NEW_PIXEL
;
468 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
471 GLchan rgba
[MAX_CONVOLUTION_WIDTH
][4];
472 GET_CURRENT_CONTEXT(ctx
);
473 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
475 if (target
!= GL_CONVOLUTION_1D
) {
476 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
480 baseFormat
= base_filter_format(internalFormat
);
481 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
482 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
486 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
487 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
491 /* read pixels from framebuffer */
493 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
, (GLchan (*)[4]) rgba
);
496 /* store as convolution filter */
497 _mesa_ConvolutionFilter1D(target
, internalFormat
, width
,
498 GL_RGBA
, CHAN_TYPE
, rgba
);
503 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
507 struct gl_pixelstore_attrib packSave
;
508 GLchan rgba
[MAX_CONVOLUTION_HEIGHT
][MAX_CONVOLUTION_WIDTH
][4];
509 GET_CURRENT_CONTEXT(ctx
);
510 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
512 if (target
!= GL_CONVOLUTION_2D
) {
513 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
517 baseFormat
= base_filter_format(internalFormat
);
518 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
519 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
523 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
524 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
527 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
528 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
532 /* read pixels from framebuffer */
534 for (i
= 0; i
< height
; i
++) {
535 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
536 (GLchan (*)[4]) rgba
[i
]);
541 * store as convolution filter
543 packSave
= ctx
->Unpack
; /* save pixel packing params */
545 ctx
->Unpack
.Alignment
= 1;
546 ctx
->Unpack
.RowLength
= MAX_CONVOLUTION_WIDTH
;
547 ctx
->Unpack
.SkipPixels
= 0;
548 ctx
->Unpack
.SkipRows
= 0;
549 ctx
->Unpack
.ImageHeight
= 0;
550 ctx
->Unpack
.SkipImages
= 0;
551 ctx
->Unpack
.SwapBytes
= GL_FALSE
;
552 ctx
->Unpack
.LsbFirst
= GL_FALSE
;
553 ctx
->NewState
|= _NEW_PACKUNPACK
;
555 _mesa_ConvolutionFilter2D(target
, internalFormat
, width
, height
,
556 GL_RGBA
, CHAN_TYPE
, rgba
);
558 ctx
->Unpack
= packSave
; /* restore pixel packing params */
559 ctx
->NewState
|= _NEW_PACKUNPACK
;
564 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
566 const struct gl_convolution_attrib
*filter
;
568 GET_CURRENT_CONTEXT(ctx
);
569 ASSERT_OUTSIDE_BEGIN_END(ctx
);
572 gl_update_state(ctx
);
575 if (!_mesa_is_legal_format_and_type(format
, type
)) {
576 gl_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
580 if (format
== GL_COLOR_INDEX
||
581 format
== GL_STENCIL_INDEX
||
582 format
== GL_DEPTH_COMPONENT
||
583 format
== GL_INTENSITY
||
585 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
590 case GL_CONVOLUTION_1D
:
591 filter
= &(ctx
->Convolution1D
);
593 case GL_CONVOLUTION_2D
:
594 filter
= &(ctx
->Convolution2D
);
597 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
601 for (row
= 0; row
< filter
->Height
; row
++) {
602 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
603 filter
->Height
, format
, type
,
605 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
606 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
607 (const GLfloat (*)[4]) src
,
608 format
, type
, dst
, &ctx
->Pack
, 0);
614 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
616 GET_CURRENT_CONTEXT(ctx
);
617 const struct gl_convolution_attrib
*conv
;
619 ASSERT_OUTSIDE_BEGIN_END(ctx
);
622 case GL_CONVOLUTION_1D
:
624 conv
= &ctx
->Convolution1D
;
626 case GL_CONVOLUTION_2D
:
628 conv
= &ctx
->Convolution2D
;
630 case GL_SEPARABLE_2D
:
632 conv
= &ctx
->Separable2D
;
635 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
640 case GL_CONVOLUTION_BORDER_COLOR
:
641 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
643 case GL_CONVOLUTION_BORDER_MODE
:
644 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
646 case GL_CONVOLUTION_FILTER_SCALE
:
647 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
649 case GL_CONVOLUTION_FILTER_BIAS
:
650 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
652 case GL_CONVOLUTION_FORMAT
:
653 *params
= (GLfloat
) conv
->Format
;
655 case GL_CONVOLUTION_WIDTH
:
656 *params
= (GLfloat
) conv
->Width
;
658 case GL_CONVOLUTION_HEIGHT
:
659 *params
= (GLfloat
) conv
->Height
;
661 case GL_MAX_CONVOLUTION_WIDTH
:
662 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
664 case GL_MAX_CONVOLUTION_HEIGHT
:
665 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
668 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
675 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
677 GET_CURRENT_CONTEXT(ctx
);
678 const struct gl_convolution_attrib
*conv
;
680 ASSERT_OUTSIDE_BEGIN_END(ctx
);
683 case GL_CONVOLUTION_1D
:
685 conv
= &ctx
->Convolution1D
;
687 case GL_CONVOLUTION_2D
:
689 conv
= &ctx
->Convolution2D
;
691 case GL_SEPARABLE_2D
:
693 conv
= &ctx
->Separable2D
;
696 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
701 case GL_CONVOLUTION_BORDER_COLOR
:
702 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
703 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
704 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
705 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
707 case GL_CONVOLUTION_BORDER_MODE
:
708 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
710 case GL_CONVOLUTION_FILTER_SCALE
:
711 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
712 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
713 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
714 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
716 case GL_CONVOLUTION_FILTER_BIAS
:
717 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
718 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
719 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
720 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
722 case GL_CONVOLUTION_FORMAT
:
723 *params
= (GLint
) conv
->Format
;
725 case GL_CONVOLUTION_WIDTH
:
726 *params
= (GLint
) conv
->Width
;
728 case GL_CONVOLUTION_HEIGHT
:
729 *params
= (GLint
) conv
->Height
;
731 case GL_MAX_CONVOLUTION_WIDTH
:
732 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
734 case GL_MAX_CONVOLUTION_HEIGHT
:
735 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
738 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
745 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
747 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
748 const struct gl_convolution_attrib
*filter
;
749 GET_CURRENT_CONTEXT(ctx
);
750 ASSERT_OUTSIDE_BEGIN_END(ctx
);
753 gl_update_state(ctx
);
756 if (target
!= GL_SEPARABLE_2D
) {
757 gl_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
761 if (!_mesa_is_legal_format_and_type(format
, type
)) {
762 gl_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
766 if (format
== GL_COLOR_INDEX
||
767 format
== GL_STENCIL_INDEX
||
768 format
== GL_DEPTH_COMPONENT
||
769 format
== GL_INTENSITY
||
771 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
775 filter
= &ctx
->Separable2D
;
779 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
780 filter
->Height
, format
, type
,
782 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
783 (const GLfloat (*)[4]) filter
->Filter
,
784 format
, type
, dst
, &ctx
->Pack
, 0);
789 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
792 const GLfloat
*src
= filter
->Filter
+ colStart
;
793 _mesa_pack_float_rgba_span(ctx
, filter
->Height
,
794 (const GLfloat (*)[4]) src
,
795 format
, type
, dst
, &ctx
->Pack
, 0);
798 (void) span
; /* unused at this time */
803 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
805 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
807 GET_CURRENT_CONTEXT(ctx
);
808 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
810 if (target
!= GL_SEPARABLE_2D
) {
811 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
815 baseFormat
= base_filter_format(internalFormat
);
816 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
817 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
821 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
822 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
825 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
826 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
830 if (!_mesa_is_legal_format_and_type(format
, type
)) {
831 gl_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
835 if (format
== GL_COLOR_INDEX
||
836 format
== GL_STENCIL_INDEX
||
837 format
== GL_DEPTH_COMPONENT
||
838 format
== GL_INTENSITY
||
840 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
844 ctx
->Separable2D
.Format
= format
;
845 ctx
->Separable2D
.InternalFormat
= internalFormat
;
846 ctx
->Separable2D
.Width
= width
;
847 ctx
->Separable2D
.Height
= height
;
849 /* unpack row filter */
850 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
851 ctx
->Separable2D
.Filter
,
852 format
, type
, row
, &ctx
->Unpack
,
855 /* apply scale and bias */
857 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
858 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
860 for (i
= 0; i
< width
; i
++) {
861 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0];
862 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
863 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
864 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
865 r
= r
* scale
[0] + bias
[0];
866 g
= g
* scale
[1] + bias
[1];
867 b
= b
* scale
[2] + bias
[2];
868 a
= a
* scale
[3] + bias
[3];
869 ctx
->Separable2D
.Filter
[i
* 4 + 0] = r
;
870 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
871 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
872 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
876 /* unpack column filter */
877 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
878 &ctx
->Separable2D
.Filter
[colStart
],
879 format
, type
, column
, &ctx
->Unpack
,
882 /* apply scale and bias */
884 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
885 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
887 for (i
= 0; i
< width
; i
++) {
888 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
889 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
890 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
891 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
892 r
= r
* scale
[0] + bias
[0];
893 g
= g
* scale
[1] + bias
[1];
894 b
= b
* scale
[2] + bias
[2];
895 a
= a
* scale
[3] + bias
[3];
896 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
897 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
898 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
899 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
903 ctx
->NewState
|= _NEW_PIXEL
;
907 /**********************************************************************/
908 /*** image convolution functions ***/
909 /**********************************************************************/
912 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
913 GLint filterWidth
, const GLfloat filter
[][4],
919 if (filterWidth
>= 1)
920 dstWidth
= srcWidth
- (filterWidth
- 1);
925 return; /* null result */
927 for (i
= 0; i
< dstWidth
; i
++) {
932 for (n
= 0; n
< filterWidth
; n
++) {
933 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
934 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
935 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
936 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
938 dest
[i
][RCOMP
] = sumR
;
939 dest
[i
][GCOMP
] = sumG
;
940 dest
[i
][BCOMP
] = sumB
;
941 dest
[i
][ACOMP
] = sumA
;
947 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
948 GLint filterWidth
, const GLfloat filter
[][4],
950 const GLfloat borderColor
[4])
952 const GLint halfFilterWidth
= filterWidth
/ 2;
955 for (i
= 0; i
< srcWidth
; i
++) {
960 for (n
= 0; n
< filterWidth
; n
++) {
961 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
962 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
963 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
964 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
965 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
968 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
969 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
970 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
971 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
974 dest
[i
][RCOMP
] = sumR
;
975 dest
[i
][GCOMP
] = sumG
;
976 dest
[i
][BCOMP
] = sumB
;
977 dest
[i
][ACOMP
] = sumA
;
983 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
984 GLint filterWidth
, const GLfloat filter
[][4],
987 const GLint halfFilterWidth
= filterWidth
/ 2;
990 for (i
= 0; i
< srcWidth
; i
++) {
995 for (n
= 0; n
< filterWidth
; n
++) {
996 if (i
+ n
< halfFilterWidth
) {
997 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
998 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
999 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
1000 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
1002 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
1003 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
1004 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
1005 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
1006 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
1009 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
1010 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
1011 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
1012 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
1015 dest
[i
][RCOMP
] = sumR
;
1016 dest
[i
][GCOMP
] = sumG
;
1017 dest
[i
][BCOMP
] = sumB
;
1018 dest
[i
][ACOMP
] = sumA
;
1024 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
1025 const GLfloat src
[][4],
1026 GLint filterWidth
, GLint filterHeight
,
1027 const GLfloat filter
[][4],
1030 GLint dstWidth
, dstHeight
;
1033 if (filterWidth
>= 1)
1034 dstWidth
= srcWidth
- (filterWidth
- 1);
1036 dstWidth
= srcWidth
;
1038 if (filterHeight
>= 1)
1039 dstHeight
= srcHeight
- (filterHeight
- 1);
1041 dstHeight
= srcHeight
;
1043 if (dstWidth
<= 0 || dstHeight
<= 0)
1046 for (j
= 0; j
< dstHeight
; j
++) {
1047 for (i
= 0; i
< dstWidth
; i
++) {
1052 for (m
= 0; m
< filterHeight
; m
++) {
1053 for (n
= 0; n
< filterWidth
; n
++) {
1054 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1055 const GLint f
= m
* filterWidth
+ n
;
1056 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1057 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1058 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1059 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1062 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1063 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1064 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1065 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1072 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1073 const GLfloat src
[][4],
1074 GLint filterWidth
, GLint filterHeight
,
1075 const GLfloat filter
[][4],
1077 const GLfloat borderColor
[4])
1079 const GLint halfFilterWidth
= filterWidth
/ 2;
1080 const GLint halfFilterHeight
= filterHeight
/ 2;
1083 for (j
= 0; j
< srcHeight
; j
++) {
1084 for (i
= 0; i
< srcWidth
; i
++) {
1089 for (m
= 0; m
< filterHeight
; m
++) {
1090 for (n
= 0; n
< filterWidth
; n
++) {
1091 const GLint f
= m
* filterWidth
+ n
;
1092 const GLint is
= i
+ n
- halfFilterWidth
;
1093 const GLint js
= j
+ m
- halfFilterHeight
;
1094 if (is
< 0 || is
>= srcWidth
||
1095 js
< 0 || js
>= srcHeight
) {
1096 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1097 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1098 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1099 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1102 const GLint k
= js
* srcWidth
+ is
;
1103 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1104 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1105 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1106 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1110 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1111 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1112 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1113 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1120 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1121 const GLfloat src
[][4],
1122 GLint filterWidth
, GLint filterHeight
,
1123 const GLfloat filter
[][4],
1126 const GLint halfFilterWidth
= filterWidth
/ 2;
1127 const GLint halfFilterHeight
= filterHeight
/ 2;
1130 for (j
= 0; j
< srcHeight
; j
++) {
1131 for (i
= 0; i
< srcWidth
; i
++) {
1136 for (m
= 0; m
< filterHeight
; m
++) {
1137 for (n
= 0; n
< filterWidth
; n
++) {
1138 const GLint f
= m
* filterWidth
+ n
;
1139 GLint is
= i
+ n
- halfFilterWidth
;
1140 GLint js
= j
+ m
- halfFilterHeight
;
1144 else if (is
>= srcWidth
)
1148 else if (js
>= srcHeight
)
1150 k
= js
* srcWidth
+ is
;
1151 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1152 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1153 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1154 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1157 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1158 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1159 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1160 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1167 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1168 const GLfloat src
[][4],
1169 GLint filterWidth
, GLint filterHeight
,
1170 const GLfloat rowFilt
[][4],
1171 const GLfloat colFilt
[][4],
1174 GLint dstWidth
, dstHeight
;
1177 if (filterWidth
>= 1)
1178 dstWidth
= srcWidth
- (filterWidth
- 1);
1180 dstWidth
= srcWidth
;
1182 if (filterHeight
>= 1)
1183 dstHeight
= srcHeight
- (filterHeight
- 1);
1185 dstHeight
= srcHeight
;
1187 if (dstWidth
<= 0 || dstHeight
<= 0)
1190 for (j
= 0; j
< dstHeight
; j
++) {
1191 for (i
= 0; i
< dstWidth
; i
++) {
1196 for (m
= 0; m
< filterHeight
; m
++) {
1197 for (n
= 0; n
< filterWidth
; n
++) {
1198 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1199 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1200 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1201 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1202 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1205 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1206 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1207 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1208 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1215 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1216 const GLfloat src
[][4],
1217 GLint filterWidth
, GLint filterHeight
,
1218 const GLfloat rowFilt
[][4],
1219 const GLfloat colFilt
[][4],
1221 const GLfloat borderColor
[4])
1223 const GLint halfFilterWidth
= filterWidth
/ 2;
1224 const GLint halfFilterHeight
= filterHeight
/ 2;
1227 for (j
= 0; j
< srcHeight
; j
++) {
1228 for (i
= 0; i
< srcWidth
; i
++) {
1233 for (m
= 0; m
< filterHeight
; m
++) {
1234 for (n
= 0; n
< filterWidth
; n
++) {
1235 const GLint is
= i
+ n
- halfFilterWidth
;
1236 const GLint js
= j
+ m
- halfFilterHeight
;
1237 if (is
< 0 || is
>= srcWidth
||
1238 js
< 0 || js
>= srcHeight
) {
1239 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1240 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1241 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1242 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1245 GLint k
= js
* srcWidth
+ is
;
1246 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1247 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1248 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1249 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1254 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1255 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1256 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1257 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1264 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1265 const GLfloat src
[][4],
1266 GLint filterWidth
, GLint filterHeight
,
1267 const GLfloat rowFilt
[][4],
1268 const GLfloat colFilt
[][4],
1271 const GLint halfFilterWidth
= filterWidth
/ 2;
1272 const GLint halfFilterHeight
= filterHeight
/ 2;
1275 for (j
= 0; j
< srcHeight
; j
++) {
1276 for (i
= 0; i
< srcWidth
; i
++) {
1281 for (m
= 0; m
< filterHeight
; m
++) {
1282 for (n
= 0; n
< filterWidth
; n
++) {
1283 GLint is
= i
+ n
- halfFilterWidth
;
1284 GLint js
= j
+ m
- halfFilterHeight
;
1288 else if (is
>= srcWidth
)
1292 else if (js
>= srcHeight
)
1294 k
= js
* srcWidth
+ is
;
1295 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1296 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1297 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1298 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1301 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1302 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1303 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1304 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1312 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1313 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1315 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1317 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1318 ctx
->Convolution1D
.Width
,
1319 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1320 (GLfloat (*)[4]) dstImage
);
1321 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1323 case GL_CONSTANT_BORDER
:
1324 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1325 ctx
->Convolution1D
.Width
,
1326 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1327 (GLfloat (*)[4]) dstImage
,
1328 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1330 case GL_REPLICATE_BORDER
:
1331 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1332 ctx
->Convolution1D
.Width
,
1333 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1334 (GLfloat (*)[4]) dstImage
);
1343 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1344 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1346 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1348 convolve_2d_reduce(*width
, *height
,
1349 (const GLfloat (*)[4]) srcImage
,
1350 ctx
->Convolution2D
.Width
,
1351 ctx
->Convolution2D
.Height
,
1352 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1353 (GLfloat (*)[4]) dstImage
);
1354 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1355 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1357 case GL_CONSTANT_BORDER
:
1358 convolve_2d_constant(*width
, *height
,
1359 (const GLfloat (*)[4]) srcImage
,
1360 ctx
->Convolution2D
.Width
,
1361 ctx
->Convolution2D
.Height
,
1362 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1363 (GLfloat (*)[4]) dstImage
,
1364 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1366 case GL_REPLICATE_BORDER
:
1367 convolve_2d_replicate(*width
, *height
,
1368 (const GLfloat (*)[4]) srcImage
,
1369 ctx
->Convolution2D
.Width
,
1370 ctx
->Convolution2D
.Height
,
1371 (const GLfloat (*)[4])ctx
->Convolution2D
.Filter
,
1372 (GLfloat (*)[4]) dstImage
);
1381 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1382 GLsizei
*width
, GLsizei
*height
,
1383 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1385 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1386 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1388 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1390 convolve_sep_reduce(*width
, *height
,
1391 (const GLfloat (*)[4]) srcImage
,
1392 ctx
->Separable2D
.Width
,
1393 ctx
->Separable2D
.Height
,
1394 (const GLfloat (*)[4]) rowFilter
,
1395 (const GLfloat (*)[4]) colFilter
,
1396 (GLfloat (*)[4]) dstImage
);
1397 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1398 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1400 case GL_CONSTANT_BORDER
:
1401 convolve_sep_constant(*width
, *height
,
1402 (const GLfloat (*)[4]) srcImage
,
1403 ctx
->Separable2D
.Width
,
1404 ctx
->Separable2D
.Height
,
1405 (const GLfloat (*)[4]) rowFilter
,
1406 (const GLfloat (*)[4]) colFilter
,
1407 (GLfloat (*)[4]) dstImage
,
1408 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1410 case GL_REPLICATE_BORDER
:
1411 convolve_sep_replicate(*width
, *height
,
1412 (const GLfloat (*)[4]) srcImage
,
1413 ctx
->Separable2D
.Width
,
1414 ctx
->Separable2D
.Height
,
1415 (const GLfloat (*)[4]) rowFilter
,
1416 (const GLfloat (*)[4]) colFilter
,
1417 (GLfloat (*)[4]) dstImage
);