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