1 /* $Id: convolve.c,v 1.15 2000/11/23 02:50:56 jtaylor Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * Image convolution functions.
31 * Notes: filter kernel elements are indexed by <n> and <m> as in
46 #include "swrast/s_span.h" /* XXX SWRAST hack */
51 * Given an internalFormat token passed to glConvolutionFilter
52 * or glSeparableFilter, return the corresponding base format.
53 * Return -1 if invalid token.
56 base_filter_format( GLenum format
)
71 case GL_LUMINANCE_ALPHA
:
72 case GL_LUMINANCE4_ALPHA4
:
73 case GL_LUMINANCE6_ALPHA2
:
74 case GL_LUMINANCE8_ALPHA8
:
75 case GL_LUMINANCE12_ALPHA4
:
76 case GL_LUMINANCE12_ALPHA12
:
77 case GL_LUMINANCE16_ALPHA16
:
78 return GL_LUMINANCE_ALPHA
;
105 return -1; /* error */
111 _mesa_ConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*image
)
114 GET_CURRENT_CONTEXT(ctx
);
115 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionFilter1D");
117 if (target
!= GL_CONVOLUTION_1D
) {
118 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
122 baseFormat
= base_filter_format(internalFormat
);
123 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
124 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
128 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
129 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
133 if (!_mesa_is_legal_format_and_type(format
, type
) ||
134 format
== GL_COLOR_INDEX
||
135 format
== GL_STENCIL_INDEX
||
136 format
== GL_DEPTH_COMPONENT
||
137 format
== GL_INTENSITY
||
139 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(format or type)");
143 ctx
->Convolution1D
.Format
= format
;
144 ctx
->Convolution1D
.InternalFormat
= internalFormat
;
145 ctx
->Convolution1D
.Width
= width
;
146 ctx
->Convolution1D
.Height
= 1;
148 /* unpack filter image */
149 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
150 ctx
->Convolution1D
.Filter
,
151 format
, type
, image
, &ctx
->Unpack
,
154 /* apply scale and bias */
156 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[0];
157 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[0];
159 for (i
= 0; i
< width
; i
++) {
160 GLfloat r
= ctx
->Convolution1D
.Filter
[i
* 4 + 0];
161 GLfloat g
= ctx
->Convolution1D
.Filter
[i
* 4 + 1];
162 GLfloat b
= ctx
->Convolution1D
.Filter
[i
* 4 + 2];
163 GLfloat a
= ctx
->Convolution1D
.Filter
[i
* 4 + 3];
164 r
= r
* scale
[0] + bias
[0];
165 g
= g
* scale
[1] + bias
[1];
166 b
= b
* scale
[2] + bias
[2];
167 a
= a
* scale
[3] + bias
[3];
168 ctx
->Convolution1D
.Filter
[i
* 4 + 0] = r
;
169 ctx
->Convolution1D
.Filter
[i
* 4 + 1] = g
;
170 ctx
->Convolution1D
.Filter
[i
* 4 + 2] = b
;
171 ctx
->Convolution1D
.Filter
[i
* 4 + 3] = a
;
175 ctx
->NewState
|= _NEW_PIXEL
;
180 _mesa_ConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*image
)
184 GET_CURRENT_CONTEXT(ctx
);
185 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionFilter2D");
187 if (target
!= GL_CONVOLUTION_2D
) {
188 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
192 baseFormat
= base_filter_format(internalFormat
);
193 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
194 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
198 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
199 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
202 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
203 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
207 if (!_mesa_is_legal_format_and_type(format
, type
) ||
208 format
== GL_COLOR_INDEX
||
209 format
== GL_STENCIL_INDEX
||
210 format
== GL_DEPTH_COMPONENT
||
211 format
== GL_INTENSITY
||
213 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
217 components
= _mesa_components_in_format(format
);
218 assert(components
> 0); /* this should have been caught earlier */
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_float_color_span(ctx
, width
, GL_RGBA
, dst
,
231 format
, type
, src
, &ctx
->Unpack
,
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
* 4; 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
);
265 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameterf");
268 case GL_CONVOLUTION_1D
:
271 case GL_CONVOLUTION_2D
:
274 case GL_SEPARABLE_2D
:
278 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
283 case GL_CONVOLUTION_BORDER_MODE
:
284 if (param
== (GLfloat
) GL_REDUCE
||
285 param
== (GLfloat
) GL_CONSTANT_BORDER
||
286 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
287 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
290 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
295 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
299 ctx
->NewState
|= _NEW_PIXEL
;
304 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
306 GET_CURRENT_CONTEXT(ctx
);
307 struct gl_convolution_attrib
*conv
;
310 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameterfv");
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 gl_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 gl_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 gl_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
);
366 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameteri");
369 case GL_CONVOLUTION_1D
:
372 case GL_CONVOLUTION_2D
:
375 case GL_SEPARABLE_2D
:
379 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
384 case GL_CONVOLUTION_BORDER_MODE
:
385 if (param
== (GLint
) GL_REDUCE
||
386 param
== (GLint
) GL_CONSTANT_BORDER
||
387 param
== (GLint
) GL_REPLICATE_BORDER
) {
388 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
391 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
396 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
400 ctx
->NewState
|= _NEW_PIXEL
;
405 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
407 GET_CURRENT_CONTEXT(ctx
);
408 struct gl_convolution_attrib
*conv
;
411 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameteriv");
414 case GL_CONVOLUTION_1D
:
416 conv
= &ctx
->Convolution1D
;
418 case GL_CONVOLUTION_2D
:
420 conv
= &ctx
->Convolution2D
;
422 case GL_SEPARABLE_2D
:
424 conv
= &ctx
->Separable2D
;
427 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
432 case GL_CONVOLUTION_BORDER_COLOR
:
433 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
434 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
435 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
436 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
438 case GL_CONVOLUTION_BORDER_MODE
:
439 if (params
[0] == (GLint
) GL_REDUCE
||
440 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
441 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
442 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
445 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
449 case GL_CONVOLUTION_FILTER_SCALE
:
450 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
452 case GL_CONVOLUTION_FILTER_BIAS
:
453 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
456 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
460 ctx
->NewState
|= _NEW_PIXEL
;
465 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
468 GLchan rgba
[MAX_CONVOLUTION_WIDTH
][4];
469 GET_CURRENT_CONTEXT(ctx
);
470 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyConvolutionFilter1D");
472 if (target
!= GL_CONVOLUTION_1D
) {
473 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
477 baseFormat
= base_filter_format(internalFormat
);
478 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
479 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
483 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
484 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
488 /* read pixels from framebuffer */
490 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
, (GLchan (*)[4]) rgba
);
493 /* store as convolution filter */
494 _mesa_ConvolutionFilter1D(target
, internalFormat
, width
,
495 GL_RGBA
, CHAN_TYPE
, rgba
);
500 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
504 struct gl_pixelstore_attrib packSave
;
505 GLchan rgba
[MAX_CONVOLUTION_HEIGHT
][MAX_CONVOLUTION_WIDTH
][4];
506 GET_CURRENT_CONTEXT(ctx
);
507 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyConvolutionFilter2D");
509 if (target
!= GL_CONVOLUTION_2D
) {
510 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
514 baseFormat
= base_filter_format(internalFormat
);
515 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
516 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
520 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
521 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
524 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
525 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
529 /* read pixels from framebuffer */
531 for (i
= 0; i
< height
; i
++) {
532 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
533 (GLchan (*)[4]) rgba
[i
]);
538 * store as convolution filter
540 packSave
= ctx
->Unpack
; /* save pixel packing params */
542 ctx
->Unpack
.Alignment
= 1;
543 ctx
->Unpack
.RowLength
= MAX_CONVOLUTION_WIDTH
;
544 ctx
->Unpack
.SkipPixels
= 0;
545 ctx
->Unpack
.SkipRows
= 0;
546 ctx
->Unpack
.ImageHeight
= 0;
547 ctx
->Unpack
.SkipImages
= 0;
548 ctx
->Unpack
.SwapBytes
= GL_FALSE
;
549 ctx
->Unpack
.LsbFirst
= GL_FALSE
;
550 ctx
->NewState
|= _NEW_PACKUNPACK
;
552 _mesa_ConvolutionFilter2D(target
, internalFormat
, width
, height
,
553 GL_RGBA
, CHAN_TYPE
, rgba
);
555 ctx
->Unpack
= packSave
; /* restore pixel packing params */
556 ctx
->NewState
|= _NEW_PACKUNPACK
;
561 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
563 const struct gl_convolution_attrib
*filter
;
565 GET_CURRENT_CONTEXT(ctx
);
566 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionFilter");
569 gl_update_state(ctx
);
572 if (!_mesa_is_legal_format_and_type(format
, type
) ||
573 format
== GL_COLOR_INDEX
||
574 format
== GL_STENCIL_INDEX
||
575 format
== GL_DEPTH_COMPONENT
||
576 format
== GL_INTENSITY
||
578 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
583 case GL_CONVOLUTION_1D
:
584 filter
= &(ctx
->Convolution1D
);
586 case GL_CONVOLUTION_2D
:
587 filter
= &(ctx
->Convolution2D
);
590 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
594 for (row
= 0; row
< filter
->Height
; row
++) {
595 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
596 filter
->Height
, format
, type
,
598 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
599 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
600 (const GLfloat (*)[4]) src
,
601 format
, type
, dst
, &ctx
->Pack
, 0);
607 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
609 GET_CURRENT_CONTEXT(ctx
);
610 const struct gl_convolution_attrib
*conv
;
613 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionParameterfv");
616 case GL_CONVOLUTION_1D
:
618 conv
= &ctx
->Convolution1D
;
620 case GL_CONVOLUTION_2D
:
622 conv
= &ctx
->Convolution2D
;
624 case GL_SEPARABLE_2D
:
626 conv
= &ctx
->Separable2D
;
629 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
634 case GL_CONVOLUTION_BORDER_COLOR
:
635 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
637 case GL_CONVOLUTION_BORDER_MODE
:
638 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
640 case GL_CONVOLUTION_FILTER_SCALE
:
641 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
643 case GL_CONVOLUTION_FILTER_BIAS
:
644 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
646 case GL_CONVOLUTION_FORMAT
:
647 *params
= (GLfloat
) conv
->Format
;
649 case GL_CONVOLUTION_WIDTH
:
650 *params
= (GLfloat
) conv
->Width
;
652 case GL_CONVOLUTION_HEIGHT
:
653 *params
= (GLfloat
) conv
->Height
;
655 case GL_MAX_CONVOLUTION_WIDTH
:
656 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
658 case GL_MAX_CONVOLUTION_HEIGHT
:
659 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
662 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
669 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
671 GET_CURRENT_CONTEXT(ctx
);
672 const struct gl_convolution_attrib
*conv
;
675 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionParameteriv");
678 case GL_CONVOLUTION_1D
:
680 conv
= &ctx
->Convolution1D
;
682 case GL_CONVOLUTION_2D
:
684 conv
= &ctx
->Convolution2D
;
686 case GL_SEPARABLE_2D
:
688 conv
= &ctx
->Separable2D
;
691 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
696 case GL_CONVOLUTION_BORDER_COLOR
:
697 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
698 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
699 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
700 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
702 case GL_CONVOLUTION_BORDER_MODE
:
703 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
705 case GL_CONVOLUTION_FILTER_SCALE
:
706 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
707 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
708 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
709 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
711 case GL_CONVOLUTION_FILTER_BIAS
:
712 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
713 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
714 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
715 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
717 case GL_CONVOLUTION_FORMAT
:
718 *params
= (GLint
) conv
->Format
;
720 case GL_CONVOLUTION_WIDTH
:
721 *params
= (GLint
) conv
->Width
;
723 case GL_CONVOLUTION_HEIGHT
:
724 *params
= (GLint
) conv
->Height
;
726 case GL_MAX_CONVOLUTION_WIDTH
:
727 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
729 case GL_MAX_CONVOLUTION_HEIGHT
:
730 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
733 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
740 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
742 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
743 const struct gl_convolution_attrib
*filter
;
744 GET_CURRENT_CONTEXT(ctx
);
745 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetSeparableFilter");
748 gl_update_state(ctx
);
751 if (target
!= GL_SEPARABLE_2D
) {
752 gl_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
756 if (!_mesa_is_legal_format_and_type(format
, type
) ||
757 format
== GL_COLOR_INDEX
||
758 format
== GL_STENCIL_INDEX
||
759 format
== GL_DEPTH_COMPONENT
||
760 format
== GL_INTENSITY
||
762 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
766 filter
= &ctx
->Separable2D
;
770 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
771 filter
->Height
, format
, type
,
773 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
774 (const GLfloat (*)[4]) filter
->Filter
,
775 format
, type
, dst
, &ctx
->Pack
, 0);
780 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
783 const GLfloat
*src
= filter
->Filter
+ colStart
;
784 _mesa_pack_float_rgba_span(ctx
, filter
->Height
,
785 (const GLfloat (*)[4]) src
,
786 format
, type
, dst
, &ctx
->Pack
, 0);
789 (void) span
; /* unused at this time */
794 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
796 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
798 GET_CURRENT_CONTEXT(ctx
);
799 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glSeparableFilter2D");
801 if (target
!= GL_SEPARABLE_2D
) {
802 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
806 baseFormat
= base_filter_format(internalFormat
);
807 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
808 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
812 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
813 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
816 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
817 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
821 if (!_mesa_is_legal_format_and_type(format
, type
) ||
822 format
== GL_COLOR_INDEX
||
823 format
== GL_STENCIL_INDEX
||
824 format
== GL_DEPTH_COMPONENT
||
825 format
== GL_INTENSITY
||
827 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
831 ctx
->Separable2D
.Format
= format
;
832 ctx
->Separable2D
.InternalFormat
= internalFormat
;
833 ctx
->Separable2D
.Width
= width
;
834 ctx
->Separable2D
.Height
= height
;
836 /* unpack row filter */
837 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
838 ctx
->Separable2D
.Filter
,
839 format
, type
, row
, &ctx
->Unpack
,
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];
849 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
850 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
851 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
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] = r
;
857 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
858 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
859 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
863 /* unpack column filter */
864 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
865 &ctx
->Separable2D
.Filter
[colStart
],
866 format
, type
, column
, &ctx
->Unpack
,
869 /* apply scale and bias */
871 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
872 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
874 for (i
= 0; i
< width
; i
++) {
875 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
876 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
877 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
878 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
879 r
= r
* scale
[0] + bias
[0];
880 g
= g
* scale
[1] + bias
[1];
881 b
= b
* scale
[2] + bias
[2];
882 a
= a
* scale
[3] + bias
[3];
883 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
884 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
885 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
886 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
890 ctx
->NewState
|= _NEW_PIXEL
;
894 /**********************************************************************/
895 /*** image convolution functions ***/
896 /**********************************************************************/
899 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
900 GLint filterWidth
, const GLfloat filter
[][4],
906 if (filterWidth
>= 1)
907 dstWidth
= srcWidth
- (filterWidth
- 1);
912 return; /* null result */
914 for (i
= 0; i
< dstWidth
; i
++) {
919 for (n
= 0; n
< filterWidth
; n
++) {
920 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
921 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
922 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
923 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
925 dest
[i
][RCOMP
] = sumR
;
926 dest
[i
][GCOMP
] = sumG
;
927 dest
[i
][BCOMP
] = sumB
;
928 dest
[i
][ACOMP
] = sumA
;
934 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
935 GLint filterWidth
, const GLfloat filter
[][4],
937 const GLfloat borderColor
[4])
939 const GLint halfFilterWidth
= filterWidth
/ 2;
942 for (i
= 0; i
< srcWidth
; i
++) {
947 for (n
= 0; n
< filterWidth
; n
++) {
948 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
949 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
950 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
951 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
952 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
955 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
956 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
957 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
958 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
961 dest
[i
][RCOMP
] = sumR
;
962 dest
[i
][GCOMP
] = sumG
;
963 dest
[i
][BCOMP
] = sumB
;
964 dest
[i
][ACOMP
] = sumA
;
970 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
971 GLint filterWidth
, const GLfloat filter
[][4],
974 const GLint halfFilterWidth
= filterWidth
/ 2;
977 for (i
= 0; i
< srcWidth
; i
++) {
982 for (n
= 0; n
< filterWidth
; n
++) {
983 if (i
+ n
< halfFilterWidth
) {
984 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
985 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
986 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
987 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
989 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
990 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
991 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
992 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
993 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
996 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
997 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
998 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
999 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
1002 dest
[i
][RCOMP
] = sumR
;
1003 dest
[i
][GCOMP
] = sumG
;
1004 dest
[i
][BCOMP
] = sumB
;
1005 dest
[i
][ACOMP
] = sumA
;
1011 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
1012 const GLfloat src
[][4],
1013 GLint filterWidth
, GLint filterHeight
,
1014 const GLfloat filter
[][4],
1017 GLint dstWidth
, dstHeight
;
1020 if (filterWidth
>= 1)
1021 dstWidth
= srcWidth
- (filterWidth
- 1);
1023 dstWidth
= srcWidth
;
1025 if (filterHeight
>= 1)
1026 dstHeight
= srcHeight
- (filterHeight
- 1);
1028 dstHeight
= srcHeight
;
1030 if (dstWidth
<= 0 || dstHeight
<= 0)
1033 for (j
= 0; j
< dstHeight
; j
++) {
1034 for (i
= 0; i
< dstWidth
; i
++) {
1039 for (m
= 0; m
< filterHeight
; m
++) {
1040 for (n
= 0; n
< filterWidth
; n
++) {
1041 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1042 const GLint f
= m
* filterWidth
+ n
;
1043 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1044 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1045 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1046 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1049 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1050 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1051 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1052 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1059 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1060 const GLfloat src
[][4],
1061 GLint filterWidth
, GLint filterHeight
,
1062 const GLfloat filter
[][4],
1064 const GLfloat borderColor
[4])
1066 const GLint halfFilterWidth
= filterWidth
/ 2;
1067 const GLint halfFilterHeight
= filterHeight
/ 2;
1070 for (j
= 0; j
< srcHeight
; j
++) {
1071 for (i
= 0; i
< srcWidth
; i
++) {
1076 for (m
= 0; m
< filterHeight
; m
++) {
1077 for (n
= 0; n
< filterWidth
; n
++) {
1078 const GLint f
= m
* filterWidth
+ n
;
1079 const GLint is
= i
+ n
- halfFilterWidth
;
1080 const GLint js
= j
+ m
- halfFilterHeight
;
1081 if (is
< 0 || is
>= srcWidth
||
1082 js
< 0 || js
>= srcHeight
) {
1083 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1084 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1085 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1086 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1089 const GLint k
= js
* srcWidth
+ is
;
1090 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1091 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1092 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1093 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1097 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1098 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1099 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1100 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1107 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1108 const GLfloat src
[][4],
1109 GLint filterWidth
, GLint filterHeight
,
1110 const GLfloat filter
[][4],
1113 const GLint halfFilterWidth
= filterWidth
/ 2;
1114 const GLint halfFilterHeight
= filterHeight
/ 2;
1117 for (j
= 0; j
< srcHeight
; j
++) {
1118 for (i
= 0; i
< srcWidth
; i
++) {
1123 for (m
= 0; m
< filterHeight
; m
++) {
1124 for (n
= 0; n
< filterWidth
; n
++) {
1125 const GLint f
= m
* filterWidth
+ n
;
1126 GLint is
= i
+ n
- halfFilterWidth
;
1127 GLint js
= j
+ m
- halfFilterHeight
;
1131 else if (is
>= srcWidth
)
1135 else if (js
>= srcHeight
)
1137 k
= js
* srcWidth
+ is
;
1138 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1139 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1140 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1141 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1144 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1145 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1146 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1147 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1154 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1155 const GLfloat src
[][4],
1156 GLint filterWidth
, GLint filterHeight
,
1157 const GLfloat rowFilt
[][4],
1158 const GLfloat colFilt
[][4],
1161 GLint dstWidth
, dstHeight
;
1164 if (filterWidth
>= 1)
1165 dstWidth
= srcWidth
- (filterWidth
- 1);
1167 dstWidth
= srcWidth
;
1169 if (filterHeight
>= 1)
1170 dstHeight
= srcHeight
- (filterHeight
- 1);
1172 dstHeight
= srcHeight
;
1174 if (dstWidth
<= 0 || dstHeight
<= 0)
1177 for (j
= 0; j
< dstHeight
; j
++) {
1178 for (i
= 0; i
< dstWidth
; i
++) {
1183 for (m
= 0; m
< filterHeight
; m
++) {
1184 for (n
= 0; n
< filterWidth
; n
++) {
1185 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1186 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1187 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1188 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1189 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1192 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1193 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1194 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1195 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1202 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1203 const GLfloat src
[][4],
1204 GLint filterWidth
, GLint filterHeight
,
1205 const GLfloat rowFilt
[][4],
1206 const GLfloat colFilt
[][4],
1208 const GLfloat borderColor
[4])
1210 const GLint halfFilterWidth
= filterWidth
/ 2;
1211 const GLint halfFilterHeight
= filterHeight
/ 2;
1214 for (j
= 0; j
< srcHeight
; j
++) {
1215 for (i
= 0; i
< srcWidth
; i
++) {
1220 for (m
= 0; m
< filterHeight
; m
++) {
1221 for (n
= 0; n
< filterWidth
; n
++) {
1222 const GLint is
= i
+ n
- halfFilterWidth
;
1223 const GLint js
= j
+ m
- halfFilterHeight
;
1224 if (is
< 0 || is
>= srcWidth
||
1225 js
< 0 || js
>= srcHeight
) {
1226 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1227 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1228 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1229 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1232 GLint k
= js
* srcWidth
+ is
;
1233 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1234 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1235 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1236 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1241 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1242 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1243 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1244 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1251 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1252 const GLfloat src
[][4],
1253 GLint filterWidth
, GLint filterHeight
,
1254 const GLfloat rowFilt
[][4],
1255 const GLfloat colFilt
[][4],
1258 const GLint halfFilterWidth
= filterWidth
/ 2;
1259 const GLint halfFilterHeight
= filterHeight
/ 2;
1262 for (j
= 0; j
< srcHeight
; j
++) {
1263 for (i
= 0; i
< srcWidth
; i
++) {
1268 for (m
= 0; m
< filterHeight
; m
++) {
1269 for (n
= 0; n
< filterWidth
; n
++) {
1270 GLint is
= i
+ n
- halfFilterWidth
;
1271 GLint js
= j
+ m
- halfFilterHeight
;
1275 else if (is
>= srcWidth
)
1279 else if (js
>= srcHeight
)
1281 k
= js
* srcWidth
+ is
;
1282 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1283 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1284 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1285 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1288 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1289 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1290 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1291 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1299 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1300 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1302 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1304 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1305 ctx
->Convolution1D
.Width
,
1306 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1307 (GLfloat (*)[4]) dstImage
);
1308 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1310 case GL_CONSTANT_BORDER
:
1311 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1312 ctx
->Convolution1D
.Width
,
1313 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1314 (GLfloat (*)[4]) dstImage
,
1315 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1317 case GL_REPLICATE_BORDER
:
1318 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1319 ctx
->Convolution1D
.Width
,
1320 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1321 (GLfloat (*)[4]) dstImage
);
1330 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1331 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1333 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1335 convolve_2d_reduce(*width
, *height
,
1336 (const GLfloat (*)[4]) srcImage
,
1337 ctx
->Convolution2D
.Width
,
1338 ctx
->Convolution2D
.Height
,
1339 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1340 (GLfloat (*)[4]) dstImage
);
1341 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1342 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1344 case GL_CONSTANT_BORDER
:
1345 convolve_2d_constant(*width
, *height
,
1346 (const GLfloat (*)[4]) srcImage
,
1347 ctx
->Convolution2D
.Width
,
1348 ctx
->Convolution2D
.Height
,
1349 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1350 (GLfloat (*)[4]) dstImage
,
1351 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1353 case GL_REPLICATE_BORDER
:
1354 convolve_2d_replicate(*width
, *height
,
1355 (const GLfloat (*)[4]) srcImage
,
1356 ctx
->Convolution2D
.Width
,
1357 ctx
->Convolution2D
.Height
,
1358 (const GLfloat (*)[4])ctx
->Convolution2D
.Filter
,
1359 (GLfloat (*)[4]) dstImage
);
1368 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1369 GLsizei
*width
, GLsizei
*height
,
1370 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1372 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1373 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1375 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1377 convolve_sep_reduce(*width
, *height
,
1378 (const GLfloat (*)[4]) srcImage
,
1379 ctx
->Separable2D
.Width
,
1380 ctx
->Separable2D
.Height
,
1381 (const GLfloat (*)[4]) rowFilter
,
1382 (const GLfloat (*)[4]) colFilter
,
1383 (GLfloat (*)[4]) dstImage
);
1384 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1385 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1387 case GL_CONSTANT_BORDER
:
1388 convolve_sep_constant(*width
, *height
,
1389 (const GLfloat (*)[4]) srcImage
,
1390 ctx
->Separable2D
.Width
,
1391 ctx
->Separable2D
.Height
,
1392 (const GLfloat (*)[4]) rowFilter
,
1393 (const GLfloat (*)[4]) colFilter
,
1394 (GLfloat (*)[4]) dstImage
,
1395 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1397 case GL_REPLICATE_BORDER
:
1398 convolve_sep_replicate(*width
, *height
,
1399 (const GLfloat (*)[4]) srcImage
,
1400 ctx
->Separable2D
.Width
,
1401 ctx
->Separable2D
.Height
,
1402 (const GLfloat (*)[4]) rowFilter
,
1403 (const GLfloat (*)[4]) colFilter
,
1404 (GLfloat (*)[4]) dstImage
);