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