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