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