blob: 1ec5993572d9cc881d231cd5745231be2bd1db0f [file] [log] [blame]
Karl Schultz7c426812001-09-19 20:30:44 +00001/* $Id: convolve.c,v 1.25 2001/09/19 20:30:44 kschultz Exp $ */
Brian Paulcc8e37f2000-07-12 13:00:09 +00002
3/*
4 * Mesa 3-D graphics library
Brian Pauld4b799b2000-08-21 14:24:30 +00005 * Version: 3.5
Brian Paulcc8e37f2000-07-12 13:00:09 +00006 *
Brian Paul16461f72001-02-06 17:22:16 +00007 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
Brian Paulcc8e37f2000-07-12 13:00:09 +00008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * Image convolution functions.
30 *
31 * Notes: filter kernel elements are indexed by <n> and <m> as in
32 * the GL spec.
33 */
34
35
36#ifdef PC_HEADER
37#include "all.h"
38#else
39#include "glheader.h"
Brian Paulc893a012000-10-28 20:41:13 +000040#include "colormac.h"
Brian Pauld4b799b2000-08-21 14:24:30 +000041#include "convolve.h"
42#include "context.h"
Brian Paul147b0832000-08-23 14:31:25 +000043#include "image.h"
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000044#include "mtypes.h"
Jon Taylorcdfba5d2000-11-23 02:50:56 +000045#include "state.h"
Brian Paulba41b8a2000-11-10 17:45:15 +000046#include "swrast/s_span.h" /* XXX SWRAST hack */
Brian Paulcc8e37f2000-07-12 13:00:09 +000047#endif
48
49
Brian Paul147b0832000-08-23 14:31:25 +000050/*
51 * Given an internalFormat token passed to glConvolutionFilter
52 * or glSeparableFilter, return the corresponding base format.
53 * Return -1 if invalid token.
54 */
55static GLint
56base_filter_format( GLenum format )
57{
58 switch (format) {
59 case GL_ALPHA:
60 case GL_ALPHA4:
61 case GL_ALPHA8:
62 case GL_ALPHA12:
63 case GL_ALPHA16:
64 return GL_ALPHA;
65 case GL_LUMINANCE:
66 case GL_LUMINANCE4:
67 case GL_LUMINANCE8:
68 case GL_LUMINANCE12:
69 case GL_LUMINANCE16:
70 return GL_LUMINANCE;
71 case GL_LUMINANCE_ALPHA:
72 case GL_LUMINANCE4_ALPHA4:
73 case GL_LUMINANCE6_ALPHA2:
74 case GL_LUMINANCE8_ALPHA8:
75 case GL_LUMINANCE12_ALPHA4:
76 case GL_LUMINANCE12_ALPHA12:
77 case GL_LUMINANCE16_ALPHA16:
78 return GL_LUMINANCE_ALPHA;
79 case GL_INTENSITY:
80 case GL_INTENSITY4:
81 case GL_INTENSITY8:
82 case GL_INTENSITY12:
83 case GL_INTENSITY16:
84 return GL_INTENSITY;
85 case GL_RGB:
86 case GL_R3_G3_B2:
87 case GL_RGB4:
88 case GL_RGB5:
89 case GL_RGB8:
90 case GL_RGB10:
91 case GL_RGB12:
92 case GL_RGB16:
93 return GL_RGB;
94 case 4:
95 case GL_RGBA:
96 case GL_RGBA2:
97 case GL_RGBA4:
98 case GL_RGB5_A1:
99 case GL_RGBA8:
100 case GL_RGB10_A2:
101 case GL_RGBA12:
102 case GL_RGBA16:
103 return GL_RGBA;
104 default:
105 return -1; /* error */
106 }
107}
108
109
110void
111_mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *image)
112{
113 GLenum baseFormat;
114 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000115 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000116
117 if (target != GL_CONVOLUTION_1D) {
Brian Paul08836342001-03-03 20:33:27 +0000118 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000119 return;
120 }
121
122 baseFormat = base_filter_format(internalFormat);
123 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000124 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000125 return;
126 }
127
128 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000129 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter1D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000130 return;
131 }
132
Brian Paul90f042a2000-12-10 19:23:19 +0000133 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000134 _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000135 return;
136 }
137
138 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000139 format == GL_STENCIL_INDEX ||
140 format == GL_DEPTH_COMPONENT ||
141 format == GL_INTENSITY ||
142 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000143 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000144 return;
145 }
146
147 ctx->Convolution1D.Format = format;
148 ctx->Convolution1D.InternalFormat = internalFormat;
149 ctx->Convolution1D.Width = width;
150 ctx->Convolution1D.Height = 1;
151
152 /* unpack filter image */
153 _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
154 ctx->Convolution1D.Filter,
155 format, type, image, &ctx->Unpack,
156 0, GL_FALSE);
157
158 /* apply scale and bias */
159 {
160 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[0];
161 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[0];
162 GLint i;
163 for (i = 0; i < width; i++) {
164 GLfloat r = ctx->Convolution1D.Filter[i * 4 + 0];
165 GLfloat g = ctx->Convolution1D.Filter[i * 4 + 1];
166 GLfloat b = ctx->Convolution1D.Filter[i * 4 + 2];
167 GLfloat a = ctx->Convolution1D.Filter[i * 4 + 3];
168 r = r * scale[0] + bias[0];
169 g = g * scale[1] + bias[1];
170 b = b * scale[2] + bias[2];
171 a = a * scale[3] + bias[3];
172 ctx->Convolution1D.Filter[i * 4 + 0] = r;
173 ctx->Convolution1D.Filter[i * 4 + 1] = g;
174 ctx->Convolution1D.Filter[i * 4 + 2] = b;
175 ctx->Convolution1D.Filter[i * 4 + 3] = a;
176 }
177 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000178
Brian Paulb5012e12000-11-10 18:31:04 +0000179 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000180}
181
182
183void
184_mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image)
185{
186 GLenum baseFormat;
187 GLint i, components;
188 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000189 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000190
191 if (target != GL_CONVOLUTION_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000192 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000193 return;
194 }
195
196 baseFormat = base_filter_format(internalFormat);
197 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000198 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000199 return;
200 }
201
202 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000203 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000204 return;
205 }
206 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
Brian Paul08836342001-03-03 20:33:27 +0000207 _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)");
Brian Paul147b0832000-08-23 14:31:25 +0000208 return;
209 }
210
Brian Paul90f042a2000-12-10 19:23:19 +0000211 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000212 _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000213 return;
214 }
215 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000216 format == GL_STENCIL_INDEX ||
217 format == GL_DEPTH_COMPONENT ||
218 format == GL_INTENSITY ||
219 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000220 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000221 return;
222 }
223
224 components = _mesa_components_in_format(format);
225 assert(components > 0); /* this should have been caught earlier */
226
227 ctx->Convolution2D.Format = format;
228 ctx->Convolution2D.InternalFormat = internalFormat;
229 ctx->Convolution2D.Width = width;
230 ctx->Convolution2D.Height = height;
231
232 /* Unpack filter image. We always store filters in RGBA format. */
233 for (i = 0; i < height; i++) {
234 const GLvoid *src = _mesa_image_address(&ctx->Unpack, image, width,
235 height, format, type, 0, i, 0);
236 GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4;
237 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
238 format, type, src, &ctx->Unpack,
239 0, GL_FALSE);
240 }
241
242 /* apply scale and bias */
243 {
244 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[1];
245 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[1];
Brian Paul8acb7e92001-05-09 22:24:22 +0000246 for (i = 0; i < width * height; i++) {
Brian Paul147b0832000-08-23 14:31:25 +0000247 GLfloat r = ctx->Convolution2D.Filter[i * 4 + 0];
248 GLfloat g = ctx->Convolution2D.Filter[i * 4 + 1];
249 GLfloat b = ctx->Convolution2D.Filter[i * 4 + 2];
250 GLfloat a = ctx->Convolution2D.Filter[i * 4 + 3];
251 r = r * scale[0] + bias[0];
252 g = g * scale[1] + bias[1];
253 b = b * scale[2] + bias[2];
254 a = a * scale[3] + bias[3];
255 ctx->Convolution2D.Filter[i * 4 + 0] = r;
256 ctx->Convolution2D.Filter[i * 4 + 1] = g;
257 ctx->Convolution2D.Filter[i * 4 + 2] = b;
258 ctx->Convolution2D.Filter[i * 4 + 3] = a;
259 }
260 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000261
Brian Paulb5012e12000-11-10 18:31:04 +0000262 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000263}
264
265
266void
267_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param)
268{
269 GET_CURRENT_CONTEXT(ctx);
270 GLuint c;
Keith Whitwell58e99172001-01-05 02:26:48 +0000271 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000272
273 switch (target) {
274 case GL_CONVOLUTION_1D:
275 c = 0;
276 break;
277 case GL_CONVOLUTION_2D:
278 c = 1;
279 break;
280 case GL_SEPARABLE_2D:
281 c = 2;
282 break;
283 default:
Brian Paul08836342001-03-03 20:33:27 +0000284 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000285 return;
286 }
287
288 switch (pname) {
289 case GL_CONVOLUTION_BORDER_MODE:
290 if (param == (GLfloat) GL_REDUCE ||
291 param == (GLfloat) GL_CONSTANT_BORDER ||
292 param == (GLfloat) GL_REPLICATE_BORDER) {
293 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
294 }
295 else {
Brian Paul08836342001-03-03 20:33:27 +0000296 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000297 return;
298 }
299 break;
300 default:
Brian Paul08836342001-03-03 20:33:27 +0000301 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000302 return;
303 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000304
305 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000306}
307
308
309void
310_mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params)
311{
312 GET_CURRENT_CONTEXT(ctx);
313 struct gl_convolution_attrib *conv;
314 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000315 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000316
317 switch (target) {
318 case GL_CONVOLUTION_1D:
319 c = 0;
320 conv = &ctx->Convolution1D;
321 break;
322 case GL_CONVOLUTION_2D:
323 c = 1;
324 conv = &ctx->Convolution2D;
325 break;
326 case GL_SEPARABLE_2D:
327 c = 2;
328 conv = &ctx->Separable2D;
329 break;
330 default:
Brian Paul08836342001-03-03 20:33:27 +0000331 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000332 return;
333 }
334
335 switch (pname) {
336 case GL_CONVOLUTION_BORDER_COLOR:
337 COPY_4V(ctx->Pixel.ConvolutionBorderColor[c], params);
338 break;
339 case GL_CONVOLUTION_BORDER_MODE:
340 if (params[0] == (GLfloat) GL_REDUCE ||
341 params[0] == (GLfloat) GL_CONSTANT_BORDER ||
342 params[0] == (GLfloat) GL_REPLICATE_BORDER) {
343 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0];
344 }
345 else {
Brian Paul08836342001-03-03 20:33:27 +0000346 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000347 return;
348 }
349 break;
350 case GL_CONVOLUTION_FILTER_SCALE:
351 COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params);
352 break;
353 case GL_CONVOLUTION_FILTER_BIAS:
354 COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params);
355 break;
356 default:
Brian Paul08836342001-03-03 20:33:27 +0000357 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000358 return;
359 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000360
361 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000362}
363
364
365void
366_mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint param)
367{
368 GET_CURRENT_CONTEXT(ctx);
369 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000370 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000371
372 switch (target) {
373 case GL_CONVOLUTION_1D:
374 c = 0;
375 break;
376 case GL_CONVOLUTION_2D:
377 c = 1;
378 break;
379 case GL_SEPARABLE_2D:
380 c = 2;
381 break;
382 default:
Brian Paul08836342001-03-03 20:33:27 +0000383 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000384 return;
385 }
386
387 switch (pname) {
388 case GL_CONVOLUTION_BORDER_MODE:
389 if (param == (GLint) GL_REDUCE ||
390 param == (GLint) GL_CONSTANT_BORDER ||
391 param == (GLint) GL_REPLICATE_BORDER) {
392 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
393 }
394 else {
Brian Paul08836342001-03-03 20:33:27 +0000395 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000396 return;
397 }
398 break;
399 default:
Brian Paul08836342001-03-03 20:33:27 +0000400 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000401 return;
402 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000403
404 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000405}
406
407
408void
409_mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params)
410{
411 GET_CURRENT_CONTEXT(ctx);
412 struct gl_convolution_attrib *conv;
413 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000414 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000415
416 switch (target) {
417 case GL_CONVOLUTION_1D:
418 c = 0;
419 conv = &ctx->Convolution1D;
420 break;
421 case GL_CONVOLUTION_2D:
422 c = 1;
423 conv = &ctx->Convolution2D;
424 break;
425 case GL_SEPARABLE_2D:
426 c = 2;
427 conv = &ctx->Separable2D;
428 break;
429 default:
Brian Paul08836342001-03-03 20:33:27 +0000430 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000431 return;
432 }
433
434 switch (pname) {
435 case GL_CONVOLUTION_BORDER_COLOR:
436 ctx->Pixel.ConvolutionBorderColor[c][0] = INT_TO_FLOAT(params[0]);
437 ctx->Pixel.ConvolutionBorderColor[c][1] = INT_TO_FLOAT(params[1]);
438 ctx->Pixel.ConvolutionBorderColor[c][2] = INT_TO_FLOAT(params[2]);
439 ctx->Pixel.ConvolutionBorderColor[c][3] = INT_TO_FLOAT(params[3]);
440 break;
441 case GL_CONVOLUTION_BORDER_MODE:
442 if (params[0] == (GLint) GL_REDUCE ||
443 params[0] == (GLint) GL_CONSTANT_BORDER ||
444 params[0] == (GLint) GL_REPLICATE_BORDER) {
445 ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0];
446 }
447 else {
Brian Paul08836342001-03-03 20:33:27 +0000448 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(params)");
Brian Paul147b0832000-08-23 14:31:25 +0000449 return;
450 }
451 break;
452 case GL_CONVOLUTION_FILTER_SCALE:
Karl Schultz7c426812001-09-19 20:30:44 +0000453 /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
454 /* need cast to prevent compiler warnings */
455 ctx->Pixel.ConvolutionFilterScale[c][0] = (GLfloat) params[0];
456 ctx->Pixel.ConvolutionFilterScale[c][1] = (GLfloat) params[1];
457 ctx->Pixel.ConvolutionFilterScale[c][2] = (GLfloat) params[2];
458 ctx->Pixel.ConvolutionFilterScale[c][3] = (GLfloat) params[3];
Brian Paul147b0832000-08-23 14:31:25 +0000459 break;
460 case GL_CONVOLUTION_FILTER_BIAS:
Karl Schultz7c426812001-09-19 20:30:44 +0000461 /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
462 /* need cast to prevent compiler warnings */
463 ctx->Pixel.ConvolutionFilterBias[c][0] = (GLfloat) params[0];
464 ctx->Pixel.ConvolutionFilterBias[c][1] = (GLfloat) params[1];
465 ctx->Pixel.ConvolutionFilterBias[c][2] = (GLfloat) params[2];
466 ctx->Pixel.ConvolutionFilterBias[c][3] = (GLfloat) params[3];
Brian Paul147b0832000-08-23 14:31:25 +0000467 break;
468 default:
Brian Paul08836342001-03-03 20:33:27 +0000469 _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000470 return;
471 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000472
473 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000474}
475
476
477void
478_mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width)
479{
480 GLenum baseFormat;
Brian Paul147b0832000-08-23 14:31:25 +0000481 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000482 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000483
484 if (target != GL_CONVOLUTION_1D) {
Brian Paul08836342001-03-03 20:33:27 +0000485 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000486 return;
487 }
488
489 baseFormat = base_filter_format(internalFormat);
490 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000491 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000492 return;
493 }
494
495 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000496 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter1D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000497 return;
498 }
499
Keith Whitwell70989242001-03-19 02:25:35 +0000500 ctx->Driver.CopyConvolutionFilter1D( ctx, target,
501 internalFormat, x, y, width);
Brian Paul147b0832000-08-23 14:31:25 +0000502}
503
504
505void
506_mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height)
507{
508 GLenum baseFormat;
Brian Paul147b0832000-08-23 14:31:25 +0000509 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000510 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000511
512 if (target != GL_CONVOLUTION_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000513 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000514 return;
515 }
516
517 baseFormat = base_filter_format(internalFormat);
518 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000519 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000520 return;
521 }
522
523 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000524 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000525 return;
526 }
527 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
Brian Paul08836342001-03-03 20:33:27 +0000528 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(height)");
Brian Paul147b0832000-08-23 14:31:25 +0000529 return;
530 }
531
Keith Whitwell70989242001-03-19 02:25:35 +0000532 ctx->Driver.CopyConvolutionFilter2D( ctx, target, internalFormat, x, y,
533 width, height );
Brian Paul147b0832000-08-23 14:31:25 +0000534
Brian Paul147b0832000-08-23 14:31:25 +0000535}
536
537
538void
539_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid *image)
540{
Brian Paulf75d6972000-09-05 20:28:56 +0000541 const struct gl_convolution_attrib *filter;
Brian Paulb51b0a82001-03-07 05:06:11 +0000542 GLuint row;
Brian Paul147b0832000-08-23 14:31:25 +0000543 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000544 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000545
Brian Paul0c000ec2000-11-21 23:26:13 +0000546 if (ctx->NewState) {
Brian Paul08836342001-03-03 20:33:27 +0000547 _mesa_update_state(ctx);
Brian Paul0c000ec2000-11-21 23:26:13 +0000548 }
549
Brian Paul90f042a2000-12-10 19:23:19 +0000550 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000551 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000552 return;
553 }
554
555 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000556 format == GL_STENCIL_INDEX ||
557 format == GL_DEPTH_COMPONENT ||
558 format == GL_INTENSITY ||
559 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000560 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000561 return;
562 }
563
Brian Paulf75d6972000-09-05 20:28:56 +0000564 switch (target) {
565 case GL_CONVOLUTION_1D:
566 filter = &(ctx->Convolution1D);
567 break;
568 case GL_CONVOLUTION_2D:
569 filter = &(ctx->Convolution2D);
570 break;
571 default:
Brian Paul08836342001-03-03 20:33:27 +0000572 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(target)");
Brian Paulf75d6972000-09-05 20:28:56 +0000573 return;
574 }
575
576 for (row = 0; row < filter->Height; row++) {
577 GLvoid *dst = _mesa_image_address( &ctx->Pack, image, filter->Width,
578 filter->Height, format, type,
579 0, row, 0);
580 const GLfloat *src = filter->Filter + row * filter->Width * 4;
Brian Paulf75d6972000-09-05 20:28:56 +0000581 _mesa_pack_float_rgba_span(ctx, filter->Width,
582 (const GLfloat (*)[4]) src,
583 format, type, dst, &ctx->Pack, 0);
584 }
Brian Paul147b0832000-08-23 14:31:25 +0000585}
586
587
588void
589_mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params)
590{
591 GET_CURRENT_CONTEXT(ctx);
592 const struct gl_convolution_attrib *conv;
593 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000594 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000595
596 switch (target) {
597 case GL_CONVOLUTION_1D:
598 c = 0;
599 conv = &ctx->Convolution1D;
600 break;
601 case GL_CONVOLUTION_2D:
602 c = 1;
603 conv = &ctx->Convolution2D;
604 break;
605 case GL_SEPARABLE_2D:
606 c = 2;
607 conv = &ctx->Separable2D;
608 break;
609 default:
Brian Paul08836342001-03-03 20:33:27 +0000610 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000611 return;
612 }
613
614 switch (pname) {
615 case GL_CONVOLUTION_BORDER_COLOR:
616 COPY_4V(params, ctx->Pixel.ConvolutionBorderColor[c]);
617 break;
618 case GL_CONVOLUTION_BORDER_MODE:
619 *params = (GLfloat) ctx->Pixel.ConvolutionBorderMode[c];
620 break;
621 case GL_CONVOLUTION_FILTER_SCALE:
622 COPY_4V(params, ctx->Pixel.ConvolutionFilterScale[c]);
623 break;
624 case GL_CONVOLUTION_FILTER_BIAS:
625 COPY_4V(params, ctx->Pixel.ConvolutionFilterBias[c]);
626 break;
627 case GL_CONVOLUTION_FORMAT:
628 *params = (GLfloat) conv->Format;
629 break;
630 case GL_CONVOLUTION_WIDTH:
631 *params = (GLfloat) conv->Width;
632 break;
633 case GL_CONVOLUTION_HEIGHT:
634 *params = (GLfloat) conv->Height;
635 break;
636 case GL_MAX_CONVOLUTION_WIDTH:
637 *params = (GLfloat) ctx->Const.MaxConvolutionWidth;
638 break;
639 case GL_MAX_CONVOLUTION_HEIGHT:
640 *params = (GLfloat) ctx->Const.MaxConvolutionHeight;
641 break;
642 default:
Brian Paul08836342001-03-03 20:33:27 +0000643 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000644 return;
645 }
646}
647
648
649void
650_mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params)
651{
652 GET_CURRENT_CONTEXT(ctx);
653 const struct gl_convolution_attrib *conv;
654 GLuint c;
Keith Whitwellcab974c2000-12-26 05:09:27 +0000655 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000656
657 switch (target) {
658 case GL_CONVOLUTION_1D:
659 c = 0;
660 conv = &ctx->Convolution1D;
661 break;
662 case GL_CONVOLUTION_2D:
663 c = 1;
664 conv = &ctx->Convolution2D;
665 break;
666 case GL_SEPARABLE_2D:
667 c = 2;
668 conv = &ctx->Separable2D;
669 break;
670 default:
Brian Paul08836342001-03-03 20:33:27 +0000671 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000672 return;
673 }
674
675 switch (pname) {
676 case GL_CONVOLUTION_BORDER_COLOR:
677 params[0] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][0]);
678 params[1] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][1]);
679 params[2] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][2]);
680 params[3] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][3]);
681 break;
682 case GL_CONVOLUTION_BORDER_MODE:
683 *params = (GLint) ctx->Pixel.ConvolutionBorderMode[c];
684 break;
685 case GL_CONVOLUTION_FILTER_SCALE:
686 params[0] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][0];
687 params[1] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][1];
688 params[2] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][2];
689 params[3] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][3];
690 break;
691 case GL_CONVOLUTION_FILTER_BIAS:
692 params[0] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][0];
693 params[1] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][1];
694 params[2] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][2];
695 params[3] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][3];
696 break;
697 case GL_CONVOLUTION_FORMAT:
698 *params = (GLint) conv->Format;
699 break;
700 case GL_CONVOLUTION_WIDTH:
701 *params = (GLint) conv->Width;
702 break;
703 case GL_CONVOLUTION_HEIGHT:
704 *params = (GLint) conv->Height;
705 break;
706 case GL_MAX_CONVOLUTION_WIDTH:
707 *params = (GLint) ctx->Const.MaxConvolutionWidth;
708 break;
709 case GL_MAX_CONVOLUTION_HEIGHT:
710 *params = (GLint) ctx->Const.MaxConvolutionHeight;
711 break;
712 default:
Brian Paul08836342001-03-03 20:33:27 +0000713 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(pname)");
Brian Paul147b0832000-08-23 14:31:25 +0000714 return;
715 }
716}
717
718
719void
720_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span)
721{
Brian Paulf75d6972000-09-05 20:28:56 +0000722 const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
723 const struct gl_convolution_attrib *filter;
Brian Paul147b0832000-08-23 14:31:25 +0000724 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000725 ASSERT_OUTSIDE_BEGIN_END(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000726
Brian Paul0c000ec2000-11-21 23:26:13 +0000727 if (ctx->NewState) {
Brian Paul08836342001-03-03 20:33:27 +0000728 _mesa_update_state(ctx);
Brian Paul0c000ec2000-11-21 23:26:13 +0000729 }
730
Brian Paul147b0832000-08-23 14:31:25 +0000731 if (target != GL_SEPARABLE_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000732 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000733 return;
734 }
735
Brian Paul90f042a2000-12-10 19:23:19 +0000736 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000737 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000738 return;
739 }
740
741 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000742 format == GL_STENCIL_INDEX ||
743 format == GL_DEPTH_COMPONENT ||
744 format == GL_INTENSITY ||
745 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000746 _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000747 return;
748 }
749
Brian Paulf75d6972000-09-05 20:28:56 +0000750 filter = &ctx->Separable2D;
751
752 /* Row filter */
753 {
754 GLvoid *dst = _mesa_image_address( &ctx->Pack, row, filter->Width,
755 filter->Height, format, type,
756 0, 0, 0);
757 _mesa_pack_float_rgba_span(ctx, filter->Width,
758 (const GLfloat (*)[4]) filter->Filter,
759 format, type, dst, &ctx->Pack, 0);
760 }
761
762 /* Column filter */
763 {
764 GLvoid *dst = _mesa_image_address( &ctx->Pack, column, filter->Width,
765 1, format, type,
766 0, 0, 0);
767 const GLfloat *src = filter->Filter + colStart;
768 _mesa_pack_float_rgba_span(ctx, filter->Height,
769 (const GLfloat (*)[4]) src,
770 format, type, dst, &ctx->Pack, 0);
771 }
772
773 (void) span; /* unused at this time */
Brian Paul147b0832000-08-23 14:31:25 +0000774}
775
776
777void
778_mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column)
779{
780 const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
781 GLenum baseFormat;
782 GET_CURRENT_CONTEXT(ctx);
Keith Whitwellcab974c2000-12-26 05:09:27 +0000783 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
Brian Paul147b0832000-08-23 14:31:25 +0000784
785 if (target != GL_SEPARABLE_2D) {
Brian Paul08836342001-03-03 20:33:27 +0000786 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(target)");
Brian Paul147b0832000-08-23 14:31:25 +0000787 return;
788 }
789
790 baseFormat = base_filter_format(internalFormat);
791 if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
Brian Paul08836342001-03-03 20:33:27 +0000792 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(internalFormat)");
Brian Paul147b0832000-08-23 14:31:25 +0000793 return;
794 }
795
796 if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
Brian Paul08836342001-03-03 20:33:27 +0000797 _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(width)");
Brian Paul147b0832000-08-23 14:31:25 +0000798 return;
799 }
800 if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
Brian Paul08836342001-03-03 20:33:27 +0000801 _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(height)");
Brian Paul147b0832000-08-23 14:31:25 +0000802 return;
803 }
804
Brian Paul90f042a2000-12-10 19:23:19 +0000805 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paul08836342001-03-03 20:33:27 +0000806 _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(format or type)");
Brian Paul90f042a2000-12-10 19:23:19 +0000807 return;
808 }
809
810 if (format == GL_COLOR_INDEX ||
Brian Paul147b0832000-08-23 14:31:25 +0000811 format == GL_STENCIL_INDEX ||
812 format == GL_DEPTH_COMPONENT ||
813 format == GL_INTENSITY ||
814 type == GL_BITMAP) {
Brian Paul08836342001-03-03 20:33:27 +0000815 _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(format or type)");
Brian Paul147b0832000-08-23 14:31:25 +0000816 return;
817 }
818
819 ctx->Separable2D.Format = format;
820 ctx->Separable2D.InternalFormat = internalFormat;
821 ctx->Separable2D.Width = width;
822 ctx->Separable2D.Height = height;
823
824 /* unpack row filter */
825 _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
826 ctx->Separable2D.Filter,
827 format, type, row, &ctx->Unpack,
828 0, GL_FALSE);
829
830 /* apply scale and bias */
831 {
832 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
833 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
834 GLint i;
835 for (i = 0; i < width; i++) {
836 GLfloat r = ctx->Separable2D.Filter[i * 4 + 0];
837 GLfloat g = ctx->Separable2D.Filter[i * 4 + 1];
838 GLfloat b = ctx->Separable2D.Filter[i * 4 + 2];
839 GLfloat a = ctx->Separable2D.Filter[i * 4 + 3];
840 r = r * scale[0] + bias[0];
841 g = g * scale[1] + bias[1];
842 b = b * scale[2] + bias[2];
843 a = a * scale[3] + bias[3];
844 ctx->Separable2D.Filter[i * 4 + 0] = r;
845 ctx->Separable2D.Filter[i * 4 + 1] = g;
846 ctx->Separable2D.Filter[i * 4 + 2] = b;
847 ctx->Separable2D.Filter[i * 4 + 3] = a;
848 }
849 }
850
851 /* unpack column filter */
852 _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
853 &ctx->Separable2D.Filter[colStart],
854 format, type, column, &ctx->Unpack,
855 0, GL_FALSE);
856
857 /* apply scale and bias */
858 {
859 const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
860 const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
861 GLint i;
862 for (i = 0; i < width; i++) {
863 GLfloat r = ctx->Separable2D.Filter[i * 4 + 0 + colStart];
864 GLfloat g = ctx->Separable2D.Filter[i * 4 + 1 + colStart];
865 GLfloat b = ctx->Separable2D.Filter[i * 4 + 2 + colStart];
866 GLfloat a = ctx->Separable2D.Filter[i * 4 + 3 + colStart];
867 r = r * scale[0] + bias[0];
868 g = g * scale[1] + bias[1];
869 b = b * scale[2] + bias[2];
870 a = a * scale[3] + bias[3];
871 ctx->Separable2D.Filter[i * 4 + 0 + colStart] = r;
872 ctx->Separable2D.Filter[i * 4 + 1 + colStart] = g;
873 ctx->Separable2D.Filter[i * 4 + 2 + colStart] = b;
874 ctx->Separable2D.Filter[i * 4 + 3 + colStart] = a;
875 }
876 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000877
Brian Paulb5012e12000-11-10 18:31:04 +0000878 ctx->NewState |= _NEW_PIXEL;
Brian Paul147b0832000-08-23 14:31:25 +0000879}
880
881
882/**********************************************************************/
883/*** image convolution functions ***/
884/**********************************************************************/
885
Brian Pauld4b799b2000-08-21 14:24:30 +0000886static void
887convolve_1d_reduce(GLint srcWidth, const GLfloat src[][4],
888 GLint filterWidth, const GLfloat filter[][4],
889 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +0000890{
Brian Paul7e708742000-08-22 18:54:25 +0000891 GLint dstWidth;
Brian Paulcc8e37f2000-07-12 13:00:09 +0000892 GLint i, n;
893
Brian Paul7e708742000-08-22 18:54:25 +0000894 if (filterWidth >= 1)
895 dstWidth = srcWidth - (filterWidth - 1);
896 else
897 dstWidth = srcWidth;
898
Brian Paulcc8e37f2000-07-12 13:00:09 +0000899 if (dstWidth <= 0)
900 return; /* null result */
901
902 for (i = 0; i < dstWidth; i++) {
903 GLfloat sumR = 0.0;
904 GLfloat sumG = 0.0;
905 GLfloat sumB = 0.0;
906 GLfloat sumA = 0.0;
907 for (n = 0; n < filterWidth; n++) {
908 sumR += src[i + n][RCOMP] * filter[n][RCOMP];
909 sumG += src[i + n][GCOMP] * filter[n][GCOMP];
910 sumB += src[i + n][BCOMP] * filter[n][BCOMP];
911 sumA += src[i + n][ACOMP] * filter[n][ACOMP];
912 }
913 dest[i][RCOMP] = sumR;
914 dest[i][GCOMP] = sumG;
915 dest[i][BCOMP] = sumB;
916 dest[i][ACOMP] = sumA;
917 }
918}
919
920
Brian Pauld4b799b2000-08-21 14:24:30 +0000921static void
922convolve_1d_constant(GLint srcWidth, const GLfloat src[][4],
923 GLint filterWidth, const GLfloat filter[][4],
924 GLfloat dest[][4],
925 const GLfloat borderColor[4])
Brian Paulcc8e37f2000-07-12 13:00:09 +0000926{
927 const GLint halfFilterWidth = filterWidth / 2;
928 GLint i, n;
929
930 for (i = 0; i < srcWidth; i++) {
931 GLfloat sumR = 0.0;
932 GLfloat sumG = 0.0;
933 GLfloat sumB = 0.0;
934 GLfloat sumA = 0.0;
935 for (n = 0; n < filterWidth; n++) {
936 if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) {
937 sumR += borderColor[RCOMP] * filter[n][RCOMP];
938 sumG += borderColor[GCOMP] * filter[n][GCOMP];
939 sumB += borderColor[BCOMP] * filter[n][BCOMP];
940 sumA += borderColor[ACOMP] * filter[n][ACOMP];
941 }
942 else {
943 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
944 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
945 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
946 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
947 }
948 }
949 dest[i][RCOMP] = sumR;
950 dest[i][GCOMP] = sumG;
951 dest[i][BCOMP] = sumB;
952 dest[i][ACOMP] = sumA;
953 }
954}
955
956
Brian Pauld4b799b2000-08-21 14:24:30 +0000957static void
958convolve_1d_replicate(GLint srcWidth, const GLfloat src[][4],
959 GLint filterWidth, const GLfloat filter[][4],
960 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +0000961{
962 const GLint halfFilterWidth = filterWidth / 2;
963 GLint i, n;
964
965 for (i = 0; i < srcWidth; i++) {
966 GLfloat sumR = 0.0;
967 GLfloat sumG = 0.0;
968 GLfloat sumB = 0.0;
969 GLfloat sumA = 0.0;
970 for (n = 0; n < filterWidth; n++) {
971 if (i + n < halfFilterWidth) {
972 sumR += src[0][RCOMP] * filter[n][RCOMP];
973 sumG += src[0][GCOMP] * filter[n][GCOMP];
974 sumB += src[0][BCOMP] * filter[n][BCOMP];
975 sumA += src[0][ACOMP] * filter[n][ACOMP];
976 }
977 else if (i + n - halfFilterWidth >= srcWidth) {
978 sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP];
979 sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP];
980 sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP];
981 sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP];
982 }
983 else {
984 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
985 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
986 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
987 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
988 }
989 }
990 dest[i][RCOMP] = sumR;
991 dest[i][GCOMP] = sumG;
992 dest[i][BCOMP] = sumB;
993 dest[i][ACOMP] = sumA;
994 }
995}
996
997
Brian Pauld4b799b2000-08-21 14:24:30 +0000998static void
999convolve_2d_reduce(GLint srcWidth, GLint srcHeight,
1000 const GLfloat src[][4],
1001 GLint filterWidth, GLint filterHeight,
1002 const GLfloat filter[][4],
1003 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001004{
Brian Paul7e708742000-08-22 18:54:25 +00001005 GLint dstWidth, dstHeight;
Brian Pauld4b799b2000-08-21 14:24:30 +00001006 GLint i, j, n, m;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001007
Brian Paul7e708742000-08-22 18:54:25 +00001008 if (filterWidth >= 1)
1009 dstWidth = srcWidth - (filterWidth - 1);
1010 else
1011 dstWidth = srcWidth;
1012
1013 if (filterHeight >= 1)
1014 dstHeight = srcHeight - (filterHeight - 1);
1015 else
1016 dstHeight = srcHeight;
1017
Brian Pauld4b799b2000-08-21 14:24:30 +00001018 if (dstWidth <= 0 || dstHeight <= 0)
1019 return;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001020
Brian Pauld4b799b2000-08-21 14:24:30 +00001021 for (j = 0; j < dstHeight; j++) {
1022 for (i = 0; i < dstWidth; i++) {
1023 GLfloat sumR = 0.0;
1024 GLfloat sumG = 0.0;
1025 GLfloat sumB = 0.0;
1026 GLfloat sumA = 0.0;
1027 for (m = 0; m < filterHeight; m++) {
1028 for (n = 0; n < filterWidth; n++) {
1029 const GLint k = (j + m) * srcWidth + i + n;
1030 const GLint f = m * filterWidth + n;
1031 sumR += src[k][RCOMP] * filter[f][RCOMP];
1032 sumG += src[k][GCOMP] * filter[f][GCOMP];
1033 sumB += src[k][BCOMP] * filter[f][BCOMP];
1034 sumA += src[k][ACOMP] * filter[f][ACOMP];
1035 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001036 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001037 dest[j * dstWidth + i][RCOMP] = sumR;
1038 dest[j * dstWidth + i][GCOMP] = sumG;
1039 dest[j * dstWidth + i][BCOMP] = sumB;
1040 dest[j * dstWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001041 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001042 }
1043}
1044
1045
Brian Pauld4b799b2000-08-21 14:24:30 +00001046static void
1047convolve_2d_constant(GLint srcWidth, GLint srcHeight,
1048 const GLfloat src[][4],
1049 GLint filterWidth, GLint filterHeight,
1050 const GLfloat filter[][4],
1051 GLfloat dest[][4],
1052 const GLfloat borderColor[4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001053{
1054 const GLint halfFilterWidth = filterWidth / 2;
Brian Pauld4b799b2000-08-21 14:24:30 +00001055 const GLint halfFilterHeight = filterHeight / 2;
1056 GLint i, j, n, m;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001057
Brian Pauld4b799b2000-08-21 14:24:30 +00001058 for (j = 0; j < srcHeight; j++) {
1059 for (i = 0; i < srcWidth; i++) {
1060 GLfloat sumR = 0.0;
1061 GLfloat sumG = 0.0;
1062 GLfloat sumB = 0.0;
1063 GLfloat sumA = 0.0;
1064 for (m = 0; m < filterHeight; m++) {
1065 for (n = 0; n < filterWidth; n++) {
1066 const GLint f = m * filterWidth + n;
1067 const GLint is = i + n - halfFilterWidth;
1068 const GLint js = j + m - halfFilterHeight;
1069 if (is < 0 || is >= srcWidth ||
1070 js < 0 || js >= srcHeight) {
1071 sumR += borderColor[RCOMP] * filter[f][RCOMP];
1072 sumG += borderColor[GCOMP] * filter[f][GCOMP];
1073 sumB += borderColor[BCOMP] * filter[f][BCOMP];
1074 sumA += borderColor[ACOMP] * filter[f][ACOMP];
1075 }
1076 else {
1077 const GLint k = js * srcWidth + is;
1078 sumR += src[k][RCOMP] * filter[f][RCOMP];
1079 sumG += src[k][GCOMP] * filter[f][GCOMP];
1080 sumB += src[k][BCOMP] * filter[f][BCOMP];
1081 sumA += src[k][ACOMP] * filter[f][ACOMP];
1082 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001083 }
1084 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001085 dest[j * srcWidth + i][RCOMP] = sumR;
1086 dest[j * srcWidth + i][GCOMP] = sumG;
1087 dest[j * srcWidth + i][BCOMP] = sumB;
1088 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001089 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001090 }
1091}
1092
1093
Brian Pauld4b799b2000-08-21 14:24:30 +00001094static void
1095convolve_2d_replicate(GLint srcWidth, GLint srcHeight,
1096 const GLfloat src[][4],
1097 GLint filterWidth, GLint filterHeight,
1098 const GLfloat filter[][4],
1099 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001100{
1101 const GLint halfFilterWidth = filterWidth / 2;
Brian Pauld4b799b2000-08-21 14:24:30 +00001102 const GLint halfFilterHeight = filterHeight / 2;
1103 GLint i, j, n, m;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001104
Brian Pauld4b799b2000-08-21 14:24:30 +00001105 for (j = 0; j < srcHeight; j++) {
1106 for (i = 0; i < srcWidth; i++) {
1107 GLfloat sumR = 0.0;
1108 GLfloat sumG = 0.0;
1109 GLfloat sumB = 0.0;
1110 GLfloat sumA = 0.0;
1111 for (m = 0; m < filterHeight; m++) {
1112 for (n = 0; n < filterWidth; n++) {
1113 const GLint f = m * filterWidth + n;
1114 GLint is = i + n - halfFilterWidth;
1115 GLint js = j + m - halfFilterHeight;
1116 GLint k;
1117 if (is < 0)
1118 is = 0;
1119 else if (is >= srcWidth)
1120 is = srcWidth - 1;
1121 if (js < 0)
1122 js = 0;
1123 else if (js >= srcHeight)
1124 js = srcHeight - 1;
1125 k = js * srcWidth + is;
1126 sumR += src[k][RCOMP] * filter[f][RCOMP];
1127 sumG += src[k][GCOMP] * filter[f][GCOMP];
1128 sumB += src[k][BCOMP] * filter[f][BCOMP];
1129 sumA += src[k][ACOMP] * filter[f][ACOMP];
Brian Paulcc8e37f2000-07-12 13:00:09 +00001130 }
1131 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001132 dest[j * srcWidth + i][RCOMP] = sumR;
1133 dest[j * srcWidth + i][GCOMP] = sumG;
1134 dest[j * srcWidth + i][BCOMP] = sumB;
1135 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001136 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001137 }
1138}
1139
1140
Brian Pauld4b799b2000-08-21 14:24:30 +00001141static void
1142convolve_sep_reduce(GLint srcWidth, GLint srcHeight,
1143 const GLfloat src[][4],
1144 GLint filterWidth, GLint filterHeight,
1145 const GLfloat rowFilt[][4],
1146 const GLfloat colFilt[][4],
1147 GLfloat dest[][4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001148{
Brian Paul7e708742000-08-22 18:54:25 +00001149 GLint dstWidth, dstHeight;
Brian Pauld4b799b2000-08-21 14:24:30 +00001150 GLint i, j, n, m;
Brian Paul7e708742000-08-22 18:54:25 +00001151
1152 if (filterWidth >= 1)
1153 dstWidth = srcWidth - (filterWidth - 1);
1154 else
1155 dstWidth = srcWidth;
1156
1157 if (filterHeight >= 1)
1158 dstHeight = srcHeight - (filterHeight - 1);
1159 else
1160 dstHeight = srcHeight;
1161
1162 if (dstWidth <= 0 || dstHeight <= 0)
1163 return;
1164
1165 for (j = 0; j < dstHeight; j++) {
1166 for (i = 0; i < dstWidth; i++) {
Brian Pauld4b799b2000-08-21 14:24:30 +00001167 GLfloat sumR = 0.0;
1168 GLfloat sumG = 0.0;
1169 GLfloat sumB = 0.0;
1170 GLfloat sumA = 0.0;
1171 for (m = 0; m < filterHeight; m++) {
1172 for (n = 0; n < filterWidth; n++) {
Brian Paul7e708742000-08-22 18:54:25 +00001173 GLint k = (j + m) * srcWidth + i + n;
1174 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1175 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1176 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1177 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
Brian Paulcc8e37f2000-07-12 13:00:09 +00001178 }
1179 }
Brian Paul7e708742000-08-22 18:54:25 +00001180 dest[j * dstWidth + i][RCOMP] = sumR;
1181 dest[j * dstWidth + i][GCOMP] = sumG;
1182 dest[j * dstWidth + i][BCOMP] = sumB;
1183 dest[j * dstWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001184 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001185 }
Brian Paulcc8e37f2000-07-12 13:00:09 +00001186}
1187
1188
Brian Pauld4b799b2000-08-21 14:24:30 +00001189static void
1190convolve_sep_constant(GLint srcWidth, GLint srcHeight,
1191 const GLfloat src[][4],
1192 GLint filterWidth, GLint filterHeight,
1193 const GLfloat rowFilt[][4],
1194 const GLfloat colFilt[][4],
1195 GLfloat dest[][4],
1196 const GLfloat borderColor[4])
Brian Paulcc8e37f2000-07-12 13:00:09 +00001197{
1198 const GLint halfFilterWidth = filterWidth / 2;
Brian Pauld4b799b2000-08-21 14:24:30 +00001199 const GLint halfFilterHeight = filterHeight / 2;
1200 GLint i, j, n, m;
Brian Paul7e708742000-08-22 18:54:25 +00001201
Brian Pauld4b799b2000-08-21 14:24:30 +00001202 for (j = 0; j < srcHeight; j++) {
1203 for (i = 0; i < srcWidth; i++) {
1204 GLfloat sumR = 0.0;
1205 GLfloat sumG = 0.0;
1206 GLfloat sumB = 0.0;
1207 GLfloat sumA = 0.0;
1208 for (m = 0; m < filterHeight; m++) {
1209 for (n = 0; n < filterWidth; n++) {
Brian Paul7e708742000-08-22 18:54:25 +00001210 const GLint is = i + n - halfFilterWidth;
1211 const GLint js = j + m - halfFilterHeight;
1212 if (is < 0 || is >= srcWidth ||
1213 js < 0 || js >= srcHeight) {
Brian Pauld4b799b2000-08-21 14:24:30 +00001214 sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1215 sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1216 sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1217 sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1218 }
1219 else {
Brian Paul7e708742000-08-22 18:54:25 +00001220 GLint k = js * srcWidth + is;
Brian Pauld4b799b2000-08-21 14:24:30 +00001221 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1222 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1223 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1224 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1225 }
Brian Paul7e708742000-08-22 18:54:25 +00001226
Brian Paulcc8e37f2000-07-12 13:00:09 +00001227 }
1228 }
Brian Paul7e708742000-08-22 18:54:25 +00001229 dest[j * srcWidth + i][RCOMP] = sumR;
1230 dest[j * srcWidth + i][GCOMP] = sumG;
1231 dest[j * srcWidth + i][BCOMP] = sumB;
1232 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001233 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001234 }
Brian Pauld4b799b2000-08-21 14:24:30 +00001235}
1236
1237
1238static void
1239convolve_sep_replicate(GLint srcWidth, GLint srcHeight,
1240 const GLfloat src[][4],
1241 GLint filterWidth, GLint filterHeight,
1242 const GLfloat rowFilt[][4],
1243 const GLfloat colFilt[][4],
1244 GLfloat dest[][4])
1245{
1246 const GLint halfFilterWidth = filterWidth / 2;
1247 const GLint halfFilterHeight = filterHeight / 2;
1248 GLint i, j, n, m;
1249
1250 for (j = 0; j < srcHeight; j++) {
1251 for (i = 0; i < srcWidth; i++) {
1252 GLfloat sumR = 0.0;
1253 GLfloat sumG = 0.0;
1254 GLfloat sumB = 0.0;
1255 GLfloat sumA = 0.0;
1256 for (m = 0; m < filterHeight; m++) {
1257 for (n = 0; n < filterWidth; n++) {
Brian Paul7e708742000-08-22 18:54:25 +00001258 GLint is = i + n - halfFilterWidth;
1259 GLint js = j + m - halfFilterHeight;
1260 GLint k;
1261 if (is < 0)
1262 is = 0;
1263 else if (is >= srcWidth)
1264 is = srcWidth - 1;
1265 if (js < 0)
1266 js = 0;
1267 else if (js >= srcHeight)
1268 js = srcHeight - 1;
1269 k = js * srcWidth + is;
1270 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1271 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1272 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1273 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
Brian Pauld4b799b2000-08-21 14:24:30 +00001274 }
1275 }
Brian Paul7e708742000-08-22 18:54:25 +00001276 dest[j * srcWidth + i][RCOMP] = sumR;
1277 dest[j * srcWidth + i][GCOMP] = sumG;
1278 dest[j * srcWidth + i][BCOMP] = sumB;
1279 dest[j * srcWidth + i][ACOMP] = sumA;
Brian Pauld4b799b2000-08-21 14:24:30 +00001280 }
1281 }
1282}
1283
1284
1285
1286void
1287_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
1288 const GLfloat *srcImage, GLfloat *dstImage)
1289{
1290 switch (ctx->Pixel.ConvolutionBorderMode[0]) {
1291 case GL_REDUCE:
1292 convolve_1d_reduce(*width, (const GLfloat (*)[4]) srcImage,
1293 ctx->Convolution1D.Width,
1294 (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1295 (GLfloat (*)[4]) dstImage);
Brian Paul7e708742000-08-22 18:54:25 +00001296 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
Brian Pauld4b799b2000-08-21 14:24:30 +00001297 break;
1298 case GL_CONSTANT_BORDER:
1299 convolve_1d_constant(*width, (const GLfloat (*)[4]) srcImage,
1300 ctx->Convolution1D.Width,
1301 (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1302 (GLfloat (*)[4]) dstImage,
1303 ctx->Pixel.ConvolutionBorderColor[0]);
1304 break;
1305 case GL_REPLICATE_BORDER:
1306 convolve_1d_replicate(*width, (const GLfloat (*)[4]) srcImage,
1307 ctx->Convolution1D.Width,
1308 (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1309 (GLfloat (*)[4]) dstImage);
1310 break;
1311 default:
1312 ;
1313 }
1314}
1315
1316
1317void
1318_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
1319 const GLfloat *srcImage, GLfloat *dstImage)
1320{
1321 switch (ctx->Pixel.ConvolutionBorderMode[1]) {
1322 case GL_REDUCE:
1323 convolve_2d_reduce(*width, *height,
1324 (const GLfloat (*)[4]) srcImage,
1325 ctx->Convolution2D.Width,
1326 ctx->Convolution2D.Height,
1327 (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
1328 (GLfloat (*)[4]) dstImage);
Brian Paul7e708742000-08-22 18:54:25 +00001329 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
1330 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
Brian Pauld4b799b2000-08-21 14:24:30 +00001331 break;
1332 case GL_CONSTANT_BORDER:
1333 convolve_2d_constant(*width, *height,
1334 (const GLfloat (*)[4]) srcImage,
1335 ctx->Convolution2D.Width,
1336 ctx->Convolution2D.Height,
1337 (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
1338 (GLfloat (*)[4]) dstImage,
1339 ctx->Pixel.ConvolutionBorderColor[1]);
1340 break;
1341 case GL_REPLICATE_BORDER:
1342 convolve_2d_replicate(*width, *height,
1343 (const GLfloat (*)[4]) srcImage,
1344 ctx->Convolution2D.Width,
1345 ctx->Convolution2D.Height,
1346 (const GLfloat (*)[4])ctx->Convolution2D.Filter,
1347 (GLfloat (*)[4]) dstImage);
1348 break;
1349 default:
1350 ;
1351 }
1352}
1353
1354
1355void
1356_mesa_convolve_sep_image(const GLcontext *ctx,
1357 GLsizei *width, GLsizei *height,
1358 const GLfloat *srcImage, GLfloat *dstImage)
1359{
1360 const GLfloat *rowFilter = ctx->Separable2D.Filter;
1361 const GLfloat *colFilter = rowFilter + 4 * MAX_CONVOLUTION_WIDTH;
1362
1363 switch (ctx->Pixel.ConvolutionBorderMode[2]) {
1364 case GL_REDUCE:
1365 convolve_sep_reduce(*width, *height,
1366 (const GLfloat (*)[4]) srcImage,
Brian Paul7e708742000-08-22 18:54:25 +00001367 ctx->Separable2D.Width,
1368 ctx->Separable2D.Height,
Brian Pauld4b799b2000-08-21 14:24:30 +00001369 (const GLfloat (*)[4]) rowFilter,
1370 (const GLfloat (*)[4]) colFilter,
1371 (GLfloat (*)[4]) dstImage);
Brian Paul7e708742000-08-22 18:54:25 +00001372 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
1373 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
Brian Pauld4b799b2000-08-21 14:24:30 +00001374 break;
1375 case GL_CONSTANT_BORDER:
1376 convolve_sep_constant(*width, *height,
1377 (const GLfloat (*)[4]) srcImage,
Brian Paul7e708742000-08-22 18:54:25 +00001378 ctx->Separable2D.Width,
1379 ctx->Separable2D.Height,
Brian Pauld4b799b2000-08-21 14:24:30 +00001380 (const GLfloat (*)[4]) rowFilter,
1381 (const GLfloat (*)[4]) colFilter,
1382 (GLfloat (*)[4]) dstImage,
1383 ctx->Pixel.ConvolutionBorderColor[2]);
1384 break;
1385 case GL_REPLICATE_BORDER:
1386 convolve_sep_replicate(*width, *height,
1387 (const GLfloat (*)[4]) srcImage,
Brian Paul7e708742000-08-22 18:54:25 +00001388 ctx->Separable2D.Width,
1389 ctx->Separable2D.Height,
Brian Pauld4b799b2000-08-21 14:24:30 +00001390 (const GLfloat (*)[4]) rowFilter,
1391 (const GLfloat (*)[4]) colFilter,
1392 (GLfloat (*)[4]) dstImage);
1393 break;
1394 default:
1395 ;
Brian Paulcc8e37f2000-07-12 13:00:09 +00001396 }
1397}
Brian Paul16461f72001-02-06 17:22:16 +00001398
1399
1400
1401/*
1402 * This function computes an image's size after convolution.
1403 * If the convolution border mode is GL_REDUCE, the post-convolution
1404 * image will be smaller than the original.
1405 */
1406void
1407_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
1408 GLsizei *width, GLsizei *height)
1409{
1410 if (ctx->Pixel.Convolution1DEnabled
1411 && dimensions == 1
1412 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
1413 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
1414 }
1415 else if (ctx->Pixel.Convolution2DEnabled
1416 && dimensions > 1
1417 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
1418 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
1419 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
1420 }
1421 else if (ctx->Pixel.Separable2DEnabled
1422 && dimensions > 1
1423 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
1424 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
1425 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
1426 }
1427}