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