2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Image convolution functions.
29 * Notes: filter kernel elements are indexed by <n> and <m> as in
44 * Given an internalFormat token passed to glConvolutionFilter
45 * or glSeparableFilter, return the corresponding base format.
46 * Return -1 if invalid token.
49 base_filter_format( GLenum format
)
64 case GL_LUMINANCE_ALPHA
:
65 case GL_LUMINANCE4_ALPHA4
:
66 case GL_LUMINANCE6_ALPHA2
:
67 case GL_LUMINANCE8_ALPHA8
:
68 case GL_LUMINANCE12_ALPHA4
:
69 case GL_LUMINANCE12_ALPHA12
:
70 case GL_LUMINANCE16_ALPHA16
:
71 return GL_LUMINANCE_ALPHA
;
98 return -1; /* error */
104 _mesa_ConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*image
)
107 GET_CURRENT_CONTEXT(ctx
);
108 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
110 if (target
!= GL_CONVOLUTION_1D
) {
111 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
115 baseFormat
= base_filter_format(internalFormat
);
116 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
117 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
121 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
122 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
126 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
127 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter1D(format or type)");
131 if (format
== GL_COLOR_INDEX
||
132 format
== GL_STENCIL_INDEX
||
133 format
== GL_DEPTH_COMPONENT
||
134 format
== GL_INTENSITY
||
136 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(format or type)");
140 ctx
->Convolution1D
.Format
= format
;
141 ctx
->Convolution1D
.InternalFormat
= internalFormat
;
142 ctx
->Convolution1D
.Width
= width
;
143 ctx
->Convolution1D
.Height
= 1;
145 /* unpack filter image */
146 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
,
147 ctx
->Convolution1D
.Filter
,
148 format
, type
, image
, &ctx
->Unpack
,
149 0); /* transferOps */
151 /* apply scale and bias */
153 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[0];
154 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[0];
156 for (i
= 0; i
< width
; i
++) {
157 GLfloat r
= ctx
->Convolution1D
.Filter
[i
* 4 + 0];
158 GLfloat g
= ctx
->Convolution1D
.Filter
[i
* 4 + 1];
159 GLfloat b
= ctx
->Convolution1D
.Filter
[i
* 4 + 2];
160 GLfloat a
= ctx
->Convolution1D
.Filter
[i
* 4 + 3];
161 r
= r
* scale
[0] + bias
[0];
162 g
= g
* scale
[1] + bias
[1];
163 b
= b
* scale
[2] + bias
[2];
164 a
= a
* scale
[3] + bias
[3];
165 ctx
->Convolution1D
.Filter
[i
* 4 + 0] = r
;
166 ctx
->Convolution1D
.Filter
[i
* 4 + 1] = g
;
167 ctx
->Convolution1D
.Filter
[i
* 4 + 2] = b
;
168 ctx
->Convolution1D
.Filter
[i
* 4 + 3] = a
;
172 ctx
->NewState
|= _NEW_PIXEL
;
177 _mesa_ConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*image
)
181 GET_CURRENT_CONTEXT(ctx
);
182 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
184 if (target
!= GL_CONVOLUTION_2D
) {
185 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
189 baseFormat
= base_filter_format(internalFormat
);
190 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
191 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
195 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
196 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
199 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
200 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
204 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
205 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter2D(format or type)");
208 if (format
== GL_COLOR_INDEX
||
209 format
== GL_STENCIL_INDEX
||
210 format
== GL_DEPTH_COMPONENT
||
211 format
== GL_INTENSITY
||
213 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
217 /* this should have been caught earlier */
218 assert(_mesa_components_in_format(format
));
220 ctx
->Convolution2D
.Format
= format
;
221 ctx
->Convolution2D
.InternalFormat
= internalFormat
;
222 ctx
->Convolution2D
.Width
= width
;
223 ctx
->Convolution2D
.Height
= height
;
225 /* Unpack filter image. We always store filters in RGBA format. */
226 for (i
= 0; i
< height
; i
++) {
227 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
, image
, width
,
228 height
, format
, type
, 0, i
, 0);
229 GLfloat
*dst
= ctx
->Convolution2D
.Filter
+ i
* width
* 4;
230 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, dst
,
231 format
, type
, src
, &ctx
->Unpack
,
232 0); /* transferOps */
235 /* apply scale and bias */
237 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[1];
238 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[1];
239 for (i
= 0; i
< width
* height
; i
++) {
240 GLfloat r
= ctx
->Convolution2D
.Filter
[i
* 4 + 0];
241 GLfloat g
= ctx
->Convolution2D
.Filter
[i
* 4 + 1];
242 GLfloat b
= ctx
->Convolution2D
.Filter
[i
* 4 + 2];
243 GLfloat a
= ctx
->Convolution2D
.Filter
[i
* 4 + 3];
244 r
= r
* scale
[0] + bias
[0];
245 g
= g
* scale
[1] + bias
[1];
246 b
= b
* scale
[2] + bias
[2];
247 a
= a
* scale
[3] + bias
[3];
248 ctx
->Convolution2D
.Filter
[i
* 4 + 0] = r
;
249 ctx
->Convolution2D
.Filter
[i
* 4 + 1] = g
;
250 ctx
->Convolution2D
.Filter
[i
* 4 + 2] = b
;
251 ctx
->Convolution2D
.Filter
[i
* 4 + 3] = a
;
255 ctx
->NewState
|= _NEW_PIXEL
;
260 _mesa_ConvolutionParameterf(GLenum target
, GLenum pname
, GLfloat param
)
262 GET_CURRENT_CONTEXT(ctx
);
264 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
267 case GL_CONVOLUTION_1D
:
270 case GL_CONVOLUTION_2D
:
273 case GL_SEPARABLE_2D
:
277 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
282 case GL_CONVOLUTION_BORDER_MODE
:
283 if (param
== (GLfloat
) GL_REDUCE
||
284 param
== (GLfloat
) GL_CONSTANT_BORDER
||
285 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
286 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
289 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
294 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
298 ctx
->NewState
|= _NEW_PIXEL
;
303 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
305 GET_CURRENT_CONTEXT(ctx
);
307 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
310 case GL_CONVOLUTION_1D
:
313 case GL_CONVOLUTION_2D
:
316 case GL_SEPARABLE_2D
:
320 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
325 case GL_CONVOLUTION_BORDER_COLOR
:
326 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
328 case GL_CONVOLUTION_BORDER_MODE
:
329 if (params
[0] == (GLfloat
) GL_REDUCE
||
330 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
331 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
332 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
335 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
339 case GL_CONVOLUTION_FILTER_SCALE
:
340 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
342 case GL_CONVOLUTION_FILTER_BIAS
:
343 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
346 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
350 ctx
->NewState
|= _NEW_PIXEL
;
355 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
357 GET_CURRENT_CONTEXT(ctx
);
359 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
362 case GL_CONVOLUTION_1D
:
365 case GL_CONVOLUTION_2D
:
368 case GL_SEPARABLE_2D
:
372 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
377 case GL_CONVOLUTION_BORDER_MODE
:
378 if (param
== (GLint
) GL_REDUCE
||
379 param
== (GLint
) GL_CONSTANT_BORDER
||
380 param
== (GLint
) GL_REPLICATE_BORDER
) {
381 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
384 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
389 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
393 ctx
->NewState
|= _NEW_PIXEL
;
398 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
400 GET_CURRENT_CONTEXT(ctx
);
402 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
405 case GL_CONVOLUTION_1D
:
408 case GL_CONVOLUTION_2D
:
411 case GL_SEPARABLE_2D
:
415 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
420 case GL_CONVOLUTION_BORDER_COLOR
:
421 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
422 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
423 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
424 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
426 case GL_CONVOLUTION_BORDER_MODE
:
427 if (params
[0] == (GLint
) GL_REDUCE
||
428 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
429 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
430 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
433 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
437 case GL_CONVOLUTION_FILTER_SCALE
:
438 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
439 /* need cast to prevent compiler warnings */
440 ctx
->Pixel
.ConvolutionFilterScale
[c
][0] = (GLfloat
) params
[0];
441 ctx
->Pixel
.ConvolutionFilterScale
[c
][1] = (GLfloat
) params
[1];
442 ctx
->Pixel
.ConvolutionFilterScale
[c
][2] = (GLfloat
) params
[2];
443 ctx
->Pixel
.ConvolutionFilterScale
[c
][3] = (GLfloat
) params
[3];
445 case GL_CONVOLUTION_FILTER_BIAS
:
446 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
447 /* need cast to prevent compiler warnings */
448 ctx
->Pixel
.ConvolutionFilterBias
[c
][0] = (GLfloat
) params
[0];
449 ctx
->Pixel
.ConvolutionFilterBias
[c
][1] = (GLfloat
) params
[1];
450 ctx
->Pixel
.ConvolutionFilterBias
[c
][2] = (GLfloat
) params
[2];
451 ctx
->Pixel
.ConvolutionFilterBias
[c
][3] = (GLfloat
) params
[3];
454 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
458 ctx
->NewState
|= _NEW_PIXEL
;
463 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
466 GET_CURRENT_CONTEXT(ctx
);
467 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
469 if (target
!= GL_CONVOLUTION_1D
) {
470 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
474 baseFormat
= base_filter_format(internalFormat
);
475 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
476 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
480 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
481 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
485 ctx
->Driver
.CopyConvolutionFilter1D( ctx
, target
,
486 internalFormat
, x
, y
, width
);
491 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
494 GET_CURRENT_CONTEXT(ctx
);
495 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
497 if (target
!= GL_CONVOLUTION_2D
) {
498 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
502 baseFormat
= base_filter_format(internalFormat
);
503 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
504 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
508 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
509 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
512 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
513 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
517 ctx
->Driver
.CopyConvolutionFilter2D( ctx
, target
, internalFormat
, x
, y
,
524 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
526 const struct gl_convolution_attrib
*filter
;
528 GET_CURRENT_CONTEXT(ctx
);
529 ASSERT_OUTSIDE_BEGIN_END(ctx
);
532 _mesa_update_state(ctx
);
535 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
536 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
540 if (format
== GL_COLOR_INDEX
||
541 format
== GL_STENCIL_INDEX
||
542 format
== GL_DEPTH_COMPONENT
||
543 format
== GL_INTENSITY
||
545 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
550 case GL_CONVOLUTION_1D
:
551 filter
= &(ctx
->Convolution1D
);
553 case GL_CONVOLUTION_2D
:
554 filter
= &(ctx
->Convolution2D
);
557 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
561 for (row
= 0; row
< filter
->Height
; row
++) {
562 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
563 filter
->Height
, format
, type
,
565 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
566 _mesa_pack_rgba_span_float(ctx
, filter
->Width
,
567 (const GLfloat (*)[4]) src
,
568 format
, type
, dst
, &ctx
->Pack
, 0);
574 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
576 GET_CURRENT_CONTEXT(ctx
);
577 const struct gl_convolution_attrib
*conv
;
579 ASSERT_OUTSIDE_BEGIN_END(ctx
);
582 case GL_CONVOLUTION_1D
:
584 conv
= &ctx
->Convolution1D
;
586 case GL_CONVOLUTION_2D
:
588 conv
= &ctx
->Convolution2D
;
590 case GL_SEPARABLE_2D
:
592 conv
= &ctx
->Separable2D
;
595 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
600 case GL_CONVOLUTION_BORDER_COLOR
:
601 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
603 case GL_CONVOLUTION_BORDER_MODE
:
604 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
606 case GL_CONVOLUTION_FILTER_SCALE
:
607 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
609 case GL_CONVOLUTION_FILTER_BIAS
:
610 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
612 case GL_CONVOLUTION_FORMAT
:
613 *params
= (GLfloat
) conv
->Format
;
615 case GL_CONVOLUTION_WIDTH
:
616 *params
= (GLfloat
) conv
->Width
;
618 case GL_CONVOLUTION_HEIGHT
:
619 *params
= (GLfloat
) conv
->Height
;
621 case GL_MAX_CONVOLUTION_WIDTH
:
622 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
624 case GL_MAX_CONVOLUTION_HEIGHT
:
625 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
628 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
635 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
637 GET_CURRENT_CONTEXT(ctx
);
638 const struct gl_convolution_attrib
*conv
;
640 ASSERT_OUTSIDE_BEGIN_END(ctx
);
643 case GL_CONVOLUTION_1D
:
645 conv
= &ctx
->Convolution1D
;
647 case GL_CONVOLUTION_2D
:
649 conv
= &ctx
->Convolution2D
;
651 case GL_SEPARABLE_2D
:
653 conv
= &ctx
->Separable2D
;
656 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
661 case GL_CONVOLUTION_BORDER_COLOR
:
662 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
663 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
664 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
665 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
667 case GL_CONVOLUTION_BORDER_MODE
:
668 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
670 case GL_CONVOLUTION_FILTER_SCALE
:
671 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
672 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
673 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
674 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
676 case GL_CONVOLUTION_FILTER_BIAS
:
677 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
678 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
679 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
680 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
682 case GL_CONVOLUTION_FORMAT
:
683 *params
= (GLint
) conv
->Format
;
685 case GL_CONVOLUTION_WIDTH
:
686 *params
= (GLint
) conv
->Width
;
688 case GL_CONVOLUTION_HEIGHT
:
689 *params
= (GLint
) conv
->Height
;
691 case GL_MAX_CONVOLUTION_WIDTH
:
692 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
694 case GL_MAX_CONVOLUTION_HEIGHT
:
695 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
698 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
705 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
707 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
708 const struct gl_convolution_attrib
*filter
;
709 GET_CURRENT_CONTEXT(ctx
);
710 ASSERT_OUTSIDE_BEGIN_END(ctx
);
713 _mesa_update_state(ctx
);
716 if (target
!= GL_SEPARABLE_2D
) {
717 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
721 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
722 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
726 if (format
== GL_COLOR_INDEX
||
727 format
== GL_STENCIL_INDEX
||
728 format
== GL_DEPTH_COMPONENT
||
729 format
== GL_INTENSITY
||
731 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
735 filter
= &ctx
->Separable2D
;
739 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
740 filter
->Height
, format
, type
,
742 _mesa_pack_rgba_span_float(ctx
, filter
->Width
,
743 (const GLfloat (*)[4]) filter
->Filter
,
744 format
, type
, dst
, &ctx
->Pack
, 0);
749 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
752 const GLfloat
*src
= filter
->Filter
+ colStart
;
753 _mesa_pack_rgba_span_float(ctx
, filter
->Height
,
754 (const GLfloat (*)[4]) src
,
755 format
, type
, dst
, &ctx
->Pack
, 0);
758 (void) span
; /* unused at this time */
763 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
765 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
767 GET_CURRENT_CONTEXT(ctx
);
768 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
770 if (target
!= GL_SEPARABLE_2D
) {
771 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
775 baseFormat
= base_filter_format(internalFormat
);
776 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
777 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
781 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
782 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
785 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
786 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
790 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
791 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
795 if (format
== GL_COLOR_INDEX
||
796 format
== GL_STENCIL_INDEX
||
797 format
== GL_DEPTH_COMPONENT
||
798 format
== GL_INTENSITY
||
800 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
804 ctx
->Separable2D
.Format
= format
;
805 ctx
->Separable2D
.InternalFormat
= internalFormat
;
806 ctx
->Separable2D
.Width
= width
;
807 ctx
->Separable2D
.Height
= height
;
809 /* unpack row filter */
810 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
,
811 ctx
->Separable2D
.Filter
,
812 format
, type
, row
, &ctx
->Unpack
,
813 0); /* transferOps */
815 /* apply scale and bias */
817 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
818 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
820 for (i
= 0; i
< width
; i
++) {
821 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0];
822 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
823 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
824 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
825 r
= r
* scale
[0] + bias
[0];
826 g
= g
* scale
[1] + bias
[1];
827 b
= b
* scale
[2] + bias
[2];
828 a
= a
* scale
[3] + bias
[3];
829 ctx
->Separable2D
.Filter
[i
* 4 + 0] = r
;
830 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
831 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
832 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
836 /* unpack column filter */
837 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
,
838 &ctx
->Separable2D
.Filter
[colStart
],
839 format
, type
, column
, &ctx
->Unpack
,
840 0); /* transferOps */
842 /* apply scale and bias */
844 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
845 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
847 for (i
= 0; i
< width
; i
++) {
848 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
849 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
850 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
851 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
852 r
= r
* scale
[0] + bias
[0];
853 g
= g
* scale
[1] + bias
[1];
854 b
= b
* scale
[2] + bias
[2];
855 a
= a
* scale
[3] + bias
[3];
856 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
857 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
858 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
859 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
863 ctx
->NewState
|= _NEW_PIXEL
;
867 /**********************************************************************/
868 /*** image convolution functions ***/
869 /**********************************************************************/
872 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
873 GLint filterWidth
, const GLfloat filter
[][4],
879 if (filterWidth
>= 1)
880 dstWidth
= srcWidth
- (filterWidth
- 1);
885 return; /* null result */
887 for (i
= 0; i
< dstWidth
; i
++) {
892 for (n
= 0; n
< filterWidth
; n
++) {
893 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
894 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
895 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
896 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
898 dest
[i
][RCOMP
] = sumR
;
899 dest
[i
][GCOMP
] = sumG
;
900 dest
[i
][BCOMP
] = sumB
;
901 dest
[i
][ACOMP
] = sumA
;
907 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
908 GLint filterWidth
, const GLfloat filter
[][4],
910 const GLfloat borderColor
[4])
912 const GLint halfFilterWidth
= filterWidth
/ 2;
915 for (i
= 0; i
< srcWidth
; i
++) {
920 for (n
= 0; n
< filterWidth
; n
++) {
921 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
922 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
923 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
924 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
925 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
928 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
929 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
930 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
931 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
934 dest
[i
][RCOMP
] = sumR
;
935 dest
[i
][GCOMP
] = sumG
;
936 dest
[i
][BCOMP
] = sumB
;
937 dest
[i
][ACOMP
] = sumA
;
943 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
944 GLint filterWidth
, const GLfloat filter
[][4],
947 const GLint halfFilterWidth
= filterWidth
/ 2;
950 for (i
= 0; i
< srcWidth
; i
++) {
955 for (n
= 0; n
< filterWidth
; n
++) {
956 if (i
+ n
< halfFilterWidth
) {
957 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
958 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
959 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
960 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
962 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
963 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
964 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
965 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
966 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
969 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
970 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
971 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
972 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
975 dest
[i
][RCOMP
] = sumR
;
976 dest
[i
][GCOMP
] = sumG
;
977 dest
[i
][BCOMP
] = sumB
;
978 dest
[i
][ACOMP
] = sumA
;
984 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
985 const GLfloat src
[][4],
986 GLint filterWidth
, GLint filterHeight
,
987 const GLfloat filter
[][4],
990 GLint dstWidth
, dstHeight
;
993 if (filterWidth
>= 1)
994 dstWidth
= srcWidth
- (filterWidth
- 1);
998 if (filterHeight
>= 1)
999 dstHeight
= srcHeight
- (filterHeight
- 1);
1001 dstHeight
= srcHeight
;
1003 if (dstWidth
<= 0 || dstHeight
<= 0)
1006 for (j
= 0; j
< dstHeight
; j
++) {
1007 for (i
= 0; i
< dstWidth
; i
++) {
1012 for (m
= 0; m
< filterHeight
; m
++) {
1013 for (n
= 0; n
< filterWidth
; n
++) {
1014 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1015 const GLint f
= m
* filterWidth
+ n
;
1016 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1017 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1018 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1019 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1022 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1023 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1024 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1025 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1032 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1033 const GLfloat src
[][4],
1034 GLint filterWidth
, GLint filterHeight
,
1035 const GLfloat filter
[][4],
1037 const GLfloat borderColor
[4])
1039 const GLint halfFilterWidth
= filterWidth
/ 2;
1040 const GLint halfFilterHeight
= filterHeight
/ 2;
1043 for (j
= 0; j
< srcHeight
; j
++) {
1044 for (i
= 0; i
< srcWidth
; i
++) {
1049 for (m
= 0; m
< filterHeight
; m
++) {
1050 for (n
= 0; n
< filterWidth
; n
++) {
1051 const GLint f
= m
* filterWidth
+ n
;
1052 const GLint is
= i
+ n
- halfFilterWidth
;
1053 const GLint js
= j
+ m
- halfFilterHeight
;
1054 if (is
< 0 || is
>= srcWidth
||
1055 js
< 0 || js
>= srcHeight
) {
1056 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1057 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1058 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1059 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1062 const GLint k
= js
* srcWidth
+ is
;
1063 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1064 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1065 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1066 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1070 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1071 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1072 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1073 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1080 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1081 const GLfloat src
[][4],
1082 GLint filterWidth
, GLint filterHeight
,
1083 const GLfloat filter
[][4],
1086 const GLint halfFilterWidth
= filterWidth
/ 2;
1087 const GLint halfFilterHeight
= filterHeight
/ 2;
1090 for (j
= 0; j
< srcHeight
; j
++) {
1091 for (i
= 0; i
< srcWidth
; i
++) {
1096 for (m
= 0; m
< filterHeight
; m
++) {
1097 for (n
= 0; n
< filterWidth
; n
++) {
1098 const GLint f
= m
* filterWidth
+ n
;
1099 GLint is
= i
+ n
- halfFilterWidth
;
1100 GLint js
= j
+ m
- halfFilterHeight
;
1104 else if (is
>= srcWidth
)
1108 else if (js
>= srcHeight
)
1110 k
= js
* srcWidth
+ is
;
1111 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1112 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1113 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1114 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1117 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1118 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1119 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1120 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1127 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1128 const GLfloat src
[][4],
1129 GLint filterWidth
, GLint filterHeight
,
1130 const GLfloat rowFilt
[][4],
1131 const GLfloat colFilt
[][4],
1134 GLint dstWidth
, dstHeight
;
1137 if (filterWidth
>= 1)
1138 dstWidth
= srcWidth
- (filterWidth
- 1);
1140 dstWidth
= srcWidth
;
1142 if (filterHeight
>= 1)
1143 dstHeight
= srcHeight
- (filterHeight
- 1);
1145 dstHeight
= srcHeight
;
1147 if (dstWidth
<= 0 || dstHeight
<= 0)
1150 for (j
= 0; j
< dstHeight
; j
++) {
1151 for (i
= 0; i
< dstWidth
; i
++) {
1156 for (m
= 0; m
< filterHeight
; m
++) {
1157 for (n
= 0; n
< filterWidth
; n
++) {
1158 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1159 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1160 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1161 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1162 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1165 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1166 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1167 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1168 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1175 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1176 const GLfloat src
[][4],
1177 GLint filterWidth
, GLint filterHeight
,
1178 const GLfloat rowFilt
[][4],
1179 const GLfloat colFilt
[][4],
1181 const GLfloat borderColor
[4])
1183 const GLint halfFilterWidth
= filterWidth
/ 2;
1184 const GLint halfFilterHeight
= filterHeight
/ 2;
1187 for (j
= 0; j
< srcHeight
; j
++) {
1188 for (i
= 0; i
< srcWidth
; i
++) {
1193 for (m
= 0; m
< filterHeight
; m
++) {
1194 for (n
= 0; n
< filterWidth
; n
++) {
1195 const GLint is
= i
+ n
- halfFilterWidth
;
1196 const GLint js
= j
+ m
- halfFilterHeight
;
1197 if (is
< 0 || is
>= srcWidth
||
1198 js
< 0 || js
>= srcHeight
) {
1199 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1200 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1201 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1202 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1205 GLint k
= js
* srcWidth
+ is
;
1206 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1207 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1208 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1209 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1214 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1215 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1216 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1217 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1224 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1225 const GLfloat src
[][4],
1226 GLint filterWidth
, GLint filterHeight
,
1227 const GLfloat rowFilt
[][4],
1228 const GLfloat colFilt
[][4],
1231 const GLint halfFilterWidth
= filterWidth
/ 2;
1232 const GLint halfFilterHeight
= filterHeight
/ 2;
1235 for (j
= 0; j
< srcHeight
; j
++) {
1236 for (i
= 0; i
< srcWidth
; i
++) {
1241 for (m
= 0; m
< filterHeight
; m
++) {
1242 for (n
= 0; n
< filterWidth
; n
++) {
1243 GLint is
= i
+ n
- halfFilterWidth
;
1244 GLint js
= j
+ m
- halfFilterHeight
;
1248 else if (is
>= srcWidth
)
1252 else if (js
>= srcHeight
)
1254 k
= js
* srcWidth
+ is
;
1255 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1256 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1257 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1258 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1261 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1262 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1263 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1264 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1272 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1273 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1275 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1277 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1278 ctx
->Convolution1D
.Width
,
1279 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1280 (GLfloat (*)[4]) dstImage
);
1281 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1283 case GL_CONSTANT_BORDER
:
1284 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1285 ctx
->Convolution1D
.Width
,
1286 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1287 (GLfloat (*)[4]) dstImage
,
1288 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1290 case GL_REPLICATE_BORDER
:
1291 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1292 ctx
->Convolution1D
.Width
,
1293 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1294 (GLfloat (*)[4]) dstImage
);
1303 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1304 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1306 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1308 convolve_2d_reduce(*width
, *height
,
1309 (const GLfloat (*)[4]) srcImage
,
1310 ctx
->Convolution2D
.Width
,
1311 ctx
->Convolution2D
.Height
,
1312 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1313 (GLfloat (*)[4]) dstImage
);
1314 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1315 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1317 case GL_CONSTANT_BORDER
:
1318 convolve_2d_constant(*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 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1326 case GL_REPLICATE_BORDER
:
1327 convolve_2d_replicate(*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
);
1341 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1342 GLsizei
*width
, GLsizei
*height
,
1343 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1345 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1346 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1348 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1350 convolve_sep_reduce(*width
, *height
,
1351 (const GLfloat (*)[4]) srcImage
,
1352 ctx
->Separable2D
.Width
,
1353 ctx
->Separable2D
.Height
,
1354 (const GLfloat (*)[4]) rowFilter
,
1355 (const GLfloat (*)[4]) colFilter
,
1356 (GLfloat (*)[4]) dstImage
);
1357 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1358 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1360 case GL_CONSTANT_BORDER
:
1361 convolve_sep_constant(*width
, *height
,
1362 (const GLfloat (*)[4]) srcImage
,
1363 ctx
->Separable2D
.Width
,
1364 ctx
->Separable2D
.Height
,
1365 (const GLfloat (*)[4]) rowFilter
,
1366 (const GLfloat (*)[4]) colFilter
,
1367 (GLfloat (*)[4]) dstImage
,
1368 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1370 case GL_REPLICATE_BORDER
:
1371 convolve_sep_replicate(*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
);
1387 * This function computes an image's size after convolution.
1388 * If the convolution border mode is GL_REDUCE, the post-convolution
1389 * image will be smaller than the original.
1392 _mesa_adjust_image_for_convolution(const GLcontext
*ctx
, GLuint dimensions
,
1393 GLsizei
*width
, GLsizei
*height
)
1395 if (ctx
->Pixel
.Convolution1DEnabled
1397 && ctx
->Pixel
.ConvolutionBorderMode
[0] == GL_REDUCE
) {
1398 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1400 else if (ctx
->Pixel
.Convolution2DEnabled
1402 && ctx
->Pixel
.ConvolutionBorderMode
[1] == GL_REDUCE
) {
1403 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1404 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1406 else if (ctx
->Pixel
.Separable2DEnabled
1408 && ctx
->Pixel
.ConvolutionBorderMode
[2] == GL_REDUCE
) {
1409 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1410 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);