1 /* $Id: convolve.c,v 1.28 2002/10/24 23:57:20 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 * Given an internalFormat token passed to glConvolutionFilter
47 * or glSeparableFilter, return the corresponding base format.
48 * Return -1 if invalid token.
51 base_filter_format( GLenum format
)
66 case GL_LUMINANCE_ALPHA
:
67 case GL_LUMINANCE4_ALPHA4
:
68 case GL_LUMINANCE6_ALPHA2
:
69 case GL_LUMINANCE8_ALPHA8
:
70 case GL_LUMINANCE12_ALPHA4
:
71 case GL_LUMINANCE12_ALPHA12
:
72 case GL_LUMINANCE16_ALPHA16
:
73 return GL_LUMINANCE_ALPHA
;
100 return -1; /* error */
106 _mesa_ConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*image
)
109 GET_CURRENT_CONTEXT(ctx
);
110 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
112 if (target
!= GL_CONVOLUTION_1D
) {
113 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
117 baseFormat
= base_filter_format(internalFormat
);
118 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
119 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
123 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
124 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
128 if (!_mesa_is_legal_format_and_type(format
, type
)) {
129 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter1D(format or type)");
133 if (format
== GL_COLOR_INDEX
||
134 format
== GL_STENCIL_INDEX
||
135 format
== GL_DEPTH_COMPONENT
||
136 format
== GL_INTENSITY
||
138 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(format or type)");
142 ctx
->Convolution1D
.Format
= format
;
143 ctx
->Convolution1D
.InternalFormat
= internalFormat
;
144 ctx
->Convolution1D
.Width
= width
;
145 ctx
->Convolution1D
.Height
= 1;
147 /* unpack filter image */
148 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
149 ctx
->Convolution1D
.Filter
,
150 format
, type
, image
, &ctx
->Unpack
,
153 /* apply scale and bias */
155 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[0];
156 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[0];
158 for (i
= 0; i
< width
; i
++) {
159 GLfloat r
= ctx
->Convolution1D
.Filter
[i
* 4 + 0];
160 GLfloat g
= ctx
->Convolution1D
.Filter
[i
* 4 + 1];
161 GLfloat b
= ctx
->Convolution1D
.Filter
[i
* 4 + 2];
162 GLfloat a
= ctx
->Convolution1D
.Filter
[i
* 4 + 3];
163 r
= r
* scale
[0] + bias
[0];
164 g
= g
* scale
[1] + bias
[1];
165 b
= b
* scale
[2] + bias
[2];
166 a
= a
* scale
[3] + bias
[3];
167 ctx
->Convolution1D
.Filter
[i
* 4 + 0] = r
;
168 ctx
->Convolution1D
.Filter
[i
* 4 + 1] = g
;
169 ctx
->Convolution1D
.Filter
[i
* 4 + 2] = b
;
170 ctx
->Convolution1D
.Filter
[i
* 4 + 3] = a
;
174 ctx
->NewState
|= _NEW_PIXEL
;
179 _mesa_ConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*image
)
183 GET_CURRENT_CONTEXT(ctx
);
184 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
186 if (target
!= GL_CONVOLUTION_2D
) {
187 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
191 baseFormat
= base_filter_format(internalFormat
);
192 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
193 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
197 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
198 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
201 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
202 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
206 if (!_mesa_is_legal_format_and_type(format
, type
)) {
207 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter2D(format or type)");
210 if (format
== GL_COLOR_INDEX
||
211 format
== GL_STENCIL_INDEX
||
212 format
== GL_DEPTH_COMPONENT
||
213 format
== GL_INTENSITY
||
215 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
219 components
= _mesa_components_in_format(format
);
220 assert(components
> 0); /* this should have been caught earlier */
222 ctx
->Convolution2D
.Format
= format
;
223 ctx
->Convolution2D
.InternalFormat
= internalFormat
;
224 ctx
->Convolution2D
.Width
= width
;
225 ctx
->Convolution2D
.Height
= height
;
227 /* Unpack filter image. We always store filters in RGBA format. */
228 for (i
= 0; i
< height
; i
++) {
229 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
, image
, width
,
230 height
, format
, type
, 0, i
, 0);
231 GLfloat
*dst
= ctx
->Convolution2D
.Filter
+ i
* width
* 4;
232 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, dst
,
233 format
, type
, src
, &ctx
->Unpack
,
237 /* apply scale and bias */
239 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[1];
240 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[1];
241 for (i
= 0; i
< width
* height
; i
++) {
242 GLfloat r
= ctx
->Convolution2D
.Filter
[i
* 4 + 0];
243 GLfloat g
= ctx
->Convolution2D
.Filter
[i
* 4 + 1];
244 GLfloat b
= ctx
->Convolution2D
.Filter
[i
* 4 + 2];
245 GLfloat a
= ctx
->Convolution2D
.Filter
[i
* 4 + 3];
246 r
= r
* scale
[0] + bias
[0];
247 g
= g
* scale
[1] + bias
[1];
248 b
= b
* scale
[2] + bias
[2];
249 a
= a
* scale
[3] + bias
[3];
250 ctx
->Convolution2D
.Filter
[i
* 4 + 0] = r
;
251 ctx
->Convolution2D
.Filter
[i
* 4 + 1] = g
;
252 ctx
->Convolution2D
.Filter
[i
* 4 + 2] = b
;
253 ctx
->Convolution2D
.Filter
[i
* 4 + 3] = a
;
257 ctx
->NewState
|= _NEW_PIXEL
;
262 _mesa_ConvolutionParameterf(GLenum target
, GLenum pname
, GLfloat param
)
264 GET_CURRENT_CONTEXT(ctx
);
266 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
269 case GL_CONVOLUTION_1D
:
272 case GL_CONVOLUTION_2D
:
275 case GL_SEPARABLE_2D
:
279 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
284 case GL_CONVOLUTION_BORDER_MODE
:
285 if (param
== (GLfloat
) GL_REDUCE
||
286 param
== (GLfloat
) GL_CONSTANT_BORDER
||
287 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
288 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
291 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
296 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
300 ctx
->NewState
|= _NEW_PIXEL
;
305 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
307 GET_CURRENT_CONTEXT(ctx
);
308 struct gl_convolution_attrib
*conv
;
310 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
313 case GL_CONVOLUTION_1D
:
315 conv
= &ctx
->Convolution1D
;
317 case GL_CONVOLUTION_2D
:
319 conv
= &ctx
->Convolution2D
;
321 case GL_SEPARABLE_2D
:
323 conv
= &ctx
->Separable2D
;
326 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
331 case GL_CONVOLUTION_BORDER_COLOR
:
332 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
334 case GL_CONVOLUTION_BORDER_MODE
:
335 if (params
[0] == (GLfloat
) GL_REDUCE
||
336 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
337 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
338 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
341 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
345 case GL_CONVOLUTION_FILTER_SCALE
:
346 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
348 case GL_CONVOLUTION_FILTER_BIAS
:
349 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
352 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
356 ctx
->NewState
|= _NEW_PIXEL
;
361 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
363 GET_CURRENT_CONTEXT(ctx
);
365 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
368 case GL_CONVOLUTION_1D
:
371 case GL_CONVOLUTION_2D
:
374 case GL_SEPARABLE_2D
:
378 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
383 case GL_CONVOLUTION_BORDER_MODE
:
384 if (param
== (GLint
) GL_REDUCE
||
385 param
== (GLint
) GL_CONSTANT_BORDER
||
386 param
== (GLint
) GL_REPLICATE_BORDER
) {
387 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
390 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
395 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
399 ctx
->NewState
|= _NEW_PIXEL
;
404 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
406 GET_CURRENT_CONTEXT(ctx
);
407 struct gl_convolution_attrib
*conv
;
409 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
412 case GL_CONVOLUTION_1D
:
414 conv
= &ctx
->Convolution1D
;
416 case GL_CONVOLUTION_2D
:
418 conv
= &ctx
->Convolution2D
;
420 case GL_SEPARABLE_2D
:
422 conv
= &ctx
->Separable2D
;
425 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
430 case GL_CONVOLUTION_BORDER_COLOR
:
431 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
432 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
433 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
434 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
436 case GL_CONVOLUTION_BORDER_MODE
:
437 if (params
[0] == (GLint
) GL_REDUCE
||
438 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
439 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
440 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
443 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
447 case GL_CONVOLUTION_FILTER_SCALE
:
448 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
449 /* need cast to prevent compiler warnings */
450 ctx
->Pixel
.ConvolutionFilterScale
[c
][0] = (GLfloat
) params
[0];
451 ctx
->Pixel
.ConvolutionFilterScale
[c
][1] = (GLfloat
) params
[1];
452 ctx
->Pixel
.ConvolutionFilterScale
[c
][2] = (GLfloat
) params
[2];
453 ctx
->Pixel
.ConvolutionFilterScale
[c
][3] = (GLfloat
) params
[3];
455 case GL_CONVOLUTION_FILTER_BIAS
:
456 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
457 /* need cast to prevent compiler warnings */
458 ctx
->Pixel
.ConvolutionFilterBias
[c
][0] = (GLfloat
) params
[0];
459 ctx
->Pixel
.ConvolutionFilterBias
[c
][1] = (GLfloat
) params
[1];
460 ctx
->Pixel
.ConvolutionFilterBias
[c
][2] = (GLfloat
) params
[2];
461 ctx
->Pixel
.ConvolutionFilterBias
[c
][3] = (GLfloat
) params
[3];
464 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
468 ctx
->NewState
|= _NEW_PIXEL
;
473 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
476 GET_CURRENT_CONTEXT(ctx
);
477 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
479 if (target
!= GL_CONVOLUTION_1D
) {
480 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
484 baseFormat
= base_filter_format(internalFormat
);
485 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
486 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
490 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
491 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
495 ctx
->Driver
.CopyConvolutionFilter1D( ctx
, target
,
496 internalFormat
, x
, y
, width
);
501 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
504 GET_CURRENT_CONTEXT(ctx
);
505 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
507 if (target
!= GL_CONVOLUTION_2D
) {
508 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
512 baseFormat
= base_filter_format(internalFormat
);
513 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
514 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
518 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
519 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
522 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
523 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
527 ctx
->Driver
.CopyConvolutionFilter2D( ctx
, target
, internalFormat
, x
, y
,
534 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
536 const struct gl_convolution_attrib
*filter
;
538 GET_CURRENT_CONTEXT(ctx
);
539 ASSERT_OUTSIDE_BEGIN_END(ctx
);
542 _mesa_update_state(ctx
);
545 if (!_mesa_is_legal_format_and_type(format
, type
)) {
546 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
550 if (format
== GL_COLOR_INDEX
||
551 format
== GL_STENCIL_INDEX
||
552 format
== GL_DEPTH_COMPONENT
||
553 format
== GL_INTENSITY
||
555 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
560 case GL_CONVOLUTION_1D
:
561 filter
= &(ctx
->Convolution1D
);
563 case GL_CONVOLUTION_2D
:
564 filter
= &(ctx
->Convolution2D
);
567 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
571 for (row
= 0; row
< filter
->Height
; row
++) {
572 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
573 filter
->Height
, format
, type
,
575 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
576 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
577 (const GLfloat (*)[4]) src
,
578 format
, type
, dst
, &ctx
->Pack
, 0);
584 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
586 GET_CURRENT_CONTEXT(ctx
);
587 const struct gl_convolution_attrib
*conv
;
589 ASSERT_OUTSIDE_BEGIN_END(ctx
);
592 case GL_CONVOLUTION_1D
:
594 conv
= &ctx
->Convolution1D
;
596 case GL_CONVOLUTION_2D
:
598 conv
= &ctx
->Convolution2D
;
600 case GL_SEPARABLE_2D
:
602 conv
= &ctx
->Separable2D
;
605 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
610 case GL_CONVOLUTION_BORDER_COLOR
:
611 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
613 case GL_CONVOLUTION_BORDER_MODE
:
614 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
616 case GL_CONVOLUTION_FILTER_SCALE
:
617 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
619 case GL_CONVOLUTION_FILTER_BIAS
:
620 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
622 case GL_CONVOLUTION_FORMAT
:
623 *params
= (GLfloat
) conv
->Format
;
625 case GL_CONVOLUTION_WIDTH
:
626 *params
= (GLfloat
) conv
->Width
;
628 case GL_CONVOLUTION_HEIGHT
:
629 *params
= (GLfloat
) conv
->Height
;
631 case GL_MAX_CONVOLUTION_WIDTH
:
632 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
634 case GL_MAX_CONVOLUTION_HEIGHT
:
635 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
638 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
645 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
647 GET_CURRENT_CONTEXT(ctx
);
648 const struct gl_convolution_attrib
*conv
;
650 ASSERT_OUTSIDE_BEGIN_END(ctx
);
653 case GL_CONVOLUTION_1D
:
655 conv
= &ctx
->Convolution1D
;
657 case GL_CONVOLUTION_2D
:
659 conv
= &ctx
->Convolution2D
;
661 case GL_SEPARABLE_2D
:
663 conv
= &ctx
->Separable2D
;
666 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
671 case GL_CONVOLUTION_BORDER_COLOR
:
672 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
673 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
674 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
675 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
677 case GL_CONVOLUTION_BORDER_MODE
:
678 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
680 case GL_CONVOLUTION_FILTER_SCALE
:
681 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
682 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
683 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
684 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
686 case GL_CONVOLUTION_FILTER_BIAS
:
687 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
688 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
689 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
690 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
692 case GL_CONVOLUTION_FORMAT
:
693 *params
= (GLint
) conv
->Format
;
695 case GL_CONVOLUTION_WIDTH
:
696 *params
= (GLint
) conv
->Width
;
698 case GL_CONVOLUTION_HEIGHT
:
699 *params
= (GLint
) conv
->Height
;
701 case GL_MAX_CONVOLUTION_WIDTH
:
702 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
704 case GL_MAX_CONVOLUTION_HEIGHT
:
705 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
708 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
715 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
717 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
718 const struct gl_convolution_attrib
*filter
;
719 GET_CURRENT_CONTEXT(ctx
);
720 ASSERT_OUTSIDE_BEGIN_END(ctx
);
723 _mesa_update_state(ctx
);
726 if (target
!= GL_SEPARABLE_2D
) {
727 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
731 if (!_mesa_is_legal_format_and_type(format
, type
)) {
732 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
736 if (format
== GL_COLOR_INDEX
||
737 format
== GL_STENCIL_INDEX
||
738 format
== GL_DEPTH_COMPONENT
||
739 format
== GL_INTENSITY
||
741 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
745 filter
= &ctx
->Separable2D
;
749 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
750 filter
->Height
, format
, type
,
752 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
753 (const GLfloat (*)[4]) filter
->Filter
,
754 format
, type
, dst
, &ctx
->Pack
, 0);
759 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
762 const GLfloat
*src
= filter
->Filter
+ colStart
;
763 _mesa_pack_float_rgba_span(ctx
, filter
->Height
,
764 (const GLfloat (*)[4]) src
,
765 format
, type
, dst
, &ctx
->Pack
, 0);
768 (void) span
; /* unused at this time */
773 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
775 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
777 GET_CURRENT_CONTEXT(ctx
);
778 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
780 if (target
!= GL_SEPARABLE_2D
) {
781 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
785 baseFormat
= base_filter_format(internalFormat
);
786 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
787 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
791 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
792 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
795 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
796 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
800 if (!_mesa_is_legal_format_and_type(format
, type
)) {
801 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
805 if (format
== GL_COLOR_INDEX
||
806 format
== GL_STENCIL_INDEX
||
807 format
== GL_DEPTH_COMPONENT
||
808 format
== GL_INTENSITY
||
810 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
814 ctx
->Separable2D
.Format
= format
;
815 ctx
->Separable2D
.InternalFormat
= internalFormat
;
816 ctx
->Separable2D
.Width
= width
;
817 ctx
->Separable2D
.Height
= height
;
819 /* unpack row filter */
820 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
821 ctx
->Separable2D
.Filter
,
822 format
, type
, row
, &ctx
->Unpack
,
825 /* apply scale and bias */
827 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
828 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
830 for (i
= 0; i
< width
; i
++) {
831 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0];
832 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
833 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
834 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
835 r
= r
* scale
[0] + bias
[0];
836 g
= g
* scale
[1] + bias
[1];
837 b
= b
* scale
[2] + bias
[2];
838 a
= a
* scale
[3] + bias
[3];
839 ctx
->Separable2D
.Filter
[i
* 4 + 0] = r
;
840 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
841 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
842 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
846 /* unpack column filter */
847 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
848 &ctx
->Separable2D
.Filter
[colStart
],
849 format
, type
, column
, &ctx
->Unpack
,
852 /* apply scale and bias */
854 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
855 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
857 for (i
= 0; i
< width
; i
++) {
858 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
859 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
860 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
861 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
862 r
= r
* scale
[0] + bias
[0];
863 g
= g
* scale
[1] + bias
[1];
864 b
= b
* scale
[2] + bias
[2];
865 a
= a
* scale
[3] + bias
[3];
866 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
867 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
868 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
869 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
873 ctx
->NewState
|= _NEW_PIXEL
;
877 /**********************************************************************/
878 /*** image convolution functions ***/
879 /**********************************************************************/
882 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
883 GLint filterWidth
, const GLfloat filter
[][4],
889 if (filterWidth
>= 1)
890 dstWidth
= srcWidth
- (filterWidth
- 1);
895 return; /* null result */
897 for (i
= 0; i
< dstWidth
; i
++) {
902 for (n
= 0; n
< filterWidth
; n
++) {
903 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
904 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
905 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
906 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
908 dest
[i
][RCOMP
] = sumR
;
909 dest
[i
][GCOMP
] = sumG
;
910 dest
[i
][BCOMP
] = sumB
;
911 dest
[i
][ACOMP
] = sumA
;
917 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
918 GLint filterWidth
, const GLfloat filter
[][4],
920 const GLfloat borderColor
[4])
922 const GLint halfFilterWidth
= filterWidth
/ 2;
925 for (i
= 0; i
< srcWidth
; i
++) {
930 for (n
= 0; n
< filterWidth
; n
++) {
931 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
932 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
933 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
934 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
935 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
938 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
939 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
940 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
941 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
944 dest
[i
][RCOMP
] = sumR
;
945 dest
[i
][GCOMP
] = sumG
;
946 dest
[i
][BCOMP
] = sumB
;
947 dest
[i
][ACOMP
] = sumA
;
953 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
954 GLint filterWidth
, const GLfloat filter
[][4],
957 const GLint halfFilterWidth
= filterWidth
/ 2;
960 for (i
= 0; i
< srcWidth
; i
++) {
965 for (n
= 0; n
< filterWidth
; n
++) {
966 if (i
+ n
< halfFilterWidth
) {
967 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
968 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
969 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
970 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
972 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
973 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
974 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
975 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
976 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
979 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
980 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
981 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
982 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
985 dest
[i
][RCOMP
] = sumR
;
986 dest
[i
][GCOMP
] = sumG
;
987 dest
[i
][BCOMP
] = sumB
;
988 dest
[i
][ACOMP
] = sumA
;
994 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
995 const GLfloat src
[][4],
996 GLint filterWidth
, GLint filterHeight
,
997 const GLfloat filter
[][4],
1000 GLint dstWidth
, dstHeight
;
1003 if (filterWidth
>= 1)
1004 dstWidth
= srcWidth
- (filterWidth
- 1);
1006 dstWidth
= srcWidth
;
1008 if (filterHeight
>= 1)
1009 dstHeight
= srcHeight
- (filterHeight
- 1);
1011 dstHeight
= srcHeight
;
1013 if (dstWidth
<= 0 || dstHeight
<= 0)
1016 for (j
= 0; j
< dstHeight
; j
++) {
1017 for (i
= 0; i
< dstWidth
; i
++) {
1022 for (m
= 0; m
< filterHeight
; m
++) {
1023 for (n
= 0; n
< filterWidth
; n
++) {
1024 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1025 const GLint f
= m
* filterWidth
+ n
;
1026 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1027 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1028 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1029 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1032 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1033 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1034 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1035 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1042 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1043 const GLfloat src
[][4],
1044 GLint filterWidth
, GLint filterHeight
,
1045 const GLfloat filter
[][4],
1047 const GLfloat borderColor
[4])
1049 const GLint halfFilterWidth
= filterWidth
/ 2;
1050 const GLint halfFilterHeight
= filterHeight
/ 2;
1053 for (j
= 0; j
< srcHeight
; j
++) {
1054 for (i
= 0; i
< srcWidth
; i
++) {
1059 for (m
= 0; m
< filterHeight
; m
++) {
1060 for (n
= 0; n
< filterWidth
; n
++) {
1061 const GLint f
= m
* filterWidth
+ n
;
1062 const GLint is
= i
+ n
- halfFilterWidth
;
1063 const GLint js
= j
+ m
- halfFilterHeight
;
1064 if (is
< 0 || is
>= srcWidth
||
1065 js
< 0 || js
>= srcHeight
) {
1066 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1067 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1068 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1069 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1072 const GLint k
= js
* srcWidth
+ is
;
1073 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1074 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1075 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1076 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1080 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1081 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1082 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1083 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1090 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1091 const GLfloat src
[][4],
1092 GLint filterWidth
, GLint filterHeight
,
1093 const GLfloat filter
[][4],
1096 const GLint halfFilterWidth
= filterWidth
/ 2;
1097 const GLint halfFilterHeight
= filterHeight
/ 2;
1100 for (j
= 0; j
< srcHeight
; j
++) {
1101 for (i
= 0; i
< srcWidth
; i
++) {
1106 for (m
= 0; m
< filterHeight
; m
++) {
1107 for (n
= 0; n
< filterWidth
; n
++) {
1108 const GLint f
= m
* filterWidth
+ n
;
1109 GLint is
= i
+ n
- halfFilterWidth
;
1110 GLint js
= j
+ m
- halfFilterHeight
;
1114 else if (is
>= srcWidth
)
1118 else if (js
>= srcHeight
)
1120 k
= js
* srcWidth
+ is
;
1121 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1122 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1123 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1124 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1127 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1128 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1129 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1130 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1137 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1138 const GLfloat src
[][4],
1139 GLint filterWidth
, GLint filterHeight
,
1140 const GLfloat rowFilt
[][4],
1141 const GLfloat colFilt
[][4],
1144 GLint dstWidth
, dstHeight
;
1147 if (filterWidth
>= 1)
1148 dstWidth
= srcWidth
- (filterWidth
- 1);
1150 dstWidth
= srcWidth
;
1152 if (filterHeight
>= 1)
1153 dstHeight
= srcHeight
- (filterHeight
- 1);
1155 dstHeight
= srcHeight
;
1157 if (dstWidth
<= 0 || dstHeight
<= 0)
1160 for (j
= 0; j
< dstHeight
; j
++) {
1161 for (i
= 0; i
< dstWidth
; i
++) {
1166 for (m
= 0; m
< filterHeight
; m
++) {
1167 for (n
= 0; n
< filterWidth
; n
++) {
1168 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1169 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1170 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1171 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1172 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1175 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1176 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1177 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1178 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1185 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1186 const GLfloat src
[][4],
1187 GLint filterWidth
, GLint filterHeight
,
1188 const GLfloat rowFilt
[][4],
1189 const GLfloat colFilt
[][4],
1191 const GLfloat borderColor
[4])
1193 const GLint halfFilterWidth
= filterWidth
/ 2;
1194 const GLint halfFilterHeight
= filterHeight
/ 2;
1197 for (j
= 0; j
< srcHeight
; j
++) {
1198 for (i
= 0; i
< srcWidth
; i
++) {
1203 for (m
= 0; m
< filterHeight
; m
++) {
1204 for (n
= 0; n
< filterWidth
; n
++) {
1205 const GLint is
= i
+ n
- halfFilterWidth
;
1206 const GLint js
= j
+ m
- halfFilterHeight
;
1207 if (is
< 0 || is
>= srcWidth
||
1208 js
< 0 || js
>= srcHeight
) {
1209 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1210 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1211 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1212 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1215 GLint k
= js
* srcWidth
+ is
;
1216 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1217 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1218 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1219 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1224 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1225 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1226 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1227 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1234 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1235 const GLfloat src
[][4],
1236 GLint filterWidth
, GLint filterHeight
,
1237 const GLfloat rowFilt
[][4],
1238 const GLfloat colFilt
[][4],
1241 const GLint halfFilterWidth
= filterWidth
/ 2;
1242 const GLint halfFilterHeight
= filterHeight
/ 2;
1245 for (j
= 0; j
< srcHeight
; j
++) {
1246 for (i
= 0; i
< srcWidth
; i
++) {
1251 for (m
= 0; m
< filterHeight
; m
++) {
1252 for (n
= 0; n
< filterWidth
; n
++) {
1253 GLint is
= i
+ n
- halfFilterWidth
;
1254 GLint js
= j
+ m
- halfFilterHeight
;
1258 else if (is
>= srcWidth
)
1262 else if (js
>= srcHeight
)
1264 k
= js
* srcWidth
+ is
;
1265 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1266 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1267 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1268 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1271 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1272 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1273 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1274 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1282 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1283 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1285 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1287 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1288 ctx
->Convolution1D
.Width
,
1289 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1290 (GLfloat (*)[4]) dstImage
);
1291 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1293 case GL_CONSTANT_BORDER
:
1294 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1295 ctx
->Convolution1D
.Width
,
1296 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1297 (GLfloat (*)[4]) dstImage
,
1298 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1300 case GL_REPLICATE_BORDER
:
1301 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1302 ctx
->Convolution1D
.Width
,
1303 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1304 (GLfloat (*)[4]) dstImage
);
1313 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1314 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1316 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1318 convolve_2d_reduce(*width
, *height
,
1319 (const GLfloat (*)[4]) srcImage
,
1320 ctx
->Convolution2D
.Width
,
1321 ctx
->Convolution2D
.Height
,
1322 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1323 (GLfloat (*)[4]) dstImage
);
1324 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1325 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1327 case GL_CONSTANT_BORDER
:
1328 convolve_2d_constant(*width
, *height
,
1329 (const GLfloat (*)[4]) srcImage
,
1330 ctx
->Convolution2D
.Width
,
1331 ctx
->Convolution2D
.Height
,
1332 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1333 (GLfloat (*)[4]) dstImage
,
1334 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1336 case GL_REPLICATE_BORDER
:
1337 convolve_2d_replicate(*width
, *height
,
1338 (const GLfloat (*)[4]) srcImage
,
1339 ctx
->Convolution2D
.Width
,
1340 ctx
->Convolution2D
.Height
,
1341 (const GLfloat (*)[4])ctx
->Convolution2D
.Filter
,
1342 (GLfloat (*)[4]) dstImage
);
1351 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1352 GLsizei
*width
, GLsizei
*height
,
1353 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1355 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1356 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1358 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1360 convolve_sep_reduce(*width
, *height
,
1361 (const GLfloat (*)[4]) srcImage
,
1362 ctx
->Separable2D
.Width
,
1363 ctx
->Separable2D
.Height
,
1364 (const GLfloat (*)[4]) rowFilter
,
1365 (const GLfloat (*)[4]) colFilter
,
1366 (GLfloat (*)[4]) dstImage
);
1367 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1368 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1370 case GL_CONSTANT_BORDER
:
1371 convolve_sep_constant(*width
, *height
,
1372 (const GLfloat (*)[4]) srcImage
,
1373 ctx
->Separable2D
.Width
,
1374 ctx
->Separable2D
.Height
,
1375 (const GLfloat (*)[4]) rowFilter
,
1376 (const GLfloat (*)[4]) colFilter
,
1377 (GLfloat (*)[4]) dstImage
,
1378 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1380 case GL_REPLICATE_BORDER
:
1381 convolve_sep_replicate(*width
, *height
,
1382 (const GLfloat (*)[4]) srcImage
,
1383 ctx
->Separable2D
.Width
,
1384 ctx
->Separable2D
.Height
,
1385 (const GLfloat (*)[4]) rowFilter
,
1386 (const GLfloat (*)[4]) colFilter
,
1387 (GLfloat (*)[4]) dstImage
);
1397 * This function computes an image's size after convolution.
1398 * If the convolution border mode is GL_REDUCE, the post-convolution
1399 * image will be smaller than the original.
1402 _mesa_adjust_image_for_convolution(const GLcontext
*ctx
, GLuint dimensions
,
1403 GLsizei
*width
, GLsizei
*height
)
1405 if (ctx
->Pixel
.Convolution1DEnabled
1407 && ctx
->Pixel
.ConvolutionBorderMode
[0] == GL_REDUCE
) {
1408 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1410 else if (ctx
->Pixel
.Convolution2DEnabled
1412 && ctx
->Pixel
.ConvolutionBorderMode
[1] == GL_REDUCE
) {
1413 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1414 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1416 else if (ctx
->Pixel
.Separable2DEnabled
1418 && ctx
->Pixel
.ConvolutionBorderMode
[2] == GL_REDUCE
) {
1419 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1420 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);