Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * Version: 7.1 |
||
4 | * |
||
5 | * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
||
6 | * |
||
7 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
8 | * copy of this software and associated documentation files (the "Software"), |
||
9 | * to deal in the Software without restriction, including without limitation |
||
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
11 | * and/or sell copies of the Software, and to permit persons to whom the |
||
12 | * Software is furnished to do so, subject to the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice shall be included |
||
15 | * in all copies or substantial portions of the Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
20 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
||
21 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
23 | */ |
||
24 | |||
25 | |||
26 | /** |
||
27 | * \file mipmap.c mipmap generation and teximage resizing functions. |
||
28 | */ |
||
29 | |||
30 | #include "imports.h" |
||
31 | #include "formats.h" |
||
32 | #include "mipmap.h" |
||
33 | #include "teximage.h" |
||
34 | #include "texstore.h" |
||
35 | #include "image.h" |
||
36 | |||
37 | |||
38 | |||
39 | static GLint |
||
40 | bytes_per_pixel(GLenum datatype, GLuint comps) |
||
41 | { |
||
42 | GLint b = _mesa_sizeof_packed_type(datatype); |
||
43 | assert(b >= 0); |
||
44 | |||
45 | if (_mesa_type_is_packed(datatype)) |
||
46 | return b; |
||
47 | else |
||
48 | return b * comps; |
||
49 | } |
||
50 | |||
51 | |||
52 | /** |
||
53 | * \name Support macros for do_row and do_row_3d |
||
54 | * |
||
55 | * The macro madness is here for two reasons. First, it compacts the code |
||
56 | * slightly. Second, it makes it much easier to adjust the specifics of the |
||
57 | * filter to tune the rounding characteristics. |
||
58 | */ |
||
59 | /*@{*/ |
||
60 | #define DECLARE_ROW_POINTERS(t, e) \ |
||
61 | const t(*rowA)[e] = (const t(*)[e]) srcRowA; \ |
||
62 | const t(*rowB)[e] = (const t(*)[e]) srcRowB; \ |
||
63 | const t(*rowC)[e] = (const t(*)[e]) srcRowC; \ |
||
64 | const t(*rowD)[e] = (const t(*)[e]) srcRowD; \ |
||
65 | t(*dst)[e] = (t(*)[e]) dstRow |
||
66 | |||
67 | #define DECLARE_ROW_POINTERS0(t) \ |
||
68 | const t *rowA = (const t *) srcRowA; \ |
||
69 | const t *rowB = (const t *) srcRowB; \ |
||
70 | const t *rowC = (const t *) srcRowC; \ |
||
71 | const t *rowD = (const t *) srcRowD; \ |
||
72 | t *dst = (t *) dstRow |
||
73 | |||
74 | #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ |
||
75 | ((unsigned) Aj + (unsigned) Ak \ |
||
76 | + (unsigned) Bj + (unsigned) Bk \ |
||
77 | + (unsigned) Cj + (unsigned) Ck \ |
||
78 | + (unsigned) Dj + (unsigned) Dk \ |
||
79 | + 4) >> 3 |
||
80 | |||
81 | #define FILTER_3D(e) \ |
||
82 | do { \ |
||
83 | dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \ |
||
84 | rowB[j][e], rowB[k][e], \ |
||
85 | rowC[j][e], rowC[k][e], \ |
||
86 | rowD[j][e], rowD[k][e]); \ |
||
87 | } while(0) |
||
88 | |||
89 | #define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ |
||
90 | (Aj + Ak \ |
||
91 | + Bj + Bk \ |
||
92 | + Cj + Ck \ |
||
93 | + Dj + Dk \ |
||
94 | + 4) / 8 |
||
95 | |||
96 | #define FILTER_3D_SIGNED(e) \ |
||
97 | do { \ |
||
98 | dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \ |
||
99 | rowB[j][e], rowB[k][e], \ |
||
100 | rowC[j][e], rowC[k][e], \ |
||
101 | rowD[j][e], rowD[k][e]); \ |
||
102 | } while(0) |
||
103 | |||
104 | #define FILTER_F_3D(e) \ |
||
105 | do { \ |
||
106 | dst[i][e] = (rowA[j][e] + rowA[k][e] \ |
||
107 | + rowB[j][e] + rowB[k][e] \ |
||
108 | + rowC[j][e] + rowC[k][e] \ |
||
109 | + rowD[j][e] + rowD[k][e]) * 0.125F; \ |
||
110 | } while(0) |
||
111 | |||
112 | #define FILTER_HF_3D(e) \ |
||
113 | do { \ |
||
114 | const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \ |
||
115 | const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \ |
||
116 | const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \ |
||
117 | const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \ |
||
118 | const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \ |
||
119 | const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \ |
||
120 | const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \ |
||
121 | const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \ |
||
122 | dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \ |
||
123 | * 0.125F); \ |
||
124 | } while(0) |
||
125 | /*@}*/ |
||
126 | |||
127 | |||
128 | /** |
||
129 | * Average together two rows of a source image to produce a single new |
||
130 | * row in the dest image. It's legal for the two source rows to point |
||
131 | * to the same data. The source width must be equal to either the |
||
132 | * dest width or two times the dest width. |
||
133 | * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc. |
||
134 | * \param comps number of components per pixel (1..4) |
||
135 | */ |
||
136 | static void |
||
137 | do_row(GLenum datatype, GLuint comps, GLint srcWidth, |
||
138 | const GLvoid *srcRowA, const GLvoid *srcRowB, |
||
139 | GLint dstWidth, GLvoid *dstRow) |
||
140 | { |
||
141 | const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; |
||
142 | const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; |
||
143 | |||
144 | ASSERT(comps >= 1); |
||
145 | ASSERT(comps <= 4); |
||
146 | |||
147 | /* This assertion is no longer valid with non-power-of-2 textures |
||
148 | assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); |
||
149 | */ |
||
150 | |||
151 | if (datatype == GL_UNSIGNED_BYTE && comps == 4) { |
||
152 | GLuint i, j, k; |
||
153 | const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA; |
||
154 | const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB; |
||
155 | GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow; |
||
156 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
157 | i++, j += colStride, k += colStride) { |
||
158 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
159 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
160 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
161 | dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; |
||
162 | } |
||
163 | } |
||
164 | else if (datatype == GL_UNSIGNED_BYTE && comps == 3) { |
||
165 | GLuint i, j, k; |
||
166 | const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA; |
||
167 | const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB; |
||
168 | GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow; |
||
169 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
170 | i++, j += colStride, k += colStride) { |
||
171 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
172 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
173 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
174 | } |
||
175 | } |
||
176 | else if (datatype == GL_UNSIGNED_BYTE && comps == 2) { |
||
177 | GLuint i, j, k; |
||
178 | const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA; |
||
179 | const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB; |
||
180 | GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow; |
||
181 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
182 | i++, j += colStride, k += colStride) { |
||
183 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2; |
||
184 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2; |
||
185 | } |
||
186 | } |
||
187 | else if (datatype == GL_UNSIGNED_BYTE && comps == 1) { |
||
188 | GLuint i, j, k; |
||
189 | const GLubyte *rowA = (const GLubyte *) srcRowA; |
||
190 | const GLubyte *rowB = (const GLubyte *) srcRowB; |
||
191 | GLubyte *dst = (GLubyte *) dstRow; |
||
192 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
193 | i++, j += colStride, k += colStride) { |
||
194 | dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; |
||
195 | } |
||
196 | } |
||
197 | |||
198 | else if (datatype == GL_BYTE && comps == 4) { |
||
199 | GLuint i, j, k; |
||
200 | const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA; |
||
201 | const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB; |
||
202 | GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow; |
||
203 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
204 | i++, j += colStride, k += colStride) { |
||
205 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
206 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
207 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
208 | dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; |
||
209 | } |
||
210 | } |
||
211 | else if (datatype == GL_BYTE && comps == 3) { |
||
212 | GLuint i, j, k; |
||
213 | const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA; |
||
214 | const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB; |
||
215 | GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow; |
||
216 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
217 | i++, j += colStride, k += colStride) { |
||
218 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
219 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
220 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
221 | } |
||
222 | } |
||
223 | else if (datatype == GL_BYTE && comps == 2) { |
||
224 | GLuint i, j, k; |
||
225 | const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA; |
||
226 | const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB; |
||
227 | GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow; |
||
228 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
229 | i++, j += colStride, k += colStride) { |
||
230 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
231 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
232 | } |
||
233 | } |
||
234 | else if (datatype == GL_BYTE && comps == 1) { |
||
235 | GLuint i, j, k; |
||
236 | const GLbyte *rowA = (const GLbyte *) srcRowA; |
||
237 | const GLbyte *rowB = (const GLbyte *) srcRowB; |
||
238 | GLbyte *dst = (GLbyte *) dstRow; |
||
239 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
240 | i++, j += colStride, k += colStride) { |
||
241 | dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; |
||
242 | } |
||
243 | } |
||
244 | |||
245 | else if (datatype == GL_UNSIGNED_SHORT && comps == 4) { |
||
246 | GLuint i, j, k; |
||
247 | const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA; |
||
248 | const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB; |
||
249 | GLushort(*dst)[4] = (GLushort(*)[4]) dstRow; |
||
250 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
251 | i++, j += colStride, k += colStride) { |
||
252 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
253 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
254 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
255 | dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; |
||
256 | } |
||
257 | } |
||
258 | else if (datatype == GL_UNSIGNED_SHORT && comps == 3) { |
||
259 | GLuint i, j, k; |
||
260 | const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA; |
||
261 | const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB; |
||
262 | GLushort(*dst)[3] = (GLushort(*)[3]) dstRow; |
||
263 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
264 | i++, j += colStride, k += colStride) { |
||
265 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
266 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
267 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
268 | } |
||
269 | } |
||
270 | else if (datatype == GL_UNSIGNED_SHORT && comps == 2) { |
||
271 | GLuint i, j, k; |
||
272 | const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA; |
||
273 | const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB; |
||
274 | GLushort(*dst)[2] = (GLushort(*)[2]) dstRow; |
||
275 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
276 | i++, j += colStride, k += colStride) { |
||
277 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
278 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
279 | } |
||
280 | } |
||
281 | else if (datatype == GL_UNSIGNED_SHORT && comps == 1) { |
||
282 | GLuint i, j, k; |
||
283 | const GLushort *rowA = (const GLushort *) srcRowA; |
||
284 | const GLushort *rowB = (const GLushort *) srcRowB; |
||
285 | GLushort *dst = (GLushort *) dstRow; |
||
286 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
287 | i++, j += colStride, k += colStride) { |
||
288 | dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; |
||
289 | } |
||
290 | } |
||
291 | |||
292 | else if (datatype == GL_SHORT && comps == 4) { |
||
293 | GLuint i, j, k; |
||
294 | const GLshort(*rowA)[4] = (const GLshort(*)[4]) srcRowA; |
||
295 | const GLshort(*rowB)[4] = (const GLshort(*)[4]) srcRowB; |
||
296 | GLshort(*dst)[4] = (GLshort(*)[4]) dstRow; |
||
297 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
298 | i++, j += colStride, k += colStride) { |
||
299 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
300 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
301 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
302 | dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; |
||
303 | } |
||
304 | } |
||
305 | else if (datatype == GL_SHORT && comps == 3) { |
||
306 | GLuint i, j, k; |
||
307 | const GLshort(*rowA)[3] = (const GLshort(*)[3]) srcRowA; |
||
308 | const GLshort(*rowB)[3] = (const GLshort(*)[3]) srcRowB; |
||
309 | GLshort(*dst)[3] = (GLshort(*)[3]) dstRow; |
||
310 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
311 | i++, j += colStride, k += colStride) { |
||
312 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
313 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
314 | dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; |
||
315 | } |
||
316 | } |
||
317 | else if (datatype == GL_SHORT && comps == 2) { |
||
318 | GLuint i, j, k; |
||
319 | const GLshort(*rowA)[2] = (const GLshort(*)[2]) srcRowA; |
||
320 | const GLshort(*rowB)[2] = (const GLshort(*)[2]) srcRowB; |
||
321 | GLshort(*dst)[2] = (GLshort(*)[2]) dstRow; |
||
322 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
323 | i++, j += colStride, k += colStride) { |
||
324 | dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; |
||
325 | dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; |
||
326 | } |
||
327 | } |
||
328 | else if (datatype == GL_SHORT && comps == 1) { |
||
329 | GLuint i, j, k; |
||
330 | const GLshort *rowA = (const GLshort *) srcRowA; |
||
331 | const GLshort *rowB = (const GLshort *) srcRowB; |
||
332 | GLshort *dst = (GLshort *) dstRow; |
||
333 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
334 | i++, j += colStride, k += colStride) { |
||
335 | dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; |
||
336 | } |
||
337 | } |
||
338 | |||
339 | else if (datatype == GL_FLOAT && comps == 4) { |
||
340 | GLuint i, j, k; |
||
341 | const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA; |
||
342 | const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB; |
||
343 | GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow; |
||
344 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
345 | i++, j += colStride, k += colStride) { |
||
346 | dst[i][0] = (rowA[j][0] + rowA[k][0] + |
||
347 | rowB[j][0] + rowB[k][0]) * 0.25F; |
||
348 | dst[i][1] = (rowA[j][1] + rowA[k][1] + |
||
349 | rowB[j][1] + rowB[k][1]) * 0.25F; |
||
350 | dst[i][2] = (rowA[j][2] + rowA[k][2] + |
||
351 | rowB[j][2] + rowB[k][2]) * 0.25F; |
||
352 | dst[i][3] = (rowA[j][3] + rowA[k][3] + |
||
353 | rowB[j][3] + rowB[k][3]) * 0.25F; |
||
354 | } |
||
355 | } |
||
356 | else if (datatype == GL_FLOAT && comps == 3) { |
||
357 | GLuint i, j, k; |
||
358 | const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA; |
||
359 | const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB; |
||
360 | GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow; |
||
361 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
362 | i++, j += colStride, k += colStride) { |
||
363 | dst[i][0] = (rowA[j][0] + rowA[k][0] + |
||
364 | rowB[j][0] + rowB[k][0]) * 0.25F; |
||
365 | dst[i][1] = (rowA[j][1] + rowA[k][1] + |
||
366 | rowB[j][1] + rowB[k][1]) * 0.25F; |
||
367 | dst[i][2] = (rowA[j][2] + rowA[k][2] + |
||
368 | rowB[j][2] + rowB[k][2]) * 0.25F; |
||
369 | } |
||
370 | } |
||
371 | else if (datatype == GL_FLOAT && comps == 2) { |
||
372 | GLuint i, j, k; |
||
373 | const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA; |
||
374 | const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB; |
||
375 | GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow; |
||
376 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
377 | i++, j += colStride, k += colStride) { |
||
378 | dst[i][0] = (rowA[j][0] + rowA[k][0] + |
||
379 | rowB[j][0] + rowB[k][0]) * 0.25F; |
||
380 | dst[i][1] = (rowA[j][1] + rowA[k][1] + |
||
381 | rowB[j][1] + rowB[k][1]) * 0.25F; |
||
382 | } |
||
383 | } |
||
384 | else if (datatype == GL_FLOAT && comps == 1) { |
||
385 | GLuint i, j, k; |
||
386 | const GLfloat *rowA = (const GLfloat *) srcRowA; |
||
387 | const GLfloat *rowB = (const GLfloat *) srcRowB; |
||
388 | GLfloat *dst = (GLfloat *) dstRow; |
||
389 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
390 | i++, j += colStride, k += colStride) { |
||
391 | dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; |
||
392 | } |
||
393 | } |
||
394 | |||
395 | else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) { |
||
396 | GLuint i, j, k, comp; |
||
397 | const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA; |
||
398 | const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB; |
||
399 | GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow; |
||
400 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
401 | i++, j += colStride, k += colStride) { |
||
402 | for (comp = 0; comp < 4; comp++) { |
||
403 | GLfloat aj, ak, bj, bk; |
||
404 | aj = _mesa_half_to_float(rowA[j][comp]); |
||
405 | ak = _mesa_half_to_float(rowA[k][comp]); |
||
406 | bj = _mesa_half_to_float(rowB[j][comp]); |
||
407 | bk = _mesa_half_to_float(rowB[k][comp]); |
||
408 | dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); |
||
409 | } |
||
410 | } |
||
411 | } |
||
412 | else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) { |
||
413 | GLuint i, j, k, comp; |
||
414 | const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA; |
||
415 | const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB; |
||
416 | GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow; |
||
417 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
418 | i++, j += colStride, k += colStride) { |
||
419 | for (comp = 0; comp < 3; comp++) { |
||
420 | GLfloat aj, ak, bj, bk; |
||
421 | aj = _mesa_half_to_float(rowA[j][comp]); |
||
422 | ak = _mesa_half_to_float(rowA[k][comp]); |
||
423 | bj = _mesa_half_to_float(rowB[j][comp]); |
||
424 | bk = _mesa_half_to_float(rowB[k][comp]); |
||
425 | dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); |
||
426 | } |
||
427 | } |
||
428 | } |
||
429 | else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) { |
||
430 | GLuint i, j, k, comp; |
||
431 | const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA; |
||
432 | const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB; |
||
433 | GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow; |
||
434 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
435 | i++, j += colStride, k += colStride) { |
||
436 | for (comp = 0; comp < 2; comp++) { |
||
437 | GLfloat aj, ak, bj, bk; |
||
438 | aj = _mesa_half_to_float(rowA[j][comp]); |
||
439 | ak = _mesa_half_to_float(rowA[k][comp]); |
||
440 | bj = _mesa_half_to_float(rowB[j][comp]); |
||
441 | bk = _mesa_half_to_float(rowB[k][comp]); |
||
442 | dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); |
||
443 | } |
||
444 | } |
||
445 | } |
||
446 | else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) { |
||
447 | GLuint i, j, k; |
||
448 | const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; |
||
449 | const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; |
||
450 | GLhalfARB *dst = (GLhalfARB *) dstRow; |
||
451 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
452 | i++, j += colStride, k += colStride) { |
||
453 | GLfloat aj, ak, bj, bk; |
||
454 | aj = _mesa_half_to_float(rowA[j]); |
||
455 | ak = _mesa_half_to_float(rowA[k]); |
||
456 | bj = _mesa_half_to_float(rowB[j]); |
||
457 | bk = _mesa_half_to_float(rowB[k]); |
||
458 | dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); |
||
459 | } |
||
460 | } |
||
461 | |||
462 | else if (datatype == GL_UNSIGNED_INT && comps == 1) { |
||
463 | GLuint i, j, k; |
||
464 | const GLuint *rowA = (const GLuint *) srcRowA; |
||
465 | const GLuint *rowB = (const GLuint *) srcRowB; |
||
466 | GLuint *dst = (GLuint *) dstRow; |
||
467 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
468 | i++, j += colStride, k += colStride) { |
||
469 | dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4); |
||
470 | } |
||
471 | } |
||
472 | |||
473 | else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) { |
||
474 | GLuint i, j, k; |
||
475 | const GLushort *rowA = (const GLushort *) srcRowA; |
||
476 | const GLushort *rowB = (const GLushort *) srcRowB; |
||
477 | GLushort *dst = (GLushort *) dstRow; |
||
478 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
479 | i++, j += colStride, k += colStride) { |
||
480 | const GLint rowAr0 = rowA[j] & 0x1f; |
||
481 | const GLint rowAr1 = rowA[k] & 0x1f; |
||
482 | const GLint rowBr0 = rowB[j] & 0x1f; |
||
483 | const GLint rowBr1 = rowB[k] & 0x1f; |
||
484 | const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; |
||
485 | const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; |
||
486 | const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; |
||
487 | const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; |
||
488 | const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; |
||
489 | const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; |
||
490 | const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; |
||
491 | const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; |
||
492 | const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; |
||
493 | const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; |
||
494 | const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; |
||
495 | dst[i] = (blue << 11) | (green << 5) | red; |
||
496 | } |
||
497 | } |
||
498 | else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) { |
||
499 | GLuint i, j, k; |
||
500 | const GLushort *rowA = (const GLushort *) srcRowA; |
||
501 | const GLushort *rowB = (const GLushort *) srcRowB; |
||
502 | GLushort *dst = (GLushort *) dstRow; |
||
503 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
504 | i++, j += colStride, k += colStride) { |
||
505 | const GLint rowAr0 = rowA[j] & 0xf; |
||
506 | const GLint rowAr1 = rowA[k] & 0xf; |
||
507 | const GLint rowBr0 = rowB[j] & 0xf; |
||
508 | const GLint rowBr1 = rowB[k] & 0xf; |
||
509 | const GLint rowAg0 = (rowA[j] >> 4) & 0xf; |
||
510 | const GLint rowAg1 = (rowA[k] >> 4) & 0xf; |
||
511 | const GLint rowBg0 = (rowB[j] >> 4) & 0xf; |
||
512 | const GLint rowBg1 = (rowB[k] >> 4) & 0xf; |
||
513 | const GLint rowAb0 = (rowA[j] >> 8) & 0xf; |
||
514 | const GLint rowAb1 = (rowA[k] >> 8) & 0xf; |
||
515 | const GLint rowBb0 = (rowB[j] >> 8) & 0xf; |
||
516 | const GLint rowBb1 = (rowB[k] >> 8) & 0xf; |
||
517 | const GLint rowAa0 = (rowA[j] >> 12) & 0xf; |
||
518 | const GLint rowAa1 = (rowA[k] >> 12) & 0xf; |
||
519 | const GLint rowBa0 = (rowB[j] >> 12) & 0xf; |
||
520 | const GLint rowBa1 = (rowB[k] >> 12) & 0xf; |
||
521 | const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; |
||
522 | const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; |
||
523 | const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; |
||
524 | const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; |
||
525 | dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; |
||
526 | } |
||
527 | } |
||
528 | else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) { |
||
529 | GLuint i, j, k; |
||
530 | const GLushort *rowA = (const GLushort *) srcRowA; |
||
531 | const GLushort *rowB = (const GLushort *) srcRowB; |
||
532 | GLushort *dst = (GLushort *) dstRow; |
||
533 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
534 | i++, j += colStride, k += colStride) { |
||
535 | const GLint rowAr0 = rowA[j] & 0x1f; |
||
536 | const GLint rowAr1 = rowA[k] & 0x1f; |
||
537 | const GLint rowBr0 = rowB[j] & 0x1f; |
||
538 | const GLint rowBr1 = rowB[k] & 0x1f; |
||
539 | const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; |
||
540 | const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; |
||
541 | const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; |
||
542 | const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; |
||
543 | const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; |
||
544 | const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; |
||
545 | const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; |
||
546 | const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; |
||
547 | const GLint rowAa0 = (rowA[j] >> 15) & 0x1; |
||
548 | const GLint rowAa1 = (rowA[k] >> 15) & 0x1; |
||
549 | const GLint rowBa0 = (rowB[j] >> 15) & 0x1; |
||
550 | const GLint rowBa1 = (rowB[k] >> 15) & 0x1; |
||
551 | const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; |
||
552 | const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; |
||
553 | const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; |
||
554 | const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; |
||
555 | dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; |
||
556 | } |
||
557 | } |
||
558 | else if (datatype == GL_UNSIGNED_SHORT_5_5_5_1 && comps == 4) { |
||
559 | GLuint i, j, k; |
||
560 | const GLushort *rowA = (const GLushort *) srcRowA; |
||
561 | const GLushort *rowB = (const GLushort *) srcRowB; |
||
562 | GLushort *dst = (GLushort *) dstRow; |
||
563 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
564 | i++, j += colStride, k += colStride) { |
||
565 | const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; |
||
566 | const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; |
||
567 | const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; |
||
568 | const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; |
||
569 | const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; |
||
570 | const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; |
||
571 | const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; |
||
572 | const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; |
||
573 | const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; |
||
574 | const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; |
||
575 | const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; |
||
576 | const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; |
||
577 | const GLint rowAa0 = (rowA[j] & 0x1); |
||
578 | const GLint rowAa1 = (rowA[k] & 0x1); |
||
579 | const GLint rowBa0 = (rowB[j] & 0x1); |
||
580 | const GLint rowBa1 = (rowB[k] & 0x1); |
||
581 | const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; |
||
582 | const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; |
||
583 | const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; |
||
584 | const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; |
||
585 | dst[i] = (red << 11) | (green << 6) | (blue << 1) | alpha; |
||
586 | } |
||
587 | } |
||
588 | |||
589 | else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) { |
||
590 | GLuint i, j, k; |
||
591 | const GLubyte *rowA = (const GLubyte *) srcRowA; |
||
592 | const GLubyte *rowB = (const GLubyte *) srcRowB; |
||
593 | GLubyte *dst = (GLubyte *) dstRow; |
||
594 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
595 | i++, j += colStride, k += colStride) { |
||
596 | const GLint rowAr0 = rowA[j] & 0x3; |
||
597 | const GLint rowAr1 = rowA[k] & 0x3; |
||
598 | const GLint rowBr0 = rowB[j] & 0x3; |
||
599 | const GLint rowBr1 = rowB[k] & 0x3; |
||
600 | const GLint rowAg0 = (rowA[j] >> 2) & 0x7; |
||
601 | const GLint rowAg1 = (rowA[k] >> 2) & 0x7; |
||
602 | const GLint rowBg0 = (rowB[j] >> 2) & 0x7; |
||
603 | const GLint rowBg1 = (rowB[k] >> 2) & 0x7; |
||
604 | const GLint rowAb0 = (rowA[j] >> 5) & 0x7; |
||
605 | const GLint rowAb1 = (rowA[k] >> 5) & 0x7; |
||
606 | const GLint rowBb0 = (rowB[j] >> 5) & 0x7; |
||
607 | const GLint rowBb1 = (rowB[k] >> 5) & 0x7; |
||
608 | const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; |
||
609 | const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; |
||
610 | const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; |
||
611 | dst[i] = (blue << 5) | (green << 2) | red; |
||
612 | } |
||
613 | } |
||
614 | else { |
||
615 | _mesa_problem(NULL, "bad format in do_row()"); |
||
616 | } |
||
617 | } |
||
618 | |||
619 | |||
620 | /** |
||
621 | * Average together four rows of a source image to produce a single new |
||
622 | * row in the dest image. It's legal for the two source rows to point |
||
623 | * to the same data. The source width must be equal to either the |
||
624 | * dest width or two times the dest width. |
||
625 | * |
||
626 | * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, |
||
627 | * \c GL_FLOAT, etc. |
||
628 | * \param comps number of components per pixel (1..4) |
||
629 | * \param srcWidth Width of a row in the source data |
||
630 | * \param srcRowA Pointer to one of the rows of source data |
||
631 | * \param srcRowB Pointer to one of the rows of source data |
||
632 | * \param srcRowC Pointer to one of the rows of source data |
||
633 | * \param srcRowD Pointer to one of the rows of source data |
||
634 | * \param dstWidth Width of a row in the destination data |
||
635 | * \param srcRowA Pointer to the row of destination data |
||
636 | */ |
||
637 | static void |
||
638 | do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, |
||
639 | const GLvoid *srcRowA, const GLvoid *srcRowB, |
||
640 | const GLvoid *srcRowC, const GLvoid *srcRowD, |
||
641 | GLint dstWidth, GLvoid *dstRow) |
||
642 | { |
||
643 | const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; |
||
644 | const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; |
||
645 | GLuint i, j, k; |
||
646 | |||
647 | ASSERT(comps >= 1); |
||
648 | ASSERT(comps <= 4); |
||
649 | |||
650 | if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) { |
||
651 | DECLARE_ROW_POINTERS(GLubyte, 4); |
||
652 | |||
653 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
654 | i++, j += colStride, k += colStride) { |
||
655 | FILTER_3D(0); |
||
656 | FILTER_3D(1); |
||
657 | FILTER_3D(2); |
||
658 | FILTER_3D(3); |
||
659 | } |
||
660 | } |
||
661 | else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) { |
||
662 | DECLARE_ROW_POINTERS(GLubyte, 3); |
||
663 | |||
664 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
665 | i++, j += colStride, k += colStride) { |
||
666 | FILTER_3D(0); |
||
667 | FILTER_3D(1); |
||
668 | FILTER_3D(2); |
||
669 | } |
||
670 | } |
||
671 | else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) { |
||
672 | DECLARE_ROW_POINTERS(GLubyte, 2); |
||
673 | |||
674 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
675 | i++, j += colStride, k += colStride) { |
||
676 | FILTER_3D(0); |
||
677 | FILTER_3D(1); |
||
678 | } |
||
679 | } |
||
680 | else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) { |
||
681 | DECLARE_ROW_POINTERS(GLubyte, 1); |
||
682 | |||
683 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
684 | i++, j += colStride, k += colStride) { |
||
685 | FILTER_3D(0); |
||
686 | } |
||
687 | } |
||
688 | else if ((datatype == GL_BYTE) && (comps == 4)) { |
||
689 | DECLARE_ROW_POINTERS(GLbyte, 4); |
||
690 | |||
691 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
692 | i++, j += colStride, k += colStride) { |
||
693 | FILTER_3D_SIGNED(0); |
||
694 | FILTER_3D_SIGNED(1); |
||
695 | FILTER_3D_SIGNED(2); |
||
696 | FILTER_3D_SIGNED(3); |
||
697 | } |
||
698 | } |
||
699 | else if ((datatype == GL_BYTE) && (comps == 3)) { |
||
700 | DECLARE_ROW_POINTERS(GLbyte, 3); |
||
701 | |||
702 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
703 | i++, j += colStride, k += colStride) { |
||
704 | FILTER_3D_SIGNED(0); |
||
705 | FILTER_3D_SIGNED(1); |
||
706 | FILTER_3D_SIGNED(2); |
||
707 | } |
||
708 | } |
||
709 | else if ((datatype == GL_BYTE) && (comps == 2)) { |
||
710 | DECLARE_ROW_POINTERS(GLbyte, 2); |
||
711 | |||
712 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
713 | i++, j += colStride, k += colStride) { |
||
714 | FILTER_3D_SIGNED(0); |
||
715 | FILTER_3D_SIGNED(1); |
||
716 | } |
||
717 | } |
||
718 | else if ((datatype == GL_BYTE) && (comps == 1)) { |
||
719 | DECLARE_ROW_POINTERS(GLbyte, 1); |
||
720 | |||
721 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
722 | i++, j += colStride, k += colStride) { |
||
723 | FILTER_3D_SIGNED(0); |
||
724 | } |
||
725 | } |
||
726 | else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) { |
||
727 | DECLARE_ROW_POINTERS(GLushort, 4); |
||
728 | |||
729 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
730 | i++, j += colStride, k += colStride) { |
||
731 | FILTER_3D(0); |
||
732 | FILTER_3D(1); |
||
733 | FILTER_3D(2); |
||
734 | FILTER_3D(3); |
||
735 | } |
||
736 | } |
||
737 | else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) { |
||
738 | DECLARE_ROW_POINTERS(GLushort, 3); |
||
739 | |||
740 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
741 | i++, j += colStride, k += colStride) { |
||
742 | FILTER_3D(0); |
||
743 | FILTER_3D(1); |
||
744 | FILTER_3D(2); |
||
745 | } |
||
746 | } |
||
747 | else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) { |
||
748 | DECLARE_ROW_POINTERS(GLushort, 2); |
||
749 | |||
750 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
751 | i++, j += colStride, k += colStride) { |
||
752 | FILTER_3D(0); |
||
753 | FILTER_3D(1); |
||
754 | } |
||
755 | } |
||
756 | else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) { |
||
757 | DECLARE_ROW_POINTERS(GLushort, 1); |
||
758 | |||
759 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
760 | i++, j += colStride, k += colStride) { |
||
761 | FILTER_3D(0); |
||
762 | } |
||
763 | } |
||
764 | else if ((datatype == GL_SHORT) && (comps == 4)) { |
||
765 | DECLARE_ROW_POINTERS(GLshort, 4); |
||
766 | |||
767 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
768 | i++, j += colStride, k += colStride) { |
||
769 | FILTER_3D(0); |
||
770 | FILTER_3D(1); |
||
771 | FILTER_3D(2); |
||
772 | FILTER_3D(3); |
||
773 | } |
||
774 | } |
||
775 | else if ((datatype == GL_SHORT) && (comps == 3)) { |
||
776 | DECLARE_ROW_POINTERS(GLshort, 3); |
||
777 | |||
778 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
779 | i++, j += colStride, k += colStride) { |
||
780 | FILTER_3D(0); |
||
781 | FILTER_3D(1); |
||
782 | FILTER_3D(2); |
||
783 | } |
||
784 | } |
||
785 | else if ((datatype == GL_SHORT) && (comps == 2)) { |
||
786 | DECLARE_ROW_POINTERS(GLshort, 2); |
||
787 | |||
788 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
789 | i++, j += colStride, k += colStride) { |
||
790 | FILTER_3D(0); |
||
791 | FILTER_3D(1); |
||
792 | } |
||
793 | } |
||
794 | else if ((datatype == GL_SHORT) && (comps == 1)) { |
||
795 | DECLARE_ROW_POINTERS(GLshort, 1); |
||
796 | |||
797 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
798 | i++, j += colStride, k += colStride) { |
||
799 | FILTER_3D(0); |
||
800 | } |
||
801 | } |
||
802 | else if ((datatype == GL_FLOAT) && (comps == 4)) { |
||
803 | DECLARE_ROW_POINTERS(GLfloat, 4); |
||
804 | |||
805 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
806 | i++, j += colStride, k += colStride) { |
||
807 | FILTER_F_3D(0); |
||
808 | FILTER_F_3D(1); |
||
809 | FILTER_F_3D(2); |
||
810 | FILTER_F_3D(3); |
||
811 | } |
||
812 | } |
||
813 | else if ((datatype == GL_FLOAT) && (comps == 3)) { |
||
814 | DECLARE_ROW_POINTERS(GLfloat, 3); |
||
815 | |||
816 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
817 | i++, j += colStride, k += colStride) { |
||
818 | FILTER_F_3D(0); |
||
819 | FILTER_F_3D(1); |
||
820 | FILTER_F_3D(2); |
||
821 | } |
||
822 | } |
||
823 | else if ((datatype == GL_FLOAT) && (comps == 2)) { |
||
824 | DECLARE_ROW_POINTERS(GLfloat, 2); |
||
825 | |||
826 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
827 | i++, j += colStride, k += colStride) { |
||
828 | FILTER_F_3D(0); |
||
829 | FILTER_F_3D(1); |
||
830 | } |
||
831 | } |
||
832 | else if ((datatype == GL_FLOAT) && (comps == 1)) { |
||
833 | DECLARE_ROW_POINTERS(GLfloat, 1); |
||
834 | |||
835 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
836 | i++, j += colStride, k += colStride) { |
||
837 | FILTER_F_3D(0); |
||
838 | } |
||
839 | } |
||
840 | else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) { |
||
841 | DECLARE_ROW_POINTERS(GLhalfARB, 4); |
||
842 | |||
843 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
844 | i++, j += colStride, k += colStride) { |
||
845 | FILTER_HF_3D(0); |
||
846 | FILTER_HF_3D(1); |
||
847 | FILTER_HF_3D(2); |
||
848 | FILTER_HF_3D(3); |
||
849 | } |
||
850 | } |
||
851 | else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) { |
||
852 | DECLARE_ROW_POINTERS(GLhalfARB, 4); |
||
853 | |||
854 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
855 | i++, j += colStride, k += colStride) { |
||
856 | FILTER_HF_3D(0); |
||
857 | FILTER_HF_3D(1); |
||
858 | FILTER_HF_3D(2); |
||
859 | } |
||
860 | } |
||
861 | else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) { |
||
862 | DECLARE_ROW_POINTERS(GLhalfARB, 4); |
||
863 | |||
864 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
865 | i++, j += colStride, k += colStride) { |
||
866 | FILTER_HF_3D(0); |
||
867 | FILTER_HF_3D(1); |
||
868 | } |
||
869 | } |
||
870 | else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) { |
||
871 | DECLARE_ROW_POINTERS(GLhalfARB, 4); |
||
872 | |||
873 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
874 | i++, j += colStride, k += colStride) { |
||
875 | FILTER_HF_3D(0); |
||
876 | } |
||
877 | } |
||
878 | else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) { |
||
879 | const GLuint *rowA = (const GLuint *) srcRowA; |
||
880 | const GLuint *rowB = (const GLuint *) srcRowB; |
||
881 | const GLuint *rowC = (const GLuint *) srcRowC; |
||
882 | const GLuint *rowD = (const GLuint *) srcRowD; |
||
883 | GLfloat *dst = (GLfloat *) dstRow; |
||
884 | |||
885 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
886 | i++, j += colStride, k += colStride) { |
||
887 | const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k]) |
||
888 | + ((uint64_t) rowB[j] + (uint64_t) rowB[k]) |
||
889 | + ((uint64_t) rowC[j] + (uint64_t) rowC[k]) |
||
890 | + ((uint64_t) rowD[j] + (uint64_t) rowD[k])); |
||
891 | dst[i] = (GLfloat)((double) tmp * 0.125); |
||
892 | } |
||
893 | } |
||
894 | else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) { |
||
895 | DECLARE_ROW_POINTERS0(GLushort); |
||
896 | |||
897 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
898 | i++, j += colStride, k += colStride) { |
||
899 | const GLint rowAr0 = rowA[j] & 0x1f; |
||
900 | const GLint rowAr1 = rowA[k] & 0x1f; |
||
901 | const GLint rowBr0 = rowB[j] & 0x1f; |
||
902 | const GLint rowBr1 = rowB[k] & 0x1f; |
||
903 | const GLint rowCr0 = rowC[j] & 0x1f; |
||
904 | const GLint rowCr1 = rowC[k] & 0x1f; |
||
905 | const GLint rowDr0 = rowD[j] & 0x1f; |
||
906 | const GLint rowDr1 = rowD[k] & 0x1f; |
||
907 | const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; |
||
908 | const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; |
||
909 | const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; |
||
910 | const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; |
||
911 | const GLint rowCg0 = (rowC[j] >> 5) & 0x3f; |
||
912 | const GLint rowCg1 = (rowC[k] >> 5) & 0x3f; |
||
913 | const GLint rowDg0 = (rowD[j] >> 5) & 0x3f; |
||
914 | const GLint rowDg1 = (rowD[k] >> 5) & 0x3f; |
||
915 | const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; |
||
916 | const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; |
||
917 | const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; |
||
918 | const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; |
||
919 | const GLint rowCb0 = (rowC[j] >> 11) & 0x1f; |
||
920 | const GLint rowCb1 = (rowC[k] >> 11) & 0x1f; |
||
921 | const GLint rowDb0 = (rowD[j] >> 11) & 0x1f; |
||
922 | const GLint rowDb1 = (rowD[k] >> 11) & 0x1f; |
||
923 | const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, |
||
924 | rowCr0, rowCr1, rowDr0, rowDr1); |
||
925 | const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, |
||
926 | rowCg0, rowCg1, rowDg0, rowDg1); |
||
927 | const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, |
||
928 | rowCb0, rowCb1, rowDb0, rowDb1); |
||
929 | dst[i] = (b << 11) | (g << 5) | r; |
||
930 | } |
||
931 | } |
||
932 | else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) { |
||
933 | DECLARE_ROW_POINTERS0(GLushort); |
||
934 | |||
935 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
936 | i++, j += colStride, k += colStride) { |
||
937 | const GLint rowAr0 = rowA[j] & 0xf; |
||
938 | const GLint rowAr1 = rowA[k] & 0xf; |
||
939 | const GLint rowBr0 = rowB[j] & 0xf; |
||
940 | const GLint rowBr1 = rowB[k] & 0xf; |
||
941 | const GLint rowCr0 = rowC[j] & 0xf; |
||
942 | const GLint rowCr1 = rowC[k] & 0xf; |
||
943 | const GLint rowDr0 = rowD[j] & 0xf; |
||
944 | const GLint rowDr1 = rowD[k] & 0xf; |
||
945 | const GLint rowAg0 = (rowA[j] >> 4) & 0xf; |
||
946 | const GLint rowAg1 = (rowA[k] >> 4) & 0xf; |
||
947 | const GLint rowBg0 = (rowB[j] >> 4) & 0xf; |
||
948 | const GLint rowBg1 = (rowB[k] >> 4) & 0xf; |
||
949 | const GLint rowCg0 = (rowC[j] >> 4) & 0xf; |
||
950 | const GLint rowCg1 = (rowC[k] >> 4) & 0xf; |
||
951 | const GLint rowDg0 = (rowD[j] >> 4) & 0xf; |
||
952 | const GLint rowDg1 = (rowD[k] >> 4) & 0xf; |
||
953 | const GLint rowAb0 = (rowA[j] >> 8) & 0xf; |
||
954 | const GLint rowAb1 = (rowA[k] >> 8) & 0xf; |
||
955 | const GLint rowBb0 = (rowB[j] >> 8) & 0xf; |
||
956 | const GLint rowBb1 = (rowB[k] >> 8) & 0xf; |
||
957 | const GLint rowCb0 = (rowC[j] >> 8) & 0xf; |
||
958 | const GLint rowCb1 = (rowC[k] >> 8) & 0xf; |
||
959 | const GLint rowDb0 = (rowD[j] >> 8) & 0xf; |
||
960 | const GLint rowDb1 = (rowD[k] >> 8) & 0xf; |
||
961 | const GLint rowAa0 = (rowA[j] >> 12) & 0xf; |
||
962 | const GLint rowAa1 = (rowA[k] >> 12) & 0xf; |
||
963 | const GLint rowBa0 = (rowB[j] >> 12) & 0xf; |
||
964 | const GLint rowBa1 = (rowB[k] >> 12) & 0xf; |
||
965 | const GLint rowCa0 = (rowC[j] >> 12) & 0xf; |
||
966 | const GLint rowCa1 = (rowC[k] >> 12) & 0xf; |
||
967 | const GLint rowDa0 = (rowD[j] >> 12) & 0xf; |
||
968 | const GLint rowDa1 = (rowD[k] >> 12) & 0xf; |
||
969 | const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, |
||
970 | rowCr0, rowCr1, rowDr0, rowDr1); |
||
971 | const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, |
||
972 | rowCg0, rowCg1, rowDg0, rowDg1); |
||
973 | const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, |
||
974 | rowCb0, rowCb1, rowDb0, rowDb1); |
||
975 | const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, |
||
976 | rowCa0, rowCa1, rowDa0, rowDa1); |
||
977 | |||
978 | dst[i] = (a << 12) | (b << 8) | (g << 4) | r; |
||
979 | } |
||
980 | } |
||
981 | else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) { |
||
982 | DECLARE_ROW_POINTERS0(GLushort); |
||
983 | |||
984 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
985 | i++, j += colStride, k += colStride) { |
||
986 | const GLint rowAr0 = rowA[j] & 0x1f; |
||
987 | const GLint rowAr1 = rowA[k] & 0x1f; |
||
988 | const GLint rowBr0 = rowB[j] & 0x1f; |
||
989 | const GLint rowBr1 = rowB[k] & 0x1f; |
||
990 | const GLint rowCr0 = rowC[j] & 0x1f; |
||
991 | const GLint rowCr1 = rowC[k] & 0x1f; |
||
992 | const GLint rowDr0 = rowD[j] & 0x1f; |
||
993 | const GLint rowDr1 = rowD[k] & 0x1f; |
||
994 | const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; |
||
995 | const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; |
||
996 | const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; |
||
997 | const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; |
||
998 | const GLint rowCg0 = (rowC[j] >> 5) & 0x1f; |
||
999 | const GLint rowCg1 = (rowC[k] >> 5) & 0x1f; |
||
1000 | const GLint rowDg0 = (rowD[j] >> 5) & 0x1f; |
||
1001 | const GLint rowDg1 = (rowD[k] >> 5) & 0x1f; |
||
1002 | const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; |
||
1003 | const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; |
||
1004 | const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; |
||
1005 | const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; |
||
1006 | const GLint rowCb0 = (rowC[j] >> 10) & 0x1f; |
||
1007 | const GLint rowCb1 = (rowC[k] >> 10) & 0x1f; |
||
1008 | const GLint rowDb0 = (rowD[j] >> 10) & 0x1f; |
||
1009 | const GLint rowDb1 = (rowD[k] >> 10) & 0x1f; |
||
1010 | const GLint rowAa0 = (rowA[j] >> 15) & 0x1; |
||
1011 | const GLint rowAa1 = (rowA[k] >> 15) & 0x1; |
||
1012 | const GLint rowBa0 = (rowB[j] >> 15) & 0x1; |
||
1013 | const GLint rowBa1 = (rowB[k] >> 15) & 0x1; |
||
1014 | const GLint rowCa0 = (rowC[j] >> 15) & 0x1; |
||
1015 | const GLint rowCa1 = (rowC[k] >> 15) & 0x1; |
||
1016 | const GLint rowDa0 = (rowD[j] >> 15) & 0x1; |
||
1017 | const GLint rowDa1 = (rowD[k] >> 15) & 0x1; |
||
1018 | const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, |
||
1019 | rowCr0, rowCr1, rowDr0, rowDr1); |
||
1020 | const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, |
||
1021 | rowCg0, rowCg1, rowDg0, rowDg1); |
||
1022 | const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, |
||
1023 | rowCb0, rowCb1, rowDb0, rowDb1); |
||
1024 | const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, |
||
1025 | rowCa0, rowCa1, rowDa0, rowDa1); |
||
1026 | |||
1027 | dst[i] = (a << 15) | (b << 10) | (g << 5) | r; |
||
1028 | } |
||
1029 | } |
||
1030 | else if ((datatype == GL_UNSIGNED_SHORT_5_5_5_1) && (comps == 4)) { |
||
1031 | DECLARE_ROW_POINTERS0(GLushort); |
||
1032 | |||
1033 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
1034 | i++, j += colStride, k += colStride) { |
||
1035 | const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; |
||
1036 | const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; |
||
1037 | const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; |
||
1038 | const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; |
||
1039 | const GLint rowCr0 = (rowC[j] >> 11) & 0x1f; |
||
1040 | const GLint rowCr1 = (rowC[k] >> 11) & 0x1f; |
||
1041 | const GLint rowDr0 = (rowD[j] >> 11) & 0x1f; |
||
1042 | const GLint rowDr1 = (rowD[k] >> 11) & 0x1f; |
||
1043 | const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; |
||
1044 | const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; |
||
1045 | const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; |
||
1046 | const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; |
||
1047 | const GLint rowCg0 = (rowC[j] >> 6) & 0x1f; |
||
1048 | const GLint rowCg1 = (rowC[k] >> 6) & 0x1f; |
||
1049 | const GLint rowDg0 = (rowD[j] >> 6) & 0x1f; |
||
1050 | const GLint rowDg1 = (rowD[k] >> 6) & 0x1f; |
||
1051 | const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; |
||
1052 | const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; |
||
1053 | const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; |
||
1054 | const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; |
||
1055 | const GLint rowCb0 = (rowC[j] >> 1) & 0x1f; |
||
1056 | const GLint rowCb1 = (rowC[k] >> 1) & 0x1f; |
||
1057 | const GLint rowDb0 = (rowD[j] >> 1) & 0x1f; |
||
1058 | const GLint rowDb1 = (rowD[k] >> 1) & 0x1f; |
||
1059 | const GLint rowAa0 = (rowA[j] & 0x1); |
||
1060 | const GLint rowAa1 = (rowA[k] & 0x1); |
||
1061 | const GLint rowBa0 = (rowB[j] & 0x1); |
||
1062 | const GLint rowBa1 = (rowB[k] & 0x1); |
||
1063 | const GLint rowCa0 = (rowC[j] & 0x1); |
||
1064 | const GLint rowCa1 = (rowC[k] & 0x1); |
||
1065 | const GLint rowDa0 = (rowD[j] & 0x1); |
||
1066 | const GLint rowDa1 = (rowD[k] & 0x1); |
||
1067 | const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, |
||
1068 | rowCr0, rowCr1, rowDr0, rowDr1); |
||
1069 | const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, |
||
1070 | rowCg0, rowCg1, rowDg0, rowDg1); |
||
1071 | const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, |
||
1072 | rowCb0, rowCb1, rowDb0, rowDb1); |
||
1073 | const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, |
||
1074 | rowCa0, rowCa1, rowDa0, rowDa1); |
||
1075 | |||
1076 | dst[i] = (r << 11) | (g << 6) | (b << 1) | a; |
||
1077 | } |
||
1078 | } |
||
1079 | else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) { |
||
1080 | DECLARE_ROW_POINTERS0(GLubyte); |
||
1081 | |||
1082 | for (i = j = 0, k = k0; i < (GLuint) dstWidth; |
||
1083 | i++, j += colStride, k += colStride) { |
||
1084 | const GLint rowAr0 = rowA[j] & 0x3; |
||
1085 | const GLint rowAr1 = rowA[k] & 0x3; |
||
1086 | const GLint rowBr0 = rowB[j] & 0x3; |
||
1087 | const GLint rowBr1 = rowB[k] & 0x3; |
||
1088 | const GLint rowCr0 = rowC[j] & 0x3; |
||
1089 | const GLint rowCr1 = rowC[k] & 0x3; |
||
1090 | const GLint rowDr0 = rowD[j] & 0x3; |
||
1091 | const GLint rowDr1 = rowD[k] & 0x3; |
||
1092 | const GLint rowAg0 = (rowA[j] >> 2) & 0x7; |
||
1093 | const GLint rowAg1 = (rowA[k] >> 2) & 0x7; |
||
1094 | const GLint rowBg0 = (rowB[j] >> 2) & 0x7; |
||
1095 | const GLint rowBg1 = (rowB[k] >> 2) & 0x7; |
||
1096 | const GLint rowCg0 = (rowC[j] >> 2) & 0x7; |
||
1097 | const GLint rowCg1 = (rowC[k] >> 2) & 0x7; |
||
1098 | const GLint rowDg0 = (rowD[j] >> 2) & 0x7; |
||
1099 | const GLint rowDg1 = (rowD[k] >> 2) & 0x7; |
||
1100 | const GLint rowAb0 = (rowA[j] >> 5) & 0x7; |
||
1101 | const GLint rowAb1 = (rowA[k] >> 5) & 0x7; |
||
1102 | const GLint rowBb0 = (rowB[j] >> 5) & 0x7; |
||
1103 | const GLint rowBb1 = (rowB[k] >> 5) & 0x7; |
||
1104 | const GLint rowCb0 = (rowC[j] >> 5) & 0x7; |
||
1105 | const GLint rowCb1 = (rowC[k] >> 5) & 0x7; |
||
1106 | const GLint rowDb0 = (rowD[j] >> 5) & 0x7; |
||
1107 | const GLint rowDb1 = (rowD[k] >> 5) & 0x7; |
||
1108 | const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, |
||
1109 | rowCr0, rowCr1, rowDr0, rowDr1); |
||
1110 | const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, |
||
1111 | rowCg0, rowCg1, rowDg0, rowDg1); |
||
1112 | const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, |
||
1113 | rowCb0, rowCb1, rowDb0, rowDb1); |
||
1114 | dst[i] = (b << 5) | (g << 2) | r; |
||
1115 | } |
||
1116 | } |
||
1117 | else { |
||
1118 | _mesa_problem(NULL, "bad format in do_row()"); |
||
1119 | } |
||
1120 | } |
||
1121 | |||
1122 | |||
1123 | /* |
||
1124 | * These functions generate a 1/2-size mipmap image from a source image. |
||
1125 | * Texture borders are handled by copying or averaging the source image's |
||
1126 | * border texels, depending on the scale-down factor. |
||
1127 | */ |
||
1128 | |||
1129 | static void |
||
1130 | make_1d_mipmap(GLenum datatype, GLuint comps, GLint border, |
||
1131 | GLint srcWidth, const GLubyte *srcPtr, |
||
1132 | GLint dstWidth, GLubyte *dstPtr) |
||
1133 | { |
||
1134 | const GLint bpt = bytes_per_pixel(datatype, comps); |
||
1135 | const GLubyte *src; |
||
1136 | GLubyte *dst; |
||
1137 | |||
1138 | /* skip the border pixel, if any */ |
||
1139 | src = srcPtr + border * bpt; |
||
1140 | dst = dstPtr + border * bpt; |
||
1141 | |||
1142 | /* we just duplicate the input row, kind of hack, saves code */ |
||
1143 | do_row(datatype, comps, srcWidth - 2 * border, src, src, |
||
1144 | dstWidth - 2 * border, dst); |
||
1145 | |||
1146 | if (border) { |
||
1147 | /* copy left-most pixel from source */ |
||
1148 | assert(dstPtr); |
||
1149 | assert(srcPtr); |
||
1150 | memcpy(dstPtr, srcPtr, bpt); |
||
1151 | /* copy right-most pixel from source */ |
||
1152 | memcpy(dstPtr + (dstWidth - 1) * bpt, |
||
1153 | srcPtr + (srcWidth - 1) * bpt, |
||
1154 | bpt); |
||
1155 | } |
||
1156 | } |
||
1157 | |||
1158 | |||
1159 | static void |
||
1160 | make_2d_mipmap(GLenum datatype, GLuint comps, GLint border, |
||
1161 | GLint srcWidth, GLint srcHeight, |
||
1162 | const GLubyte *srcPtr, GLint srcRowStride, |
||
1163 | GLint dstWidth, GLint dstHeight, |
||
1164 | GLubyte *dstPtr, GLint dstRowStride) |
||
1165 | { |
||
1166 | const GLint bpt = bytes_per_pixel(datatype, comps); |
||
1167 | const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ |
||
1168 | const GLint dstWidthNB = dstWidth - 2 * border; |
||
1169 | const GLint dstHeightNB = dstHeight - 2 * border; |
||
1170 | const GLint srcRowBytes = bpt * srcRowStride; |
||
1171 | const GLint dstRowBytes = bpt * dstRowStride; |
||
1172 | const GLubyte *srcA, *srcB; |
||
1173 | GLubyte *dst; |
||
1174 | GLint row, srcRowStep; |
||
1175 | |||
1176 | /* Compute src and dst pointers, skipping any border */ |
||
1177 | srcA = srcPtr + border * ((srcWidth + 1) * bpt); |
||
1178 | if (srcHeight > 1 && srcHeight > dstHeight) { |
||
1179 | /* sample from two source rows */ |
||
1180 | srcB = srcA + srcRowBytes; |
||
1181 | srcRowStep = 2; |
||
1182 | } |
||
1183 | else { |
||
1184 | /* sample from one source row */ |
||
1185 | srcB = srcA; |
||
1186 | srcRowStep = 1; |
||
1187 | } |
||
1188 | |||
1189 | dst = dstPtr + border * ((dstWidth + 1) * bpt); |
||
1190 | |||
1191 | for (row = 0; row < dstHeightNB; row++) { |
||
1192 | do_row(datatype, comps, srcWidthNB, srcA, srcB, |
||
1193 | dstWidthNB, dst); |
||
1194 | srcA += srcRowStep * srcRowBytes; |
||
1195 | srcB += srcRowStep * srcRowBytes; |
||
1196 | dst += dstRowBytes; |
||
1197 | } |
||
1198 | |||
1199 | /* This is ugly but probably won't be used much */ |
||
1200 | if (border > 0) { |
||
1201 | /* fill in dest border */ |
||
1202 | /* lower-left border pixel */ |
||
1203 | assert(dstPtr); |
||
1204 | assert(srcPtr); |
||
1205 | memcpy(dstPtr, srcPtr, bpt); |
||
1206 | /* lower-right border pixel */ |
||
1207 | memcpy(dstPtr + (dstWidth - 1) * bpt, |
||
1208 | srcPtr + (srcWidth - 1) * bpt, bpt); |
||
1209 | /* upper-left border pixel */ |
||
1210 | memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt, |
||
1211 | srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); |
||
1212 | /* upper-right border pixel */ |
||
1213 | memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt, |
||
1214 | srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); |
||
1215 | /* lower border */ |
||
1216 | do_row(datatype, comps, srcWidthNB, |
||
1217 | srcPtr + bpt, |
||
1218 | srcPtr + bpt, |
||
1219 | dstWidthNB, dstPtr + bpt); |
||
1220 | /* upper border */ |
||
1221 | do_row(datatype, comps, srcWidthNB, |
||
1222 | srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, |
||
1223 | srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, |
||
1224 | dstWidthNB, |
||
1225 | dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); |
||
1226 | /* left and right borders */ |
||
1227 | if (srcHeight == dstHeight) { |
||
1228 | /* copy border pixel from src to dst */ |
||
1229 | for (row = 1; row < srcHeight; row++) { |
||
1230 | memcpy(dstPtr + dstWidth * row * bpt, |
||
1231 | srcPtr + srcWidth * row * bpt, bpt); |
||
1232 | memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, |
||
1233 | srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); |
||
1234 | } |
||
1235 | } |
||
1236 | else { |
||
1237 | /* average two src pixels each dest pixel */ |
||
1238 | for (row = 0; row < dstHeightNB; row += 2) { |
||
1239 | do_row(datatype, comps, 1, |
||
1240 | srcPtr + (srcWidth * (row * 2 + 1)) * bpt, |
||
1241 | srcPtr + (srcWidth * (row * 2 + 2)) * bpt, |
||
1242 | 1, dstPtr + (dstWidth * row + 1) * bpt); |
||
1243 | do_row(datatype, comps, 1, |
||
1244 | srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, |
||
1245 | srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, |
||
1246 | 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); |
||
1247 | } |
||
1248 | } |
||
1249 | } |
||
1250 | } |
||
1251 | |||
1252 | |||
1253 | static void |
||
1254 | make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, |
||
1255 | GLint srcWidth, GLint srcHeight, GLint srcDepth, |
||
1256 | const GLubyte *srcPtr, GLint srcRowStride, |
||
1257 | GLint dstWidth, GLint dstHeight, GLint dstDepth, |
||
1258 | GLubyte *dstPtr, GLint dstRowStride) |
||
1259 | { |
||
1260 | const GLint bpt = bytes_per_pixel(datatype, comps); |
||
1261 | const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ |
||
1262 | const GLint srcDepthNB = srcDepth - 2 * border; |
||
1263 | const GLint dstWidthNB = dstWidth - 2 * border; |
||
1264 | const GLint dstHeightNB = dstHeight - 2 * border; |
||
1265 | const GLint dstDepthNB = dstDepth - 2 * border; |
||
1266 | GLint img, row; |
||
1267 | GLint bytesPerSrcImage, bytesPerDstImage; |
||
1268 | GLint bytesPerSrcRow, bytesPerDstRow; |
||
1269 | GLint srcImageOffset, srcRowOffset; |
||
1270 | |||
1271 | (void) srcDepthNB; /* silence warnings */ |
||
1272 | |||
1273 | |||
1274 | bytesPerSrcImage = srcWidth * srcHeight * bpt; |
||
1275 | bytesPerDstImage = dstWidth * dstHeight * bpt; |
||
1276 | |||
1277 | bytesPerSrcRow = srcWidth * bpt; |
||
1278 | bytesPerDstRow = dstWidth * bpt; |
||
1279 | |||
1280 | /* Offset between adjacent src images to be averaged together */ |
||
1281 | srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage; |
||
1282 | |||
1283 | /* Offset between adjacent src rows to be averaged together */ |
||
1284 | srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; |
||
1285 | |||
1286 | /* |
||
1287 | * Need to average together up to 8 src pixels for each dest pixel. |
||
1288 | * Break that down into 3 operations: |
||
1289 | * 1. take two rows from source image and average them together. |
||
1290 | * 2. take two rows from next source image and average them together. |
||
1291 | * 3. take the two averaged rows and average them for the final dst row. |
||
1292 | */ |
||
1293 | |||
1294 | /* |
||
1295 | printf("mip3d %d x %d x %d -> %d x %d x %d\n", |
||
1296 | srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); |
||
1297 | */ |
||
1298 | |||
1299 | for (img = 0; img < dstDepthNB; img++) { |
||
1300 | /* first source image pointer, skipping border */ |
||
1301 | const GLubyte *imgSrcA = srcPtr |
||
1302 | + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border |
||
1303 | + img * (bytesPerSrcImage + srcImageOffset); |
||
1304 | /* second source image pointer, skipping border */ |
||
1305 | const GLubyte *imgSrcB = imgSrcA + srcImageOffset; |
||
1306 | /* address of the dest image, skipping border */ |
||
1307 | GLubyte *imgDst = dstPtr |
||
1308 | + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border |
||
1309 | + img * bytesPerDstImage; |
||
1310 | |||
1311 | /* setup the four source row pointers and the dest row pointer */ |
||
1312 | const GLubyte *srcImgARowA = imgSrcA; |
||
1313 | const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; |
||
1314 | const GLubyte *srcImgBRowA = imgSrcB; |
||
1315 | const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; |
||
1316 | GLubyte *dstImgRow = imgDst; |
||
1317 | |||
1318 | for (row = 0; row < dstHeightNB; row++) { |
||
1319 | do_row_3D(datatype, comps, srcWidthNB, |
||
1320 | srcImgARowA, srcImgARowB, |
||
1321 | srcImgBRowA, srcImgBRowB, |
||
1322 | dstWidthNB, dstImgRow); |
||
1323 | |||
1324 | /* advance to next rows */ |
||
1325 | srcImgARowA += bytesPerSrcRow + srcRowOffset; |
||
1326 | srcImgARowB += bytesPerSrcRow + srcRowOffset; |
||
1327 | srcImgBRowA += bytesPerSrcRow + srcRowOffset; |
||
1328 | srcImgBRowB += bytesPerSrcRow + srcRowOffset; |
||
1329 | dstImgRow += bytesPerDstRow; |
||
1330 | } |
||
1331 | } |
||
1332 | |||
1333 | |||
1334 | /* Luckily we can leverage the make_2d_mipmap() function here! */ |
||
1335 | if (border > 0) { |
||
1336 | /* do front border image */ |
||
1337 | make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride, |
||
1338 | dstWidth, dstHeight, dstPtr, dstRowStride); |
||
1339 | /* do back border image */ |
||
1340 | make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, |
||
1341 | srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride, |
||
1342 | dstWidth, dstHeight, |
||
1343 | dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride); |
||
1344 | /* do four remaining border edges that span the image slices */ |
||
1345 | if (srcDepth == dstDepth) { |
||
1346 | /* just copy border pixels from src to dst */ |
||
1347 | for (img = 0; img < dstDepthNB; img++) { |
||
1348 | const GLubyte *src; |
||
1349 | GLubyte *dst; |
||
1350 | |||
1351 | /* do border along [img][row=0][col=0] */ |
||
1352 | src = srcPtr + (img + 1) * bytesPerSrcImage; |
||
1353 | dst = dstPtr + (img + 1) * bytesPerDstImage; |
||
1354 | memcpy(dst, src, bpt); |
||
1355 | |||
1356 | /* do border along [img][row=dstHeight-1][col=0] */ |
||
1357 | src = srcPtr + (img * 2 + 1) * bytesPerSrcImage |
||
1358 | + (srcHeight - 1) * bytesPerSrcRow; |
||
1359 | dst = dstPtr + (img + 1) * bytesPerDstImage |
||
1360 | + (dstHeight - 1) * bytesPerDstRow; |
||
1361 | memcpy(dst, src, bpt); |
||
1362 | |||
1363 | /* do border along [img][row=0][col=dstWidth-1] */ |
||
1364 | src = srcPtr + (img * 2 + 1) * bytesPerSrcImage |
||
1365 | + (srcWidth - 1) * bpt; |
||
1366 | dst = dstPtr + (img + 1) * bytesPerDstImage |
||
1367 | + (dstWidth - 1) * bpt; |
||
1368 | memcpy(dst, src, bpt); |
||
1369 | |||
1370 | /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ |
||
1371 | src = srcPtr + (img * 2 + 1) * bytesPerSrcImage |
||
1372 | + (bytesPerSrcImage - bpt); |
||
1373 | dst = dstPtr + (img + 1) * bytesPerDstImage |
||
1374 | + (bytesPerDstImage - bpt); |
||
1375 | memcpy(dst, src, bpt); |
||
1376 | } |
||
1377 | } |
||
1378 | else { |
||
1379 | /* average border pixels from adjacent src image pairs */ |
||
1380 | ASSERT(srcDepthNB == 2 * dstDepthNB); |
||
1381 | for (img = 0; img < dstDepthNB; img++) { |
||
1382 | const GLubyte *src; |
||
1383 | GLubyte *dst; |
||
1384 | |||
1385 | /* do border along [img][row=0][col=0] */ |
||
1386 | src = srcPtr + (img * 2 + 1) * bytesPerSrcImage; |
||
1387 | dst = dstPtr + (img + 1) * bytesPerDstImage; |
||
1388 | do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); |
||
1389 | |||
1390 | /* do border along [img][row=dstHeight-1][col=0] */ |
||
1391 | src = srcPtr + (img * 2 + 1) * bytesPerSrcImage |
||
1392 | + (srcHeight - 1) * bytesPerSrcRow; |
||
1393 | dst = dstPtr + (img + 1) * bytesPerDstImage |
||
1394 | + (dstHeight - 1) * bytesPerDstRow; |
||
1395 | do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); |
||
1396 | |||
1397 | /* do border along [img][row=0][col=dstWidth-1] */ |
||
1398 | src = srcPtr + (img * 2 + 1) * bytesPerSrcImage |
||
1399 | + (srcWidth - 1) * bpt; |
||
1400 | dst = dstPtr + (img + 1) * bytesPerDstImage |
||
1401 | + (dstWidth - 1) * bpt; |
||
1402 | do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); |
||
1403 | |||
1404 | /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ |
||
1405 | src = srcPtr + (img * 2 + 1) * bytesPerSrcImage |
||
1406 | + (bytesPerSrcImage - bpt); |
||
1407 | dst = dstPtr + (img + 1) * bytesPerDstImage |
||
1408 | + (bytesPerDstImage - bpt); |
||
1409 | do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); |
||
1410 | } |
||
1411 | } |
||
1412 | } |
||
1413 | } |
||
1414 | |||
1415 | |||
1416 | static void |
||
1417 | make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, |
||
1418 | GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride, |
||
1419 | GLint dstWidth, GLint dstHeight, |
||
1420 | GLubyte *dstPtr, GLuint dstRowStride ) |
||
1421 | { |
||
1422 | const GLint bpt = bytes_per_pixel(datatype, comps); |
||
1423 | const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ |
||
1424 | const GLint dstWidthNB = dstWidth - 2 * border; |
||
1425 | const GLint dstHeightNB = dstHeight - 2 * border; |
||
1426 | const GLint srcRowBytes = bpt * srcRowStride; |
||
1427 | const GLint dstRowBytes = bpt * dstRowStride; |
||
1428 | const GLubyte *src; |
||
1429 | GLubyte *dst; |
||
1430 | GLint row; |
||
1431 | |||
1432 | /* Compute src and dst pointers, skipping any border */ |
||
1433 | src = srcPtr + border * ((srcWidth + 1) * bpt); |
||
1434 | dst = dstPtr + border * ((dstWidth + 1) * bpt); |
||
1435 | |||
1436 | for (row = 0; row < dstHeightNB; row++) { |
||
1437 | do_row(datatype, comps, srcWidthNB, src, src, |
||
1438 | dstWidthNB, dst); |
||
1439 | src += srcRowBytes; |
||
1440 | dst += dstRowBytes; |
||
1441 | } |
||
1442 | |||
1443 | if (border) { |
||
1444 | /* copy left-most pixel from source */ |
||
1445 | assert(dstPtr); |
||
1446 | assert(srcPtr); |
||
1447 | memcpy(dstPtr, srcPtr, bpt); |
||
1448 | /* copy right-most pixel from source */ |
||
1449 | memcpy(dstPtr + (dstWidth - 1) * bpt, |
||
1450 | srcPtr + (srcWidth - 1) * bpt, |
||
1451 | bpt); |
||
1452 | } |
||
1453 | } |
||
1454 | |||
1455 | |||
1456 | /** |
||
1457 | * \bug |
||
1458 | * There is quite a bit of refactoring that could be done with this function |
||
1459 | * and \c make_2d_mipmap. |
||
1460 | */ |
||
1461 | static void |
||
1462 | make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, |
||
1463 | GLint srcWidth, GLint srcHeight, |
||
1464 | const GLubyte *srcPtr, GLint srcRowStride, |
||
1465 | GLint dstWidth, GLint dstHeight, GLint dstDepth, |
||
1466 | GLubyte *dstPtr, GLint dstRowStride) |
||
1467 | { |
||
1468 | const GLint bpt = bytes_per_pixel(datatype, comps); |
||
1469 | const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ |
||
1470 | const GLint dstWidthNB = dstWidth - 2 * border; |
||
1471 | const GLint dstHeightNB = dstHeight - 2 * border; |
||
1472 | const GLint dstDepthNB = dstDepth - 2 * border; |
||
1473 | const GLint srcRowBytes = bpt * srcRowStride; |
||
1474 | const GLint dstRowBytes = bpt * dstRowStride; |
||
1475 | const GLubyte *srcA, *srcB; |
||
1476 | GLubyte *dst; |
||
1477 | GLint layer; |
||
1478 | GLint row; |
||
1479 | |||
1480 | /* Compute src and dst pointers, skipping any border */ |
||
1481 | srcA = srcPtr + border * ((srcWidth + 1) * bpt); |
||
1482 | if (srcHeight > 1) |
||
1483 | srcB = srcA + srcRowBytes; |
||
1484 | else |
||
1485 | srcB = srcA; |
||
1486 | dst = dstPtr + border * ((dstWidth + 1) * bpt); |
||
1487 | |||
1488 | for (layer = 0; layer < dstDepthNB; layer++) { |
||
1489 | for (row = 0; row < dstHeightNB; row++) { |
||
1490 | do_row(datatype, comps, srcWidthNB, srcA, srcB, |
||
1491 | dstWidthNB, dst); |
||
1492 | srcA += 2 * srcRowBytes; |
||
1493 | srcB += 2 * srcRowBytes; |
||
1494 | dst += dstRowBytes; |
||
1495 | } |
||
1496 | |||
1497 | /* This is ugly but probably won't be used much */ |
||
1498 | if (border > 0) { |
||
1499 | /* fill in dest border */ |
||
1500 | /* lower-left border pixel */ |
||
1501 | assert(dstPtr); |
||
1502 | assert(srcPtr); |
||
1503 | memcpy(dstPtr, srcPtr, bpt); |
||
1504 | /* lower-right border pixel */ |
||
1505 | memcpy(dstPtr + (dstWidth - 1) * bpt, |
||
1506 | srcPtr + (srcWidth - 1) * bpt, bpt); |
||
1507 | /* upper-left border pixel */ |
||
1508 | memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt, |
||
1509 | srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); |
||
1510 | /* upper-right border pixel */ |
||
1511 | memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt, |
||
1512 | srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); |
||
1513 | /* lower border */ |
||
1514 | do_row(datatype, comps, srcWidthNB, |
||
1515 | srcPtr + bpt, |
||
1516 | srcPtr + bpt, |
||
1517 | dstWidthNB, dstPtr + bpt); |
||
1518 | /* upper border */ |
||
1519 | do_row(datatype, comps, srcWidthNB, |
||
1520 | srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, |
||
1521 | srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, |
||
1522 | dstWidthNB, |
||
1523 | dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); |
||
1524 | /* left and right borders */ |
||
1525 | if (srcHeight == dstHeight) { |
||
1526 | /* copy border pixel from src to dst */ |
||
1527 | for (row = 1; row < srcHeight; row++) { |
||
1528 | memcpy(dstPtr + dstWidth * row * bpt, |
||
1529 | srcPtr + srcWidth * row * bpt, bpt); |
||
1530 | memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, |
||
1531 | srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); |
||
1532 | } |
||
1533 | } |
||
1534 | else { |
||
1535 | /* average two src pixels each dest pixel */ |
||
1536 | for (row = 0; row < dstHeightNB; row += 2) { |
||
1537 | do_row(datatype, comps, 1, |
||
1538 | srcPtr + (srcWidth * (row * 2 + 1)) * bpt, |
||
1539 | srcPtr + (srcWidth * (row * 2 + 2)) * bpt, |
||
1540 | 1, dstPtr + (dstWidth * row + 1) * bpt); |
||
1541 | do_row(datatype, comps, 1, |
||
1542 | srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, |
||
1543 | srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, |
||
1544 | 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); |
||
1545 | } |
||
1546 | } |
||
1547 | } |
||
1548 | } |
||
1549 | } |
||
1550 | |||
1551 | |||
1552 | /** |
||
1553 | * Down-sample a texture image to produce the next lower mipmap level. |
||
1554 | * \param comps components per texel (1, 2, 3 or 4) |
||
1555 | * \param srcRowStride stride between source rows, in texels |
||
1556 | * \param dstRowStride stride between destination rows, in texels |
||
1557 | */ |
||
1558 | void |
||
1559 | _mesa_generate_mipmap_level(GLenum target, |
||
1560 | GLenum datatype, GLuint comps, |
||
1561 | GLint border, |
||
1562 | GLint srcWidth, GLint srcHeight, GLint srcDepth, |
||
1563 | const GLubyte *srcData, |
||
1564 | GLint srcRowStride, |
||
1565 | GLint dstWidth, GLint dstHeight, GLint dstDepth, |
||
1566 | GLubyte *dstData, |
||
1567 | GLint dstRowStride) |
||
1568 | { |
||
1569 | /* |
||
1570 | * We use simple 2x2 averaging to compute the next mipmap level. |
||
1571 | */ |
||
1572 | switch (target) { |
||
1573 | case GL_TEXTURE_1D: |
||
1574 | make_1d_mipmap(datatype, comps, border, |
||
1575 | srcWidth, srcData, |
||
1576 | dstWidth, dstData); |
||
1577 | break; |
||
1578 | case GL_TEXTURE_2D: |
||
1579 | case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: |
||
1580 | case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: |
||
1581 | case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: |
||
1582 | case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: |
||
1583 | case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: |
||
1584 | case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: |
||
1585 | make_2d_mipmap(datatype, comps, border, |
||
1586 | srcWidth, srcHeight, srcData, srcRowStride, |
||
1587 | dstWidth, dstHeight, dstData, dstRowStride); |
||
1588 | break; |
||
1589 | case GL_TEXTURE_3D: |
||
1590 | make_3d_mipmap(datatype, comps, border, |
||
1591 | srcWidth, srcHeight, srcDepth, |
||
1592 | srcData, srcRowStride, |
||
1593 | dstWidth, dstHeight, dstDepth, |
||
1594 | dstData, dstRowStride); |
||
1595 | break; |
||
1596 | case GL_TEXTURE_1D_ARRAY_EXT: |
||
1597 | make_1d_stack_mipmap(datatype, comps, border, |
||
1598 | srcWidth, srcData, srcRowStride, |
||
1599 | dstWidth, dstHeight, |
||
1600 | dstData, dstRowStride); |
||
1601 | break; |
||
1602 | case GL_TEXTURE_2D_ARRAY_EXT: |
||
1603 | make_2d_stack_mipmap(datatype, comps, border, |
||
1604 | srcWidth, srcHeight, |
||
1605 | srcData, srcRowStride, |
||
1606 | dstWidth, dstHeight, |
||
1607 | dstDepth, dstData, dstRowStride); |
||
1608 | break; |
||
1609 | case GL_TEXTURE_RECTANGLE_NV: |
||
1610 | /* no mipmaps, do nothing */ |
||
1611 | break; |
||
1612 | default: |
||
1613 | _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps"); |
||
1614 | return; |
||
1615 | } |
||
1616 | } |
||
1617 | |||
1618 | |||
1619 | /** |
||
1620 | * compute next (level+1) image size |
||
1621 | * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size) |
||
1622 | */ |
||
1623 | static GLboolean |
||
1624 | next_mipmap_level_size(GLenum target, GLint border, |
||
1625 | GLint srcWidth, GLint srcHeight, GLint srcDepth, |
||
1626 | GLint *dstWidth, GLint *dstHeight, GLint *dstDepth) |
||
1627 | { |
||
1628 | if (srcWidth - 2 * border > 1) { |
||
1629 | *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; |
||
1630 | } |
||
1631 | else { |
||
1632 | *dstWidth = srcWidth; /* can't go smaller */ |
||
1633 | } |
||
1634 | |||
1635 | if ((srcHeight - 2 * border > 1) && |
||
1636 | (target != GL_TEXTURE_1D_ARRAY_EXT)) { |
||
1637 | *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; |
||
1638 | } |
||
1639 | else { |
||
1640 | *dstHeight = srcHeight; /* can't go smaller */ |
||
1641 | } |
||
1642 | |||
1643 | if ((srcDepth - 2 * border > 1) && |
||
1644 | (target != GL_TEXTURE_2D_ARRAY_EXT)) { |
||
1645 | *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; |
||
1646 | } |
||
1647 | else { |
||
1648 | *dstDepth = srcDepth; /* can't go smaller */ |
||
1649 | } |
||
1650 | |||
1651 | if (*dstWidth == srcWidth && |
||
1652 | *dstHeight == srcHeight && |
||
1653 | *dstDepth == srcDepth) { |
||
1654 | return GL_FALSE; |
||
1655 | } |
||
1656 | else { |
||
1657 | return GL_TRUE; |
||
1658 | } |
||
1659 | } |
||
1660 | |||
1661 | |||
1662 | |||
1663 | |||
1664 | /** |
||
1665 | * Automatic mipmap generation. |
||
1666 | * This is the fallback/default function for ctx->Driver.GenerateMipmap(). |
||
1667 | * Generate a complete set of mipmaps from texObj's BaseLevel image. |
||
1668 | * Stop at texObj's MaxLevel or when we get to the 1x1 texture. |
||
1669 | * For cube maps, target will be one of |
||
1670 | * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP. |
||
1671 | */ |
||
1672 | void |
||
1673 | _mesa_generate_mipmap(struct gl_context *ctx, GLenum target, |
||
1674 | struct gl_texture_object *texObj) |
||
1675 | { |
||
1676 | const struct gl_texture_image *srcImage; |
||
1677 | gl_format convertFormat; |
||
1678 | const GLubyte *srcData = NULL; |
||
1679 | GLubyte *dstData = NULL; |
||
1680 | GLint level, maxLevels; |
||
1681 | GLenum datatype; |
||
1682 | GLuint comps; |
||
1683 | |||
1684 | ASSERT(texObj); |
||
1685 | srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); |
||
1686 | ASSERT(srcImage); |
||
1687 | |||
1688 | maxLevels = _mesa_max_texture_levels(ctx, texObj->Target); |
||
1689 | ASSERT(maxLevels > 0); /* bad target */ |
||
1690 | |||
1691 | /* Find convertFormat - the format that do_row() will process */ |
||
1692 | |||
1693 | if (_mesa_is_format_compressed(srcImage->TexFormat)) { |
||
1694 | /* setup for compressed textures - need to allocate temporary |
||
1695 | * image buffers to hold uncompressed images. |
||
1696 | */ |
||
1697 | GLuint row; |
||
1698 | GLint components, size; |
||
1699 | GLchan *dst; |
||
1700 | |||
1701 | assert(texObj->Target == GL_TEXTURE_2D || |
||
1702 | texObj->Target == GL_TEXTURE_CUBE_MAP_ARB); |
||
1703 | |||
1704 | if (srcImage->_BaseFormat == GL_RGB) { |
||
1705 | convertFormat = MESA_FORMAT_RGB888; |
||
1706 | components = 3; |
||
1707 | } |
||
1708 | else if (srcImage->_BaseFormat == GL_RGBA) { |
||
1709 | convertFormat = MESA_FORMAT_RGBA8888; |
||
1710 | components = 4; |
||
1711 | } |
||
1712 | else { |
||
1713 | _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps"); |
||
1714 | return; |
||
1715 | } |
||
1716 | |||
1717 | /* allocate storage for uncompressed GL_RGB or GL_RGBA images */ |
||
1718 | size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE) |
||
1719 | * srcImage->Width * srcImage->Height * srcImage->Depth + 20; |
||
1720 | /* 20 extra bytes, just be safe when calling last FetchTexel */ |
||
1721 | srcData = (GLubyte *) malloc(size); |
||
1722 | if (!srcData) { |
||
1723 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); |
||
1724 | return; |
||
1725 | } |
||
1726 | dstData = (GLubyte *) malloc(size / 2); /* 1/4 would probably be OK */ |
||
1727 | if (!dstData) { |
||
1728 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); |
||
1729 | free((void *) srcData); |
||
1730 | return; |
||
1731 | } |
||
1732 | |||
1733 | /* decompress base image here */ |
||
1734 | dst = (GLchan *) srcData; |
||
1735 | for (row = 0; row < srcImage->Height; row++) { |
||
1736 | GLuint col; |
||
1737 | for (col = 0; col < srcImage->Width; col++) { |
||
1738 | srcImage->FetchTexelc(srcImage, col, row, 0, dst); |
||
1739 | dst += components; |
||
1740 | } |
||
1741 | } |
||
1742 | } |
||
1743 | else { |
||
1744 | /* uncompressed */ |
||
1745 | convertFormat = srcImage->TexFormat; |
||
1746 | } |
||
1747 | |||
1748 | _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps); |
||
1749 | |||
1750 | for (level = texObj->BaseLevel; level < texObj->MaxLevel |
||
1751 | && level < maxLevels - 1; level++) { |
||
1752 | /* generate image[level+1] from image[level] */ |
||
1753 | const struct gl_texture_image *srcImage; |
||
1754 | struct gl_texture_image *dstImage; |
||
1755 | GLint srcWidth, srcHeight, srcDepth; |
||
1756 | GLint dstWidth, dstHeight, dstDepth; |
||
1757 | GLint border; |
||
1758 | GLboolean nextLevel; |
||
1759 | |||
1760 | /* get src image parameters */ |
||
1761 | srcImage = _mesa_select_tex_image(ctx, texObj, target, level); |
||
1762 | ASSERT(srcImage); |
||
1763 | srcWidth = srcImage->Width; |
||
1764 | srcHeight = srcImage->Height; |
||
1765 | srcDepth = srcImage->Depth; |
||
1766 | border = srcImage->Border; |
||
1767 | |||
1768 | nextLevel = next_mipmap_level_size(target, border, |
||
1769 | srcWidth, srcHeight, srcDepth, |
||
1770 | &dstWidth, &dstHeight, &dstDepth); |
||
1771 | if (!nextLevel) { |
||
1772 | /* all done */ |
||
1773 | if (_mesa_is_format_compressed(srcImage->TexFormat)) { |
||
1774 | free((void *) srcData); |
||
1775 | free(dstData); |
||
1776 | } |
||
1777 | return; |
||
1778 | } |
||
1779 | |||
1780 | /* get dest gl_texture_image */ |
||
1781 | dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); |
||
1782 | if (!dstImage) { |
||
1783 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); |
||
1784 | return; |
||
1785 | } |
||
1786 | |||
1787 | /* Free old image data */ |
||
1788 | if (dstImage->Data) |
||
1789 | ctx->Driver.FreeTexImageData(ctx, dstImage); |
||
1790 | |||
1791 | /* initialize new image */ |
||
1792 | _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, |
||
1793 | dstDepth, border, srcImage->InternalFormat, |
||
1794 | srcImage->TexFormat); |
||
1795 | dstImage->DriverData = NULL; |
||
1796 | dstImage->FetchTexelc = srcImage->FetchTexelc; |
||
1797 | dstImage->FetchTexelf = srcImage->FetchTexelf; |
||
1798 | |||
1799 | /* Alloc new teximage data buffer */ |
||
1800 | { |
||
1801 | GLuint size = _mesa_format_image_size(dstImage->TexFormat, |
||
1802 | dstWidth, dstHeight, dstDepth); |
||
1803 | dstImage->Data = _mesa_alloc_texmemory(size); |
||
1804 | if (!dstImage->Data) { |
||
1805 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); |
||
1806 | return; |
||
1807 | } |
||
1808 | } |
||
1809 | |||
1810 | /* Setup src and dest data pointers */ |
||
1811 | if (_mesa_is_format_compressed(dstImage->TexFormat)) { |
||
1812 | /* srcData and dstData are already set */ |
||
1813 | ASSERT(srcData); |
||
1814 | ASSERT(dstData); |
||
1815 | } |
||
1816 | else { |
||
1817 | srcData = (const GLubyte *) srcImage->Data; |
||
1818 | dstData = (GLubyte *) dstImage->Data; |
||
1819 | } |
||
1820 | |||
1821 | ASSERT(dstImage->TexFormat); |
||
1822 | ASSERT(dstImage->FetchTexelc); |
||
1823 | ASSERT(dstImage->FetchTexelf); |
||
1824 | |||
1825 | _mesa_generate_mipmap_level(target, datatype, comps, border, |
||
1826 | srcWidth, srcHeight, srcDepth, |
||
1827 | srcData, srcImage->RowStride, |
||
1828 | dstWidth, dstHeight, dstDepth, |
||
1829 | dstData, dstImage->RowStride); |
||
1830 | |||
1831 | |||
1832 | if (_mesa_is_format_compressed(dstImage->TexFormat)) { |
||
1833 | GLubyte *temp; |
||
1834 | /* compress image from dstData into dstImage->Data */ |
||
1835 | const GLenum srcFormat = _mesa_get_format_base_format(convertFormat); |
||
1836 | GLint dstRowStride |
||
1837 | = _mesa_format_row_stride(dstImage->TexFormat, dstWidth); |
||
1838 | ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA); |
||
1839 | |||
1840 | _mesa_texstore(ctx, 2, dstImage->_BaseFormat, |
||
1841 | dstImage->TexFormat, |
||
1842 | dstImage->Data, |
||
1843 | 0, 0, 0, /* dstX/Y/Zoffset */ |
||
1844 | dstRowStride, 0, /* strides */ |
||
1845 | dstWidth, dstHeight, 1, /* size */ |
||
1846 | srcFormat, CHAN_TYPE, |
||
1847 | dstData, /* src data, actually */ |
||
1848 | &ctx->DefaultPacking); |
||
1849 | |||
1850 | /* swap src and dest pointers */ |
||
1851 | temp = (GLubyte *) srcData; |
||
1852 | srcData = dstData; |
||
1853 | dstData = temp; |
||
1854 | } |
||
1855 | |||
1856 | } /* loop over mipmap levels */ |
||
1857 | } |
||
1858 | |||
1859 | |||
1860 | /** |
||
1861 | * Helper function for drivers which need to rescale texture images to |
||
1862 | * certain aspect ratios. |
||
1863 | * Nearest filtering only (for broken hardware that can't support |
||
1864 | * all aspect ratios). This can be made a lot faster, but I don't |
||
1865 | * really care enough... |
||
1866 | */ |
||
1867 | void |
||
1868 | _mesa_rescale_teximage2d(GLuint bytesPerPixel, |
||
1869 | GLuint srcStrideInPixels, |
||
1870 | GLuint dstRowStride, |
||
1871 | GLint srcWidth, GLint srcHeight, |
||
1872 | GLint dstWidth, GLint dstHeight, |
||
1873 | const GLvoid *srcImage, GLvoid *dstImage) |
||
1874 | { |
||
1875 | GLint row, col; |
||
1876 | |||
1877 | #define INNER_LOOP( TYPE, HOP, WOP ) \ |
||
1878 | for ( row = 0 ; row < dstHeight ; row++ ) { \ |
||
1879 | GLint srcRow = row HOP hScale; \ |
||
1880 | for ( col = 0 ; col < dstWidth ; col++ ) { \ |
||
1881 | GLint srcCol = col WOP wScale; \ |
||
1882 | dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ |
||
1883 | } \ |
||
1884 | dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ |
||
1885 | } \ |
||
1886 | |||
1887 | #define RESCALE_IMAGE( TYPE ) \ |
||
1888 | do { \ |
||
1889 | const TYPE *src = (const TYPE *)srcImage; \ |
||
1890 | TYPE *dst = (TYPE *)dstImage; \ |
||
1891 | \ |
||
1892 | if ( srcHeight < dstHeight ) { \ |
||
1893 | const GLint hScale = dstHeight / srcHeight; \ |
||
1894 | if ( srcWidth < dstWidth ) { \ |
||
1895 | const GLint wScale = dstWidth / srcWidth; \ |
||
1896 | INNER_LOOP( TYPE, /, / ); \ |
||
1897 | } \ |
||
1898 | else { \ |
||
1899 | const GLint wScale = srcWidth / dstWidth; \ |
||
1900 | INNER_LOOP( TYPE, /, * ); \ |
||
1901 | } \ |
||
1902 | } \ |
||
1903 | else { \ |
||
1904 | const GLint hScale = srcHeight / dstHeight; \ |
||
1905 | if ( srcWidth < dstWidth ) { \ |
||
1906 | const GLint wScale = dstWidth / srcWidth; \ |
||
1907 | INNER_LOOP( TYPE, *, / ); \ |
||
1908 | } \ |
||
1909 | else { \ |
||
1910 | const GLint wScale = srcWidth / dstWidth; \ |
||
1911 | INNER_LOOP( TYPE, *, * ); \ |
||
1912 | } \ |
||
1913 | } \ |
||
1914 | } while (0) |
||
1915 | |||
1916 | switch ( bytesPerPixel ) { |
||
1917 | case 4: |
||
1918 | RESCALE_IMAGE( GLuint ); |
||
1919 | break; |
||
1920 | |||
1921 | case 2: |
||
1922 | RESCALE_IMAGE( GLushort ); |
||
1923 | break; |
||
1924 | |||
1925 | case 1: |
||
1926 | RESCALE_IMAGE( GLubyte ); |
||
1927 | break; |
||
1928 | default: |
||
1929 | _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d"); |
||
1930 | } |
||
1931 | } |
||
1932 | |||
1933 | |||
1934 | /** |
||
1935 | * Upscale an image by replication, not (typical) stretching. |
||
1936 | * We use this when the image width or height is less than a |
||
1937 | * certain size (4, 8) and we need to upscale an image. |
||
1938 | */ |
||
1939 | void |
||
1940 | _mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight, |
||
1941 | GLsizei outWidth, GLsizei outHeight, |
||
1942 | GLint comps, const GLchan *src, GLint srcRowStride, |
||
1943 | GLchan *dest ) |
||
1944 | { |
||
1945 | GLint i, j, k; |
||
1946 | |||
1947 | ASSERT(outWidth >= inWidth); |
||
1948 | ASSERT(outHeight >= inHeight); |
||
1949 | #if 0 |
||
1950 | ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); |
||
1951 | ASSERT((outWidth & 3) == 0); |
||
1952 | ASSERT((outHeight & 3) == 0); |
||
1953 | #endif |
||
1954 | |||
1955 | for (i = 0; i < outHeight; i++) { |
||
1956 | const GLint ii = i % inHeight; |
||
1957 | for (j = 0; j < outWidth; j++) { |
||
1958 | const GLint jj = j % inWidth; |
||
1959 | for (k = 0; k < comps; k++) { |
||
1960 | dest[(i * outWidth + j) * comps + k] |
||
1961 | = src[ii * srcRowStride + jj * comps + k]; |
||
1962 | } |
||
1963 | } |
||
1964 | } |
||
1965 | }>>>>>>>>>>>>>>>>>>>>>>>>><>><>>><>><>><>>><>><>><>>><>><>><>>><>><>>>>>>>>>>>>>>>>>>>>>>>>>>>=>><>><>>><>><>><>>><>><>><>>><>><>><>>><>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=> |
||
1966 |