2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 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
35 #include "bufferobj.h"
42 #include "main/dispatch.h"
49 * Given an internalFormat token passed to glConvolutionFilter
50 * or glSeparableFilter, return the corresponding base format.
51 * Return -1 if invalid token.
54 base_filter_format( GLenum format
)
69 case GL_LUMINANCE_ALPHA
:
70 case GL_LUMINANCE4_ALPHA4
:
71 case GL_LUMINANCE6_ALPHA2
:
72 case GL_LUMINANCE8_ALPHA8
:
73 case GL_LUMINANCE12_ALPHA4
:
74 case GL_LUMINANCE12_ALPHA12
:
75 case GL_LUMINANCE16_ALPHA16
:
76 return GL_LUMINANCE_ALPHA
;
103 return -1; /* error */
109 _mesa_ConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*image
)
112 GET_CURRENT_CONTEXT(ctx
);
113 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
115 if (target
!= GL_CONVOLUTION_1D
) {
116 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
120 baseFormat
= base_filter_format(internalFormat
);
121 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
122 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
126 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
127 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
131 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
132 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter1D(format or type)");
136 if (format
== GL_COLOR_INDEX
||
137 format
== GL_STENCIL_INDEX
||
138 format
== GL_DEPTH_COMPONENT
||
139 format
== GL_INTENSITY
||
141 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(format or type)");
145 ctx
->Convolution1D
.Format
= format
;
146 ctx
->Convolution1D
.InternalFormat
= internalFormat
;
147 ctx
->Convolution1D
.Width
= width
;
148 ctx
->Convolution1D
.Height
= 1;
150 image
= _mesa_map_validate_pbo_source(ctx
,
151 1, &ctx
->Unpack
, width
, 1, 1,
153 "glConvolutionFilter1D");
157 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
,
158 ctx
->Convolution1D
.Filter
,
159 format
, type
, image
, &ctx
->Unpack
,
160 0); /* transferOps */
162 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
164 _mesa_scale_and_bias_rgba(width
,
165 (GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
166 ctx
->Pixel
.ConvolutionFilterScale
[0][0],
167 ctx
->Pixel
.ConvolutionFilterScale
[0][1],
168 ctx
->Pixel
.ConvolutionFilterScale
[0][2],
169 ctx
->Pixel
.ConvolutionFilterScale
[0][3],
170 ctx
->Pixel
.ConvolutionFilterBias
[0][0],
171 ctx
->Pixel
.ConvolutionFilterBias
[0][1],
172 ctx
->Pixel
.ConvolutionFilterBias
[0][2],
173 ctx
->Pixel
.ConvolutionFilterBias
[0][3]);
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
);
187 if (target
!= GL_CONVOLUTION_2D
) {
188 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
192 baseFormat
= base_filter_format(internalFormat
);
193 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
194 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
198 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
199 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
202 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
203 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
207 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
208 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter2D(format or type)");
211 if (format
== GL_COLOR_INDEX
||
212 format
== GL_STENCIL_INDEX
||
213 format
== GL_DEPTH_COMPONENT
||
214 format
== GL_INTENSITY
||
216 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
220 /* this should have been caught earlier */
221 assert(_mesa_components_in_format(format
));
223 ctx
->Convolution2D
.Format
= format
;
224 ctx
->Convolution2D
.InternalFormat
= internalFormat
;
225 ctx
->Convolution2D
.Width
= width
;
226 ctx
->Convolution2D
.Height
= height
;
228 image
= _mesa_map_validate_pbo_source(ctx
,
229 2, &ctx
->Unpack
, width
, height
, 1,
231 "glConvolutionFilter2D");
235 /* Unpack filter image. We always store filters in RGBA format. */
236 for (i
= 0; i
< height
; i
++) {
237 const GLvoid
*src
= _mesa_image_address2d(&ctx
->Unpack
, image
, width
,
238 height
, format
, type
, i
, 0);
239 GLfloat
*dst
= ctx
->Convolution2D
.Filter
+ i
* width
* 4;
240 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, dst
,
241 format
, type
, src
, &ctx
->Unpack
,
242 0); /* transferOps */
245 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
247 _mesa_scale_and_bias_rgba(width
* height
,
248 (GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
249 ctx
->Pixel
.ConvolutionFilterScale
[1][0],
250 ctx
->Pixel
.ConvolutionFilterScale
[1][1],
251 ctx
->Pixel
.ConvolutionFilterScale
[1][2],
252 ctx
->Pixel
.ConvolutionFilterScale
[1][3],
253 ctx
->Pixel
.ConvolutionFilterBias
[1][0],
254 ctx
->Pixel
.ConvolutionFilterBias
[1][1],
255 ctx
->Pixel
.ConvolutionFilterBias
[1][2],
256 ctx
->Pixel
.ConvolutionFilterBias
[1][3]);
258 ctx
->NewState
|= _NEW_PIXEL
;
262 static void GLAPIENTRY
263 _mesa_ConvolutionParameterf(GLenum target
, GLenum pname
, GLfloat param
)
265 GET_CURRENT_CONTEXT(ctx
);
267 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
270 case GL_CONVOLUTION_1D
:
273 case GL_CONVOLUTION_2D
:
276 case GL_SEPARABLE_2D
:
280 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
285 case GL_CONVOLUTION_BORDER_MODE
:
286 if (param
== (GLfloat
) GL_REDUCE
||
287 param
== (GLfloat
) GL_CONSTANT_BORDER
||
288 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
289 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
292 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
297 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
301 ctx
->NewState
|= _NEW_PIXEL
;
305 static void GLAPIENTRY
306 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
308 GET_CURRENT_CONTEXT(ctx
);
310 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
313 case GL_CONVOLUTION_1D
:
316 case GL_CONVOLUTION_2D
:
319 case GL_SEPARABLE_2D
:
323 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
328 case GL_CONVOLUTION_BORDER_COLOR
:
329 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
331 case GL_CONVOLUTION_BORDER_MODE
:
332 if (params
[0] == (GLfloat
) GL_REDUCE
||
333 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
334 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
335 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
338 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
342 case GL_CONVOLUTION_FILTER_SCALE
:
343 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
345 case GL_CONVOLUTION_FILTER_BIAS
:
346 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
349 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
353 ctx
->NewState
|= _NEW_PIXEL
;
357 static void GLAPIENTRY
358 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
360 GET_CURRENT_CONTEXT(ctx
);
362 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
365 case GL_CONVOLUTION_1D
:
368 case GL_CONVOLUTION_2D
:
371 case GL_SEPARABLE_2D
:
375 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
380 case GL_CONVOLUTION_BORDER_MODE
:
381 if (param
== (GLint
) GL_REDUCE
||
382 param
== (GLint
) GL_CONSTANT_BORDER
||
383 param
== (GLint
) GL_REPLICATE_BORDER
) {
384 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
387 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
392 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
396 ctx
->NewState
|= _NEW_PIXEL
;
400 static void GLAPIENTRY
401 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
403 GET_CURRENT_CONTEXT(ctx
);
405 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
408 case GL_CONVOLUTION_1D
:
411 case GL_CONVOLUTION_2D
:
414 case GL_SEPARABLE_2D
:
418 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
423 case GL_CONVOLUTION_BORDER_COLOR
:
424 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
425 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
426 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
427 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
429 case GL_CONVOLUTION_BORDER_MODE
:
430 if (params
[0] == (GLint
) GL_REDUCE
||
431 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
432 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
433 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
436 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
440 case GL_CONVOLUTION_FILTER_SCALE
:
441 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
442 /* need cast to prevent compiler warnings */
443 ctx
->Pixel
.ConvolutionFilterScale
[c
][0] = (GLfloat
) params
[0];
444 ctx
->Pixel
.ConvolutionFilterScale
[c
][1] = (GLfloat
) params
[1];
445 ctx
->Pixel
.ConvolutionFilterScale
[c
][2] = (GLfloat
) params
[2];
446 ctx
->Pixel
.ConvolutionFilterScale
[c
][3] = (GLfloat
) params
[3];
448 case GL_CONVOLUTION_FILTER_BIAS
:
449 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
450 /* need cast to prevent compiler warnings */
451 ctx
->Pixel
.ConvolutionFilterBias
[c
][0] = (GLfloat
) params
[0];
452 ctx
->Pixel
.ConvolutionFilterBias
[c
][1] = (GLfloat
) params
[1];
453 ctx
->Pixel
.ConvolutionFilterBias
[c
][2] = (GLfloat
) params
[2];
454 ctx
->Pixel
.ConvolutionFilterBias
[c
][3] = (GLfloat
) params
[3];
457 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
461 ctx
->NewState
|= _NEW_PIXEL
;
465 static void GLAPIENTRY
466 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
469 GET_CURRENT_CONTEXT(ctx
);
470 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
472 if (target
!= GL_CONVOLUTION_1D
) {
473 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
477 baseFormat
= base_filter_format(internalFormat
);
478 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
479 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
483 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
484 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
488 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
489 return; /* no readbuffer - OK */
492 ctx
->Driver
.CopyConvolutionFilter1D( ctx
, target
,
493 internalFormat
, x
, y
, width
);
497 static void GLAPIENTRY
498 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
501 GET_CURRENT_CONTEXT(ctx
);
502 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
504 if (target
!= GL_CONVOLUTION_2D
) {
505 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
509 baseFormat
= base_filter_format(internalFormat
);
510 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
511 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
515 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
516 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
519 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
520 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
524 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
525 return; /* no readbuffer - OK */
528 ctx
->Driver
.CopyConvolutionFilter2D( ctx
, target
, internalFormat
, x
, y
,
533 static void GLAPIENTRY
534 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
,
537 struct gl_convolution_attrib
*filter
;
539 GET_CURRENT_CONTEXT(ctx
);
540 ASSERT_OUTSIDE_BEGIN_END(ctx
);
543 _mesa_update_state(ctx
);
546 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
547 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
551 if (format
== GL_COLOR_INDEX
||
552 format
== GL_STENCIL_INDEX
||
553 format
== GL_DEPTH_COMPONENT
||
554 format
== GL_INTENSITY
||
556 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
561 case GL_CONVOLUTION_1D
:
562 filter
= &(ctx
->Convolution1D
);
564 case GL_CONVOLUTION_2D
:
565 filter
= &(ctx
->Convolution2D
);
568 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
572 image
= _mesa_map_validate_pbo_dest(ctx
, 2, &ctx
->Pack
,
573 filter
->Width
, filter
->Height
, 1,
575 "glGetConvolutionFilter");
579 for (row
= 0; row
< filter
->Height
; row
++) {
580 GLvoid
*dst
= _mesa_image_address2d(&ctx
->Pack
, image
, filter
->Width
,
581 filter
->Height
, format
, type
,
583 GLfloat (*src
)[4] = (GLfloat (*)[4]) (filter
->Filter
+ row
* filter
->Width
* 4);
584 _mesa_pack_rgba_span_float(ctx
, filter
->Width
, src
,
585 format
, type
, dst
, &ctx
->Pack
, 0x0);
588 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
592 static void GLAPIENTRY
593 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
595 GET_CURRENT_CONTEXT(ctx
);
596 const struct gl_convolution_attrib
*conv
;
598 ASSERT_OUTSIDE_BEGIN_END(ctx
);
601 case GL_CONVOLUTION_1D
:
603 conv
= &ctx
->Convolution1D
;
605 case GL_CONVOLUTION_2D
:
607 conv
= &ctx
->Convolution2D
;
609 case GL_SEPARABLE_2D
:
611 conv
= &ctx
->Separable2D
;
614 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
619 case GL_CONVOLUTION_BORDER_COLOR
:
620 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
622 case GL_CONVOLUTION_BORDER_MODE
:
623 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
625 case GL_CONVOLUTION_FILTER_SCALE
:
626 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
628 case GL_CONVOLUTION_FILTER_BIAS
:
629 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
631 case GL_CONVOLUTION_FORMAT
:
632 *params
= (GLfloat
) conv
->Format
;
634 case GL_CONVOLUTION_WIDTH
:
635 *params
= (GLfloat
) conv
->Width
;
637 case GL_CONVOLUTION_HEIGHT
:
638 *params
= (GLfloat
) conv
->Height
;
640 case GL_MAX_CONVOLUTION_WIDTH
:
641 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
643 case GL_MAX_CONVOLUTION_HEIGHT
:
644 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
647 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
653 static void GLAPIENTRY
654 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
656 GET_CURRENT_CONTEXT(ctx
);
657 const struct gl_convolution_attrib
*conv
;
659 ASSERT_OUTSIDE_BEGIN_END(ctx
);
662 case GL_CONVOLUTION_1D
:
664 conv
= &ctx
->Convolution1D
;
666 case GL_CONVOLUTION_2D
:
668 conv
= &ctx
->Convolution2D
;
670 case GL_SEPARABLE_2D
:
672 conv
= &ctx
->Separable2D
;
675 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
680 case GL_CONVOLUTION_BORDER_COLOR
:
681 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
682 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
683 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
684 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
686 case GL_CONVOLUTION_BORDER_MODE
:
687 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
689 case GL_CONVOLUTION_FILTER_SCALE
:
690 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
691 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
692 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
693 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
695 case GL_CONVOLUTION_FILTER_BIAS
:
696 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
697 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
698 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
699 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
701 case GL_CONVOLUTION_FORMAT
:
702 *params
= (GLint
) conv
->Format
;
704 case GL_CONVOLUTION_WIDTH
:
705 *params
= (GLint
) conv
->Width
;
707 case GL_CONVOLUTION_HEIGHT
:
708 *params
= (GLint
) conv
->Height
;
710 case GL_MAX_CONVOLUTION_WIDTH
:
711 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
713 case GL_MAX_CONVOLUTION_HEIGHT
:
714 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
717 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
723 static void GLAPIENTRY
724 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
,
725 GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
727 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
728 struct gl_convolution_attrib
*filter
;
729 GET_CURRENT_CONTEXT(ctx
);
730 ASSERT_OUTSIDE_BEGIN_END(ctx
);
733 _mesa_update_state(ctx
);
736 if (target
!= GL_SEPARABLE_2D
) {
737 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
741 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
742 _mesa_error(ctx
, GL_INVALID_OPERATION
,
743 "glGetConvolutionFilter(format or type)");
747 if (format
== GL_COLOR_INDEX
||
748 format
== GL_STENCIL_INDEX
||
749 format
== GL_DEPTH_COMPONENT
||
750 format
== GL_INTENSITY
||
752 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
756 filter
= &ctx
->Separable2D
;
759 row
= _mesa_map_validate_pbo_dest(ctx
, 1, &ctx
->Pack
,
762 "glGetConvolutionFilter");
764 GLvoid
*dst
= _mesa_image_address1d(&ctx
->Pack
, row
, filter
->Width
,
766 _mesa_pack_rgba_span_float(ctx
, filter
->Width
,
767 (GLfloat (*)[4]) filter
->Filter
,
768 format
, type
, dst
, &ctx
->Pack
, 0x0);
769 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
772 /* get column filter */
773 column
= _mesa_map_validate_pbo_dest(ctx
, 1, &ctx
->Pack
,
774 filter
->Height
, 1, 1,
775 format
, type
, column
,
776 "glGetConvolutionFilter");
778 GLvoid
*dst
= _mesa_image_address1d(&ctx
->Pack
, column
, filter
->Height
,
780 GLfloat (*src
)[4] = (GLfloat (*)[4]) (filter
->Filter
+ colStart
);
781 _mesa_pack_rgba_span_float(ctx
, filter
->Height
, src
,
782 format
, type
, dst
, &ctx
->Pack
, 0x0);
783 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
786 (void) span
; /* unused at this time */
790 static void GLAPIENTRY
791 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
793 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
795 GET_CURRENT_CONTEXT(ctx
);
796 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
798 if (target
!= GL_SEPARABLE_2D
) {
799 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
803 baseFormat
= base_filter_format(internalFormat
);
804 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
805 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
809 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
810 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
813 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
814 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
818 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
819 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
823 if (format
== GL_COLOR_INDEX
||
824 format
== GL_STENCIL_INDEX
||
825 format
== GL_DEPTH_COMPONENT
||
826 format
== GL_INTENSITY
||
828 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
832 ctx
->Separable2D
.Format
= format
;
833 ctx
->Separable2D
.InternalFormat
= internalFormat
;
834 ctx
->Separable2D
.Width
= width
;
835 ctx
->Separable2D
.Height
= height
;
837 /* unpack row filter */
838 row
= _mesa_map_validate_pbo_source(ctx
, 1, &ctx
->Unpack
,
841 "glSeparableFilter2D");
843 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
,
844 ctx
->Separable2D
.Filter
,
845 format
, type
, row
, &ctx
->Unpack
,
846 0x0); /* transferOps */
847 _mesa_scale_and_bias_rgba(width
,
848 (GLfloat (*)[4]) ctx
->Separable2D
.Filter
,
849 ctx
->Pixel
.ConvolutionFilterScale
[2][0],
850 ctx
->Pixel
.ConvolutionFilterScale
[2][1],
851 ctx
->Pixel
.ConvolutionFilterScale
[2][2],
852 ctx
->Pixel
.ConvolutionFilterScale
[2][3],
853 ctx
->Pixel
.ConvolutionFilterBias
[2][0],
854 ctx
->Pixel
.ConvolutionFilterBias
[2][1],
855 ctx
->Pixel
.ConvolutionFilterBias
[2][2],
856 ctx
->Pixel
.ConvolutionFilterBias
[2][3]);
857 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
860 /* unpack column filter */
861 column
= _mesa_map_validate_pbo_source(ctx
, 1, &ctx
->Unpack
,
863 format
, type
, column
,
864 "glSeparableFilter2D");
866 _mesa_unpack_color_span_float(ctx
, height
, GL_RGBA
,
867 &ctx
->Separable2D
.Filter
[colStart
],
868 format
, type
, column
, &ctx
->Unpack
,
869 0); /* transferOps */
871 _mesa_scale_and_bias_rgba(height
,
872 (GLfloat (*)[4]) (ctx
->Separable2D
.Filter
+ colStart
),
873 ctx
->Pixel
.ConvolutionFilterScale
[2][0],
874 ctx
->Pixel
.ConvolutionFilterScale
[2][1],
875 ctx
->Pixel
.ConvolutionFilterScale
[2][2],
876 ctx
->Pixel
.ConvolutionFilterScale
[2][3],
877 ctx
->Pixel
.ConvolutionFilterBias
[2][0],
878 ctx
->Pixel
.ConvolutionFilterBias
[2][1],
879 ctx
->Pixel
.ConvolutionFilterBias
[2][2],
880 ctx
->Pixel
.ConvolutionFilterBias
[2][3]);
881 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
884 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
885 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
886 ctx
->Unpack
.BufferObj
);
889 ctx
->NewState
|= _NEW_PIXEL
;
893 /**********************************************************************/
894 /*** image convolution functions ***/
895 /**********************************************************************/
898 convolve_1d_reduce(GLint srcWidth
, const GLfloat src
[][4],
899 GLint filterWidth
, const GLfloat filter
[][4],
905 if (filterWidth
>= 1)
906 dstWidth
= srcWidth
- (filterWidth
- 1);
911 return; /* null result */
913 for (i
= 0; i
< dstWidth
; i
++) {
918 for (n
= 0; n
< filterWidth
; n
++) {
919 sumR
+= src
[i
+ n
][RCOMP
] * filter
[n
][RCOMP
];
920 sumG
+= src
[i
+ n
][GCOMP
] * filter
[n
][GCOMP
];
921 sumB
+= src
[i
+ n
][BCOMP
] * filter
[n
][BCOMP
];
922 sumA
+= src
[i
+ n
][ACOMP
] * filter
[n
][ACOMP
];
924 dest
[i
][RCOMP
] = sumR
;
925 dest
[i
][GCOMP
] = sumG
;
926 dest
[i
][BCOMP
] = sumB
;
927 dest
[i
][ACOMP
] = sumA
;
933 convolve_1d_constant(GLint srcWidth
, const GLfloat src
[][4],
934 GLint filterWidth
, const GLfloat filter
[][4],
936 const GLfloat borderColor
[4])
938 const GLint halfFilterWidth
= filterWidth
/ 2;
941 for (i
= 0; i
< srcWidth
; i
++) {
946 for (n
= 0; n
< filterWidth
; n
++) {
947 if (i
+ n
< halfFilterWidth
|| i
+ n
- halfFilterWidth
>= srcWidth
) {
948 sumR
+= borderColor
[RCOMP
] * filter
[n
][RCOMP
];
949 sumG
+= borderColor
[GCOMP
] * filter
[n
][GCOMP
];
950 sumB
+= borderColor
[BCOMP
] * filter
[n
][BCOMP
];
951 sumA
+= borderColor
[ACOMP
] * filter
[n
][ACOMP
];
954 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
955 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
956 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
957 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
960 dest
[i
][RCOMP
] = sumR
;
961 dest
[i
][GCOMP
] = sumG
;
962 dest
[i
][BCOMP
] = sumB
;
963 dest
[i
][ACOMP
] = sumA
;
969 convolve_1d_replicate(GLint srcWidth
, const GLfloat src
[][4],
970 GLint filterWidth
, const GLfloat filter
[][4],
973 const GLint halfFilterWidth
= filterWidth
/ 2;
976 for (i
= 0; i
< srcWidth
; i
++) {
981 for (n
= 0; n
< filterWidth
; n
++) {
982 if (i
+ n
< halfFilterWidth
) {
983 sumR
+= src
[0][RCOMP
] * filter
[n
][RCOMP
];
984 sumG
+= src
[0][GCOMP
] * filter
[n
][GCOMP
];
985 sumB
+= src
[0][BCOMP
] * filter
[n
][BCOMP
];
986 sumA
+= src
[0][ACOMP
] * filter
[n
][ACOMP
];
988 else if (i
+ n
- halfFilterWidth
>= srcWidth
) {
989 sumR
+= src
[srcWidth
- 1][RCOMP
] * filter
[n
][RCOMP
];
990 sumG
+= src
[srcWidth
- 1][GCOMP
] * filter
[n
][GCOMP
];
991 sumB
+= src
[srcWidth
- 1][BCOMP
] * filter
[n
][BCOMP
];
992 sumA
+= src
[srcWidth
- 1][ACOMP
] * filter
[n
][ACOMP
];
995 sumR
+= src
[i
+ n
- halfFilterWidth
][RCOMP
] * filter
[n
][RCOMP
];
996 sumG
+= src
[i
+ n
- halfFilterWidth
][GCOMP
] * filter
[n
][GCOMP
];
997 sumB
+= src
[i
+ n
- halfFilterWidth
][BCOMP
] * filter
[n
][BCOMP
];
998 sumA
+= src
[i
+ n
- halfFilterWidth
][ACOMP
] * filter
[n
][ACOMP
];
1001 dest
[i
][RCOMP
] = sumR
;
1002 dest
[i
][GCOMP
] = sumG
;
1003 dest
[i
][BCOMP
] = sumB
;
1004 dest
[i
][ACOMP
] = sumA
;
1010 convolve_2d_reduce(GLint srcWidth
, GLint srcHeight
,
1011 const GLfloat src
[][4],
1012 GLint filterWidth
, GLint filterHeight
,
1013 const GLfloat filter
[][4],
1016 GLint dstWidth
, dstHeight
;
1019 if (filterWidth
>= 1)
1020 dstWidth
= srcWidth
- (filterWidth
- 1);
1022 dstWidth
= srcWidth
;
1024 if (filterHeight
>= 1)
1025 dstHeight
= srcHeight
- (filterHeight
- 1);
1027 dstHeight
= srcHeight
;
1029 if (dstWidth
<= 0 || dstHeight
<= 0)
1032 for (j
= 0; j
< dstHeight
; j
++) {
1033 for (i
= 0; i
< dstWidth
; i
++) {
1038 for (m
= 0; m
< filterHeight
; m
++) {
1039 for (n
= 0; n
< filterWidth
; n
++) {
1040 const GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1041 const GLint f
= m
* filterWidth
+ n
;
1042 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1043 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1044 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1045 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1048 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1049 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1050 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1051 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1058 convolve_2d_constant(GLint srcWidth
, GLint srcHeight
,
1059 const GLfloat src
[][4],
1060 GLint filterWidth
, GLint filterHeight
,
1061 const GLfloat filter
[][4],
1063 const GLfloat borderColor
[4])
1065 const GLint halfFilterWidth
= filterWidth
/ 2;
1066 const GLint halfFilterHeight
= filterHeight
/ 2;
1069 for (j
= 0; j
< srcHeight
; j
++) {
1070 for (i
= 0; i
< srcWidth
; i
++) {
1075 for (m
= 0; m
< filterHeight
; m
++) {
1076 for (n
= 0; n
< filterWidth
; n
++) {
1077 const GLint f
= m
* filterWidth
+ n
;
1078 const GLint is
= i
+ n
- halfFilterWidth
;
1079 const GLint js
= j
+ m
- halfFilterHeight
;
1080 if (is
< 0 || is
>= srcWidth
||
1081 js
< 0 || js
>= srcHeight
) {
1082 sumR
+= borderColor
[RCOMP
] * filter
[f
][RCOMP
];
1083 sumG
+= borderColor
[GCOMP
] * filter
[f
][GCOMP
];
1084 sumB
+= borderColor
[BCOMP
] * filter
[f
][BCOMP
];
1085 sumA
+= borderColor
[ACOMP
] * filter
[f
][ACOMP
];
1088 const GLint k
= js
* srcWidth
+ is
;
1089 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1090 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1091 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1092 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1096 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1097 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1098 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1099 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1106 convolve_2d_replicate(GLint srcWidth
, GLint srcHeight
,
1107 const GLfloat src
[][4],
1108 GLint filterWidth
, GLint filterHeight
,
1109 const GLfloat filter
[][4],
1112 const GLint halfFilterWidth
= filterWidth
/ 2;
1113 const GLint halfFilterHeight
= filterHeight
/ 2;
1116 for (j
= 0; j
< srcHeight
; j
++) {
1117 for (i
= 0; i
< srcWidth
; i
++) {
1122 for (m
= 0; m
< filterHeight
; m
++) {
1123 for (n
= 0; n
< filterWidth
; n
++) {
1124 const GLint f
= m
* filterWidth
+ n
;
1125 GLint is
= i
+ n
- halfFilterWidth
;
1126 GLint js
= j
+ m
- halfFilterHeight
;
1130 else if (is
>= srcWidth
)
1134 else if (js
>= srcHeight
)
1136 k
= js
* srcWidth
+ is
;
1137 sumR
+= src
[k
][RCOMP
] * filter
[f
][RCOMP
];
1138 sumG
+= src
[k
][GCOMP
] * filter
[f
][GCOMP
];
1139 sumB
+= src
[k
][BCOMP
] * filter
[f
][BCOMP
];
1140 sumA
+= src
[k
][ACOMP
] * filter
[f
][ACOMP
];
1143 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1144 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1145 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1146 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1153 convolve_sep_reduce(GLint srcWidth
, GLint srcHeight
,
1154 const GLfloat src
[][4],
1155 GLint filterWidth
, GLint filterHeight
,
1156 const GLfloat rowFilt
[][4],
1157 const GLfloat colFilt
[][4],
1160 GLint dstWidth
, dstHeight
;
1163 if (filterWidth
>= 1)
1164 dstWidth
= srcWidth
- (filterWidth
- 1);
1166 dstWidth
= srcWidth
;
1168 if (filterHeight
>= 1)
1169 dstHeight
= srcHeight
- (filterHeight
- 1);
1171 dstHeight
= srcHeight
;
1173 if (dstWidth
<= 0 || dstHeight
<= 0)
1176 for (j
= 0; j
< dstHeight
; j
++) {
1177 for (i
= 0; i
< dstWidth
; i
++) {
1182 for (m
= 0; m
< filterHeight
; m
++) {
1183 for (n
= 0; n
< filterWidth
; n
++) {
1184 GLint k
= (j
+ m
) * srcWidth
+ i
+ n
;
1185 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1186 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1187 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1188 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1191 dest
[j
* dstWidth
+ i
][RCOMP
] = sumR
;
1192 dest
[j
* dstWidth
+ i
][GCOMP
] = sumG
;
1193 dest
[j
* dstWidth
+ i
][BCOMP
] = sumB
;
1194 dest
[j
* dstWidth
+ i
][ACOMP
] = sumA
;
1201 convolve_sep_constant(GLint srcWidth
, GLint srcHeight
,
1202 const GLfloat src
[][4],
1203 GLint filterWidth
, GLint filterHeight
,
1204 const GLfloat rowFilt
[][4],
1205 const GLfloat colFilt
[][4],
1207 const GLfloat borderColor
[4])
1209 const GLint halfFilterWidth
= filterWidth
/ 2;
1210 const GLint halfFilterHeight
= filterHeight
/ 2;
1213 for (j
= 0; j
< srcHeight
; j
++) {
1214 for (i
= 0; i
< srcWidth
; i
++) {
1219 for (m
= 0; m
< filterHeight
; m
++) {
1220 for (n
= 0; n
< filterWidth
; n
++) {
1221 const GLint is
= i
+ n
- halfFilterWidth
;
1222 const GLint js
= j
+ m
- halfFilterHeight
;
1223 if (is
< 0 || is
>= srcWidth
||
1224 js
< 0 || js
>= srcHeight
) {
1225 sumR
+= borderColor
[RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1226 sumG
+= borderColor
[GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1227 sumB
+= borderColor
[BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1228 sumA
+= borderColor
[ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1231 GLint k
= js
* srcWidth
+ is
;
1232 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1233 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1234 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1235 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1240 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1241 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1242 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1243 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1250 convolve_sep_replicate(GLint srcWidth
, GLint srcHeight
,
1251 const GLfloat src
[][4],
1252 GLint filterWidth
, GLint filterHeight
,
1253 const GLfloat rowFilt
[][4],
1254 const GLfloat colFilt
[][4],
1257 const GLint halfFilterWidth
= filterWidth
/ 2;
1258 const GLint halfFilterHeight
= filterHeight
/ 2;
1261 for (j
= 0; j
< srcHeight
; j
++) {
1262 for (i
= 0; i
< srcWidth
; i
++) {
1267 for (m
= 0; m
< filterHeight
; m
++) {
1268 for (n
= 0; n
< filterWidth
; n
++) {
1269 GLint is
= i
+ n
- halfFilterWidth
;
1270 GLint js
= j
+ m
- halfFilterHeight
;
1274 else if (is
>= srcWidth
)
1278 else if (js
>= srcHeight
)
1280 k
= js
* srcWidth
+ is
;
1281 sumR
+= src
[k
][RCOMP
] * rowFilt
[n
][RCOMP
] * colFilt
[m
][RCOMP
];
1282 sumG
+= src
[k
][GCOMP
] * rowFilt
[n
][GCOMP
] * colFilt
[m
][GCOMP
];
1283 sumB
+= src
[k
][BCOMP
] * rowFilt
[n
][BCOMP
] * colFilt
[m
][BCOMP
];
1284 sumA
+= src
[k
][ACOMP
] * rowFilt
[n
][ACOMP
] * colFilt
[m
][ACOMP
];
1287 dest
[j
* srcWidth
+ i
][RCOMP
] = sumR
;
1288 dest
[j
* srcWidth
+ i
][GCOMP
] = sumG
;
1289 dest
[j
* srcWidth
+ i
][BCOMP
] = sumB
;
1290 dest
[j
* srcWidth
+ i
][ACOMP
] = sumA
;
1298 _mesa_convolve_1d_image(const GLcontext
*ctx
, GLsizei
*width
,
1299 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1301 switch (ctx
->Pixel
.ConvolutionBorderMode
[0]) {
1303 convolve_1d_reduce(*width
, (const GLfloat (*)[4]) srcImage
,
1304 ctx
->Convolution1D
.Width
,
1305 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1306 (GLfloat (*)[4]) dstImage
);
1307 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1309 case GL_CONSTANT_BORDER
:
1310 convolve_1d_constant(*width
, (const GLfloat (*)[4]) srcImage
,
1311 ctx
->Convolution1D
.Width
,
1312 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1313 (GLfloat (*)[4]) dstImage
,
1314 ctx
->Pixel
.ConvolutionBorderColor
[0]);
1316 case GL_REPLICATE_BORDER
:
1317 convolve_1d_replicate(*width
, (const GLfloat (*)[4]) srcImage
,
1318 ctx
->Convolution1D
.Width
,
1319 (const GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
1320 (GLfloat (*)[4]) dstImage
);
1329 _mesa_convolve_2d_image(const GLcontext
*ctx
, GLsizei
*width
, GLsizei
*height
,
1330 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1332 switch (ctx
->Pixel
.ConvolutionBorderMode
[1]) {
1334 convolve_2d_reduce(*width
, *height
,
1335 (const GLfloat (*)[4]) srcImage
,
1336 ctx
->Convolution2D
.Width
,
1337 ctx
->Convolution2D
.Height
,
1338 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1339 (GLfloat (*)[4]) dstImage
);
1340 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1341 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1343 case GL_CONSTANT_BORDER
:
1344 convolve_2d_constant(*width
, *height
,
1345 (const GLfloat (*)[4]) srcImage
,
1346 ctx
->Convolution2D
.Width
,
1347 ctx
->Convolution2D
.Height
,
1348 (const GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
1349 (GLfloat (*)[4]) dstImage
,
1350 ctx
->Pixel
.ConvolutionBorderColor
[1]);
1352 case GL_REPLICATE_BORDER
:
1353 convolve_2d_replicate(*width
, *height
,
1354 (const GLfloat (*)[4]) srcImage
,
1355 ctx
->Convolution2D
.Width
,
1356 ctx
->Convolution2D
.Height
,
1357 (const GLfloat (*)[4])ctx
->Convolution2D
.Filter
,
1358 (GLfloat (*)[4]) dstImage
);
1367 _mesa_convolve_sep_image(const GLcontext
*ctx
,
1368 GLsizei
*width
, GLsizei
*height
,
1369 const GLfloat
*srcImage
, GLfloat
*dstImage
)
1371 const GLfloat
*rowFilter
= ctx
->Separable2D
.Filter
;
1372 const GLfloat
*colFilter
= rowFilter
+ 4 * MAX_CONVOLUTION_WIDTH
;
1374 switch (ctx
->Pixel
.ConvolutionBorderMode
[2]) {
1376 convolve_sep_reduce(*width
, *height
,
1377 (const GLfloat (*)[4]) srcImage
,
1378 ctx
->Separable2D
.Width
,
1379 ctx
->Separable2D
.Height
,
1380 (const GLfloat (*)[4]) rowFilter
,
1381 (const GLfloat (*)[4]) colFilter
,
1382 (GLfloat (*)[4]) dstImage
);
1383 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1384 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1386 case GL_CONSTANT_BORDER
:
1387 convolve_sep_constant(*width
, *height
,
1388 (const GLfloat (*)[4]) srcImage
,
1389 ctx
->Separable2D
.Width
,
1390 ctx
->Separable2D
.Height
,
1391 (const GLfloat (*)[4]) rowFilter
,
1392 (const GLfloat (*)[4]) colFilter
,
1393 (GLfloat (*)[4]) dstImage
,
1394 ctx
->Pixel
.ConvolutionBorderColor
[2]);
1396 case GL_REPLICATE_BORDER
:
1397 convolve_sep_replicate(*width
, *height
,
1398 (const GLfloat (*)[4]) srcImage
,
1399 ctx
->Separable2D
.Width
,
1400 ctx
->Separable2D
.Height
,
1401 (const GLfloat (*)[4]) rowFilter
,
1402 (const GLfloat (*)[4]) colFilter
,
1403 (GLfloat (*)[4]) dstImage
);
1413 * This function computes an image's size after convolution.
1414 * If the convolution border mode is GL_REDUCE, the post-convolution
1415 * image will be smaller than the original.
1418 _mesa_adjust_image_for_convolution(const GLcontext
*ctx
, GLuint dimensions
,
1419 GLsizei
*width
, GLsizei
*height
)
1421 if (ctx
->Pixel
.Convolution1DEnabled
1423 && ctx
->Pixel
.ConvolutionBorderMode
[0] == GL_REDUCE
) {
1424 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1426 else if (ctx
->Pixel
.Convolution2DEnabled
1428 && ctx
->Pixel
.ConvolutionBorderMode
[1] == GL_REDUCE
) {
1429 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1430 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1432 else if (ctx
->Pixel
.Separable2DEnabled
1434 && ctx
->Pixel
.ConvolutionBorderMode
[2] == GL_REDUCE
) {
1435 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1436 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1442 _mesa_init_convolve_dispatch(struct _glapi_table
*disp
)
1444 SET_ConvolutionFilter1D(disp
, _mesa_ConvolutionFilter1D
);
1445 SET_ConvolutionFilter2D(disp
, _mesa_ConvolutionFilter2D
);
1446 SET_ConvolutionParameterf(disp
, _mesa_ConvolutionParameterf
);
1447 SET_ConvolutionParameterfv(disp
, _mesa_ConvolutionParameterfv
);
1448 SET_ConvolutionParameteri(disp
, _mesa_ConvolutionParameteri
);
1449 SET_ConvolutionParameteriv(disp
, _mesa_ConvolutionParameteriv
);
1450 SET_CopyConvolutionFilter1D(disp
, _mesa_CopyConvolutionFilter1D
);
1451 SET_CopyConvolutionFilter2D(disp
, _mesa_CopyConvolutionFilter2D
);
1452 SET_GetConvolutionFilter(disp
, _mesa_GetConvolutionFilter
);
1453 SET_GetConvolutionParameterfv(disp
, _mesa_GetConvolutionParameterfv
);
1454 SET_GetConvolutionParameteriv(disp
, _mesa_GetConvolutionParameteriv
);
1455 SET_SeparableFilter2D(disp
, _mesa_SeparableFilter2D
);
1456 SET_GetSeparableFilter(disp
, _mesa_GetSeparableFilter
);
1460 #endif /* FEATURE_convolve */