1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * \file mipmap.c mipmap generation and teximage resizing functions. 28848b8605Smrg */ 29848b8605Smrg 30b8e80941Smrg#include "errors.h" 31848b8605Smrg#include "imports.h" 32848b8605Smrg#include "formats.h" 33848b8605Smrg#include "glformats.h" 34848b8605Smrg#include "mipmap.h" 35848b8605Smrg#include "mtypes.h" 36848b8605Smrg#include "teximage.h" 37848b8605Smrg#include "texobj.h" 38848b8605Smrg#include "texstore.h" 39848b8605Smrg#include "image.h" 40848b8605Smrg#include "macros.h" 41b8e80941Smrg#include "util/half_float.h" 42b8e80941Smrg#include "util/format_rgb9e5.h" 43b8e80941Smrg#include "util/format_r11g11b10f.h" 44848b8605Smrg 45848b8605Smrg 46b8e80941Smrg/** 47b8e80941Smrg * Compute the expected number of mipmap levels in the texture given 48b8e80941Smrg * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/ 49b8e80941Smrg * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap 50b8e80941Smrg * levels should be generated. 51b8e80941Smrg */ 52b8e80941Smrgunsigned 53b8e80941Smrg_mesa_compute_num_levels(struct gl_context *ctx, 54b8e80941Smrg struct gl_texture_object *texObj, 55b8e80941Smrg GLenum target) 56b8e80941Smrg{ 57b8e80941Smrg const struct gl_texture_image *baseImage; 58b8e80941Smrg GLuint numLevels; 59b8e80941Smrg 60b8e80941Smrg baseImage = _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel); 61b8e80941Smrg 62b8e80941Smrg numLevels = texObj->BaseLevel + baseImage->MaxNumLevels; 63b8e80941Smrg numLevels = MIN2(numLevels, (GLuint) texObj->MaxLevel + 1); 64b8e80941Smrg if (texObj->Immutable) 65b8e80941Smrg numLevels = MIN2(numLevels, texObj->NumLevels); 66b8e80941Smrg assert(numLevels >= 1); 67b8e80941Smrg 68b8e80941Smrg return numLevels; 69b8e80941Smrg} 70848b8605Smrg 71848b8605Smrgstatic GLint 72848b8605Smrgbytes_per_pixel(GLenum datatype, GLuint comps) 73848b8605Smrg{ 74848b8605Smrg GLint b; 75848b8605Smrg 76848b8605Smrg if (datatype == GL_UNSIGNED_INT_8_24_REV_MESA || 77848b8605Smrg datatype == GL_UNSIGNED_INT_24_8_MESA) 78848b8605Smrg return 4; 79848b8605Smrg 80848b8605Smrg b = _mesa_sizeof_packed_type(datatype); 81848b8605Smrg assert(b >= 0); 82848b8605Smrg 83848b8605Smrg if (_mesa_type_is_packed(datatype)) 84848b8605Smrg return b; 85848b8605Smrg else 86848b8605Smrg return b * comps; 87848b8605Smrg} 88848b8605Smrg 89848b8605Smrg 90848b8605Smrg/** 91848b8605Smrg * \name Support macros for do_row and do_row_3d 92848b8605Smrg * 93848b8605Smrg * The macro madness is here for two reasons. First, it compacts the code 94848b8605Smrg * slightly. Second, it makes it much easier to adjust the specifics of the 95848b8605Smrg * filter to tune the rounding characteristics. 96848b8605Smrg */ 97848b8605Smrg/*@{*/ 98848b8605Smrg#define DECLARE_ROW_POINTERS(t, e) \ 99848b8605Smrg const t(*rowA)[e] = (const t(*)[e]) srcRowA; \ 100848b8605Smrg const t(*rowB)[e] = (const t(*)[e]) srcRowB; \ 101848b8605Smrg const t(*rowC)[e] = (const t(*)[e]) srcRowC; \ 102848b8605Smrg const t(*rowD)[e] = (const t(*)[e]) srcRowD; \ 103848b8605Smrg t(*dst)[e] = (t(*)[e]) dstRow 104848b8605Smrg 105848b8605Smrg#define DECLARE_ROW_POINTERS0(t) \ 106848b8605Smrg const t *rowA = (const t *) srcRowA; \ 107848b8605Smrg const t *rowB = (const t *) srcRowB; \ 108848b8605Smrg const t *rowC = (const t *) srcRowC; \ 109848b8605Smrg const t *rowD = (const t *) srcRowD; \ 110848b8605Smrg t *dst = (t *) dstRow 111848b8605Smrg 112848b8605Smrg#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ 113848b8605Smrg ((unsigned) Aj + (unsigned) Ak \ 114848b8605Smrg + (unsigned) Bj + (unsigned) Bk \ 115848b8605Smrg + (unsigned) Cj + (unsigned) Ck \ 116848b8605Smrg + (unsigned) Dj + (unsigned) Dk \ 117848b8605Smrg + 4) >> 3 118848b8605Smrg 119848b8605Smrg#define FILTER_3D(e) \ 120848b8605Smrg do { \ 121848b8605Smrg dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \ 122848b8605Smrg rowB[j][e], rowB[k][e], \ 123848b8605Smrg rowC[j][e], rowC[k][e], \ 124848b8605Smrg rowD[j][e], rowD[k][e]); \ 125848b8605Smrg } while(0) 126848b8605Smrg 127848b8605Smrg#define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ 128848b8605Smrg (Aj + Ak \ 129848b8605Smrg + Bj + Bk \ 130848b8605Smrg + Cj + Ck \ 131848b8605Smrg + Dj + Dk \ 132848b8605Smrg + 4) / 8 133848b8605Smrg 134848b8605Smrg#define FILTER_3D_SIGNED(e) \ 135848b8605Smrg do { \ 136848b8605Smrg dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \ 137848b8605Smrg rowB[j][e], rowB[k][e], \ 138848b8605Smrg rowC[j][e], rowC[k][e], \ 139848b8605Smrg rowD[j][e], rowD[k][e]); \ 140848b8605Smrg } while(0) 141848b8605Smrg 142848b8605Smrg#define FILTER_F_3D(e) \ 143848b8605Smrg do { \ 144848b8605Smrg dst[i][e] = (rowA[j][e] + rowA[k][e] \ 145848b8605Smrg + rowB[j][e] + rowB[k][e] \ 146848b8605Smrg + rowC[j][e] + rowC[k][e] \ 147848b8605Smrg + rowD[j][e] + rowD[k][e]) * 0.125F; \ 148848b8605Smrg } while(0) 149848b8605Smrg 150848b8605Smrg#define FILTER_HF_3D(e) \ 151848b8605Smrg do { \ 152848b8605Smrg const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \ 153848b8605Smrg const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \ 154848b8605Smrg const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \ 155848b8605Smrg const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \ 156848b8605Smrg const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \ 157848b8605Smrg const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \ 158848b8605Smrg const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \ 159848b8605Smrg const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \ 160848b8605Smrg dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \ 161848b8605Smrg * 0.125F); \ 162848b8605Smrg } while(0) 163848b8605Smrg/*@}*/ 164848b8605Smrg 165848b8605Smrg 166848b8605Smrg/** 167848b8605Smrg * Average together two rows of a source image to produce a single new 168848b8605Smrg * row in the dest image. It's legal for the two source rows to point 169848b8605Smrg * to the same data. The source width must be equal to either the 170848b8605Smrg * dest width or two times the dest width. 171848b8605Smrg * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc. 172848b8605Smrg * \param comps number of components per pixel (1..4) 173848b8605Smrg */ 174848b8605Smrgstatic void 175848b8605Smrgdo_row(GLenum datatype, GLuint comps, GLint srcWidth, 176848b8605Smrg const GLvoid *srcRowA, const GLvoid *srcRowB, 177848b8605Smrg GLint dstWidth, GLvoid *dstRow) 178848b8605Smrg{ 179848b8605Smrg const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; 180848b8605Smrg const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; 181848b8605Smrg 182b8e80941Smrg assert(comps >= 1); 183b8e80941Smrg assert(comps <= 4); 184848b8605Smrg 185848b8605Smrg /* This assertion is no longer valid with non-power-of-2 textures 186848b8605Smrg assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); 187848b8605Smrg */ 188848b8605Smrg 189848b8605Smrg if (datatype == GL_UNSIGNED_BYTE && comps == 4) { 190848b8605Smrg GLuint i, j, k; 191848b8605Smrg const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA; 192848b8605Smrg const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB; 193848b8605Smrg GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow; 194848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 195848b8605Smrg i++, j += colStride, k += colStride) { 196848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 197848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 198848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 199848b8605Smrg dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 200848b8605Smrg } 201848b8605Smrg } 202848b8605Smrg else if (datatype == GL_UNSIGNED_BYTE && comps == 3) { 203848b8605Smrg GLuint i, j, k; 204848b8605Smrg const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA; 205848b8605Smrg const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB; 206848b8605Smrg GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow; 207848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 208848b8605Smrg i++, j += colStride, k += colStride) { 209848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 210848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 211848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 212848b8605Smrg } 213848b8605Smrg } 214848b8605Smrg else if (datatype == GL_UNSIGNED_BYTE && comps == 2) { 215848b8605Smrg GLuint i, j, k; 216848b8605Smrg const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA; 217848b8605Smrg const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB; 218848b8605Smrg GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow; 219848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 220848b8605Smrg i++, j += colStride, k += colStride) { 221848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2; 222848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2; 223848b8605Smrg } 224848b8605Smrg } 225848b8605Smrg else if (datatype == GL_UNSIGNED_BYTE && comps == 1) { 226848b8605Smrg GLuint i, j, k; 227848b8605Smrg const GLubyte *rowA = (const GLubyte *) srcRowA; 228848b8605Smrg const GLubyte *rowB = (const GLubyte *) srcRowB; 229848b8605Smrg GLubyte *dst = (GLubyte *) dstRow; 230848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 231848b8605Smrg i++, j += colStride, k += colStride) { 232848b8605Smrg dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; 233848b8605Smrg } 234848b8605Smrg } 235848b8605Smrg 236848b8605Smrg else if (datatype == GL_BYTE && comps == 4) { 237848b8605Smrg GLuint i, j, k; 238848b8605Smrg const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA; 239848b8605Smrg const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB; 240848b8605Smrg GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow; 241848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 242848b8605Smrg i++, j += colStride, k += colStride) { 243848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 244848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 245848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 246848b8605Smrg dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 247848b8605Smrg } 248848b8605Smrg } 249848b8605Smrg else if (datatype == GL_BYTE && comps == 3) { 250848b8605Smrg GLuint i, j, k; 251848b8605Smrg const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA; 252848b8605Smrg const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB; 253848b8605Smrg GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow; 254848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 255848b8605Smrg i++, j += colStride, k += colStride) { 256848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 257848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 258848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 259848b8605Smrg } 260848b8605Smrg } 261848b8605Smrg else if (datatype == GL_BYTE && comps == 2) { 262848b8605Smrg GLuint i, j, k; 263848b8605Smrg const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA; 264848b8605Smrg const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB; 265848b8605Smrg GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow; 266848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 267848b8605Smrg i++, j += colStride, k += colStride) { 268848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 269848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 270848b8605Smrg } 271848b8605Smrg } 272848b8605Smrg else if (datatype == GL_BYTE && comps == 1) { 273848b8605Smrg GLuint i, j, k; 274848b8605Smrg const GLbyte *rowA = (const GLbyte *) srcRowA; 275848b8605Smrg const GLbyte *rowB = (const GLbyte *) srcRowB; 276848b8605Smrg GLbyte *dst = (GLbyte *) dstRow; 277848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 278848b8605Smrg i++, j += colStride, k += colStride) { 279848b8605Smrg dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 280848b8605Smrg } 281848b8605Smrg } 282848b8605Smrg 283848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT && comps == 4) { 284848b8605Smrg GLuint i, j, k; 285848b8605Smrg const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA; 286848b8605Smrg const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB; 287848b8605Smrg GLushort(*dst)[4] = (GLushort(*)[4]) dstRow; 288848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 289848b8605Smrg i++, j += colStride, k += colStride) { 290848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 291848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 292848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 293848b8605Smrg dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 294848b8605Smrg } 295848b8605Smrg } 296848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT && comps == 3) { 297848b8605Smrg GLuint i, j, k; 298848b8605Smrg const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA; 299848b8605Smrg const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB; 300848b8605Smrg GLushort(*dst)[3] = (GLushort(*)[3]) dstRow; 301848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 302848b8605Smrg i++, j += colStride, k += colStride) { 303848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 304848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 305848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 306848b8605Smrg } 307848b8605Smrg } 308848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT && comps == 2) { 309848b8605Smrg GLuint i, j, k; 310848b8605Smrg const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA; 311848b8605Smrg const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB; 312848b8605Smrg GLushort(*dst)[2] = (GLushort(*)[2]) dstRow; 313848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 314848b8605Smrg i++, j += colStride, k += colStride) { 315848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 316848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 317848b8605Smrg } 318848b8605Smrg } 319848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT && comps == 1) { 320848b8605Smrg GLuint i, j, k; 321848b8605Smrg const GLushort *rowA = (const GLushort *) srcRowA; 322848b8605Smrg const GLushort *rowB = (const GLushort *) srcRowB; 323848b8605Smrg GLushort *dst = (GLushort *) dstRow; 324848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 325848b8605Smrg i++, j += colStride, k += colStride) { 326848b8605Smrg dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 327848b8605Smrg } 328848b8605Smrg } 329848b8605Smrg 330848b8605Smrg else if (datatype == GL_SHORT && comps == 4) { 331848b8605Smrg GLuint i, j, k; 332848b8605Smrg const GLshort(*rowA)[4] = (const GLshort(*)[4]) srcRowA; 333848b8605Smrg const GLshort(*rowB)[4] = (const GLshort(*)[4]) srcRowB; 334848b8605Smrg GLshort(*dst)[4] = (GLshort(*)[4]) dstRow; 335848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 336848b8605Smrg i++, j += colStride, k += colStride) { 337848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 338848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 339848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 340848b8605Smrg dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 341848b8605Smrg } 342848b8605Smrg } 343848b8605Smrg else if (datatype == GL_SHORT && comps == 3) { 344848b8605Smrg GLuint i, j, k; 345848b8605Smrg const GLshort(*rowA)[3] = (const GLshort(*)[3]) srcRowA; 346848b8605Smrg const GLshort(*rowB)[3] = (const GLshort(*)[3]) srcRowB; 347848b8605Smrg GLshort(*dst)[3] = (GLshort(*)[3]) dstRow; 348848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 349848b8605Smrg i++, j += colStride, k += colStride) { 350848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 351848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 352848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 353848b8605Smrg } 354848b8605Smrg } 355848b8605Smrg else if (datatype == GL_SHORT && comps == 2) { 356848b8605Smrg GLuint i, j, k; 357848b8605Smrg const GLshort(*rowA)[2] = (const GLshort(*)[2]) srcRowA; 358848b8605Smrg const GLshort(*rowB)[2] = (const GLshort(*)[2]) srcRowB; 359848b8605Smrg GLshort(*dst)[2] = (GLshort(*)[2]) dstRow; 360848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 361848b8605Smrg i++, j += colStride, k += colStride) { 362848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 363848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 364848b8605Smrg } 365848b8605Smrg } 366848b8605Smrg else if (datatype == GL_SHORT && comps == 1) { 367848b8605Smrg GLuint i, j, k; 368848b8605Smrg const GLshort *rowA = (const GLshort *) srcRowA; 369848b8605Smrg const GLshort *rowB = (const GLshort *) srcRowB; 370848b8605Smrg GLshort *dst = (GLshort *) dstRow; 371848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 372848b8605Smrg i++, j += colStride, k += colStride) { 373848b8605Smrg dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 374848b8605Smrg } 375848b8605Smrg } 376848b8605Smrg 377848b8605Smrg else if (datatype == GL_FLOAT && comps == 4) { 378848b8605Smrg GLuint i, j, k; 379848b8605Smrg const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA; 380848b8605Smrg const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB; 381848b8605Smrg GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow; 382848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 383848b8605Smrg i++, j += colStride, k += colStride) { 384848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + 385848b8605Smrg rowB[j][0] + rowB[k][0]) * 0.25F; 386848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + 387848b8605Smrg rowB[j][1] + rowB[k][1]) * 0.25F; 388848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + 389848b8605Smrg rowB[j][2] + rowB[k][2]) * 0.25F; 390848b8605Smrg dst[i][3] = (rowA[j][3] + rowA[k][3] + 391848b8605Smrg rowB[j][3] + rowB[k][3]) * 0.25F; 392848b8605Smrg } 393848b8605Smrg } 394848b8605Smrg else if (datatype == GL_FLOAT && comps == 3) { 395848b8605Smrg GLuint i, j, k; 396848b8605Smrg const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA; 397848b8605Smrg const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB; 398848b8605Smrg GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow; 399848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 400848b8605Smrg i++, j += colStride, k += colStride) { 401848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + 402848b8605Smrg rowB[j][0] + rowB[k][0]) * 0.25F; 403848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + 404848b8605Smrg rowB[j][1] + rowB[k][1]) * 0.25F; 405848b8605Smrg dst[i][2] = (rowA[j][2] + rowA[k][2] + 406848b8605Smrg rowB[j][2] + rowB[k][2]) * 0.25F; 407848b8605Smrg } 408848b8605Smrg } 409848b8605Smrg else if (datatype == GL_FLOAT && comps == 2) { 410848b8605Smrg GLuint i, j, k; 411848b8605Smrg const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA; 412848b8605Smrg const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB; 413848b8605Smrg GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow; 414848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 415848b8605Smrg i++, j += colStride, k += colStride) { 416848b8605Smrg dst[i][0] = (rowA[j][0] + rowA[k][0] + 417848b8605Smrg rowB[j][0] + rowB[k][0]) * 0.25F; 418848b8605Smrg dst[i][1] = (rowA[j][1] + rowA[k][1] + 419848b8605Smrg rowB[j][1] + rowB[k][1]) * 0.25F; 420848b8605Smrg } 421848b8605Smrg } 422848b8605Smrg else if (datatype == GL_FLOAT && comps == 1) { 423848b8605Smrg GLuint i, j, k; 424848b8605Smrg const GLfloat *rowA = (const GLfloat *) srcRowA; 425848b8605Smrg const GLfloat *rowB = (const GLfloat *) srcRowB; 426848b8605Smrg GLfloat *dst = (GLfloat *) dstRow; 427848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 428848b8605Smrg i++, j += colStride, k += colStride) { 429848b8605Smrg dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; 430848b8605Smrg } 431848b8605Smrg } 432848b8605Smrg 433848b8605Smrg else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) { 434848b8605Smrg GLuint i, j, k, comp; 435848b8605Smrg const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA; 436848b8605Smrg const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB; 437848b8605Smrg GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow; 438848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 439848b8605Smrg i++, j += colStride, k += colStride) { 440848b8605Smrg for (comp = 0; comp < 4; comp++) { 441848b8605Smrg GLfloat aj, ak, bj, bk; 442848b8605Smrg aj = _mesa_half_to_float(rowA[j][comp]); 443848b8605Smrg ak = _mesa_half_to_float(rowA[k][comp]); 444848b8605Smrg bj = _mesa_half_to_float(rowB[j][comp]); 445848b8605Smrg bk = _mesa_half_to_float(rowB[k][comp]); 446848b8605Smrg dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 447848b8605Smrg } 448848b8605Smrg } 449848b8605Smrg } 450848b8605Smrg else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) { 451848b8605Smrg GLuint i, j, k, comp; 452848b8605Smrg const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA; 453848b8605Smrg const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB; 454848b8605Smrg GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow; 455848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 456848b8605Smrg i++, j += colStride, k += colStride) { 457848b8605Smrg for (comp = 0; comp < 3; comp++) { 458848b8605Smrg GLfloat aj, ak, bj, bk; 459848b8605Smrg aj = _mesa_half_to_float(rowA[j][comp]); 460848b8605Smrg ak = _mesa_half_to_float(rowA[k][comp]); 461848b8605Smrg bj = _mesa_half_to_float(rowB[j][comp]); 462848b8605Smrg bk = _mesa_half_to_float(rowB[k][comp]); 463848b8605Smrg dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 464848b8605Smrg } 465848b8605Smrg } 466848b8605Smrg } 467848b8605Smrg else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) { 468848b8605Smrg GLuint i, j, k, comp; 469848b8605Smrg const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA; 470848b8605Smrg const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB; 471848b8605Smrg GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow; 472848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 473848b8605Smrg i++, j += colStride, k += colStride) { 474848b8605Smrg for (comp = 0; comp < 2; comp++) { 475848b8605Smrg GLfloat aj, ak, bj, bk; 476848b8605Smrg aj = _mesa_half_to_float(rowA[j][comp]); 477848b8605Smrg ak = _mesa_half_to_float(rowA[k][comp]); 478848b8605Smrg bj = _mesa_half_to_float(rowB[j][comp]); 479848b8605Smrg bk = _mesa_half_to_float(rowB[k][comp]); 480848b8605Smrg dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 481848b8605Smrg } 482848b8605Smrg } 483848b8605Smrg } 484848b8605Smrg else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) { 485848b8605Smrg GLuint i, j, k; 486848b8605Smrg const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; 487848b8605Smrg const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; 488848b8605Smrg GLhalfARB *dst = (GLhalfARB *) dstRow; 489848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 490848b8605Smrg i++, j += colStride, k += colStride) { 491848b8605Smrg GLfloat aj, ak, bj, bk; 492848b8605Smrg aj = _mesa_half_to_float(rowA[j]); 493848b8605Smrg ak = _mesa_half_to_float(rowA[k]); 494848b8605Smrg bj = _mesa_half_to_float(rowB[j]); 495848b8605Smrg bk = _mesa_half_to_float(rowB[k]); 496848b8605Smrg dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 497848b8605Smrg } 498848b8605Smrg } 499848b8605Smrg 500848b8605Smrg else if (datatype == GL_UNSIGNED_INT && comps == 1) { 501848b8605Smrg GLuint i, j, k; 502848b8605Smrg const GLuint *rowA = (const GLuint *) srcRowA; 503848b8605Smrg const GLuint *rowB = (const GLuint *) srcRowB; 504848b8605Smrg GLuint *dst = (GLuint *) dstRow; 505848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 506848b8605Smrg i++, j += colStride, k += colStride) { 507848b8605Smrg dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4; 508848b8605Smrg } 509848b8605Smrg } 510848b8605Smrg 511848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) { 512848b8605Smrg GLuint i, j, k; 513848b8605Smrg const GLushort *rowA = (const GLushort *) srcRowA; 514848b8605Smrg const GLushort *rowB = (const GLushort *) srcRowB; 515848b8605Smrg GLushort *dst = (GLushort *) dstRow; 516848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 517848b8605Smrg i++, j += colStride, k += colStride) { 518848b8605Smrg const GLint rowAr0 = rowA[j] & 0x1f; 519848b8605Smrg const GLint rowAr1 = rowA[k] & 0x1f; 520848b8605Smrg const GLint rowBr0 = rowB[j] & 0x1f; 521848b8605Smrg const GLint rowBr1 = rowB[k] & 0x1f; 522848b8605Smrg const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; 523848b8605Smrg const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; 524848b8605Smrg const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; 525848b8605Smrg const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; 526848b8605Smrg const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; 527848b8605Smrg const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; 528848b8605Smrg const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; 529848b8605Smrg const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; 530848b8605Smrg const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 531848b8605Smrg const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 532848b8605Smrg const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 533848b8605Smrg dst[i] = (blue << 11) | (green << 5) | red; 534848b8605Smrg } 535848b8605Smrg } 536848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) { 537848b8605Smrg GLuint i, j, k; 538848b8605Smrg const GLushort *rowA = (const GLushort *) srcRowA; 539848b8605Smrg const GLushort *rowB = (const GLushort *) srcRowB; 540848b8605Smrg GLushort *dst = (GLushort *) dstRow; 541848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 542848b8605Smrg i++, j += colStride, k += colStride) { 543848b8605Smrg const GLint rowAr0 = rowA[j] & 0xf; 544848b8605Smrg const GLint rowAr1 = rowA[k] & 0xf; 545848b8605Smrg const GLint rowBr0 = rowB[j] & 0xf; 546848b8605Smrg const GLint rowBr1 = rowB[k] & 0xf; 547848b8605Smrg const GLint rowAg0 = (rowA[j] >> 4) & 0xf; 548848b8605Smrg const GLint rowAg1 = (rowA[k] >> 4) & 0xf; 549848b8605Smrg const GLint rowBg0 = (rowB[j] >> 4) & 0xf; 550848b8605Smrg const GLint rowBg1 = (rowB[k] >> 4) & 0xf; 551848b8605Smrg const GLint rowAb0 = (rowA[j] >> 8) & 0xf; 552848b8605Smrg const GLint rowAb1 = (rowA[k] >> 8) & 0xf; 553848b8605Smrg const GLint rowBb0 = (rowB[j] >> 8) & 0xf; 554848b8605Smrg const GLint rowBb1 = (rowB[k] >> 8) & 0xf; 555848b8605Smrg const GLint rowAa0 = (rowA[j] >> 12) & 0xf; 556848b8605Smrg const GLint rowAa1 = (rowA[k] >> 12) & 0xf; 557848b8605Smrg const GLint rowBa0 = (rowB[j] >> 12) & 0xf; 558848b8605Smrg const GLint rowBa1 = (rowB[k] >> 12) & 0xf; 559848b8605Smrg const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 560848b8605Smrg const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 561848b8605Smrg const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 562848b8605Smrg const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 563848b8605Smrg dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; 564848b8605Smrg } 565848b8605Smrg } 566848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) { 567848b8605Smrg GLuint i, j, k; 568848b8605Smrg const GLushort *rowA = (const GLushort *) srcRowA; 569848b8605Smrg const GLushort *rowB = (const GLushort *) srcRowB; 570848b8605Smrg GLushort *dst = (GLushort *) dstRow; 571848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 572848b8605Smrg i++, j += colStride, k += colStride) { 573848b8605Smrg const GLint rowAr0 = rowA[j] & 0x1f; 574848b8605Smrg const GLint rowAr1 = rowA[k] & 0x1f; 575848b8605Smrg const GLint rowBr0 = rowB[j] & 0x1f; 576848b8605Smrg const GLint rowBr1 = rowB[k] & 0x1f; 577848b8605Smrg const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; 578848b8605Smrg const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; 579848b8605Smrg const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; 580848b8605Smrg const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; 581848b8605Smrg const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; 582848b8605Smrg const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; 583848b8605Smrg const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; 584848b8605Smrg const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; 585848b8605Smrg const GLint rowAa0 = (rowA[j] >> 15) & 0x1; 586848b8605Smrg const GLint rowAa1 = (rowA[k] >> 15) & 0x1; 587848b8605Smrg const GLint rowBa0 = (rowB[j] >> 15) & 0x1; 588848b8605Smrg const GLint rowBa1 = (rowB[k] >> 15) & 0x1; 589848b8605Smrg const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 590848b8605Smrg const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 591848b8605Smrg const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 592848b8605Smrg const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 593848b8605Smrg dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; 594848b8605Smrg } 595848b8605Smrg } 596848b8605Smrg else if (datatype == GL_UNSIGNED_SHORT_5_5_5_1 && comps == 4) { 597848b8605Smrg GLuint i, j, k; 598848b8605Smrg const GLushort *rowA = (const GLushort *) srcRowA; 599848b8605Smrg const GLushort *rowB = (const GLushort *) srcRowB; 600848b8605Smrg GLushort *dst = (GLushort *) dstRow; 601848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 602848b8605Smrg i++, j += colStride, k += colStride) { 603848b8605Smrg const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; 604848b8605Smrg const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; 605848b8605Smrg const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; 606848b8605Smrg const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; 607848b8605Smrg const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; 608848b8605Smrg const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; 609848b8605Smrg const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; 610848b8605Smrg const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; 611848b8605Smrg const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; 612848b8605Smrg const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; 613848b8605Smrg const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; 614848b8605Smrg const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; 615848b8605Smrg const GLint rowAa0 = (rowA[j] & 0x1); 616848b8605Smrg const GLint rowAa1 = (rowA[k] & 0x1); 617848b8605Smrg const GLint rowBa0 = (rowB[j] & 0x1); 618848b8605Smrg const GLint rowBa1 = (rowB[k] & 0x1); 619848b8605Smrg const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 620848b8605Smrg const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 621848b8605Smrg const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 622848b8605Smrg const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 623848b8605Smrg dst[i] = (red << 11) | (green << 6) | (blue << 1) | alpha; 624848b8605Smrg } 625848b8605Smrg } 626848b8605Smrg 627848b8605Smrg else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) { 628848b8605Smrg GLuint i, j, k; 629848b8605Smrg const GLubyte *rowA = (const GLubyte *) srcRowA; 630848b8605Smrg const GLubyte *rowB = (const GLubyte *) srcRowB; 631848b8605Smrg GLubyte *dst = (GLubyte *) dstRow; 632848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 633848b8605Smrg i++, j += colStride, k += colStride) { 634848b8605Smrg const GLint rowAr0 = rowA[j] & 0x3; 635848b8605Smrg const GLint rowAr1 = rowA[k] & 0x3; 636848b8605Smrg const GLint rowBr0 = rowB[j] & 0x3; 637848b8605Smrg const GLint rowBr1 = rowB[k] & 0x3; 638848b8605Smrg const GLint rowAg0 = (rowA[j] >> 2) & 0x7; 639848b8605Smrg const GLint rowAg1 = (rowA[k] >> 2) & 0x7; 640848b8605Smrg const GLint rowBg0 = (rowB[j] >> 2) & 0x7; 641848b8605Smrg const GLint rowBg1 = (rowB[k] >> 2) & 0x7; 642848b8605Smrg const GLint rowAb0 = (rowA[j] >> 5) & 0x7; 643848b8605Smrg const GLint rowAb1 = (rowA[k] >> 5) & 0x7; 644848b8605Smrg const GLint rowBb0 = (rowB[j] >> 5) & 0x7; 645848b8605Smrg const GLint rowBb1 = (rowB[k] >> 5) & 0x7; 646848b8605Smrg const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 647848b8605Smrg const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 648848b8605Smrg const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 649848b8605Smrg dst[i] = (blue << 5) | (green << 2) | red; 650848b8605Smrg } 651848b8605Smrg } 652848b8605Smrg 653848b8605Smrg else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { 654848b8605Smrg GLuint i, j, k; 655848b8605Smrg const GLubyte *rowA = (const GLubyte *) srcRowA; 656848b8605Smrg const GLubyte *rowB = (const GLubyte *) srcRowB; 657848b8605Smrg GLubyte *dst = (GLubyte *) dstRow; 658848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 659848b8605Smrg i++, j += colStride, k += colStride) { 660848b8605Smrg const GLint rowAr0 = rowA[j] & 0xf; 661848b8605Smrg const GLint rowAr1 = rowA[k] & 0xf; 662848b8605Smrg const GLint rowBr0 = rowB[j] & 0xf; 663848b8605Smrg const GLint rowBr1 = rowB[k] & 0xf; 664848b8605Smrg const GLint rowAg0 = (rowA[j] >> 4) & 0xf; 665848b8605Smrg const GLint rowAg1 = (rowA[k] >> 4) & 0xf; 666848b8605Smrg const GLint rowBg0 = (rowB[j] >> 4) & 0xf; 667848b8605Smrg const GLint rowBg1 = (rowB[k] >> 4) & 0xf; 668848b8605Smrg const GLint r = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 669848b8605Smrg const GLint g = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 670848b8605Smrg dst[i] = (g << 4) | r; 671848b8605Smrg } 672848b8605Smrg } 673848b8605Smrg 674848b8605Smrg else if (datatype == GL_UNSIGNED_INT_2_10_10_10_REV && comps == 4) { 675848b8605Smrg GLuint i, j, k; 676848b8605Smrg const GLuint *rowA = (const GLuint *) srcRowA; 677848b8605Smrg const GLuint *rowB = (const GLuint *) srcRowB; 678848b8605Smrg GLuint *dst = (GLuint *) dstRow; 679848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 680848b8605Smrg i++, j += colStride, k += colStride) { 681848b8605Smrg const GLint rowAr0 = rowA[j] & 0x3ff; 682848b8605Smrg const GLint rowAr1 = rowA[k] & 0x3ff; 683848b8605Smrg const GLint rowBr0 = rowB[j] & 0x3ff; 684848b8605Smrg const GLint rowBr1 = rowB[k] & 0x3ff; 685848b8605Smrg const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff; 686848b8605Smrg const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff; 687848b8605Smrg const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff; 688848b8605Smrg const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff; 689848b8605Smrg const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff; 690848b8605Smrg const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff; 691848b8605Smrg const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff; 692848b8605Smrg const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff; 693848b8605Smrg const GLint rowAa0 = (rowA[j] >> 30) & 0x3; 694848b8605Smrg const GLint rowAa1 = (rowA[k] >> 30) & 0x3; 695848b8605Smrg const GLint rowBa0 = (rowB[j] >> 30) & 0x3; 696848b8605Smrg const GLint rowBa1 = (rowB[k] >> 30) & 0x3; 697848b8605Smrg const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 698848b8605Smrg const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 699848b8605Smrg const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 700848b8605Smrg const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 701848b8605Smrg dst[i] = (alpha << 30) | (blue << 20) | (green << 10) | red; 702848b8605Smrg } 703848b8605Smrg } 704848b8605Smrg 705848b8605Smrg else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { 706848b8605Smrg GLuint i, j, k; 707848b8605Smrg const GLuint *rowA = (const GLuint*) srcRowA; 708848b8605Smrg const GLuint *rowB = (const GLuint*) srcRowB; 709848b8605Smrg GLuint *dst = (GLuint*)dstRow; 710848b8605Smrg GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3]; 711848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 712848b8605Smrg i++, j += colStride, k += colStride) { 713848b8605Smrg rgb9e5_to_float3(rowA[j], rowAj); 714848b8605Smrg rgb9e5_to_float3(rowB[j], rowBj); 715848b8605Smrg rgb9e5_to_float3(rowA[k], rowAk); 716848b8605Smrg rgb9e5_to_float3(rowB[k], rowBk); 717848b8605Smrg res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F; 718848b8605Smrg res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F; 719848b8605Smrg res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F; 720848b8605Smrg dst[i] = float3_to_rgb9e5(res); 721848b8605Smrg } 722848b8605Smrg } 723848b8605Smrg 724848b8605Smrg else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) { 725848b8605Smrg GLuint i, j, k; 726848b8605Smrg const GLuint *rowA = (const GLuint*) srcRowA; 727848b8605Smrg const GLuint *rowB = (const GLuint*) srcRowB; 728848b8605Smrg GLuint *dst = (GLuint*)dstRow; 729848b8605Smrg GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3]; 730848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 731848b8605Smrg i++, j += colStride, k += colStride) { 732848b8605Smrg r11g11b10f_to_float3(rowA[j], rowAj); 733848b8605Smrg r11g11b10f_to_float3(rowB[j], rowBj); 734848b8605Smrg r11g11b10f_to_float3(rowA[k], rowAk); 735848b8605Smrg r11g11b10f_to_float3(rowB[k], rowBk); 736848b8605Smrg res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F; 737848b8605Smrg res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F; 738848b8605Smrg res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F; 739848b8605Smrg dst[i] = float3_to_r11g11b10f(res); 740848b8605Smrg } 741848b8605Smrg } 742848b8605Smrg 743848b8605Smrg else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) { 744848b8605Smrg GLuint i, j, k; 745848b8605Smrg const GLfloat *rowA = (const GLfloat *) srcRowA; 746848b8605Smrg const GLfloat *rowB = (const GLfloat *) srcRowB; 747848b8605Smrg GLfloat *dst = (GLfloat *) dstRow; 748848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 749848b8605Smrg i++, j += colStride, k += colStride) { 750848b8605Smrg dst[i*2] = (rowA[j*2] + rowA[k*2] + rowB[j*2] + rowB[k*2]) * 0.25F; 751848b8605Smrg } 752848b8605Smrg } 753848b8605Smrg 754848b8605Smrg else if (datatype == GL_UNSIGNED_INT_24_8_MESA && comps == 2) { 755848b8605Smrg GLuint i, j, k; 756848b8605Smrg const GLuint *rowA = (const GLuint *) srcRowA; 757848b8605Smrg const GLuint *rowB = (const GLuint *) srcRowB; 758848b8605Smrg GLuint *dst = (GLuint *) dstRow; 759848b8605Smrg /* note: averaging stencil values seems weird, but what else? */ 760848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 761848b8605Smrg i++, j += colStride, k += colStride) { 762848b8605Smrg GLuint z = (((rowA[j] >> 8) + (rowA[k] >> 8) + 763848b8605Smrg (rowB[j] >> 8) + (rowB[k] >> 8)) / 4) << 8; 764848b8605Smrg GLuint s = ((rowA[j] & 0xff) + (rowA[k] & 0xff) + 765848b8605Smrg (rowB[j] & 0xff) + (rowB[k] & 0xff)) / 4; 766848b8605Smrg dst[i] = z | s; 767848b8605Smrg } 768848b8605Smrg } 769848b8605Smrg else if (datatype == GL_UNSIGNED_INT_8_24_REV_MESA && comps == 2) { 770848b8605Smrg GLuint i, j, k; 771848b8605Smrg const GLuint *rowA = (const GLuint *) srcRowA; 772848b8605Smrg const GLuint *rowB = (const GLuint *) srcRowB; 773848b8605Smrg GLuint *dst = (GLuint *) dstRow; 774848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 775848b8605Smrg i++, j += colStride, k += colStride) { 776848b8605Smrg GLuint z = ((rowA[j] & 0xffffff) + (rowA[k] & 0xffffff) + 777848b8605Smrg (rowB[j] & 0xffffff) + (rowB[k] & 0xffffff)) / 4; 778848b8605Smrg GLuint s = (((rowA[j] >> 24) + (rowA[k] >> 24) + 779848b8605Smrg (rowB[j] >> 24) + (rowB[k] >> 24)) / 4) << 24; 780848b8605Smrg dst[i] = z | s; 781848b8605Smrg } 782848b8605Smrg } 783848b8605Smrg 784848b8605Smrg else { 785b8e80941Smrg unreachable("bad format in do_row()"); 786848b8605Smrg } 787848b8605Smrg} 788848b8605Smrg 789848b8605Smrg 790848b8605Smrg/** 791848b8605Smrg * Average together four rows of a source image to produce a single new 792848b8605Smrg * row in the dest image. It's legal for the two source rows to point 793848b8605Smrg * to the same data. The source width must be equal to either the 794848b8605Smrg * dest width or two times the dest width. 795848b8605Smrg * 796848b8605Smrg * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, 797848b8605Smrg * \c GL_FLOAT, etc. 798848b8605Smrg * \param comps number of components per pixel (1..4) 799848b8605Smrg * \param srcWidth Width of a row in the source data 800848b8605Smrg * \param srcRowA Pointer to one of the rows of source data 801848b8605Smrg * \param srcRowB Pointer to one of the rows of source data 802848b8605Smrg * \param srcRowC Pointer to one of the rows of source data 803848b8605Smrg * \param srcRowD Pointer to one of the rows of source data 804848b8605Smrg * \param dstWidth Width of a row in the destination data 805848b8605Smrg * \param srcRowA Pointer to the row of destination data 806848b8605Smrg */ 807848b8605Smrgstatic void 808848b8605Smrgdo_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, 809848b8605Smrg const GLvoid *srcRowA, const GLvoid *srcRowB, 810848b8605Smrg const GLvoid *srcRowC, const GLvoid *srcRowD, 811848b8605Smrg GLint dstWidth, GLvoid *dstRow) 812848b8605Smrg{ 813848b8605Smrg const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; 814848b8605Smrg const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; 815848b8605Smrg GLuint i, j, k; 816848b8605Smrg 817b8e80941Smrg assert(comps >= 1); 818b8e80941Smrg assert(comps <= 4); 819848b8605Smrg 820848b8605Smrg if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) { 821848b8605Smrg DECLARE_ROW_POINTERS(GLubyte, 4); 822848b8605Smrg 823848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 824848b8605Smrg i++, j += colStride, k += colStride) { 825848b8605Smrg FILTER_3D(0); 826848b8605Smrg FILTER_3D(1); 827848b8605Smrg FILTER_3D(2); 828848b8605Smrg FILTER_3D(3); 829848b8605Smrg } 830848b8605Smrg } 831848b8605Smrg else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) { 832848b8605Smrg DECLARE_ROW_POINTERS(GLubyte, 3); 833848b8605Smrg 834848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 835848b8605Smrg i++, j += colStride, k += colStride) { 836848b8605Smrg FILTER_3D(0); 837848b8605Smrg FILTER_3D(1); 838848b8605Smrg FILTER_3D(2); 839848b8605Smrg } 840848b8605Smrg } 841848b8605Smrg else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) { 842848b8605Smrg DECLARE_ROW_POINTERS(GLubyte, 2); 843848b8605Smrg 844848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 845848b8605Smrg i++, j += colStride, k += colStride) { 846848b8605Smrg FILTER_3D(0); 847848b8605Smrg FILTER_3D(1); 848848b8605Smrg } 849848b8605Smrg } 850848b8605Smrg else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) { 851848b8605Smrg DECLARE_ROW_POINTERS(GLubyte, 1); 852848b8605Smrg 853848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 854848b8605Smrg i++, j += colStride, k += colStride) { 855848b8605Smrg FILTER_3D(0); 856848b8605Smrg } 857848b8605Smrg } 858848b8605Smrg else if ((datatype == GL_BYTE) && (comps == 4)) { 859848b8605Smrg DECLARE_ROW_POINTERS(GLbyte, 4); 860848b8605Smrg 861848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 862848b8605Smrg i++, j += colStride, k += colStride) { 863848b8605Smrg FILTER_3D_SIGNED(0); 864848b8605Smrg FILTER_3D_SIGNED(1); 865848b8605Smrg FILTER_3D_SIGNED(2); 866848b8605Smrg FILTER_3D_SIGNED(3); 867848b8605Smrg } 868848b8605Smrg } 869848b8605Smrg else if ((datatype == GL_BYTE) && (comps == 3)) { 870848b8605Smrg DECLARE_ROW_POINTERS(GLbyte, 3); 871848b8605Smrg 872848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 873848b8605Smrg i++, j += colStride, k += colStride) { 874848b8605Smrg FILTER_3D_SIGNED(0); 875848b8605Smrg FILTER_3D_SIGNED(1); 876848b8605Smrg FILTER_3D_SIGNED(2); 877848b8605Smrg } 878848b8605Smrg } 879848b8605Smrg else if ((datatype == GL_BYTE) && (comps == 2)) { 880848b8605Smrg DECLARE_ROW_POINTERS(GLbyte, 2); 881848b8605Smrg 882848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 883848b8605Smrg i++, j += colStride, k += colStride) { 884848b8605Smrg FILTER_3D_SIGNED(0); 885848b8605Smrg FILTER_3D_SIGNED(1); 886848b8605Smrg } 887848b8605Smrg } 888848b8605Smrg else if ((datatype == GL_BYTE) && (comps == 1)) { 889848b8605Smrg DECLARE_ROW_POINTERS(GLbyte, 1); 890848b8605Smrg 891848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 892848b8605Smrg i++, j += colStride, k += colStride) { 893848b8605Smrg FILTER_3D_SIGNED(0); 894848b8605Smrg } 895848b8605Smrg } 896848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) { 897848b8605Smrg DECLARE_ROW_POINTERS(GLushort, 4); 898848b8605Smrg 899848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 900848b8605Smrg i++, j += colStride, k += colStride) { 901848b8605Smrg FILTER_3D(0); 902848b8605Smrg FILTER_3D(1); 903848b8605Smrg FILTER_3D(2); 904848b8605Smrg FILTER_3D(3); 905848b8605Smrg } 906848b8605Smrg } 907848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) { 908848b8605Smrg DECLARE_ROW_POINTERS(GLushort, 3); 909848b8605Smrg 910848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 911848b8605Smrg i++, j += colStride, k += colStride) { 912848b8605Smrg FILTER_3D(0); 913848b8605Smrg FILTER_3D(1); 914848b8605Smrg FILTER_3D(2); 915848b8605Smrg } 916848b8605Smrg } 917848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) { 918848b8605Smrg DECLARE_ROW_POINTERS(GLushort, 2); 919848b8605Smrg 920848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 921848b8605Smrg i++, j += colStride, k += colStride) { 922848b8605Smrg FILTER_3D(0); 923848b8605Smrg FILTER_3D(1); 924848b8605Smrg } 925848b8605Smrg } 926848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) { 927848b8605Smrg DECLARE_ROW_POINTERS(GLushort, 1); 928848b8605Smrg 929848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 930848b8605Smrg i++, j += colStride, k += colStride) { 931848b8605Smrg FILTER_3D(0); 932848b8605Smrg } 933848b8605Smrg } 934848b8605Smrg else if ((datatype == GL_SHORT) && (comps == 4)) { 935848b8605Smrg DECLARE_ROW_POINTERS(GLshort, 4); 936848b8605Smrg 937848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 938848b8605Smrg i++, j += colStride, k += colStride) { 939848b8605Smrg FILTER_3D(0); 940848b8605Smrg FILTER_3D(1); 941848b8605Smrg FILTER_3D(2); 942848b8605Smrg FILTER_3D(3); 943848b8605Smrg } 944848b8605Smrg } 945848b8605Smrg else if ((datatype == GL_SHORT) && (comps == 3)) { 946848b8605Smrg DECLARE_ROW_POINTERS(GLshort, 3); 947848b8605Smrg 948848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 949848b8605Smrg i++, j += colStride, k += colStride) { 950848b8605Smrg FILTER_3D(0); 951848b8605Smrg FILTER_3D(1); 952848b8605Smrg FILTER_3D(2); 953848b8605Smrg } 954848b8605Smrg } 955848b8605Smrg else if ((datatype == GL_SHORT) && (comps == 2)) { 956848b8605Smrg DECLARE_ROW_POINTERS(GLshort, 2); 957848b8605Smrg 958848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 959848b8605Smrg i++, j += colStride, k += colStride) { 960848b8605Smrg FILTER_3D(0); 961848b8605Smrg FILTER_3D(1); 962848b8605Smrg } 963848b8605Smrg } 964848b8605Smrg else if ((datatype == GL_SHORT) && (comps == 1)) { 965848b8605Smrg DECLARE_ROW_POINTERS(GLshort, 1); 966848b8605Smrg 967848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 968848b8605Smrg i++, j += colStride, k += colStride) { 969848b8605Smrg FILTER_3D(0); 970848b8605Smrg } 971848b8605Smrg } 972848b8605Smrg else if ((datatype == GL_FLOAT) && (comps == 4)) { 973848b8605Smrg DECLARE_ROW_POINTERS(GLfloat, 4); 974848b8605Smrg 975848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 976848b8605Smrg i++, j += colStride, k += colStride) { 977848b8605Smrg FILTER_F_3D(0); 978848b8605Smrg FILTER_F_3D(1); 979848b8605Smrg FILTER_F_3D(2); 980848b8605Smrg FILTER_F_3D(3); 981848b8605Smrg } 982848b8605Smrg } 983848b8605Smrg else if ((datatype == GL_FLOAT) && (comps == 3)) { 984848b8605Smrg DECLARE_ROW_POINTERS(GLfloat, 3); 985848b8605Smrg 986848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 987848b8605Smrg i++, j += colStride, k += colStride) { 988848b8605Smrg FILTER_F_3D(0); 989848b8605Smrg FILTER_F_3D(1); 990848b8605Smrg FILTER_F_3D(2); 991848b8605Smrg } 992848b8605Smrg } 993848b8605Smrg else if ((datatype == GL_FLOAT) && (comps == 2)) { 994848b8605Smrg DECLARE_ROW_POINTERS(GLfloat, 2); 995848b8605Smrg 996848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 997848b8605Smrg i++, j += colStride, k += colStride) { 998848b8605Smrg FILTER_F_3D(0); 999848b8605Smrg FILTER_F_3D(1); 1000848b8605Smrg } 1001848b8605Smrg } 1002848b8605Smrg else if ((datatype == GL_FLOAT) && (comps == 1)) { 1003848b8605Smrg DECLARE_ROW_POINTERS(GLfloat, 1); 1004848b8605Smrg 1005848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1006848b8605Smrg i++, j += colStride, k += colStride) { 1007848b8605Smrg FILTER_F_3D(0); 1008848b8605Smrg } 1009848b8605Smrg } 1010848b8605Smrg else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) { 1011848b8605Smrg DECLARE_ROW_POINTERS(GLhalfARB, 4); 1012848b8605Smrg 1013848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1014848b8605Smrg i++, j += colStride, k += colStride) { 1015848b8605Smrg FILTER_HF_3D(0); 1016848b8605Smrg FILTER_HF_3D(1); 1017848b8605Smrg FILTER_HF_3D(2); 1018848b8605Smrg FILTER_HF_3D(3); 1019848b8605Smrg } 1020848b8605Smrg } 1021848b8605Smrg else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) { 1022848b8605Smrg DECLARE_ROW_POINTERS(GLhalfARB, 3); 1023848b8605Smrg 1024848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1025848b8605Smrg i++, j += colStride, k += colStride) { 1026848b8605Smrg FILTER_HF_3D(0); 1027848b8605Smrg FILTER_HF_3D(1); 1028848b8605Smrg FILTER_HF_3D(2); 1029848b8605Smrg } 1030848b8605Smrg } 1031848b8605Smrg else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) { 1032848b8605Smrg DECLARE_ROW_POINTERS(GLhalfARB, 2); 1033848b8605Smrg 1034848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1035848b8605Smrg i++, j += colStride, k += colStride) { 1036848b8605Smrg FILTER_HF_3D(0); 1037848b8605Smrg FILTER_HF_3D(1); 1038848b8605Smrg } 1039848b8605Smrg } 1040848b8605Smrg else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) { 1041848b8605Smrg DECLARE_ROW_POINTERS(GLhalfARB, 1); 1042848b8605Smrg 1043848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1044848b8605Smrg i++, j += colStride, k += colStride) { 1045848b8605Smrg FILTER_HF_3D(0); 1046848b8605Smrg } 1047848b8605Smrg } 1048848b8605Smrg else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) { 1049848b8605Smrg const GLuint *rowA = (const GLuint *) srcRowA; 1050848b8605Smrg const GLuint *rowB = (const GLuint *) srcRowB; 1051848b8605Smrg const GLuint *rowC = (const GLuint *) srcRowC; 1052848b8605Smrg const GLuint *rowD = (const GLuint *) srcRowD; 1053848b8605Smrg GLfloat *dst = (GLfloat *) dstRow; 1054848b8605Smrg 1055848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1056848b8605Smrg i++, j += colStride, k += colStride) { 1057848b8605Smrg const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k]) 1058848b8605Smrg + ((uint64_t) rowB[j] + (uint64_t) rowB[k]) 1059848b8605Smrg + ((uint64_t) rowC[j] + (uint64_t) rowC[k]) 1060848b8605Smrg + ((uint64_t) rowD[j] + (uint64_t) rowD[k])); 1061848b8605Smrg dst[i] = (GLfloat)((double) tmp * 0.125); 1062848b8605Smrg } 1063848b8605Smrg } 1064848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) { 1065848b8605Smrg DECLARE_ROW_POINTERS0(GLushort); 1066848b8605Smrg 1067848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1068848b8605Smrg i++, j += colStride, k += colStride) { 1069848b8605Smrg const GLint rowAr0 = rowA[j] & 0x1f; 1070848b8605Smrg const GLint rowAr1 = rowA[k] & 0x1f; 1071848b8605Smrg const GLint rowBr0 = rowB[j] & 0x1f; 1072848b8605Smrg const GLint rowBr1 = rowB[k] & 0x1f; 1073848b8605Smrg const GLint rowCr0 = rowC[j] & 0x1f; 1074848b8605Smrg const GLint rowCr1 = rowC[k] & 0x1f; 1075848b8605Smrg const GLint rowDr0 = rowD[j] & 0x1f; 1076848b8605Smrg const GLint rowDr1 = rowD[k] & 0x1f; 1077848b8605Smrg const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; 1078848b8605Smrg const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; 1079848b8605Smrg const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; 1080848b8605Smrg const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; 1081848b8605Smrg const GLint rowCg0 = (rowC[j] >> 5) & 0x3f; 1082848b8605Smrg const GLint rowCg1 = (rowC[k] >> 5) & 0x3f; 1083848b8605Smrg const GLint rowDg0 = (rowD[j] >> 5) & 0x3f; 1084848b8605Smrg const GLint rowDg1 = (rowD[k] >> 5) & 0x3f; 1085848b8605Smrg const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; 1086848b8605Smrg const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; 1087848b8605Smrg const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; 1088848b8605Smrg const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; 1089848b8605Smrg const GLint rowCb0 = (rowC[j] >> 11) & 0x1f; 1090848b8605Smrg const GLint rowCb1 = (rowC[k] >> 11) & 0x1f; 1091848b8605Smrg const GLint rowDb0 = (rowD[j] >> 11) & 0x1f; 1092848b8605Smrg const GLint rowDb1 = (rowD[k] >> 11) & 0x1f; 1093848b8605Smrg const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 1094848b8605Smrg rowCr0, rowCr1, rowDr0, rowDr1); 1095848b8605Smrg const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 1096848b8605Smrg rowCg0, rowCg1, rowDg0, rowDg1); 1097848b8605Smrg const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 1098848b8605Smrg rowCb0, rowCb1, rowDb0, rowDb1); 1099848b8605Smrg dst[i] = (b << 11) | (g << 5) | r; 1100848b8605Smrg } 1101848b8605Smrg } 1102848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) { 1103848b8605Smrg DECLARE_ROW_POINTERS0(GLushort); 1104848b8605Smrg 1105848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1106848b8605Smrg i++, j += colStride, k += colStride) { 1107848b8605Smrg const GLint rowAr0 = rowA[j] & 0xf; 1108848b8605Smrg const GLint rowAr1 = rowA[k] & 0xf; 1109848b8605Smrg const GLint rowBr0 = rowB[j] & 0xf; 1110848b8605Smrg const GLint rowBr1 = rowB[k] & 0xf; 1111848b8605Smrg const GLint rowCr0 = rowC[j] & 0xf; 1112848b8605Smrg const GLint rowCr1 = rowC[k] & 0xf; 1113848b8605Smrg const GLint rowDr0 = rowD[j] & 0xf; 1114848b8605Smrg const GLint rowDr1 = rowD[k] & 0xf; 1115848b8605Smrg const GLint rowAg0 = (rowA[j] >> 4) & 0xf; 1116848b8605Smrg const GLint rowAg1 = (rowA[k] >> 4) & 0xf; 1117848b8605Smrg const GLint rowBg0 = (rowB[j] >> 4) & 0xf; 1118848b8605Smrg const GLint rowBg1 = (rowB[k] >> 4) & 0xf; 1119848b8605Smrg const GLint rowCg0 = (rowC[j] >> 4) & 0xf; 1120848b8605Smrg const GLint rowCg1 = (rowC[k] >> 4) & 0xf; 1121848b8605Smrg const GLint rowDg0 = (rowD[j] >> 4) & 0xf; 1122848b8605Smrg const GLint rowDg1 = (rowD[k] >> 4) & 0xf; 1123848b8605Smrg const GLint rowAb0 = (rowA[j] >> 8) & 0xf; 1124848b8605Smrg const GLint rowAb1 = (rowA[k] >> 8) & 0xf; 1125848b8605Smrg const GLint rowBb0 = (rowB[j] >> 8) & 0xf; 1126848b8605Smrg const GLint rowBb1 = (rowB[k] >> 8) & 0xf; 1127848b8605Smrg const GLint rowCb0 = (rowC[j] >> 8) & 0xf; 1128848b8605Smrg const GLint rowCb1 = (rowC[k] >> 8) & 0xf; 1129848b8605Smrg const GLint rowDb0 = (rowD[j] >> 8) & 0xf; 1130848b8605Smrg const GLint rowDb1 = (rowD[k] >> 8) & 0xf; 1131848b8605Smrg const GLint rowAa0 = (rowA[j] >> 12) & 0xf; 1132848b8605Smrg const GLint rowAa1 = (rowA[k] >> 12) & 0xf; 1133848b8605Smrg const GLint rowBa0 = (rowB[j] >> 12) & 0xf; 1134848b8605Smrg const GLint rowBa1 = (rowB[k] >> 12) & 0xf; 1135848b8605Smrg const GLint rowCa0 = (rowC[j] >> 12) & 0xf; 1136848b8605Smrg const GLint rowCa1 = (rowC[k] >> 12) & 0xf; 1137848b8605Smrg const GLint rowDa0 = (rowD[j] >> 12) & 0xf; 1138848b8605Smrg const GLint rowDa1 = (rowD[k] >> 12) & 0xf; 1139848b8605Smrg const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 1140848b8605Smrg rowCr0, rowCr1, rowDr0, rowDr1); 1141848b8605Smrg const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 1142848b8605Smrg rowCg0, rowCg1, rowDg0, rowDg1); 1143848b8605Smrg const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 1144848b8605Smrg rowCb0, rowCb1, rowDb0, rowDb1); 1145848b8605Smrg const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 1146848b8605Smrg rowCa0, rowCa1, rowDa0, rowDa1); 1147848b8605Smrg 1148848b8605Smrg dst[i] = (a << 12) | (b << 8) | (g << 4) | r; 1149848b8605Smrg } 1150848b8605Smrg } 1151848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) { 1152848b8605Smrg DECLARE_ROW_POINTERS0(GLushort); 1153848b8605Smrg 1154848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1155848b8605Smrg i++, j += colStride, k += colStride) { 1156848b8605Smrg const GLint rowAr0 = rowA[j] & 0x1f; 1157848b8605Smrg const GLint rowAr1 = rowA[k] & 0x1f; 1158848b8605Smrg const GLint rowBr0 = rowB[j] & 0x1f; 1159848b8605Smrg const GLint rowBr1 = rowB[k] & 0x1f; 1160848b8605Smrg const GLint rowCr0 = rowC[j] & 0x1f; 1161848b8605Smrg const GLint rowCr1 = rowC[k] & 0x1f; 1162848b8605Smrg const GLint rowDr0 = rowD[j] & 0x1f; 1163848b8605Smrg const GLint rowDr1 = rowD[k] & 0x1f; 1164848b8605Smrg const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; 1165848b8605Smrg const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; 1166848b8605Smrg const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; 1167848b8605Smrg const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; 1168848b8605Smrg const GLint rowCg0 = (rowC[j] >> 5) & 0x1f; 1169848b8605Smrg const GLint rowCg1 = (rowC[k] >> 5) & 0x1f; 1170848b8605Smrg const GLint rowDg0 = (rowD[j] >> 5) & 0x1f; 1171848b8605Smrg const GLint rowDg1 = (rowD[k] >> 5) & 0x1f; 1172848b8605Smrg const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; 1173848b8605Smrg const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; 1174848b8605Smrg const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; 1175848b8605Smrg const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; 1176848b8605Smrg const GLint rowCb0 = (rowC[j] >> 10) & 0x1f; 1177848b8605Smrg const GLint rowCb1 = (rowC[k] >> 10) & 0x1f; 1178848b8605Smrg const GLint rowDb0 = (rowD[j] >> 10) & 0x1f; 1179848b8605Smrg const GLint rowDb1 = (rowD[k] >> 10) & 0x1f; 1180848b8605Smrg const GLint rowAa0 = (rowA[j] >> 15) & 0x1; 1181848b8605Smrg const GLint rowAa1 = (rowA[k] >> 15) & 0x1; 1182848b8605Smrg const GLint rowBa0 = (rowB[j] >> 15) & 0x1; 1183848b8605Smrg const GLint rowBa1 = (rowB[k] >> 15) & 0x1; 1184848b8605Smrg const GLint rowCa0 = (rowC[j] >> 15) & 0x1; 1185848b8605Smrg const GLint rowCa1 = (rowC[k] >> 15) & 0x1; 1186848b8605Smrg const GLint rowDa0 = (rowD[j] >> 15) & 0x1; 1187848b8605Smrg const GLint rowDa1 = (rowD[k] >> 15) & 0x1; 1188848b8605Smrg const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 1189848b8605Smrg rowCr0, rowCr1, rowDr0, rowDr1); 1190848b8605Smrg const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 1191848b8605Smrg rowCg0, rowCg1, rowDg0, rowDg1); 1192848b8605Smrg const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 1193848b8605Smrg rowCb0, rowCb1, rowDb0, rowDb1); 1194848b8605Smrg const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 1195848b8605Smrg rowCa0, rowCa1, rowDa0, rowDa1); 1196848b8605Smrg 1197848b8605Smrg dst[i] = (a << 15) | (b << 10) | (g << 5) | r; 1198848b8605Smrg } 1199848b8605Smrg } 1200848b8605Smrg else if ((datatype == GL_UNSIGNED_SHORT_5_5_5_1) && (comps == 4)) { 1201848b8605Smrg DECLARE_ROW_POINTERS0(GLushort); 1202848b8605Smrg 1203848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1204848b8605Smrg i++, j += colStride, k += colStride) { 1205848b8605Smrg const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; 1206848b8605Smrg const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; 1207848b8605Smrg const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; 1208848b8605Smrg const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; 1209848b8605Smrg const GLint rowCr0 = (rowC[j] >> 11) & 0x1f; 1210848b8605Smrg const GLint rowCr1 = (rowC[k] >> 11) & 0x1f; 1211848b8605Smrg const GLint rowDr0 = (rowD[j] >> 11) & 0x1f; 1212848b8605Smrg const GLint rowDr1 = (rowD[k] >> 11) & 0x1f; 1213848b8605Smrg const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; 1214848b8605Smrg const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; 1215848b8605Smrg const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; 1216848b8605Smrg const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; 1217848b8605Smrg const GLint rowCg0 = (rowC[j] >> 6) & 0x1f; 1218848b8605Smrg const GLint rowCg1 = (rowC[k] >> 6) & 0x1f; 1219848b8605Smrg const GLint rowDg0 = (rowD[j] >> 6) & 0x1f; 1220848b8605Smrg const GLint rowDg1 = (rowD[k] >> 6) & 0x1f; 1221848b8605Smrg const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; 1222848b8605Smrg const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; 1223848b8605Smrg const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; 1224848b8605Smrg const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; 1225848b8605Smrg const GLint rowCb0 = (rowC[j] >> 1) & 0x1f; 1226848b8605Smrg const GLint rowCb1 = (rowC[k] >> 1) & 0x1f; 1227848b8605Smrg const GLint rowDb0 = (rowD[j] >> 1) & 0x1f; 1228848b8605Smrg const GLint rowDb1 = (rowD[k] >> 1) & 0x1f; 1229848b8605Smrg const GLint rowAa0 = (rowA[j] & 0x1); 1230848b8605Smrg const GLint rowAa1 = (rowA[k] & 0x1); 1231848b8605Smrg const GLint rowBa0 = (rowB[j] & 0x1); 1232848b8605Smrg const GLint rowBa1 = (rowB[k] & 0x1); 1233848b8605Smrg const GLint rowCa0 = (rowC[j] & 0x1); 1234848b8605Smrg const GLint rowCa1 = (rowC[k] & 0x1); 1235848b8605Smrg const GLint rowDa0 = (rowD[j] & 0x1); 1236848b8605Smrg const GLint rowDa1 = (rowD[k] & 0x1); 1237848b8605Smrg const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 1238848b8605Smrg rowCr0, rowCr1, rowDr0, rowDr1); 1239848b8605Smrg const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 1240848b8605Smrg rowCg0, rowCg1, rowDg0, rowDg1); 1241848b8605Smrg const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 1242848b8605Smrg rowCb0, rowCb1, rowDb0, rowDb1); 1243848b8605Smrg const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 1244848b8605Smrg rowCa0, rowCa1, rowDa0, rowDa1); 1245848b8605Smrg 1246848b8605Smrg dst[i] = (r << 11) | (g << 6) | (b << 1) | a; 1247848b8605Smrg } 1248848b8605Smrg } 1249848b8605Smrg else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) { 1250848b8605Smrg DECLARE_ROW_POINTERS0(GLubyte); 1251848b8605Smrg 1252848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1253848b8605Smrg i++, j += colStride, k += colStride) { 1254848b8605Smrg const GLint rowAr0 = rowA[j] & 0x3; 1255848b8605Smrg const GLint rowAr1 = rowA[k] & 0x3; 1256848b8605Smrg const GLint rowBr0 = rowB[j] & 0x3; 1257848b8605Smrg const GLint rowBr1 = rowB[k] & 0x3; 1258848b8605Smrg const GLint rowCr0 = rowC[j] & 0x3; 1259848b8605Smrg const GLint rowCr1 = rowC[k] & 0x3; 1260848b8605Smrg const GLint rowDr0 = rowD[j] & 0x3; 1261848b8605Smrg const GLint rowDr1 = rowD[k] & 0x3; 1262848b8605Smrg const GLint rowAg0 = (rowA[j] >> 2) & 0x7; 1263848b8605Smrg const GLint rowAg1 = (rowA[k] >> 2) & 0x7; 1264848b8605Smrg const GLint rowBg0 = (rowB[j] >> 2) & 0x7; 1265848b8605Smrg const GLint rowBg1 = (rowB[k] >> 2) & 0x7; 1266848b8605Smrg const GLint rowCg0 = (rowC[j] >> 2) & 0x7; 1267848b8605Smrg const GLint rowCg1 = (rowC[k] >> 2) & 0x7; 1268848b8605Smrg const GLint rowDg0 = (rowD[j] >> 2) & 0x7; 1269848b8605Smrg const GLint rowDg1 = (rowD[k] >> 2) & 0x7; 1270848b8605Smrg const GLint rowAb0 = (rowA[j] >> 5) & 0x7; 1271848b8605Smrg const GLint rowAb1 = (rowA[k] >> 5) & 0x7; 1272848b8605Smrg const GLint rowBb0 = (rowB[j] >> 5) & 0x7; 1273848b8605Smrg const GLint rowBb1 = (rowB[k] >> 5) & 0x7; 1274848b8605Smrg const GLint rowCb0 = (rowC[j] >> 5) & 0x7; 1275848b8605Smrg const GLint rowCb1 = (rowC[k] >> 5) & 0x7; 1276848b8605Smrg const GLint rowDb0 = (rowD[j] >> 5) & 0x7; 1277848b8605Smrg const GLint rowDb1 = (rowD[k] >> 5) & 0x7; 1278848b8605Smrg const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 1279848b8605Smrg rowCr0, rowCr1, rowDr0, rowDr1); 1280848b8605Smrg const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 1281848b8605Smrg rowCg0, rowCg1, rowDg0, rowDg1); 1282848b8605Smrg const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 1283848b8605Smrg rowCb0, rowCb1, rowDb0, rowDb1); 1284848b8605Smrg dst[i] = (b << 5) | (g << 2) | r; 1285848b8605Smrg } 1286848b8605Smrg } 1287848b8605Smrg else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { 1288848b8605Smrg DECLARE_ROW_POINTERS0(GLubyte); 1289848b8605Smrg 1290848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1291848b8605Smrg i++, j += colStride, k += colStride) { 1292848b8605Smrg const GLint rowAr0 = rowA[j] & 0xf; 1293848b8605Smrg const GLint rowAr1 = rowA[k] & 0xf; 1294848b8605Smrg const GLint rowBr0 = rowB[j] & 0xf; 1295848b8605Smrg const GLint rowBr1 = rowB[k] & 0xf; 1296848b8605Smrg const GLint rowCr0 = rowC[j] & 0xf; 1297848b8605Smrg const GLint rowCr1 = rowC[k] & 0xf; 1298848b8605Smrg const GLint rowDr0 = rowD[j] & 0xf; 1299848b8605Smrg const GLint rowDr1 = rowD[k] & 0xf; 1300848b8605Smrg const GLint rowAg0 = (rowA[j] >> 4) & 0xf; 1301848b8605Smrg const GLint rowAg1 = (rowA[k] >> 4) & 0xf; 1302848b8605Smrg const GLint rowBg0 = (rowB[j] >> 4) & 0xf; 1303848b8605Smrg const GLint rowBg1 = (rowB[k] >> 4) & 0xf; 1304848b8605Smrg const GLint rowCg0 = (rowC[j] >> 4) & 0xf; 1305848b8605Smrg const GLint rowCg1 = (rowC[k] >> 4) & 0xf; 1306848b8605Smrg const GLint rowDg0 = (rowD[j] >> 4) & 0xf; 1307848b8605Smrg const GLint rowDg1 = (rowD[k] >> 4) & 0xf; 1308848b8605Smrg const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 1309848b8605Smrg rowCr0, rowCr1, rowDr0, rowDr1); 1310848b8605Smrg const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 1311848b8605Smrg rowCg0, rowCg1, rowDg0, rowDg1); 1312848b8605Smrg dst[i] = (g << 4) | r; 1313848b8605Smrg } 1314848b8605Smrg } 1315848b8605Smrg else if ((datatype == GL_UNSIGNED_INT_2_10_10_10_REV) && (comps == 4)) { 1316848b8605Smrg DECLARE_ROW_POINTERS0(GLuint); 1317848b8605Smrg 1318848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1319848b8605Smrg i++, j += colStride, k += colStride) { 1320848b8605Smrg const GLint rowAr0 = rowA[j] & 0x3ff; 1321848b8605Smrg const GLint rowAr1 = rowA[k] & 0x3ff; 1322848b8605Smrg const GLint rowBr0 = rowB[j] & 0x3ff; 1323848b8605Smrg const GLint rowBr1 = rowB[k] & 0x3ff; 1324848b8605Smrg const GLint rowCr0 = rowC[j] & 0x3ff; 1325848b8605Smrg const GLint rowCr1 = rowC[k] & 0x3ff; 1326848b8605Smrg const GLint rowDr0 = rowD[j] & 0x3ff; 1327848b8605Smrg const GLint rowDr1 = rowD[k] & 0x3ff; 1328848b8605Smrg const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff; 1329848b8605Smrg const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff; 1330848b8605Smrg const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff; 1331848b8605Smrg const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff; 1332848b8605Smrg const GLint rowCg0 = (rowC[j] >> 10) & 0x3ff; 1333848b8605Smrg const GLint rowCg1 = (rowC[k] >> 10) & 0x3ff; 1334848b8605Smrg const GLint rowDg0 = (rowD[j] >> 10) & 0x3ff; 1335848b8605Smrg const GLint rowDg1 = (rowD[k] >> 10) & 0x3ff; 1336848b8605Smrg const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff; 1337848b8605Smrg const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff; 1338848b8605Smrg const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff; 1339848b8605Smrg const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff; 1340848b8605Smrg const GLint rowCb0 = (rowC[j] >> 20) & 0x3ff; 1341848b8605Smrg const GLint rowCb1 = (rowC[k] >> 20) & 0x3ff; 1342848b8605Smrg const GLint rowDb0 = (rowD[j] >> 20) & 0x3ff; 1343848b8605Smrg const GLint rowDb1 = (rowD[k] >> 20) & 0x3ff; 1344848b8605Smrg const GLint rowAa0 = (rowA[j] >> 30) & 0x3; 1345848b8605Smrg const GLint rowAa1 = (rowA[k] >> 30) & 0x3; 1346848b8605Smrg const GLint rowBa0 = (rowB[j] >> 30) & 0x3; 1347848b8605Smrg const GLint rowBa1 = (rowB[k] >> 30) & 0x3; 1348848b8605Smrg const GLint rowCa0 = (rowC[j] >> 30) & 0x3; 1349848b8605Smrg const GLint rowCa1 = (rowC[k] >> 30) & 0x3; 1350848b8605Smrg const GLint rowDa0 = (rowD[j] >> 30) & 0x3; 1351848b8605Smrg const GLint rowDa1 = (rowD[k] >> 30) & 0x3; 1352848b8605Smrg const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 1353848b8605Smrg rowCr0, rowCr1, rowDr0, rowDr1); 1354848b8605Smrg const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 1355848b8605Smrg rowCg0, rowCg1, rowDg0, rowDg1); 1356848b8605Smrg const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 1357848b8605Smrg rowCb0, rowCb1, rowDb0, rowDb1); 1358848b8605Smrg const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 1359848b8605Smrg rowCa0, rowCa1, rowDa0, rowDa1); 1360848b8605Smrg 1361848b8605Smrg dst[i] = (a << 30) | (b << 20) | (g << 10) | r; 1362848b8605Smrg } 1363848b8605Smrg } 1364848b8605Smrg 1365848b8605Smrg else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { 1366848b8605Smrg DECLARE_ROW_POINTERS0(GLuint); 1367848b8605Smrg 1368848b8605Smrg GLfloat res[3]; 1369848b8605Smrg GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3]; 1370848b8605Smrg GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3]; 1371848b8605Smrg 1372848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1373848b8605Smrg i++, j += colStride, k += colStride) { 1374848b8605Smrg rgb9e5_to_float3(rowA[j], rowAj); 1375848b8605Smrg rgb9e5_to_float3(rowB[j], rowBj); 1376848b8605Smrg rgb9e5_to_float3(rowC[j], rowCj); 1377848b8605Smrg rgb9e5_to_float3(rowD[j], rowDj); 1378848b8605Smrg rgb9e5_to_float3(rowA[k], rowAk); 1379848b8605Smrg rgb9e5_to_float3(rowB[k], rowBk); 1380848b8605Smrg rgb9e5_to_float3(rowC[k], rowCk); 1381848b8605Smrg rgb9e5_to_float3(rowD[k], rowDk); 1382848b8605Smrg res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] + 1383848b8605Smrg rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F; 1384848b8605Smrg res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] + 1385848b8605Smrg rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F; 1386848b8605Smrg res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] + 1387848b8605Smrg rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F; 1388848b8605Smrg dst[i] = float3_to_rgb9e5(res); 1389848b8605Smrg } 1390848b8605Smrg } 1391848b8605Smrg 1392848b8605Smrg else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) { 1393848b8605Smrg DECLARE_ROW_POINTERS0(GLuint); 1394848b8605Smrg 1395848b8605Smrg GLfloat res[3]; 1396848b8605Smrg GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3]; 1397848b8605Smrg GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3]; 1398848b8605Smrg 1399848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1400848b8605Smrg i++, j += colStride, k += colStride) { 1401848b8605Smrg r11g11b10f_to_float3(rowA[j], rowAj); 1402848b8605Smrg r11g11b10f_to_float3(rowB[j], rowBj); 1403848b8605Smrg r11g11b10f_to_float3(rowC[j], rowCj); 1404848b8605Smrg r11g11b10f_to_float3(rowD[j], rowDj); 1405848b8605Smrg r11g11b10f_to_float3(rowA[k], rowAk); 1406848b8605Smrg r11g11b10f_to_float3(rowB[k], rowBk); 1407848b8605Smrg r11g11b10f_to_float3(rowC[k], rowCk); 1408848b8605Smrg r11g11b10f_to_float3(rowD[k], rowDk); 1409848b8605Smrg res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] + 1410848b8605Smrg rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F; 1411848b8605Smrg res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] + 1412848b8605Smrg rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F; 1413848b8605Smrg res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] + 1414848b8605Smrg rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F; 1415848b8605Smrg dst[i] = float3_to_r11g11b10f(res); 1416848b8605Smrg } 1417848b8605Smrg } 1418848b8605Smrg 1419848b8605Smrg else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) { 1420848b8605Smrg DECLARE_ROW_POINTERS(GLfloat, 2); 1421848b8605Smrg 1422848b8605Smrg for (i = j = 0, k = k0; i < (GLuint) dstWidth; 1423848b8605Smrg i++, j += colStride, k += colStride) { 1424848b8605Smrg FILTER_F_3D(0); 1425848b8605Smrg } 1426848b8605Smrg } 1427848b8605Smrg 1428848b8605Smrg else { 1429b8e80941Smrg unreachable("bad format in do_row()"); 1430848b8605Smrg } 1431848b8605Smrg} 1432848b8605Smrg 1433848b8605Smrg 1434848b8605Smrg/* 1435848b8605Smrg * These functions generate a 1/2-size mipmap image from a source image. 1436848b8605Smrg * Texture borders are handled by copying or averaging the source image's 1437848b8605Smrg * border texels, depending on the scale-down factor. 1438848b8605Smrg */ 1439848b8605Smrg 1440848b8605Smrgstatic void 1441848b8605Smrgmake_1d_mipmap(GLenum datatype, GLuint comps, GLint border, 1442848b8605Smrg GLint srcWidth, const GLubyte *srcPtr, 1443848b8605Smrg GLint dstWidth, GLubyte *dstPtr) 1444848b8605Smrg{ 1445848b8605Smrg const GLint bpt = bytes_per_pixel(datatype, comps); 1446848b8605Smrg const GLubyte *src; 1447848b8605Smrg GLubyte *dst; 1448848b8605Smrg 1449848b8605Smrg /* skip the border pixel, if any */ 1450848b8605Smrg src = srcPtr + border * bpt; 1451848b8605Smrg dst = dstPtr + border * bpt; 1452848b8605Smrg 1453848b8605Smrg /* we just duplicate the input row, kind of hack, saves code */ 1454848b8605Smrg do_row(datatype, comps, srcWidth - 2 * border, src, src, 1455848b8605Smrg dstWidth - 2 * border, dst); 1456848b8605Smrg 1457848b8605Smrg if (border) { 1458848b8605Smrg /* copy left-most pixel from source */ 1459848b8605Smrg assert(dstPtr); 1460848b8605Smrg assert(srcPtr); 1461848b8605Smrg memcpy(dstPtr, srcPtr, bpt); 1462848b8605Smrg /* copy right-most pixel from source */ 1463848b8605Smrg memcpy(dstPtr + (dstWidth - 1) * bpt, 1464848b8605Smrg srcPtr + (srcWidth - 1) * bpt, 1465848b8605Smrg bpt); 1466848b8605Smrg } 1467848b8605Smrg} 1468848b8605Smrg 1469848b8605Smrg 1470848b8605Smrgstatic void 1471848b8605Smrgmake_2d_mipmap(GLenum datatype, GLuint comps, GLint border, 1472848b8605Smrg GLint srcWidth, GLint srcHeight, 1473b8e80941Smrg const GLubyte *srcPtr, GLint srcRowStride, 1474848b8605Smrg GLint dstWidth, GLint dstHeight, 1475b8e80941Smrg GLubyte *dstPtr, GLint dstRowStride) 1476848b8605Smrg{ 1477848b8605Smrg const GLint bpt = bytes_per_pixel(datatype, comps); 1478848b8605Smrg const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 1479848b8605Smrg const GLint dstWidthNB = dstWidth - 2 * border; 1480848b8605Smrg const GLint dstHeightNB = dstHeight - 2 * border; 1481848b8605Smrg const GLubyte *srcA, *srcB; 1482848b8605Smrg GLubyte *dst; 1483848b8605Smrg GLint row, srcRowStep; 1484848b8605Smrg 1485848b8605Smrg /* Compute src and dst pointers, skipping any border */ 1486848b8605Smrg srcA = srcPtr + border * ((srcWidth + 1) * bpt); 1487848b8605Smrg if (srcHeight > 1 && srcHeight > dstHeight) { 1488848b8605Smrg /* sample from two source rows */ 1489848b8605Smrg srcB = srcA + srcRowStride; 1490848b8605Smrg srcRowStep = 2; 1491848b8605Smrg } 1492848b8605Smrg else { 1493848b8605Smrg /* sample from one source row */ 1494848b8605Smrg srcB = srcA; 1495848b8605Smrg srcRowStep = 1; 1496848b8605Smrg } 1497848b8605Smrg 1498848b8605Smrg dst = dstPtr + border * ((dstWidth + 1) * bpt); 1499848b8605Smrg 1500848b8605Smrg for (row = 0; row < dstHeightNB; row++) { 1501848b8605Smrg do_row(datatype, comps, srcWidthNB, srcA, srcB, 1502848b8605Smrg dstWidthNB, dst); 1503848b8605Smrg srcA += srcRowStep * srcRowStride; 1504848b8605Smrg srcB += srcRowStep * srcRowStride; 1505848b8605Smrg dst += dstRowStride; 1506848b8605Smrg } 1507848b8605Smrg 1508848b8605Smrg /* This is ugly but probably won't be used much */ 1509848b8605Smrg if (border > 0) { 1510848b8605Smrg /* fill in dest border */ 1511848b8605Smrg /* lower-left border pixel */ 1512848b8605Smrg assert(dstPtr); 1513848b8605Smrg assert(srcPtr); 1514848b8605Smrg memcpy(dstPtr, srcPtr, bpt); 1515848b8605Smrg /* lower-right border pixel */ 1516848b8605Smrg memcpy(dstPtr + (dstWidth - 1) * bpt, 1517848b8605Smrg srcPtr + (srcWidth - 1) * bpt, bpt); 1518848b8605Smrg /* upper-left border pixel */ 1519848b8605Smrg memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt, 1520848b8605Smrg srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); 1521848b8605Smrg /* upper-right border pixel */ 1522848b8605Smrg memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt, 1523848b8605Smrg srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); 1524848b8605Smrg /* lower border */ 1525848b8605Smrg do_row(datatype, comps, srcWidthNB, 1526848b8605Smrg srcPtr + bpt, 1527848b8605Smrg srcPtr + bpt, 1528848b8605Smrg dstWidthNB, dstPtr + bpt); 1529848b8605Smrg /* upper border */ 1530848b8605Smrg do_row(datatype, comps, srcWidthNB, 1531848b8605Smrg srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 1532848b8605Smrg srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 1533848b8605Smrg dstWidthNB, 1534848b8605Smrg dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); 1535848b8605Smrg /* left and right borders */ 1536848b8605Smrg if (srcHeight == dstHeight) { 1537848b8605Smrg /* copy border pixel from src to dst */ 1538848b8605Smrg for (row = 1; row < srcHeight; row++) { 1539848b8605Smrg memcpy(dstPtr + dstWidth * row * bpt, 1540848b8605Smrg srcPtr + srcWidth * row * bpt, bpt); 1541848b8605Smrg memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, 1542848b8605Smrg srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); 1543848b8605Smrg } 1544848b8605Smrg } 1545848b8605Smrg else { 1546848b8605Smrg /* average two src pixels each dest pixel */ 1547848b8605Smrg for (row = 0; row < dstHeightNB; row += 2) { 1548848b8605Smrg do_row(datatype, comps, 1, 1549848b8605Smrg srcPtr + (srcWidth * (row * 2 + 1)) * bpt, 1550848b8605Smrg srcPtr + (srcWidth * (row * 2 + 2)) * bpt, 1551848b8605Smrg 1, dstPtr + (dstWidth * row + 1) * bpt); 1552848b8605Smrg do_row(datatype, comps, 1, 1553848b8605Smrg srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, 1554848b8605Smrg srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, 1555848b8605Smrg 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); 1556848b8605Smrg } 1557848b8605Smrg } 1558848b8605Smrg } 1559848b8605Smrg} 1560848b8605Smrg 1561848b8605Smrg 1562848b8605Smrgstatic void 1563848b8605Smrgmake_3d_mipmap(GLenum datatype, GLuint comps, GLint border, 1564848b8605Smrg GLint srcWidth, GLint srcHeight, GLint srcDepth, 1565848b8605Smrg const GLubyte **srcPtr, GLint srcRowStride, 1566848b8605Smrg GLint dstWidth, GLint dstHeight, GLint dstDepth, 1567848b8605Smrg GLubyte **dstPtr, GLint dstRowStride) 1568848b8605Smrg{ 1569848b8605Smrg const GLint bpt = bytes_per_pixel(datatype, comps); 1570848b8605Smrg const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 1571848b8605Smrg const GLint srcDepthNB = srcDepth - 2 * border; 1572848b8605Smrg const GLint dstWidthNB = dstWidth - 2 * border; 1573848b8605Smrg const GLint dstHeightNB = dstHeight - 2 * border; 1574848b8605Smrg const GLint dstDepthNB = dstDepth - 2 * border; 1575848b8605Smrg GLint img, row; 1576848b8605Smrg GLint bytesPerSrcImage, bytesPerDstImage; 1577848b8605Smrg GLint srcImageOffset, srcRowOffset; 1578848b8605Smrg 1579848b8605Smrg (void) srcDepthNB; /* silence warnings */ 1580848b8605Smrg 1581848b8605Smrg bytesPerSrcImage = srcRowStride * srcHeight * bpt; 1582848b8605Smrg bytesPerDstImage = dstRowStride * dstHeight * bpt; 1583848b8605Smrg 1584848b8605Smrg /* Offset between adjacent src images to be averaged together */ 1585848b8605Smrg srcImageOffset = (srcDepth == dstDepth) ? 0 : 1; 1586848b8605Smrg 1587848b8605Smrg /* Offset between adjacent src rows to be averaged together */ 1588848b8605Smrg srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride; 1589848b8605Smrg 1590848b8605Smrg /* 1591848b8605Smrg * Need to average together up to 8 src pixels for each dest pixel. 1592848b8605Smrg * Break that down into 3 operations: 1593848b8605Smrg * 1. take two rows from source image and average them together. 1594848b8605Smrg * 2. take two rows from next source image and average them together. 1595848b8605Smrg * 3. take the two averaged rows and average them for the final dst row. 1596848b8605Smrg */ 1597848b8605Smrg 1598848b8605Smrg /* 1599848b8605Smrg printf("mip3d %d x %d x %d -> %d x %d x %d\n", 1600848b8605Smrg srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); 1601848b8605Smrg */ 1602848b8605Smrg 1603848b8605Smrg for (img = 0; img < dstDepthNB; img++) { 1604848b8605Smrg /* first source image pointer, skipping border */ 1605848b8605Smrg const GLubyte *imgSrcA = srcPtr[img * 2 + border] 1606848b8605Smrg + srcRowStride * border + bpt * border; 1607848b8605Smrg /* second source image pointer, skipping border */ 1608848b8605Smrg const GLubyte *imgSrcB = srcPtr[img * 2 + srcImageOffset + border] 1609848b8605Smrg + srcRowStride * border + bpt * border; 1610848b8605Smrg 1611848b8605Smrg /* address of the dest image, skipping border */ 1612848b8605Smrg GLubyte *imgDst = dstPtr[img + border] 1613848b8605Smrg + dstRowStride * border + bpt * border; 1614848b8605Smrg 1615848b8605Smrg /* setup the four source row pointers and the dest row pointer */ 1616848b8605Smrg const GLubyte *srcImgARowA = imgSrcA; 1617848b8605Smrg const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; 1618848b8605Smrg const GLubyte *srcImgBRowA = imgSrcB; 1619848b8605Smrg const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; 1620848b8605Smrg GLubyte *dstImgRow = imgDst; 1621848b8605Smrg 1622848b8605Smrg for (row = 0; row < dstHeightNB; row++) { 1623848b8605Smrg do_row_3D(datatype, comps, srcWidthNB, 1624848b8605Smrg srcImgARowA, srcImgARowB, 1625848b8605Smrg srcImgBRowA, srcImgBRowB, 1626848b8605Smrg dstWidthNB, dstImgRow); 1627848b8605Smrg 1628848b8605Smrg /* advance to next rows */ 1629848b8605Smrg srcImgARowA += srcRowStride + srcRowOffset; 1630848b8605Smrg srcImgARowB += srcRowStride + srcRowOffset; 1631848b8605Smrg srcImgBRowA += srcRowStride + srcRowOffset; 1632848b8605Smrg srcImgBRowB += srcRowStride + srcRowOffset; 1633848b8605Smrg dstImgRow += dstRowStride; 1634848b8605Smrg } 1635848b8605Smrg } 1636848b8605Smrg 1637848b8605Smrg 1638848b8605Smrg /* Luckily we can leverage the make_2d_mipmap() function here! */ 1639848b8605Smrg if (border > 0) { 1640848b8605Smrg /* do front border image */ 1641848b8605Smrg make_2d_mipmap(datatype, comps, 1, 1642848b8605Smrg srcWidth, srcHeight, srcPtr[0], srcRowStride, 1643848b8605Smrg dstWidth, dstHeight, dstPtr[0], dstRowStride); 1644848b8605Smrg /* do back border image */ 1645848b8605Smrg make_2d_mipmap(datatype, comps, 1, 1646848b8605Smrg srcWidth, srcHeight, srcPtr[srcDepth - 1], srcRowStride, 1647848b8605Smrg dstWidth, dstHeight, dstPtr[dstDepth - 1], dstRowStride); 1648848b8605Smrg 1649848b8605Smrg /* do four remaining border edges that span the image slices */ 1650848b8605Smrg if (srcDepth == dstDepth) { 1651848b8605Smrg /* just copy border pixels from src to dst */ 1652848b8605Smrg for (img = 0; img < dstDepthNB; img++) { 1653848b8605Smrg const GLubyte *src; 1654848b8605Smrg GLubyte *dst; 1655848b8605Smrg 1656848b8605Smrg /* do border along [img][row=0][col=0] */ 1657848b8605Smrg src = srcPtr[img * 2]; 1658848b8605Smrg dst = dstPtr[img]; 1659848b8605Smrg memcpy(dst, src, bpt); 1660848b8605Smrg 1661848b8605Smrg /* do border along [img][row=dstHeight-1][col=0] */ 1662848b8605Smrg src = srcPtr[img * 2] + (srcHeight - 1) * srcRowStride; 1663848b8605Smrg dst = dstPtr[img] + (dstHeight - 1) * dstRowStride; 1664848b8605Smrg memcpy(dst, src, bpt); 1665848b8605Smrg 1666848b8605Smrg /* do border along [img][row=0][col=dstWidth-1] */ 1667848b8605Smrg src = srcPtr[img * 2] + (srcWidth - 1) * bpt; 1668848b8605Smrg dst = dstPtr[img] + (dstWidth - 1) * bpt; 1669848b8605Smrg memcpy(dst, src, bpt); 1670848b8605Smrg 1671848b8605Smrg /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ 1672848b8605Smrg src = srcPtr[img * 2] + (bytesPerSrcImage - bpt); 1673848b8605Smrg dst = dstPtr[img] + (bytesPerDstImage - bpt); 1674848b8605Smrg memcpy(dst, src, bpt); 1675848b8605Smrg } 1676848b8605Smrg } 1677848b8605Smrg else { 1678848b8605Smrg /* average border pixels from adjacent src image pairs */ 1679b8e80941Smrg assert(srcDepthNB == 2 * dstDepthNB); 1680848b8605Smrg for (img = 0; img < dstDepthNB; img++) { 1681848b8605Smrg const GLubyte *srcA, *srcB; 1682848b8605Smrg GLubyte *dst; 1683848b8605Smrg 1684848b8605Smrg /* do border along [img][row=0][col=0] */ 1685848b8605Smrg srcA = srcPtr[img * 2 + 0]; 1686848b8605Smrg srcB = srcPtr[img * 2 + srcImageOffset]; 1687848b8605Smrg dst = dstPtr[img]; 1688848b8605Smrg do_row(datatype, comps, 1, srcA, srcB, 1, dst); 1689848b8605Smrg 1690848b8605Smrg /* do border along [img][row=dstHeight-1][col=0] */ 1691848b8605Smrg srcA = srcPtr[img * 2 + 0] 1692848b8605Smrg + (srcHeight - 1) * srcRowStride; 1693848b8605Smrg srcB = srcPtr[img * 2 + srcImageOffset] 1694848b8605Smrg + (srcHeight - 1) * srcRowStride; 1695848b8605Smrg dst = dstPtr[img] + (dstHeight - 1) * dstRowStride; 1696848b8605Smrg do_row(datatype, comps, 1, srcA, srcB, 1, dst); 1697848b8605Smrg 1698848b8605Smrg /* do border along [img][row=0][col=dstWidth-1] */ 1699848b8605Smrg srcA = srcPtr[img * 2 + 0] + (srcWidth - 1) * bpt; 1700848b8605Smrg srcB = srcPtr[img * 2 + srcImageOffset] + (srcWidth - 1) * bpt; 1701848b8605Smrg dst = dstPtr[img] + (dstWidth - 1) * bpt; 1702848b8605Smrg do_row(datatype, comps, 1, srcA, srcB, 1, dst); 1703848b8605Smrg 1704848b8605Smrg /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ 1705848b8605Smrg srcA = srcPtr[img * 2 + 0] + (bytesPerSrcImage - bpt); 1706848b8605Smrg srcB = srcPtr[img * 2 + srcImageOffset] + (bytesPerSrcImage - bpt); 1707848b8605Smrg dst = dstPtr[img] + (bytesPerDstImage - bpt); 1708848b8605Smrg do_row(datatype, comps, 1, srcA, srcB, 1, dst); 1709848b8605Smrg } 1710848b8605Smrg } 1711848b8605Smrg } 1712848b8605Smrg} 1713848b8605Smrg 1714848b8605Smrg 1715848b8605Smrg/** 1716848b8605Smrg * Down-sample a texture image to produce the next lower mipmap level. 1717848b8605Smrg * \param comps components per texel (1, 2, 3 or 4) 1718848b8605Smrg * \param srcData array[slice] of pointers to source image slices 1719848b8605Smrg * \param dstData array[slice] of pointers to dest image slices 1720848b8605Smrg * \param srcRowStride stride between source rows, in bytes 1721848b8605Smrg * \param dstRowStride stride between destination rows, in bytes 1722848b8605Smrg */ 1723848b8605Smrgvoid 1724848b8605Smrg_mesa_generate_mipmap_level(GLenum target, 1725848b8605Smrg GLenum datatype, GLuint comps, 1726848b8605Smrg GLint border, 1727848b8605Smrg GLint srcWidth, GLint srcHeight, GLint srcDepth, 1728848b8605Smrg const GLubyte **srcData, 1729848b8605Smrg GLint srcRowStride, 1730848b8605Smrg GLint dstWidth, GLint dstHeight, GLint dstDepth, 1731848b8605Smrg GLubyte **dstData, 1732848b8605Smrg GLint dstRowStride) 1733848b8605Smrg{ 1734848b8605Smrg int i; 1735848b8605Smrg 1736848b8605Smrg switch (target) { 1737848b8605Smrg case GL_TEXTURE_1D: 1738848b8605Smrg make_1d_mipmap(datatype, comps, border, 1739848b8605Smrg srcWidth, srcData[0], 1740848b8605Smrg dstWidth, dstData[0]); 1741848b8605Smrg break; 1742848b8605Smrg case GL_TEXTURE_2D: 1743b8e80941Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1744b8e80941Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1745b8e80941Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1746b8e80941Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1747b8e80941Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1748b8e80941Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1749848b8605Smrg make_2d_mipmap(datatype, comps, border, 1750848b8605Smrg srcWidth, srcHeight, srcData[0], srcRowStride, 1751848b8605Smrg dstWidth, dstHeight, dstData[0], dstRowStride); 1752848b8605Smrg break; 1753848b8605Smrg case GL_TEXTURE_3D: 1754848b8605Smrg make_3d_mipmap(datatype, comps, border, 1755848b8605Smrg srcWidth, srcHeight, srcDepth, 1756848b8605Smrg srcData, srcRowStride, 1757848b8605Smrg dstWidth, dstHeight, dstDepth, 1758848b8605Smrg dstData, dstRowStride); 1759848b8605Smrg break; 1760848b8605Smrg case GL_TEXTURE_1D_ARRAY_EXT: 1761848b8605Smrg assert(srcHeight == 1); 1762848b8605Smrg assert(dstHeight == 1); 1763848b8605Smrg for (i = 0; i < dstDepth; i++) { 1764b8e80941Smrg make_1d_mipmap(datatype, comps, border, 1765b8e80941Smrg srcWidth, srcData[i], 1766b8e80941Smrg dstWidth, dstData[i]); 1767848b8605Smrg } 1768848b8605Smrg break; 1769848b8605Smrg case GL_TEXTURE_2D_ARRAY_EXT: 1770848b8605Smrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1771848b8605Smrg for (i = 0; i < dstDepth; i++) { 1772b8e80941Smrg make_2d_mipmap(datatype, comps, border, 1773b8e80941Smrg srcWidth, srcHeight, srcData[i], srcRowStride, 1774b8e80941Smrg dstWidth, dstHeight, dstData[i], dstRowStride); 1775848b8605Smrg } 1776848b8605Smrg break; 1777848b8605Smrg case GL_TEXTURE_RECTANGLE_NV: 1778848b8605Smrg case GL_TEXTURE_EXTERNAL_OES: 1779848b8605Smrg /* no mipmaps, do nothing */ 1780848b8605Smrg break; 1781848b8605Smrg default: 1782b8e80941Smrg unreachable("bad tex target in _mesa_generate_mipmaps"); 1783848b8605Smrg } 1784848b8605Smrg} 1785848b8605Smrg 1786848b8605Smrg 1787848b8605Smrg/** 1788848b8605Smrg * compute next (level+1) image size 1789848b8605Smrg * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size) 1790848b8605Smrg */ 1791848b8605SmrgGLboolean 1792848b8605Smrg_mesa_next_mipmap_level_size(GLenum target, GLint border, 1793848b8605Smrg GLint srcWidth, GLint srcHeight, GLint srcDepth, 1794848b8605Smrg GLint *dstWidth, GLint *dstHeight, GLint *dstDepth) 1795848b8605Smrg{ 1796848b8605Smrg if (srcWidth - 2 * border > 1) { 1797848b8605Smrg *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; 1798848b8605Smrg } 1799848b8605Smrg else { 1800848b8605Smrg *dstWidth = srcWidth; /* can't go smaller */ 1801848b8605Smrg } 1802848b8605Smrg 1803b8e80941Smrg if ((srcHeight - 2 * border > 1) && 1804b8e80941Smrg target != GL_TEXTURE_1D_ARRAY_EXT && 1805b8e80941Smrg target != GL_PROXY_TEXTURE_1D_ARRAY_EXT) { 1806848b8605Smrg *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; 1807848b8605Smrg } 1808848b8605Smrg else { 1809848b8605Smrg *dstHeight = srcHeight; /* can't go smaller */ 1810848b8605Smrg } 1811848b8605Smrg 1812848b8605Smrg if ((srcDepth - 2 * border > 1) && 1813b8e80941Smrg target != GL_TEXTURE_2D_ARRAY_EXT && 1814b8e80941Smrg target != GL_PROXY_TEXTURE_2D_ARRAY_EXT && 1815b8e80941Smrg target != GL_TEXTURE_CUBE_MAP_ARRAY && 1816b8e80941Smrg target != GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) { 1817848b8605Smrg *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; 1818848b8605Smrg } 1819848b8605Smrg else { 1820848b8605Smrg *dstDepth = srcDepth; /* can't go smaller */ 1821848b8605Smrg } 1822848b8605Smrg 1823848b8605Smrg if (*dstWidth == srcWidth && 1824848b8605Smrg *dstHeight == srcHeight && 1825848b8605Smrg *dstDepth == srcDepth) { 1826848b8605Smrg return GL_FALSE; 1827848b8605Smrg } 1828848b8605Smrg else { 1829848b8605Smrg return GL_TRUE; 1830848b8605Smrg } 1831848b8605Smrg} 1832848b8605Smrg 1833848b8605Smrg 1834848b8605Smrg/** 1835848b8605Smrg * Helper function for mipmap generation. 1836848b8605Smrg * Make sure the specified destination mipmap level is the right size/format 1837848b8605Smrg * for mipmap generation. If not, (re) allocate it. 1838848b8605Smrg * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop 1839848b8605Smrg */ 1840b8e80941Smrgstatic GLboolean 1841b8e80941Smrgprepare_mipmap_level(struct gl_context *ctx, 1842b8e80941Smrg struct gl_texture_object *texObj, GLuint level, 1843b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1844b8e80941Smrg GLsizei border, GLenum intFormat, mesa_format format) 1845848b8605Smrg{ 1846848b8605Smrg const GLuint numFaces = _mesa_num_tex_faces(texObj->Target); 1847848b8605Smrg GLuint face; 1848848b8605Smrg 1849848b8605Smrg if (texObj->Immutable) { 1850848b8605Smrg /* The texture was created with glTexStorage() so the number/size of 1851848b8605Smrg * mipmap levels is fixed and the storage for all images is already 1852848b8605Smrg * allocated. 1853848b8605Smrg */ 1854848b8605Smrg if (!texObj->Image[0][level]) { 1855848b8605Smrg /* No more levels to create - we're done */ 1856848b8605Smrg return GL_FALSE; 1857848b8605Smrg } 1858848b8605Smrg else { 1859848b8605Smrg /* Nothing to do - the texture memory must have already been 1860848b8605Smrg * allocated to the right size so we're all set. 1861848b8605Smrg */ 1862848b8605Smrg return GL_TRUE; 1863848b8605Smrg } 1864848b8605Smrg } 1865848b8605Smrg 1866848b8605Smrg for (face = 0; face < numFaces; face++) { 1867848b8605Smrg struct gl_texture_image *dstImage; 1868b8e80941Smrg const GLenum target = _mesa_cube_face_target(texObj->Target, face); 1869848b8605Smrg 1870848b8605Smrg dstImage = _mesa_get_tex_image(ctx, texObj, target, level); 1871848b8605Smrg if (!dstImage) { 1872848b8605Smrg /* out of memory */ 1873848b8605Smrg return GL_FALSE; 1874848b8605Smrg } 1875848b8605Smrg 1876848b8605Smrg if (dstImage->Width != width || 1877848b8605Smrg dstImage->Height != height || 1878848b8605Smrg dstImage->Depth != depth || 1879848b8605Smrg dstImage->Border != border || 1880848b8605Smrg dstImage->InternalFormat != intFormat || 1881848b8605Smrg dstImage->TexFormat != format) { 1882848b8605Smrg /* need to (re)allocate image */ 1883848b8605Smrg ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); 1884848b8605Smrg 1885848b8605Smrg _mesa_init_teximage_fields(ctx, dstImage, 1886848b8605Smrg width, height, depth, 1887848b8605Smrg border, intFormat, format); 1888848b8605Smrg 1889848b8605Smrg ctx->Driver.AllocTextureImageBuffer(ctx, dstImage); 1890848b8605Smrg 1891848b8605Smrg /* in case the mipmap level is part of an FBO: */ 1892848b8605Smrg _mesa_update_fbo_texture(ctx, texObj, face, level); 1893848b8605Smrg 1894b8e80941Smrg ctx->NewState |= _NEW_TEXTURE_OBJECT; 1895848b8605Smrg } 1896848b8605Smrg } 1897848b8605Smrg 1898848b8605Smrg return GL_TRUE; 1899848b8605Smrg} 1900848b8605Smrg 1901848b8605Smrg 1902b8e80941Smrg/** 1903b8e80941Smrg * Prepare all mipmap levels beyond 'baseLevel' for mipmap generation. 1904b8e80941Smrg * When finished, all the gl_texture_image structures for the smaller 1905b8e80941Smrg * mipmap levels will be consistent with the base level (in terms of 1906b8e80941Smrg * dimensions, format, etc). 1907b8e80941Smrg */ 1908b8e80941Smrgvoid 1909b8e80941Smrg_mesa_prepare_mipmap_levels(struct gl_context *ctx, 1910b8e80941Smrg struct gl_texture_object *texObj, 1911b8e80941Smrg unsigned baseLevel, unsigned maxLevel) 1912b8e80941Smrg{ 1913b8e80941Smrg const struct gl_texture_image *baseImage = 1914b8e80941Smrg _mesa_select_tex_image(texObj, texObj->Target, baseLevel); 1915b8e80941Smrg const GLint border = 0; 1916b8e80941Smrg GLint width = baseImage->Width; 1917b8e80941Smrg GLint height = baseImage->Height; 1918b8e80941Smrg GLint depth = baseImage->Depth; 1919b8e80941Smrg const GLenum intFormat = baseImage->InternalFormat; 1920b8e80941Smrg const mesa_format texFormat = baseImage->TexFormat; 1921b8e80941Smrg GLint newWidth, newHeight, newDepth; 1922b8e80941Smrg 1923b8e80941Smrg /* Prepare baseLevel + 1, baseLevel + 2, ... */ 1924b8e80941Smrg for (unsigned level = baseLevel + 1; level <= maxLevel; level++) { 1925b8e80941Smrg if (!_mesa_next_mipmap_level_size(texObj->Target, border, 1926b8e80941Smrg width, height, depth, 1927b8e80941Smrg &newWidth, &newHeight, &newDepth)) { 1928b8e80941Smrg /* all done */ 1929b8e80941Smrg break; 1930b8e80941Smrg } 1931b8e80941Smrg 1932b8e80941Smrg if (!prepare_mipmap_level(ctx, texObj, level, 1933b8e80941Smrg newWidth, newHeight, newDepth, 1934b8e80941Smrg border, intFormat, texFormat)) { 1935b8e80941Smrg break; 1936b8e80941Smrg } 1937b8e80941Smrg 1938b8e80941Smrg width = newWidth; 1939b8e80941Smrg height = newHeight; 1940b8e80941Smrg depth = newDepth; 1941b8e80941Smrg } 1942b8e80941Smrg} 1943b8e80941Smrg 1944b8e80941Smrg 1945848b8605Smrgstatic void 1946848b8605Smrggenerate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, 1947b8e80941Smrg struct gl_texture_object *texObj, 1948b8e80941Smrg const struct gl_texture_image *srcImage, 1949b8e80941Smrg GLuint maxLevel) 1950848b8605Smrg{ 1951848b8605Smrg GLuint level; 1952848b8605Smrg GLenum datatype; 1953848b8605Smrg GLuint comps; 1954848b8605Smrg 1955b8e80941Smrg _mesa_uncompressed_format_to_type_and_comps(srcImage->TexFormat, &datatype, &comps); 1956848b8605Smrg 1957848b8605Smrg for (level = texObj->BaseLevel; level < maxLevel; level++) { 1958848b8605Smrg /* generate image[level+1] from image[level] */ 1959848b8605Smrg struct gl_texture_image *srcImage, *dstImage; 1960848b8605Smrg GLint srcRowStride, dstRowStride; 1961848b8605Smrg GLint srcWidth, srcHeight, srcDepth; 1962848b8605Smrg GLint dstWidth, dstHeight, dstDepth; 1963848b8605Smrg GLint border; 1964848b8605Smrg GLint slice; 1965848b8605Smrg GLubyte **srcMaps, **dstMaps; 1966848b8605Smrg GLboolean success = GL_TRUE; 1967848b8605Smrg 1968848b8605Smrg /* get src image parameters */ 1969b8e80941Smrg srcImage = _mesa_select_tex_image(texObj, target, level); 1970b8e80941Smrg assert(srcImage); 1971848b8605Smrg srcWidth = srcImage->Width; 1972848b8605Smrg srcHeight = srcImage->Height; 1973848b8605Smrg srcDepth = srcImage->Depth; 1974848b8605Smrg border = srcImage->Border; 1975848b8605Smrg 1976848b8605Smrg /* get dest gl_texture_image */ 1977b8e80941Smrg dstImage = _mesa_select_tex_image(texObj, target, level + 1); 1978848b8605Smrg if (!dstImage) { 1979b8e80941Smrg break; 1980848b8605Smrg } 1981b8e80941Smrg dstWidth = dstImage->Width; 1982b8e80941Smrg dstHeight = dstImage->Height; 1983b8e80941Smrg dstDepth = dstImage->Depth; 1984848b8605Smrg 1985848b8605Smrg if (target == GL_TEXTURE_1D_ARRAY) { 1986b8e80941Smrg srcDepth = srcHeight; 1987b8e80941Smrg dstDepth = dstHeight; 1988b8e80941Smrg srcHeight = 1; 1989b8e80941Smrg dstHeight = 1; 1990848b8605Smrg } 1991848b8605Smrg 1992848b8605Smrg /* Map src texture image slices */ 1993848b8605Smrg srcMaps = calloc(srcDepth, sizeof(GLubyte *)); 1994848b8605Smrg if (srcMaps) { 1995848b8605Smrg for (slice = 0; slice < srcDepth; slice++) { 1996848b8605Smrg ctx->Driver.MapTextureImage(ctx, srcImage, slice, 1997848b8605Smrg 0, 0, srcWidth, srcHeight, 1998848b8605Smrg GL_MAP_READ_BIT, 1999848b8605Smrg &srcMaps[slice], &srcRowStride); 2000848b8605Smrg if (!srcMaps[slice]) { 2001848b8605Smrg success = GL_FALSE; 2002848b8605Smrg break; 2003848b8605Smrg } 2004848b8605Smrg } 2005848b8605Smrg } 2006848b8605Smrg else { 2007848b8605Smrg success = GL_FALSE; 2008848b8605Smrg } 2009848b8605Smrg 2010848b8605Smrg /* Map dst texture image slices */ 2011848b8605Smrg dstMaps = calloc(dstDepth, sizeof(GLubyte *)); 2012848b8605Smrg if (dstMaps) { 2013848b8605Smrg for (slice = 0; slice < dstDepth; slice++) { 2014848b8605Smrg ctx->Driver.MapTextureImage(ctx, dstImage, slice, 2015848b8605Smrg 0, 0, dstWidth, dstHeight, 2016848b8605Smrg GL_MAP_WRITE_BIT, 2017848b8605Smrg &dstMaps[slice], &dstRowStride); 2018848b8605Smrg if (!dstMaps[slice]) { 2019848b8605Smrg success = GL_FALSE; 2020848b8605Smrg break; 2021848b8605Smrg } 2022848b8605Smrg } 2023848b8605Smrg } 2024848b8605Smrg else { 2025848b8605Smrg success = GL_FALSE; 2026848b8605Smrg } 2027848b8605Smrg 2028848b8605Smrg if (success) { 2029848b8605Smrg /* generate one mipmap level (for 1D/2D/3D/array/etc texture) */ 2030848b8605Smrg _mesa_generate_mipmap_level(target, datatype, comps, border, 2031848b8605Smrg srcWidth, srcHeight, srcDepth, 2032848b8605Smrg (const GLubyte **) srcMaps, srcRowStride, 2033848b8605Smrg dstWidth, dstHeight, dstDepth, 2034848b8605Smrg dstMaps, dstRowStride); 2035848b8605Smrg } 2036848b8605Smrg 2037848b8605Smrg /* Unmap src image slices */ 2038848b8605Smrg if (srcMaps) { 2039848b8605Smrg for (slice = 0; slice < srcDepth; slice++) { 2040848b8605Smrg if (srcMaps[slice]) { 2041848b8605Smrg ctx->Driver.UnmapTextureImage(ctx, srcImage, slice); 2042848b8605Smrg } 2043848b8605Smrg } 2044848b8605Smrg free(srcMaps); 2045848b8605Smrg } 2046848b8605Smrg 2047848b8605Smrg /* Unmap dst image slices */ 2048848b8605Smrg if (dstMaps) { 2049848b8605Smrg for (slice = 0; slice < dstDepth; slice++) { 2050848b8605Smrg if (dstMaps[slice]) { 2051848b8605Smrg ctx->Driver.UnmapTextureImage(ctx, dstImage, slice); 2052848b8605Smrg } 2053848b8605Smrg } 2054848b8605Smrg free(dstMaps); 2055848b8605Smrg } 2056848b8605Smrg 2057848b8605Smrg if (!success) { 2058848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation"); 2059848b8605Smrg break; 2060848b8605Smrg } 2061848b8605Smrg } /* loop over mipmap levels */ 2062848b8605Smrg} 2063848b8605Smrg 2064848b8605Smrg 2065848b8605Smrgstatic void 2066848b8605Smrggenerate_mipmap_compressed(struct gl_context *ctx, GLenum target, 2067b8e80941Smrg struct gl_texture_object *texObj, 2068b8e80941Smrg struct gl_texture_image *srcImage, 2069b8e80941Smrg GLuint maxLevel) 2070848b8605Smrg{ 2071848b8605Smrg GLuint level; 2072848b8605Smrg mesa_format temp_format; 2073848b8605Smrg GLint components; 2074848b8605Smrg GLuint temp_src_row_stride, temp_src_img_stride; /* in bytes */ 2075848b8605Smrg GLubyte *temp_src = NULL, *temp_dst = NULL; 2076848b8605Smrg GLenum temp_datatype; 2077848b8605Smrg GLenum temp_base_format; 2078848b8605Smrg GLubyte **temp_src_slices = NULL, **temp_dst_slices = NULL; 2079848b8605Smrg 2080848b8605Smrg /* only two types of compressed textures at this time */ 2081848b8605Smrg assert(texObj->Target == GL_TEXTURE_2D || 2082b8e80941Smrg texObj->Target == GL_TEXTURE_2D_ARRAY || 2083b8e80941Smrg texObj->Target == GL_TEXTURE_CUBE_MAP || 2084848b8605Smrg texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY); 2085848b8605Smrg 2086848b8605Smrg /* 2087848b8605Smrg * Choose a format for the temporary, uncompressed base image. 2088848b8605Smrg * Then, get number of components, choose temporary image datatype, 2089848b8605Smrg * and get base format. 2090848b8605Smrg */ 2091848b8605Smrg temp_format = _mesa_get_uncompressed_format(srcImage->TexFormat); 2092848b8605Smrg 2093848b8605Smrg components = _mesa_format_num_components(temp_format); 2094848b8605Smrg 2095848b8605Smrg switch (_mesa_get_format_datatype(srcImage->TexFormat)) { 2096848b8605Smrg case GL_FLOAT: 2097848b8605Smrg temp_datatype = GL_FLOAT; 2098848b8605Smrg break; 2099848b8605Smrg case GL_SIGNED_NORMALIZED: 2100848b8605Smrg /* Revisit this if we get compressed formats with >8 bits per component */ 2101848b8605Smrg temp_datatype = GL_BYTE; 2102848b8605Smrg break; 2103848b8605Smrg default: 2104848b8605Smrg temp_datatype = GL_UNSIGNED_BYTE; 2105848b8605Smrg } 2106848b8605Smrg 2107848b8605Smrg temp_base_format = _mesa_get_format_base_format(temp_format); 2108848b8605Smrg 2109848b8605Smrg 2110848b8605Smrg /* allocate storage for the temporary, uncompressed image */ 2111848b8605Smrg temp_src_row_stride = _mesa_format_row_stride(temp_format, srcImage->Width); 2112848b8605Smrg temp_src_img_stride = _mesa_format_image_size(temp_format, srcImage->Width, 2113848b8605Smrg srcImage->Height, 1); 2114848b8605Smrg temp_src = malloc(temp_src_img_stride * srcImage->Depth); 2115848b8605Smrg 2116848b8605Smrg /* Allocate storage for arrays of slice pointers */ 2117848b8605Smrg temp_src_slices = malloc(srcImage->Depth * sizeof(GLubyte *)); 2118848b8605Smrg temp_dst_slices = malloc(srcImage->Depth * sizeof(GLubyte *)); 2119848b8605Smrg 2120848b8605Smrg if (!temp_src || !temp_src_slices || !temp_dst_slices) { 2121848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); 2122848b8605Smrg goto end; 2123848b8605Smrg } 2124848b8605Smrg 2125848b8605Smrg /* decompress base image to the temporary src buffer */ 2126848b8605Smrg { 2127848b8605Smrg /* save pixel packing mode */ 2128848b8605Smrg struct gl_pixelstore_attrib save = ctx->Pack; 2129848b8605Smrg /* use default/tight packing parameters */ 2130848b8605Smrg ctx->Pack = ctx->DefaultPacking; 2131848b8605Smrg 2132848b8605Smrg /* Get the uncompressed image */ 2133848b8605Smrg assert(srcImage->Level == texObj->BaseLevel); 2134b8e80941Smrg ctx->Driver.GetTexSubImage(ctx, 2135b8e80941Smrg 0, 0, 0, 2136b8e80941Smrg srcImage->Width, srcImage->Height, 2137b8e80941Smrg srcImage->Depth, 2138b8e80941Smrg temp_base_format, temp_datatype, 2139b8e80941Smrg temp_src, srcImage); 2140848b8605Smrg /* restore packing mode */ 2141848b8605Smrg ctx->Pack = save; 2142848b8605Smrg } 2143848b8605Smrg 2144848b8605Smrg for (level = texObj->BaseLevel; level < maxLevel; level++) { 2145848b8605Smrg /* generate image[level+1] from image[level] */ 2146848b8605Smrg const struct gl_texture_image *srcImage; 2147848b8605Smrg struct gl_texture_image *dstImage; 2148848b8605Smrg GLint srcWidth, srcHeight, srcDepth; 2149848b8605Smrg GLint dstWidth, dstHeight, dstDepth; 2150848b8605Smrg GLint border; 2151848b8605Smrg GLuint temp_dst_row_stride, temp_dst_img_stride; /* in bytes */ 2152b8e80941Smrg GLint i; 2153848b8605Smrg 2154848b8605Smrg /* get src image parameters */ 2155b8e80941Smrg srcImage = _mesa_select_tex_image(texObj, target, level); 2156b8e80941Smrg assert(srcImage); 2157848b8605Smrg srcWidth = srcImage->Width; 2158848b8605Smrg srcHeight = srcImage->Height; 2159848b8605Smrg srcDepth = srcImage->Depth; 2160848b8605Smrg border = srcImage->Border; 2161848b8605Smrg 2162b8e80941Smrg /* get dest gl_texture_image */ 2163b8e80941Smrg dstImage = _mesa_select_tex_image(texObj, target, level + 1); 2164b8e80941Smrg if (!dstImage) { 2165b8e80941Smrg break; 2166b8e80941Smrg } 2167b8e80941Smrg dstWidth = dstImage->Width; 2168b8e80941Smrg dstHeight = dstImage->Height; 2169b8e80941Smrg dstDepth = dstImage->Depth; 2170848b8605Smrg 2171848b8605Smrg /* Compute dst image strides and alloc memory on first iteration */ 2172848b8605Smrg temp_dst_row_stride = _mesa_format_row_stride(temp_format, dstWidth); 2173848b8605Smrg temp_dst_img_stride = _mesa_format_image_size(temp_format, dstWidth, 2174848b8605Smrg dstHeight, 1); 2175848b8605Smrg if (!temp_dst) { 2176b8e80941Smrg temp_dst = malloc(temp_dst_img_stride * dstDepth); 2177b8e80941Smrg if (!temp_dst) { 2178b8e80941Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); 2179848b8605Smrg goto end; 2180b8e80941Smrg } 2181848b8605Smrg } 2182848b8605Smrg 2183848b8605Smrg /* for 2D arrays, setup array[depth] of slice pointers */ 2184848b8605Smrg for (i = 0; i < srcDepth; i++) { 2185848b8605Smrg temp_src_slices[i] = temp_src + temp_src_img_stride * i; 2186848b8605Smrg } 2187848b8605Smrg for (i = 0; i < dstDepth; i++) { 2188848b8605Smrg temp_dst_slices[i] = temp_dst + temp_dst_img_stride * i; 2189848b8605Smrg } 2190848b8605Smrg 2191848b8605Smrg /* Rescale src image to dest image. 2192848b8605Smrg * This will loop over the slices of a 2D array. 2193848b8605Smrg */ 2194848b8605Smrg _mesa_generate_mipmap_level(target, temp_datatype, components, border, 2195848b8605Smrg srcWidth, srcHeight, srcDepth, 2196848b8605Smrg (const GLubyte **) temp_src_slices, 2197848b8605Smrg temp_src_row_stride, 2198848b8605Smrg dstWidth, dstHeight, dstDepth, 2199848b8605Smrg temp_dst_slices, temp_dst_row_stride); 2200848b8605Smrg 2201848b8605Smrg /* The image space was allocated above so use glTexSubImage now */ 2202848b8605Smrg ctx->Driver.TexSubImage(ctx, 2, dstImage, 2203848b8605Smrg 0, 0, 0, dstWidth, dstHeight, dstDepth, 2204848b8605Smrg temp_base_format, temp_datatype, 2205848b8605Smrg temp_dst, &ctx->DefaultPacking); 2206848b8605Smrg 2207848b8605Smrg /* swap src and dest pointers */ 2208848b8605Smrg { 2209b8e80941Smrg GLubyte *temp = temp_src; 2210b8e80941Smrg temp_src = temp_dst; 2211b8e80941Smrg temp_dst = temp; 2212848b8605Smrg temp_src_row_stride = temp_dst_row_stride; 2213848b8605Smrg temp_src_img_stride = temp_dst_img_stride; 2214848b8605Smrg } 2215848b8605Smrg } /* loop over mipmap levels */ 2216848b8605Smrg 2217848b8605Smrgend: 2218848b8605Smrg free(temp_src); 2219848b8605Smrg free(temp_dst); 2220848b8605Smrg free(temp_src_slices); 2221848b8605Smrg free(temp_dst_slices); 2222848b8605Smrg} 2223848b8605Smrg 2224848b8605Smrg/** 2225848b8605Smrg * Automatic mipmap generation. 2226848b8605Smrg * This is the fallback/default function for ctx->Driver.GenerateMipmap(). 2227848b8605Smrg * Generate a complete set of mipmaps from texObj's BaseLevel image. 2228848b8605Smrg * Stop at texObj's MaxLevel or when we get to the 1x1 texture. 2229848b8605Smrg * For cube maps, target will be one of 2230848b8605Smrg * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP. 2231848b8605Smrg */ 2232848b8605Smrgvoid 2233848b8605Smrg_mesa_generate_mipmap(struct gl_context *ctx, GLenum target, 2234848b8605Smrg struct gl_texture_object *texObj) 2235848b8605Smrg{ 2236848b8605Smrg struct gl_texture_image *srcImage; 2237848b8605Smrg GLint maxLevel; 2238848b8605Smrg 2239b8e80941Smrg assert(texObj); 2240b8e80941Smrg srcImage = _mesa_select_tex_image(texObj, target, texObj->BaseLevel); 2241b8e80941Smrg assert(srcImage); 2242848b8605Smrg 2243848b8605Smrg maxLevel = _mesa_max_texture_levels(ctx, texObj->Target) - 1; 2244b8e80941Smrg assert(maxLevel >= 0); /* bad target */ 2245848b8605Smrg 2246848b8605Smrg maxLevel = MIN2(maxLevel, texObj->MaxLevel); 2247848b8605Smrg 2248b8e80941Smrg _mesa_prepare_mipmap_levels(ctx, texObj, texObj->BaseLevel, maxLevel); 2249b8e80941Smrg 2250848b8605Smrg if (_mesa_is_format_compressed(srcImage->TexFormat)) { 2251848b8605Smrg generate_mipmap_compressed(ctx, target, texObj, srcImage, maxLevel); 2252848b8605Smrg } else { 2253848b8605Smrg generate_mipmap_uncompressed(ctx, target, texObj, srcImage, maxLevel); 2254848b8605Smrg } 2255848b8605Smrg} 2256