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"
43 #include "glapi/dispatch.h"
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
);
116 if (target
!= GL_CONVOLUTION_1D
) {
117 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(target)");
121 baseFormat
= base_filter_format(internalFormat
);
122 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
123 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(internalFormat)");
127 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
128 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter1D(width)");
132 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
133 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter1D(format or type)");
137 if (format
== GL_COLOR_INDEX
||
138 format
== GL_STENCIL_INDEX
||
139 format
== GL_DEPTH_COMPONENT
||
140 format
== GL_INTENSITY
||
142 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter1D(format or type)");
146 ctx
->Convolution1D
.Format
= format
;
147 ctx
->Convolution1D
.InternalFormat
= internalFormat
;
148 ctx
->Convolution1D
.Width
= width
;
149 ctx
->Convolution1D
.Height
= 1;
151 image
= _mesa_map_validate_pbo_source(ctx
,
152 1, &ctx
->Unpack
, width
, 1, 1,
154 "glConvolutionFilter1D");
158 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
,
159 ctx
->Convolution1D
.Filter
,
160 format
, type
, image
, &ctx
->Unpack
,
161 0); /* transferOps */
163 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
165 _mesa_scale_and_bias_rgba(width
,
166 (GLfloat (*)[4]) ctx
->Convolution1D
.Filter
,
167 ctx
->Pixel
.ConvolutionFilterScale
[0][0],
168 ctx
->Pixel
.ConvolutionFilterScale
[0][1],
169 ctx
->Pixel
.ConvolutionFilterScale
[0][2],
170 ctx
->Pixel
.ConvolutionFilterScale
[0][3],
171 ctx
->Pixel
.ConvolutionFilterBias
[0][0],
172 ctx
->Pixel
.ConvolutionFilterBias
[0][1],
173 ctx
->Pixel
.ConvolutionFilterBias
[0][2],
174 ctx
->Pixel
.ConvolutionFilterBias
[0][3]);
176 ctx
->NewState
|= _NEW_PIXEL
;
181 _mesa_ConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*image
)
185 GET_CURRENT_CONTEXT(ctx
);
186 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
188 if (target
!= GL_CONVOLUTION_2D
) {
189 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(target)");
193 baseFormat
= base_filter_format(internalFormat
);
194 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
195 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(internalFormat)");
199 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
200 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(width)");
203 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
204 _mesa_error(ctx
, GL_INVALID_VALUE
, "glConvolutionFilter2D(height)");
208 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
209 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glConvolutionFilter2D(format or type)");
212 if (format
== GL_COLOR_INDEX
||
213 format
== GL_STENCIL_INDEX
||
214 format
== GL_DEPTH_COMPONENT
||
215 format
== GL_INTENSITY
||
217 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionFilter2D(format or type)");
221 /* this should have been caught earlier */
222 assert(_mesa_components_in_format(format
));
224 ctx
->Convolution2D
.Format
= format
;
225 ctx
->Convolution2D
.InternalFormat
= internalFormat
;
226 ctx
->Convolution2D
.Width
= width
;
227 ctx
->Convolution2D
.Height
= height
;
229 image
= _mesa_map_validate_pbo_source(ctx
,
230 2, &ctx
->Unpack
, width
, height
, 1,
232 "glConvolutionFilter2D");
236 /* Unpack filter image. We always store filters in RGBA format. */
237 for (i
= 0; i
< height
; i
++) {
238 const GLvoid
*src
= _mesa_image_address2d(&ctx
->Unpack
, image
, width
,
239 height
, format
, type
, i
, 0);
240 GLfloat
*dst
= ctx
->Convolution2D
.Filter
+ i
* width
* 4;
241 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, dst
,
242 format
, type
, src
, &ctx
->Unpack
,
243 0); /* transferOps */
246 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
248 _mesa_scale_and_bias_rgba(width
* height
,
249 (GLfloat (*)[4]) ctx
->Convolution2D
.Filter
,
250 ctx
->Pixel
.ConvolutionFilterScale
[1][0],
251 ctx
->Pixel
.ConvolutionFilterScale
[1][1],
252 ctx
->Pixel
.ConvolutionFilterScale
[1][2],
253 ctx
->Pixel
.ConvolutionFilterScale
[1][3],
254 ctx
->Pixel
.ConvolutionFilterBias
[1][0],
255 ctx
->Pixel
.ConvolutionFilterBias
[1][1],
256 ctx
->Pixel
.ConvolutionFilterBias
[1][2],
257 ctx
->Pixel
.ConvolutionFilterBias
[1][3]);
259 ctx
->NewState
|= _NEW_PIXEL
;
263 static void GLAPIENTRY
264 _mesa_ConvolutionParameterf(GLenum target
, GLenum pname
, GLfloat param
)
266 GET_CURRENT_CONTEXT(ctx
);
268 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
271 case GL_CONVOLUTION_1D
:
274 case GL_CONVOLUTION_2D
:
277 case GL_SEPARABLE_2D
:
281 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(target)");
286 case GL_CONVOLUTION_BORDER_MODE
:
287 if (param
== (GLfloat
) GL_REDUCE
||
288 param
== (GLfloat
) GL_CONSTANT_BORDER
||
289 param
== (GLfloat
) GL_REPLICATE_BORDER
) {
290 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
293 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(params)");
298 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterf(pname)");
302 ctx
->NewState
|= _NEW_PIXEL
;
306 static void GLAPIENTRY
307 _mesa_ConvolutionParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
309 GET_CURRENT_CONTEXT(ctx
);
311 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
314 case GL_CONVOLUTION_1D
:
317 case GL_CONVOLUTION_2D
:
320 case GL_SEPARABLE_2D
:
324 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(target)");
329 case GL_CONVOLUTION_BORDER_COLOR
:
330 COPY_4V(ctx
->Pixel
.ConvolutionBorderColor
[c
], params
);
332 case GL_CONVOLUTION_BORDER_MODE
:
333 if (params
[0] == (GLfloat
) GL_REDUCE
||
334 params
[0] == (GLfloat
) GL_CONSTANT_BORDER
||
335 params
[0] == (GLfloat
) GL_REPLICATE_BORDER
) {
336 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
339 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(params)");
343 case GL_CONVOLUTION_FILTER_SCALE
:
344 COPY_4V(ctx
->Pixel
.ConvolutionFilterScale
[c
], params
);
346 case GL_CONVOLUTION_FILTER_BIAS
:
347 COPY_4V(ctx
->Pixel
.ConvolutionFilterBias
[c
], params
);
350 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameterfv(pname)");
354 ctx
->NewState
|= _NEW_PIXEL
;
358 static void GLAPIENTRY
359 _mesa_ConvolutionParameteri(GLenum target
, GLenum pname
, GLint param
)
361 GET_CURRENT_CONTEXT(ctx
);
363 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
366 case GL_CONVOLUTION_1D
:
369 case GL_CONVOLUTION_2D
:
372 case GL_SEPARABLE_2D
:
376 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(target)");
381 case GL_CONVOLUTION_BORDER_MODE
:
382 if (param
== (GLint
) GL_REDUCE
||
383 param
== (GLint
) GL_CONSTANT_BORDER
||
384 param
== (GLint
) GL_REPLICATE_BORDER
) {
385 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) param
;
388 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(params)");
393 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteri(pname)");
397 ctx
->NewState
|= _NEW_PIXEL
;
401 static void GLAPIENTRY
402 _mesa_ConvolutionParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
404 GET_CURRENT_CONTEXT(ctx
);
406 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
409 case GL_CONVOLUTION_1D
:
412 case GL_CONVOLUTION_2D
:
415 case GL_SEPARABLE_2D
:
419 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(target)");
424 case GL_CONVOLUTION_BORDER_COLOR
:
425 ctx
->Pixel
.ConvolutionBorderColor
[c
][0] = INT_TO_FLOAT(params
[0]);
426 ctx
->Pixel
.ConvolutionBorderColor
[c
][1] = INT_TO_FLOAT(params
[1]);
427 ctx
->Pixel
.ConvolutionBorderColor
[c
][2] = INT_TO_FLOAT(params
[2]);
428 ctx
->Pixel
.ConvolutionBorderColor
[c
][3] = INT_TO_FLOAT(params
[3]);
430 case GL_CONVOLUTION_BORDER_MODE
:
431 if (params
[0] == (GLint
) GL_REDUCE
||
432 params
[0] == (GLint
) GL_CONSTANT_BORDER
||
433 params
[0] == (GLint
) GL_REPLICATE_BORDER
) {
434 ctx
->Pixel
.ConvolutionBorderMode
[c
] = (GLenum
) params
[0];
437 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(params)");
441 case GL_CONVOLUTION_FILTER_SCALE
:
442 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
443 /* need cast to prevent compiler warnings */
444 ctx
->Pixel
.ConvolutionFilterScale
[c
][0] = (GLfloat
) params
[0];
445 ctx
->Pixel
.ConvolutionFilterScale
[c
][1] = (GLfloat
) params
[1];
446 ctx
->Pixel
.ConvolutionFilterScale
[c
][2] = (GLfloat
) params
[2];
447 ctx
->Pixel
.ConvolutionFilterScale
[c
][3] = (GLfloat
) params
[3];
449 case GL_CONVOLUTION_FILTER_BIAS
:
450 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
451 /* need cast to prevent compiler warnings */
452 ctx
->Pixel
.ConvolutionFilterBias
[c
][0] = (GLfloat
) params
[0];
453 ctx
->Pixel
.ConvolutionFilterBias
[c
][1] = (GLfloat
) params
[1];
454 ctx
->Pixel
.ConvolutionFilterBias
[c
][2] = (GLfloat
) params
[2];
455 ctx
->Pixel
.ConvolutionFilterBias
[c
][3] = (GLfloat
) params
[3];
458 _mesa_error(ctx
, GL_INVALID_ENUM
, "glConvolutionParameteriv(pname)");
462 ctx
->NewState
|= _NEW_PIXEL
;
466 static void GLAPIENTRY
467 _mesa_CopyConvolutionFilter1D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
)
470 GET_CURRENT_CONTEXT(ctx
);
471 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
473 if (target
!= GL_CONVOLUTION_1D
) {
474 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(target)");
478 baseFormat
= base_filter_format(internalFormat
);
479 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
480 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter1D(internalFormat)");
484 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
485 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter1D(width)");
489 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
490 return; /* no readbuffer - OK */
493 ctx
->Driver
.CopyConvolutionFilter1D( ctx
, target
,
494 internalFormat
, x
, y
, width
);
498 static void GLAPIENTRY
499 _mesa_CopyConvolutionFilter2D(GLenum target
, GLenum internalFormat
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
502 GET_CURRENT_CONTEXT(ctx
);
503 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
505 if (target
!= GL_CONVOLUTION_2D
) {
506 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(target)");
510 baseFormat
= base_filter_format(internalFormat
);
511 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
512 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyConvolutionFilter2D(internalFormat)");
516 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
517 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(width)");
520 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
521 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCopyConvolutionFilter2D(height)");
525 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
526 return; /* no readbuffer - OK */
529 ctx
->Driver
.CopyConvolutionFilter2D( ctx
, target
, internalFormat
, x
, y
,
534 static void GLAPIENTRY
535 _mesa_GetConvolutionFilter(GLenum target
, GLenum format
, GLenum type
,
538 struct gl_convolution_attrib
*filter
;
540 GET_CURRENT_CONTEXT(ctx
);
541 ASSERT_OUTSIDE_BEGIN_END(ctx
);
544 _mesa_update_state(ctx
);
547 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
548 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetConvolutionFilter(format or type)");
552 if (format
== GL_COLOR_INDEX
||
553 format
== GL_STENCIL_INDEX
||
554 format
== GL_DEPTH_COMPONENT
||
555 format
== GL_INTENSITY
||
557 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
562 case GL_CONVOLUTION_1D
:
563 filter
= &(ctx
->Convolution1D
);
565 case GL_CONVOLUTION_2D
:
566 filter
= &(ctx
->Convolution2D
);
569 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(target)");
573 image
= _mesa_map_validate_pbo_dest(ctx
, 2, &ctx
->Pack
,
574 filter
->Width
, filter
->Height
, 1,
576 "glGetConvolutionFilter");
580 for (row
= 0; row
< filter
->Height
; row
++) {
581 GLvoid
*dst
= _mesa_image_address2d(&ctx
->Pack
, image
, filter
->Width
,
582 filter
->Height
, format
, type
,
584 GLfloat (*src
)[4] = (GLfloat (*)[4]) (filter
->Filter
+ row
* filter
->Width
* 4);
585 _mesa_pack_rgba_span_float(ctx
, filter
->Width
, src
,
586 format
, type
, dst
, &ctx
->Pack
, 0x0);
589 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
593 static void GLAPIENTRY
594 _mesa_GetConvolutionParameterfv(GLenum target
, GLenum pname
, GLfloat
*params
)
596 GET_CURRENT_CONTEXT(ctx
);
597 const struct gl_convolution_attrib
*conv
;
599 ASSERT_OUTSIDE_BEGIN_END(ctx
);
602 case GL_CONVOLUTION_1D
:
604 conv
= &ctx
->Convolution1D
;
606 case GL_CONVOLUTION_2D
:
608 conv
= &ctx
->Convolution2D
;
610 case GL_SEPARABLE_2D
:
612 conv
= &ctx
->Separable2D
;
615 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(target)");
620 case GL_CONVOLUTION_BORDER_COLOR
:
621 COPY_4V(params
, ctx
->Pixel
.ConvolutionBorderColor
[c
]);
623 case GL_CONVOLUTION_BORDER_MODE
:
624 *params
= (GLfloat
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
626 case GL_CONVOLUTION_FILTER_SCALE
:
627 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterScale
[c
]);
629 case GL_CONVOLUTION_FILTER_BIAS
:
630 COPY_4V(params
, ctx
->Pixel
.ConvolutionFilterBias
[c
]);
632 case GL_CONVOLUTION_FORMAT
:
633 *params
= (GLfloat
) conv
->Format
;
635 case GL_CONVOLUTION_WIDTH
:
636 *params
= (GLfloat
) conv
->Width
;
638 case GL_CONVOLUTION_HEIGHT
:
639 *params
= (GLfloat
) conv
->Height
;
641 case GL_MAX_CONVOLUTION_WIDTH
:
642 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionWidth
;
644 case GL_MAX_CONVOLUTION_HEIGHT
:
645 *params
= (GLfloat
) ctx
->Const
.MaxConvolutionHeight
;
648 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameterfv(pname)");
654 static void GLAPIENTRY
655 _mesa_GetConvolutionParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
657 GET_CURRENT_CONTEXT(ctx
);
658 const struct gl_convolution_attrib
*conv
;
660 ASSERT_OUTSIDE_BEGIN_END(ctx
);
663 case GL_CONVOLUTION_1D
:
665 conv
= &ctx
->Convolution1D
;
667 case GL_CONVOLUTION_2D
:
669 conv
= &ctx
->Convolution2D
;
671 case GL_SEPARABLE_2D
:
673 conv
= &ctx
->Separable2D
;
676 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(target)");
681 case GL_CONVOLUTION_BORDER_COLOR
:
682 params
[0] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][0]);
683 params
[1] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][1]);
684 params
[2] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][2]);
685 params
[3] = FLOAT_TO_INT(ctx
->Pixel
.ConvolutionBorderColor
[c
][3]);
687 case GL_CONVOLUTION_BORDER_MODE
:
688 *params
= (GLint
) ctx
->Pixel
.ConvolutionBorderMode
[c
];
690 case GL_CONVOLUTION_FILTER_SCALE
:
691 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][0];
692 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][1];
693 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][2];
694 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterScale
[c
][3];
696 case GL_CONVOLUTION_FILTER_BIAS
:
697 params
[0] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][0];
698 params
[1] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][1];
699 params
[2] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][2];
700 params
[3] = (GLint
) ctx
->Pixel
.ConvolutionFilterBias
[c
][3];
702 case GL_CONVOLUTION_FORMAT
:
703 *params
= (GLint
) conv
->Format
;
705 case GL_CONVOLUTION_WIDTH
:
706 *params
= (GLint
) conv
->Width
;
708 case GL_CONVOLUTION_HEIGHT
:
709 *params
= (GLint
) conv
->Height
;
711 case GL_MAX_CONVOLUTION_WIDTH
:
712 *params
= (GLint
) ctx
->Const
.MaxConvolutionWidth
;
714 case GL_MAX_CONVOLUTION_HEIGHT
:
715 *params
= (GLint
) ctx
->Const
.MaxConvolutionHeight
;
718 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionParameteriv(pname)");
724 static void GLAPIENTRY
725 _mesa_GetSeparableFilter(GLenum target
, GLenum format
, GLenum type
,
726 GLvoid
*row
, GLvoid
*column
, GLvoid
*span
)
728 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
729 struct gl_convolution_attrib
*filter
;
730 GET_CURRENT_CONTEXT(ctx
);
731 ASSERT_OUTSIDE_BEGIN_END(ctx
);
734 _mesa_update_state(ctx
);
737 if (target
!= GL_SEPARABLE_2D
) {
738 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetSeparableFilter(target)");
742 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
743 _mesa_error(ctx
, GL_INVALID_OPERATION
,
744 "glGetConvolutionFilter(format or type)");
748 if (format
== GL_COLOR_INDEX
||
749 format
== GL_STENCIL_INDEX
||
750 format
== GL_DEPTH_COMPONENT
||
751 format
== GL_INTENSITY
||
753 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetConvolutionFilter(format or type)");
757 filter
= &ctx
->Separable2D
;
760 row
= _mesa_map_validate_pbo_dest(ctx
, 1, &ctx
->Pack
,
763 "glGetConvolutionFilter");
765 GLvoid
*dst
= _mesa_image_address1d(&ctx
->Pack
, row
, filter
->Width
,
767 _mesa_pack_rgba_span_float(ctx
, filter
->Width
,
768 (GLfloat (*)[4]) filter
->Filter
,
769 format
, type
, dst
, &ctx
->Pack
, 0x0);
770 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
773 /* get column filter */
774 column
= _mesa_map_validate_pbo_dest(ctx
, 1, &ctx
->Pack
,
775 filter
->Height
, 1, 1,
776 format
, type
, column
,
777 "glGetConvolutionFilter");
779 GLvoid
*dst
= _mesa_image_address1d(&ctx
->Pack
, column
, filter
->Height
,
781 GLfloat (*src
)[4] = (GLfloat (*)[4]) (filter
->Filter
+ colStart
);
782 _mesa_pack_rgba_span_float(ctx
, filter
->Height
, src
,
783 format
, type
, dst
, &ctx
->Pack
, 0x0);
784 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
787 (void) span
; /* unused at this time */
791 static void GLAPIENTRY
792 _mesa_SeparableFilter2D(GLenum target
, GLenum internalFormat
, GLsizei width
, GLsizei height
, GLenum format
, GLenum type
, const GLvoid
*row
, const GLvoid
*column
)
794 const GLint colStart
= MAX_CONVOLUTION_WIDTH
* 4;
796 GET_CURRENT_CONTEXT(ctx
);
797 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
799 if (target
!= GL_SEPARABLE_2D
) {
800 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(target)");
804 baseFormat
= base_filter_format(internalFormat
);
805 if (baseFormat
< 0 || baseFormat
== GL_COLOR_INDEX
) {
806 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(internalFormat)");
810 if (width
< 0 || width
> MAX_CONVOLUTION_WIDTH
) {
811 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(width)");
814 if (height
< 0 || height
> MAX_CONVOLUTION_HEIGHT
) {
815 _mesa_error(ctx
, GL_INVALID_VALUE
, "glSeparableFilter2D(height)");
819 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
820 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSeparableFilter2D(format or type)");
824 if (format
== GL_COLOR_INDEX
||
825 format
== GL_STENCIL_INDEX
||
826 format
== GL_DEPTH_COMPONENT
||
827 format
== GL_INTENSITY
||
829 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSeparableFilter2D(format or type)");
833 ctx
->Separable2D
.Format
= format
;
834 ctx
->Separable2D
.InternalFormat
= internalFormat
;
835 ctx
->Separable2D
.Width
= width
;
836 ctx
->Separable2D
.Height
= height
;
838 /* unpack row filter */
839 row
= _mesa_map_validate_pbo_source(ctx
, 1, &ctx
->Unpack
,
842 "glSeparableFilter2D");
844 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
,
845 ctx
->Separable2D
.Filter
,
846 format
, type
, row
, &ctx
->Unpack
,
847 0x0); /* transferOps */
848 _mesa_scale_and_bias_rgba(width
,
849 (GLfloat (*)[4]) ctx
->Separable2D
.Filter
,
850 ctx
->Pixel
.ConvolutionFilterScale
[2][0],
851 ctx
->Pixel
.ConvolutionFilterScale
[2][1],
852 ctx
->Pixel
.ConvolutionFilterScale
[2][2],
853 ctx
->Pixel
.ConvolutionFilterScale
[2][3],
854 ctx
->Pixel
.ConvolutionFilterBias
[2][0],
855 ctx
->Pixel
.ConvolutionFilterBias
[2][1],
856 ctx
->Pixel
.ConvolutionFilterBias
[2][2],
857 ctx
->Pixel
.ConvolutionFilterBias
[2][3]);
858 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
861 /* unpack column filter */
862 column
= _mesa_map_validate_pbo_source(ctx
, 1, &ctx
->Unpack
,
864 format
, type
, column
,
865 "glSeparableFilter2D");
867 _mesa_unpack_color_span_float(ctx
, height
, GL_RGBA
,
868 &ctx
->Separable2D
.Filter
[colStart
],
869 format
, type
, column
, &ctx
->Unpack
,
870 0); /* transferOps */
872 _mesa_scale_and_bias_rgba(height
,
873 (GLfloat (*)[4]) (ctx
->Separable2D
.Filter
+ colStart
),
874 ctx
->Pixel
.ConvolutionFilterScale
[2][0],
875 ctx
->Pixel
.ConvolutionFilterScale
[2][1],
876 ctx
->Pixel
.ConvolutionFilterScale
[2][2],
877 ctx
->Pixel
.ConvolutionFilterScale
[2][3],
878 ctx
->Pixel
.ConvolutionFilterBias
[2][0],
879 ctx
->Pixel
.ConvolutionFilterBias
[2][1],
880 ctx
->Pixel
.ConvolutionFilterBias
[2][2],
881 ctx
->Pixel
.ConvolutionFilterBias
[2][3]);
882 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
885 if (_mesa_is_bufferobj(ctx
->Unpack
.BufferObj
)) {
886 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
887 ctx
->Unpack
.BufferObj
);
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
);
1414 * This function computes an image's size after convolution.
1415 * If the convolution border mode is GL_REDUCE, the post-convolution
1416 * image will be smaller than the original.
1419 _mesa_adjust_image_for_convolution(const GLcontext
*ctx
, GLuint dimensions
,
1420 GLsizei
*width
, GLsizei
*height
)
1422 if (ctx
->Pixel
.Convolution1DEnabled
1424 && ctx
->Pixel
.ConvolutionBorderMode
[0] == GL_REDUCE
) {
1425 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
1427 else if (ctx
->Pixel
.Convolution2DEnabled
1429 && ctx
->Pixel
.ConvolutionBorderMode
[1] == GL_REDUCE
) {
1430 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
1431 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
1433 else if (ctx
->Pixel
.Separable2DEnabled
1435 && ctx
->Pixel
.ConvolutionBorderMode
[2] == GL_REDUCE
) {
1436 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
1437 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
1443 _mesa_init_convolve_dispatch(struct _glapi_table
*disp
)
1445 SET_ConvolutionFilter1D(disp
, _mesa_ConvolutionFilter1D
);
1446 SET_ConvolutionFilter2D(disp
, _mesa_ConvolutionFilter2D
);
1447 SET_ConvolutionParameterf(disp
, _mesa_ConvolutionParameterf
);
1448 SET_ConvolutionParameterfv(disp
, _mesa_ConvolutionParameterfv
);
1449 SET_ConvolutionParameteri(disp
, _mesa_ConvolutionParameteri
);
1450 SET_ConvolutionParameteriv(disp
, _mesa_ConvolutionParameteriv
);
1451 SET_CopyConvolutionFilter1D(disp
, _mesa_CopyConvolutionFilter1D
);
1452 SET_CopyConvolutionFilter2D(disp
, _mesa_CopyConvolutionFilter2D
);
1453 SET_GetConvolutionFilter(disp
, _mesa_GetConvolutionFilter
);
1454 SET_GetConvolutionParameterfv(disp
, _mesa_GetConvolutionParameterfv
);
1455 SET_GetConvolutionParameteriv(disp
, _mesa_GetConvolutionParameteriv
);
1456 SET_SeparableFilter2D(disp
, _mesa_SeparableFilter2D
);
1457 SET_GetSeparableFilter(disp
, _mesa_GetSeparableFilter
);
1461 #endif /* FEATURE_convolve */