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