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