1 /* $Id: convolve.c,v 1.26 2002/03/19 15:22:50 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
122 baseFormat
= base_filter_format(internalFormat
);
123 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
124 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
128 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
129 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
133 if (!_mesa_is_legal_format_and_type(format
, type
)) {
134 _mesa_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 _mesa_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 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
196 baseFormat
= base_filter_format(internalFormat
);
197 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
198 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
202 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
203 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
206 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
207 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
211 if (!_mesa_is_legal_format_and_type(format
, type
)) {
212 _mesa_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 _mesa_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
; 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_AND_FLUSH(ctx
);
274 case GL_CONVOLUTION_1D
:
277 case GL_CONVOLUTION_2D
:
280 case GL_SEPARABLE_2D
:
284 _mesa_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 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
301 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
400 _mesa_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 _mesa_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 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
452 case GL_CONVOLUTION_FILTER_SCALE
:
453 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
454 /* need cast to prevent compiler warnings */
455 ctx
->Pixel
.ConvolutionFilterScale
[c
][0] = (GLfloat
) params
[0];
456 ctx
->Pixel
.ConvolutionFilterScale
[c
][1] = (GLfloat
) params
[1];
457 ctx
->Pixel
.ConvolutionFilterScale
[c
][2] = (GLfloat
) params
[2];
458 ctx
->Pixel
.ConvolutionFilterScale
[c
][3] = (GLfloat
) params
[3];
460 case GL_CONVOLUTION_FILTER_BIAS
:
461 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
462 /* need cast to prevent compiler warnings */
463 ctx
->Pixel
.ConvolutionFilterBias
[c
][0] = (GLfloat
) params
[0];
464 ctx
->Pixel
.ConvolutionFilterBias
[c
][1] = (GLfloat
) params
[1];
465 ctx
->Pixel
.ConvolutionFilterBias
[c
][2] = (GLfloat
) params
[2];
466 ctx
->Pixel
.ConvolutionFilterBias
[c
][3] = (GLfloat
) params
[3];
469 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
473 ctx
->NewState
|= _NEW_PIXEL
;
478 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
481 GET_CURRENT_CONTEXT(ctx
);
482 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
484 if (target
!= GL_CONVOLUTION_1D
) {
485 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
489 baseFormat
= base_filter_format(internalFormat
);
490 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
491 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
495 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
496 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
500 ctx
->Driver
.CopyConvolutionFilter1D( ctx
, target
,
501 internalFormat
, x
, y
, width
);
506 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
509 GET_CURRENT_CONTEXT(ctx
);
510 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
512 if (target
!= GL_CONVOLUTION_2D
) {
513 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
517 baseFormat
= base_filter_format(internalFormat
);
518 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
519 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
523 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
524 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
527 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
528 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
532 ctx
->Driver
.CopyConvolutionFilter2D( ctx
, target
, internalFormat
, x
, y
,
539 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
541 const struct gl_convolution_attrib
*filter
;
543 GET_CURRENT_CONTEXT(ctx
);
544 ASSERT_OUTSIDE_BEGIN_END(ctx
);
547 _mesa_update_state(ctx
);
550 if (!_mesa_is_legal_format_and_type(format
, type
)) {
551 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
555 if (format
== GL_COLOR_INDEX
||
556 format
== GL_STENCIL_INDEX
||
557 format
== GL_DEPTH_COMPONENT
||
558 format
== GL_INTENSITY
||
560 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
565 case GL_CONVOLUTION_1D
:
566 filter
= &(ctx
->Convolution1D
);
568 case GL_CONVOLUTION_2D
:
569 filter
= &(ctx
->Convolution2D
);
572 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
576 for (row
= 0; row
< filter
->Height
; row
++) {
577 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
578 filter
->Height
, format
, type
,
580 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
581 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
582 (const GLfloat (*)[4]) src
,
583 format
, type
, dst
, &ctx
->Pack
, 0);
589 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
591 GET_CURRENT_CONTEXT(ctx
);
592 const struct gl_convolution_attrib
*conv
;
594 ASSERT_OUTSIDE_BEGIN_END(ctx
);
597 case GL_CONVOLUTION_1D
:
599 conv
= &ctx
->Convolution1D
;
601 case GL_CONVOLUTION_2D
:
603 conv
= &ctx
->Convolution2D
;
605 case GL_SEPARABLE_2D
:
607 conv
= &ctx
->Separable2D
;
610 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
615 case GL_CONVOLUTION_BORDER_COLOR
:
616 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
618 case GL_CONVOLUTION_BORDER_MODE
:
619 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
621 case GL_CONVOLUTION_FILTER_SCALE
:
622 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
624 case GL_CONVOLUTION_FILTER_BIAS
:
625 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
627 case GL_CONVOLUTION_FORMAT
:
628 *params
= (GLfloat
) conv
->Format
;
630 case GL_CONVOLUTION_WIDTH
:
631 *params
= (GLfloat
) conv
->Width
;
633 case GL_CONVOLUTION_HEIGHT
:
634 *params
= (GLfloat
) conv
->Height
;
636 case GL_MAX_CONVOLUTION_WIDTH
:
637 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
639 case GL_MAX_CONVOLUTION_HEIGHT
:
640 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
643 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
650 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
652 GET_CURRENT_CONTEXT(ctx
);
653 const struct gl_convolution_attrib
*conv
;
655 ASSERT_OUTSIDE_BEGIN_END(ctx
);
658 case GL_CONVOLUTION_1D
:
660 conv
= &ctx
->Convolution1D
;
662 case GL_CONVOLUTION_2D
:
664 conv
= &ctx
->Convolution2D
;
666 case GL_SEPARABLE_2D
:
668 conv
= &ctx
->Separable2D
;
671 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
676 case GL_CONVOLUTION_BORDER_COLOR
:
677 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
678 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
679 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
680 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
682 case GL_CONVOLUTION_BORDER_MODE
:
683 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
685 case GL_CONVOLUTION_FILTER_SCALE
:
686 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
687 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
688 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
689 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
691 case GL_CONVOLUTION_FILTER_BIAS
:
692 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
693 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
694 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
695 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
697 case GL_CONVOLUTION_FORMAT
:
698 *params
= (GLint
) conv
->Format
;
700 case GL_CONVOLUTION_WIDTH
:
701 *params
= (GLint
) conv
->Width
;
703 case GL_CONVOLUTION_HEIGHT
:
704 *params
= (GLint
) conv
->Height
;
706 case GL_MAX_CONVOLUTION_WIDTH
:
707 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
709 case GL_MAX_CONVOLUTION_HEIGHT
:
710 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
713 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
720 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
722 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
723 const struct gl_convolution_attrib
*filter
;
724 GET_CURRENT_CONTEXT(ctx
);
725 ASSERT_OUTSIDE_BEGIN_END(ctx
);
728 _mesa_update_state(ctx
);
731 if (target
!= GL_SEPARABLE_2D
) {
732 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
736 if (!_mesa_is_legal_format_and_type(format
, type
)) {
737 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
741 if (format
== GL_COLOR_INDEX
||
742 format
== GL_STENCIL_INDEX
||
743 format
== GL_DEPTH_COMPONENT
||
744 format
== GL_INTENSITY
||
746 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
750 filter
= &ctx
->Separable2D
;
754 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
755 filter
->Height
, format
, type
,
757 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
758 (const GLfloat (*)[4]) filter
->Filter
,
759 format
, type
, dst
, &ctx
->Pack
, 0);
764 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
767 const GLfloat
*src
= filter
->Filter
+ colStart
;
768 _mesa_pack_float_rgba_span(ctx
, filter
->Height
,
769 (const GLfloat (*)[4]) src
,
770 format
, type
, dst
, &ctx
->Pack
, 0);
773 (void) span
; /* unused at this time */
778 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
780 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
782 GET_CURRENT_CONTEXT(ctx
);
783 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
785 if (target
!= GL_SEPARABLE_2D
) {
786 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
790 baseFormat
= base_filter_format(internalFormat
);
791 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
792 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
796 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
797 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
800 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
801 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
805 if (!_mesa_is_legal_format_and_type(format
, type
)) {
806 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
810 if (format
== GL_COLOR_INDEX
||
811 format
== GL_STENCIL_INDEX
||
812 format
== GL_DEPTH_COMPONENT
||
813 format
== GL_INTENSITY
||
815 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
819 ctx
->Separable2D
.Format
= format
;
820 ctx
->Separable2D
.InternalFormat
= internalFormat
;
821 ctx
->Separable2D
.Width
= width
;
822 ctx
->Separable2D
.Height
= height
;
824 /* unpack row filter */
825 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
826 ctx
->Separable2D
.Filter
,
827 format
, type
, row
, &ctx
->Unpack
,
830 /* apply scale and bias */
832 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
833 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
835 for (i
= 0; i
< width
; i
++) {
836 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0];
837 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
838 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
839 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
840 r
= r
* scale
[0] + bias
[0];
841 g
= g
* scale
[1] + bias
[1];
842 b
= b
* scale
[2] + bias
[2];
843 a
= a
* scale
[3] + bias
[3];
844 ctx
->Separable2D
.Filter
[i
* 4 + 0] = r
;
845 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
846 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
847 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
851 /* unpack column filter */
852 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
853 &ctx
->Separable2D
.Filter
[colStart
],
854 format
, type
, column
, &ctx
->Unpack
,
857 /* apply scale and bias */
859 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
860 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
862 for (i
= 0; i
< width
; i
++) {
863 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
864 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
865 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
866 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
867 r
= r
* scale
[0] + bias
[0];
868 g
= g
* scale
[1] + bias
[1];
869 b
= b
* scale
[2] + bias
[2];
870 a
= a
* scale
[3] + bias
[3];
871 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
872 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
873 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
874 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
878 ctx
->NewState
|= _NEW_PIXEL
;
882 /**********************************************************************/
883 /*** image convolution functions ***/
884 /**********************************************************************/
887 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
888 GLint filterWidth
, const GLfloat filter
[][4],
894 if (filterWidth
>= 1)
895 dstWidth
= srcWidth
- (filterWidth
- 1);
900 return; /* null result */
902 for (i
= 0; i
< dstWidth
; i
++) {
907 for (n
= 0; n
< filterWidth
; n
++) {
908 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
909 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
910 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
911 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
913 dest
[i
][RCOMP
] = sumR
;
914 dest
[i
][GCOMP
] = sumG
;
915 dest
[i
][BCOMP
] = sumB
;
916 dest
[i
][ACOMP
] = sumA
;
922 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
923 GLint filterWidth
, const GLfloat filter
[][4],
925 const GLfloat borderColor
[4])
927 const GLint halfFilterWidth
= filterWidth
/ 2;
930 for (i
= 0; i
< srcWidth
; i
++) {
935 for (n
= 0; n
< filterWidth
; n
++) {
936 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
937 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
938 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
939 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
940 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
943 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
944 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
945 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
946 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
949 dest
[i
][RCOMP
] = sumR
;
950 dest
[i
][GCOMP
] = sumG
;
951 dest
[i
][BCOMP
] = sumB
;
952 dest
[i
][ACOMP
] = sumA
;
958 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
959 GLint filterWidth
, const GLfloat filter
[][4],
962 const GLint halfFilterWidth
= filterWidth
/ 2;
965 for (i
= 0; i
< srcWidth
; i
++) {
970 for (n
= 0; n
< filterWidth
; n
++) {
971 if (i
+ n
< halfFilterWidth
) {
972 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
973 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
974 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
975 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
977 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
978 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
979 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
980 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
981 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
984 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
985 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
986 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
987 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
990 dest
[i
][RCOMP
] = sumR
;
991 dest
[i
][GCOMP
] = sumG
;
992 dest
[i
][BCOMP
] = sumB
;
993 dest
[i
][ACOMP
] = sumA
;
999 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
1000 const GLfloat src
[][4],
1001 GLint filterWidth
, GLint filterHeight
,
1002 const GLfloat filter
[][4],
1005 GLint dstWidth
, dstHeight
;
1008 if (filterWidth
>= 1)
1009 dstWidth
= srcWidth
- (filterWidth
- 1);
1011 dstWidth
= srcWidth
;
1013 if (filterHeight
>= 1)
1014 dstHeight
= srcHeight
- (filterHeight
- 1);
1016 dstHeight
= srcHeight
;
1018 if (dstWidth
<= 0 || dstHeight
<= 0)
1021 for (j
= 0; j
< dstHeight
; j
++) {
1022 for (i
= 0; i
< dstWidth
; i
++) {
1027 for (m
= 0; m
< filterHeight
; m
++) {
1028 for (n
= 0; n
< filterWidth
; n
++) {
1029 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1030 const GLint f
= m
* filterWidth
+ n
;
1031 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1032 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1033 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1034 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1037 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1038 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1039 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1040 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1047 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1048 const GLfloat src
[][4],
1049 GLint filterWidth
, GLint filterHeight
,
1050 const GLfloat filter
[][4],
1052 const GLfloat borderColor
[4])
1054 const GLint halfFilterWidth
= filterWidth
/ 2;
1055 const GLint halfFilterHeight
= filterHeight
/ 2;
1058 for (j
= 0; j
< srcHeight
; j
++) {
1059 for (i
= 0; i
< srcWidth
; i
++) {
1064 for (m
= 0; m
< filterHeight
; m
++) {
1065 for (n
= 0; n
< filterWidth
; n
++) {
1066 const GLint f
= m
* filterWidth
+ n
;
1067 const GLint is
= i
+ n
- halfFilterWidth
;
1068 const GLint js
= j
+ m
- halfFilterHeight
;
1069 if (is
< 0 || is
>= srcWidth
||
1070 js
< 0 || js
>= srcHeight
) {
1071 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1072 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1073 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1074 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1077 const GLint k
= js
* srcWidth
+ is
;
1078 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1079 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1080 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1081 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1085 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1086 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1087 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1088 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1095 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1096 const GLfloat src
[][4],
1097 GLint filterWidth
, GLint filterHeight
,
1098 const GLfloat filter
[][4],
1101 const GLint halfFilterWidth
= filterWidth
/ 2;
1102 const GLint halfFilterHeight
= filterHeight
/ 2;
1105 for (j
= 0; j
< srcHeight
; j
++) {
1106 for (i
= 0; i
< srcWidth
; i
++) {
1111 for (m
= 0; m
< filterHeight
; m
++) {
1112 for (n
= 0; n
< filterWidth
; n
++) {
1113 const GLint f
= m
* filterWidth
+ n
;
1114 GLint is
= i
+ n
- halfFilterWidth
;
1115 GLint js
= j
+ m
- halfFilterHeight
;
1119 else if (is
>= srcWidth
)
1123 else if (js
>= srcHeight
)
1125 k
= js
* srcWidth
+ is
;
1126 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1127 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1128 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1129 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1132 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1133 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1134 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1135 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1142 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1143 const GLfloat src
[][4],
1144 GLint filterWidth
, GLint filterHeight
,
1145 const GLfloat rowFilt
[][4],
1146 const GLfloat colFilt
[][4],
1149 GLint dstWidth
, dstHeight
;
1152 if (filterWidth
>= 1)
1153 dstWidth
= srcWidth
- (filterWidth
- 1);
1155 dstWidth
= srcWidth
;
1157 if (filterHeight
>= 1)
1158 dstHeight
= srcHeight
- (filterHeight
- 1);
1160 dstHeight
= srcHeight
;
1162 if (dstWidth
<= 0 || dstHeight
<= 0)
1165 for (j
= 0; j
< dstHeight
; j
++) {
1166 for (i
= 0; i
< dstWidth
; i
++) {
1171 for (m
= 0; m
< filterHeight
; m
++) {
1172 for (n
= 0; n
< filterWidth
; n
++) {
1173 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1174 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1175 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1176 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1177 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1180 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1181 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1182 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1183 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1190 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1191 const GLfloat src
[][4],
1192 GLint filterWidth
, GLint filterHeight
,
1193 const GLfloat rowFilt
[][4],
1194 const GLfloat colFilt
[][4],
1196 const GLfloat borderColor
[4])
1198 const GLint halfFilterWidth
= filterWidth
/ 2;
1199 const GLint halfFilterHeight
= filterHeight
/ 2;
1202 for (j
= 0; j
< srcHeight
; j
++) {
1203 for (i
= 0; i
< srcWidth
; i
++) {
1208 for (m
= 0; m
< filterHeight
; m
++) {
1209 for (n
= 0; n
< filterWidth
; n
++) {
1210 const GLint is
= i
+ n
- halfFilterWidth
;
1211 const GLint js
= j
+ m
- halfFilterHeight
;
1212 if (is
< 0 || is
>= srcWidth
||
1213 js
< 0 || js
>= srcHeight
) {
1214 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1215 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1216 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1217 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1220 GLint k
= js
* srcWidth
+ is
;
1221 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1222 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1223 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1224 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1229 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1230 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1231 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1232 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1239 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1240 const GLfloat src
[][4],
1241 GLint filterWidth
, GLint filterHeight
,
1242 const GLfloat rowFilt
[][4],
1243 const GLfloat colFilt
[][4],
1246 const GLint halfFilterWidth
= filterWidth
/ 2;
1247 const GLint halfFilterHeight
= filterHeight
/ 2;
1250 for (j
= 0; j
< srcHeight
; j
++) {
1251 for (i
= 0; i
< srcWidth
; i
++) {
1256 for (m
= 0; m
< filterHeight
; m
++) {
1257 for (n
= 0; n
< filterWidth
; n
++) {
1258 GLint is
= i
+ n
- halfFilterWidth
;
1259 GLint js
= j
+ m
- halfFilterHeight
;
1263 else if (is
>= srcWidth
)
1267 else if (js
>= srcHeight
)
1269 k
= js
* srcWidth
+ is
;
1270 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1271 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1272 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1273 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1276 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1277 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1278 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1279 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1287 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1288 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1290 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1292 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1293 ctx
->Convolution1D
.Width
,
1294 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1295 (GLfloat (*)[4]) dstImage
);
1296 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1298 case GL_CONSTANT_BORDER
:
1299 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1300 ctx
->Convolution1D
.Width
,
1301 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1302 (GLfloat (*)[4]) dstImage
,
1303 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1305 case GL_REPLICATE_BORDER
:
1306 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1307 ctx
->Convolution1D
.Width
,
1308 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1309 (GLfloat (*)[4]) dstImage
);
1318 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1319 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1321 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1323 convolve_2d_reduce(*width
, *height
,
1324 (const GLfloat (*)[4]) srcImage
,
1325 ctx
->Convolution2D
.Width
,
1326 ctx
->Convolution2D
.Height
,
1327 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1328 (GLfloat (*)[4]) dstImage
);
1329 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1330 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1332 case GL_CONSTANT_BORDER
:
1333 convolve_2d_constant(*width
, *height
,
1334 (const GLfloat (*)[4]) srcImage
,
1335 ctx
->Convolution2D
.Width
,
1336 ctx
->Convolution2D
.Height
,
1337 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1338 (GLfloat (*)[4]) dstImage
,
1339 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1341 case GL_REPLICATE_BORDER
:
1342 convolve_2d_replicate(*width
, *height
,
1343 (const GLfloat (*)[4]) srcImage
,
1344 ctx
->Convolution2D
.Width
,
1345 ctx
->Convolution2D
.Height
,
1346 (const GLfloat (*)[4])ctx
->Convolution2D
.Filter
,
1347 (GLfloat (*)[4]) dstImage
);
1356 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1357 GLsizei
*width
, GLsizei
*height
,
1358 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1360 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1361 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1363 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1365 convolve_sep_reduce(*width
, *height
,
1366 (const GLfloat (*)[4]) srcImage
,
1367 ctx
->Separable2D
.Width
,
1368 ctx
->Separable2D
.Height
,
1369 (const GLfloat (*)[4]) rowFilter
,
1370 (const GLfloat (*)[4]) colFilter
,
1371 (GLfloat (*)[4]) dstImage
);
1372 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1373 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1375 case GL_CONSTANT_BORDER
:
1376 convolve_sep_constant(*width
, *height
,
1377 (const GLfloat (*)[4]) srcImage
,
1378 ctx
->Separable2D
.Width
,
1379 ctx
->Separable2D
.Height
,
1380 (const GLfloat (*)[4]) rowFilter
,
1381 (const GLfloat (*)[4]) colFilter
,
1382 (GLfloat (*)[4]) dstImage
,
1383 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1385 case GL_REPLICATE_BORDER
:
1386 convolve_sep_replicate(*width
, *height
,
1387 (const GLfloat (*)[4]) srcImage
,
1388 ctx
->Separable2D
.Width
,
1389 ctx
->Separable2D
.Height
,
1390 (const GLfloat (*)[4]) rowFilter
,
1391 (const GLfloat (*)[4]) colFilter
,
1392 (GLfloat (*)[4]) dstImage
);
1402 * This function computes an image's size after convolution.
1403 * If the convolution border mode is GL_REDUCE, the post-convolution
1404 * image will be smaller than the original.
1407 _mesa_adjust_image_for_convolution(const GLcontext
*ctx
, GLuint dimensions
,
1408 GLsizei
*width
, GLsizei
*height
)
1410 if (ctx
->Pixel
.Convolution1DEnabled
1412 && ctx
->Pixel
.ConvolutionBorderMode
[0] == GL_REDUCE
) {
1413 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1415 else if (ctx
->Pixel
.Convolution2DEnabled
1417 && ctx
->Pixel
.ConvolutionBorderMode
[1] == GL_REDUCE
) {
1418 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1419 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1421 else if (ctx
->Pixel
.Separable2DEnabled
1423 && ctx
->Pixel
.ConvolutionBorderMode
[2] == GL_REDUCE
) {
1424 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1425 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);