gallium: setup an identity viewport
[mesa.git] / src / gallium / auxiliary / util / u_gen_mipmap.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * 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
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * Mipmap generation utility
31 *
32 * @author Brian Paul
33 */
34
35
36 #include "pipe/p_context.h"
37 #include "pipe/p_debug.h"
38 #include "pipe/p_defines.h"
39 #include "pipe/p_inlines.h"
40 #include "pipe/p_util.h"
41 #include "pipe/p_winsys.h"
42 #include "pipe/p_shader_tokens.h"
43
44 #include "util/u_draw_quad.h"
45 #include "util/u_gen_mipmap.h"
46 #include "util/u_simple_shaders.h"
47
48 #include "tgsi/util/tgsi_build.h"
49 #include "tgsi/util/tgsi_dump.h"
50 #include "tgsi/util/tgsi_parse.h"
51
52 #include "cso_cache/cso_context.h"
53
54
55 struct gen_mipmap_state
56 {
57 struct pipe_context *pipe;
58 struct cso_context *cso;
59
60 struct pipe_blend_state blend;
61 struct pipe_depth_stencil_alpha_state depthstencil;
62 struct pipe_rasterizer_state rasterizer;
63 struct pipe_sampler_state sampler;
64 struct pipe_viewport_state viewport;
65
66 struct pipe_shader_state vert_shader;
67 struct pipe_shader_state frag_shader;
68 void *vs;
69 void *fs;
70
71 struct pipe_buffer *vbuf; /**< quad vertices */
72 float vertices[4][2][4]; /**< vertex/texcoords for quad */
73 };
74
75
76
77 enum dtype
78 {
79 UBYTE,
80 UBYTE_3_3_2,
81 USHORT,
82 USHORT_4_4_4_4,
83 USHORT_5_6_5,
84 USHORT_1_5_5_5_REV,
85 UINT,
86 FLOAT,
87 HALF_FLOAT
88 };
89
90
91 typedef ushort half_float;
92
93
94 #if 0
95 extern half_float
96 float_to_half(float f);
97
98 extern float
99 half_to_float(half_float h);
100 #endif
101
102
103 /**
104 * Average together two rows of a source image to produce a single new
105 * row in the dest image. It's legal for the two source rows to point
106 * to the same data. The source width must be equal to either the
107 * dest width or two times the dest width.
108 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
109 * \param comps number of components per pixel (1..4)
110 */
111 static void
112 do_row(enum dtype datatype, uint comps, int srcWidth,
113 const void *srcRowA, const void *srcRowB,
114 int dstWidth, void *dstRow)
115 {
116 const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
117 const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
118
119 assert(comps >= 1);
120 assert(comps <= 4);
121
122 /* This assertion is no longer valid with non-power-of-2 textures
123 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
124 */
125
126 if (datatype == UBYTE && comps == 4) {
127 uint i, j, k;
128 const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
129 const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
130 ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
131 for (i = j = 0, k = k0; i < (uint) dstWidth;
132 i++, j += colStride, k += colStride) {
133 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
134 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
135 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
136 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
137 }
138 }
139 else if (datatype == UBYTE && comps == 3) {
140 uint i, j, k;
141 const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
142 const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
143 ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
144 for (i = j = 0, k = k0; i < (uint) dstWidth;
145 i++, j += colStride, k += colStride) {
146 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
147 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
148 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
149 }
150 }
151 else if (datatype == UBYTE && comps == 2) {
152 uint i, j, k;
153 const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
154 const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
155 ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
156 for (i = j = 0, k = k0; i < (uint) dstWidth;
157 i++, j += colStride, k += colStride) {
158 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
159 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
160 }
161 }
162 else if (datatype == UBYTE && comps == 1) {
163 uint i, j, k;
164 const ubyte *rowA = (const ubyte *) srcRowA;
165 const ubyte *rowB = (const ubyte *) srcRowB;
166 ubyte *dst = (ubyte *) dstRow;
167 for (i = j = 0, k = k0; i < (uint) dstWidth;
168 i++, j += colStride, k += colStride) {
169 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
170 }
171 }
172
173 else if (datatype == USHORT && comps == 4) {
174 uint i, j, k;
175 const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
176 const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
177 ushort(*dst)[4] = (ushort(*)[4]) dstRow;
178 for (i = j = 0, k = k0; i < (uint) dstWidth;
179 i++, j += colStride, k += colStride) {
180 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
181 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
182 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
183 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
184 }
185 }
186 else if (datatype == USHORT && comps == 3) {
187 uint i, j, k;
188 const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
189 const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
190 ushort(*dst)[3] = (ushort(*)[3]) dstRow;
191 for (i = j = 0, k = k0; i < (uint) dstWidth;
192 i++, j += colStride, k += colStride) {
193 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
194 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
195 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
196 }
197 }
198 else if (datatype == USHORT && comps == 2) {
199 uint i, j, k;
200 const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
201 const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
202 ushort(*dst)[2] = (ushort(*)[2]) dstRow;
203 for (i = j = 0, k = k0; i < (uint) dstWidth;
204 i++, j += colStride, k += colStride) {
205 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
206 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
207 }
208 }
209 else if (datatype == USHORT && comps == 1) {
210 uint i, j, k;
211 const ushort *rowA = (const ushort *) srcRowA;
212 const ushort *rowB = (const ushort *) srcRowB;
213 ushort *dst = (ushort *) dstRow;
214 for (i = j = 0, k = k0; i < (uint) dstWidth;
215 i++, j += colStride, k += colStride) {
216 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
217 }
218 }
219
220 else if (datatype == FLOAT && comps == 4) {
221 uint i, j, k;
222 const float(*rowA)[4] = (const float(*)[4]) srcRowA;
223 const float(*rowB)[4] = (const float(*)[4]) srcRowB;
224 float(*dst)[4] = (float(*)[4]) dstRow;
225 for (i = j = 0, k = k0; i < (uint) dstWidth;
226 i++, j += colStride, k += colStride) {
227 dst[i][0] = (rowA[j][0] + rowA[k][0] +
228 rowB[j][0] + rowB[k][0]) * 0.25F;
229 dst[i][1] = (rowA[j][1] + rowA[k][1] +
230 rowB[j][1] + rowB[k][1]) * 0.25F;
231 dst[i][2] = (rowA[j][2] + rowA[k][2] +
232 rowB[j][2] + rowB[k][2]) * 0.25F;
233 dst[i][3] = (rowA[j][3] + rowA[k][3] +
234 rowB[j][3] + rowB[k][3]) * 0.25F;
235 }
236 }
237 else if (datatype == FLOAT && comps == 3) {
238 uint i, j, k;
239 const float(*rowA)[3] = (const float(*)[3]) srcRowA;
240 const float(*rowB)[3] = (const float(*)[3]) srcRowB;
241 float(*dst)[3] = (float(*)[3]) dstRow;
242 for (i = j = 0, k = k0; i < (uint) dstWidth;
243 i++, j += colStride, k += colStride) {
244 dst[i][0] = (rowA[j][0] + rowA[k][0] +
245 rowB[j][0] + rowB[k][0]) * 0.25F;
246 dst[i][1] = (rowA[j][1] + rowA[k][1] +
247 rowB[j][1] + rowB[k][1]) * 0.25F;
248 dst[i][2] = (rowA[j][2] + rowA[k][2] +
249 rowB[j][2] + rowB[k][2]) * 0.25F;
250 }
251 }
252 else if (datatype == FLOAT && comps == 2) {
253 uint i, j, k;
254 const float(*rowA)[2] = (const float(*)[2]) srcRowA;
255 const float(*rowB)[2] = (const float(*)[2]) srcRowB;
256 float(*dst)[2] = (float(*)[2]) dstRow;
257 for (i = j = 0, k = k0; i < (uint) dstWidth;
258 i++, j += colStride, k += colStride) {
259 dst[i][0] = (rowA[j][0] + rowA[k][0] +
260 rowB[j][0] + rowB[k][0]) * 0.25F;
261 dst[i][1] = (rowA[j][1] + rowA[k][1] +
262 rowB[j][1] + rowB[k][1]) * 0.25F;
263 }
264 }
265 else if (datatype == FLOAT && comps == 1) {
266 uint i, j, k;
267 const float *rowA = (const float *) srcRowA;
268 const float *rowB = (const float *) srcRowB;
269 float *dst = (float *) dstRow;
270 for (i = j = 0, k = k0; i < (uint) dstWidth;
271 i++, j += colStride, k += colStride) {
272 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
273 }
274 }
275
276 #if 0
277 else if (datatype == HALF_FLOAT && comps == 4) {
278 uint i, j, k, comp;
279 const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
280 const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
281 half_float(*dst)[4] = (half_float(*)[4]) dstRow;
282 for (i = j = 0, k = k0; i < (uint) dstWidth;
283 i++, j += colStride, k += colStride) {
284 for (comp = 0; comp < 4; comp++) {
285 float aj, ak, bj, bk;
286 aj = half_to_float(rowA[j][comp]);
287 ak = half_to_float(rowA[k][comp]);
288 bj = half_to_float(rowB[j][comp]);
289 bk = half_to_float(rowB[k][comp]);
290 dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
291 }
292 }
293 }
294 else if (datatype == HALF_FLOAT && comps == 3) {
295 uint i, j, k, comp;
296 const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
297 const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
298 half_float(*dst)[3] = (half_float(*)[3]) dstRow;
299 for (i = j = 0, k = k0; i < (uint) dstWidth;
300 i++, j += colStride, k += colStride) {
301 for (comp = 0; comp < 3; comp++) {
302 float aj, ak, bj, bk;
303 aj = half_to_float(rowA[j][comp]);
304 ak = half_to_float(rowA[k][comp]);
305 bj = half_to_float(rowB[j][comp]);
306 bk = half_to_float(rowB[k][comp]);
307 dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
308 }
309 }
310 }
311 else if (datatype == HALF_FLOAT && comps == 2) {
312 uint i, j, k, comp;
313 const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
314 const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
315 half_float(*dst)[2] = (half_float(*)[2]) dstRow;
316 for (i = j = 0, k = k0; i < (uint) dstWidth;
317 i++, j += colStride, k += colStride) {
318 for (comp = 0; comp < 2; comp++) {
319 float aj, ak, bj, bk;
320 aj = half_to_float(rowA[j][comp]);
321 ak = half_to_float(rowA[k][comp]);
322 bj = half_to_float(rowB[j][comp]);
323 bk = half_to_float(rowB[k][comp]);
324 dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
325 }
326 }
327 }
328 else if (datatype == HALF_FLOAT && comps == 1) {
329 uint i, j, k;
330 const half_float *rowA = (const half_float *) srcRowA;
331 const half_float *rowB = (const half_float *) srcRowB;
332 half_float *dst = (half_float *) dstRow;
333 for (i = j = 0, k = k0; i < (uint) dstWidth;
334 i++, j += colStride, k += colStride) {
335 float aj, ak, bj, bk;
336 aj = half_to_float(rowA[j]);
337 ak = half_to_float(rowA[k]);
338 bj = half_to_float(rowB[j]);
339 bk = half_to_float(rowB[k]);
340 dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
341 }
342 }
343 #endif
344
345 else if (datatype == UINT && comps == 1) {
346 uint i, j, k;
347 const uint *rowA = (const uint *) srcRowA;
348 const uint *rowB = (const uint *) srcRowB;
349 uint *dst = (uint *) dstRow;
350 for (i = j = 0, k = k0; i < (uint) dstWidth;
351 i++, j += colStride, k += colStride) {
352 dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
353 }
354 }
355
356 else if (datatype == USHORT_5_6_5 && comps == 3) {
357 uint i, j, k;
358 const ushort *rowA = (const ushort *) srcRowA;
359 const ushort *rowB = (const ushort *) srcRowB;
360 ushort *dst = (ushort *) dstRow;
361 for (i = j = 0, k = k0; i < (uint) dstWidth;
362 i++, j += colStride, k += colStride) {
363 const int rowAr0 = rowA[j] & 0x1f;
364 const int rowAr1 = rowA[k] & 0x1f;
365 const int rowBr0 = rowB[j] & 0x1f;
366 const int rowBr1 = rowB[k] & 0x1f;
367 const int rowAg0 = (rowA[j] >> 5) & 0x3f;
368 const int rowAg1 = (rowA[k] >> 5) & 0x3f;
369 const int rowBg0 = (rowB[j] >> 5) & 0x3f;
370 const int rowBg1 = (rowB[k] >> 5) & 0x3f;
371 const int rowAb0 = (rowA[j] >> 11) & 0x1f;
372 const int rowAb1 = (rowA[k] >> 11) & 0x1f;
373 const int rowBb0 = (rowB[j] >> 11) & 0x1f;
374 const int rowBb1 = (rowB[k] >> 11) & 0x1f;
375 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
376 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
377 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
378 dst[i] = (blue << 11) | (green << 5) | red;
379 }
380 }
381 else if (datatype == USHORT_4_4_4_4 && comps == 4) {
382 uint i, j, k;
383 const ushort *rowA = (const ushort *) srcRowA;
384 const ushort *rowB = (const ushort *) srcRowB;
385 ushort *dst = (ushort *) dstRow;
386 for (i = j = 0, k = k0; i < (uint) dstWidth;
387 i++, j += colStride, k += colStride) {
388 const int rowAr0 = rowA[j] & 0xf;
389 const int rowAr1 = rowA[k] & 0xf;
390 const int rowBr0 = rowB[j] & 0xf;
391 const int rowBr1 = rowB[k] & 0xf;
392 const int rowAg0 = (rowA[j] >> 4) & 0xf;
393 const int rowAg1 = (rowA[k] >> 4) & 0xf;
394 const int rowBg0 = (rowB[j] >> 4) & 0xf;
395 const int rowBg1 = (rowB[k] >> 4) & 0xf;
396 const int rowAb0 = (rowA[j] >> 8) & 0xf;
397 const int rowAb1 = (rowA[k] >> 8) & 0xf;
398 const int rowBb0 = (rowB[j] >> 8) & 0xf;
399 const int rowBb1 = (rowB[k] >> 8) & 0xf;
400 const int rowAa0 = (rowA[j] >> 12) & 0xf;
401 const int rowAa1 = (rowA[k] >> 12) & 0xf;
402 const int rowBa0 = (rowB[j] >> 12) & 0xf;
403 const int rowBa1 = (rowB[k] >> 12) & 0xf;
404 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
405 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
406 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
407 const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
408 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
409 }
410 }
411 else if (datatype == USHORT_1_5_5_5_REV && comps == 4) {
412 uint i, j, k;
413 const ushort *rowA = (const ushort *) srcRowA;
414 const ushort *rowB = (const ushort *) srcRowB;
415 ushort *dst = (ushort *) dstRow;
416 for (i = j = 0, k = k0; i < (uint) dstWidth;
417 i++, j += colStride, k += colStride) {
418 const int rowAr0 = rowA[j] & 0x1f;
419 const int rowAr1 = rowA[k] & 0x1f;
420 const int rowBr0 = rowB[j] & 0x1f;
421 const int rowBr1 = rowB[k] & 0xf;
422 const int rowAg0 = (rowA[j] >> 5) & 0x1f;
423 const int rowAg1 = (rowA[k] >> 5) & 0x1f;
424 const int rowBg0 = (rowB[j] >> 5) & 0x1f;
425 const int rowBg1 = (rowB[k] >> 5) & 0x1f;
426 const int rowAb0 = (rowA[j] >> 10) & 0x1f;
427 const int rowAb1 = (rowA[k] >> 10) & 0x1f;
428 const int rowBb0 = (rowB[j] >> 10) & 0x1f;
429 const int rowBb1 = (rowB[k] >> 10) & 0x1f;
430 const int rowAa0 = (rowA[j] >> 15) & 0x1;
431 const int rowAa1 = (rowA[k] >> 15) & 0x1;
432 const int rowBa0 = (rowB[j] >> 15) & 0x1;
433 const int rowBa1 = (rowB[k] >> 15) & 0x1;
434 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
435 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
436 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
437 const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
438 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
439 }
440 }
441 else if (datatype == UBYTE_3_3_2 && comps == 3) {
442 uint i, j, k;
443 const ubyte *rowA = (const ubyte *) srcRowA;
444 const ubyte *rowB = (const ubyte *) srcRowB;
445 ubyte *dst = (ubyte *) dstRow;
446 for (i = j = 0, k = k0; i < (uint) dstWidth;
447 i++, j += colStride, k += colStride) {
448 const int rowAr0 = rowA[j] & 0x3;
449 const int rowAr1 = rowA[k] & 0x3;
450 const int rowBr0 = rowB[j] & 0x3;
451 const int rowBr1 = rowB[k] & 0x3;
452 const int rowAg0 = (rowA[j] >> 2) & 0x7;
453 const int rowAg1 = (rowA[k] >> 2) & 0x7;
454 const int rowBg0 = (rowB[j] >> 2) & 0x7;
455 const int rowBg1 = (rowB[k] >> 2) & 0x7;
456 const int rowAb0 = (rowA[j] >> 5) & 0x7;
457 const int rowAb1 = (rowA[k] >> 5) & 0x7;
458 const int rowBb0 = (rowB[j] >> 5) & 0x7;
459 const int rowBb1 = (rowB[k] >> 5) & 0x7;
460 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
461 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
462 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
463 dst[i] = (blue << 5) | (green << 2) | red;
464 }
465 }
466 else {
467 debug_printf("bad format in do_row()");
468 }
469 }
470
471
472 static void
473 format_to_type_comps(enum pipe_format pformat,
474 enum dtype *datatype, uint *comps)
475 {
476 switch (pformat) {
477 case PIPE_FORMAT_A8R8G8B8_UNORM:
478 case PIPE_FORMAT_B8G8R8A8_UNORM:
479 *datatype = UBYTE;
480 *comps = 4;
481 return;
482 case PIPE_FORMAT_A1R5G5B5_UNORM:
483 *datatype = USHORT_1_5_5_5_REV;
484 *comps = 4;
485 return;
486 case PIPE_FORMAT_A4R4G4B4_UNORM:
487 *datatype = USHORT_4_4_4_4;
488 *comps = 4;
489 return;
490 case PIPE_FORMAT_R5G6B5_UNORM:
491 *datatype = USHORT_5_6_5;
492 *comps = 3;
493 return;
494 case PIPE_FORMAT_U_L8:
495 case PIPE_FORMAT_U_A8:
496 case PIPE_FORMAT_U_I8:
497 *datatype = UBYTE;
498 *comps = 1;
499 return;
500 case PIPE_FORMAT_U_A8_L8:
501 *datatype = UBYTE;
502 *comps = 2;
503 return;
504 default:
505 assert(0);
506 }
507 }
508
509
510 static void
511 reduce_1d(enum pipe_format pformat,
512 int srcWidth, const ubyte *srcPtr,
513 int dstWidth, ubyte *dstPtr)
514 {
515 enum dtype datatype;
516 uint comps;
517
518 format_to_type_comps(pformat, &datatype, &comps);
519
520 /* we just duplicate the input row, kind of hack, saves code */
521 do_row(datatype, comps,
522 srcWidth, srcPtr, srcPtr,
523 dstWidth, dstPtr);
524 }
525
526
527 /**
528 * Strides are in bytes. If zero, it'll be computed as width * bpp.
529 */
530 static void
531 reduce_2d(enum pipe_format pformat,
532 int srcWidth, int srcHeight,
533 int srcRowStride, const ubyte *srcPtr,
534 int dstWidth, int dstHeight,
535 int dstRowStride, ubyte *dstPtr)
536 {
537 enum dtype datatype;
538 uint comps;
539 const int bpt = pf_get_size(pformat);
540 const ubyte *srcA, *srcB;
541 ubyte *dst;
542 int row;
543
544 format_to_type_comps(pformat, &datatype, &comps);
545
546 if (!srcRowStride)
547 srcRowStride = bpt * srcWidth;
548
549 if (!dstRowStride)
550 dstRowStride = bpt * dstWidth;
551
552 /* Compute src and dst pointers */
553 srcA = srcPtr;
554 if (srcHeight > 1)
555 srcB = srcA + srcRowStride;
556 else
557 srcB = srcA;
558 dst = dstPtr;
559
560 for (row = 0; row < dstHeight; row++) {
561 do_row(datatype, comps,
562 srcWidth, srcA, srcB,
563 dstWidth, dst);
564 srcA += 2 * srcRowStride;
565 srcB += 2 * srcRowStride;
566 dst += dstRowStride;
567 }
568 }
569
570
571 static void
572 make_1d_mipmap(struct gen_mipmap_state *ctx,
573 struct pipe_texture *pt,
574 uint face, uint baseLevel, uint lastLevel)
575 {
576 struct pipe_context *pipe = ctx->pipe;
577 struct pipe_screen *screen = pipe->screen;
578 struct pipe_winsys *winsys = pipe->winsys;
579 const uint zslice = 0;
580 uint dstLevel;
581
582 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
583 const uint srcLevel = dstLevel - 1;
584 struct pipe_surface *srcSurf, *dstSurf;
585 void *srcMap, *dstMap;
586
587 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice);
588 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
589
590 srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
591 PIPE_BUFFER_USAGE_CPU_READ)
592 + srcSurf->offset);
593 dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
594 PIPE_BUFFER_USAGE_CPU_WRITE)
595 + dstSurf->offset);
596
597 reduce_1d(pt->format,
598 srcSurf->width, srcMap,
599 dstSurf->width, dstMap);
600
601 winsys->buffer_unmap(winsys, srcSurf->buffer);
602 winsys->buffer_unmap(winsys, dstSurf->buffer);
603
604 pipe_surface_reference(&srcSurf, NULL);
605 pipe_surface_reference(&dstSurf, NULL);
606 }
607 }
608
609
610 static void
611 make_2d_mipmap(struct gen_mipmap_state *ctx,
612 struct pipe_texture *pt,
613 uint face, uint baseLevel, uint lastLevel)
614 {
615 struct pipe_context *pipe = ctx->pipe;
616 struct pipe_screen *screen = pipe->screen;
617 struct pipe_winsys *winsys = pipe->winsys;
618 const uint zslice = 0;
619 uint dstLevel;
620 const int bpt = pf_get_size(pt->format);
621
622 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
623 const uint srcLevel = dstLevel - 1;
624 struct pipe_surface *srcSurf, *dstSurf;
625 ubyte *srcMap, *dstMap;
626
627 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice);
628 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
629
630 srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
631 PIPE_BUFFER_USAGE_CPU_READ)
632 + srcSurf->offset);
633 dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
634 PIPE_BUFFER_USAGE_CPU_WRITE)
635 + dstSurf->offset);
636
637 reduce_2d(pt->format,
638 srcSurf->width, srcSurf->height,
639 srcSurf->pitch * bpt, srcMap,
640 dstSurf->width, dstSurf->height,
641 dstSurf->pitch * bpt, dstMap);
642
643 winsys->buffer_unmap(winsys, srcSurf->buffer);
644 winsys->buffer_unmap(winsys, dstSurf->buffer);
645
646 pipe_surface_reference(&srcSurf, NULL);
647 pipe_surface_reference(&dstSurf, NULL);
648 }
649 }
650
651
652 static void
653 make_3d_mipmap(struct gen_mipmap_state *ctx,
654 struct pipe_texture *pt,
655 uint face, uint baseLevel, uint lastLevel)
656 {
657 }
658
659
660 static void
661 fallback_gen_mipmap(struct gen_mipmap_state *ctx,
662 struct pipe_texture *pt,
663 uint face, uint baseLevel, uint lastLevel)
664 {
665 switch (pt->target) {
666 case PIPE_TEXTURE_1D:
667 make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
668 break;
669 case PIPE_TEXTURE_2D:
670 case PIPE_TEXTURE_CUBE:
671 make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
672 break;
673 case PIPE_TEXTURE_3D:
674 make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
675 break;
676 default:
677 assert(0);
678 }
679 }
680
681
682 /**
683 * Create a mipmap generation context.
684 * The idea is to create one of these and re-use it each time we need to
685 * generate a mipmap.
686 */
687 struct gen_mipmap_state *
688 util_create_gen_mipmap(struct pipe_context *pipe,
689 struct cso_context *cso)
690 {
691 struct gen_mipmap_state *ctx;
692 uint i;
693
694 ctx = CALLOC_STRUCT(gen_mipmap_state);
695 if (!ctx)
696 return NULL;
697
698 ctx->pipe = pipe;
699 ctx->cso = cso;
700
701 /* disabled blending/masking */
702 memset(&ctx->blend, 0, sizeof(ctx->blend));
703 ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
704 ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
705 ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
706 ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
707 ctx->blend.colormask = PIPE_MASK_RGBA;
708
709 /* no-op depth/stencil/alpha */
710 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
711
712 /* rasterizer */
713 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
714 ctx->rasterizer.front_winding = PIPE_WINDING_CW;
715 ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
716 ctx->rasterizer.bypass_clipping = 1; /* bypasses viewport too */
717 /*ctx->rasterizer.bypass_vs = 1;*/
718
719 /* sampler state */
720 memset(&ctx->sampler, 0, sizeof(ctx->sampler));
721 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
722 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
723 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
724 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
725 ctx->sampler.normalized_coords = 1;
726
727 /* viewport state (identity, verts are in wincoords) */
728 ctx->viewport.scale[0] = 1.0;
729 ctx->viewport.scale[1] = 1.0;
730 ctx->viewport.scale[2] = 1.0;
731 ctx->viewport.scale[3] = 1.0;
732 ctx->viewport.translate[0] = 0.0;
733 ctx->viewport.translate[1] = 0.0;
734 ctx->viewport.translate[2] = 0.0;
735 ctx->viewport.translate[3] = 0.0;
736
737 /* vertex shader */
738 {
739 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
740 TGSI_SEMANTIC_GENERIC };
741 const uint semantic_indexes[] = { 0, 0 };
742 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
743 semantic_indexes,
744 &ctx->vert_shader);
745 }
746
747 /* fragment shader */
748 ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
749
750 ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys,
751 32,
752 PIPE_BUFFER_USAGE_VERTEX,
753 sizeof(ctx->vertices));
754 if (!ctx->vbuf) {
755 FREE(ctx);
756 return NULL;
757 }
758
759 /* vertex data that doesn't change */
760 for (i = 0; i < 4; i++) {
761 ctx->vertices[i][0][2] = 0.0f; /* z */
762 ctx->vertices[i][0][3] = 1.0f; /* w */
763 ctx->vertices[i][1][2] = 0.0f; /* r */
764 ctx->vertices[i][1][3] = 1.0f; /* q */
765 }
766
767 return ctx;
768 }
769
770
771 static void
772 set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
773 {
774 void *buf;
775
776 ctx->vertices[0][0][0] = -0.5f; /*x*/
777 ctx->vertices[0][0][1] = -0.5f; /*y*/
778 ctx->vertices[0][1][0] = 0.0f; /*s*/
779 ctx->vertices[0][1][1] = 0.0f; /*t*/
780
781 ctx->vertices[1][0][0] = width - 0.5f; /*x*/
782 ctx->vertices[1][0][1] = -0.5f; /*y*/
783 ctx->vertices[1][1][0] = 1.0f; /*s*/
784 ctx->vertices[1][1][1] = 0.0f; /*t*/
785
786 ctx->vertices[2][0][0] = width - 0.5f;
787 ctx->vertices[2][0][1] = height - 0.5f;
788 ctx->vertices[2][1][0] = 1.0f;
789 ctx->vertices[2][1][1] = 1.0f;
790
791 ctx->vertices[3][0][0] = -0.5f;
792 ctx->vertices[3][0][1] = height - 0.5f;
793 ctx->vertices[3][1][0] = 0.0f;
794 ctx->vertices[3][1][1] = 1.0f;
795
796 buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf,
797 PIPE_BUFFER_USAGE_CPU_WRITE);
798
799 memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
800
801 ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf);
802 }
803
804
805
806 /**
807 * Destroy a mipmap generation context
808 */
809 void
810 util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
811 {
812 struct pipe_context *pipe = ctx->pipe;
813
814 pipe->delete_vs_state(pipe, ctx->vs);
815 pipe->delete_fs_state(pipe, ctx->fs);
816
817 FREE((void*) ctx->vert_shader.tokens);
818 FREE((void*) ctx->frag_shader.tokens);
819
820 pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf);
821
822 FREE(ctx);
823 }
824
825
826 /**
827 * Generate mipmap images. It's assumed all needed texture memory is
828 * already allocated.
829 *
830 * \param pt the texture to generate mipmap levels for
831 * \param face which cube face to generate mipmaps for (0 for non-cube maps)
832 * \param baseLevel the first mipmap level to use as a src
833 * \param lastLevel the last mipmap level to generate
834 * \param filter the minification filter used to generate mipmap levels with
835 * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
836 */
837 void
838 util_gen_mipmap(struct gen_mipmap_state *ctx,
839 struct pipe_texture *pt,
840 uint face, uint baseLevel, uint lastLevel, uint filter)
841 {
842 struct pipe_context *pipe = ctx->pipe;
843 struct pipe_screen *screen = pipe->screen;
844 struct pipe_framebuffer_state fb;
845 uint dstLevel;
846 uint zslice = 0;
847
848 /* check if we can render in the texture's format */
849 if (!screen->is_format_supported(screen, pt->format, PIPE_SURFACE)) {
850 fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
851 return;
852 }
853
854 /* save state (restored below) */
855 cso_save_blend(ctx->cso);
856 cso_save_depth_stencil_alpha(ctx->cso);
857 cso_save_rasterizer(ctx->cso);
858 cso_save_samplers(ctx->cso);
859 cso_save_sampler_textures(ctx->cso);
860 cso_save_framebuffer(ctx->cso);
861 cso_save_fragment_shader(ctx->cso);
862 cso_save_vertex_shader(ctx->cso);
863 cso_save_viewport(ctx->cso);
864
865 /* bind our state */
866 cso_set_blend(ctx->cso, &ctx->blend);
867 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
868 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
869 cso_set_viewport(ctx->cso, &ctx->viewport);
870
871 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
872 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
873
874 /* init framebuffer state */
875 memset(&fb, 0, sizeof(fb));
876 fb.num_cbufs = 1;
877
878 /* set min/mag to same filter for faster sw speed */
879 ctx->sampler.mag_img_filter = filter;
880 ctx->sampler.min_img_filter = filter;
881
882 /*
883 * XXX for small mipmap levels, it may be faster to use the software
884 * fallback path...
885 */
886 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
887 const uint srcLevel = dstLevel - 1;
888
889 /*
890 * Setup framebuffer / dest surface
891 */
892 fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
893 fb.width = pt->width[dstLevel];
894 fb.height = pt->height[dstLevel];
895 cso_set_framebuffer(ctx->cso, &fb);
896
897 /*
898 * Setup sampler state
899 * Note: we should only have to set the min/max LOD clamps to ensure
900 * we grab texels from the right mipmap level. But some hardware
901 * has trouble with min clamping so we also set the lod_bias to
902 * try to work around that.
903 */
904 ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
905 ctx->sampler.lod_bias = (float) srcLevel;
906 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
907 cso_single_sampler_done(ctx->cso);
908
909 cso_set_sampler_textures(ctx->cso, 1, &pt);
910
911 /* quad coords in window coords (bypassing clipping, viewport mapping) */
912 set_vertex_data(ctx,
913 (float) pt->width[dstLevel],
914 (float) pt->height[dstLevel]);
915 util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
916 PIPE_PRIM_TRIANGLE_FAN,
917 4, /* verts */
918 2); /* attribs/vert */
919
920 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
921
922 /* need to signal that the texture has changed _after_ rendering to it */
923 pipe->texture_update(pipe, pt, face, (1 << dstLevel));
924 }
925
926 /* restore state we changed */
927 cso_restore_blend(ctx->cso);
928 cso_restore_depth_stencil_alpha(ctx->cso);
929 cso_restore_rasterizer(ctx->cso);
930 cso_restore_samplers(ctx->cso);
931 cso_restore_sampler_textures(ctx->cso);
932 cso_restore_framebuffer(ctx->cso);
933 cso_restore_fragment_shader(ctx->cso);
934 cso_restore_vertex_shader(ctx->cso);
935 cso_restore_viewport(ctx->cso);
936 }