1 /* $Id: convolve.c,v 1.12 2000/11/21 23:01:22 brianp 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
45 #include "swrast/s_span.h" /* XXX SWRAST hack */
50 * Given an internalFormat token passed to glConvolutionFilter
51 * or glSeparableFilter, return the corresponding base format.
52 * Return -1 if invalid token.
55 base_filter_format( GLenum format
)
70 case GL_LUMINANCE_ALPHA
:
71 case GL_LUMINANCE4_ALPHA4
:
72 case GL_LUMINANCE6_ALPHA2
:
73 case GL_LUMINANCE8_ALPHA8
:
74 case GL_LUMINANCE12_ALPHA4
:
75 case GL_LUMINANCE12_ALPHA12
:
76 case GL_LUMINANCE16_ALPHA16
:
77 return GL_LUMINANCE_ALPHA
;
104 return -1; /* error */
110 _mesa_ConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*image
)
113 GET_CURRENT_CONTEXT(ctx
);
114 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionFilter1D");
116 if (target
!= GL_CONVOLUTION_1D
) {
117 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
121 baseFormat
= base_filter_format(internalFormat
);
122 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
123 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
127 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
128 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
132 if (!_mesa_is_legal_format_and_type(format
, type
) ||
133 format
== GL_COLOR_INDEX
||
134 format
== GL_STENCIL_INDEX
||
135 format
== GL_DEPTH_COMPONENT
||
136 format
== GL_INTENSITY
||
138 gl_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
, "glConvolutionFilter2D");
186 if (target
!= GL_CONVOLUTION_2D
) {
187 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
191 baseFormat
= base_filter_format(internalFormat
);
192 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
193 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
197 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
198 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
201 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
202 gl_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
206 if (!_mesa_is_legal_format_and_type(format
, type
) ||
207 format
== GL_COLOR_INDEX
||
208 format
== GL_STENCIL_INDEX
||
209 format
== GL_DEPTH_COMPONENT
||
210 format
== GL_INTENSITY
||
212 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
216 components
= _mesa_components_in_format(format
);
217 assert(components
> 0); /* this should have been caught earlier */
219 ctx
->Convolution2D
.Format
= format
;
220 ctx
->Convolution2D
.InternalFormat
= internalFormat
;
221 ctx
->Convolution2D
.Width
= width
;
222 ctx
->Convolution2D
.Height
= height
;
224 /* Unpack filter image. We always store filters in RGBA format. */
225 for (i
= 0; i
< height
; i
++) {
226 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
, image
, width
,
227 height
, format
, type
, 0, i
, 0);
228 GLfloat
*dst
= ctx
->Convolution2D
.Filter
+ i
* width
* 4;
229 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, dst
,
230 format
, type
, src
, &ctx
->Unpack
,
234 /* apply scale and bias */
236 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[1];
237 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[1];
238 for (i
= 0; i
< width
* height
* 4; i
++) {
239 GLfloat r
= ctx
->Convolution2D
.Filter
[i
* 4 + 0];
240 GLfloat g
= ctx
->Convolution2D
.Filter
[i
* 4 + 1];
241 GLfloat b
= ctx
->Convolution2D
.Filter
[i
* 4 + 2];
242 GLfloat a
= ctx
->Convolution2D
.Filter
[i
* 4 + 3];
243 r
= r
* scale
[0] + bias
[0];
244 g
= g
* scale
[1] + bias
[1];
245 b
= b
* scale
[2] + bias
[2];
246 a
= a
* scale
[3] + bias
[3];
247 ctx
->Convolution2D
.Filter
[i
* 4 + 0] = r
;
248 ctx
->Convolution2D
.Filter
[i
* 4 + 1] = g
;
249 ctx
->Convolution2D
.Filter
[i
* 4 + 2] = b
;
250 ctx
->Convolution2D
.Filter
[i
* 4 + 3] = a
;
254 ctx
->NewState
|= _NEW_PIXEL
;
259 _mesa_ConvolutionParameterf(GLenum target
, GLenum pname
, GLfloat param
)
261 GET_CURRENT_CONTEXT(ctx
);
264 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameterf");
267 case GL_CONVOLUTION_1D
:
270 case GL_CONVOLUTION_2D
:
273 case GL_SEPARABLE_2D
:
277 gl_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 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
294 gl_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
);
306 struct gl_convolution_attrib
*conv
;
309 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameterfv");
312 case GL_CONVOLUTION_1D
:
314 conv
= &ctx
->Convolution1D
;
316 case GL_CONVOLUTION_2D
:
318 conv
= &ctx
->Convolution2D
;
320 case GL_SEPARABLE_2D
:
322 conv
= &ctx
->Separable2D
;
325 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
330 case GL_CONVOLUTION_BORDER_COLOR
:
331 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
333 case GL_CONVOLUTION_BORDER_MODE
:
334 if (params
[0] == (GLfloat
) GL_REDUCE
||
335 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
336 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
337 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
340 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
344 case GL_CONVOLUTION_FILTER_SCALE
:
345 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
347 case GL_CONVOLUTION_FILTER_BIAS
:
348 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
351 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
355 ctx
->NewState
|= _NEW_PIXEL
;
360 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
362 GET_CURRENT_CONTEXT(ctx
);
365 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameteri");
368 case GL_CONVOLUTION_1D
:
371 case GL_CONVOLUTION_2D
:
374 case GL_SEPARABLE_2D
:
378 gl_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 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
395 gl_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
;
410 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glConvolutionParameteriv");
413 case GL_CONVOLUTION_1D
:
415 conv
= &ctx
->Convolution1D
;
417 case GL_CONVOLUTION_2D
:
419 conv
= &ctx
->Convolution2D
;
421 case GL_SEPARABLE_2D
:
423 conv
= &ctx
->Separable2D
;
426 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
431 case GL_CONVOLUTION_BORDER_COLOR
:
432 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
433 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
434 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
435 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
437 case GL_CONVOLUTION_BORDER_MODE
:
438 if (params
[0] == (GLint
) GL_REDUCE
||
439 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
440 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
441 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
444 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
448 case GL_CONVOLUTION_FILTER_SCALE
:
449 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
451 case GL_CONVOLUTION_FILTER_BIAS
:
452 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
455 gl_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
459 ctx
->NewState
|= _NEW_PIXEL
;
464 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
467 GLchan rgba
[MAX_CONVOLUTION_WIDTH
][4];
468 GET_CURRENT_CONTEXT(ctx
);
469 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyConvolutionFilter1D");
471 if (target
!= GL_CONVOLUTION_1D
) {
472 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
476 baseFormat
= base_filter_format(internalFormat
);
477 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
478 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
482 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
483 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
487 /* read pixels from framebuffer */
489 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
, (GLchan (*)[4]) rgba
);
492 /* store as convolution filter */
493 _mesa_ConvolutionFilter1D(target
, internalFormat
, width
,
494 GL_RGBA
, CHAN_TYPE
, rgba
);
499 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
503 struct gl_pixelstore_attrib packSave
;
504 GLchan rgba
[MAX_CONVOLUTION_HEIGHT
][MAX_CONVOLUTION_WIDTH
][4];
505 GET_CURRENT_CONTEXT(ctx
);
506 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyConvolutionFilter2D");
508 if (target
!= GL_CONVOLUTION_2D
) {
509 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
513 baseFormat
= base_filter_format(internalFormat
);
514 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
515 gl_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
519 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
520 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
523 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
524 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
528 /* read pixels from framebuffer */
530 for (i
= 0; i
< height
; i
++) {
531 gl_read_rgba_span(ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
532 (GLchan (*)[4]) rgba
[i
]);
537 * store as convolution filter
539 packSave
= ctx
->Unpack
; /* save pixel packing params */
541 ctx
->Unpack
.Alignment
= 1;
542 ctx
->Unpack
.RowLength
= MAX_CONVOLUTION_WIDTH
;
543 ctx
->Unpack
.SkipPixels
= 0;
544 ctx
->Unpack
.SkipRows
= 0;
545 ctx
->Unpack
.ImageHeight
= 0;
546 ctx
->Unpack
.SkipImages
= 0;
547 ctx
->Unpack
.SwapBytes
= GL_FALSE
;
548 ctx
->Unpack
.LsbFirst
= GL_FALSE
;
549 ctx
->NewState
|= _NEW_PACKUNPACK
;
551 _mesa_ConvolutionFilter2D(target
, internalFormat
, width
, height
,
552 GL_RGBA
, CHAN_TYPE
, rgba
);
554 ctx
->Unpack
= packSave
; /* restore pixel packing params */
555 ctx
->NewState
|= _NEW_PACKUNPACK
;
560 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*image
)
562 const struct gl_convolution_attrib
*filter
;
564 GET_CURRENT_CONTEXT(ctx
);
565 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionFilter");
567 if (!_mesa_is_legal_format_and_type(format
, type
) ||
568 format
== GL_COLOR_INDEX
||
569 format
== GL_STENCIL_INDEX
||
570 format
== GL_DEPTH_COMPONENT
||
571 format
== GL_INTENSITY
||
573 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
578 case GL_CONVOLUTION_1D
:
579 filter
= &(ctx
->Convolution1D
);
581 case GL_CONVOLUTION_2D
:
582 filter
= &(ctx
->Convolution2D
);
585 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
589 for (row
= 0; row
< filter
->Height
; row
++) {
590 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, image
, filter
->Width
,
591 filter
->Height
, format
, type
,
593 const GLfloat
*src
= filter
->Filter
+ row
* filter
->Width
* 4;
594 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
595 (const GLfloat (*)[4]) src
,
596 format
, type
, dst
, &ctx
->Pack
, 0);
602 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
604 GET_CURRENT_CONTEXT(ctx
);
605 const struct gl_convolution_attrib
*conv
;
608 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionParameterfv");
611 case GL_CONVOLUTION_1D
:
613 conv
= &ctx
->Convolution1D
;
615 case GL_CONVOLUTION_2D
:
617 conv
= &ctx
->Convolution2D
;
619 case GL_SEPARABLE_2D
:
621 conv
= &ctx
->Separable2D
;
624 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
629 case GL_CONVOLUTION_BORDER_COLOR
:
630 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
632 case GL_CONVOLUTION_BORDER_MODE
:
633 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
635 case GL_CONVOLUTION_FILTER_SCALE
:
636 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
638 case GL_CONVOLUTION_FILTER_BIAS
:
639 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
641 case GL_CONVOLUTION_FORMAT
:
642 *params
= (GLfloat
) conv
->Format
;
644 case GL_CONVOLUTION_WIDTH
:
645 *params
= (GLfloat
) conv
->Width
;
647 case GL_CONVOLUTION_HEIGHT
:
648 *params
= (GLfloat
) conv
->Height
;
650 case GL_MAX_CONVOLUTION_WIDTH
:
651 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
653 case GL_MAX_CONVOLUTION_HEIGHT
:
654 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
657 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
664 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
666 GET_CURRENT_CONTEXT(ctx
);
667 const struct gl_convolution_attrib
*conv
;
670 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetConvolutionParameteriv");
673 case GL_CONVOLUTION_1D
:
675 conv
= &ctx
->Convolution1D
;
677 case GL_CONVOLUTION_2D
:
679 conv
= &ctx
->Convolution2D
;
681 case GL_SEPARABLE_2D
:
683 conv
= &ctx
->Separable2D
;
686 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
691 case GL_CONVOLUTION_BORDER_COLOR
:
692 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
693 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
694 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
695 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
697 case GL_CONVOLUTION_BORDER_MODE
:
698 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
700 case GL_CONVOLUTION_FILTER_SCALE
:
701 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
702 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
703 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
704 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
706 case GL_CONVOLUTION_FILTER_BIAS
:
707 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
708 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
709 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
710 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
712 case GL_CONVOLUTION_FORMAT
:
713 *params
= (GLint
) conv
->Format
;
715 case GL_CONVOLUTION_WIDTH
:
716 *params
= (GLint
) conv
->Width
;
718 case GL_CONVOLUTION_HEIGHT
:
719 *params
= (GLint
) conv
->Height
;
721 case GL_MAX_CONVOLUTION_WIDTH
:
722 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
724 case GL_MAX_CONVOLUTION_HEIGHT
:
725 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
728 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
735 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
, GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
737 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
738 const struct gl_convolution_attrib
*filter
;
739 GET_CURRENT_CONTEXT(ctx
);
740 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetSeparableFilter");
742 if (target
!= GL_SEPARABLE_2D
) {
743 gl_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
747 if (!_mesa_is_legal_format_and_type(format
, type
) ||
748 format
== GL_COLOR_INDEX
||
749 format
== GL_STENCIL_INDEX
||
750 format
== GL_DEPTH_COMPONENT
||
751 format
== GL_INTENSITY
||
753 gl_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
757 filter
= &ctx
->Separable2D
;
761 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, row
, filter
->Width
,
762 filter
->Height
, format
, type
,
764 _mesa_pack_float_rgba_span(ctx
, filter
->Width
,
765 (const GLfloat (*)[4]) filter
->Filter
,
766 format
, type
, dst
, &ctx
->Pack
, 0);
771 GLvoid
*dst
= _mesa_image_address( &ctx
->Pack
, column
, filter
->Width
,
774 const GLfloat
*src
= filter
->Filter
+ colStart
;
775 _mesa_pack_float_rgba_span(ctx
, filter
->Height
,
776 (const GLfloat (*)[4]) src
,
777 format
, type
, dst
, &ctx
->Pack
, 0);
780 (void) span
; /* unused at this time */
785 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
787 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
789 GET_CURRENT_CONTEXT(ctx
);
790 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glSeparableFilter2D");
792 if (target
!= GL_SEPARABLE_2D
) {
793 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
797 baseFormat
= base_filter_format(internalFormat
);
798 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
799 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
803 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
804 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
807 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
808 gl_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
812 if (!_mesa_is_legal_format_and_type(format
, type
) ||
813 format
== GL_COLOR_INDEX
||
814 format
== GL_STENCIL_INDEX
||
815 format
== GL_DEPTH_COMPONENT
||
816 format
== GL_INTENSITY
||
818 gl_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
822 ctx
->Separable2D
.Format
= format
;
823 ctx
->Separable2D
.InternalFormat
= internalFormat
;
824 ctx
->Separable2D
.Width
= width
;
825 ctx
->Separable2D
.Height
= height
;
827 /* unpack row filter */
828 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
829 ctx
->Separable2D
.Filter
,
830 format
, type
, row
, &ctx
->Unpack
,
833 /* apply scale and bias */
835 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
836 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
838 for (i
= 0; i
< width
; i
++) {
839 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0];
840 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1];
841 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2];
842 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3];
843 r
= r
* scale
[0] + bias
[0];
844 g
= g
* scale
[1] + bias
[1];
845 b
= b
* scale
[2] + bias
[2];
846 a
= a
* scale
[3] + bias
[3];
847 ctx
->Separable2D
.Filter
[i
* 4 + 0] = r
;
848 ctx
->Separable2D
.Filter
[i
* 4 + 1] = g
;
849 ctx
->Separable2D
.Filter
[i
* 4 + 2] = b
;
850 ctx
->Separable2D
.Filter
[i
* 4 + 3] = a
;
854 /* unpack column filter */
855 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
,
856 &ctx
->Separable2D
.Filter
[colStart
],
857 format
, type
, column
, &ctx
->Unpack
,
860 /* apply scale and bias */
862 const GLfloat
*scale
= ctx
->Pixel
.ConvolutionFilterScale
[2];
863 const GLfloat
*bias
= ctx
->Pixel
.ConvolutionFilterBias
[2];
865 for (i
= 0; i
< width
; i
++) {
866 GLfloat r
= ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
];
867 GLfloat g
= ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
];
868 GLfloat b
= ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
];
869 GLfloat a
= ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
];
870 r
= r
* scale
[0] + bias
[0];
871 g
= g
* scale
[1] + bias
[1];
872 b
= b
* scale
[2] + bias
[2];
873 a
= a
* scale
[3] + bias
[3];
874 ctx
->Separable2D
.Filter
[i
* 4 + 0 + colStart
] = r
;
875 ctx
->Separable2D
.Filter
[i
* 4 + 1 + colStart
] = g
;
876 ctx
->Separable2D
.Filter
[i
* 4 + 2 + colStart
] = b
;
877 ctx
->Separable2D
.Filter
[i
* 4 + 3 + colStart
] = a
;
881 ctx
->NewState
|= _NEW_PIXEL
;
885 /**********************************************************************/
886 /*** image convolution functions ***/
887 /**********************************************************************/
890 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
891 GLint filterWidth
, const GLfloat filter
[][4],
897 if (filterWidth
>= 1)
898 dstWidth
= srcWidth
- (filterWidth
- 1);
903 return; /* null result */
905 for (i
= 0; i
< dstWidth
; i
++) {
910 for (n
= 0; n
< filterWidth
; n
++) {
911 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
912 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
913 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
914 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
916 dest
[i
][RCOMP
] = sumR
;
917 dest
[i
][GCOMP
] = sumG
;
918 dest
[i
][BCOMP
] = sumB
;
919 dest
[i
][ACOMP
] = sumA
;
925 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
926 GLint filterWidth
, const GLfloat filter
[][4],
928 const GLfloat borderColor
[4])
930 const GLint halfFilterWidth
= filterWidth
/ 2;
933 for (i
= 0; i
< srcWidth
; i
++) {
938 for (n
= 0; n
< filterWidth
; n
++) {
939 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
940 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
941 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
942 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
943 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
946 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
947 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
948 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
949 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
952 dest
[i
][RCOMP
] = sumR
;
953 dest
[i
][GCOMP
] = sumG
;
954 dest
[i
][BCOMP
] = sumB
;
955 dest
[i
][ACOMP
] = sumA
;
961 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
962 GLint filterWidth
, const GLfloat filter
[][4],
965 const GLint halfFilterWidth
= filterWidth
/ 2;
968 for (i
= 0; i
< srcWidth
; i
++) {
973 for (n
= 0; n
< filterWidth
; n
++) {
974 if (i
+ n
< halfFilterWidth
) {
975 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
976 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
977 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
978 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
980 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
981 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
982 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
983 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
984 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
987 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
988 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
989 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
990 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
993 dest
[i
][RCOMP
] = sumR
;
994 dest
[i
][GCOMP
] = sumG
;
995 dest
[i
][BCOMP
] = sumB
;
996 dest
[i
][ACOMP
] = sumA
;
1002 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
1003 const GLfloat src
[][4],
1004 GLint filterWidth
, GLint filterHeight
,
1005 const GLfloat filter
[][4],
1008 GLint dstWidth
, dstHeight
;
1011 if (filterWidth
>= 1)
1012 dstWidth
= srcWidth
- (filterWidth
- 1);
1014 dstWidth
= srcWidth
;
1016 if (filterHeight
>= 1)
1017 dstHeight
= srcHeight
- (filterHeight
- 1);
1019 dstHeight
= srcHeight
;
1021 if (dstWidth
<= 0 || dstHeight
<= 0)
1024 for (j
= 0; j
< dstHeight
; j
++) {
1025 for (i
= 0; i
< dstWidth
; i
++) {
1030 for (m
= 0; m
< filterHeight
; m
++) {
1031 for (n
= 0; n
< filterWidth
; n
++) {
1032 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1033 const GLint f
= m
* filterWidth
+ n
;
1034 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1035 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1036 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1037 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1040 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1041 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1042 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1043 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1050 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1051 const GLfloat src
[][4],
1052 GLint filterWidth
, GLint filterHeight
,
1053 const GLfloat filter
[][4],
1055 const GLfloat borderColor
[4])
1057 const GLint halfFilterWidth
= filterWidth
/ 2;
1058 const GLint halfFilterHeight
= filterHeight
/ 2;
1061 for (j
= 0; j
< srcHeight
; j
++) {
1062 for (i
= 0; i
< srcWidth
; i
++) {
1067 for (m
= 0; m
< filterHeight
; m
++) {
1068 for (n
= 0; n
< filterWidth
; n
++) {
1069 const GLint f
= m
* filterWidth
+ n
;
1070 const GLint is
= i
+ n
- halfFilterWidth
;
1071 const GLint js
= j
+ m
- halfFilterHeight
;
1072 if (is
< 0 || is
>= srcWidth
||
1073 js
< 0 || js
>= srcHeight
) {
1074 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1075 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1076 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1077 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1080 const GLint k
= js
* srcWidth
+ is
;
1081 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1082 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1083 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1084 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1088 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1089 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1090 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1091 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1098 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1099 const GLfloat src
[][4],
1100 GLint filterWidth
, GLint filterHeight
,
1101 const GLfloat filter
[][4],
1104 const GLint halfFilterWidth
= filterWidth
/ 2;
1105 const GLint halfFilterHeight
= filterHeight
/ 2;
1108 for (j
= 0; j
< srcHeight
; j
++) {
1109 for (i
= 0; i
< srcWidth
; i
++) {
1114 for (m
= 0; m
< filterHeight
; m
++) {
1115 for (n
= 0; n
< filterWidth
; n
++) {
1116 const GLint f
= m
* filterWidth
+ n
;
1117 GLint is
= i
+ n
- halfFilterWidth
;
1118 GLint js
= j
+ m
- halfFilterHeight
;
1122 else if (is
>= srcWidth
)
1126 else if (js
>= srcHeight
)
1128 k
= js
* srcWidth
+ is
;
1129 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1130 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1131 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1132 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1135 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1136 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1137 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1138 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1145 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1146 const GLfloat src
[][4],
1147 GLint filterWidth
, GLint filterHeight
,
1148 const GLfloat rowFilt
[][4],
1149 const GLfloat colFilt
[][4],
1152 GLint dstWidth
, dstHeight
;
1155 if (filterWidth
>= 1)
1156 dstWidth
= srcWidth
- (filterWidth
- 1);
1158 dstWidth
= srcWidth
;
1160 if (filterHeight
>= 1)
1161 dstHeight
= srcHeight
- (filterHeight
- 1);
1163 dstHeight
= srcHeight
;
1165 if (dstWidth
<= 0 || dstHeight
<= 0)
1168 for (j
= 0; j
< dstHeight
; j
++) {
1169 for (i
= 0; i
< dstWidth
; i
++) {
1174 for (m
= 0; m
< filterHeight
; m
++) {
1175 for (n
= 0; n
< filterWidth
; n
++) {
1176 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1177 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1178 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1179 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1180 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1183 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1184 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1185 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1186 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1193 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1194 const GLfloat src
[][4],
1195 GLint filterWidth
, GLint filterHeight
,
1196 const GLfloat rowFilt
[][4],
1197 const GLfloat colFilt
[][4],
1199 const GLfloat borderColor
[4])
1201 const GLint halfFilterWidth
= filterWidth
/ 2;
1202 const GLint halfFilterHeight
= filterHeight
/ 2;
1205 for (j
= 0; j
< srcHeight
; j
++) {
1206 for (i
= 0; i
< srcWidth
; i
++) {
1211 for (m
= 0; m
< filterHeight
; m
++) {
1212 for (n
= 0; n
< filterWidth
; n
++) {
1213 const GLint is
= i
+ n
- halfFilterWidth
;
1214 const GLint js
= j
+ m
- halfFilterHeight
;
1215 if (is
< 0 || is
>= srcWidth
||
1216 js
< 0 || js
>= srcHeight
) {
1217 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1218 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1219 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1220 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1223 GLint k
= js
* srcWidth
+ is
;
1224 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1225 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1226 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1227 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1232 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1233 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1234 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1235 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1242 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1243 const GLfloat src
[][4],
1244 GLint filterWidth
, GLint filterHeight
,
1245 const GLfloat rowFilt
[][4],
1246 const GLfloat colFilt
[][4],
1249 const GLint halfFilterWidth
= filterWidth
/ 2;
1250 const GLint halfFilterHeight
= filterHeight
/ 2;
1253 for (j
= 0; j
< srcHeight
; j
++) {
1254 for (i
= 0; i
< srcWidth
; i
++) {
1259 for (m
= 0; m
< filterHeight
; m
++) {
1260 for (n
= 0; n
< filterWidth
; n
++) {
1261 GLint is
= i
+ n
- halfFilterWidth
;
1262 GLint js
= j
+ m
- halfFilterHeight
;
1266 else if (is
>= srcWidth
)
1270 else if (js
>= srcHeight
)
1272 k
= js
* srcWidth
+ is
;
1273 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1274 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1275 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1276 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1279 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1280 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1281 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1282 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1290 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1291 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1293 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1295 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1296 ctx
->Convolution1D
.Width
,
1297 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1298 (GLfloat (*)[4]) dstImage
);
1299 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1301 case GL_CONSTANT_BORDER
:
1302 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1303 ctx
->Convolution1D
.Width
,
1304 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1305 (GLfloat (*)[4]) dstImage
,
1306 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1308 case GL_REPLICATE_BORDER
:
1309 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1310 ctx
->Convolution1D
.Width
,
1311 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1312 (GLfloat (*)[4]) dstImage
);
1321 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1322 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1324 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1326 convolve_2d_reduce(*width
, *height
,
1327 (const GLfloat (*)[4]) srcImage
,
1328 ctx
->Convolution2D
.Width
,
1329 ctx
->Convolution2D
.Height
,
1330 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1331 (GLfloat (*)[4]) dstImage
);
1332 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1333 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1335 case GL_CONSTANT_BORDER
:
1336 convolve_2d_constant(*width
, *height
,
1337 (const GLfloat (*)[4]) srcImage
,
1338 ctx
->Convolution2D
.Width
,
1339 ctx
->Convolution2D
.Height
,
1340 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1341 (GLfloat (*)[4]) dstImage
,
1342 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1344 case GL_REPLICATE_BORDER
:
1345 convolve_2d_replicate(*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
);
1359 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1360 GLsizei
*width
, GLsizei
*height
,
1361 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1363 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1364 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1366 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1368 convolve_sep_reduce(*width
, *height
,
1369 (const GLfloat (*)[4]) srcImage
,
1370 ctx
->Separable2D
.Width
,
1371 ctx
->Separable2D
.Height
,
1372 (const GLfloat (*)[4]) rowFilter
,
1373 (const GLfloat (*)[4]) colFilter
,
1374 (GLfloat (*)[4]) dstImage
);
1375 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1376 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1378 case GL_CONSTANT_BORDER
:
1379 convolve_sep_constant(*width
, *height
,
1380 (const GLfloat (*)[4]) srcImage
,
1381 ctx
->Separable2D
.Width
,
1382 ctx
->Separable2D
.Height
,
1383 (const GLfloat (*)[4]) rowFilter
,
1384 (const GLfloat (*)[4]) colFilter
,
1385 (GLfloat (*)[4]) dstImage
,
1386 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1388 case GL_REPLICATE_BORDER
:
1389 convolve_sep_replicate(*width
, *height
,
1390 (const GLfloat (*)[4]) srcImage
,
1391 ctx
->Separable2D
.Width
,
1392 ctx
->Separable2D
.Height
,
1393 (const GLfloat (*)[4]) rowFilter
,
1394 (const GLfloat (*)[4]) colFilter
,
1395 (GLfloat (*)[4]) dstImage
);