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