blob: b7d2eeb20f9046efcc87bad5c166ad31786b2ecd [file] [log] [blame]
Brian Paulcc8e37f2000-07-12 13:00:09 +00001
2/*
3 * Mesa 3-D graphics library
Brian Paul3c634522002-10-24 23:57:19 +00004 * Version: 4.1
Brian Paulcc8e37f2000-07-12 13:00:09 +00005 *
Brian Pauld0570642002-03-19 15:22:50 +00006 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
Brian Paulcc8e37f2000-07-12 13:00:09 +00007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27/*
28 * Image convolution functions.
29 *
30 * Notes: filter kernel elements are indexed by <n> and <m> as in
31 * the GL spec.
32 */
33
34
Brian Paulcc8e37f2000-07-12 13:00:09 +000035#include "glheader.h"
Brian Paulc893a012000-10-28 20:41:13 +000036#include "colormac.h"
Brian Pauld4b799b2000-08-21 14:24:30 +000037#include "convolve.h"
38#include "context.h"
Brian Paul147b0832000-08-23 14:31:25 +000039#include "image.h"
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000040#include "mtypes.h"
Jon Taylorcdfba5d2000-11-23 02:50:56 +000041#include "state.h"
Brian Paulcc8e37f2000-07-12 13:00:09 +000042
43
Brian Paul147b0832000-08-23 14:31:25 +000044/*
45 * Given an internalFormat token passed to glConvolutionFilter
46 * or glSeparableFilter, return the corresponding base format.
47 * Return -1 if invalid token.
48 */
49static GLint
50base_filter_format( GLenum format )
51{
52 switch (format) {
53 case GL_ALPHA:
54 case GL_ALPHA4:
55 case GL_ALPHA8:
56 case GL_ALPHA12:
57 case GL_ALPHA16:
58 return GL_ALPHA;
59 case GL_LUMINANCE:
60 case GL_LUMINANCE4:
61 case GL_LUMINANCE8:
62 case GL_LUMINANCE12:
63 case GL_LUMINANCE16:
64 return GL_LUMINANCE;
65 case GL_LUMINANCE_ALPHA:
66 case GL_LUMINANCE4_ALPHA4:
67 case GL_LUMINANCE6_ALPHA2:
68 case GL_LUMINANCE8_ALPHA8:
69 case GL_LUMINANCE12_ALPHA4:
70 case GL_LUMINANCE12_ALPHA12:
71 case GL_LUMINANCE16_ALPHA16:
72 return GL_LUMINANCE_ALPHA;
73 case GL_INTENSITY:
74 case GL_INTENSITY4:
75 case GL_INTENSITY8:
76 case GL_INTENSITY12:
77 case GL_INTENSITY16:
78 return GL_INTENSITY;
79 case GL_RGB:
80 case GL_R3_G3_B2:
81 case GL_RGB4:
82 case GL_RGB5:
83 case GL_RGB8:
84 case GL_RGB10:
85 case GL_RGB12:
86 case GL_RGB16:
87 return GL_RGB;
88 case 4:
89 case GL_RGBA:
90 case GL_RGBA2:
91 case GL_RGBA4:
92 case GL_RGB5_A1:
93 case GL_RGBA8:
94 case GL_RGB10_A2:
95 case GL_RGBA12:
96 case GL_RGBA16:
97 return GL_RGBA;
98 default:
99 return -1; /* error */
100 }
101}
102
103
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000104void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000105_mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *image)
106{
Brian Pauld0570642002-03-19 15:22:50 +0000107 GLint baseFormat;
Brian Paul147b0832000-08-23 14:31:25 +0000108 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000109 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000110
111 if (target != GL_CONVOLUTION_1D) {
Brian Paul08836342001-03-03 20:33:27 +0000112 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000113 return;
114 }
115
116 baseFormat = base_filter_format(internalFormat);
117 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000118 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000119 return;
120 }
121
122 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000123 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter1D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000124 return;
125 }
126
Brian Paul90f042a2000-12-10 19:23:19 +0000127 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000128 _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000129 return;
130 }
131
132 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000133 format == GL_STENCIL_INDEX ||
134 format == GL_DEPTH_COMPONENT ||
135 format == GL_INTENSITY ||
136 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000137 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000138 return;
139 }
140
141 ctx->Convolution1D.Format = format;
142 ctx->Convolution1D.InternalFormat = internalFormat;
143 ctx->Convolution1D.Width = width;
144 ctx->Convolution1D.Height = 1;
145
146 /* unpack filter image */
147 _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
148 ctx->Convolution1D.Filter,
149 format, type, image, &ctx->Unpack,
150 0, GL_FALSE);
151
152 /* apply scale and bias */
153 {
154 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[0];
155 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[0];
156 GLint i;
157 for (i = 0; i < width; i++) {
158 GLfloat r = ctx->Convolution1D.Filter[i * 4 + 0];
159 GLfloat g = ctx->Convolution1D.Filter[i * 4 + 1];
160 GLfloat b = ctx->Convolution1D.Filter[i * 4 + 2];
161 GLfloat a = ctx->Convolution1D.Filter[i * 4 + 3];
162 r = r * scale[0] + bias[0];
163 g = g * scale[1] + bias[1];
164 b = b * scale[2] + bias[2];
165 a = a * scale[3] + bias[3];
166 ctx->Convolution1D.Filter[i * 4 + 0] = r;
167 ctx->Convolution1D.Filter[i * 4 + 1] = g;
168 ctx->Convolution1D.Filter[i * 4 + 2] = b;
169 ctx->Convolution1D.Filter[i * 4 + 3] = a;
170 }
171 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000172
Brian Paulb5012e12000-11-10 18:31:04 +0000173 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000174}
175
176
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000177void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000178_mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image)
179{
Brian Pauld0570642002-03-19 15:22:50 +0000180 GLint baseFormat;
Brian Paul147b0832000-08-23 14:31:25 +0000181 GLint i, components;
182 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000183 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000184
185 if (target != GL_CONVOLUTION_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000186 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000187 return;
188 }
189
190 baseFormat = base_filter_format(internalFormat);
191 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000192 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000193 return;
194 }
195
196 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000197 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000198 return;
199 }
200 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
Brian Paul08836342001-03-03 20:33:27 +0000201 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)");
Brian Paul147b0832000-08-23 14:31:25 +0000202 return;
203 }
204
Brian Paul90f042a2000-12-10 19:23:19 +0000205 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000206 _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000207 return;
208 }
209 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000210 format == GL_STENCIL_INDEX ||
211 format == GL_DEPTH_COMPONENT ||
212 format == GL_INTENSITY ||
213 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000214 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000215 return;
216 }
217
218 components = _mesa_components_in_format(format);
219 assert(components > 0); /* this should have been caught earlier */
220
221 ctx->Convolution2D.Format = format;
222 ctx->Convolution2D.InternalFormat = internalFormat;
223 ctx->Convolution2D.Width = width;
224 ctx->Convolution2D.Height = height;
225
226 /* Unpack filter image. We always store filters in RGBA format. */
227 for (i = 0; i < height; i++) {
228 const GLvoid *src = _mesa_image_address(&ctx->Unpack, image, width,
229 height, format, type, 0, i, 0);
230 GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4;
231 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
232 format, type, src, &ctx->Unpack,
233 0, GL_FALSE);
234 }
235
236 /* apply scale and bias */
237 {
238 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[1];
239 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[1];
Brian Paul8acb7e92001-05-09 22:24:22 +0000240 for (i = 0; i < width * height; i++) {
Brian Paul147b0832000-08-23 14:31:25 +0000241 GLfloat r = ctx->Convolution2D.Filter[i * 4 + 0];
242 GLfloat g = ctx->Convolution2D.Filter[i * 4 + 1];
243 GLfloat b = ctx->Convolution2D.Filter[i * 4 + 2];
244 GLfloat a = ctx->Convolution2D.Filter[i * 4 + 3];
245 r = r * scale[0] + bias[0];
246 g = g * scale[1] + bias[1];
247 b = b * scale[2] + bias[2];
248 a = a * scale[3] + bias[3];
249 ctx->Convolution2D.Filter[i * 4 + 0] = r;
250 ctx->Convolution2D.Filter[i * 4 + 1] = g;
251 ctx->Convolution2D.Filter[i * 4 + 2] = b;
252 ctx->Convolution2D.Filter[i * 4 + 3] = a;
253 }
254 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000255
Brian Paulb5012e12000-11-10 18:31:04 +0000256 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000257}
258
259
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000260void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000261_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param)
262{
263 GET_CURRENT_CONTEXT(ctx);
264 GLuint c;
Keith Whitwell58e99172001-01-05 02:26:48 +0000265 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000266
267 switch (target) {
268 case GL_CONVOLUTION_1D:
269 c = 0;
270 break;
271 case GL_CONVOLUTION_2D:
272 c = 1;
273 break;
274 case GL_SEPARABLE_2D:
275 c = 2;
276 break;
277 default:
Brian Paul08836342001-03-03 20:33:27 +0000278 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000279 return;
280 }
281
282 switch (pname) {
283 case GL_CONVOLUTION_BORDER_MODE:
284 if (param == (GLfloat) GL_REDUCE ||
285 param == (GLfloat) GL_CONSTANT_BORDER ||
286 param == (GLfloat) GL_REPLICATE_BORDER) {
287 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
288 }
289 else {
Brian Paul08836342001-03-03 20:33:27 +0000290 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000291 return;
292 }
293 break;
294 default:
Brian Paul08836342001-03-03 20:33:27 +0000295 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000296 return;
297 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000298
299 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000300}
301
302
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000303void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000304_mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params)
305{
306 GET_CURRENT_CONTEXT(ctx);
307 struct gl_convolution_attrib *conv;
308 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000309 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000310
311 switch (target) {
312 case GL_CONVOLUTION_1D:
313 c = 0;
314 conv = &ctx->Convolution1D;
315 break;
316 case GL_CONVOLUTION_2D:
317 c = 1;
318 conv = &ctx->Convolution2D;
319 break;
320 case GL_SEPARABLE_2D:
321 c = 2;
322 conv = &ctx->Separable2D;
323 break;
324 default:
Brian Paul08836342001-03-03 20:33:27 +0000325 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000326 return;
327 }
328
329 switch (pname) {
330 case GL_CONVOLUTION_BORDER_COLOR:
331 COPY_4V(ctx->Pixel.ConvolutionBorderColor[c], params);
332 break;
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];
338 }
339 else {
Brian Paul08836342001-03-03 20:33:27 +0000340 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000341 return;
342 }
343 break;
344 case GL_CONVOLUTION_FILTER_SCALE:
345 COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params);
346 break;
347 case GL_CONVOLUTION_FILTER_BIAS:
348 COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params);
349 break;
350 default:
Brian Paul08836342001-03-03 20:33:27 +0000351 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000352 return;
353 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000354
355 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000356}
357
358
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000359void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000360_mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint param)
361{
362 GET_CURRENT_CONTEXT(ctx);
363 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000364 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000365
366 switch (target) {
367 case GL_CONVOLUTION_1D:
368 c = 0;
369 break;
370 case GL_CONVOLUTION_2D:
371 c = 1;
372 break;
373 case GL_SEPARABLE_2D:
374 c = 2;
375 break;
376 default:
Brian Paul08836342001-03-03 20:33:27 +0000377 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000378 return;
379 }
380
381 switch (pname) {
382 case GL_CONVOLUTION_BORDER_MODE:
383 if (param == (GLint) GL_REDUCE ||
384 param == (GLint) GL_CONSTANT_BORDER ||
385 param == (GLint) GL_REPLICATE_BORDER) {
386 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
387 }
388 else {
Brian Paul08836342001-03-03 20:33:27 +0000389 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000390 return;
391 }
392 break;
393 default:
Brian Paul08836342001-03-03 20:33:27 +0000394 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000395 return;
396 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000397
398 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000399}
400
401
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000402void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000403_mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params)
404{
405 GET_CURRENT_CONTEXT(ctx);
406 struct gl_convolution_attrib *conv;
407 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000408 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000409
410 switch (target) {
411 case GL_CONVOLUTION_1D:
412 c = 0;
413 conv = &ctx->Convolution1D;
414 break;
415 case GL_CONVOLUTION_2D:
416 c = 1;
417 conv = &ctx->Convolution2D;
418 break;
419 case GL_SEPARABLE_2D:
420 c = 2;
421 conv = &ctx->Separable2D;
422 break;
423 default:
Brian Paul08836342001-03-03 20:33:27 +0000424 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000425 return;
426 }
427
428 switch (pname) {
429 case GL_CONVOLUTION_BORDER_COLOR:
430 ctx->Pixel.ConvolutionBorderColor[c][0] = INT_TO_FLOAT(params[0]);
431 ctx->Pixel.ConvolutionBorderColor[c][1] = INT_TO_FLOAT(params[1]);
432 ctx->Pixel.ConvolutionBorderColor[c][2] = INT_TO_FLOAT(params[2]);
433 ctx->Pixel.ConvolutionBorderColor[c][3] = INT_TO_FLOAT(params[3]);
434 break;
435 case GL_CONVOLUTION_BORDER_MODE:
436 if (params[0] == (GLint) GL_REDUCE ||
437 params[0] == (GLint) GL_CONSTANT_BORDER ||
438 params[0] == (GLint) GL_REPLICATE_BORDER) {
439 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0];
440 }
441 else {
Brian Paul08836342001-03-03 20:33:27 +0000442 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000443 return;
444 }
445 break;
446 case GL_CONVOLUTION_FILTER_SCALE:
Karl Schultz7c426812001-09-19 20:30:44 +0000447 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
448 /* need cast to prevent compiler warnings */
449 ctx->Pixel.ConvolutionFilterScale[c][0] = (GLfloat) params[0];
450 ctx->Pixel.ConvolutionFilterScale[c][1] = (GLfloat) params[1];
451 ctx->Pixel.ConvolutionFilterScale[c][2] = (GLfloat) params[2];
452 ctx->Pixel.ConvolutionFilterScale[c][3] = (GLfloat) params[3];
Brian Paul147b0832000-08-23 14:31:25 +0000453 break;
454 case GL_CONVOLUTION_FILTER_BIAS:
Karl Schultz7c426812001-09-19 20:30:44 +0000455 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
456 /* need cast to prevent compiler warnings */
457 ctx->Pixel.ConvolutionFilterBias[c][0] = (GLfloat) params[0];
458 ctx->Pixel.ConvolutionFilterBias[c][1] = (GLfloat) params[1];
459 ctx->Pixel.ConvolutionFilterBias[c][2] = (GLfloat) params[2];
460 ctx->Pixel.ConvolutionFilterBias[c][3] = (GLfloat) params[3];
Brian Paul147b0832000-08-23 14:31:25 +0000461 break;
462 default:
Brian Paul08836342001-03-03 20:33:27 +0000463 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000464 return;
465 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000466
467 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000468}
469
470
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000471void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000472_mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width)
473{
Brian Pauld0570642002-03-19 15:22:50 +0000474 GLint baseFormat;
Brian Paul147b0832000-08-23 14:31:25 +0000475 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000476 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000477
478 if (target != GL_CONVOLUTION_1D) {
Brian Paul08836342001-03-03 20:33:27 +0000479 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000480 return;
481 }
482
483 baseFormat = base_filter_format(internalFormat);
484 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000485 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000486 return;
487 }
488
489 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000490 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter1D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000491 return;
492 }
493
Keith Whitwell70989242001-03-19 02:25:35 +0000494 ctx->Driver.CopyConvolutionFilter1D( ctx, target,
495 internalFormat, x, y, width);
Brian Paul147b0832000-08-23 14:31:25 +0000496}
497
498
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000499void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000500_mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height)
501{
Brian Pauld0570642002-03-19 15:22:50 +0000502 GLint baseFormat;
Brian Paul147b0832000-08-23 14:31:25 +0000503 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000504 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000505
506 if (target != GL_CONVOLUTION_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000507 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000508 return;
509 }
510
511 baseFormat = base_filter_format(internalFormat);
512 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000513 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000514 return;
515 }
516
517 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000518 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000519 return;
520 }
521 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
Brian Paul08836342001-03-03 20:33:27 +0000522 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(height)");
Brian Paul147b0832000-08-23 14:31:25 +0000523 return;
524 }
525
Keith Whitwell70989242001-03-19 02:25:35 +0000526 ctx->Driver.CopyConvolutionFilter2D( ctx, target, internalFormat, x, y,
527 width, height );
Brian Paul147b0832000-08-23 14:31:25 +0000528
Brian Paul147b0832000-08-23 14:31:25 +0000529}
530
531
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000532void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000533_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid *image)
534{
Brian Paulf75d6972000-09-05 20:28:56 +0000535 const struct gl_convolution_attrib *filter;
Brian Paulb51b0a82001-03-07 05:06:11 +0000536 GLuint row;
Brian Paul147b0832000-08-23 14:31:25 +0000537 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000538 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000539
Brian Paul0c000ec2000-11-21 23:26:13 +0000540 if (ctx->NewState) {
Brian Paul08836342001-03-03 20:33:27 +0000541 _mesa_update_state(ctx);
Brian Paul0c000ec2000-11-21 23:26:13 +0000542 }
543
Brian Paul90f042a2000-12-10 19:23:19 +0000544 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000545 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000546 return;
547 }
548
549 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000550 format == GL_STENCIL_INDEX ||
551 format == GL_DEPTH_COMPONENT ||
552 format == GL_INTENSITY ||
553 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000554 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000555 return;
556 }
557
Brian Paulf75d6972000-09-05 20:28:56 +0000558 switch (target) {
559 case GL_CONVOLUTION_1D:
560 filter = &(ctx->Convolution1D);
561 break;
562 case GL_CONVOLUTION_2D:
563 filter = &(ctx->Convolution2D);
564 break;
565 default:
Brian Paul08836342001-03-03 20:33:27 +0000566 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(target)");
Brian Paulf75d6972000-09-05 20:28:56 +0000567 return;
568 }
569
570 for (row = 0; row < filter->Height; row++) {
571 GLvoid *dst = _mesa_image_address( &ctx->Pack, image, filter->Width,
572 filter->Height, format, type,
573 0, row, 0);
574 const GLfloat *src = filter->Filter + row * filter->Width * 4;
Brian Paulf75d6972000-09-05 20:28:56 +0000575 _mesa_pack_float_rgba_span(ctx, filter->Width,
576 (const GLfloat (*)[4]) src,
577 format, type, dst, &ctx->Pack, 0);
578 }
Brian Paul147b0832000-08-23 14:31:25 +0000579}
580
581
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000582void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000583_mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params)
584{
585 GET_CURRENT_CONTEXT(ctx);
586 const struct gl_convolution_attrib *conv;
587 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000588 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000589
590 switch (target) {
591 case GL_CONVOLUTION_1D:
592 c = 0;
593 conv = &ctx->Convolution1D;
594 break;
595 case GL_CONVOLUTION_2D:
596 c = 1;
597 conv = &ctx->Convolution2D;
598 break;
599 case GL_SEPARABLE_2D:
600 c = 2;
601 conv = &ctx->Separable2D;
602 break;
603 default:
Brian Paul08836342001-03-03 20:33:27 +0000604 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000605 return;
606 }
607
608 switch (pname) {
609 case GL_CONVOLUTION_BORDER_COLOR:
610 COPY_4V(params, ctx->Pixel.ConvolutionBorderColor[c]);
611 break;
612 case GL_CONVOLUTION_BORDER_MODE:
613 *params = (GLfloat) ctx->Pixel.ConvolutionBorderMode[c];
614 break;
615 case GL_CONVOLUTION_FILTER_SCALE:
616 COPY_4V(params, ctx->Pixel.ConvolutionFilterScale[c]);
617 break;
618 case GL_CONVOLUTION_FILTER_BIAS:
619 COPY_4V(params, ctx->Pixel.ConvolutionFilterBias[c]);
620 break;
621 case GL_CONVOLUTION_FORMAT:
622 *params = (GLfloat) conv->Format;
623 break;
624 case GL_CONVOLUTION_WIDTH:
625 *params = (GLfloat) conv->Width;
626 break;
627 case GL_CONVOLUTION_HEIGHT:
628 *params = (GLfloat) conv->Height;
629 break;
630 case GL_MAX_CONVOLUTION_WIDTH:
631 *params = (GLfloat) ctx->Const.MaxConvolutionWidth;
632 break;
633 case GL_MAX_CONVOLUTION_HEIGHT:
634 *params = (GLfloat) ctx->Const.MaxConvolutionHeight;
635 break;
636 default:
Brian Paul08836342001-03-03 20:33:27 +0000637 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000638 return;
639 }
640}
641
642
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000643void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000644_mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params)
645{
646 GET_CURRENT_CONTEXT(ctx);
647 const struct gl_convolution_attrib *conv;
648 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000649 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000650
651 switch (target) {
652 case GL_CONVOLUTION_1D:
653 c = 0;
654 conv = &ctx->Convolution1D;
655 break;
656 case GL_CONVOLUTION_2D:
657 c = 1;
658 conv = &ctx->Convolution2D;
659 break;
660 case GL_SEPARABLE_2D:
661 c = 2;
662 conv = &ctx->Separable2D;
663 break;
664 default:
Brian Paul08836342001-03-03 20:33:27 +0000665 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000666 return;
667 }
668
669 switch (pname) {
670 case GL_CONVOLUTION_BORDER_COLOR:
671 params[0] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][0]);
672 params[1] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][1]);
673 params[2] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][2]);
674 params[3] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][3]);
675 break;
676 case GL_CONVOLUTION_BORDER_MODE:
677 *params = (GLint) ctx->Pixel.ConvolutionBorderMode[c];
678 break;
679 case GL_CONVOLUTION_FILTER_SCALE:
680 params[0] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][0];
681 params[1] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][1];
682 params[2] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][2];
683 params[3] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][3];
684 break;
685 case GL_CONVOLUTION_FILTER_BIAS:
686 params[0] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][0];
687 params[1] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][1];
688 params[2] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][2];
689 params[3] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][3];
690 break;
691 case GL_CONVOLUTION_FORMAT:
692 *params = (GLint) conv->Format;
693 break;
694 case GL_CONVOLUTION_WIDTH:
695 *params = (GLint) conv->Width;
696 break;
697 case GL_CONVOLUTION_HEIGHT:
698 *params = (GLint) conv->Height;
699 break;
700 case GL_MAX_CONVOLUTION_WIDTH:
701 *params = (GLint) ctx->Const.MaxConvolutionWidth;
702 break;
703 case GL_MAX_CONVOLUTION_HEIGHT:
704 *params = (GLint) ctx->Const.MaxConvolutionHeight;
705 break;
706 default:
Brian Paul08836342001-03-03 20:33:27 +0000707 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000708 return;
709 }
710}
711
712
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000713void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000714_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span)
715{
Brian Paulf75d6972000-09-05 20:28:56 +0000716 const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
717 const struct gl_convolution_attrib *filter;
Brian Paul147b0832000-08-23 14:31:25 +0000718 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000719 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000720
Brian Paul0c000ec2000-11-21 23:26:13 +0000721 if (ctx->NewState) {
Brian Paul08836342001-03-03 20:33:27 +0000722 _mesa_update_state(ctx);
Brian Paul0c000ec2000-11-21 23:26:13 +0000723 }
724
Brian Paul147b0832000-08-23 14:31:25 +0000725 if (target != GL_SEPARABLE_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000726 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000727 return;
728 }
729
Brian Paul90f042a2000-12-10 19:23:19 +0000730 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000731 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000732 return;
733 }
734
735 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000736 format == GL_STENCIL_INDEX ||
737 format == GL_DEPTH_COMPONENT ||
738 format == GL_INTENSITY ||
739 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000740 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000741 return;
742 }
743
Brian Paulf75d6972000-09-05 20:28:56 +0000744 filter = &ctx->Separable2D;
745
746 /* Row filter */
747 {
748 GLvoid *dst = _mesa_image_address( &ctx->Pack, row, filter->Width,
749 filter->Height, format, type,
750 0, 0, 0);
751 _mesa_pack_float_rgba_span(ctx, filter->Width,
752 (const GLfloat (*)[4]) filter->Filter,
753 format, type, dst, &ctx->Pack, 0);
754 }
755
756 /* Column filter */
757 {
758 GLvoid *dst = _mesa_image_address( &ctx->Pack, column, filter->Width,
759 1, format, type,
760 0, 0, 0);
761 const GLfloat *src = filter->Filter + colStart;
762 _mesa_pack_float_rgba_span(ctx, filter->Height,
763 (const GLfloat (*)[4]) src,
764 format, type, dst, &ctx->Pack, 0);
765 }
766
767 (void) span; /* unused at this time */
Brian Paul147b0832000-08-23 14:31:25 +0000768}
769
770
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000771void GLAPIENTRY
Brian Paul147b0832000-08-23 14:31:25 +0000772_mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column)
773{
774 const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
Brian Pauld0570642002-03-19 15:22:50 +0000775 GLint baseFormat;
Brian Paul147b0832000-08-23 14:31:25 +0000776 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000777 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000778
779 if (target != GL_SEPARABLE_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000780 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000781 return;
782 }
783
784 baseFormat = base_filter_format(internalFormat);
785 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000786 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000787 return;
788 }
789
790 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000791 _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000792 return;
793 }
794 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
Brian Paul08836342001-03-03 20:33:27 +0000795 _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(height)");
Brian Paul147b0832000-08-23 14:31:25 +0000796 return;
797 }
798
Brian Paul90f042a2000-12-10 19:23:19 +0000799 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000800 _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000801 return;
802 }
803
804 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000805 format == GL_STENCIL_INDEX ||
806 format == GL_DEPTH_COMPONENT ||
807 format == GL_INTENSITY ||
808 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000809 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000810 return;
811 }
812
813 ctx->Separable2D.Format = format;
814 ctx->Separable2D.InternalFormat = internalFormat;
815 ctx->Separable2D.Width = width;
816 ctx->Separable2D.Height = height;
817
818 /* unpack row filter */
819 _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
820 ctx->Separable2D.Filter,
821 format, type, row, &ctx->Unpack,
822 0, GL_FALSE);
823
824 /* apply scale and bias */
825 {
826 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
827 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
828 GLint i;
829 for (i = 0; i < width; i++) {
830 GLfloat r = ctx->Separable2D.Filter[i * 4 + 0];
831 GLfloat g = ctx->Separable2D.Filter[i * 4 + 1];
832 GLfloat b = ctx->Separable2D.Filter[i * 4 + 2];
833 GLfloat a = ctx->Separable2D.Filter[i * 4 + 3];
834 r = r * scale[0] + bias[0];
835 g = g * scale[1] + bias[1];
836 b = b * scale[2] + bias[2];
837 a = a * scale[3] + bias[3];
838 ctx->Separable2D.Filter[i * 4 + 0] = r;
839 ctx->Separable2D.Filter[i * 4 + 1] = g;
840 ctx->Separable2D.Filter[i * 4 + 2] = b;
841 ctx->Separable2D.Filter[i * 4 + 3] = a;
842 }
843 }
844
845 /* unpack column filter */
846 _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
847 &ctx->Separable2D.Filter[colStart],
848 format, type, column, &ctx->Unpack,
849 0, GL_FALSE);
850
851 /* apply scale and bias */
852 {
853 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
854 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
855 GLint i;
856 for (i = 0; i < width; i++) {
857 GLfloat r = ctx->Separable2D.Filter[i * 4 + 0 + colStart];
858 GLfloat g = ctx->Separable2D.Filter[i * 4 + 1 + colStart];
859 GLfloat b = ctx->Separable2D.Filter[i * 4 + 2 + colStart];
860 GLfloat a = ctx->Separable2D.Filter[i * 4 + 3 + colStart];
861 r = r * scale[0] + bias[0];
862 g = g * scale[1] + bias[1];
863 b = b * scale[2] + bias[2];
864 a = a * scale[3] + bias[3];
865 ctx->Separable2D.Filter[i * 4 + 0 + colStart] = r;
866 ctx->Separable2D.Filter[i * 4 + 1 + colStart] = g;
867 ctx->Separable2D.Filter[i * 4 + 2 + colStart] = b;
868 ctx->Separable2D.Filter[i * 4 + 3 + colStart] = a;
869 }
870 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000871
Brian Paulb5012e12000-11-10 18:31:04 +0000872 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000873}
874
875
876/**********************************************************************/
877/*** image convolution functions ***/
878/**********************************************************************/
879
Brian Pauld4b799b2000-08-21 14:24:30 +0000880static void
881convolve_1d_reduce(GLint srcWidth, const GLfloat src[][4],
882 GLint filterWidth, const GLfloat filter[][4],
883 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +0000884{
Brian Paul7e708742000-08-22 18:54:25 +0000885 GLint dstWidth;
Brian Paulcc8e37f2000-07-12 13:00:09 +0000886 GLint i, n;
887
Brian Paul7e708742000-08-22 18:54:25 +0000888 if (filterWidth >= 1)
889 dstWidth = srcWidth - (filterWidth - 1);
890 else
891 dstWidth = srcWidth;
892
Brian Paulcc8e37f2000-07-12 13:00:09 +0000893 if (dstWidth <= 0)
894 return; /* null result */
895
896 for (i = 0; i < dstWidth; i++) {
897 GLfloat sumR = 0.0;
898 GLfloat sumG = 0.0;
899 GLfloat sumB = 0.0;
900 GLfloat sumA = 0.0;
901 for (n = 0; n < filterWidth; n++) {
902 sumR += src[i + n][RCOMP] * filter[n][RCOMP];
903 sumG += src[i + n][GCOMP] * filter[n][GCOMP];
904 sumB += src[i + n][BCOMP] * filter[n][BCOMP];
905 sumA += src[i + n][ACOMP] * filter[n][ACOMP];
906 }
907 dest[i][RCOMP] = sumR;
908 dest[i][GCOMP] = sumG;
909 dest[i][BCOMP] = sumB;
910 dest[i][ACOMP] = sumA;
911 }
912}
913
914
Brian Pauld4b799b2000-08-21 14:24:30 +0000915static void
916convolve_1d_constant(GLint srcWidth, const GLfloat src[][4],
917 GLint filterWidth, const GLfloat filter[][4],
918 GLfloat dest[][4],
919 const GLfloat borderColor[4])
Brian Paulcc8e37f2000-07-12 13:00:09 +0000920{
921 const GLint halfFilterWidth = filterWidth / 2;
922 GLint i, n;
923
924 for (i = 0; i < srcWidth; i++) {
925 GLfloat sumR = 0.0;
926 GLfloat sumG = 0.0;
927 GLfloat sumB = 0.0;
928 GLfloat sumA = 0.0;
929 for (n = 0; n < filterWidth; n++) {
930 if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) {
931 sumR += borderColor[RCOMP] * filter[n][RCOMP];
932 sumG += borderColor[GCOMP] * filter[n][GCOMP];
933 sumB += borderColor[BCOMP] * filter[n][BCOMP];
934 sumA += borderColor[ACOMP] * filter[n][ACOMP];
935 }
936 else {
937 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
938 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
939 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
940 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
941 }
942 }
943 dest[i][RCOMP] = sumR;
944 dest[i][GCOMP] = sumG;
945 dest[i][BCOMP] = sumB;
946 dest[i][ACOMP] = sumA;
947 }
948}
949
950
Brian Pauld4b799b2000-08-21 14:24:30 +0000951static void
952convolve_1d_replicate(GLint srcWidth, const GLfloat src[][4],
953 GLint filterWidth, const GLfloat filter[][4],
954 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +0000955{
956 const GLint halfFilterWidth = filterWidth / 2;
957 GLint i, n;
958
959 for (i = 0; i < srcWidth; i++) {
960 GLfloat sumR = 0.0;
961 GLfloat sumG = 0.0;
962 GLfloat sumB = 0.0;
963 GLfloat sumA = 0.0;
964 for (n = 0; n < filterWidth; n++) {
965 if (i + n < halfFilterWidth) {
966 sumR += src[0][RCOMP] * filter[n][RCOMP];
967 sumG += src[0][GCOMP] * filter[n][GCOMP];
968 sumB += src[0][BCOMP] * filter[n][BCOMP];
969 sumA += src[0][ACOMP] * filter[n][ACOMP];
970 }
971 else if (i + n - halfFilterWidth >= srcWidth) {
972 sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP];
973 sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP];
974 sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP];
975 sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP];
976 }
977 else {
978 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
979 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
980 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
981 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
982 }
983 }
984 dest[i][RCOMP] = sumR;
985 dest[i][GCOMP] = sumG;
986 dest[i][BCOMP] = sumB;
987 dest[i][ACOMP] = sumA;
988 }
989}
990
991
Brian Pauld4b799b2000-08-21 14:24:30 +0000992static void
993convolve_2d_reduce(GLint srcWidth, GLint srcHeight,
994 const GLfloat src[][4],
995 GLint filterWidth, GLint filterHeight,
996 const GLfloat filter[][4],
997 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +0000998{
Brian Paul7e708742000-08-22 18:54:25 +0000999 GLint dstWidth, dstHeight;
Brian Pauld4b799b2000-08-21 14:24:30 +00001000 GLint i, j, n, m;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001001
Brian Paul7e708742000-08-22 18:54:25 +00001002 if (filterWidth >= 1)
1003 dstWidth = srcWidth - (filterWidth - 1);
1004 else
1005 dstWidth = srcWidth;
1006
1007 if (filterHeight >= 1)
1008 dstHeight = srcHeight - (filterHeight - 1);
1009 else
1010 dstHeight = srcHeight;
1011
Brian Pauld4b799b2000-08-21 14:24:30 +00001012 if (dstWidth <= 0 || dstHeight <= 0)
1013 return;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001014
Brian Pauld4b799b2000-08-21 14:24:30 +00001015 for (j = 0; j < dstHeight; j++) {
1016 for (i = 0; i < dstWidth; i++) {
1017 GLfloat sumR = 0.0;
1018 GLfloat sumG = 0.0;
1019 GLfloat sumB = 0.0;
1020 GLfloat sumA = 0.0;
1021 for (m = 0; m < filterHeight; m++) {
1022 for (n = 0; n < filterWidth; n++) {
1023 const GLint k = (j + m) * srcWidth + i + n;
1024 const GLint f = m * filterWidth + n;
1025 sumR += src[k][RCOMP] * filter[f][RCOMP];
1026 sumG += src[k][GCOMP] * filter[f][GCOMP];
1027 sumB += src[k][BCOMP] * filter[f][BCOMP];
1028 sumA += src[k][ACOMP] * filter[f][ACOMP];
1029 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001030 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001031 dest[j * dstWidth + i][RCOMP] = sumR;
1032 dest[j * dstWidth + i][GCOMP] = sumG;
1033 dest[j * dstWidth + i][BCOMP] = sumB;
1034 dest[j * dstWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001035 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001036 }
1037}
1038
1039
Brian Pauld4b799b2000-08-21 14:24:30 +00001040static void
1041convolve_2d_constant(GLint srcWidth, GLint srcHeight,
1042 const GLfloat src[][4],
1043 GLint filterWidth, GLint filterHeight,
1044 const GLfloat filter[][4],
1045 GLfloat dest[][4],
1046 const GLfloat borderColor[4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001047{
1048 const GLint halfFilterWidth = filterWidth / 2;
Brian Pauld4b799b2000-08-21 14:24:30 +00001049 const GLint halfFilterHeight = filterHeight / 2;
1050 GLint i, j, n, m;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001051
Brian Pauld4b799b2000-08-21 14:24:30 +00001052 for (j = 0; j < srcHeight; j++) {
1053 for (i = 0; i < srcWidth; i++) {
1054 GLfloat sumR = 0.0;
1055 GLfloat sumG = 0.0;
1056 GLfloat sumB = 0.0;
1057 GLfloat sumA = 0.0;
1058 for (m = 0; m < filterHeight; m++) {
1059 for (n = 0; n < filterWidth; n++) {
1060 const GLint f = m * filterWidth + n;
1061 const GLint is = i + n - halfFilterWidth;
1062 const GLint js = j + m - halfFilterHeight;
1063 if (is < 0 || is >= srcWidth ||
1064 js < 0 || js >= srcHeight) {
1065 sumR += borderColor[RCOMP] * filter[f][RCOMP];
1066 sumG += borderColor[GCOMP] * filter[f][GCOMP];
1067 sumB += borderColor[BCOMP] * filter[f][BCOMP];
1068 sumA += borderColor[ACOMP] * filter[f][ACOMP];
1069 }
1070 else {
1071 const GLint k = js * srcWidth + is;
1072 sumR += src[k][RCOMP] * filter[f][RCOMP];
1073 sumG += src[k][GCOMP] * filter[f][GCOMP];
1074 sumB += src[k][BCOMP] * filter[f][BCOMP];
1075 sumA += src[k][ACOMP] * filter[f][ACOMP];
1076 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001077 }
1078 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001079 dest[j * srcWidth + i][RCOMP] = sumR;
1080 dest[j * srcWidth + i][GCOMP] = sumG;
1081 dest[j * srcWidth + i][BCOMP] = sumB;
1082 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001083 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001084 }
1085}
1086
1087
Brian Pauld4b799b2000-08-21 14:24:30 +00001088static void
1089convolve_2d_replicate(GLint srcWidth, GLint srcHeight,
1090 const GLfloat src[][4],
1091 GLint filterWidth, GLint filterHeight,
1092 const GLfloat filter[][4],
1093 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001094{
1095 const GLint halfFilterWidth = filterWidth / 2;
Brian Pauld4b799b2000-08-21 14:24:30 +00001096 const GLint halfFilterHeight = filterHeight / 2;
1097 GLint i, j, n, m;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001098
Brian Pauld4b799b2000-08-21 14:24:30 +00001099 for (j = 0; j < srcHeight; j++) {
1100 for (i = 0; i < srcWidth; i++) {
1101 GLfloat sumR = 0.0;
1102 GLfloat sumG = 0.0;
1103 GLfloat sumB = 0.0;
1104 GLfloat sumA = 0.0;
1105 for (m = 0; m < filterHeight; m++) {
1106 for (n = 0; n < filterWidth; n++) {
1107 const GLint f = m * filterWidth + n;
1108 GLint is = i + n - halfFilterWidth;
1109 GLint js = j + m - halfFilterHeight;
1110 GLint k;
1111 if (is < 0)
1112 is = 0;
1113 else if (is >= srcWidth)
1114 is = srcWidth - 1;
1115 if (js < 0)
1116 js = 0;
1117 else if (js >= srcHeight)
1118 js = srcHeight - 1;
1119 k = js * srcWidth + is;
1120 sumR += src[k][RCOMP] * filter[f][RCOMP];
1121 sumG += src[k][GCOMP] * filter[f][GCOMP];
1122 sumB += src[k][BCOMP] * filter[f][BCOMP];
1123 sumA += src[k][ACOMP] * filter[f][ACOMP];
Brian Paulcc8e37f2000-07-12 13:00:09 +00001124 }
1125 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001126 dest[j * srcWidth + i][RCOMP] = sumR;
1127 dest[j * srcWidth + i][GCOMP] = sumG;
1128 dest[j * srcWidth + i][BCOMP] = sumB;
1129 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001130 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001131 }
1132}
1133
1134
Brian Pauld4b799b2000-08-21 14:24:30 +00001135static void
1136convolve_sep_reduce(GLint srcWidth, GLint srcHeight,
1137 const GLfloat src[][4],
1138 GLint filterWidth, GLint filterHeight,
1139 const GLfloat rowFilt[][4],
1140 const GLfloat colFilt[][4],
1141 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001142{
Brian Paul7e708742000-08-22 18:54:25 +00001143 GLint dstWidth, dstHeight;
Brian Pauld4b799b2000-08-21 14:24:30 +00001144 GLint i, j, n, m;
Brian Paul7e708742000-08-22 18:54:25 +00001145
1146 if (filterWidth >= 1)
1147 dstWidth = srcWidth - (filterWidth - 1);
1148 else
1149 dstWidth = srcWidth;
1150
1151 if (filterHeight >= 1)
1152 dstHeight = srcHeight - (filterHeight - 1);
1153 else
1154 dstHeight = srcHeight;
1155
1156 if (dstWidth <= 0 || dstHeight <= 0)
1157 return;
1158
1159 for (j = 0; j < dstHeight; j++) {
1160 for (i = 0; i < dstWidth; i++) {
Brian Pauld4b799b2000-08-21 14:24:30 +00001161 GLfloat sumR = 0.0;
1162 GLfloat sumG = 0.0;
1163 GLfloat sumB = 0.0;
1164 GLfloat sumA = 0.0;
1165 for (m = 0; m < filterHeight; m++) {
1166 for (n = 0; n < filterWidth; n++) {
Brian Paul7e708742000-08-22 18:54:25 +00001167 GLint k = (j + m) * srcWidth + i + n;
1168 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1169 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1170 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1171 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
Brian Paulcc8e37f2000-07-12 13:00:09 +00001172 }
1173 }
Brian Paul7e708742000-08-22 18:54:25 +00001174 dest[j * dstWidth + i][RCOMP] = sumR;
1175 dest[j * dstWidth + i][GCOMP] = sumG;
1176 dest[j * dstWidth + i][BCOMP] = sumB;
1177 dest[j * dstWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001178 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001179 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001180}
1181
1182
Brian Pauld4b799b2000-08-21 14:24:30 +00001183static void
1184convolve_sep_constant(GLint srcWidth, GLint srcHeight,
1185 const GLfloat src[][4],
1186 GLint filterWidth, GLint filterHeight,
1187 const GLfloat rowFilt[][4],
1188 const GLfloat colFilt[][4],
1189 GLfloat dest[][4],
1190 const GLfloat borderColor[4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001191{
1192 const GLint halfFilterWidth = filterWidth / 2;
Brian Pauld4b799b2000-08-21 14:24:30 +00001193 const GLint halfFilterHeight = filterHeight / 2;
1194 GLint i, j, n, m;
Brian Paul7e708742000-08-22 18:54:25 +00001195
Brian Pauld4b799b2000-08-21 14:24:30 +00001196 for (j = 0; j < srcHeight; j++) {
1197 for (i = 0; i < srcWidth; i++) {
1198 GLfloat sumR = 0.0;
1199 GLfloat sumG = 0.0;
1200 GLfloat sumB = 0.0;
1201 GLfloat sumA = 0.0;
1202 for (m = 0; m < filterHeight; m++) {
1203 for (n = 0; n < filterWidth; n++) {
Brian Paul7e708742000-08-22 18:54:25 +00001204 const GLint is = i + n - halfFilterWidth;
1205 const GLint js = j + m - halfFilterHeight;
1206 if (is < 0 || is >= srcWidth ||
1207 js < 0 || js >= srcHeight) {
Brian Pauld4b799b2000-08-21 14:24:30 +00001208 sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1209 sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1210 sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1211 sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1212 }
1213 else {
Brian Paul7e708742000-08-22 18:54:25 +00001214 GLint k = js * srcWidth + is;
Brian Pauld4b799b2000-08-21 14:24:30 +00001215 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1216 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1217 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1218 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1219 }
Brian Paul7e708742000-08-22 18:54:25 +00001220
Brian Paulcc8e37f2000-07-12 13:00:09 +00001221 }
1222 }
Brian Paul7e708742000-08-22 18:54:25 +00001223 dest[j * srcWidth + i][RCOMP] = sumR;
1224 dest[j * srcWidth + i][GCOMP] = sumG;
1225 dest[j * srcWidth + i][BCOMP] = sumB;
1226 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001227 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001228 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001229}
1230
1231
1232static void
1233convolve_sep_replicate(GLint srcWidth, GLint srcHeight,
1234 const GLfloat src[][4],
1235 GLint filterWidth, GLint filterHeight,
1236 const GLfloat rowFilt[][4],
1237 const GLfloat colFilt[][4],
1238 GLfloat dest[][4])
1239{
1240 const GLint halfFilterWidth = filterWidth / 2;
1241 const GLint halfFilterHeight = filterHeight / 2;
1242 GLint i, j, n, m;
1243
1244 for (j = 0; j < srcHeight; j++) {
1245 for (i = 0; i < srcWidth; i++) {
1246 GLfloat sumR = 0.0;
1247 GLfloat sumG = 0.0;
1248 GLfloat sumB = 0.0;
1249 GLfloat sumA = 0.0;
1250 for (m = 0; m < filterHeight; m++) {
1251 for (n = 0; n < filterWidth; n++) {
Brian Paul7e708742000-08-22 18:54:25 +00001252 GLint is = i + n - halfFilterWidth;
1253 GLint js = j + m - halfFilterHeight;
1254 GLint k;
1255 if (is < 0)
1256 is = 0;
1257 else if (is >= srcWidth)
1258 is = srcWidth - 1;
1259 if (js < 0)
1260 js = 0;
1261 else if (js >= srcHeight)
1262 js = srcHeight - 1;
1263 k = js * srcWidth + is;
1264 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1265 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1266 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1267 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
Brian Pauld4b799b2000-08-21 14:24:30 +00001268 }
1269 }
Brian Paul7e708742000-08-22 18:54:25 +00001270 dest[j * srcWidth + i][RCOMP] = sumR;
1271 dest[j * srcWidth + i][GCOMP] = sumG;
1272 dest[j * srcWidth + i][BCOMP] = sumB;
1273 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Pauld4b799b2000-08-21 14:24:30 +00001274 }
1275 }
1276}
1277
1278
1279
1280void
1281_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
1282 const GLfloat *srcImage, GLfloat *dstImage)
1283{
1284 switch (ctx->Pixel.ConvolutionBorderMode[0]) {
1285 case GL_REDUCE:
1286 convolve_1d_reduce(*width, (const GLfloat (*)[4]) srcImage,
1287 ctx->Convolution1D.Width,
1288 (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1289 (GLfloat (*)[4]) dstImage);
Brian Paul7e708742000-08-22 18:54:25 +00001290 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
Brian Pauld4b799b2000-08-21 14:24:30 +00001291 break;
1292 case GL_CONSTANT_BORDER:
1293 convolve_1d_constant(*width, (const GLfloat (*)[4]) srcImage,
1294 ctx->Convolution1D.Width,
1295 (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1296 (GLfloat (*)[4]) dstImage,
1297 ctx->Pixel.ConvolutionBorderColor[0]);
1298 break;
1299 case GL_REPLICATE_BORDER:
1300 convolve_1d_replicate(*width, (const GLfloat (*)[4]) srcImage,
1301 ctx->Convolution1D.Width,
1302 (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1303 (GLfloat (*)[4]) dstImage);
1304 break;
1305 default:
1306 ;
1307 }
1308}
1309
1310
1311void
1312_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
1313 const GLfloat *srcImage, GLfloat *dstImage)
1314{
1315 switch (ctx->Pixel.ConvolutionBorderMode[1]) {
1316 case GL_REDUCE:
1317 convolve_2d_reduce(*width, *height,
1318 (const GLfloat (*)[4]) srcImage,
1319 ctx->Convolution2D.Width,
1320 ctx->Convolution2D.Height,
1321 (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
1322 (GLfloat (*)[4]) dstImage);
Brian Paul7e708742000-08-22 18:54:25 +00001323 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
1324 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
Brian Pauld4b799b2000-08-21 14:24:30 +00001325 break;
1326 case GL_CONSTANT_BORDER:
1327 convolve_2d_constant(*width, *height,
1328 (const GLfloat (*)[4]) srcImage,
1329 ctx->Convolution2D.Width,
1330 ctx->Convolution2D.Height,
1331 (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
1332 (GLfloat (*)[4]) dstImage,
1333 ctx->Pixel.ConvolutionBorderColor[1]);
1334 break;
1335 case GL_REPLICATE_BORDER:
1336 convolve_2d_replicate(*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 break;
1343 default:
1344 ;
1345 }
1346}
1347
1348
1349void
1350_mesa_convolve_sep_image(const GLcontext *ctx,
1351 GLsizei *width, GLsizei *height,
1352 const GLfloat *srcImage, GLfloat *dstImage)
1353{
1354 const GLfloat *rowFilter = ctx->Separable2D.Filter;
1355 const GLfloat *colFilter = rowFilter + 4 * MAX_CONVOLUTION_WIDTH;
1356
1357 switch (ctx->Pixel.ConvolutionBorderMode[2]) {
1358 case GL_REDUCE:
1359 convolve_sep_reduce(*width, *height,
1360 (const GLfloat (*)[4]) srcImage,
Brian Paul7e708742000-08-22 18:54:25 +00001361 ctx->Separable2D.Width,
1362 ctx->Separable2D.Height,
Brian Pauld4b799b2000-08-21 14:24:30 +00001363 (const GLfloat (*)[4]) rowFilter,
1364 (const GLfloat (*)[4]) colFilter,
1365 (GLfloat (*)[4]) dstImage);
Brian Paul7e708742000-08-22 18:54:25 +00001366 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
1367 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
Brian Pauld4b799b2000-08-21 14:24:30 +00001368 break;
1369 case GL_CONSTANT_BORDER:
1370 convolve_sep_constant(*width, *height,
1371 (const GLfloat (*)[4]) srcImage,
Brian Paul7e708742000-08-22 18:54:25 +00001372 ctx->Separable2D.Width,
1373 ctx->Separable2D.Height,
Brian Pauld4b799b2000-08-21 14:24:30 +00001374 (const GLfloat (*)[4]) rowFilter,
1375 (const GLfloat (*)[4]) colFilter,
1376 (GLfloat (*)[4]) dstImage,
1377 ctx->Pixel.ConvolutionBorderColor[2]);
1378 break;
1379 case GL_REPLICATE_BORDER:
1380 convolve_sep_replicate(*width, *height,
1381 (const GLfloat (*)[4]) srcImage,
Brian Paul7e708742000-08-22 18:54:25 +00001382 ctx->Separable2D.Width,
1383 ctx->Separable2D.Height,
Brian Pauld4b799b2000-08-21 14:24:30 +00001384 (const GLfloat (*)[4]) rowFilter,
1385 (const GLfloat (*)[4]) colFilter,
1386 (GLfloat (*)[4]) dstImage);
1387 break;
1388 default:
1389 ;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001390 }
1391}
Brian Paul16461f72001-02-06 17:22:16 +00001392
1393
1394
1395/*
1396 * This function computes an image's size after convolution.
1397 * If the convolution border mode is GL_REDUCE, the post-convolution
1398 * image will be smaller than the original.
1399 */
1400void
1401_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
1402 GLsizei *width, GLsizei *height)
1403{
1404 if (ctx->Pixel.Convolution1DEnabled
1405 && dimensions == 1
1406 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
1407 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
1408 }
1409 else if (ctx->Pixel.Convolution2DEnabled
1410 && dimensions > 1
1411 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
1412 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
1413 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
1414 }
1415 else if (ctx->Pixel.Separable2DEnabled
1416 && dimensions > 1
1417 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
1418 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
1419 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
1420 }
1421}