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