u_gen_mipmap.c revision bdb0ad77c20653d01570a4ce44f4200a97fb5f11
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * Copyright 2008 VMware, Inc. All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29/** 30 * @file 31 * Mipmap generation utility 32 * 33 * @author Brian Paul 34 */ 35 36 37#include "pipe/p_context.h" 38#include "util/u_debug.h" 39#include "pipe/p_defines.h" 40#include "util/u_inlines.h" 41#include "pipe/p_shader_tokens.h" 42#include "pipe/p_state.h" 43 44#include "util/u_format.h" 45#include "util/u_memory.h" 46#include "util/u_draw_quad.h" 47#include "util/u_gen_mipmap.h" 48#include "util/u_simple_shaders.h" 49#include "util/u_math.h" 50#include "util/u_texture.h" 51#include "util/u_half.h" 52#include "util/u_surface.h" 53 54#include "cso_cache/cso_context.h" 55 56 57struct gen_mipmap_state 58{ 59 struct pipe_context *pipe; 60 struct cso_context *cso; 61 62 struct pipe_blend_state blend; 63 struct pipe_depth_stencil_alpha_state depthstencil; 64 struct pipe_rasterizer_state rasterizer; 65 struct pipe_sampler_state sampler; 66 struct pipe_vertex_element velem[2]; 67 68 void *vs; 69 void *fs[TGSI_TEXTURE_COUNT]; /**< Not all are used, but simplifies code */ 70 71 struct pipe_resource *vbuf; /**< quad vertices */ 72 unsigned vbuf_slot; 73 74 float vertices[4][2][4]; /**< vertex/texcoords for quad */ 75}; 76 77 78 79enum dtype 80{ 81 DTYPE_UBYTE, 82 DTYPE_UBYTE_3_3_2, 83 DTYPE_USHORT, 84 DTYPE_USHORT_4_4_4_4, 85 DTYPE_USHORT_5_6_5, 86 DTYPE_USHORT_1_5_5_5_REV, 87 DTYPE_UINT, 88 DTYPE_FLOAT, 89 DTYPE_HALF_FLOAT 90}; 91 92 93typedef uint16_t half_float; 94 95 96/** 97 * \name Support macros for do_row and do_row_3d 98 * 99 * The macro madness is here for two reasons. First, it compacts the code 100 * slightly. Second, it makes it much easier to adjust the specifics of the 101 * filter to tune the rounding characteristics. 102 */ 103/*@{*/ 104#define DECLARE_ROW_POINTERS(t, e) \ 105 const t(*rowA)[e] = (const t(*)[e]) srcRowA; \ 106 const t(*rowB)[e] = (const t(*)[e]) srcRowB; \ 107 const t(*rowC)[e] = (const t(*)[e]) srcRowC; \ 108 const t(*rowD)[e] = (const t(*)[e]) srcRowD; \ 109 t(*dst)[e] = (t(*)[e]) dstRow 110 111#define DECLARE_ROW_POINTERS0(t) \ 112 const t *rowA = (const t *) srcRowA; \ 113 const t *rowB = (const t *) srcRowB; \ 114 const t *rowC = (const t *) srcRowC; \ 115 const t *rowD = (const t *) srcRowD; \ 116 t *dst = (t *) dstRow 117 118#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ 119 ((unsigned) Aj + (unsigned) Ak \ 120 + (unsigned) Bj + (unsigned) Bk \ 121 + (unsigned) Cj + (unsigned) Ck \ 122 + (unsigned) Dj + (unsigned) Dk \ 123 + 4) >> 3 124 125#define FILTER_3D(e) \ 126 do { \ 127 dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \ 128 rowB[j][e], rowB[k][e], \ 129 rowC[j][e], rowC[k][e], \ 130 rowD[j][e], rowD[k][e]); \ 131 } while(0) 132 133#define FILTER_F_3D(e) \ 134 do { \ 135 dst[i][e] = (rowA[j][e] + rowA[k][e] \ 136 + rowB[j][e] + rowB[k][e] \ 137 + rowC[j][e] + rowC[k][e] \ 138 + rowD[j][e] + rowD[k][e]) * 0.125F; \ 139 } while(0) 140 141#define FILTER_HF_3D(e) \ 142 do { \ 143 const float aj = util_half_to_float(rowA[j][e]); \ 144 const float ak = util_half_to_float(rowA[k][e]); \ 145 const float bj = util_half_to_float(rowB[j][e]); \ 146 const float bk = util_half_to_float(rowB[k][e]); \ 147 const float cj = util_half_to_float(rowC[j][e]); \ 148 const float ck = util_half_to_float(rowC[k][e]); \ 149 const float dj = util_half_to_float(rowD[j][e]); \ 150 const float dk = util_half_to_float(rowD[k][e]); \ 151 dst[i][e] = util_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \ 152 * 0.125F); \ 153 } while(0) 154/*@}*/ 155 156 157/** 158 * Average together two rows of a source image to produce a single new 159 * row in the dest image. It's legal for the two source rows to point 160 * to the same data. The source width must be equal to either the 161 * dest width or two times the dest width. 162 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc. 163 * \param comps number of components per pixel (1..4) 164 */ 165static void 166do_row(enum dtype datatype, uint comps, int srcWidth, 167 const void *srcRowA, const void *srcRowB, 168 int dstWidth, void *dstRow) 169{ 170 const uint k0 = (srcWidth == dstWidth) ? 0 : 1; 171 const uint colStride = (srcWidth == dstWidth) ? 1 : 2; 172 173 assert(comps >= 1); 174 assert(comps <= 4); 175 176 /* This assertion is no longer valid with non-power-of-2 textures 177 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); 178 */ 179 180 if (datatype == DTYPE_UBYTE && comps == 4) { 181 uint i, j, k; 182 const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA; 183 const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB; 184 ubyte(*dst)[4] = (ubyte(*)[4]) dstRow; 185 for (i = j = 0, k = k0; i < (uint) dstWidth; 186 i++, j += colStride, k += colStride) { 187 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 188 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 189 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 190 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 191 } 192 } 193 else if (datatype == DTYPE_UBYTE && comps == 3) { 194 uint i, j, k; 195 const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA; 196 const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB; 197 ubyte(*dst)[3] = (ubyte(*)[3]) dstRow; 198 for (i = j = 0, k = k0; i < (uint) dstWidth; 199 i++, j += colStride, k += colStride) { 200 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 201 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 202 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 203 } 204 } 205 else if (datatype == DTYPE_UBYTE && comps == 2) { 206 uint i, j, k; 207 const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA; 208 const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB; 209 ubyte(*dst)[2] = (ubyte(*)[2]) dstRow; 210 for (i = j = 0, k = k0; i < (uint) dstWidth; 211 i++, j += colStride, k += colStride) { 212 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2; 213 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2; 214 } 215 } 216 else if (datatype == DTYPE_UBYTE && comps == 1) { 217 uint i, j, k; 218 const ubyte *rowA = (const ubyte *) srcRowA; 219 const ubyte *rowB = (const ubyte *) srcRowB; 220 ubyte *dst = (ubyte *) dstRow; 221 for (i = j = 0, k = k0; i < (uint) dstWidth; 222 i++, j += colStride, k += colStride) { 223 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; 224 } 225 } 226 227 else if (datatype == DTYPE_USHORT && comps == 4) { 228 uint i, j, k; 229 const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA; 230 const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB; 231 ushort(*dst)[4] = (ushort(*)[4]) dstRow; 232 for (i = j = 0, k = k0; i < (uint) dstWidth; 233 i++, j += colStride, k += colStride) { 234 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 235 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 236 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 237 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 238 } 239 } 240 else if (datatype == DTYPE_USHORT && comps == 3) { 241 uint i, j, k; 242 const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA; 243 const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB; 244 ushort(*dst)[3] = (ushort(*)[3]) dstRow; 245 for (i = j = 0, k = k0; i < (uint) dstWidth; 246 i++, j += colStride, k += colStride) { 247 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 248 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 249 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 250 } 251 } 252 else if (datatype == DTYPE_USHORT && comps == 2) { 253 uint i, j, k; 254 const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA; 255 const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB; 256 ushort(*dst)[2] = (ushort(*)[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] + rowB[j][0] + rowB[k][0]) / 4; 260 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 261 } 262 } 263 else if (datatype == DTYPE_USHORT && comps == 1) { 264 uint i, j, k; 265 const ushort *rowA = (const ushort *) srcRowA; 266 const ushort *rowB = (const ushort *) srcRowB; 267 ushort *dst = (ushort *) dstRow; 268 for (i = j = 0, k = k0; i < (uint) dstWidth; 269 i++, j += colStride, k += colStride) { 270 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 271 } 272 } 273 274 else if (datatype == DTYPE_FLOAT && comps == 4) { 275 uint i, j, k; 276 const float(*rowA)[4] = (const float(*)[4]) srcRowA; 277 const float(*rowB)[4] = (const float(*)[4]) srcRowB; 278 float(*dst)[4] = (float(*)[4]) dstRow; 279 for (i = j = 0, k = k0; i < (uint) dstWidth; 280 i++, j += colStride, k += colStride) { 281 dst[i][0] = (rowA[j][0] + rowA[k][0] + 282 rowB[j][0] + rowB[k][0]) * 0.25F; 283 dst[i][1] = (rowA[j][1] + rowA[k][1] + 284 rowB[j][1] + rowB[k][1]) * 0.25F; 285 dst[i][2] = (rowA[j][2] + rowA[k][2] + 286 rowB[j][2] + rowB[k][2]) * 0.25F; 287 dst[i][3] = (rowA[j][3] + rowA[k][3] + 288 rowB[j][3] + rowB[k][3]) * 0.25F; 289 } 290 } 291 else if (datatype == DTYPE_FLOAT && comps == 3) { 292 uint i, j, k; 293 const float(*rowA)[3] = (const float(*)[3]) srcRowA; 294 const float(*rowB)[3] = (const float(*)[3]) srcRowB; 295 float(*dst)[3] = (float(*)[3]) dstRow; 296 for (i = j = 0, k = k0; i < (uint) dstWidth; 297 i++, j += colStride, k += colStride) { 298 dst[i][0] = (rowA[j][0] + rowA[k][0] + 299 rowB[j][0] + rowB[k][0]) * 0.25F; 300 dst[i][1] = (rowA[j][1] + rowA[k][1] + 301 rowB[j][1] + rowB[k][1]) * 0.25F; 302 dst[i][2] = (rowA[j][2] + rowA[k][2] + 303 rowB[j][2] + rowB[k][2]) * 0.25F; 304 } 305 } 306 else if (datatype == DTYPE_FLOAT && comps == 2) { 307 uint i, j, k; 308 const float(*rowA)[2] = (const float(*)[2]) srcRowA; 309 const float(*rowB)[2] = (const float(*)[2]) srcRowB; 310 float(*dst)[2] = (float(*)[2]) dstRow; 311 for (i = j = 0, k = k0; i < (uint) dstWidth; 312 i++, j += colStride, k += colStride) { 313 dst[i][0] = (rowA[j][0] + rowA[k][0] + 314 rowB[j][0] + rowB[k][0]) * 0.25F; 315 dst[i][1] = (rowA[j][1] + rowA[k][1] + 316 rowB[j][1] + rowB[k][1]) * 0.25F; 317 } 318 } 319 else if (datatype == DTYPE_FLOAT && comps == 1) { 320 uint i, j, k; 321 const float *rowA = (const float *) srcRowA; 322 const float *rowB = (const float *) srcRowB; 323 float *dst = (float *) dstRow; 324 for (i = j = 0, k = k0; i < (uint) dstWidth; 325 i++, j += colStride, k += colStride) { 326 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; 327 } 328 } 329 330 else if (datatype == DTYPE_HALF_FLOAT && comps == 4) { 331 uint i, j, k, comp; 332 const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA; 333 const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB; 334 half_float(*dst)[4] = (half_float(*)[4]) dstRow; 335 for (i = j = 0, k = k0; i < (uint) dstWidth; 336 i++, j += colStride, k += colStride) { 337 for (comp = 0; comp < 4; comp++) { 338 float aj, ak, bj, bk; 339 aj = util_half_to_float(rowA[j][comp]); 340 ak = util_half_to_float(rowA[k][comp]); 341 bj = util_half_to_float(rowB[j][comp]); 342 bk = util_half_to_float(rowB[k][comp]); 343 dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F); 344 } 345 } 346 } 347 else if (datatype == DTYPE_HALF_FLOAT && comps == 3) { 348 uint i, j, k, comp; 349 const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA; 350 const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB; 351 half_float(*dst)[3] = (half_float(*)[3]) dstRow; 352 for (i = j = 0, k = k0; i < (uint) dstWidth; 353 i++, j += colStride, k += colStride) { 354 for (comp = 0; comp < 3; comp++) { 355 float aj, ak, bj, bk; 356 aj = util_half_to_float(rowA[j][comp]); 357 ak = util_half_to_float(rowA[k][comp]); 358 bj = util_half_to_float(rowB[j][comp]); 359 bk = util_half_to_float(rowB[k][comp]); 360 dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F); 361 } 362 } 363 } 364 else if (datatype == DTYPE_HALF_FLOAT && comps == 2) { 365 uint i, j, k, comp; 366 const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA; 367 const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB; 368 half_float(*dst)[2] = (half_float(*)[2]) dstRow; 369 for (i = j = 0, k = k0; i < (uint) dstWidth; 370 i++, j += colStride, k += colStride) { 371 for (comp = 0; comp < 2; comp++) { 372 float aj, ak, bj, bk; 373 aj = util_half_to_float(rowA[j][comp]); 374 ak = util_half_to_float(rowA[k][comp]); 375 bj = util_half_to_float(rowB[j][comp]); 376 bk = util_half_to_float(rowB[k][comp]); 377 dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F); 378 } 379 } 380 } 381 else if (datatype == DTYPE_HALF_FLOAT && comps == 1) { 382 uint i, j, k; 383 const half_float *rowA = (const half_float *) srcRowA; 384 const half_float *rowB = (const half_float *) srcRowB; 385 half_float *dst = (half_float *) dstRow; 386 for (i = j = 0, k = k0; i < (uint) dstWidth; 387 i++, j += colStride, k += colStride) { 388 float aj, ak, bj, bk; 389 aj = util_half_to_float(rowA[j]); 390 ak = util_half_to_float(rowA[k]); 391 bj = util_half_to_float(rowB[j]); 392 bk = util_half_to_float(rowB[k]); 393 dst[i] = util_float_to_half((aj + ak + bj + bk) * 0.25F); 394 } 395 } 396 397 else if (datatype == DTYPE_UINT && comps == 1) { 398 uint i, j, k; 399 const uint *rowA = (const uint *) srcRowA; 400 const uint *rowB = (const uint *) srcRowB; 401 uint *dst = (uint *) dstRow; 402 for (i = j = 0, k = k0; i < (uint) dstWidth; 403 i++, j += colStride, k += colStride) { 404 dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4; 405 } 406 } 407 408 else if (datatype == DTYPE_USHORT_5_6_5 && comps == 3) { 409 uint i, j, k; 410 const ushort *rowA = (const ushort *) srcRowA; 411 const ushort *rowB = (const ushort *) srcRowB; 412 ushort *dst = (ushort *) dstRow; 413 for (i = j = 0, k = k0; i < (uint) dstWidth; 414 i++, j += colStride, k += colStride) { 415 const int rowAr0 = rowA[j] & 0x1f; 416 const int rowAr1 = rowA[k] & 0x1f; 417 const int rowBr0 = rowB[j] & 0x1f; 418 const int rowBr1 = rowB[k] & 0x1f; 419 const int rowAg0 = (rowA[j] >> 5) & 0x3f; 420 const int rowAg1 = (rowA[k] >> 5) & 0x3f; 421 const int rowBg0 = (rowB[j] >> 5) & 0x3f; 422 const int rowBg1 = (rowB[k] >> 5) & 0x3f; 423 const int rowAb0 = (rowA[j] >> 11) & 0x1f; 424 const int rowAb1 = (rowA[k] >> 11) & 0x1f; 425 const int rowBb0 = (rowB[j] >> 11) & 0x1f; 426 const int rowBb1 = (rowB[k] >> 11) & 0x1f; 427 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 428 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 429 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 430 dst[i] = (blue << 11) | (green << 5) | red; 431 } 432 } 433 else if (datatype == DTYPE_USHORT_4_4_4_4 && comps == 4) { 434 uint i, j, k; 435 const ushort *rowA = (const ushort *) srcRowA; 436 const ushort *rowB = (const ushort *) srcRowB; 437 ushort *dst = (ushort *) dstRow; 438 for (i = j = 0, k = k0; i < (uint) dstWidth; 439 i++, j += colStride, k += colStride) { 440 const int rowAr0 = rowA[j] & 0xf; 441 const int rowAr1 = rowA[k] & 0xf; 442 const int rowBr0 = rowB[j] & 0xf; 443 const int rowBr1 = rowB[k] & 0xf; 444 const int rowAg0 = (rowA[j] >> 4) & 0xf; 445 const int rowAg1 = (rowA[k] >> 4) & 0xf; 446 const int rowBg0 = (rowB[j] >> 4) & 0xf; 447 const int rowBg1 = (rowB[k] >> 4) & 0xf; 448 const int rowAb0 = (rowA[j] >> 8) & 0xf; 449 const int rowAb1 = (rowA[k] >> 8) & 0xf; 450 const int rowBb0 = (rowB[j] >> 8) & 0xf; 451 const int rowBb1 = (rowB[k] >> 8) & 0xf; 452 const int rowAa0 = (rowA[j] >> 12) & 0xf; 453 const int rowAa1 = (rowA[k] >> 12) & 0xf; 454 const int rowBa0 = (rowB[j] >> 12) & 0xf; 455 const int rowBa1 = (rowB[k] >> 12) & 0xf; 456 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 457 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 458 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 459 const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 460 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; 461 } 462 } 463 else if (datatype == DTYPE_USHORT_1_5_5_5_REV && comps == 4) { 464 uint i, j, k; 465 const ushort *rowA = (const ushort *) srcRowA; 466 const ushort *rowB = (const ushort *) srcRowB; 467 ushort *dst = (ushort *) dstRow; 468 for (i = j = 0, k = k0; i < (uint) dstWidth; 469 i++, j += colStride, k += colStride) { 470 const int rowAr0 = rowA[j] & 0x1f; 471 const int rowAr1 = rowA[k] & 0x1f; 472 const int rowBr0 = rowB[j] & 0x1f; 473 const int rowBr1 = rowB[k] & 0x1f; 474 const int rowAg0 = (rowA[j] >> 5) & 0x1f; 475 const int rowAg1 = (rowA[k] >> 5) & 0x1f; 476 const int rowBg0 = (rowB[j] >> 5) & 0x1f; 477 const int rowBg1 = (rowB[k] >> 5) & 0x1f; 478 const int rowAb0 = (rowA[j] >> 10) & 0x1f; 479 const int rowAb1 = (rowA[k] >> 10) & 0x1f; 480 const int rowBb0 = (rowB[j] >> 10) & 0x1f; 481 const int rowBb1 = (rowB[k] >> 10) & 0x1f; 482 const int rowAa0 = (rowA[j] >> 15) & 0x1; 483 const int rowAa1 = (rowA[k] >> 15) & 0x1; 484 const int rowBa0 = (rowB[j] >> 15) & 0x1; 485 const int rowBa1 = (rowB[k] >> 15) & 0x1; 486 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 487 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 488 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 489 const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 490 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; 491 } 492 } 493 else if (datatype == DTYPE_UBYTE_3_3_2 && comps == 3) { 494 uint i, j, k; 495 const ubyte *rowA = (const ubyte *) srcRowA; 496 const ubyte *rowB = (const ubyte *) srcRowB; 497 ubyte *dst = (ubyte *) dstRow; 498 for (i = j = 0, k = k0; i < (uint) dstWidth; 499 i++, j += colStride, k += colStride) { 500 const int rowAr0 = rowA[j] & 0x3; 501 const int rowAr1 = rowA[k] & 0x3; 502 const int rowBr0 = rowB[j] & 0x3; 503 const int rowBr1 = rowB[k] & 0x3; 504 const int rowAg0 = (rowA[j] >> 2) & 0x7; 505 const int rowAg1 = (rowA[k] >> 2) & 0x7; 506 const int rowBg0 = (rowB[j] >> 2) & 0x7; 507 const int rowBg1 = (rowB[k] >> 2) & 0x7; 508 const int rowAb0 = (rowA[j] >> 5) & 0x7; 509 const int rowAb1 = (rowA[k] >> 5) & 0x7; 510 const int rowBb0 = (rowB[j] >> 5) & 0x7; 511 const int rowBb1 = (rowB[k] >> 5) & 0x7; 512 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 513 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 514 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 515 dst[i] = (blue << 5) | (green << 2) | red; 516 } 517 } 518 else { 519 debug_printf("bad format in do_row()"); 520 } 521} 522 523 524/** 525 * Average together four rows of a source image to produce a single new 526 * row in the dest image. It's legal for the two source rows to point 527 * to the same data. The source width must be equal to either the 528 * dest width or two times the dest width. 529 * 530 * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, 531 * \c GL_FLOAT, etc. 532 * \param comps number of components per pixel (1..4) 533 * \param srcWidth Width of a row in the source data 534 * \param srcRowA Pointer to one of the rows of source data 535 * \param srcRowB Pointer to one of the rows of source data 536 * \param srcRowC Pointer to one of the rows of source data 537 * \param srcRowD Pointer to one of the rows of source data 538 * \param dstWidth Width of a row in the destination data 539 * \param srcRowA Pointer to the row of destination data 540 */ 541static void 542do_row_3D(enum dtype datatype, uint comps, int srcWidth, 543 const void *srcRowA, const void *srcRowB, 544 const void *srcRowC, const void *srcRowD, 545 int dstWidth, void *dstRow) 546{ 547 const uint k0 = (srcWidth == dstWidth) ? 0 : 1; 548 const uint colStride = (srcWidth == dstWidth) ? 1 : 2; 549 uint i, j, k; 550 551 assert(comps >= 1); 552 assert(comps <= 4); 553 554 if ((datatype == DTYPE_UBYTE) && (comps == 4)) { 555 DECLARE_ROW_POINTERS(ubyte, 4); 556 557 for (i = j = 0, k = k0; i < (uint) dstWidth; 558 i++, j += colStride, k += colStride) { 559 FILTER_3D(0); 560 FILTER_3D(1); 561 FILTER_3D(2); 562 FILTER_3D(3); 563 } 564 } 565 else if ((datatype == DTYPE_UBYTE) && (comps == 3)) { 566 DECLARE_ROW_POINTERS(ubyte, 3); 567 568 for (i = j = 0, k = k0; i < (uint) dstWidth; 569 i++, j += colStride, k += colStride) { 570 FILTER_3D(0); 571 FILTER_3D(1); 572 FILTER_3D(2); 573 } 574 } 575 else if ((datatype == DTYPE_UBYTE) && (comps == 2)) { 576 DECLARE_ROW_POINTERS(ubyte, 2); 577 578 for (i = j = 0, k = k0; i < (uint) dstWidth; 579 i++, j += colStride, k += colStride) { 580 FILTER_3D(0); 581 FILTER_3D(1); 582 } 583 } 584 else if ((datatype == DTYPE_UBYTE) && (comps == 1)) { 585 DECLARE_ROW_POINTERS(ubyte, 1); 586 587 for (i = j = 0, k = k0; i < (uint) dstWidth; 588 i++, j += colStride, k += colStride) { 589 FILTER_3D(0); 590 } 591 } 592 else if ((datatype == DTYPE_USHORT) && (comps == 4)) { 593 DECLARE_ROW_POINTERS(ushort, 4); 594 595 for (i = j = 0, k = k0; i < (uint) dstWidth; 596 i++, j += colStride, k += colStride) { 597 FILTER_3D(0); 598 FILTER_3D(1); 599 FILTER_3D(2); 600 FILTER_3D(3); 601 } 602 } 603 else if ((datatype == DTYPE_USHORT) && (comps == 3)) { 604 DECLARE_ROW_POINTERS(ushort, 3); 605 606 for (i = j = 0, k = k0; i < (uint) dstWidth; 607 i++, j += colStride, k += colStride) { 608 FILTER_3D(0); 609 FILTER_3D(1); 610 FILTER_3D(2); 611 } 612 } 613 else if ((datatype == DTYPE_USHORT) && (comps == 2)) { 614 DECLARE_ROW_POINTERS(ushort, 2); 615 616 for (i = j = 0, k = k0; i < (uint) dstWidth; 617 i++, j += colStride, k += colStride) { 618 FILTER_3D(0); 619 FILTER_3D(1); 620 } 621 } 622 else if ((datatype == DTYPE_USHORT) && (comps == 1)) { 623 DECLARE_ROW_POINTERS(ushort, 1); 624 625 for (i = j = 0, k = k0; i < (uint) dstWidth; 626 i++, j += colStride, k += colStride) { 627 FILTER_3D(0); 628 } 629 } 630 else if ((datatype == DTYPE_FLOAT) && (comps == 4)) { 631 DECLARE_ROW_POINTERS(float, 4); 632 633 for (i = j = 0, k = k0; i < (uint) dstWidth; 634 i++, j += colStride, k += colStride) { 635 FILTER_F_3D(0); 636 FILTER_F_3D(1); 637 FILTER_F_3D(2); 638 FILTER_F_3D(3); 639 } 640 } 641 else if ((datatype == DTYPE_FLOAT) && (comps == 3)) { 642 DECLARE_ROW_POINTERS(float, 3); 643 644 for (i = j = 0, k = k0; i < (uint) dstWidth; 645 i++, j += colStride, k += colStride) { 646 FILTER_F_3D(0); 647 FILTER_F_3D(1); 648 FILTER_F_3D(2); 649 } 650 } 651 else if ((datatype == DTYPE_FLOAT) && (comps == 2)) { 652 DECLARE_ROW_POINTERS(float, 2); 653 654 for (i = j = 0, k = k0; i < (uint) dstWidth; 655 i++, j += colStride, k += colStride) { 656 FILTER_F_3D(0); 657 FILTER_F_3D(1); 658 } 659 } 660 else if ((datatype == DTYPE_FLOAT) && (comps == 1)) { 661 DECLARE_ROW_POINTERS(float, 1); 662 663 for (i = j = 0, k = k0; i < (uint) dstWidth; 664 i++, j += colStride, k += colStride) { 665 FILTER_F_3D(0); 666 } 667 } 668 else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 4)) { 669 DECLARE_ROW_POINTERS(half_float, 4); 670 671 for (i = j = 0, k = k0; i < (uint) dstWidth; 672 i++, j += colStride, k += colStride) { 673 FILTER_HF_3D(0); 674 FILTER_HF_3D(1); 675 FILTER_HF_3D(2); 676 FILTER_HF_3D(3); 677 } 678 } 679 else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 3)) { 680 DECLARE_ROW_POINTERS(half_float, 4); 681 682 for (i = j = 0, k = k0; i < (uint) dstWidth; 683 i++, j += colStride, k += colStride) { 684 FILTER_HF_3D(0); 685 FILTER_HF_3D(1); 686 FILTER_HF_3D(2); 687 } 688 } 689 else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 2)) { 690 DECLARE_ROW_POINTERS(half_float, 4); 691 692 for (i = j = 0, k = k0; i < (uint) dstWidth; 693 i++, j += colStride, k += colStride) { 694 FILTER_HF_3D(0); 695 FILTER_HF_3D(1); 696 } 697 } 698 else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 1)) { 699 DECLARE_ROW_POINTERS(half_float, 4); 700 701 for (i = j = 0, k = k0; i < (uint) dstWidth; 702 i++, j += colStride, k += colStride) { 703 FILTER_HF_3D(0); 704 } 705 } 706 else if ((datatype == DTYPE_UINT) && (comps == 1)) { 707 const uint *rowA = (const uint *) srcRowA; 708 const uint *rowB = (const uint *) srcRowB; 709 const uint *rowC = (const uint *) srcRowC; 710 const uint *rowD = (const uint *) srcRowD; 711 float *dst = (float *) dstRow; 712 713 for (i = j = 0, k = k0; i < (uint) dstWidth; 714 i++, j += colStride, k += colStride) { 715 const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k]) 716 + ((uint64_t) rowB[j] + (uint64_t) rowB[k]) 717 + ((uint64_t) rowC[j] + (uint64_t) rowC[k]) 718 + ((uint64_t) rowD[j] + (uint64_t) rowD[k])); 719 dst[i] = (float)((double) tmp * 0.125); 720 } 721 } 722 else if ((datatype == DTYPE_USHORT_5_6_5) && (comps == 3)) { 723 DECLARE_ROW_POINTERS0(ushort); 724 725 for (i = j = 0, k = k0; i < (uint) dstWidth; 726 i++, j += colStride, k += colStride) { 727 const int rowAr0 = rowA[j] & 0x1f; 728 const int rowAr1 = rowA[k] & 0x1f; 729 const int rowBr0 = rowB[j] & 0x1f; 730 const int rowBr1 = rowB[k] & 0x1f; 731 const int rowCr0 = rowC[j] & 0x1f; 732 const int rowCr1 = rowC[k] & 0x1f; 733 const int rowDr0 = rowD[j] & 0x1f; 734 const int rowDr1 = rowD[k] & 0x1f; 735 const int rowAg0 = (rowA[j] >> 5) & 0x3f; 736 const int rowAg1 = (rowA[k] >> 5) & 0x3f; 737 const int rowBg0 = (rowB[j] >> 5) & 0x3f; 738 const int rowBg1 = (rowB[k] >> 5) & 0x3f; 739 const int rowCg0 = (rowC[j] >> 5) & 0x3f; 740 const int rowCg1 = (rowC[k] >> 5) & 0x3f; 741 const int rowDg0 = (rowD[j] >> 5) & 0x3f; 742 const int rowDg1 = (rowD[k] >> 5) & 0x3f; 743 const int rowAb0 = (rowA[j] >> 11) & 0x1f; 744 const int rowAb1 = (rowA[k] >> 11) & 0x1f; 745 const int rowBb0 = (rowB[j] >> 11) & 0x1f; 746 const int rowBb1 = (rowB[k] >> 11) & 0x1f; 747 const int rowCb0 = (rowC[j] >> 11) & 0x1f; 748 const int rowCb1 = (rowC[k] >> 11) & 0x1f; 749 const int rowDb0 = (rowD[j] >> 11) & 0x1f; 750 const int rowDb1 = (rowD[k] >> 11) & 0x1f; 751 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 752 rowCr0, rowCr1, rowDr0, rowDr1); 753 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 754 rowCg0, rowCg1, rowDg0, rowDg1); 755 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 756 rowCb0, rowCb1, rowDb0, rowDb1); 757 dst[i] = (b << 11) | (g << 5) | r; 758 } 759 } 760 else if ((datatype == DTYPE_USHORT_4_4_4_4) && (comps == 4)) { 761 DECLARE_ROW_POINTERS0(ushort); 762 763 for (i = j = 0, k = k0; i < (uint) dstWidth; 764 i++, j += colStride, k += colStride) { 765 const int rowAr0 = rowA[j] & 0xf; 766 const int rowAr1 = rowA[k] & 0xf; 767 const int rowBr0 = rowB[j] & 0xf; 768 const int rowBr1 = rowB[k] & 0xf; 769 const int rowCr0 = rowC[j] & 0xf; 770 const int rowCr1 = rowC[k] & 0xf; 771 const int rowDr0 = rowD[j] & 0xf; 772 const int rowDr1 = rowD[k] & 0xf; 773 const int rowAg0 = (rowA[j] >> 4) & 0xf; 774 const int rowAg1 = (rowA[k] >> 4) & 0xf; 775 const int rowBg0 = (rowB[j] >> 4) & 0xf; 776 const int rowBg1 = (rowB[k] >> 4) & 0xf; 777 const int rowCg0 = (rowC[j] >> 4) & 0xf; 778 const int rowCg1 = (rowC[k] >> 4) & 0xf; 779 const int rowDg0 = (rowD[j] >> 4) & 0xf; 780 const int rowDg1 = (rowD[k] >> 4) & 0xf; 781 const int rowAb0 = (rowA[j] >> 8) & 0xf; 782 const int rowAb1 = (rowA[k] >> 8) & 0xf; 783 const int rowBb0 = (rowB[j] >> 8) & 0xf; 784 const int rowBb1 = (rowB[k] >> 8) & 0xf; 785 const int rowCb0 = (rowC[j] >> 8) & 0xf; 786 const int rowCb1 = (rowC[k] >> 8) & 0xf; 787 const int rowDb0 = (rowD[j] >> 8) & 0xf; 788 const int rowDb1 = (rowD[k] >> 8) & 0xf; 789 const int rowAa0 = (rowA[j] >> 12) & 0xf; 790 const int rowAa1 = (rowA[k] >> 12) & 0xf; 791 const int rowBa0 = (rowB[j] >> 12) & 0xf; 792 const int rowBa1 = (rowB[k] >> 12) & 0xf; 793 const int rowCa0 = (rowC[j] >> 12) & 0xf; 794 const int rowCa1 = (rowC[k] >> 12) & 0xf; 795 const int rowDa0 = (rowD[j] >> 12) & 0xf; 796 const int rowDa1 = (rowD[k] >> 12) & 0xf; 797 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 798 rowCr0, rowCr1, rowDr0, rowDr1); 799 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 800 rowCg0, rowCg1, rowDg0, rowDg1); 801 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 802 rowCb0, rowCb1, rowDb0, rowDb1); 803 const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 804 rowCa0, rowCa1, rowDa0, rowDa1); 805 806 dst[i] = (a << 12) | (b << 8) | (g << 4) | r; 807 } 808 } 809 else if ((datatype == DTYPE_USHORT_1_5_5_5_REV) && (comps == 4)) { 810 DECLARE_ROW_POINTERS0(ushort); 811 812 for (i = j = 0, k = k0; i < (uint) dstWidth; 813 i++, j += colStride, k += colStride) { 814 const int rowAr0 = rowA[j] & 0x1f; 815 const int rowAr1 = rowA[k] & 0x1f; 816 const int rowBr0 = rowB[j] & 0x1f; 817 const int rowBr1 = rowB[k] & 0x1f; 818 const int rowCr0 = rowC[j] & 0x1f; 819 const int rowCr1 = rowC[k] & 0x1f; 820 const int rowDr0 = rowD[j] & 0x1f; 821 const int rowDr1 = rowD[k] & 0x1f; 822 const int rowAg0 = (rowA[j] >> 5) & 0x1f; 823 const int rowAg1 = (rowA[k] >> 5) & 0x1f; 824 const int rowBg0 = (rowB[j] >> 5) & 0x1f; 825 const int rowBg1 = (rowB[k] >> 5) & 0x1f; 826 const int rowCg0 = (rowC[j] >> 5) & 0x1f; 827 const int rowCg1 = (rowC[k] >> 5) & 0x1f; 828 const int rowDg0 = (rowD[j] >> 5) & 0x1f; 829 const int rowDg1 = (rowD[k] >> 5) & 0x1f; 830 const int rowAb0 = (rowA[j] >> 10) & 0x1f; 831 const int rowAb1 = (rowA[k] >> 10) & 0x1f; 832 const int rowBb0 = (rowB[j] >> 10) & 0x1f; 833 const int rowBb1 = (rowB[k] >> 10) & 0x1f; 834 const int rowCb0 = (rowC[j] >> 10) & 0x1f; 835 const int rowCb1 = (rowC[k] >> 10) & 0x1f; 836 const int rowDb0 = (rowD[j] >> 10) & 0x1f; 837 const int rowDb1 = (rowD[k] >> 10) & 0x1f; 838 const int rowAa0 = (rowA[j] >> 15) & 0x1; 839 const int rowAa1 = (rowA[k] >> 15) & 0x1; 840 const int rowBa0 = (rowB[j] >> 15) & 0x1; 841 const int rowBa1 = (rowB[k] >> 15) & 0x1; 842 const int rowCa0 = (rowC[j] >> 15) & 0x1; 843 const int rowCa1 = (rowC[k] >> 15) & 0x1; 844 const int rowDa0 = (rowD[j] >> 15) & 0x1; 845 const int rowDa1 = (rowD[k] >> 15) & 0x1; 846 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 847 rowCr0, rowCr1, rowDr0, rowDr1); 848 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 849 rowCg0, rowCg1, rowDg0, rowDg1); 850 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 851 rowCb0, rowCb1, rowDb0, rowDb1); 852 const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 853 rowCa0, rowCa1, rowDa0, rowDa1); 854 855 dst[i] = (a << 15) | (b << 10) | (g << 5) | r; 856 } 857 } 858 else if ((datatype == DTYPE_UBYTE_3_3_2) && (comps == 3)) { 859 DECLARE_ROW_POINTERS0(ushort); 860 861 for (i = j = 0, k = k0; i < (uint) dstWidth; 862 i++, j += colStride, k += colStride) { 863 const int rowAr0 = rowA[j] & 0x3; 864 const int rowAr1 = rowA[k] & 0x3; 865 const int rowBr0 = rowB[j] & 0x3; 866 const int rowBr1 = rowB[k] & 0x3; 867 const int rowCr0 = rowC[j] & 0x3; 868 const int rowCr1 = rowC[k] & 0x3; 869 const int rowDr0 = rowD[j] & 0x3; 870 const int rowDr1 = rowD[k] & 0x3; 871 const int rowAg0 = (rowA[j] >> 2) & 0x7; 872 const int rowAg1 = (rowA[k] >> 2) & 0x7; 873 const int rowBg0 = (rowB[j] >> 2) & 0x7; 874 const int rowBg1 = (rowB[k] >> 2) & 0x7; 875 const int rowCg0 = (rowC[j] >> 2) & 0x7; 876 const int rowCg1 = (rowC[k] >> 2) & 0x7; 877 const int rowDg0 = (rowD[j] >> 2) & 0x7; 878 const int rowDg1 = (rowD[k] >> 2) & 0x7; 879 const int rowAb0 = (rowA[j] >> 5) & 0x7; 880 const int rowAb1 = (rowA[k] >> 5) & 0x7; 881 const int rowBb0 = (rowB[j] >> 5) & 0x7; 882 const int rowBb1 = (rowB[k] >> 5) & 0x7; 883 const int rowCb0 = (rowC[j] >> 5) & 0x7; 884 const int rowCb1 = (rowC[k] >> 5) & 0x7; 885 const int rowDb0 = (rowD[j] >> 5) & 0x7; 886 const int rowDb1 = (rowD[k] >> 5) & 0x7; 887 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 888 rowCr0, rowCr1, rowDr0, rowDr1); 889 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 890 rowCg0, rowCg1, rowDg0, rowDg1); 891 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 892 rowCb0, rowCb1, rowDb0, rowDb1); 893 dst[i] = (b << 5) | (g << 2) | r; 894 } 895 } 896 else { 897 debug_printf("bad format in do_row_3D()"); 898 } 899} 900 901 902 903static void 904format_to_type_comps(enum pipe_format pformat, 905 enum dtype *datatype, uint *comps) 906{ 907 /* XXX I think this could be implemented in terms of the pf_*() functions */ 908 switch (pformat) { 909 case PIPE_FORMAT_B8G8R8A8_UNORM: 910 case PIPE_FORMAT_B8G8R8X8_UNORM: 911 case PIPE_FORMAT_A8R8G8B8_UNORM: 912 case PIPE_FORMAT_X8R8G8B8_UNORM: 913 case PIPE_FORMAT_A8B8G8R8_SRGB: 914 case PIPE_FORMAT_X8B8G8R8_SRGB: 915 case PIPE_FORMAT_B8G8R8A8_SRGB: 916 case PIPE_FORMAT_B8G8R8X8_SRGB: 917 case PIPE_FORMAT_A8R8G8B8_SRGB: 918 case PIPE_FORMAT_X8R8G8B8_SRGB: 919 case PIPE_FORMAT_R8G8B8_SRGB: 920 *datatype = DTYPE_UBYTE; 921 *comps = 4; 922 return; 923 case PIPE_FORMAT_B5G5R5X1_UNORM: 924 case PIPE_FORMAT_B5G5R5A1_UNORM: 925 *datatype = DTYPE_USHORT_1_5_5_5_REV; 926 *comps = 4; 927 return; 928 case PIPE_FORMAT_B4G4R4A4_UNORM: 929 *datatype = DTYPE_USHORT_4_4_4_4; 930 *comps = 4; 931 return; 932 case PIPE_FORMAT_B5G6R5_UNORM: 933 *datatype = DTYPE_USHORT_5_6_5; 934 *comps = 3; 935 return; 936 case PIPE_FORMAT_L8_UNORM: 937 case PIPE_FORMAT_L8_SRGB: 938 case PIPE_FORMAT_A8_UNORM: 939 case PIPE_FORMAT_I8_UNORM: 940 *datatype = DTYPE_UBYTE; 941 *comps = 1; 942 return; 943 case PIPE_FORMAT_L8A8_UNORM: 944 case PIPE_FORMAT_L8A8_SRGB: 945 *datatype = DTYPE_UBYTE; 946 *comps = 2; 947 return; 948 default: 949 assert(0); 950 *datatype = DTYPE_UBYTE; 951 *comps = 0; 952 break; 953 } 954} 955 956 957static void 958reduce_1d(enum pipe_format pformat, 959 int srcWidth, const ubyte *srcPtr, 960 int dstWidth, ubyte *dstPtr) 961{ 962 enum dtype datatype; 963 uint comps; 964 965 format_to_type_comps(pformat, &datatype, &comps); 966 967 /* we just duplicate the input row, kind of hack, saves code */ 968 do_row(datatype, comps, 969 srcWidth, srcPtr, srcPtr, 970 dstWidth, dstPtr); 971} 972 973 974/** 975 * Strides are in bytes. If zero, it'll be computed as width * bpp. 976 */ 977static void 978reduce_2d(enum pipe_format pformat, 979 int srcWidth, int srcHeight, 980 int srcRowStride, const ubyte *srcPtr, 981 int dstWidth, int dstHeight, 982 int dstRowStride, ubyte *dstPtr) 983{ 984 enum dtype datatype; 985 uint comps; 986 const int bpt = util_format_get_blocksize(pformat); 987 const ubyte *srcA, *srcB; 988 ubyte *dst; 989 int row; 990 991 format_to_type_comps(pformat, &datatype, &comps); 992 993 if (!srcRowStride) 994 srcRowStride = bpt * srcWidth; 995 996 if (!dstRowStride) 997 dstRowStride = bpt * dstWidth; 998 999 /* Compute src and dst pointers */ 1000 srcA = srcPtr; 1001 if (srcHeight > 1) 1002 srcB = srcA + srcRowStride; 1003 else 1004 srcB = srcA; 1005 dst = dstPtr; 1006 1007 for (row = 0; row < dstHeight; row++) { 1008 do_row(datatype, comps, 1009 srcWidth, srcA, srcB, 1010 dstWidth, dst); 1011 srcA += 2 * srcRowStride; 1012 srcB += 2 * srcRowStride; 1013 dst += dstRowStride; 1014 } 1015} 1016 1017 1018static void 1019reduce_3d(enum pipe_format pformat, 1020 int srcWidth, int srcHeight, int srcDepth, 1021 int srcRowStride, int srcImageStride, const ubyte *srcPtr, 1022 int dstWidth, int dstHeight, int dstDepth, 1023 int dstRowStride, int dstImageStride, ubyte *dstPtr) 1024{ 1025 const int bpt = util_format_get_blocksize(pformat); 1026 int img, row; 1027 int srcImageOffset, srcRowOffset; 1028 enum dtype datatype; 1029 uint comps; 1030 1031 format_to_type_comps(pformat, &datatype, &comps); 1032 1033 /* XXX I think we should rather assert those strides */ 1034 if (!srcImageStride) 1035 srcImageStride = srcWidth * srcHeight * bpt; 1036 if (!dstImageStride) 1037 dstImageStride = dstWidth * dstHeight * bpt; 1038 1039 if (!srcRowStride) 1040 srcRowStride = srcWidth * bpt; 1041 if (!dstRowStride) 1042 dstRowStride = dstWidth * bpt; 1043 1044 /* Offset between adjacent src images to be averaged together */ 1045 srcImageOffset = (srcDepth == dstDepth) ? 0 : srcImageStride; 1046 1047 /* Offset between adjacent src rows to be averaged together */ 1048 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride; 1049 1050 /* 1051 * Need to average together up to 8 src pixels for each dest pixel. 1052 * Break that down into 3 operations: 1053 * 1. take two rows from source image and average them together. 1054 * 2. take two rows from next source image and average them together. 1055 * 3. take the two averaged rows and average them for the final dst row. 1056 */ 1057 1058 /* 1059 printf("mip3d %d x %d x %d -> %d x %d x %d\n", 1060 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); 1061 */ 1062 1063 for (img = 0; img < dstDepth; img++) { 1064 /* first source image pointer */ 1065 const ubyte *imgSrcA = srcPtr 1066 + img * (srcImageStride + srcImageOffset); 1067 /* second source image pointer */ 1068 const ubyte *imgSrcB = imgSrcA + srcImageOffset; 1069 /* address of the dest image */ 1070 ubyte *imgDst = dstPtr + img * dstImageStride; 1071 1072 /* setup the four source row pointers and the dest row pointer */ 1073 const ubyte *srcImgARowA = imgSrcA; 1074 const ubyte *srcImgARowB = imgSrcA + srcRowOffset; 1075 const ubyte *srcImgBRowA = imgSrcB; 1076 const ubyte *srcImgBRowB = imgSrcB + srcRowOffset; 1077 ubyte *dstImgRow = imgDst; 1078 1079 for (row = 0; row < dstHeight; row++) { 1080 do_row_3D(datatype, comps, srcWidth, 1081 srcImgARowA, srcImgARowB, 1082 srcImgBRowA, srcImgBRowB, 1083 dstWidth, dstImgRow); 1084 1085 /* advance to next rows */ 1086 srcImgARowA += srcRowStride + srcRowOffset; 1087 srcImgARowB += srcRowStride + srcRowOffset; 1088 srcImgBRowA += srcRowStride + srcRowOffset; 1089 srcImgBRowB += srcRowStride + srcRowOffset; 1090 dstImgRow += dstImageStride; 1091 } 1092 } 1093} 1094 1095 1096 1097 1098static void 1099make_1d_mipmap(struct gen_mipmap_state *ctx, 1100 struct pipe_resource *pt, 1101 uint layer, uint baseLevel, uint lastLevel) 1102{ 1103 struct pipe_context *pipe = ctx->pipe; 1104 uint dstLevel; 1105 1106 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 1107 const uint srcLevel = dstLevel - 1; 1108 struct pipe_transfer *srcTrans, *dstTrans; 1109 void *srcMap, *dstMap; 1110 1111 srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer, 1112 PIPE_TRANSFER_READ, 0, 0, 1113 u_minify(pt->width0, srcLevel), 1114 u_minify(pt->height0, srcLevel)); 1115 dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer, 1116 PIPE_TRANSFER_WRITE, 0, 0, 1117 u_minify(pt->width0, dstLevel), 1118 u_minify(pt->height0, dstLevel)); 1119 1120 srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); 1121 dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); 1122 1123 reduce_1d(pt->format, 1124 srcTrans->box.width, srcMap, 1125 dstTrans->box.width, dstMap); 1126 1127 pipe->transfer_unmap(pipe, srcTrans); 1128 pipe->transfer_unmap(pipe, dstTrans); 1129 1130 pipe->transfer_destroy(pipe, srcTrans); 1131 pipe->transfer_destroy(pipe, dstTrans); 1132 } 1133} 1134 1135 1136static void 1137make_2d_mipmap(struct gen_mipmap_state *ctx, 1138 struct pipe_resource *pt, 1139 uint layer, uint baseLevel, uint lastLevel) 1140{ 1141 struct pipe_context *pipe = ctx->pipe; 1142 uint dstLevel; 1143 1144 assert(util_format_get_blockwidth(pt->format) == 1); 1145 assert(util_format_get_blockheight(pt->format) == 1); 1146 1147 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 1148 const uint srcLevel = dstLevel - 1; 1149 struct pipe_transfer *srcTrans, *dstTrans; 1150 ubyte *srcMap, *dstMap; 1151 1152 srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer, 1153 PIPE_TRANSFER_READ, 0, 0, 1154 u_minify(pt->width0, srcLevel), 1155 u_minify(pt->height0, srcLevel)); 1156 dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer, 1157 PIPE_TRANSFER_WRITE, 0, 0, 1158 u_minify(pt->width0, dstLevel), 1159 u_minify(pt->height0, dstLevel)); 1160 1161 srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); 1162 dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); 1163 1164 reduce_2d(pt->format, 1165 srcTrans->box.width, srcTrans->box.height, 1166 srcTrans->stride, srcMap, 1167 dstTrans->box.width, dstTrans->box.height, 1168 dstTrans->stride, dstMap); 1169 1170 pipe->transfer_unmap(pipe, srcTrans); 1171 pipe->transfer_unmap(pipe, dstTrans); 1172 1173 pipe->transfer_destroy(pipe, srcTrans); 1174 pipe->transfer_destroy(pipe, dstTrans); 1175 } 1176} 1177 1178 1179/* XXX looks a bit more like it could work now but need to test */ 1180static void 1181make_3d_mipmap(struct gen_mipmap_state *ctx, 1182 struct pipe_resource *pt, 1183 uint face, uint baseLevel, uint lastLevel) 1184{ 1185 struct pipe_context *pipe = ctx->pipe; 1186 uint dstLevel; 1187 struct pipe_box src_box, dst_box; 1188 1189 assert(util_format_get_blockwidth(pt->format) == 1); 1190 assert(util_format_get_blockheight(pt->format) == 1); 1191 1192 src_box.x = src_box.y = src_box.z = 0; 1193 dst_box.x = dst_box.y = dst_box.z = 0; 1194 1195 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 1196 const uint srcLevel = dstLevel - 1; 1197 struct pipe_transfer *srcTrans, *dstTrans; 1198 ubyte *srcMap, *dstMap; 1199 struct pipe_box src_box, dst_box; 1200 src_box.width = u_minify(pt->width0, srcLevel); 1201 src_box.height = u_minify(pt->height0, srcLevel); 1202 src_box.depth = u_minify(pt->depth0, srcLevel); 1203 dst_box.width = u_minify(pt->width0, dstLevel); 1204 dst_box.height = u_minify(pt->height0, dstLevel); 1205 dst_box.depth = u_minify(pt->depth0, dstLevel); 1206 1207 srcTrans = pipe->get_transfer(pipe, pt, srcLevel, 1208 PIPE_TRANSFER_READ, 1209 &src_box); 1210 dstTrans = pipe->get_transfer(pipe, pt, dstLevel, 1211 PIPE_TRANSFER_WRITE, 1212 &dst_box); 1213 1214 srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); 1215 dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); 1216 1217 reduce_3d(pt->format, 1218 srcTrans->box.width, srcTrans->box.height, srcTrans->box.depth, 1219 srcTrans->stride, srcTrans->layer_stride, srcMap, 1220 dstTrans->box.width, dstTrans->box.height, dstTrans->box.depth, 1221 dstTrans->stride, dstTrans->layer_stride, dstMap); 1222 1223 pipe->transfer_unmap(pipe, srcTrans); 1224 pipe->transfer_unmap(pipe, dstTrans); 1225 1226 pipe->transfer_destroy(pipe, srcTrans); 1227 pipe->transfer_destroy(pipe, dstTrans); 1228 } 1229} 1230 1231 1232static void 1233fallback_gen_mipmap(struct gen_mipmap_state *ctx, 1234 struct pipe_resource *pt, 1235 uint layer, uint baseLevel, uint lastLevel) 1236{ 1237 switch (pt->target) { 1238 case PIPE_TEXTURE_1D: 1239 make_1d_mipmap(ctx, pt, layer, baseLevel, lastLevel); 1240 break; 1241 case PIPE_TEXTURE_2D: 1242 case PIPE_TEXTURE_RECT: 1243 case PIPE_TEXTURE_CUBE: 1244 make_2d_mipmap(ctx, pt, layer, baseLevel, lastLevel); 1245 break; 1246 case PIPE_TEXTURE_3D: 1247 make_3d_mipmap(ctx, pt, layer, baseLevel, lastLevel); 1248 break; 1249 default: 1250 assert(0); 1251 } 1252} 1253 1254 1255/** 1256 * Create a mipmap generation context. 1257 * The idea is to create one of these and re-use it each time we need to 1258 * generate a mipmap. 1259 */ 1260struct gen_mipmap_state * 1261util_create_gen_mipmap(struct pipe_context *pipe, 1262 struct cso_context *cso) 1263{ 1264 struct gen_mipmap_state *ctx; 1265 uint i; 1266 1267 ctx = CALLOC_STRUCT(gen_mipmap_state); 1268 if (!ctx) 1269 return NULL; 1270 1271 ctx->pipe = pipe; 1272 ctx->cso = cso; 1273 1274 /* disabled blending/masking */ 1275 memset(&ctx->blend, 0, sizeof(ctx->blend)); 1276 ctx->blend.rt[0].colormask = PIPE_MASK_RGBA; 1277 1278 /* no-op depth/stencil/alpha */ 1279 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil)); 1280 1281 /* rasterizer */ 1282 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer)); 1283 ctx->rasterizer.cull_face = PIPE_FACE_NONE; 1284 ctx->rasterizer.gl_rasterization_rules = 1; 1285 ctx->rasterizer.depth_clip = 1; 1286 1287 /* sampler state */ 1288 memset(&ctx->sampler, 0, sizeof(ctx->sampler)); 1289 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 1290 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 1291 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 1292 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 1293 ctx->sampler.normalized_coords = 1; 1294 1295 /* vertex elements state */ 1296 memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2); 1297 for (i = 0; i < 2; i++) { 1298 ctx->velem[i].src_offset = i * 4 * sizeof(float); 1299 ctx->velem[i].instance_divisor = 0; 1300 ctx->velem[i].vertex_buffer_index = 0; 1301 ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 1302 } 1303 1304 /* vertex data that doesn't change */ 1305 for (i = 0; i < 4; i++) { 1306 ctx->vertices[i][0][2] = 0.0f; /* z */ 1307 ctx->vertices[i][0][3] = 1.0f; /* w */ 1308 ctx->vertices[i][1][3] = 1.0f; /* q */ 1309 } 1310 1311 /* Note: the actual vertex buffer is allocated as needed below */ 1312 1313 return ctx; 1314} 1315 1316 1317/** 1318 * Helper function to set the fragment shaders. 1319 */ 1320static INLINE void 1321set_fragment_shader(struct gen_mipmap_state *ctx, uint type) 1322{ 1323 if (!ctx->fs[type]) 1324 ctx->fs[type] = 1325 util_make_fragment_tex_shader(ctx->pipe, type, 1326 TGSI_INTERPOLATE_LINEAR); 1327 1328 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[type]); 1329} 1330 1331 1332/** 1333 * Helper function to set the vertex shader. 1334 */ 1335static INLINE void 1336set_vertex_shader(struct gen_mipmap_state *ctx) 1337{ 1338 /* vertex shader - still required to provide the linkage between 1339 * fragment shader input semantics and vertex_element/buffers. 1340 */ 1341 if (!ctx->vs) 1342 { 1343 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 1344 TGSI_SEMANTIC_GENERIC }; 1345 const uint semantic_indexes[] = { 0, 0 }; 1346 ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2, 1347 semantic_names, 1348 semantic_indexes); 1349 } 1350 1351 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 1352} 1353 1354 1355/** 1356 * Get next "slot" of vertex space in the vertex buffer. 1357 * We're allocating one large vertex buffer and using it piece by piece. 1358 */ 1359static unsigned 1360get_next_slot(struct gen_mipmap_state *ctx) 1361{ 1362 const unsigned max_slots = 4096 / sizeof ctx->vertices; 1363 1364 if (ctx->vbuf_slot >= max_slots) { 1365 pipe_resource_reference(&ctx->vbuf, NULL); 1366 ctx->vbuf_slot = 0; 1367 } 1368 1369 if (!ctx->vbuf) { 1370 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, 1371 PIPE_BIND_VERTEX_BUFFER, 1372 PIPE_USAGE_STREAM, 1373 max_slots * sizeof ctx->vertices); 1374 } 1375 1376 return ctx->vbuf_slot++ * sizeof ctx->vertices; 1377} 1378 1379 1380static unsigned 1381set_vertex_data(struct gen_mipmap_state *ctx, 1382 enum pipe_texture_target tex_target, 1383 uint layer, float r) 1384{ 1385 unsigned offset; 1386 1387 /* vert[0].position */ 1388 ctx->vertices[0][0][0] = -1.0f; /*x*/ 1389 ctx->vertices[0][0][1] = -1.0f; /*y*/ 1390 1391 /* vert[1].position */ 1392 ctx->vertices[1][0][0] = 1.0f; 1393 ctx->vertices[1][0][1] = -1.0f; 1394 1395 /* vert[2].position */ 1396 ctx->vertices[2][0][0] = 1.0f; 1397 ctx->vertices[2][0][1] = 1.0f; 1398 1399 /* vert[3].position */ 1400 ctx->vertices[3][0][0] = -1.0f; 1401 ctx->vertices[3][0][1] = 1.0f; 1402 1403 /* Setup vertex texcoords. This is a little tricky for cube maps. */ 1404 if (tex_target == PIPE_TEXTURE_CUBE) { 1405 static const float st[4][2] = { 1406 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} 1407 }; 1408 1409 util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2, 1410 &ctx->vertices[0][1][0], 8); 1411 } 1412 else if (tex_target == PIPE_TEXTURE_1D_ARRAY) { 1413 /* 1D texture array */ 1414 ctx->vertices[0][1][0] = 0.0f; /*s*/ 1415 ctx->vertices[0][1][1] = r; /*t*/ 1416 ctx->vertices[0][1][2] = 0.0f; /*r*/ 1417 1418 ctx->vertices[1][1][0] = 1.0f; 1419 ctx->vertices[1][1][1] = r; 1420 ctx->vertices[1][1][2] = 0.0f; 1421 1422 ctx->vertices[2][1][0] = 1.0f; 1423 ctx->vertices[2][1][1] = r; 1424 ctx->vertices[2][1][2] = 0.0f; 1425 1426 ctx->vertices[3][1][0] = 0.0f; 1427 ctx->vertices[3][1][1] = r; 1428 ctx->vertices[3][1][2] = 0.0f; 1429 } else { 1430 /* 1D/2D/3D/2D array */ 1431 ctx->vertices[0][1][0] = 0.0f; /*s*/ 1432 ctx->vertices[0][1][1] = 0.0f; /*t*/ 1433 ctx->vertices[0][1][2] = r; /*r*/ 1434 1435 ctx->vertices[1][1][0] = 1.0f; 1436 ctx->vertices[1][1][1] = 0.0f; 1437 ctx->vertices[1][1][2] = r; 1438 1439 ctx->vertices[2][1][0] = 1.0f; 1440 ctx->vertices[2][1][1] = 1.0f; 1441 ctx->vertices[2][1][2] = r; 1442 1443 ctx->vertices[3][1][0] = 0.0f; 1444 ctx->vertices[3][1][1] = 1.0f; 1445 ctx->vertices[3][1][2] = r; 1446 } 1447 1448 offset = get_next_slot( ctx ); 1449 1450 pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, 1451 offset, sizeof(ctx->vertices), ctx->vertices); 1452 1453 return offset; 1454} 1455 1456 1457 1458/** 1459 * Destroy a mipmap generation context 1460 */ 1461void 1462util_destroy_gen_mipmap(struct gen_mipmap_state *ctx) 1463{ 1464 struct pipe_context *pipe = ctx->pipe; 1465 unsigned i; 1466 1467 for (i = 0; i < Elements(ctx->fs); i++) 1468 if (ctx->fs[i]) 1469 pipe->delete_fs_state(pipe, ctx->fs[i]); 1470 1471 if (ctx->vs) 1472 pipe->delete_vs_state(pipe, ctx->vs); 1473 1474 pipe_resource_reference(&ctx->vbuf, NULL); 1475 1476 FREE(ctx); 1477} 1478 1479 1480/** 1481 * Generate mipmap images. It's assumed all needed texture memory is 1482 * already allocated. 1483 * 1484 * \param psv the sampler view to the texture to generate mipmap levels for 1485 * \param face which cube face to generate mipmaps for (0 for non-cube maps) 1486 * \param baseLevel the first mipmap level to use as a src 1487 * \param lastLevel the last mipmap level to generate 1488 * \param filter the minification filter used to generate mipmap levels with 1489 * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST 1490 */ 1491void 1492util_gen_mipmap(struct gen_mipmap_state *ctx, 1493 struct pipe_sampler_view *psv, 1494 uint face, uint baseLevel, uint lastLevel, uint filter) 1495{ 1496 struct pipe_context *pipe = ctx->pipe; 1497 struct pipe_screen *screen = pipe->screen; 1498 struct pipe_framebuffer_state fb; 1499 struct pipe_resource *pt = psv->texture; 1500 uint dstLevel; 1501 uint offset; 1502 uint type; 1503 1504 /* The texture object should have room for the levels which we're 1505 * about to generate. 1506 */ 1507 assert(lastLevel <= pt->last_level); 1508 1509 /* If this fails, why are we here? */ 1510 assert(lastLevel > baseLevel); 1511 1512 assert(filter == PIPE_TEX_FILTER_LINEAR || 1513 filter == PIPE_TEX_FILTER_NEAREST); 1514 1515 switch (pt->target) { 1516 case PIPE_TEXTURE_1D: 1517 type = TGSI_TEXTURE_1D; 1518 break; 1519 case PIPE_TEXTURE_2D: 1520 type = TGSI_TEXTURE_2D; 1521 break; 1522 case PIPE_TEXTURE_3D: 1523 type = TGSI_TEXTURE_3D; 1524 break; 1525 case PIPE_TEXTURE_CUBE: 1526 type = TGSI_TEXTURE_CUBE; 1527 break; 1528 case PIPE_TEXTURE_1D_ARRAY: 1529 type = TGSI_TEXTURE_1D_ARRAY; 1530 break; 1531 case PIPE_TEXTURE_2D_ARRAY: 1532 type = TGSI_TEXTURE_2D_ARRAY; 1533 break; 1534 default: 1535 assert(0); 1536 type = TGSI_TEXTURE_2D; 1537 } 1538 1539 /* check if we can render in the texture's format */ 1540 if (!screen->is_format_supported(screen, psv->format, pt->target, 1541 pt->nr_samples, PIPE_BIND_RENDER_TARGET)) { 1542 fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel); 1543 return; 1544 } 1545 1546 /* save state (restored below) */ 1547 cso_save_blend(ctx->cso); 1548 cso_save_depth_stencil_alpha(ctx->cso); 1549 cso_save_rasterizer(ctx->cso); 1550 cso_save_samplers(ctx->cso); 1551 cso_save_fragment_sampler_views(ctx->cso); 1552 cso_save_stream_outputs(ctx->cso); 1553 cso_save_framebuffer(ctx->cso); 1554 cso_save_fragment_shader(ctx->cso); 1555 cso_save_vertex_shader(ctx->cso); 1556 cso_save_geometry_shader(ctx->cso); 1557 cso_save_viewport(ctx->cso); 1558 cso_save_vertex_elements(ctx->cso); 1559 1560 /* bind our state */ 1561 cso_set_blend(ctx->cso, &ctx->blend); 1562 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); 1563 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 1564 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 1565 cso_set_stream_outputs(ctx->cso, 0, NULL, 0); 1566 1567 set_fragment_shader(ctx, type); 1568 set_vertex_shader(ctx); 1569 cso_set_geometry_shader_handle(ctx->cso, NULL); 1570 1571 /* init framebuffer state */ 1572 memset(&fb, 0, sizeof(fb)); 1573 fb.nr_cbufs = 1; 1574 1575 /* set min/mag to same filter for faster sw speed */ 1576 ctx->sampler.mag_img_filter = filter; 1577 ctx->sampler.min_img_filter = filter; 1578 1579 /* 1580 * XXX for small mipmap levels, it may be faster to use the software 1581 * fallback path... 1582 */ 1583 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 1584 const uint srcLevel = dstLevel - 1; 1585 struct pipe_viewport_state vp; 1586 unsigned nr_layers, layer, i; 1587 float rcoord = 0.0f; 1588 1589 if (pt->target == PIPE_TEXTURE_3D) 1590 nr_layers = u_minify(pt->depth0, dstLevel); 1591 else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) 1592 nr_layers = pt->array_size; 1593 else 1594 nr_layers = 1; 1595 1596 for (i = 0; i < nr_layers; i++) { 1597 struct pipe_surface *surf, surf_templ; 1598 if (pt->target == PIPE_TEXTURE_3D) { 1599 /* in theory with geom shaders and driver with full layer support 1600 could do that in one go. */ 1601 layer = i; 1602 /* XXX hmm really? */ 1603 rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2); 1604 } else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) { 1605 layer = i; 1606 rcoord = (float)layer; 1607 } else 1608 layer = face; 1609 1610 memset(&surf_templ, 0, sizeof(surf_templ)); 1611 u_surface_default_template(&surf_templ, pt, PIPE_BIND_RENDER_TARGET); 1612 surf_templ.u.tex.level = dstLevel; 1613 surf_templ.u.tex.first_layer = layer; 1614 surf_templ.u.tex.last_layer = layer; 1615 surf = pipe->create_surface(pipe, pt, &surf_templ); 1616 1617 /* 1618 * Setup framebuffer / dest surface 1619 */ 1620 fb.cbufs[0] = surf; 1621 fb.width = u_minify(pt->width0, dstLevel); 1622 fb.height = u_minify(pt->height0, dstLevel); 1623 cso_set_framebuffer(ctx->cso, &fb); 1624 1625 /* viewport */ 1626 vp.scale[0] = 0.5f * fb.width; 1627 vp.scale[1] = 0.5f * fb.height; 1628 vp.scale[2] = 1.0f; 1629 vp.scale[3] = 1.0f; 1630 vp.translate[0] = 0.5f * fb.width; 1631 vp.translate[1] = 0.5f * fb.height; 1632 vp.translate[2] = 0.0f; 1633 vp.translate[3] = 0.0f; 1634 cso_set_viewport(ctx->cso, &vp); 1635 1636 /* 1637 * Setup sampler state 1638 * Note: we should only have to set the min/max LOD clamps to ensure 1639 * we grab texels from the right mipmap level. But some hardware 1640 * has trouble with min clamping so we also set the lod_bias to 1641 * try to work around that. 1642 */ 1643 ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel; 1644 ctx->sampler.lod_bias = (float) srcLevel; 1645 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 1646 cso_single_sampler_done(ctx->cso); 1647 1648 cso_set_fragment_sampler_views(ctx->cso, 1, &psv); 1649 1650 /* quad coords in clip coords */ 1651 offset = set_vertex_data(ctx, 1652 pt->target, 1653 face, 1654 rcoord); 1655 1656 util_draw_vertex_buffer(ctx->pipe, 1657 ctx->cso, 1658 ctx->vbuf, 1659 offset, 1660 PIPE_PRIM_TRIANGLE_FAN, 1661 4, /* verts */ 1662 2); /* attribs/vert */ 1663 1664 /* need to signal that the texture has changed _after_ rendering to it */ 1665 pipe_surface_reference( &surf, NULL ); 1666 } 1667 } 1668 1669 /* restore state we changed */ 1670 cso_restore_blend(ctx->cso); 1671 cso_restore_depth_stencil_alpha(ctx->cso); 1672 cso_restore_rasterizer(ctx->cso); 1673 cso_restore_samplers(ctx->cso); 1674 cso_restore_fragment_sampler_views(ctx->cso); 1675 cso_restore_framebuffer(ctx->cso); 1676 cso_restore_fragment_shader(ctx->cso); 1677 cso_restore_vertex_shader(ctx->cso); 1678 cso_restore_geometry_shader(ctx->cso); 1679 cso_restore_viewport(ctx->cso); 1680 cso_restore_vertex_elements(ctx->cso); 1681 cso_restore_stream_outputs(ctx->cso); 1682} 1683