3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Image convolution functions.
30 * Notes: filter kernel elements are indexed by <n> and <m> as in
45 * Given an internalFormat token passed to glConvolutionFilter
46 * or glSeparableFilter, return the corresponding base format.
47 * Return -1 if invalid token.
50 base_filter_format( GLenum format
)
65 case GL_LUMINANCE_ALPHA
:
66 case GL_LUMINANCE4_ALPHA4
:
67 case GL_LUMINANCE6_ALPHA2
:
68 case GL_LUMINANCE8_ALPHA8
:
69 case GL_LUMINANCE12_ALPHA4
:
70 case GL_LUMINANCE12_ALPHA12
:
71 case GL_LUMINANCE16_ALPHA16
:
72 return GL_LUMINANCE_ALPHA
;
99 return -1; /* error */
105 _mesa_ConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*image
)
108 GET_CURRENT_CONTEXT(ctx
);
109 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
111 if (target
!= GL_CONVOLUTION_1D
) {
112 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
116 baseFormat
= base_filter_format(internalFormat
);
117 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
118 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
122 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
123 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
127 if (!_mesa_is_legal_format_and_type(format
, type
)) {
128 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter1D(format or type)");
132 if (format
== GL_COLOR_INDEX
||
133 format
== GL_STENCIL_INDEX
||
134 format
== GL_DEPTH_COMPONENT
||
135 format
== GL_INTENSITY
||
137 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(format or type)");
141 ctx
->Convolution1D
.Format
= format
;
142 ctx
->Convolution1D
.InternalFormat
= internalFormat
;
143 ctx
->Convolution1D
.Width
= width
;
144 ctx
->Convolution1D
.Height
= 1;
146 /* unpack filter image */
147 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
148 ctx
->Convolution1D
.Filter
,
149 format
, type
, image
, &ctx
->Unpack
,
152 /* apply scale and bias */
154 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[0];
155 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[0];
157 for (i
= 0; i
< width
; i
++) {
158 GLfloat r
= ctx
->Convolution1D
.Filter
[i
* 4 + 0];
159 GLfloat g
= ctx
->Convolution1D
.Filter
[i
* 4 + 1];
160 GLfloat b
= ctx
->Convolution1D
.Filter
[i
* 4 + 2];
161 GLfloat a
= ctx
->Convolution1D
.Filter
[i
* 4 + 3];
162 r
= r
* scale
[0] + bias
[0];
163 g
= g
* scale
[1] + bias
[1];
164 b
= b
* scale
[2] + bias
[2];
165 a
= a
* scale
[3] + bias
[3];
166 ctx
->Convolution1D
.Filter
[i
* 4 + 0] = r
;
167 ctx
->Convolution1D
.Filter
[i
* 4 + 1] = g
;
168 ctx
->Convolution1D
.Filter
[i
* 4 + 2] = b
;
169 ctx
->Convolution1D
.Filter
[i
* 4 + 3] = a
;
173 ctx
->NewState
|= _NEW_PIXEL
;
178 _mesa_ConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*image
)
182 GET_CURRENT_CONTEXT(ctx
);
183 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
185 if (target
!= GL_CONVOLUTION_2D
) {
186 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
190 baseFormat
= base_filter_format(internalFormat
);
191 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
192 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
196 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
197 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
200 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
201 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
205 if (!_mesa_is_legal_format_and_type(format
, type
)) {
206 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter2D(format or type)");
209 if (format
== GL_COLOR_INDEX
||
210 format
== GL_STENCIL_INDEX
||
211 format
== GL_DEPTH_COMPONENT
||
212 format
== GL_INTENSITY
||
214 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
218 components
= _mesa_components_in_format(format
);
219 assert(components
> 0); /* this should have been caught earlier */
221 ctx
->Convolution2D
.Format
= format
;
222 ctx
->Convolution2D
.InternalFormat
= internalFormat
;
223 ctx
->Convolution2D
.Width
= width
;
224 ctx
->Convolution2D
.Height
= height
;
226 /* Unpack filter image. We always store filters in RGBA format. */
227 for (i
= 0; i
< height
; i
++) {
228 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
, image
, width
,
229 height
, format
, type
, 0, i
, 0);
230 GLfloat
*dst
= ctx
->Convolution2D
.Filter
+ i
* width
* 4;
231 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, dst
,
232 format
, type
, src
, &ctx
->Unpack
,
236 /* apply scale and bias */
238 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[1];
239 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[1];
240 for (i
= 0; i
< width
* height
; i
++) {
241 GLfloat r
= ctx
->Convolution2D
.Filter
[i
* 4 + 0];
242 GLfloat g
= ctx
->Convolution2D
.Filter
[i
* 4 + 1];
243 GLfloat b
= ctx
->Convolution2D
.Filter
[i
* 4 + 2];
244 GLfloat a
= ctx
->Convolution2D
.Filter
[i
* 4 + 3];
245 r
= r
* scale
[0] + bias
[0];
246 g
= g
* scale
[1] + bias
[1];
247 b
= b
* scale
[2] + bias
[2];
248 a
= a
* scale
[3] + bias
[3];
249 ctx
->Convolution2D
.Filter
[i
* 4 + 0] = r
;
250 ctx
->Convolution2D
.Filter
[i
* 4 + 1] = g
;
251 ctx
->Convolution2D
.Filter
[i
* 4 + 2] = b
;
252 ctx
->Convolution2D
.Filter
[i
* 4 + 3] = a
;
256 ctx
->NewState
|= _NEW_PIXEL
;
261 _mesa_ConvolutionParameterf(GLenum target
, GLenum pname
, GLfloat param
)
263 GET_CURRENT_CONTEXT(ctx
);
265 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
268 case GL_CONVOLUTION_1D
:
271 case GL_CONVOLUTION_2D
:
274 case GL_SEPARABLE_2D
:
278 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
283 case GL_CONVOLUTION_BORDER_MODE
:
284 if (param
== (GLfloat
) GL_REDUCE
||
285 param
== (GLfloat
) GL_CONSTANT_BORDER
||
286 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
287 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
290 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
295 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
299 ctx
->NewState
|= _NEW_PIXEL
;
304 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
306 GET_CURRENT_CONTEXT(ctx
);
307 struct gl_convolution_attrib
*conv
;
309 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
312 case GL_CONVOLUTION_1D
:
314 conv
= &ctx
->Convolution1D
;
316 case GL_CONVOLUTION_2D
:
318 conv
= &ctx
->Convolution2D
;
320 case GL_SEPARABLE_2D
:
322 conv
= &ctx
->Separable2D
;
325 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
330 case GL_CONVOLUTION_BORDER_COLOR
:
331 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
333 case GL_CONVOLUTION_BORDER_MODE
:
334 if (params
[0] == (GLfloat
) GL_REDUCE
||
335 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
336 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
337 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
340 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
344 case GL_CONVOLUTION_FILTER_SCALE
:
345 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
347 case GL_CONVOLUTION_FILTER_BIAS
:
348 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
351 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
355 ctx
->NewState
|= _NEW_PIXEL
;
360 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
362 GET_CURRENT_CONTEXT(ctx
);
364 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
367 case GL_CONVOLUTION_1D
:
370 case GL_CONVOLUTION_2D
:
373 case GL_SEPARABLE_2D
:
377 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
382 case GL_CONVOLUTION_BORDER_MODE
:
383 if (param
== (GLint
) GL_REDUCE
||
384 param
== (GLint
) GL_CONSTANT_BORDER
||
385 param
== (GLint
) GL_REPLICATE_BORDER
) {
386 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
389 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
394 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
398 ctx
->NewState
|= _NEW_PIXEL
;
403 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
405 GET_CURRENT_CONTEXT(ctx
);
406 struct gl_convolution_attrib
*conv
;
408 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
411 case GL_CONVOLUTION_1D
:
413 conv
= &ctx
->Convolution1D
;
415 case GL_CONVOLUTION_2D
:
417 conv
= &ctx
->Convolution2D
;
419 case GL_SEPARABLE_2D
:
421 conv
= &ctx
->Separable2D
;
424 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
429 case GL_CONVOLUTION_BORDER_COLOR
:
430 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
431 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
432 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
433 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
435 case GL_CONVOLUTION_BORDER_MODE
:
436 if (params
[0] == (GLint
) GL_REDUCE
||
437 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
438 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
439 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
442 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
446 case GL_CONVOLUTION_FILTER_SCALE
:
447 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
448 /* need cast to prevent compiler warnings */
449 ctx
->Pixel
.ConvolutionFilterScale
[c
][0] = (GLfloat
) params
[0];
450 ctx
->Pixel
.ConvolutionFilterScale
[c
][1] = (GLfloat
) params
[1];
451 ctx
->Pixel
.ConvolutionFilterScale
[c
][2] = (GLfloat
) params
[2];
452 ctx
->Pixel
.ConvolutionFilterScale
[c
][3] = (GLfloat
) params
[3];
454 case GL_CONVOLUTION_FILTER_BIAS
:
455 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
456 /* need cast to prevent compiler warnings */
457 ctx
->Pixel
.ConvolutionFilterBias
[c
][0] = (GLfloat
) params
[0];
458 ctx
->Pixel
.ConvolutionFilterBias
[c
][1] = (GLfloat
) params
[1];
459 ctx
->Pixel
.ConvolutionFilterBias
[c
][2] = (GLfloat
) params
[2];
460 ctx
->Pixel
.ConvolutionFilterBias
[c
][3] = (GLfloat
) params
[3];
463 _mesa_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 GET_CURRENT_CONTEXT(ctx
);
476 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
478 if (target
!= GL_CONVOLUTION_1D
) {
479 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
483 baseFormat
= base_filter_format(internalFormat
);
484 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
485 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
489 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
490 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
494 ctx
->Driver
.CopyConvolutionFilter1D( ctx
, target
,
495 internalFormat
, x
, y
, width
);
500 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
503 GET_CURRENT_CONTEXT(ctx
);
504 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
506 if (target
!= GL_CONVOLUTION_2D
) {
507 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
511 baseFormat
= base_filter_format(internalFormat
);
512 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
513 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
517 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
518 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
521 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
522 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
526 ctx
->Driver
.CopyConvolutionFilter2D( ctx
, target
, internalFormat
, x
, y
,
533 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
535 const struct gl_convolution_attrib
*filter
;
537 GET_CURRENT_CONTEXT(ctx
);
538 ASSERT_OUTSIDE_BEGIN_END(ctx
);
541 _mesa_update_state(ctx
);
544 if (!_mesa_is_legal_format_and_type(format
, type
)) {
545 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
549 if (format
== GL_COLOR_INDEX
||
550 format
== GL_STENCIL_INDEX
||
551 format
== GL_DEPTH_COMPONENT
||
552 format
== GL_INTENSITY
||
554 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
559 case GL_CONVOLUTION_1D
:
560 filter
= &(ctx
->Convolution1D
);
562 case GL_CONVOLUTION_2D
:
563 filter
= &(ctx
->Convolution2D
);
566 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
570 for (row
= 0; row
< filter
->Height
; row
++) {
571 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
572 filter
->Height
, format
, type
,
574 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
575 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
576 (const GLfloat (*)[4]) src
,
577 format
, type
, dst
, &ctx
->Pack
, 0);
583 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
585 GET_CURRENT_CONTEXT(ctx
);
586 const struct gl_convolution_attrib
*conv
;
588 ASSERT_OUTSIDE_BEGIN_END(ctx
);
591 case GL_CONVOLUTION_1D
:
593 conv
= &ctx
->Convolution1D
;
595 case GL_CONVOLUTION_2D
:
597 conv
= &ctx
->Convolution2D
;
599 case GL_SEPARABLE_2D
:
601 conv
= &ctx
->Separable2D
;
604 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
609 case GL_CONVOLUTION_BORDER_COLOR
:
610 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
612 case GL_CONVOLUTION_BORDER_MODE
:
613 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
615 case GL_CONVOLUTION_FILTER_SCALE
:
616 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
618 case GL_CONVOLUTION_FILTER_BIAS
:
619 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
621 case GL_CONVOLUTION_FORMAT
:
622 *params
= (GLfloat
) conv
->Format
;
624 case GL_CONVOLUTION_WIDTH
:
625 *params
= (GLfloat
) conv
->Width
;
627 case GL_CONVOLUTION_HEIGHT
:
628 *params
= (GLfloat
) conv
->Height
;
630 case GL_MAX_CONVOLUTION_WIDTH
:
631 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
633 case GL_MAX_CONVOLUTION_HEIGHT
:
634 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
637 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
644 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
646 GET_CURRENT_CONTEXT(ctx
);
647 const struct gl_convolution_attrib
*conv
;
649 ASSERT_OUTSIDE_BEGIN_END(ctx
);
652 case GL_CONVOLUTION_1D
:
654 conv
= &ctx
->Convolution1D
;
656 case GL_CONVOLUTION_2D
:
658 conv
= &ctx
->Convolution2D
;
660 case GL_SEPARABLE_2D
:
662 conv
= &ctx
->Separable2D
;
665 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
670 case GL_CONVOLUTION_BORDER_COLOR
:
671 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
672 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
673 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
674 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
676 case GL_CONVOLUTION_BORDER_MODE
:
677 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
679 case GL_CONVOLUTION_FILTER_SCALE
:
680 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
681 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
682 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
683 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
685 case GL_CONVOLUTION_FILTER_BIAS
:
686 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
687 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
688 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
689 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
691 case GL_CONVOLUTION_FORMAT
:
692 *params
= (GLint
) conv
->Format
;
694 case GL_CONVOLUTION_WIDTH
:
695 *params
= (GLint
) conv
->Width
;
697 case GL_CONVOLUTION_HEIGHT
:
698 *params
= (GLint
) conv
->Height
;
700 case GL_MAX_CONVOLUTION_WIDTH
:
701 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
703 case GL_MAX_CONVOLUTION_HEIGHT
:
704 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
707 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
714 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
716 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
717 const struct gl_convolution_attrib
*filter
;
718 GET_CURRENT_CONTEXT(ctx
);
719 ASSERT_OUTSIDE_BEGIN_END(ctx
);
722 _mesa_update_state(ctx
);
725 if (target
!= GL_SEPARABLE_2D
) {
726 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
730 if (!_mesa_is_legal_format_and_type(format
, type
)) {
731 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
735 if (format
== GL_COLOR_INDEX
||
736 format
== GL_STENCIL_INDEX
||
737 format
== GL_DEPTH_COMPONENT
||
738 format
== GL_INTENSITY
||
740 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
744 filter
= &ctx
->Separable2D
;
748 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
749 filter
->Height
, format
, type
,
751 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
752 (const GLfloat (*)[4]) filter
->Filter
,
753 format
, type
, dst
, &ctx
->Pack
, 0);
758 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
761 const GLfloat
*src
= filter
->Filter
+ colStart
;
762 _mesa_pack_float_rgba_span(ctx
, filter
->Height
,
763 (const GLfloat (*)[4]) src
,
764 format
, type
, dst
, &ctx
->Pack
, 0);
767 (void) span
; /* unused at this time */
772 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
774 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
776 GET_CURRENT_CONTEXT(ctx
);
777 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
779 if (target
!= GL_SEPARABLE_2D
) {
780 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
784 baseFormat
= base_filter_format(internalFormat
);
785 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
786 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
790 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
791 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
794 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
795 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
799 if (!_mesa_is_legal_format_and_type(format
, type
)) {
800 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
804 if (format
== GL_COLOR_INDEX
||
805 format
== GL_STENCIL_INDEX
||
806 format
== GL_DEPTH_COMPONENT
||
807 format
== GL_INTENSITY
||
809 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
813 ctx
->Separable2D
.Format
= format
;
814 ctx
->Separable2D
.InternalFormat
= internalFormat
;
815 ctx
->Separable2D
.Width
= width
;
816 ctx
->Separable2D
.Height
= height
;
818 /* unpack row filter */
819 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
820 ctx
->Separable2D
.Filter
,
821 format
, type
, row
, &ctx
->Unpack
,
824 /* apply scale and bias */
826 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
827 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
829 for (i
= 0; i
< width
; i
++) {
830 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0];
831 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
832 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
833 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
834 r
= r
* scale
[0] + bias
[0];
835 g
= g
* scale
[1] + bias
[1];
836 b
= b
* scale
[2] + bias
[2];
837 a
= a
* scale
[3] + bias
[3];
838 ctx
->Separable2D
.Filter
[i
* 4 + 0] = r
;
839 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
840 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
841 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
845 /* unpack column filter */
846 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
847 &ctx
->Separable2D
.Filter
[colStart
],
848 format
, type
, column
, &ctx
->Unpack
,
851 /* apply scale and bias */
853 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
854 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
856 for (i
= 0; i
< width
; i
++) {
857 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
858 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
859 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
860 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
861 r
= r
* scale
[0] + bias
[0];
862 g
= g
* scale
[1] + bias
[1];
863 b
= b
* scale
[2] + bias
[2];
864 a
= a
* scale
[3] + bias
[3];
865 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
866 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
867 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
868 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
872 ctx
->NewState
|= _NEW_PIXEL
;
876 /**********************************************************************/
877 /*** image convolution functions ***/
878 /**********************************************************************/
881 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
882 GLint filterWidth
, const GLfloat filter
[][4],
888 if (filterWidth
>= 1)
889 dstWidth
= srcWidth
- (filterWidth
- 1);
894 return; /* null result */
896 for (i
= 0; i
< dstWidth
; i
++) {
901 for (n
= 0; n
< filterWidth
; n
++) {
902 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
903 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
904 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
905 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
907 dest
[i
][RCOMP
] = sumR
;
908 dest
[i
][GCOMP
] = sumG
;
909 dest
[i
][BCOMP
] = sumB
;
910 dest
[i
][ACOMP
] = sumA
;
916 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
917 GLint filterWidth
, const GLfloat filter
[][4],
919 const GLfloat borderColor
[4])
921 const GLint halfFilterWidth
= filterWidth
/ 2;
924 for (i
= 0; i
< srcWidth
; i
++) {
929 for (n
= 0; n
< filterWidth
; n
++) {
930 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
931 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
932 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
933 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
934 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
937 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
938 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
939 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
940 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
943 dest
[i
][RCOMP
] = sumR
;
944 dest
[i
][GCOMP
] = sumG
;
945 dest
[i
][BCOMP
] = sumB
;
946 dest
[i
][ACOMP
] = sumA
;
952 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
953 GLint filterWidth
, const GLfloat filter
[][4],
956 const GLint halfFilterWidth
= filterWidth
/ 2;
959 for (i
= 0; i
< srcWidth
; i
++) {
964 for (n
= 0; n
< filterWidth
; n
++) {
965 if (i
+ n
< halfFilterWidth
) {
966 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
967 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
968 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
969 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
971 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
972 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
973 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
974 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
975 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
978 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
979 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
980 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
981 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
984 dest
[i
][RCOMP
] = sumR
;
985 dest
[i
][GCOMP
] = sumG
;
986 dest
[i
][BCOMP
] = sumB
;
987 dest
[i
][ACOMP
] = sumA
;
993 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
994 const GLfloat src
[][4],
995 GLint filterWidth
, GLint filterHeight
,
996 const GLfloat filter
[][4],
999 GLint dstWidth
, dstHeight
;
1002 if (filterWidth
>= 1)
1003 dstWidth
= srcWidth
- (filterWidth
- 1);
1005 dstWidth
= srcWidth
;
1007 if (filterHeight
>= 1)
1008 dstHeight
= srcHeight
- (filterHeight
- 1);
1010 dstHeight
= srcHeight
;
1012 if (dstWidth
<= 0 || dstHeight
<= 0)
1015 for (j
= 0; j
< dstHeight
; j
++) {
1016 for (i
= 0; i
< dstWidth
; i
++) {
1021 for (m
= 0; m
< filterHeight
; m
++) {
1022 for (n
= 0; n
< filterWidth
; n
++) {
1023 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1024 const GLint f
= m
* filterWidth
+ n
;
1025 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1026 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1027 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1028 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1031 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1032 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1033 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1034 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1041 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1042 const GLfloat src
[][4],
1043 GLint filterWidth
, GLint filterHeight
,
1044 const GLfloat filter
[][4],
1046 const GLfloat borderColor
[4])
1048 const GLint halfFilterWidth
= filterWidth
/ 2;
1049 const GLint halfFilterHeight
= filterHeight
/ 2;
1052 for (j
= 0; j
< srcHeight
; j
++) {
1053 for (i
= 0; i
< srcWidth
; i
++) {
1058 for (m
= 0; m
< filterHeight
; m
++) {
1059 for (n
= 0; n
< filterWidth
; n
++) {
1060 const GLint f
= m
* filterWidth
+ n
;
1061 const GLint is
= i
+ n
- halfFilterWidth
;
1062 const GLint js
= j
+ m
- halfFilterHeight
;
1063 if (is
< 0 || is
>= srcWidth
||
1064 js
< 0 || js
>= srcHeight
) {
1065 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1066 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1067 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1068 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1071 const GLint k
= js
* srcWidth
+ is
;
1072 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1073 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1074 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1075 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1079 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1080 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1081 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1082 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1089 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1090 const GLfloat src
[][4],
1091 GLint filterWidth
, GLint filterHeight
,
1092 const GLfloat filter
[][4],
1095 const GLint halfFilterWidth
= filterWidth
/ 2;
1096 const GLint halfFilterHeight
= filterHeight
/ 2;
1099 for (j
= 0; j
< srcHeight
; j
++) {
1100 for (i
= 0; i
< srcWidth
; i
++) {
1105 for (m
= 0; m
< filterHeight
; m
++) {
1106 for (n
= 0; n
< filterWidth
; n
++) {
1107 const GLint f
= m
* filterWidth
+ n
;
1108 GLint is
= i
+ n
- halfFilterWidth
;
1109 GLint js
= j
+ m
- halfFilterHeight
;
1113 else if (is
>= srcWidth
)
1117 else if (js
>= srcHeight
)
1119 k
= js
* srcWidth
+ is
;
1120 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1121 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1122 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1123 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1126 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1127 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1128 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1129 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1136 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1137 const GLfloat src
[][4],
1138 GLint filterWidth
, GLint filterHeight
,
1139 const GLfloat rowFilt
[][4],
1140 const GLfloat colFilt
[][4],
1143 GLint dstWidth
, dstHeight
;
1146 if (filterWidth
>= 1)
1147 dstWidth
= srcWidth
- (filterWidth
- 1);
1149 dstWidth
= srcWidth
;
1151 if (filterHeight
>= 1)
1152 dstHeight
= srcHeight
- (filterHeight
- 1);
1154 dstHeight
= srcHeight
;
1156 if (dstWidth
<= 0 || dstHeight
<= 0)
1159 for (j
= 0; j
< dstHeight
; j
++) {
1160 for (i
= 0; i
< dstWidth
; i
++) {
1165 for (m
= 0; m
< filterHeight
; m
++) {
1166 for (n
= 0; n
< filterWidth
; n
++) {
1167 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1168 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1169 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1170 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1171 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1174 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1175 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1176 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1177 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1184 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1185 const GLfloat src
[][4],
1186 GLint filterWidth
, GLint filterHeight
,
1187 const GLfloat rowFilt
[][4],
1188 const GLfloat colFilt
[][4],
1190 const GLfloat borderColor
[4])
1192 const GLint halfFilterWidth
= filterWidth
/ 2;
1193 const GLint halfFilterHeight
= filterHeight
/ 2;
1196 for (j
= 0; j
< srcHeight
; j
++) {
1197 for (i
= 0; i
< srcWidth
; i
++) {
1202 for (m
= 0; m
< filterHeight
; m
++) {
1203 for (n
= 0; n
< filterWidth
; n
++) {
1204 const GLint is
= i
+ n
- halfFilterWidth
;
1205 const GLint js
= j
+ m
- halfFilterHeight
;
1206 if (is
< 0 || is
>= srcWidth
||
1207 js
< 0 || js
>= srcHeight
) {
1208 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1209 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1210 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1211 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1214 GLint k
= js
* srcWidth
+ is
;
1215 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1216 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1217 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1218 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1223 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1224 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1225 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1226 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1233 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1234 const GLfloat src
[][4],
1235 GLint filterWidth
, GLint filterHeight
,
1236 const GLfloat rowFilt
[][4],
1237 const GLfloat colFilt
[][4],
1240 const GLint halfFilterWidth
= filterWidth
/ 2;
1241 const GLint halfFilterHeight
= filterHeight
/ 2;
1244 for (j
= 0; j
< srcHeight
; j
++) {
1245 for (i
= 0; i
< srcWidth
; i
++) {
1250 for (m
= 0; m
< filterHeight
; m
++) {
1251 for (n
= 0; n
< filterWidth
; n
++) {
1252 GLint is
= i
+ n
- halfFilterWidth
;
1253 GLint js
= j
+ m
- halfFilterHeight
;
1257 else if (is
>= srcWidth
)
1261 else if (js
>= srcHeight
)
1263 k
= js
* srcWidth
+ is
;
1264 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1265 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1266 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1267 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1270 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1271 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1272 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1273 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1281 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1282 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1284 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1286 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1287 ctx
->Convolution1D
.Width
,
1288 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1289 (GLfloat (*)[4]) dstImage
);
1290 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1292 case GL_CONSTANT_BORDER
:
1293 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1294 ctx
->Convolution1D
.Width
,
1295 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1296 (GLfloat (*)[4]) dstImage
,
1297 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1299 case GL_REPLICATE_BORDER
:
1300 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1301 ctx
->Convolution1D
.Width
,
1302 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1303 (GLfloat (*)[4]) dstImage
);
1312 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1313 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1315 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1317 convolve_2d_reduce(*width
, *height
,
1318 (const GLfloat (*)[4]) srcImage
,
1319 ctx
->Convolution2D
.Width
,
1320 ctx
->Convolution2D
.Height
,
1321 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1322 (GLfloat (*)[4]) dstImage
);
1323 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1324 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1326 case GL_CONSTANT_BORDER
:
1327 convolve_2d_constant(*width
, *height
,
1328 (const GLfloat (*)[4]) srcImage
,
1329 ctx
->Convolution2D
.Width
,
1330 ctx
->Convolution2D
.Height
,
1331 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1332 (GLfloat (*)[4]) dstImage
,
1333 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1335 case GL_REPLICATE_BORDER
:
1336 convolve_2d_replicate(*width
, *height
,
1337 (const GLfloat (*)[4]) srcImage
,
1338 ctx
->Convolution2D
.Width
,
1339 ctx
->Convolution2D
.Height
,
1340 (const GLfloat (*)[4])ctx
->Convolution2D
.Filter
,
1341 (GLfloat (*)[4]) dstImage
);
1350 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1351 GLsizei
*width
, GLsizei
*height
,
1352 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1354 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1355 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1357 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1359 convolve_sep_reduce(*width
, *height
,
1360 (const GLfloat (*)[4]) srcImage
,
1361 ctx
->Separable2D
.Width
,
1362 ctx
->Separable2D
.Height
,
1363 (const GLfloat (*)[4]) rowFilter
,
1364 (const GLfloat (*)[4]) colFilter
,
1365 (GLfloat (*)[4]) dstImage
);
1366 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1367 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1369 case GL_CONSTANT_BORDER
:
1370 convolve_sep_constant(*width
, *height
,
1371 (const GLfloat (*)[4]) srcImage
,
1372 ctx
->Separable2D
.Width
,
1373 ctx
->Separable2D
.Height
,
1374 (const GLfloat (*)[4]) rowFilter
,
1375 (const GLfloat (*)[4]) colFilter
,
1376 (GLfloat (*)[4]) dstImage
,
1377 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1379 case GL_REPLICATE_BORDER
:
1380 convolve_sep_replicate(*width
, *height
,
1381 (const GLfloat (*)[4]) srcImage
,
1382 ctx
->Separable2D
.Width
,
1383 ctx
->Separable2D
.Height
,
1384 (const GLfloat (*)[4]) rowFilter
,
1385 (const GLfloat (*)[4]) colFilter
,
1386 (GLfloat (*)[4]) dstImage
);
1396 * This function computes an image's size after convolution.
1397 * If the convolution border mode is GL_REDUCE, the post-convolution
1398 * image will be smaller than the original.
1401 _mesa_adjust_image_for_convolution(const GLcontext
*ctx
, GLuint dimensions
,
1402 GLsizei
*width
, GLsizei
*height
)
1404 if (ctx
->Pixel
.Convolution1DEnabled
1406 && ctx
->Pixel
.ConvolutionBorderMode
[0] == GL_REDUCE
) {
1407 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1409 else if (ctx
->Pixel
.Convolution2DEnabled
1411 && ctx
->Pixel
.ConvolutionBorderMode
[1] == GL_REDUCE
) {
1412 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1413 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1415 else if (ctx
->Pixel
.Separable2DEnabled
1417 && ctx
->Pixel
.ConvolutionBorderMode
[2] == GL_REDUCE
) {
1418 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1419 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);