convolve.c revision c893a015d8a50a38cd3f727d99835e7e7e2ccea9
1c893a015d8a50a38cd3f727d99835e7e7e2ccea9Brian Paul/* $Id: convolve.c,v 1.7 2000/10/28 20:41:13 brianp Exp $ */
2cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
3cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul/*
4cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * Mesa 3-D graphics library
5d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul * Version:  3.5
6cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul *
7cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
8cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul *
9cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
10cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * copy of this software and associated documentation files (the "Software"),
11cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * to deal in the Software without restriction, including without limitation
12cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * and/or sell copies of the Software, and to permit persons to whom the
14cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * Software is furnished to do so, subject to the following conditions:
15cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul *
16cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * The above copyright notice and this permission notice shall be included
17cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * in all copies or substantial portions of the Software.
18cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul *
19cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul */
26cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
27cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
28cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul/*
29cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * Image convolution functions.
30cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul *
31cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * Notes: filter kernel elements are indexed by <n> and <m> as in
32cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul * the GL spec.
33cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul */
34cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
35cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
36cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul#ifdef PC_HEADER
37cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul#include "all.h"
38cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul#else
39cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul#include "glheader.h"
40c893a015d8a50a38cd3f727d99835e7e7e2ccea9Brian Paul#include "colormac.h"
41d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul#include "convolve.h"
42d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul#include "context.h"
43147b08328a2ccb0c1150feaf7871037683236e33Brian Paul#include "image.h"
44147b08328a2ccb0c1150feaf7871037683236e33Brian Paul#include "span.h"
45cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul#include "types.h"
46cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul#endif
47cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
48cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
49147b08328a2ccb0c1150feaf7871037683236e33Brian Paul/*
50147b08328a2ccb0c1150feaf7871037683236e33Brian Paul * Given an internalFormat token passed to glConvolutionFilter
51147b08328a2ccb0c1150feaf7871037683236e33Brian Paul * or glSeparableFilter, return the corresponding base format.
52147b08328a2ccb0c1150feaf7871037683236e33Brian Paul * Return -1 if invalid token.
53147b08328a2ccb0c1150feaf7871037683236e33Brian Paul */
54147b08328a2ccb0c1150feaf7871037683236e33Brian Paulstatic GLint
55147b08328a2ccb0c1150feaf7871037683236e33Brian Paulbase_filter_format( GLenum format )
56147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
57147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (format) {
58147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_ALPHA:
59147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_ALPHA4:
60147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_ALPHA8:
61147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_ALPHA12:
62147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_ALPHA16:
63147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return GL_ALPHA;
64147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE:
65147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE4:
66147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE8:
67147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE12:
68147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE16:
69147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return GL_LUMINANCE;
70147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE_ALPHA:
71147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE4_ALPHA4:
72147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE6_ALPHA2:
73147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE8_ALPHA8:
74147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE12_ALPHA4:
75147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE12_ALPHA12:
76147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_LUMINANCE16_ALPHA16:
77147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return GL_LUMINANCE_ALPHA;
78147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_INTENSITY:
79147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_INTENSITY4:
80147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_INTENSITY8:
81147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_INTENSITY12:
82147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_INTENSITY16:
83147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return GL_INTENSITY;
84147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB:
85147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_R3_G3_B2:
86147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB4:
87147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB5:
88147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB8:
89147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB10:
90147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB12:
91147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB16:
92147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return GL_RGB;
93147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case 4:
94147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGBA:
95147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGBA2:
96147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGBA4:
97147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB5_A1:
98147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGBA8:
99147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGB10_A2:
100147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGBA12:
101147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_RGBA16:
102147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return GL_RGBA;
103147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
104147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return -1;  /* error */
105147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
106147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
107147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
108147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
109147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
110147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *image)
111147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
112147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLenum baseFormat;
113147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
114147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glConvolutionFilter1D");
115147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
116147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (target != GL_CONVOLUTION_1D) {
117147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(target)");
118147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
119147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
120147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
121147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   baseFormat = base_filter_format(internalFormat);
122147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
123147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(internalFormat)");
124147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
125147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
126147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
127147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
128147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter1D(width)");
129147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
130147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
131147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
132147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (!_mesa_is_legal_format_and_type(format, type) ||
133147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_COLOR_INDEX ||
134147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_STENCIL_INDEX ||
135147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_DEPTH_COMPONENT ||
136147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_INTENSITY ||
137147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       type == GL_BITMAP) {
138147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(format or type)");
139147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
140147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
141147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
142147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution1D.Format = format;
143147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution1D.InternalFormat = internalFormat;
144147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution1D.Width = width;
145147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution1D.Height = 1;
146147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
147147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* unpack filter image */
148147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
149147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 ctx->Convolution1D.Filter,
150147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 format, type, image, &ctx->Unpack,
151147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 0, GL_FALSE);
152147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
153147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* apply scale and bias */
154147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   {
155147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[0];
156147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[0];
157147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      GLint i;
158147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      for (i = 0; i < width; i++) {
159147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat r = ctx->Convolution1D.Filter[i * 4 + 0];
160147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat g = ctx->Convolution1D.Filter[i * 4 + 1];
161147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat b = ctx->Convolution1D.Filter[i * 4 + 2];
162147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat a = ctx->Convolution1D.Filter[i * 4 + 3];
163147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         r = r * scale[0] + bias[0];
164147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         g = g * scale[1] + bias[1];
165147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         b = b * scale[2] + bias[2];
166147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         a = a * scale[3] + bias[3];
167147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution1D.Filter[i * 4 + 0] = r;
168147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution1D.Filter[i * 4 + 1] = g;
169147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution1D.Filter[i * 4 + 2] = b;
170147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution1D.Filter[i * 4 + 3] = a;
171147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      }
172147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
173147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
174147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
175147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
176147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
177147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image)
178147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
179147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLenum baseFormat;
180147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLint i, components;
181147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
182147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glConvolutionFilter2D");
183147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
184147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (target != GL_CONVOLUTION_2D) {
185147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)");
186147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
187147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
188147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
189147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   baseFormat = base_filter_format(internalFormat);
190147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
191147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)");
192147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
193147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
194147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
195147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
196147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)");
197147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
198147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
199147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
200147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)");
201147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
202147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
203147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
204147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (!_mesa_is_legal_format_and_type(format, type) ||
205147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_COLOR_INDEX ||
206147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_STENCIL_INDEX ||
207147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_DEPTH_COMPONENT ||
208147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_INTENSITY ||
209147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       type == GL_BITMAP) {
210147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)");
211147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
212147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
213147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
214147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   components = _mesa_components_in_format(format);
215147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   assert(components > 0);  /* this should have been caught earlier */
216147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
217147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution2D.Format = format;
218147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution2D.InternalFormat = internalFormat;
219147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution2D.Width = width;
220147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Convolution2D.Height = height;
221147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
222147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* Unpack filter image.  We always store filters in RGBA format. */
223147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   for (i = 0; i < height; i++) {
224147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLvoid *src = _mesa_image_address(&ctx->Unpack, image, width,
225147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                              height, format, type, 0, i, 0);
226147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4;
227147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
228147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                    format, type, src, &ctx->Unpack,
229147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                    0, GL_FALSE);
230147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
231147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
232147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* apply scale and bias */
233147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   {
234147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[1];
235147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[1];
236147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      for (i = 0; i < width * height * 4; i++) {
237147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat r = ctx->Convolution2D.Filter[i * 4 + 0];
238147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat g = ctx->Convolution2D.Filter[i * 4 + 1];
239147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat b = ctx->Convolution2D.Filter[i * 4 + 2];
240147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat a = ctx->Convolution2D.Filter[i * 4 + 3];
241147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         r = r * scale[0] + bias[0];
242147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         g = g * scale[1] + bias[1];
243147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         b = b * scale[2] + bias[2];
244147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         a = a * scale[3] + bias[3];
245147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution2D.Filter[i * 4 + 0] = r;
246147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution2D.Filter[i * 4 + 1] = g;
247147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution2D.Filter[i * 4 + 2] = b;
248147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Convolution2D.Filter[i * 4 + 3] = a;
249147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      }
250147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
251147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
252147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
253147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
254147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
255147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param)
256147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
257147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
258147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLuint c;
259147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
260147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glConvolutionParameterf");
261147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
262147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (target) {
263147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_1D:
264147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 0;
265147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
266147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_2D:
267147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 1;
268147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
269147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_SEPARABLE_2D:
270147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 2;
271147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
272147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
273147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(target)");
274147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
275147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
276147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
277147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (pname) {
278147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_MODE:
279147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         if (param == (GLfloat) GL_REDUCE ||
280147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             param == (GLfloat) GL_CONSTANT_BORDER ||
281147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             param == (GLfloat) GL_REPLICATE_BORDER) {
282147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
283147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
284147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         else {
285147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(params)");
286147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            return;
287147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
288147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
289147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
290147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(pname)");
291147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
292147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
293147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
294147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
295147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
296147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
297147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params)
298147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
299147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
300147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   struct gl_convolution_attrib *conv;
301147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLuint c;
302147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
303147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glConvolutionParameterfv");
304147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
305147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (target) {
306147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_1D:
307147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 0;
308147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution1D;
309147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
310147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_2D:
311147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 1;
312147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution2D;
313147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
314147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_SEPARABLE_2D:
315147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 2;
316147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Separable2D;
317147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
318147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
319147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(target)");
320147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
321147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
322147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
323147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (pname) {
324147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_COLOR:
325147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(ctx->Pixel.ConvolutionBorderColor[c], params);
326147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
327147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_MODE:
328147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         if (params[0] == (GLfloat) GL_REDUCE ||
329147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             params[0] == (GLfloat) GL_CONSTANT_BORDER ||
330147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             params[0] == (GLfloat) GL_REPLICATE_BORDER) {
331147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0];
332147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
333147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         else {
334147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(params)");
335147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            return;
336147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
337147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
338147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_SCALE:
339147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params);
340147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
341147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_BIAS:
342147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params);
343147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
344147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
345147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(pname)");
346147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
347147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
348147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
349147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
350147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
351147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
352147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint param)
353147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
354147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
355147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLuint c;
356147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
357147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glConvolutionParameteri");
358147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
359147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (target) {
360147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_1D:
361147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 0;
362147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
363147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_2D:
364147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 1;
365147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
366147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_SEPARABLE_2D:
367147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 2;
368147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
369147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
370147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(target)");
371147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
372147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
373147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
374147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (pname) {
375147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_MODE:
376147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         if (param == (GLint) GL_REDUCE ||
377147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             param == (GLint) GL_CONSTANT_BORDER ||
378147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             param == (GLint) GL_REPLICATE_BORDER) {
379147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
380147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
381147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         else {
382147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(params)");
383147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            return;
384147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
385147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
386147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
387147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(pname)");
388147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
389147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
390147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
391147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
392147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
393147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
394147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params)
395147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
396147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
397147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   struct gl_convolution_attrib *conv;
398147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLuint c;
399147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
400147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glConvolutionParameteriv");
401147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
402147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (target) {
403147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_1D:
404147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 0;
405147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution1D;
406147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
407147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_2D:
408147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 1;
409147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution2D;
410147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
411147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_SEPARABLE_2D:
412147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 2;
413147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Separable2D;
414147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
415147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
416147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(target)");
417147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
418147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
419147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
420147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (pname) {
421147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_COLOR:
422147b08328a2ccb0c1150feaf7871037683236e33Brian Paul	 ctx->Pixel.ConvolutionBorderColor[c][0] = INT_TO_FLOAT(params[0]);
423147b08328a2ccb0c1150feaf7871037683236e33Brian Paul	 ctx->Pixel.ConvolutionBorderColor[c][1] = INT_TO_FLOAT(params[1]);
424147b08328a2ccb0c1150feaf7871037683236e33Brian Paul	 ctx->Pixel.ConvolutionBorderColor[c][2] = INT_TO_FLOAT(params[2]);
425147b08328a2ccb0c1150feaf7871037683236e33Brian Paul	 ctx->Pixel.ConvolutionBorderColor[c][3] = INT_TO_FLOAT(params[3]);
426147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
427147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_MODE:
428147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         if (params[0] == (GLint) GL_REDUCE ||
429147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             params[0] == (GLint) GL_CONSTANT_BORDER ||
430147b08328a2ccb0c1150feaf7871037683236e33Brian Paul             params[0] == (GLint) GL_REPLICATE_BORDER) {
431147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0];
432147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
433147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         else {
434147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(params)");
435147b08328a2ccb0c1150feaf7871037683236e33Brian Paul            return;
436147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         }
437147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
438147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_SCALE:
439147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params);
440147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
441147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_BIAS:
442147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params);
443147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
444147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
445147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(pname)");
446147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
447147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
448147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
449147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
450147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
451147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
452147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width)
453147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
454147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLenum baseFormat;
455147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLfloat rgba[MAX_CONVOLUTION_WIDTH][4];
456147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
457147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyConvolutionFilter1D");
458147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
459147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (target != GL_CONVOLUTION_1D) {
460147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(target)");
461147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
462147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
463147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
464147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   baseFormat = base_filter_format(internalFormat);
465147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
466147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(internalFormat)");
467147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
468147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
469147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
470147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
471147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter1D(width)");
472147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
473147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
474147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
475147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* read pixels from framebuffer */
476ba643a2094a1e844b6ce60f468057057557859ceBrian Paul   gl_read_rgba_span(ctx, ctx->ReadBuffer, width, x, y, (GLchan (*)[4]) rgba);
477147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
478147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* store as convolution filter */
479147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   _mesa_ConvolutionFilter1D(target, internalFormat, width,
480147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                             GL_RGBA, GL_UNSIGNED_BYTE, rgba);
481147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
482147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
483147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
484147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
485147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height)
486147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
487147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLenum baseFormat;
488147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLint i;
489147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   struct gl_pixelstore_attrib packSave;
490147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLfloat rgba[MAX_CONVOLUTION_HEIGHT][MAX_CONVOLUTION_WIDTH][4];
491147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
492147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyConvolutionFilter2D");
493147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
494147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (target != GL_CONVOLUTION_2D) {
495147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(target)");
496147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
497147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
498147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
499147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   baseFormat = base_filter_format(internalFormat);
500147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
501147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(internalFormat)");
502147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
503147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
504147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
505147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
506147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(width)");
507147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
508147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
509147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
510147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(height)");
511147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
512147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
513147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
514147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* read pixels from framebuffer */
515147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   for (i = 0; i < height; i++) {
516147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_read_rgba_span(ctx, ctx->ReadBuffer, width, x, y + i,
517ba643a2094a1e844b6ce60f468057057557859ceBrian Paul                        (GLchan (*)[4]) rgba[i]);
518147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
519147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
520147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /*
521147b08328a2ccb0c1150feaf7871037683236e33Brian Paul    * store as convolution filter
522147b08328a2ccb0c1150feaf7871037683236e33Brian Paul    */
523147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   packSave = ctx->Unpack;  /* save pixel packing params */
524147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
525147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.Alignment = 1;
526147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.RowLength = MAX_CONVOLUTION_WIDTH;
527147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.SkipPixels = 0;
528147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.SkipRows = 0;
529147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.ImageHeight = 0;
530147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.SkipImages = 0;
531147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.SwapBytes = GL_FALSE;
532147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack.LsbFirst = GL_FALSE;
533147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
534147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   _mesa_ConvolutionFilter2D(target, internalFormat, width, height,
535147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                             GL_RGBA, GL_UNSIGNED_BYTE, rgba);
536147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
537147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Unpack = packSave;  /* restore pixel packing params */
538147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
539147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
540147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
541147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
542147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid *image)
543147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
544f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   const struct gl_convolution_attrib *filter;
545f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   GLint row;
546147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
547147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetConvolutionFilter");
548147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
549147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (!_mesa_is_legal_format_and_type(format, type) ||
550147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_COLOR_INDEX ||
551147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_STENCIL_INDEX ||
552147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_DEPTH_COMPONENT ||
553147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_INTENSITY ||
554147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       type == GL_BITMAP) {
555147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
556147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
557147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
558147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
559f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   switch (target) {
560f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      case GL_CONVOLUTION_1D:
561f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul         filter = &(ctx->Convolution1D);
562f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul         break;
563f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      case GL_CONVOLUTION_2D:
564f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul         filter = &(ctx->Convolution2D);
565f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul         break;
566f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      default:
567f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(target)");
568f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul         return;
569f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   }
570f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul
571f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   for (row = 0; row < filter->Height; row++) {
572f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      GLvoid *dst = _mesa_image_address( &ctx->Pack, image, filter->Width,
573f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                         filter->Height, format, type,
574f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                         0, row, 0);
575f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      const GLfloat *src = filter->Filter + row * filter->Width * 4;
576f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      /* XXX apply transfer ops or not? */
577f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      _mesa_pack_float_rgba_span(ctx, filter->Width,
578f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                 (const GLfloat (*)[4]) src,
579f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                 format, type, dst, &ctx->Pack, 0);
580f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   }
581147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
582147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
583147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
584147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
585147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params)
586147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
587147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
588147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   const struct gl_convolution_attrib *conv;
589147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLuint c;
590147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
591147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetConvolutionParameterfv");
592147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
593147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (target) {
594147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_1D:
595147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 0;
596147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution1D;
597147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
598147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_2D:
599147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 1;
600147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution2D;
601147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
602147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_SEPARABLE_2D:
603147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 2;
604147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Separable2D;
605147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
606147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
607147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(target)");
608147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
609147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
610147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
611147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (pname) {
612147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_COLOR:
613147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(params, ctx->Pixel.ConvolutionBorderColor[c]);
614147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
615147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_MODE:
616147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLfloat) ctx->Pixel.ConvolutionBorderMode[c];
617147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
618147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_SCALE:
619147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(params, ctx->Pixel.ConvolutionFilterScale[c]);
620147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
621147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_BIAS:
622147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         COPY_4V(params, ctx->Pixel.ConvolutionFilterBias[c]);
623147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
624147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FORMAT:
625147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLfloat) conv->Format;
626147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
627147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_WIDTH:
628147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLfloat) conv->Width;
629147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
630147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_HEIGHT:
631147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLfloat) conv->Height;
632147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
633147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_MAX_CONVOLUTION_WIDTH:
634147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLfloat) ctx->Const.MaxConvolutionWidth;
635147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
636147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_MAX_CONVOLUTION_HEIGHT:
637147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLfloat) ctx->Const.MaxConvolutionHeight;
638147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
639147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
640147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(pname)");
641147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
642147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
643147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
644147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
645147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
646147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
647147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params)
648147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
649147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
650147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   const struct gl_convolution_attrib *conv;
651147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLuint c;
652147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
653147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetConvolutionParameteriv");
654147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
655147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (target) {
656147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_1D:
657147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 0;
658147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution1D;
659147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
660147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_2D:
661147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 1;
662147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Convolution2D;
663147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
664147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_SEPARABLE_2D:
665147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         c = 2;
666147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         conv = &ctx->Separable2D;
667147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
668147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
669147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(target)");
670147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
671147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
672147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
673147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   switch (pname) {
674147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_COLOR:
675147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[0] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][0]);
676147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[1] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][1]);
677147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[2] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][2]);
678147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[3] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][3]);
679147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
680147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_BORDER_MODE:
681147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLint) ctx->Pixel.ConvolutionBorderMode[c];
682147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
683147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_SCALE:
684147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[0] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][0];
685147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[1] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][1];
686147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[2] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][2];
687147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[3] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][3];
688147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
689147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FILTER_BIAS:
690147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[0] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][0];
691147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[1] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][1];
692147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[2] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][2];
693147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         params[3] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][3];
694147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
695147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_FORMAT:
696147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLint) conv->Format;
697147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
698147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_WIDTH:
699147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLint) conv->Width;
700147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
701147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_CONVOLUTION_HEIGHT:
702147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLint) conv->Height;
703147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
704147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_MAX_CONVOLUTION_WIDTH:
705147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLint) ctx->Const.MaxConvolutionWidth;
706147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
707147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      case GL_MAX_CONVOLUTION_HEIGHT:
708147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         *params = (GLint) ctx->Const.MaxConvolutionHeight;
709147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         break;
710147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      default:
711147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         gl_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(pname)");
712147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         return;
713147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
714147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
715147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
716147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
717147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
718147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span)
719147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
720f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
721f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   const struct gl_convolution_attrib *filter;
722147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
723147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetSeparableFilter");
724147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
725147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (target != GL_SEPARABLE_2D) {
726147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter(target)");
727147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
728147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
729147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
730147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (!_mesa_is_legal_format_and_type(format, type) ||
731147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_COLOR_INDEX ||
732147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_STENCIL_INDEX ||
733147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_DEPTH_COMPONENT ||
734147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_INTENSITY ||
735147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       type == GL_BITMAP) {
736147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
737147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
738147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
739147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
740f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   filter = &ctx->Separable2D;
741f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul
742f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   /* Row filter */
743f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   {
744f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      GLvoid *dst = _mesa_image_address( &ctx->Pack, row, filter->Width,
745f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                         filter->Height, format, type,
746f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                         0, 0, 0);
747f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      _mesa_pack_float_rgba_span(ctx, filter->Width,
748f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                 (const GLfloat (*)[4]) filter->Filter,
749f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                 format, type, dst, &ctx->Pack, 0);
750f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   }
751f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul
752f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   /* Column filter */
753f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   {
754f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      GLvoid *dst = _mesa_image_address( &ctx->Pack, column, filter->Width,
755f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                         1, format, type,
756f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                         0, 0, 0);
757f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      const GLfloat *src = filter->Filter + colStart;
758f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul      _mesa_pack_float_rgba_span(ctx, filter->Height,
759f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                 (const GLfloat (*)[4]) src,
760f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul                                 format, type, dst, &ctx->Pack, 0);
761f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   }
762f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul
763f75d697c0319e43ac15b42c8bbd5e956286c7005Brian Paul   (void) span;  /* unused at this time */
764147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
765147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
766147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
767147b08328a2ccb0c1150feaf7871037683236e33Brian Paulvoid
768147b08328a2ccb0c1150feaf7871037683236e33Brian Paul_mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column)
769147b08328a2ccb0c1150feaf7871037683236e33Brian Paul{
770147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
771147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GLenum baseFormat;
772147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   GET_CURRENT_CONTEXT(ctx);
773147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glSeparableFilter2D");
774147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
775147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (target != GL_SEPARABLE_2D) {
776147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(target)");
777147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
778147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
779147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
780147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   baseFormat = base_filter_format(internalFormat);
781147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
782147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(internalFormat)");
783147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
784147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
785147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
786147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
787147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(width)");
788147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
789147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
790147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
791147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(height)");
792147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
793147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
794147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
795147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   if (!_mesa_is_legal_format_and_type(format, type) ||
796147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_COLOR_INDEX ||
797147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_STENCIL_INDEX ||
798147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_DEPTH_COMPONENT ||
799147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       format == GL_INTENSITY ||
800147b08328a2ccb0c1150feaf7871037683236e33Brian Paul       type == GL_BITMAP) {
801147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      gl_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(format or type)");
802147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      return;
803147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
804147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
805147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Separable2D.Format = format;
806147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Separable2D.InternalFormat = internalFormat;
807147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Separable2D.Width = width;
808147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   ctx->Separable2D.Height = height;
809147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
810147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* unpack row filter */
811147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
812147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 ctx->Separable2D.Filter,
813147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 format, type, row, &ctx->Unpack,
814147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 0, GL_FALSE);
815147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
816147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* apply scale and bias */
817147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   {
818147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
819147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
820147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      GLint i;
821147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      for (i = 0; i < width; i++) {
822147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat r = ctx->Separable2D.Filter[i * 4 + 0];
823147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat g = ctx->Separable2D.Filter[i * 4 + 1];
824147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat b = ctx->Separable2D.Filter[i * 4 + 2];
825147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat a = ctx->Separable2D.Filter[i * 4 + 3];
826147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         r = r * scale[0] + bias[0];
827147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         g = g * scale[1] + bias[1];
828147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         b = b * scale[2] + bias[2];
829147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         a = a * scale[3] + bias[3];
830147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 0] = r;
831147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 1] = g;
832147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 2] = b;
833147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 3] = a;
834147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      }
835147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
836147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
837147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* unpack column filter */
838147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   _mesa_unpack_float_color_span(ctx, width, GL_RGBA,
839147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 &ctx->Separable2D.Filter[colStart],
840147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 format, type, column, &ctx->Unpack,
841147b08328a2ccb0c1150feaf7871037683236e33Brian Paul                                 0, GL_FALSE);
842147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
843147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   /* apply scale and bias */
844147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   {
845147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
846147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
847147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      GLint i;
848147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      for (i = 0; i < width; i++) {
849147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat r = ctx->Separable2D.Filter[i * 4 + 0 + colStart];
850147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat g = ctx->Separable2D.Filter[i * 4 + 1 + colStart];
851147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat b = ctx->Separable2D.Filter[i * 4 + 2 + colStart];
852147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         GLfloat a = ctx->Separable2D.Filter[i * 4 + 3 + colStart];
853147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         r = r * scale[0] + bias[0];
854147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         g = g * scale[1] + bias[1];
855147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         b = b * scale[2] + bias[2];
856147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         a = a * scale[3] + bias[3];
857147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 0 + colStart] = r;
858147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 1 + colStart] = g;
859147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 2 + colStart] = b;
860147b08328a2ccb0c1150feaf7871037683236e33Brian Paul         ctx->Separable2D.Filter[i * 4 + 3 + colStart] = a;
861147b08328a2ccb0c1150feaf7871037683236e33Brian Paul      }
862147b08328a2ccb0c1150feaf7871037683236e33Brian Paul   }
863147b08328a2ccb0c1150feaf7871037683236e33Brian Paul}
864147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
865147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
866147b08328a2ccb0c1150feaf7871037683236e33Brian Paul/**********************************************************************/
867147b08328a2ccb0c1150feaf7871037683236e33Brian Paul/***                   image convolution functions                  ***/
868147b08328a2ccb0c1150feaf7871037683236e33Brian Paul/**********************************************************************/
869147b08328a2ccb0c1150feaf7871037683236e33Brian Paul
870d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
871d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_1d_reduce(GLint srcWidth, const GLfloat src[][4],
872d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                   GLint filterWidth, const GLfloat filter[][4],
873d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                   GLfloat dest[][4])
874cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
8757e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   GLint dstWidth;
876cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   GLint i, n;
877cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
8787e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   if (filterWidth >= 1)
8797e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstWidth = srcWidth - (filterWidth - 1);
8807e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   else
8817e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstWidth = srcWidth;
8827e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
883cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   if (dstWidth <= 0)
884cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      return;  /* null result */
885cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
886cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   for (i = 0; i < dstWidth; i++) {
887cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumR = 0.0;
888cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumG = 0.0;
889cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumB = 0.0;
890cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumA = 0.0;
891cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      for (n = 0; n < filterWidth; n++) {
892cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         sumR += src[i + n][RCOMP] * filter[n][RCOMP];
893cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         sumG += src[i + n][GCOMP] * filter[n][GCOMP];
894cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         sumB += src[i + n][BCOMP] * filter[n][BCOMP];
895cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         sumA += src[i + n][ACOMP] * filter[n][ACOMP];
896cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
897cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][RCOMP] = sumR;
898cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][GCOMP] = sumG;
899cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][BCOMP] = sumB;
900cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][ACOMP] = sumA;
901cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
902cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
903cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
904cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
905d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
906d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_1d_constant(GLint srcWidth, const GLfloat src[][4],
907d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     GLint filterWidth, const GLfloat filter[][4],
908d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     GLfloat dest[][4],
909d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     const GLfloat borderColor[4])
910cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
911cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   const GLint halfFilterWidth = filterWidth / 2;
912cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   GLint i, n;
913cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
914cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   for (i = 0; i < srcWidth; i++) {
915cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumR = 0.0;
916cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumG = 0.0;
917cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumB = 0.0;
918cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumA = 0.0;
919cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      for (n = 0; n < filterWidth; n++) {
920cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) {
921cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumR += borderColor[RCOMP] * filter[n][RCOMP];
922cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumG += borderColor[GCOMP] * filter[n][GCOMP];
923cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumB += borderColor[BCOMP] * filter[n][BCOMP];
924cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumA += borderColor[ACOMP] * filter[n][ACOMP];
925cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
926cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         else {
927cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
928cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
929cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
930cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
931cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
932cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
933cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][RCOMP] = sumR;
934cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][GCOMP] = sumG;
935cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][BCOMP] = sumB;
936cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][ACOMP] = sumA;
937cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
938cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
939cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
940cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
941d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
942d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_1d_replicate(GLint srcWidth, const GLfloat src[][4],
943d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      GLint filterWidth, const GLfloat filter[][4],
944d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      GLfloat dest[][4])
945cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
946cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   const GLint halfFilterWidth = filterWidth / 2;
947cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   GLint i, n;
948cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
949cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   for (i = 0; i < srcWidth; i++) {
950cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumR = 0.0;
951cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumG = 0.0;
952cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumB = 0.0;
953cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      GLfloat sumA = 0.0;
954cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      for (n = 0; n < filterWidth; n++) {
955cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         if (i + n < halfFilterWidth) {
956cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumR += src[0][RCOMP] * filter[n][RCOMP];
957cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumG += src[0][GCOMP] * filter[n][GCOMP];
958cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumB += src[0][BCOMP] * filter[n][BCOMP];
959cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumA += src[0][ACOMP] * filter[n][ACOMP];
960cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
961cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         else if (i + n - halfFilterWidth >= srcWidth) {
962cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP];
963cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP];
964cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP];
965cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP];
966cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
967cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         else {
968cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
969cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
970cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
971cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
972cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
973cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
974cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][RCOMP] = sumR;
975cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][GCOMP] = sumG;
976cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][BCOMP] = sumB;
977cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      dest[i][ACOMP] = sumA;
978cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
979cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
980cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
981cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
982d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
983d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_2d_reduce(GLint srcWidth, GLint srcHeight,
984d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                   const GLfloat src[][4],
985d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                   GLint filterWidth, GLint filterHeight,
986d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                   const GLfloat filter[][4],
987d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                   GLfloat dest[][4])
988cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
9897e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   GLint dstWidth, dstHeight;
990d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   GLint i, j, n, m;
991d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
9927e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   if (filterWidth >= 1)
9937e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstWidth = srcWidth - (filterWidth - 1);
9947e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   else
9957e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstWidth = srcWidth;
9967e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
9977e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   if (filterHeight >= 1)
9987e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstHeight = srcHeight - (filterHeight - 1);
9997e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   else
10007e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstHeight = srcHeight;
10017e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
1002d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   if (dstWidth <= 0 || dstHeight <= 0)
1003d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      return;
1004d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1005d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   for (j = 0; j < dstHeight; j++) {
1006d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      for (i = 0; i < dstWidth; i++) {
1007d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumR = 0.0;
1008d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumG = 0.0;
1009d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumB = 0.0;
1010d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumA = 0.0;
1011d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         for (m = 0; m < filterHeight; m++) {
1012d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul            for (n = 0; n < filterWidth; n++) {
1013d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               const GLint k = (j + m) * srcWidth + i + n;
1014d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               const GLint f = m * filterWidth + n;
1015d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumR += src[k][RCOMP] * filter[f][RCOMP];
1016d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumG += src[k][GCOMP] * filter[f][GCOMP];
1017d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumB += src[k][BCOMP] * filter[f][BCOMP];
1018d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumA += src[k][ACOMP] * filter[f][ACOMP];
1019d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul            }
1020cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
1021d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * dstWidth + i][RCOMP] = sumR;
1022d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * dstWidth + i][GCOMP] = sumG;
1023d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * dstWidth + i][BCOMP] = sumB;
1024d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * dstWidth + i][ACOMP] = sumA;
1025cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
1026cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
1027cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
1028cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1029cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1030d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
1031d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_2d_constant(GLint srcWidth, GLint srcHeight,
1032d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     const GLfloat src[][4],
1033d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     GLint filterWidth, GLint filterHeight,
1034d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     const GLfloat filter[][4],
1035d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     GLfloat dest[][4],
1036d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                     const GLfloat borderColor[4])
1037cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
1038cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   const GLint halfFilterWidth = filterWidth / 2;
1039d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   const GLint halfFilterHeight = filterHeight / 2;
1040d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   GLint i, j, n, m;
1041cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1042d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   for (j = 0; j < srcHeight; j++) {
1043d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      for (i = 0; i < srcWidth; i++) {
1044d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumR = 0.0;
1045d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumG = 0.0;
1046d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumB = 0.0;
1047d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumA = 0.0;
1048d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         for (m = 0; m < filterHeight; m++) {
1049d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul            for (n = 0; n < filterWidth; n++) {
1050d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               const GLint f = m * filterWidth + n;
1051d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               const GLint is = i + n - halfFilterWidth;
1052d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               const GLint js = j + m - halfFilterHeight;
1053d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               if (is < 0 || is >= srcWidth ||
1054d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                   js < 0 || js >= srcHeight) {
1055d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumR += borderColor[RCOMP] * filter[f][RCOMP];
1056d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumG += borderColor[GCOMP] * filter[f][GCOMP];
1057d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumB += borderColor[BCOMP] * filter[f][BCOMP];
1058d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumA += borderColor[ACOMP] * filter[f][ACOMP];
1059d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               }
1060d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               else {
1061d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  const GLint k = js * srcWidth + is;
1062d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumR += src[k][RCOMP] * filter[f][RCOMP];
1063d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumG += src[k][GCOMP] * filter[f][GCOMP];
1064d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumB += src[k][BCOMP] * filter[f][BCOMP];
1065d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumA += src[k][ACOMP] * filter[f][ACOMP];
1066d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               }
1067cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            }
1068cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
1069d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][RCOMP] = sumR;
1070d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][GCOMP] = sumG;
1071d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][BCOMP] = sumB;
1072d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][ACOMP] = sumA;
1073cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
1074cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
1075cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
1076cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1077cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1078d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
1079d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_2d_replicate(GLint srcWidth, GLint srcHeight,
1080d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      const GLfloat src[][4],
1081d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      GLint filterWidth, GLint filterHeight,
1082d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      const GLfloat filter[][4],
1083d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      GLfloat dest[][4])
1084cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
1085cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   const GLint halfFilterWidth = filterWidth / 2;
1086d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   const GLint halfFilterHeight = filterHeight / 2;
1087d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   GLint i, j, n, m;
1088d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1089d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   for (j = 0; j < srcHeight; j++) {
1090d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      for (i = 0; i < srcWidth; i++) {
1091d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumR = 0.0;
1092d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumG = 0.0;
1093d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumB = 0.0;
1094d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumA = 0.0;
1095d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         for (m = 0; m < filterHeight; m++) {
1096d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul            for (n = 0; n < filterWidth; n++) {
1097d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               const GLint f = m * filterWidth + n;
1098d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               GLint is = i + n - halfFilterWidth;
1099d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               GLint js = j + m - halfFilterHeight;
1100d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               GLint k;
1101d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               if (is < 0)
1102d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  is = 0;
1103d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               else if (is >= srcWidth)
1104d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  is = srcWidth - 1;
1105d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               if (js < 0)
1106d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  js = 0;
1107d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               else if (js >= srcHeight)
1108d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  js = srcHeight - 1;
1109d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               k = js * srcWidth + is;
1110d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumR += src[k][RCOMP] * filter[f][RCOMP];
1111d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumG += src[k][GCOMP] * filter[f][GCOMP];
1112d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumB += src[k][BCOMP] * filter[f][BCOMP];
1113d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               sumA += src[k][ACOMP] * filter[f][ACOMP];
1114cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            }
1115cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
1116d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][RCOMP] = sumR;
1117d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][GCOMP] = sumG;
1118d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][BCOMP] = sumB;
1119d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         dest[j * srcWidth + i][ACOMP] = sumA;
1120cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
1121cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
1122cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
1123cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1124cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1125d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
1126d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_sep_reduce(GLint srcWidth, GLint srcHeight,
1127d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                    const GLfloat src[][4],
1128d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                    GLint filterWidth, GLint filterHeight,
1129d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                    const GLfloat rowFilt[][4],
1130d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                    const GLfloat colFilt[][4],
1131d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                    GLfloat dest[][4])
1132cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
11337e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   GLint dstWidth, dstHeight;
1134d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   GLint i, j, n, m;
11357e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
11367e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   if (filterWidth >= 1)
11377e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstWidth = srcWidth - (filterWidth - 1);
11387e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   else
11397e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstWidth = srcWidth;
11407e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
11417e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   if (filterHeight >= 1)
11427e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstHeight = srcHeight - (filterHeight - 1);
11437e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   else
11447e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      dstHeight = srcHeight;
11457e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
11467e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   if (dstWidth <= 0 || dstHeight <= 0)
11477e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      return;
11487e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
11497e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul   for (j = 0; j < dstHeight; j++) {
11507e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul      for (i = 0; i < dstWidth; i++) {
1151d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumR = 0.0;
1152d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumG = 0.0;
1153d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumB = 0.0;
1154d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumA = 0.0;
1155d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         for (m = 0; m < filterHeight; m++) {
1156d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul            for (n = 0; n < filterWidth; n++) {
11577e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               GLint k = (j + m) * srcWidth + i + n;
11587e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
11597e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
11607e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
11617e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1162cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            }
1163cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
11647e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * dstWidth + i][RCOMP] = sumR;
11657e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * dstWidth + i][GCOMP] = sumG;
11667e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * dstWidth + i][BCOMP] = sumB;
11677e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * dstWidth + i][ACOMP] = sumA;
1168cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
1169cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
1170cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
1171cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1172cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1173d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
1174d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_sep_constant(GLint srcWidth, GLint srcHeight,
1175d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      const GLfloat src[][4],
1176d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      GLint filterWidth, GLint filterHeight,
1177d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      const GLfloat rowFilt[][4],
1178d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      const GLfloat colFilt[][4],
1179d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      GLfloat dest[][4],
1180d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                      const GLfloat borderColor[4])
1181cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
1182cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   const GLint halfFilterWidth = filterWidth / 2;
1183d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   const GLint halfFilterHeight = filterHeight / 2;
1184d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   GLint i, j, n, m;
11857e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
1186d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   for (j = 0; j < srcHeight; j++) {
1187d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      for (i = 0; i < srcWidth; i++) {
1188d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumR = 0.0;
1189d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumG = 0.0;
1190d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumB = 0.0;
1191d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumA = 0.0;
1192d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         for (m = 0; m < filterHeight; m++) {
1193d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul            for (n = 0; n < filterWidth; n++) {
11947e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               const GLint is = i + n - halfFilterWidth;
11957e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               const GLint js = j + m - halfFilterHeight;
11967e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               if (is < 0 || is >= srcWidth ||
11977e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                   js < 0 || js >= srcHeight) {
1198d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1199d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1200d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1201d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1202d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               }
1203d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               else {
12047e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                  GLint k = js * srcWidth + is;
1205d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
1206d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
1207d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
1208d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                  sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1209d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul               }
12107e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul
1211cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            }
1212cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
12137e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][RCOMP] = sumR;
12147e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][GCOMP] = sumG;
12157e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][BCOMP] = sumB;
12167e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][ACOMP] = sumA;
1217cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
1218cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
1219cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
1220cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1221cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul
1222d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulstatic void
1223d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulconvolve_sep_replicate(GLint srcWidth, GLint srcHeight,
1224d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                       const GLfloat src[][4],
1225d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                       GLint filterWidth, GLint filterHeight,
1226d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                       const GLfloat rowFilt[][4],
1227d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                       const GLfloat colFilt[][4],
1228d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                       GLfloat dest[][4])
1229cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul{
1230cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   const GLint halfFilterWidth = filterWidth / 2;
1231d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   const GLint halfFilterHeight = filterHeight / 2;
1232d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   GLint i, j, n, m;
1233d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1234d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   for (j = 0; j < srcHeight; j++) {
1235d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      for (i = 0; i < srcWidth; i++) {
1236d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumR = 0.0;
1237d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumG = 0.0;
1238d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumB = 0.0;
1239d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         GLfloat sumA = 0.0;
1240d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         for (m = 0; m < filterHeight; m++) {
1241d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul            for (n = 0; n < filterWidth; n++) {
12427e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               GLint is = i + n - halfFilterWidth;
12437e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               GLint js = j + m - halfFilterHeight;
12447e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               GLint k;
12457e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               if (is < 0)
12467e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                  is = 0;
12477e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               else if (is >= srcWidth)
12487e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                  is = srcWidth - 1;
12497e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               if (js < 0)
12507e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                  js = 0;
12517e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               else if (js >= srcHeight)
12527e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                  js = srcHeight - 1;
12537e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               k = js * srcWidth + is;
12547e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
12557e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
12567e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
12577e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul               sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
1258cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul            }
1259cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul         }
12607e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][RCOMP] = sumR;
12617e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][GCOMP] = sumG;
12627e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][BCOMP] = sumB;
12637e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         dest[j * srcWidth + i][ACOMP] = sumA;
1264cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul      }
1265d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   }
1266d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul}
1267d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1268d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1269d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1270d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulvoid
1271d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
1272d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                        const GLfloat *srcImage, GLfloat *dstImage)
1273d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul{
1274d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   switch (ctx->Pixel.ConvolutionBorderMode[0]) {
1275d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_REDUCE:
1276d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_1d_reduce(*width, (const GLfloat (*)[4]) srcImage,
1277d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            ctx->Convolution1D.Width,
1278d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1279d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            (GLfloat (*)[4]) dstImage);
12807e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
1281d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1282d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_CONSTANT_BORDER:
1283d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_1d_constant(*width, (const GLfloat (*)[4]) srcImage,
1284d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              ctx->Convolution1D.Width,
1285d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1286d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              (GLfloat (*)[4]) dstImage,
1287d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              ctx->Pixel.ConvolutionBorderColor[0]);
1288d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1289d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_REPLICATE_BORDER:
1290d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_1d_replicate(*width, (const GLfloat (*)[4]) srcImage,
1291d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              ctx->Convolution1D.Width,
1292d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
1293d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              (GLfloat (*)[4]) dstImage);
1294d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1295d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      default:
1296d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         ;
1297d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   }
1298d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul}
1299d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1300d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1301d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulvoid
1302d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
1303d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                        const GLfloat *srcImage, GLfloat *dstImage)
1304d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul{
1305d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   switch (ctx->Pixel.ConvolutionBorderMode[1]) {
1306d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_REDUCE:
1307d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_2d_reduce(*width, *height,
1308d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            (const GLfloat (*)[4]) srcImage,
1309d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            ctx->Convolution2D.Width,
1310d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            ctx->Convolution2D.Height,
1311d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
1312d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                            (GLfloat (*)[4]) dstImage);
13137e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
13147e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
1315d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1316d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_CONSTANT_BORDER:
1317d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_2d_constant(*width, *height,
1318d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              (const GLfloat (*)[4]) srcImage,
1319d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              ctx->Convolution2D.Width,
1320d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              ctx->Convolution2D.Height,
1321d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
1322d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              (GLfloat (*)[4]) dstImage,
1323d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                              ctx->Pixel.ConvolutionBorderColor[1]);
1324d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1325d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_REPLICATE_BORDER:
1326d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_2d_replicate(*width, *height,
1327d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               (const GLfloat (*)[4]) srcImage,
1328d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               ctx->Convolution2D.Width,
1329d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               ctx->Convolution2D.Height,
1330d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               (const GLfloat (*)[4])ctx->Convolution2D.Filter,
1331d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               (GLfloat (*)[4]) dstImage);
1332d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1333d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      default:
1334d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         ;
1335d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      }
1336d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul}
1337d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1338d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1339d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paulvoid
1340d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul_mesa_convolve_sep_image(const GLcontext *ctx,
1341d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                         GLsizei *width, GLsizei *height,
1342d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                         const GLfloat *srcImage, GLfloat *dstImage)
1343d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul{
1344d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   const GLfloat *rowFilter = ctx->Separable2D.Filter;
1345d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   const GLfloat *colFilter = rowFilter + 4 * MAX_CONVOLUTION_WIDTH;
1346d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul
1347d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul   switch (ctx->Pixel.ConvolutionBorderMode[2]) {
1348d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_REDUCE:
1349d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_sep_reduce(*width, *height,
1350d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                             (const GLfloat (*)[4]) srcImage,
13517e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                             ctx->Separable2D.Width,
13527e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                             ctx->Separable2D.Height,
1353d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                             (const GLfloat (*)[4]) rowFilter,
1354d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                             (const GLfloat (*)[4]) colFilter,
1355d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                             (GLfloat (*)[4]) dstImage);
13567e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
13577e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul         *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
1358d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1359d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_CONSTANT_BORDER:
1360d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_sep_constant(*width, *height,
1361d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               (const GLfloat (*)[4]) srcImage,
13627e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                               ctx->Separable2D.Width,
13637e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                               ctx->Separable2D.Height,
1364d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               (const GLfloat (*)[4]) rowFilter,
1365d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               (const GLfloat (*)[4]) colFilter,
1366d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               (GLfloat (*)[4]) dstImage,
1367d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                               ctx->Pixel.ConvolutionBorderColor[2]);
1368d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1369d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      case GL_REPLICATE_BORDER:
1370d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         convolve_sep_replicate(*width, *height,
1371d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                                (const GLfloat (*)[4]) srcImage,
13727e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                                ctx->Separable2D.Width,
13737e70874420266fb81bed13c8464ee4c0309d75b2Brian Paul                                ctx->Separable2D.Height,
1374d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                                (const GLfloat (*)[4]) rowFilter,
1375d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                                (const GLfloat (*)[4]) colFilter,
1376d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul                                (GLfloat (*)[4]) dstImage);
1377d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         break;
1378d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul      default:
1379d4b799b60c693ecebbbdcdb3fd6931a78b7a0e30Brian Paul         ;
1380cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul   }
1381cc8e37ffb393c892bbbf8850fef0e208c71d00f4Brian Paul}
1382