From 0e661faf8cf2e3460b5e2389414f99c035ad4d6a Mon Sep 17 00:00:00 2001 From: marha Date: Wed, 15 Jun 2011 16:50:54 +0200 Subject: mesa xserver git update 15 June 2011 --- mesalib/src/mesa/main/mipmap.c | 4442 +++++++++++----------- mesalib/src/mesa/state_tracker/st_atom_blend.c | 61 +- mesalib/src/mesa/state_tracker/st_atom_clip.c | 151 +- mesalib/src/mesa/state_tracker/st_atom_sampler.c | 550 +-- mesalib/src/mesa/state_tracker/st_atom_scissor.c | 201 +- mesalib/src/mesa/state_tracker/st_atom_stipple.c | 187 +- mesalib/src/mesa/state_tracker/st_atom_texture.c | 762 ++-- mesalib/src/mesa/state_tracker/st_draw.c | 61 +- 8 files changed, 3229 insertions(+), 3186 deletions(-) (limited to 'mesalib/src/mesa') diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index ed93cbc6c..f2724dbca 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -1,2202 +1,2240 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -/** - * \file mipmap.c mipmap generation and teximage resizing functions. - */ - -#include "imports.h" -#include "formats.h" -#include "mipmap.h" -#include "mtypes.h" -#include "teximage.h" -#include "texstore.h" -#include "image.h" -#include "macros.h" -#include "../../gallium/auxiliary/util/u_format_rgb9e5.h" -#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" - - - -static GLint -bytes_per_pixel(GLenum datatype, GLuint comps) -{ - GLint b = _mesa_sizeof_packed_type(datatype); - assert(b >= 0); - - if (_mesa_type_is_packed(datatype)) - return b; - else - return b * comps; -} - - -/** - * \name Support macros for do_row and do_row_3d - * - * The macro madness is here for two reasons. First, it compacts the code - * slightly. Second, it makes it much easier to adjust the specifics of the - * filter to tune the rounding characteristics. - */ -/*@{*/ -#define DECLARE_ROW_POINTERS(t, e) \ - const t(*rowA)[e] = (const t(*)[e]) srcRowA; \ - const t(*rowB)[e] = (const t(*)[e]) srcRowB; \ - const t(*rowC)[e] = (const t(*)[e]) srcRowC; \ - const t(*rowD)[e] = (const t(*)[e]) srcRowD; \ - t(*dst)[e] = (t(*)[e]) dstRow - -#define DECLARE_ROW_POINTERS0(t) \ - const t *rowA = (const t *) srcRowA; \ - const t *rowB = (const t *) srcRowB; \ - const t *rowC = (const t *) srcRowC; \ - const t *rowD = (const t *) srcRowD; \ - t *dst = (t *) dstRow - -#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ - ((unsigned) Aj + (unsigned) Ak \ - + (unsigned) Bj + (unsigned) Bk \ - + (unsigned) Cj + (unsigned) Ck \ - + (unsigned) Dj + (unsigned) Dk \ - + 4) >> 3 - -#define FILTER_3D(e) \ - do { \ - dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \ - rowB[j][e], rowB[k][e], \ - rowC[j][e], rowC[k][e], \ - rowD[j][e], rowD[k][e]); \ - } while(0) - -#define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ - (Aj + Ak \ - + Bj + Bk \ - + Cj + Ck \ - + Dj + Dk \ - + 4) / 8 - -#define FILTER_3D_SIGNED(e) \ - do { \ - dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \ - rowB[j][e], rowB[k][e], \ - rowC[j][e], rowC[k][e], \ - rowD[j][e], rowD[k][e]); \ - } while(0) - -#define FILTER_F_3D(e) \ - do { \ - dst[i][e] = (rowA[j][e] + rowA[k][e] \ - + rowB[j][e] + rowB[k][e] \ - + rowC[j][e] + rowC[k][e] \ - + rowD[j][e] + rowD[k][e]) * 0.125F; \ - } while(0) - -#define FILTER_HF_3D(e) \ - do { \ - const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \ - const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \ - const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \ - const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \ - const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \ - const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \ - const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \ - const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \ - dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \ - * 0.125F); \ - } while(0) -/*@}*/ - - -/** - * Average together two rows of a source image to produce a single new - * row in the dest image. It's legal for the two source rows to point - * to the same data. The source width must be equal to either the - * dest width or two times the dest width. - * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc. - * \param comps number of components per pixel (1..4) - */ -static void -do_row(GLenum datatype, GLuint comps, GLint srcWidth, - const GLvoid *srcRowA, const GLvoid *srcRowB, - GLint dstWidth, GLvoid *dstRow) -{ - const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; - const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; - - ASSERT(comps >= 1); - ASSERT(comps <= 4); - - /* This assertion is no longer valid with non-power-of-2 textures - assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); - */ - - if (datatype == GL_UNSIGNED_BYTE && comps == 4) { - GLuint i, j, k; - const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA; - const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB; - GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; - } - } - else if (datatype == GL_UNSIGNED_BYTE && comps == 3) { - GLuint i, j, k; - const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA; - const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB; - GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - } - } - else if (datatype == GL_UNSIGNED_BYTE && comps == 2) { - GLuint i, j, k; - const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA; - const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB; - GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2; - } - } - else if (datatype == GL_UNSIGNED_BYTE && comps == 1) { - GLuint i, j, k; - const GLubyte *rowA = (const GLubyte *) srcRowA; - const GLubyte *rowB = (const GLubyte *) srcRowB; - GLubyte *dst = (GLubyte *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; - } - } - - else if (datatype == GL_BYTE && comps == 4) { - GLuint i, j, k; - const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA; - const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB; - GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; - } - } - else if (datatype == GL_BYTE && comps == 3) { - GLuint i, j, k; - const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA; - const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB; - GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - } - } - else if (datatype == GL_BYTE && comps == 2) { - GLuint i, j, k; - const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA; - const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB; - GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - } - } - else if (datatype == GL_BYTE && comps == 1) { - GLuint i, j, k; - const GLbyte *rowA = (const GLbyte *) srcRowA; - const GLbyte *rowB = (const GLbyte *) srcRowB; - GLbyte *dst = (GLbyte *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; - } - } - - else if (datatype == GL_UNSIGNED_SHORT && comps == 4) { - GLuint i, j, k; - const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA; - const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB; - GLushort(*dst)[4] = (GLushort(*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; - } - } - else if (datatype == GL_UNSIGNED_SHORT && comps == 3) { - GLuint i, j, k; - const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA; - const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB; - GLushort(*dst)[3] = (GLushort(*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - } - } - else if (datatype == GL_UNSIGNED_SHORT && comps == 2) { - GLuint i, j, k; - const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA; - const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB; - GLushort(*dst)[2] = (GLushort(*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - } - } - else if (datatype == GL_UNSIGNED_SHORT && comps == 1) { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; - } - } - - else if (datatype == GL_SHORT && comps == 4) { - GLuint i, j, k; - const GLshort(*rowA)[4] = (const GLshort(*)[4]) srcRowA; - const GLshort(*rowB)[4] = (const GLshort(*)[4]) srcRowB; - GLshort(*dst)[4] = (GLshort(*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; - } - } - else if (datatype == GL_SHORT && comps == 3) { - GLuint i, j, k; - const GLshort(*rowA)[3] = (const GLshort(*)[3]) srcRowA; - const GLshort(*rowB)[3] = (const GLshort(*)[3]) srcRowB; - GLshort(*dst)[3] = (GLshort(*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; - } - } - else if (datatype == GL_SHORT && comps == 2) { - GLuint i, j, k; - const GLshort(*rowA)[2] = (const GLshort(*)[2]) srcRowA; - const GLshort(*rowB)[2] = (const GLshort(*)[2]) srcRowB; - GLshort(*dst)[2] = (GLshort(*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; - } - } - else if (datatype == GL_SHORT && comps == 1) { - GLuint i, j, k; - const GLshort *rowA = (const GLshort *) srcRowA; - const GLshort *rowB = (const GLshort *) srcRowB; - GLshort *dst = (GLshort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; - } - } - - else if (datatype == GL_FLOAT && comps == 4) { - GLuint i, j, k; - const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA; - const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB; - GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) * 0.25F; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) * 0.25F; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) * 0.25F; - dst[i][3] = (rowA[j][3] + rowA[k][3] + - rowB[j][3] + rowB[k][3]) * 0.25F; - } - } - else if (datatype == GL_FLOAT && comps == 3) { - GLuint i, j, k; - const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA; - const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB; - GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) * 0.25F; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) * 0.25F; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) * 0.25F; - } - } - else if (datatype == GL_FLOAT && comps == 2) { - GLuint i, j, k; - const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA; - const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB; - GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) * 0.25F; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) * 0.25F; - } - } - else if (datatype == GL_FLOAT && comps == 1) { - GLuint i, j, k; - const GLfloat *rowA = (const GLfloat *) srcRowA; - const GLfloat *rowB = (const GLfloat *) srcRowB; - GLfloat *dst = (GLfloat *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; - } - } - - else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) { - GLuint i, j, k, comp; - const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA; - const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB; - GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - for (comp = 0; comp < 4; comp++) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j][comp]); - ak = _mesa_half_to_float(rowA[k][comp]); - bj = _mesa_half_to_float(rowB[j][comp]); - bk = _mesa_half_to_float(rowB[k][comp]); - dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - } - else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) { - GLuint i, j, k, comp; - const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA; - const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB; - GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - for (comp = 0; comp < 3; comp++) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j][comp]); - ak = _mesa_half_to_float(rowA[k][comp]); - bj = _mesa_half_to_float(rowB[j][comp]); - bk = _mesa_half_to_float(rowB[k][comp]); - dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - } - else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) { - GLuint i, j, k, comp; - const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA; - const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB; - GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - for (comp = 0; comp < 2; comp++) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j][comp]); - ak = _mesa_half_to_float(rowA[k][comp]); - bj = _mesa_half_to_float(rowB[j][comp]); - bk = _mesa_half_to_float(rowB[k][comp]); - dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - } - else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) { - GLuint i, j, k; - const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; - const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; - GLhalfARB *dst = (GLhalfARB *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j]); - ak = _mesa_half_to_float(rowA[k]); - bj = _mesa_half_to_float(rowB[j]); - bk = _mesa_half_to_float(rowB[k]); - dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - - else if (datatype == GL_UNSIGNED_INT && comps == 1) { - GLuint i, j, k; - const GLuint *rowA = (const GLuint *) srcRowA; - const GLuint *rowB = (const GLuint *) srcRowB; - GLuint *dst = (GLuint *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4); - } - } - - else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x1f; - const GLint rowAr1 = rowA[k] & 0x1f; - const GLint rowBr0 = rowB[j] & 0x1f; - const GLint rowBr1 = rowB[k] & 0x1f; - const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; - const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; - const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; - const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; - const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - dst[i] = (blue << 11) | (green << 5) | red; - } - } - else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0xf; - const GLint rowAr1 = rowA[k] & 0xf; - const GLint rowBr0 = rowB[j] & 0xf; - const GLint rowBr1 = rowB[k] & 0xf; - const GLint rowAg0 = (rowA[j] >> 4) & 0xf; - const GLint rowAg1 = (rowA[k] >> 4) & 0xf; - const GLint rowBg0 = (rowB[j] >> 4) & 0xf; - const GLint rowBg1 = (rowB[k] >> 4) & 0xf; - const GLint rowAb0 = (rowA[j] >> 8) & 0xf; - const GLint rowAb1 = (rowA[k] >> 8) & 0xf; - const GLint rowBb0 = (rowB[j] >> 8) & 0xf; - const GLint rowBb1 = (rowB[k] >> 8) & 0xf; - const GLint rowAa0 = (rowA[j] >> 12) & 0xf; - const GLint rowAa1 = (rowA[k] >> 12) & 0xf; - const GLint rowBa0 = (rowB[j] >> 12) & 0xf; - const GLint rowBa1 = (rowB[k] >> 12) & 0xf; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; - dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; - } - } - else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x1f; - const GLint rowAr1 = rowA[k] & 0x1f; - const GLint rowBr0 = rowB[j] & 0x1f; - const GLint rowBr1 = rowB[k] & 0x1f; - const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; - const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; - const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; - const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; - const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; - const GLint rowAa0 = (rowA[j] >> 15) & 0x1; - const GLint rowAa1 = (rowA[k] >> 15) & 0x1; - const GLint rowBa0 = (rowB[j] >> 15) & 0x1; - const GLint rowBa1 = (rowB[k] >> 15) & 0x1; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; - dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; - } - } - else if (datatype == GL_UNSIGNED_SHORT_5_5_5_1 && comps == 4) { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; - const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; - const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; - const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; - const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; - const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; - const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; - const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; - const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; - const GLint rowAa0 = (rowA[j] & 0x1); - const GLint rowAa1 = (rowA[k] & 0x1); - const GLint rowBa0 = (rowB[j] & 0x1); - const GLint rowBa1 = (rowB[k] & 0x1); - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; - dst[i] = (red << 11) | (green << 6) | (blue << 1) | alpha; - } - } - - else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) { - GLuint i, j, k; - const GLubyte *rowA = (const GLubyte *) srcRowA; - const GLubyte *rowB = (const GLubyte *) srcRowB; - GLubyte *dst = (GLubyte *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x3; - const GLint rowAr1 = rowA[k] & 0x3; - const GLint rowBr0 = rowB[j] & 0x3; - const GLint rowBr1 = rowB[k] & 0x3; - const GLint rowAg0 = (rowA[j] >> 2) & 0x7; - const GLint rowAg1 = (rowA[k] >> 2) & 0x7; - const GLint rowBg0 = (rowB[j] >> 2) & 0x7; - const GLint rowBg1 = (rowB[k] >> 2) & 0x7; - const GLint rowAb0 = (rowA[j] >> 5) & 0x7; - const GLint rowAb1 = (rowA[k] >> 5) & 0x7; - const GLint rowBb0 = (rowB[j] >> 5) & 0x7; - const GLint rowBb1 = (rowB[k] >> 5) & 0x7; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - dst[i] = (blue << 5) | (green << 2) | red; - } - } - - else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { - GLuint i, j, k; - const GLubyte *rowA = (const GLubyte *) srcRowA; - const GLubyte *rowB = (const GLubyte *) srcRowB; - GLubyte *dst = (GLubyte *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0xf; - const GLint rowAr1 = rowA[k] & 0xf; - const GLint rowBr0 = rowB[j] & 0xf; - const GLint rowBr1 = rowB[k] & 0xf; - const GLint rowAg0 = (rowA[j] >> 4) & 0xf; - const GLint rowAg1 = (rowA[k] >> 4) & 0xf; - const GLint rowBg0 = (rowB[j] >> 4) & 0xf; - const GLint rowBg1 = (rowB[k] >> 4) & 0xf; - const GLint r = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint g = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - dst[i] = (g << 4) | r; - } - } - - else if (datatype == GL_UNSIGNED_INT_2_10_10_10_REV && comps == 4) { - GLuint i, j, k; - const GLuint *rowA = (const GLuint *) srcRowA; - const GLuint *rowB = (const GLuint *) srcRowB; - GLuint *dst = (GLuint *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x3ff; - const GLint rowAr1 = rowA[k] & 0x3ff; - const GLint rowBr0 = rowB[j] & 0x3ff; - const GLint rowBr1 = rowB[k] & 0x3ff; - const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff; - const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff; - const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff; - const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff; - const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff; - const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff; - const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff; - const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff; - const GLint rowAa0 = (rowA[j] >> 30) & 0x3; - const GLint rowAa1 = (rowA[k] >> 30) & 0x3; - const GLint rowBa0 = (rowB[j] >> 30) & 0x3; - const GLint rowBa1 = (rowB[k] >> 30) & 0x3; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; - dst[i] = (alpha << 30) | (blue << 20) | (green << 10) | red; - } - } - - else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { - GLuint i, j, k; - const GLuint *rowA = (const GLuint*) srcRowA; - const GLuint *rowB = (const GLuint*) srcRowB; - GLuint *dst = (GLuint*)dstRow; - GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3]; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - rgb9e5_to_float3(rowA[j], rowAj); - rgb9e5_to_float3(rowB[j], rowBj); - rgb9e5_to_float3(rowA[k], rowAk); - rgb9e5_to_float3(rowB[k], rowBk); - res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F; - res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F; - res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F; - dst[i] = float3_to_rgb9e5(res); - } - } - - else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) { - GLuint i, j, k; - const GLuint *rowA = (const GLuint*) srcRowA; - const GLuint *rowB = (const GLuint*) srcRowB; - GLuint *dst = (GLuint*)dstRow; - GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3]; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - r11g11b10f_to_float3(rowA[j], rowAj); - r11g11b10f_to_float3(rowB[j], rowBj); - r11g11b10f_to_float3(rowA[k], rowAk); - r11g11b10f_to_float3(rowB[k], rowBk); - res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F; - res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F; - res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F; - dst[i] = float3_to_r11g11b10f(res); - } - } - - else { - _mesa_problem(NULL, "bad format in do_row()"); - } -} - - -/** - * Average together four rows of a source image to produce a single new - * row in the dest image. It's legal for the two source rows to point - * to the same data. The source width must be equal to either the - * dest width or two times the dest width. - * - * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, - * \c GL_FLOAT, etc. - * \param comps number of components per pixel (1..4) - * \param srcWidth Width of a row in the source data - * \param srcRowA Pointer to one of the rows of source data - * \param srcRowB Pointer to one of the rows of source data - * \param srcRowC Pointer to one of the rows of source data - * \param srcRowD Pointer to one of the rows of source data - * \param dstWidth Width of a row in the destination data - * \param srcRowA Pointer to the row of destination data - */ -static void -do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, - const GLvoid *srcRowA, const GLvoid *srcRowB, - const GLvoid *srcRowC, const GLvoid *srcRowD, - GLint dstWidth, GLvoid *dstRow) -{ - const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; - const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; - GLuint i, j, k; - - ASSERT(comps >= 1); - ASSERT(comps <= 4); - - if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) { - DECLARE_ROW_POINTERS(GLubyte, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - FILTER_3D(2); - FILTER_3D(3); - } - } - else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) { - DECLARE_ROW_POINTERS(GLubyte, 3); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - FILTER_3D(2); - } - } - else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) { - DECLARE_ROW_POINTERS(GLubyte, 2); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - } - } - else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) { - DECLARE_ROW_POINTERS(GLubyte, 1); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - } - } - else if ((datatype == GL_BYTE) && (comps == 4)) { - DECLARE_ROW_POINTERS(GLbyte, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D_SIGNED(0); - FILTER_3D_SIGNED(1); - FILTER_3D_SIGNED(2); - FILTER_3D_SIGNED(3); - } - } - else if ((datatype == GL_BYTE) && (comps == 3)) { - DECLARE_ROW_POINTERS(GLbyte, 3); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D_SIGNED(0); - FILTER_3D_SIGNED(1); - FILTER_3D_SIGNED(2); - } - } - else if ((datatype == GL_BYTE) && (comps == 2)) { - DECLARE_ROW_POINTERS(GLbyte, 2); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D_SIGNED(0); - FILTER_3D_SIGNED(1); - } - } - else if ((datatype == GL_BYTE) && (comps == 1)) { - DECLARE_ROW_POINTERS(GLbyte, 1); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D_SIGNED(0); - } - } - else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) { - DECLARE_ROW_POINTERS(GLushort, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - FILTER_3D(2); - FILTER_3D(3); - } - } - else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) { - DECLARE_ROW_POINTERS(GLushort, 3); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - FILTER_3D(2); - } - } - else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) { - DECLARE_ROW_POINTERS(GLushort, 2); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - } - } - else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) { - DECLARE_ROW_POINTERS(GLushort, 1); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - } - } - else if ((datatype == GL_SHORT) && (comps == 4)) { - DECLARE_ROW_POINTERS(GLshort, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - FILTER_3D(2); - FILTER_3D(3); - } - } - else if ((datatype == GL_SHORT) && (comps == 3)) { - DECLARE_ROW_POINTERS(GLshort, 3); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - FILTER_3D(2); - } - } - else if ((datatype == GL_SHORT) && (comps == 2)) { - DECLARE_ROW_POINTERS(GLshort, 2); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - FILTER_3D(1); - } - } - else if ((datatype == GL_SHORT) && (comps == 1)) { - DECLARE_ROW_POINTERS(GLshort, 1); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_3D(0); - } - } - else if ((datatype == GL_FLOAT) && (comps == 4)) { - DECLARE_ROW_POINTERS(GLfloat, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_F_3D(0); - FILTER_F_3D(1); - FILTER_F_3D(2); - FILTER_F_3D(3); - } - } - else if ((datatype == GL_FLOAT) && (comps == 3)) { - DECLARE_ROW_POINTERS(GLfloat, 3); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_F_3D(0); - FILTER_F_3D(1); - FILTER_F_3D(2); - } - } - else if ((datatype == GL_FLOAT) && (comps == 2)) { - DECLARE_ROW_POINTERS(GLfloat, 2); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_F_3D(0); - FILTER_F_3D(1); - } - } - else if ((datatype == GL_FLOAT) && (comps == 1)) { - DECLARE_ROW_POINTERS(GLfloat, 1); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_F_3D(0); - } - } - else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) { - DECLARE_ROW_POINTERS(GLhalfARB, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_HF_3D(0); - FILTER_HF_3D(1); - FILTER_HF_3D(2); - FILTER_HF_3D(3); - } - } - else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) { - DECLARE_ROW_POINTERS(GLhalfARB, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_HF_3D(0); - FILTER_HF_3D(1); - FILTER_HF_3D(2); - } - } - else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) { - DECLARE_ROW_POINTERS(GLhalfARB, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_HF_3D(0); - FILTER_HF_3D(1); - } - } - else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) { - DECLARE_ROW_POINTERS(GLhalfARB, 4); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - FILTER_HF_3D(0); - } - } - else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) { - const GLuint *rowA = (const GLuint *) srcRowA; - const GLuint *rowB = (const GLuint *) srcRowB; - const GLuint *rowC = (const GLuint *) srcRowC; - const GLuint *rowD = (const GLuint *) srcRowD; - GLfloat *dst = (GLfloat *) dstRow; - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k]) - + ((uint64_t) rowB[j] + (uint64_t) rowB[k]) - + ((uint64_t) rowC[j] + (uint64_t) rowC[k]) - + ((uint64_t) rowD[j] + (uint64_t) rowD[k])); - dst[i] = (GLfloat)((double) tmp * 0.125); - } - } - else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) { - DECLARE_ROW_POINTERS0(GLushort); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x1f; - const GLint rowAr1 = rowA[k] & 0x1f; - const GLint rowBr0 = rowB[j] & 0x1f; - const GLint rowBr1 = rowB[k] & 0x1f; - const GLint rowCr0 = rowC[j] & 0x1f; - const GLint rowCr1 = rowC[k] & 0x1f; - const GLint rowDr0 = rowD[j] & 0x1f; - const GLint rowDr1 = rowD[k] & 0x1f; - const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; - const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; - const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; - const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; - const GLint rowCg0 = (rowC[j] >> 5) & 0x3f; - const GLint rowCg1 = (rowC[k] >> 5) & 0x3f; - const GLint rowDg0 = (rowD[j] >> 5) & 0x3f; - const GLint rowDg1 = (rowD[k] >> 5) & 0x3f; - const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; - const GLint rowCb0 = (rowC[j] >> 11) & 0x1f; - const GLint rowCb1 = (rowC[k] >> 11) & 0x1f; - const GLint rowDb0 = (rowD[j] >> 11) & 0x1f; - const GLint rowDb1 = (rowD[k] >> 11) & 0x1f; - const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, - rowCr0, rowCr1, rowDr0, rowDr1); - const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, - rowCg0, rowCg1, rowDg0, rowDg1); - const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, - rowCb0, rowCb1, rowDb0, rowDb1); - dst[i] = (b << 11) | (g << 5) | r; - } - } - else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) { - DECLARE_ROW_POINTERS0(GLushort); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0xf; - const GLint rowAr1 = rowA[k] & 0xf; - const GLint rowBr0 = rowB[j] & 0xf; - const GLint rowBr1 = rowB[k] & 0xf; - const GLint rowCr0 = rowC[j] & 0xf; - const GLint rowCr1 = rowC[k] & 0xf; - const GLint rowDr0 = rowD[j] & 0xf; - const GLint rowDr1 = rowD[k] & 0xf; - const GLint rowAg0 = (rowA[j] >> 4) & 0xf; - const GLint rowAg1 = (rowA[k] >> 4) & 0xf; - const GLint rowBg0 = (rowB[j] >> 4) & 0xf; - const GLint rowBg1 = (rowB[k] >> 4) & 0xf; - const GLint rowCg0 = (rowC[j] >> 4) & 0xf; - const GLint rowCg1 = (rowC[k] >> 4) & 0xf; - const GLint rowDg0 = (rowD[j] >> 4) & 0xf; - const GLint rowDg1 = (rowD[k] >> 4) & 0xf; - const GLint rowAb0 = (rowA[j] >> 8) & 0xf; - const GLint rowAb1 = (rowA[k] >> 8) & 0xf; - const GLint rowBb0 = (rowB[j] >> 8) & 0xf; - const GLint rowBb1 = (rowB[k] >> 8) & 0xf; - const GLint rowCb0 = (rowC[j] >> 8) & 0xf; - const GLint rowCb1 = (rowC[k] >> 8) & 0xf; - const GLint rowDb0 = (rowD[j] >> 8) & 0xf; - const GLint rowDb1 = (rowD[k] >> 8) & 0xf; - const GLint rowAa0 = (rowA[j] >> 12) & 0xf; - const GLint rowAa1 = (rowA[k] >> 12) & 0xf; - const GLint rowBa0 = (rowB[j] >> 12) & 0xf; - const GLint rowBa1 = (rowB[k] >> 12) & 0xf; - const GLint rowCa0 = (rowC[j] >> 12) & 0xf; - const GLint rowCa1 = (rowC[k] >> 12) & 0xf; - const GLint rowDa0 = (rowD[j] >> 12) & 0xf; - const GLint rowDa1 = (rowD[k] >> 12) & 0xf; - const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, - rowCr0, rowCr1, rowDr0, rowDr1); - const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, - rowCg0, rowCg1, rowDg0, rowDg1); - const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, - rowCb0, rowCb1, rowDb0, rowDb1); - const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, - rowCa0, rowCa1, rowDa0, rowDa1); - - dst[i] = (a << 12) | (b << 8) | (g << 4) | r; - } - } - else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) { - DECLARE_ROW_POINTERS0(GLushort); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x1f; - const GLint rowAr1 = rowA[k] & 0x1f; - const GLint rowBr0 = rowB[j] & 0x1f; - const GLint rowBr1 = rowB[k] & 0x1f; - const GLint rowCr0 = rowC[j] & 0x1f; - const GLint rowCr1 = rowC[k] & 0x1f; - const GLint rowDr0 = rowD[j] & 0x1f; - const GLint rowDr1 = rowD[k] & 0x1f; - const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; - const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; - const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; - const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; - const GLint rowCg0 = (rowC[j] >> 5) & 0x1f; - const GLint rowCg1 = (rowC[k] >> 5) & 0x1f; - const GLint rowDg0 = (rowD[j] >> 5) & 0x1f; - const GLint rowDg1 = (rowD[k] >> 5) & 0x1f; - const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; - const GLint rowCb0 = (rowC[j] >> 10) & 0x1f; - const GLint rowCb1 = (rowC[k] >> 10) & 0x1f; - const GLint rowDb0 = (rowD[j] >> 10) & 0x1f; - const GLint rowDb1 = (rowD[k] >> 10) & 0x1f; - const GLint rowAa0 = (rowA[j] >> 15) & 0x1; - const GLint rowAa1 = (rowA[k] >> 15) & 0x1; - const GLint rowBa0 = (rowB[j] >> 15) & 0x1; - const GLint rowBa1 = (rowB[k] >> 15) & 0x1; - const GLint rowCa0 = (rowC[j] >> 15) & 0x1; - const GLint rowCa1 = (rowC[k] >> 15) & 0x1; - const GLint rowDa0 = (rowD[j] >> 15) & 0x1; - const GLint rowDa1 = (rowD[k] >> 15) & 0x1; - const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, - rowCr0, rowCr1, rowDr0, rowDr1); - const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, - rowCg0, rowCg1, rowDg0, rowDg1); - const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, - rowCb0, rowCb1, rowDb0, rowDb1); - const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, - rowCa0, rowCa1, rowDa0, rowDa1); - - dst[i] = (a << 15) | (b << 10) | (g << 5) | r; - } - } - else if ((datatype == GL_UNSIGNED_SHORT_5_5_5_1) && (comps == 4)) { - DECLARE_ROW_POINTERS0(GLushort); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; - const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; - const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; - const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; - const GLint rowCr0 = (rowC[j] >> 11) & 0x1f; - const GLint rowCr1 = (rowC[k] >> 11) & 0x1f; - const GLint rowDr0 = (rowD[j] >> 11) & 0x1f; - const GLint rowDr1 = (rowD[k] >> 11) & 0x1f; - const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; - const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; - const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; - const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; - const GLint rowCg0 = (rowC[j] >> 6) & 0x1f; - const GLint rowCg1 = (rowC[k] >> 6) & 0x1f; - const GLint rowDg0 = (rowD[j] >> 6) & 0x1f; - const GLint rowDg1 = (rowD[k] >> 6) & 0x1f; - const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; - const GLint rowCb0 = (rowC[j] >> 1) & 0x1f; - const GLint rowCb1 = (rowC[k] >> 1) & 0x1f; - const GLint rowDb0 = (rowD[j] >> 1) & 0x1f; - const GLint rowDb1 = (rowD[k] >> 1) & 0x1f; - const GLint rowAa0 = (rowA[j] & 0x1); - const GLint rowAa1 = (rowA[k] & 0x1); - const GLint rowBa0 = (rowB[j] & 0x1); - const GLint rowBa1 = (rowB[k] & 0x1); - const GLint rowCa0 = (rowC[j] & 0x1); - const GLint rowCa1 = (rowC[k] & 0x1); - const GLint rowDa0 = (rowD[j] & 0x1); - const GLint rowDa1 = (rowD[k] & 0x1); - const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, - rowCr0, rowCr1, rowDr0, rowDr1); - const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, - rowCg0, rowCg1, rowDg0, rowDg1); - const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, - rowCb0, rowCb1, rowDb0, rowDb1); - const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, - rowCa0, rowCa1, rowDa0, rowDa1); - - dst[i] = (r << 11) | (g << 6) | (b << 1) | a; - } - } - else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) { - DECLARE_ROW_POINTERS0(GLubyte); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x3; - const GLint rowAr1 = rowA[k] & 0x3; - const GLint rowBr0 = rowB[j] & 0x3; - const GLint rowBr1 = rowB[k] & 0x3; - const GLint rowCr0 = rowC[j] & 0x3; - const GLint rowCr1 = rowC[k] & 0x3; - const GLint rowDr0 = rowD[j] & 0x3; - const GLint rowDr1 = rowD[k] & 0x3; - const GLint rowAg0 = (rowA[j] >> 2) & 0x7; - const GLint rowAg1 = (rowA[k] >> 2) & 0x7; - const GLint rowBg0 = (rowB[j] >> 2) & 0x7; - const GLint rowBg1 = (rowB[k] >> 2) & 0x7; - const GLint rowCg0 = (rowC[j] >> 2) & 0x7; - const GLint rowCg1 = (rowC[k] >> 2) & 0x7; - const GLint rowDg0 = (rowD[j] >> 2) & 0x7; - const GLint rowDg1 = (rowD[k] >> 2) & 0x7; - const GLint rowAb0 = (rowA[j] >> 5) & 0x7; - const GLint rowAb1 = (rowA[k] >> 5) & 0x7; - const GLint rowBb0 = (rowB[j] >> 5) & 0x7; - const GLint rowBb1 = (rowB[k] >> 5) & 0x7; - const GLint rowCb0 = (rowC[j] >> 5) & 0x7; - const GLint rowCb1 = (rowC[k] >> 5) & 0x7; - const GLint rowDb0 = (rowD[j] >> 5) & 0x7; - const GLint rowDb1 = (rowD[k] >> 5) & 0x7; - const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, - rowCr0, rowCr1, rowDr0, rowDr1); - const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, - rowCg0, rowCg1, rowDg0, rowDg1); - const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, - rowCb0, rowCb1, rowDb0, rowDb1); - dst[i] = (b << 5) | (g << 2) | r; - } - } - else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { - DECLARE_ROW_POINTERS0(GLubyte); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0xf; - const GLint rowAr1 = rowA[k] & 0xf; - const GLint rowBr0 = rowB[j] & 0xf; - const GLint rowBr1 = rowB[k] & 0xf; - const GLint rowCr0 = rowC[j] & 0xf; - const GLint rowCr1 = rowC[k] & 0xf; - const GLint rowDr0 = rowD[j] & 0xf; - const GLint rowDr1 = rowD[k] & 0xf; - const GLint rowAg0 = (rowA[j] >> 4) & 0xf; - const GLint rowAg1 = (rowA[k] >> 4) & 0xf; - const GLint rowBg0 = (rowB[j] >> 4) & 0xf; - const GLint rowBg1 = (rowB[k] >> 4) & 0xf; - const GLint rowCg0 = (rowC[j] >> 4) & 0xf; - const GLint rowCg1 = (rowC[k] >> 4) & 0xf; - const GLint rowDg0 = (rowD[j] >> 4) & 0xf; - const GLint rowDg1 = (rowD[k] >> 4) & 0xf; - const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, - rowCr0, rowCr1, rowDr0, rowDr1); - const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, - rowCg0, rowCg1, rowDg0, rowDg1); - dst[i] = (g << 4) | r; - } - } - else if ((datatype == GL_UNSIGNED_INT_2_10_10_10_REV) && (comps == 4)) { - DECLARE_ROW_POINTERS0(GLuint); - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x3ff; - const GLint rowAr1 = rowA[k] & 0x3ff; - const GLint rowBr0 = rowB[j] & 0x3ff; - const GLint rowBr1 = rowB[k] & 0x3ff; - const GLint rowCr0 = rowC[j] & 0x3ff; - const GLint rowCr1 = rowC[k] & 0x3ff; - const GLint rowDr0 = rowD[j] & 0x3ff; - const GLint rowDr1 = rowD[k] & 0x3ff; - const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff; - const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff; - const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff; - const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff; - const GLint rowCg0 = (rowC[j] >> 10) & 0x3ff; - const GLint rowCg1 = (rowC[k] >> 10) & 0x3ff; - const GLint rowDg0 = (rowD[j] >> 10) & 0x3ff; - const GLint rowDg1 = (rowD[k] >> 10) & 0x3ff; - const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff; - const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff; - const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff; - const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff; - const GLint rowCb0 = (rowC[j] >> 20) & 0x3ff; - const GLint rowCb1 = (rowC[k] >> 20) & 0x3ff; - const GLint rowDb0 = (rowD[j] >> 20) & 0x3ff; - const GLint rowDb1 = (rowD[k] >> 20) & 0x3ff; - const GLint rowAa0 = (rowA[j] >> 30) & 0x3; - const GLint rowAa1 = (rowA[k] >> 30) & 0x3; - const GLint rowBa0 = (rowB[j] >> 30) & 0x3; - const GLint rowBa1 = (rowB[k] >> 30) & 0x3; - const GLint rowCa0 = (rowC[j] >> 30) & 0x3; - const GLint rowCa1 = (rowC[k] >> 30) & 0x3; - const GLint rowDa0 = (rowD[j] >> 30) & 0x3; - const GLint rowDa1 = (rowD[k] >> 30) & 0x3; - const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, - rowCr0, rowCr1, rowDr0, rowDr1); - const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, - rowCg0, rowCg1, rowDg0, rowDg1); - const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, - rowCb0, rowCb1, rowDb0, rowDb1); - const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, - rowCa0, rowCa1, rowDa0, rowDa1); - - dst[i] = (a << 30) | (b << 20) | (g << 10) | r; - } - } - - else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { - DECLARE_ROW_POINTERS0(GLuint); - - GLfloat res[3]; - GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3]; - GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3]; - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - rgb9e5_to_float3(rowA[j], rowAj); - rgb9e5_to_float3(rowB[j], rowBj); - rgb9e5_to_float3(rowC[j], rowCj); - rgb9e5_to_float3(rowD[j], rowDj); - rgb9e5_to_float3(rowA[k], rowAk); - rgb9e5_to_float3(rowB[k], rowBk); - rgb9e5_to_float3(rowC[k], rowCk); - rgb9e5_to_float3(rowD[k], rowDk); - res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] + - rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F; - res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] + - rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F; - res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] + - rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F; - dst[i] = float3_to_rgb9e5(res); - } - } - - else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) { - DECLARE_ROW_POINTERS0(GLuint); - - GLfloat res[3]; - GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3]; - GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3]; - - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - r11g11b10f_to_float3(rowA[j], rowAj); - r11g11b10f_to_float3(rowB[j], rowBj); - r11g11b10f_to_float3(rowC[j], rowCj); - r11g11b10f_to_float3(rowD[j], rowDj); - r11g11b10f_to_float3(rowA[k], rowAk); - r11g11b10f_to_float3(rowB[k], rowBk); - r11g11b10f_to_float3(rowC[k], rowCk); - r11g11b10f_to_float3(rowD[k], rowDk); - res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] + - rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F; - res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] + - rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F; - res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] + - rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F; - dst[i] = float3_to_r11g11b10f(res); - } - } - - else { - _mesa_problem(NULL, "bad format in do_row()"); - } -} - - -/* - * These functions generate a 1/2-size mipmap image from a source image. - * Texture borders are handled by copying or averaging the source image's - * border texels, depending on the scale-down factor. - */ - -static void -make_1d_mipmap(GLenum datatype, GLuint comps, GLint border, - GLint srcWidth, const GLubyte *srcPtr, - GLint dstWidth, GLubyte *dstPtr) -{ - const GLint bpt = bytes_per_pixel(datatype, comps); - const GLubyte *src; - GLubyte *dst; - - /* skip the border pixel, if any */ - src = srcPtr + border * bpt; - dst = dstPtr + border * bpt; - - /* we just duplicate the input row, kind of hack, saves code */ - do_row(datatype, comps, srcWidth - 2 * border, src, src, - dstWidth - 2 * border, dst); - - if (border) { - /* copy left-most pixel from source */ - assert(dstPtr); - assert(srcPtr); - memcpy(dstPtr, srcPtr, bpt); - /* copy right-most pixel from source */ - memcpy(dstPtr + (dstWidth - 1) * bpt, - srcPtr + (srcWidth - 1) * bpt, - bpt); - } -} - - -static void -make_2d_mipmap(GLenum datatype, GLuint comps, GLint border, - GLint srcWidth, GLint srcHeight, - const GLubyte *srcPtr, GLint srcRowStride, - GLint dstWidth, GLint dstHeight, - GLubyte *dstPtr, GLint dstRowStride) -{ - const GLint bpt = bytes_per_pixel(datatype, comps); - const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ - const GLint dstWidthNB = dstWidth - 2 * border; - const GLint dstHeightNB = dstHeight - 2 * border; - const GLint srcRowBytes = bpt * srcRowStride; - const GLint dstRowBytes = bpt * dstRowStride; - const GLubyte *srcA, *srcB; - GLubyte *dst; - GLint row, srcRowStep; - - /* Compute src and dst pointers, skipping any border */ - srcA = srcPtr + border * ((srcWidth + 1) * bpt); - if (srcHeight > 1 && srcHeight > dstHeight) { - /* sample from two source rows */ - srcB = srcA + srcRowBytes; - srcRowStep = 2; - } - else { - /* sample from one source row */ - srcB = srcA; - srcRowStep = 1; - } - - dst = dstPtr + border * ((dstWidth + 1) * bpt); - - for (row = 0; row < dstHeightNB; row++) { - do_row(datatype, comps, srcWidthNB, srcA, srcB, - dstWidthNB, dst); - srcA += srcRowStep * srcRowBytes; - srcB += srcRowStep * srcRowBytes; - dst += dstRowBytes; - } - - /* This is ugly but probably won't be used much */ - if (border > 0) { - /* fill in dest border */ - /* lower-left border pixel */ - assert(dstPtr); - assert(srcPtr); - memcpy(dstPtr, srcPtr, bpt); - /* lower-right border pixel */ - memcpy(dstPtr + (dstWidth - 1) * bpt, - srcPtr + (srcWidth - 1) * bpt, bpt); - /* upper-left border pixel */ - memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt, - srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); - /* upper-right border pixel */ - memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt, - srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); - /* lower border */ - do_row(datatype, comps, srcWidthNB, - srcPtr + bpt, - srcPtr + bpt, - dstWidthNB, dstPtr + bpt); - /* upper border */ - do_row(datatype, comps, srcWidthNB, - srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, - srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, - dstWidthNB, - dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); - /* left and right borders */ - if (srcHeight == dstHeight) { - /* copy border pixel from src to dst */ - for (row = 1; row < srcHeight; row++) { - memcpy(dstPtr + dstWidth * row * bpt, - srcPtr + srcWidth * row * bpt, bpt); - memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, - srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); - } - } - else { - /* average two src pixels each dest pixel */ - for (row = 0; row < dstHeightNB; row += 2) { - do_row(datatype, comps, 1, - srcPtr + (srcWidth * (row * 2 + 1)) * bpt, - srcPtr + (srcWidth * (row * 2 + 2)) * bpt, - 1, dstPtr + (dstWidth * row + 1) * bpt); - do_row(datatype, comps, 1, - srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, - srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, - 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); - } - } - } -} - - -static void -make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - const GLubyte *srcPtr, GLint srcRowStride, - GLint dstWidth, GLint dstHeight, GLint dstDepth, - GLubyte *dstPtr, GLint dstRowStride) -{ - const GLint bpt = bytes_per_pixel(datatype, comps); - const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ - const GLint srcDepthNB = srcDepth - 2 * border; - const GLint dstWidthNB = dstWidth - 2 * border; - const GLint dstHeightNB = dstHeight - 2 * border; - const GLint dstDepthNB = dstDepth - 2 * border; - GLint img, row; - GLint bytesPerSrcImage, bytesPerDstImage; - GLint bytesPerSrcRow, bytesPerDstRow; - GLint srcImageOffset, srcRowOffset; - - (void) srcDepthNB; /* silence warnings */ - - - bytesPerSrcImage = srcWidth * srcHeight * bpt; - bytesPerDstImage = dstWidth * dstHeight * bpt; - - bytesPerSrcRow = srcWidth * bpt; - bytesPerDstRow = dstWidth * bpt; - - /* Offset between adjacent src images to be averaged together */ - srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage; - - /* Offset between adjacent src rows to be averaged together */ - srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; - - /* - * Need to average together up to 8 src pixels for each dest pixel. - * Break that down into 3 operations: - * 1. take two rows from source image and average them together. - * 2. take two rows from next source image and average them together. - * 3. take the two averaged rows and average them for the final dst row. - */ - - /* - printf("mip3d %d x %d x %d -> %d x %d x %d\n", - srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); - */ - - for (img = 0; img < dstDepthNB; img++) { - /* first source image pointer, skipping border */ - const GLubyte *imgSrcA = srcPtr - + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border - + img * (bytesPerSrcImage + srcImageOffset); - /* second source image pointer, skipping border */ - const GLubyte *imgSrcB = imgSrcA + srcImageOffset; - /* address of the dest image, skipping border */ - GLubyte *imgDst = dstPtr - + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border - + img * bytesPerDstImage; - - /* setup the four source row pointers and the dest row pointer */ - const GLubyte *srcImgARowA = imgSrcA; - const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; - const GLubyte *srcImgBRowA = imgSrcB; - const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; - GLubyte *dstImgRow = imgDst; - - for (row = 0; row < dstHeightNB; row++) { - do_row_3D(datatype, comps, srcWidthNB, - srcImgARowA, srcImgARowB, - srcImgBRowA, srcImgBRowB, - dstWidthNB, dstImgRow); - - /* advance to next rows */ - srcImgARowA += bytesPerSrcRow + srcRowOffset; - srcImgARowB += bytesPerSrcRow + srcRowOffset; - srcImgBRowA += bytesPerSrcRow + srcRowOffset; - srcImgBRowB += bytesPerSrcRow + srcRowOffset; - dstImgRow += bytesPerDstRow; - } - } - - - /* Luckily we can leverage the make_2d_mipmap() function here! */ - if (border > 0) { - /* do front border image */ - make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride, - dstWidth, dstHeight, dstPtr, dstRowStride); - /* do back border image */ - make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, - srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride, - dstWidth, dstHeight, - dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride); - /* do four remaining border edges that span the image slices */ - if (srcDepth == dstDepth) { - /* just copy border pixels from src to dst */ - for (img = 0; img < dstDepthNB; img++) { - const GLubyte *src; - GLubyte *dst; - - /* do border along [img][row=0][col=0] */ - src = srcPtr + (img + 1) * bytesPerSrcImage; - dst = dstPtr + (img + 1) * bytesPerDstImage; - memcpy(dst, src, bpt); - - /* do border along [img][row=dstHeight-1][col=0] */ - src = srcPtr + (img * 2 + 1) * bytesPerSrcImage - + (srcHeight - 1) * bytesPerSrcRow; - dst = dstPtr + (img + 1) * bytesPerDstImage - + (dstHeight - 1) * bytesPerDstRow; - memcpy(dst, src, bpt); - - /* do border along [img][row=0][col=dstWidth-1] */ - src = srcPtr + (img * 2 + 1) * bytesPerSrcImage - + (srcWidth - 1) * bpt; - dst = dstPtr + (img + 1) * bytesPerDstImage - + (dstWidth - 1) * bpt; - memcpy(dst, src, bpt); - - /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ - src = srcPtr + (img * 2 + 1) * bytesPerSrcImage - + (bytesPerSrcImage - bpt); - dst = dstPtr + (img + 1) * bytesPerDstImage - + (bytesPerDstImage - bpt); - memcpy(dst, src, bpt); - } - } - else { - /* average border pixels from adjacent src image pairs */ - ASSERT(srcDepthNB == 2 * dstDepthNB); - for (img = 0; img < dstDepthNB; img++) { - const GLubyte *src; - GLubyte *dst; - - /* do border along [img][row=0][col=0] */ - src = srcPtr + (img * 2 + 1) * bytesPerSrcImage; - dst = dstPtr + (img + 1) * bytesPerDstImage; - do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); - - /* do border along [img][row=dstHeight-1][col=0] */ - src = srcPtr + (img * 2 + 1) * bytesPerSrcImage - + (srcHeight - 1) * bytesPerSrcRow; - dst = dstPtr + (img + 1) * bytesPerDstImage - + (dstHeight - 1) * bytesPerDstRow; - do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); - - /* do border along [img][row=0][col=dstWidth-1] */ - src = srcPtr + (img * 2 + 1) * bytesPerSrcImage - + (srcWidth - 1) * bpt; - dst = dstPtr + (img + 1) * bytesPerDstImage - + (dstWidth - 1) * bpt; - do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); - - /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ - src = srcPtr + (img * 2 + 1) * bytesPerSrcImage - + (bytesPerSrcImage - bpt); - dst = dstPtr + (img + 1) * bytesPerDstImage - + (bytesPerDstImage - bpt); - do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); - } - } - } -} - - -static void -make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, - GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride, - GLint dstWidth, GLint dstHeight, - GLubyte *dstPtr, GLuint dstRowStride ) -{ - const GLint bpt = bytes_per_pixel(datatype, comps); - const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ - const GLint dstWidthNB = dstWidth - 2 * border; - const GLint dstHeightNB = dstHeight - 2 * border; - const GLint srcRowBytes = bpt * srcRowStride; - const GLint dstRowBytes = bpt * dstRowStride; - const GLubyte *src; - GLubyte *dst; - GLint row; - - /* Compute src and dst pointers, skipping any border */ - src = srcPtr + border * ((srcWidth + 1) * bpt); - dst = dstPtr + border * ((dstWidth + 1) * bpt); - - for (row = 0; row < dstHeightNB; row++) { - do_row(datatype, comps, srcWidthNB, src, src, - dstWidthNB, dst); - src += srcRowBytes; - dst += dstRowBytes; - } - - if (border) { - /* copy left-most pixel from source */ - assert(dstPtr); - assert(srcPtr); - memcpy(dstPtr, srcPtr, bpt); - /* copy right-most pixel from source */ - memcpy(dstPtr + (dstWidth - 1) * bpt, - srcPtr + (srcWidth - 1) * bpt, - bpt); - } -} - - -/** - * \bug - * There is quite a bit of refactoring that could be done with this function - * and \c make_2d_mipmap. - */ -static void -make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, - GLint srcWidth, GLint srcHeight, - const GLubyte *srcPtr, GLint srcRowStride, - GLint dstWidth, GLint dstHeight, GLint dstDepth, - GLubyte *dstPtr, GLint dstRowStride) -{ - const GLint bpt = bytes_per_pixel(datatype, comps); - const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ - const GLint dstWidthNB = dstWidth - 2 * border; - const GLint dstHeightNB = dstHeight - 2 * border; - const GLint dstDepthNB = dstDepth - 2 * border; - const GLint srcRowBytes = bpt * srcRowStride; - const GLint dstRowBytes = bpt * dstRowStride; - const GLubyte *srcA, *srcB; - GLubyte *dst; - GLint layer; - GLint row; - - /* Compute src and dst pointers, skipping any border */ - srcA = srcPtr + border * ((srcWidth + 1) * bpt); - if (srcHeight > 1) - srcB = srcA + srcRowBytes; - else - srcB = srcA; - dst = dstPtr + border * ((dstWidth + 1) * bpt); - - for (layer = 0; layer < dstDepthNB; layer++) { - for (row = 0; row < dstHeightNB; row++) { - do_row(datatype, comps, srcWidthNB, srcA, srcB, - dstWidthNB, dst); - srcA += 2 * srcRowBytes; - srcB += 2 * srcRowBytes; - dst += dstRowBytes; - } - - /* This is ugly but probably won't be used much */ - if (border > 0) { - /* fill in dest border */ - /* lower-left border pixel */ - assert(dstPtr); - assert(srcPtr); - memcpy(dstPtr, srcPtr, bpt); - /* lower-right border pixel */ - memcpy(dstPtr + (dstWidth - 1) * bpt, - srcPtr + (srcWidth - 1) * bpt, bpt); - /* upper-left border pixel */ - memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt, - srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); - /* upper-right border pixel */ - memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt, - srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); - /* lower border */ - do_row(datatype, comps, srcWidthNB, - srcPtr + bpt, - srcPtr + bpt, - dstWidthNB, dstPtr + bpt); - /* upper border */ - do_row(datatype, comps, srcWidthNB, - srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, - srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, - dstWidthNB, - dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); - /* left and right borders */ - if (srcHeight == dstHeight) { - /* copy border pixel from src to dst */ - for (row = 1; row < srcHeight; row++) { - memcpy(dstPtr + dstWidth * row * bpt, - srcPtr + srcWidth * row * bpt, bpt); - memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, - srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); - } - } - else { - /* average two src pixels each dest pixel */ - for (row = 0; row < dstHeightNB; row += 2) { - do_row(datatype, comps, 1, - srcPtr + (srcWidth * (row * 2 + 1)) * bpt, - srcPtr + (srcWidth * (row * 2 + 2)) * bpt, - 1, dstPtr + (dstWidth * row + 1) * bpt); - do_row(datatype, comps, 1, - srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, - srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, - 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); - } - } - } - } -} - - -/** - * Down-sample a texture image to produce the next lower mipmap level. - * \param comps components per texel (1, 2, 3 or 4) - * \param srcRowStride stride between source rows, in texels - * \param dstRowStride stride between destination rows, in texels - */ -void -_mesa_generate_mipmap_level(GLenum target, - GLenum datatype, GLuint comps, - GLint border, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - const GLubyte *srcData, - GLint srcRowStride, - GLint dstWidth, GLint dstHeight, GLint dstDepth, - GLubyte *dstData, - GLint dstRowStride) -{ - /* - * We use simple 2x2 averaging to compute the next mipmap level. - */ - switch (target) { - case GL_TEXTURE_1D: - make_1d_mipmap(datatype, comps, border, - srcWidth, srcData, - dstWidth, dstData); - break; - case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - make_2d_mipmap(datatype, comps, border, - srcWidth, srcHeight, srcData, srcRowStride, - dstWidth, dstHeight, dstData, dstRowStride); - break; - case GL_TEXTURE_3D: - make_3d_mipmap(datatype, comps, border, - srcWidth, srcHeight, srcDepth, - srcData, srcRowStride, - dstWidth, dstHeight, dstDepth, - dstData, dstRowStride); - break; - case GL_TEXTURE_1D_ARRAY_EXT: - make_1d_stack_mipmap(datatype, comps, border, - srcWidth, srcData, srcRowStride, - dstWidth, dstHeight, - dstData, dstRowStride); - break; - case GL_TEXTURE_2D_ARRAY_EXT: - make_2d_stack_mipmap(datatype, comps, border, - srcWidth, srcHeight, - srcData, srcRowStride, - dstWidth, dstHeight, - dstDepth, dstData, dstRowStride); - break; - case GL_TEXTURE_RECTANGLE_NV: - /* no mipmaps, do nothing */ - break; - default: - _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps"); - return; - } -} - - -/** - * compute next (level+1) image size - * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size) - */ -static GLboolean -next_mipmap_level_size(GLenum target, GLint border, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLint *dstWidth, GLint *dstHeight, GLint *dstDepth) -{ - if (srcWidth - 2 * border > 1) { - *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; - } - else { - *dstWidth = srcWidth; /* can't go smaller */ - } - - if ((srcHeight - 2 * border > 1) && - (target != GL_TEXTURE_1D_ARRAY_EXT)) { - *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; - } - else { - *dstHeight = srcHeight; /* can't go smaller */ - } - - if ((srcDepth - 2 * border > 1) && - (target != GL_TEXTURE_2D_ARRAY_EXT)) { - *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; - } - else { - *dstDepth = srcDepth; /* can't go smaller */ - } - - if (*dstWidth == srcWidth && - *dstHeight == srcHeight && - *dstDepth == srcDepth) { - return GL_FALSE; - } - else { - return GL_TRUE; - } -} - - - - -/** - * Automatic mipmap generation. - * This is the fallback/default function for ctx->Driver.GenerateMipmap(). - * Generate a complete set of mipmaps from texObj's BaseLevel image. - * Stop at texObj's MaxLevel or when we get to the 1x1 texture. - * For cube maps, target will be one of - * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP. - */ -void -_mesa_generate_mipmap(struct gl_context *ctx, GLenum target, - struct gl_texture_object *texObj) -{ - const struct gl_texture_image *srcImage; - gl_format convertFormat; - const GLubyte *srcData = NULL; - GLubyte *dstData = NULL; - GLint level, maxLevels; - GLenum datatype; - GLuint comps; - - ASSERT(texObj); - srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); - ASSERT(srcImage); - - maxLevels = _mesa_max_texture_levels(ctx, texObj->Target); - ASSERT(maxLevels > 0); /* bad target */ - - /* Find convertFormat - the format that do_row() will process */ - - if (_mesa_is_format_compressed(srcImage->TexFormat)) { - /* setup for compressed textures - need to allocate temporary - * image buffers to hold uncompressed images. - */ - GLuint row; - GLint components, size; - GLchan *dst; - - assert(texObj->Target == GL_TEXTURE_2D || - texObj->Target == GL_TEXTURE_CUBE_MAP_ARB); - - if (srcImage->_BaseFormat == GL_RGB) { - convertFormat = MESA_FORMAT_RGB888; - components = 3; - } else if (srcImage->_BaseFormat == GL_RED) { - convertFormat = MESA_FORMAT_R8; - components = 1; - } else if (srcImage->_BaseFormat == GL_RG) { - convertFormat = MESA_FORMAT_RG88; - components = 2; - } else if (srcImage->_BaseFormat == GL_RGBA) { - convertFormat = MESA_FORMAT_RGBA8888; - components = 4; - } else if (srcImage->_BaseFormat == GL_LUMINANCE) { - convertFormat = MESA_FORMAT_L8; - components = 1; - } else if (srcImage->_BaseFormat == GL_LUMINANCE_ALPHA) { - convertFormat = MESA_FORMAT_AL88; - components = 2; - } else { - _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps"); - return; - } - - /* allocate storage for uncompressed GL_RGB or GL_RGBA images */ - size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE) - * srcImage->Width * srcImage->Height * srcImage->Depth + 20; - /* 20 extra bytes, just be safe when calling last FetchTexel */ - srcData = (GLubyte *) malloc(size); - if (!srcData) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); - return; - } - dstData = (GLubyte *) malloc(size / 2); /* 1/4 would probably be OK */ - if (!dstData) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); - free((void *) srcData); - return; - } - - /* decompress base image here */ - dst = (GLchan *) srcData; - for (row = 0; row < srcImage->Height; row++) { - GLuint col; - for (col = 0; col < srcImage->Width; col++) { - srcImage->FetchTexelc(srcImage, col, row, 0, dst); - dst += components; - } - } - } - else { - /* uncompressed */ - convertFormat = srcImage->TexFormat; - } - - _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps); - - for (level = texObj->BaseLevel; level < texObj->MaxLevel - && level < maxLevels - 1; level++) { - /* generate image[level+1] from image[level] */ - const struct gl_texture_image *srcImage; - struct gl_texture_image *dstImage; - GLint srcWidth, srcHeight, srcDepth; - GLint dstWidth, dstHeight, dstDepth; - GLint border; - GLboolean nextLevel; - - /* get src image parameters */ - srcImage = _mesa_select_tex_image(ctx, texObj, target, level); - ASSERT(srcImage); - srcWidth = srcImage->Width; - srcHeight = srcImage->Height; - srcDepth = srcImage->Depth; - border = srcImage->Border; - - nextLevel = next_mipmap_level_size(target, border, - srcWidth, srcHeight, srcDepth, - &dstWidth, &dstHeight, &dstDepth); - if (!nextLevel) { - /* all done */ - if (_mesa_is_format_compressed(srcImage->TexFormat)) { - free((void *) srcData); - free(dstData); - } - return; - } - - /* get dest gl_texture_image */ - dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); - if (!dstImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; - } - - /* Free old image data */ - if (dstImage->Data) - ctx->Driver.FreeTexImageData(ctx, dstImage); - - /* initialize new image */ - _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->InternalFormat, - srcImage->TexFormat); - dstImage->DriverData = NULL; - dstImage->FetchTexelc = srcImage->FetchTexelc; - dstImage->FetchTexelf = srcImage->FetchTexelf; - - /* Alloc new teximage data buffer */ - { - GLuint size = _mesa_format_image_size(dstImage->TexFormat, - dstWidth, dstHeight, dstDepth); - dstImage->Data = _mesa_alloc_texmemory(size); - if (!dstImage->Data) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; - } - } - - /* Setup src and dest data pointers */ - if (_mesa_is_format_compressed(dstImage->TexFormat)) { - /* srcData and dstData are already set */ - ASSERT(srcData); - ASSERT(dstData); - } - else { - srcData = (const GLubyte *) srcImage->Data; - dstData = (GLubyte *) dstImage->Data; - } - - ASSERT(dstImage->TexFormat); - ASSERT(dstImage->FetchTexelc); - ASSERT(dstImage->FetchTexelf); - - _mesa_generate_mipmap_level(target, datatype, comps, border, - srcWidth, srcHeight, srcDepth, - srcData, srcImage->RowStride, - dstWidth, dstHeight, dstDepth, - dstData, dstImage->RowStride); - - - if (_mesa_is_format_compressed(dstImage->TexFormat)) { - GLubyte *temp; - /* compress image from dstData into dstImage->Data */ - const GLenum srcFormat = _mesa_get_format_base_format(convertFormat); - GLint dstRowStride - = _mesa_format_row_stride(dstImage->TexFormat, dstWidth); - - _mesa_texstore(ctx, 2, dstImage->_BaseFormat, - dstImage->TexFormat, - dstImage->Data, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, 0, /* strides */ - dstWidth, dstHeight, 1, /* size */ - srcFormat, CHAN_TYPE, - dstData, /* src data, actually */ - &ctx->DefaultPacking); - - /* swap src and dest pointers */ - temp = (GLubyte *) srcData; - srcData = dstData; - dstData = temp; - } - - } /* loop over mipmap levels */ -} - - -/** - * Helper function for drivers which need to rescale texture images to - * certain aspect ratios. - * Nearest filtering only (for broken hardware that can't support - * all aspect ratios). This can be made a lot faster, but I don't - * really care enough... - */ -void -_mesa_rescale_teximage2d(GLuint bytesPerPixel, - GLuint srcStrideInPixels, - GLuint dstRowStride, - GLint srcWidth, GLint srcHeight, - GLint dstWidth, GLint dstHeight, - const GLvoid *srcImage, GLvoid *dstImage) -{ - GLint row, col; - -#define INNER_LOOP( TYPE, HOP, WOP ) \ - for ( row = 0 ; row < dstHeight ; row++ ) { \ - GLint srcRow = row HOP hScale; \ - for ( col = 0 ; col < dstWidth ; col++ ) { \ - GLint srcCol = col WOP wScale; \ - dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ - } \ - dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ - } \ - -#define RESCALE_IMAGE( TYPE ) \ -do { \ - const TYPE *src = (const TYPE *)srcImage; \ - TYPE *dst = (TYPE *)dstImage; \ - \ - if ( srcHeight < dstHeight ) { \ - const GLint hScale = dstHeight / srcHeight; \ - if ( srcWidth < dstWidth ) { \ - const GLint wScale = dstWidth / srcWidth; \ - INNER_LOOP( TYPE, /, / ); \ - } \ - else { \ - const GLint wScale = srcWidth / dstWidth; \ - INNER_LOOP( TYPE, /, * ); \ - } \ - } \ - else { \ - const GLint hScale = srcHeight / dstHeight; \ - if ( srcWidth < dstWidth ) { \ - const GLint wScale = dstWidth / srcWidth; \ - INNER_LOOP( TYPE, *, / ); \ - } \ - else { \ - const GLint wScale = srcWidth / dstWidth; \ - INNER_LOOP( TYPE, *, * ); \ - } \ - } \ -} while (0) - - switch ( bytesPerPixel ) { - case 4: - RESCALE_IMAGE( GLuint ); - break; - - case 2: - RESCALE_IMAGE( GLushort ); - break; - - case 1: - RESCALE_IMAGE( GLubyte ); - break; - default: - _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d"); - } -} - - -/** - * Upscale an image by replication, not (typical) stretching. - * We use this when the image width or height is less than a - * certain size (4, 8) and we need to upscale an image. - */ -void -_mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight, - GLsizei outWidth, GLsizei outHeight, - GLint comps, const GLchan *src, GLint srcRowStride, - GLchan *dest ) -{ - GLint i, j, k; - - ASSERT(outWidth >= inWidth); - ASSERT(outHeight >= inHeight); -#if 0 - ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); - ASSERT((outWidth & 3) == 0); - ASSERT((outHeight & 3) == 0); -#endif - - for (i = 0; i < outHeight; i++) { - const GLint ii = i % inHeight; - for (j = 0; j < outWidth; j++) { - const GLint jj = j % inWidth; - for (k = 0; k < comps; k++) { - dest[(i * outWidth + j) * comps + k] - = src[ii * srcRowStride + jj * comps + k]; - } - } - } -} - +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file mipmap.c mipmap generation and teximage resizing functions. + */ + +#include "imports.h" +#include "formats.h" +#include "mipmap.h" +#include "mtypes.h" +#include "teximage.h" +#include "texstore.h" +#include "image.h" +#include "macros.h" +#include "../../gallium/auxiliary/util/u_format_rgb9e5.h" +#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" + + + +static GLint +bytes_per_pixel(GLenum datatype, GLuint comps) +{ + GLint b = _mesa_sizeof_packed_type(datatype); + assert(b >= 0); + + if (_mesa_type_is_packed(datatype)) + return b; + else + return b * comps; +} + + +/** + * \name Support macros for do_row and do_row_3d + * + * The macro madness is here for two reasons. First, it compacts the code + * slightly. Second, it makes it much easier to adjust the specifics of the + * filter to tune the rounding characteristics. + */ +/*@{*/ +#define DECLARE_ROW_POINTERS(t, e) \ + const t(*rowA)[e] = (const t(*)[e]) srcRowA; \ + const t(*rowB)[e] = (const t(*)[e]) srcRowB; \ + const t(*rowC)[e] = (const t(*)[e]) srcRowC; \ + const t(*rowD)[e] = (const t(*)[e]) srcRowD; \ + t(*dst)[e] = (t(*)[e]) dstRow + +#define DECLARE_ROW_POINTERS0(t) \ + const t *rowA = (const t *) srcRowA; \ + const t *rowB = (const t *) srcRowB; \ + const t *rowC = (const t *) srcRowC; \ + const t *rowD = (const t *) srcRowD; \ + t *dst = (t *) dstRow + +#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ + ((unsigned) Aj + (unsigned) Ak \ + + (unsigned) Bj + (unsigned) Bk \ + + (unsigned) Cj + (unsigned) Ck \ + + (unsigned) Dj + (unsigned) Dk \ + + 4) >> 3 + +#define FILTER_3D(e) \ + do { \ + dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \ + rowB[j][e], rowB[k][e], \ + rowC[j][e], rowC[k][e], \ + rowD[j][e], rowD[k][e]); \ + } while(0) + +#define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ + (Aj + Ak \ + + Bj + Bk \ + + Cj + Ck \ + + Dj + Dk \ + + 4) / 8 + +#define FILTER_3D_SIGNED(e) \ + do { \ + dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \ + rowB[j][e], rowB[k][e], \ + rowC[j][e], rowC[k][e], \ + rowD[j][e], rowD[k][e]); \ + } while(0) + +#define FILTER_F_3D(e) \ + do { \ + dst[i][e] = (rowA[j][e] + rowA[k][e] \ + + rowB[j][e] + rowB[k][e] \ + + rowC[j][e] + rowC[k][e] \ + + rowD[j][e] + rowD[k][e]) * 0.125F; \ + } while(0) + +#define FILTER_HF_3D(e) \ + do { \ + const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \ + const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \ + const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \ + const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \ + const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \ + const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \ + const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \ + const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \ + dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \ + * 0.125F); \ + } while(0) +/*@}*/ + + +/** + * Average together two rows of a source image to produce a single new + * row in the dest image. It's legal for the two source rows to point + * to the same data. The source width must be equal to either the + * dest width or two times the dest width. + * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc. + * \param comps number of components per pixel (1..4) + */ +static void +do_row(GLenum datatype, GLuint comps, GLint srcWidth, + const GLvoid *srcRowA, const GLvoid *srcRowB, + GLint dstWidth, GLvoid *dstRow) +{ + const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; + const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; + + ASSERT(comps >= 1); + ASSERT(comps <= 4); + + /* This assertion is no longer valid with non-power-of-2 textures + assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); + */ + + if (datatype == GL_UNSIGNED_BYTE && comps == 4) { + GLuint i, j, k; + const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA; + const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB; + GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; + } + } + else if (datatype == GL_UNSIGNED_BYTE && comps == 3) { + GLuint i, j, k; + const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA; + const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB; + GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + } + } + else if (datatype == GL_UNSIGNED_BYTE && comps == 2) { + GLuint i, j, k; + const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA; + const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB; + GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2; + } + } + else if (datatype == GL_UNSIGNED_BYTE && comps == 1) { + GLuint i, j, k; + const GLubyte *rowA = (const GLubyte *) srcRowA; + const GLubyte *rowB = (const GLubyte *) srcRowB; + GLubyte *dst = (GLubyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; + } + } + + else if (datatype == GL_BYTE && comps == 4) { + GLuint i, j, k; + const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA; + const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB; + GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; + } + } + else if (datatype == GL_BYTE && comps == 3) { + GLuint i, j, k; + const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA; + const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB; + GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + } + } + else if (datatype == GL_BYTE && comps == 2) { + GLuint i, j, k; + const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA; + const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB; + GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + } + } + else if (datatype == GL_BYTE && comps == 1) { + GLuint i, j, k; + const GLbyte *rowA = (const GLbyte *) srcRowA; + const GLbyte *rowB = (const GLbyte *) srcRowB; + GLbyte *dst = (GLbyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; + } + } + + else if (datatype == GL_UNSIGNED_SHORT && comps == 4) { + GLuint i, j, k; + const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA; + const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB; + GLushort(*dst)[4] = (GLushort(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; + } + } + else if (datatype == GL_UNSIGNED_SHORT && comps == 3) { + GLuint i, j, k; + const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA; + const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB; + GLushort(*dst)[3] = (GLushort(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + } + } + else if (datatype == GL_UNSIGNED_SHORT && comps == 2) { + GLuint i, j, k; + const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA; + const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB; + GLushort(*dst)[2] = (GLushort(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + } + } + else if (datatype == GL_UNSIGNED_SHORT && comps == 1) { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; + } + } + + else if (datatype == GL_SHORT && comps == 4) { + GLuint i, j, k; + const GLshort(*rowA)[4] = (const GLshort(*)[4]) srcRowA; + const GLshort(*rowB)[4] = (const GLshort(*)[4]) srcRowB; + GLshort(*dst)[4] = (GLshort(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; + } + } + else if (datatype == GL_SHORT && comps == 3) { + GLuint i, j, k; + const GLshort(*rowA)[3] = (const GLshort(*)[3]) srcRowA; + const GLshort(*rowB)[3] = (const GLshort(*)[3]) srcRowB; + GLshort(*dst)[3] = (GLshort(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + } + } + else if (datatype == GL_SHORT && comps == 2) { + GLuint i, j, k; + const GLshort(*rowA)[2] = (const GLshort(*)[2]) srcRowA; + const GLshort(*rowB)[2] = (const GLshort(*)[2]) srcRowB; + GLshort(*dst)[2] = (GLshort(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + } + } + else if (datatype == GL_SHORT && comps == 1) { + GLuint i, j, k; + const GLshort *rowA = (const GLshort *) srcRowA; + const GLshort *rowB = (const GLshort *) srcRowB; + GLshort *dst = (GLshort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; + } + } + + else if (datatype == GL_FLOAT && comps == 4) { + GLuint i, j, k; + const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA; + const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB; + GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + dst[i][3] = (rowA[j][3] + rowA[k][3] + + rowB[j][3] + rowB[k][3]) * 0.25F; + } + } + else if (datatype == GL_FLOAT && comps == 3) { + GLuint i, j, k; + const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA; + const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB; + GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + } + } + else if (datatype == GL_FLOAT && comps == 2) { + GLuint i, j, k; + const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA; + const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB; + GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + } + } + else if (datatype == GL_FLOAT && comps == 1) { + GLuint i, j, k; + const GLfloat *rowA = (const GLfloat *) srcRowA; + const GLfloat *rowB = (const GLfloat *) srcRowB; + GLfloat *dst = (GLfloat *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; + } + } + + else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) { + GLuint i, j, k, comp; + const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA; + const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB; + GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 4; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) { + GLuint i, j, k, comp; + const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA; + const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB; + GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 3; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) { + GLuint i, j, k, comp; + const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA; + const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB; + GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 2; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) { + GLuint i, j, k; + const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; + const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; + GLhalfARB *dst = (GLhalfARB *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j]); + ak = _mesa_half_to_float(rowA[k]); + bj = _mesa_half_to_float(rowB[j]); + bk = _mesa_half_to_float(rowB[k]); + dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + + else if (datatype == GL_UNSIGNED_INT && comps == 1) { + GLuint i, j, k; + const GLuint *rowA = (const GLuint *) srcRowA; + const GLuint *rowB = (const GLuint *) srcRowB; + GLuint *dst = (GLuint *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4); + } + } + + else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x1f; + const GLint rowAr1 = rowA[k] & 0x1f; + const GLint rowBr0 = rowB[j] & 0x1f; + const GLint rowBr1 = rowB[k] & 0x1f; + const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; + const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; + const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; + const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; + const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + dst[i] = (blue << 11) | (green << 5) | red; + } + } + else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint rowAb0 = (rowA[j] >> 8) & 0xf; + const GLint rowAb1 = (rowA[k] >> 8) & 0xf; + const GLint rowBb0 = (rowB[j] >> 8) & 0xf; + const GLint rowBb1 = (rowB[k] >> 8) & 0xf; + const GLint rowAa0 = (rowA[j] >> 12) & 0xf; + const GLint rowAa1 = (rowA[k] >> 12) & 0xf; + const GLint rowBa0 = (rowB[j] >> 12) & 0xf; + const GLint rowBa1 = (rowB[k] >> 12) & 0xf; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; + } + } + else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x1f; + const GLint rowAr1 = rowA[k] & 0x1f; + const GLint rowBr0 = rowB[j] & 0x1f; + const GLint rowBr1 = rowB[k] & 0x1f; + const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; + const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; + const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; + const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; + const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; + const GLint rowAa0 = (rowA[j] >> 15) & 0x1; + const GLint rowAa1 = (rowA[k] >> 15) & 0x1; + const GLint rowBa0 = (rowB[j] >> 15) & 0x1; + const GLint rowBa1 = (rowB[k] >> 15) & 0x1; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; + } + } + else if (datatype == GL_UNSIGNED_SHORT_5_5_5_1 && comps == 4) { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; + const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; + const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; + const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; + const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; + const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; + const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; + const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; + const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; + const GLint rowAa0 = (rowA[j] & 0x1); + const GLint rowAa1 = (rowA[k] & 0x1); + const GLint rowBa0 = (rowB[j] & 0x1); + const GLint rowBa1 = (rowB[k] & 0x1); + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (red << 11) | (green << 6) | (blue << 1) | alpha; + } + } + + else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) { + GLuint i, j, k; + const GLubyte *rowA = (const GLubyte *) srcRowA; + const GLubyte *rowB = (const GLubyte *) srcRowB; + GLubyte *dst = (GLubyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x3; + const GLint rowAr1 = rowA[k] & 0x3; + const GLint rowBr0 = rowB[j] & 0x3; + const GLint rowBr1 = rowB[k] & 0x3; + const GLint rowAg0 = (rowA[j] >> 2) & 0x7; + const GLint rowAg1 = (rowA[k] >> 2) & 0x7; + const GLint rowBg0 = (rowB[j] >> 2) & 0x7; + const GLint rowBg1 = (rowB[k] >> 2) & 0x7; + const GLint rowAb0 = (rowA[j] >> 5) & 0x7; + const GLint rowAb1 = (rowA[k] >> 5) & 0x7; + const GLint rowBb0 = (rowB[j] >> 5) & 0x7; + const GLint rowBb1 = (rowB[k] >> 5) & 0x7; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + dst[i] = (blue << 5) | (green << 2) | red; + } + } + + else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { + GLuint i, j, k; + const GLubyte *rowA = (const GLubyte *) srcRowA; + const GLubyte *rowB = (const GLubyte *) srcRowB; + GLubyte *dst = (GLubyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint r = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint g = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + dst[i] = (g << 4) | r; + } + } + + else if (datatype == GL_UNSIGNED_INT_2_10_10_10_REV && comps == 4) { + GLuint i, j, k; + const GLuint *rowA = (const GLuint *) srcRowA; + const GLuint *rowB = (const GLuint *) srcRowB; + GLuint *dst = (GLuint *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x3ff; + const GLint rowAr1 = rowA[k] & 0x3ff; + const GLint rowBr0 = rowB[j] & 0x3ff; + const GLint rowBr1 = rowB[k] & 0x3ff; + const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff; + const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff; + const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff; + const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff; + const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff; + const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff; + const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff; + const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff; + const GLint rowAa0 = (rowA[j] >> 30) & 0x3; + const GLint rowAa1 = (rowA[k] >> 30) & 0x3; + const GLint rowBa0 = (rowB[j] >> 30) & 0x3; + const GLint rowBa1 = (rowB[k] >> 30) & 0x3; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (alpha << 30) | (blue << 20) | (green << 10) | red; + } + } + + else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { + GLuint i, j, k; + const GLuint *rowA = (const GLuint*) srcRowA; + const GLuint *rowB = (const GLuint*) srcRowB; + GLuint *dst = (GLuint*)dstRow; + GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3]; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + rgb9e5_to_float3(rowA[j], rowAj); + rgb9e5_to_float3(rowB[j], rowBj); + rgb9e5_to_float3(rowA[k], rowAk); + rgb9e5_to_float3(rowB[k], rowBk); + res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F; + res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F; + res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F; + dst[i] = float3_to_rgb9e5(res); + } + } + + else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) { + GLuint i, j, k; + const GLuint *rowA = (const GLuint*) srcRowA; + const GLuint *rowB = (const GLuint*) srcRowB; + GLuint *dst = (GLuint*)dstRow; + GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3]; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + r11g11b10f_to_float3(rowA[j], rowAj); + r11g11b10f_to_float3(rowB[j], rowBj); + r11g11b10f_to_float3(rowA[k], rowAk); + r11g11b10f_to_float3(rowB[k], rowBk); + res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F; + res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F; + res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F; + dst[i] = float3_to_r11g11b10f(res); + } + } + + else { + _mesa_problem(NULL, "bad format in do_row()"); + } +} + + +/** + * Average together four rows of a source image to produce a single new + * row in the dest image. It's legal for the two source rows to point + * to the same data. The source width must be equal to either the + * dest width or two times the dest width. + * + * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, + * \c GL_FLOAT, etc. + * \param comps number of components per pixel (1..4) + * \param srcWidth Width of a row in the source data + * \param srcRowA Pointer to one of the rows of source data + * \param srcRowB Pointer to one of the rows of source data + * \param srcRowC Pointer to one of the rows of source data + * \param srcRowD Pointer to one of the rows of source data + * \param dstWidth Width of a row in the destination data + * \param srcRowA Pointer to the row of destination data + */ +static void +do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, + const GLvoid *srcRowA, const GLvoid *srcRowB, + const GLvoid *srcRowC, const GLvoid *srcRowD, + GLint dstWidth, GLvoid *dstRow) +{ + const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; + const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; + GLuint i, j, k; + + ASSERT(comps >= 1); + ASSERT(comps <= 4); + + if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) { + DECLARE_ROW_POINTERS(GLubyte, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + FILTER_3D(3); + } + } + else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) { + DECLARE_ROW_POINTERS(GLubyte, 3); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + } + } + else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) { + DECLARE_ROW_POINTERS(GLubyte, 2); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + } + } + else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) { + DECLARE_ROW_POINTERS(GLubyte, 1); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + } + } + else if ((datatype == GL_BYTE) && (comps == 4)) { + DECLARE_ROW_POINTERS(GLbyte, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D_SIGNED(0); + FILTER_3D_SIGNED(1); + FILTER_3D_SIGNED(2); + FILTER_3D_SIGNED(3); + } + } + else if ((datatype == GL_BYTE) && (comps == 3)) { + DECLARE_ROW_POINTERS(GLbyte, 3); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D_SIGNED(0); + FILTER_3D_SIGNED(1); + FILTER_3D_SIGNED(2); + } + } + else if ((datatype == GL_BYTE) && (comps == 2)) { + DECLARE_ROW_POINTERS(GLbyte, 2); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D_SIGNED(0); + FILTER_3D_SIGNED(1); + } + } + else if ((datatype == GL_BYTE) && (comps == 1)) { + DECLARE_ROW_POINTERS(GLbyte, 1); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D_SIGNED(0); + } + } + else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) { + DECLARE_ROW_POINTERS(GLushort, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + FILTER_3D(3); + } + } + else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) { + DECLARE_ROW_POINTERS(GLushort, 3); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + } + } + else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) { + DECLARE_ROW_POINTERS(GLushort, 2); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + } + } + else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) { + DECLARE_ROW_POINTERS(GLushort, 1); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + } + } + else if ((datatype == GL_SHORT) && (comps == 4)) { + DECLARE_ROW_POINTERS(GLshort, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + FILTER_3D(3); + } + } + else if ((datatype == GL_SHORT) && (comps == 3)) { + DECLARE_ROW_POINTERS(GLshort, 3); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + } + } + else if ((datatype == GL_SHORT) && (comps == 2)) { + DECLARE_ROW_POINTERS(GLshort, 2); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + } + } + else if ((datatype == GL_SHORT) && (comps == 1)) { + DECLARE_ROW_POINTERS(GLshort, 1); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + } + } + else if ((datatype == GL_FLOAT) && (comps == 4)) { + DECLARE_ROW_POINTERS(GLfloat, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + FILTER_F_3D(1); + FILTER_F_3D(2); + FILTER_F_3D(3); + } + } + else if ((datatype == GL_FLOAT) && (comps == 3)) { + DECLARE_ROW_POINTERS(GLfloat, 3); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + FILTER_F_3D(1); + FILTER_F_3D(2); + } + } + else if ((datatype == GL_FLOAT) && (comps == 2)) { + DECLARE_ROW_POINTERS(GLfloat, 2); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + FILTER_F_3D(1); + } + } + else if ((datatype == GL_FLOAT) && (comps == 1)) { + DECLARE_ROW_POINTERS(GLfloat, 1); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + } + } + else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) { + DECLARE_ROW_POINTERS(GLhalfARB, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + FILTER_HF_3D(1); + FILTER_HF_3D(2); + FILTER_HF_3D(3); + } + } + else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) { + DECLARE_ROW_POINTERS(GLhalfARB, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + FILTER_HF_3D(1); + FILTER_HF_3D(2); + } + } + else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) { + DECLARE_ROW_POINTERS(GLhalfARB, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + FILTER_HF_3D(1); + } + } + else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) { + DECLARE_ROW_POINTERS(GLhalfARB, 4); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + } + } + else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) { + const GLuint *rowA = (const GLuint *) srcRowA; + const GLuint *rowB = (const GLuint *) srcRowB; + const GLuint *rowC = (const GLuint *) srcRowC; + const GLuint *rowD = (const GLuint *) srcRowD; + GLfloat *dst = (GLfloat *) dstRow; + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k]) + + ((uint64_t) rowB[j] + (uint64_t) rowB[k]) + + ((uint64_t) rowC[j] + (uint64_t) rowC[k]) + + ((uint64_t) rowD[j] + (uint64_t) rowD[k])); + dst[i] = (GLfloat)((double) tmp * 0.125); + } + } + else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) { + DECLARE_ROW_POINTERS0(GLushort); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x1f; + const GLint rowAr1 = rowA[k] & 0x1f; + const GLint rowBr0 = rowB[j] & 0x1f; + const GLint rowBr1 = rowB[k] & 0x1f; + const GLint rowCr0 = rowC[j] & 0x1f; + const GLint rowCr1 = rowC[k] & 0x1f; + const GLint rowDr0 = rowD[j] & 0x1f; + const GLint rowDr1 = rowD[k] & 0x1f; + const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; + const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; + const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; + const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; + const GLint rowCg0 = (rowC[j] >> 5) & 0x3f; + const GLint rowCg1 = (rowC[k] >> 5) & 0x3f; + const GLint rowDg0 = (rowD[j] >> 5) & 0x3f; + const GLint rowDg1 = (rowD[k] >> 5) & 0x3f; + const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; + const GLint rowCb0 = (rowC[j] >> 11) & 0x1f; + const GLint rowCb1 = (rowC[k] >> 11) & 0x1f; + const GLint rowDb0 = (rowD[j] >> 11) & 0x1f; + const GLint rowDb1 = (rowD[k] >> 11) & 0x1f; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + dst[i] = (b << 11) | (g << 5) | r; + } + } + else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) { + DECLARE_ROW_POINTERS0(GLushort); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowCr0 = rowC[j] & 0xf; + const GLint rowCr1 = rowC[k] & 0xf; + const GLint rowDr0 = rowD[j] & 0xf; + const GLint rowDr1 = rowD[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint rowCg0 = (rowC[j] >> 4) & 0xf; + const GLint rowCg1 = (rowC[k] >> 4) & 0xf; + const GLint rowDg0 = (rowD[j] >> 4) & 0xf; + const GLint rowDg1 = (rowD[k] >> 4) & 0xf; + const GLint rowAb0 = (rowA[j] >> 8) & 0xf; + const GLint rowAb1 = (rowA[k] >> 8) & 0xf; + const GLint rowBb0 = (rowB[j] >> 8) & 0xf; + const GLint rowBb1 = (rowB[k] >> 8) & 0xf; + const GLint rowCb0 = (rowC[j] >> 8) & 0xf; + const GLint rowCb1 = (rowC[k] >> 8) & 0xf; + const GLint rowDb0 = (rowD[j] >> 8) & 0xf; + const GLint rowDb1 = (rowD[k] >> 8) & 0xf; + const GLint rowAa0 = (rowA[j] >> 12) & 0xf; + const GLint rowAa1 = (rowA[k] >> 12) & 0xf; + const GLint rowBa0 = (rowB[j] >> 12) & 0xf; + const GLint rowBa1 = (rowB[k] >> 12) & 0xf; + const GLint rowCa0 = (rowC[j] >> 12) & 0xf; + const GLint rowCa1 = (rowC[k] >> 12) & 0xf; + const GLint rowDa0 = (rowD[j] >> 12) & 0xf; + const GLint rowDa1 = (rowD[k] >> 12) & 0xf; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, + rowCa0, rowCa1, rowDa0, rowDa1); + + dst[i] = (a << 12) | (b << 8) | (g << 4) | r; + } + } + else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) { + DECLARE_ROW_POINTERS0(GLushort); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x1f; + const GLint rowAr1 = rowA[k] & 0x1f; + const GLint rowBr0 = rowB[j] & 0x1f; + const GLint rowBr1 = rowB[k] & 0x1f; + const GLint rowCr0 = rowC[j] & 0x1f; + const GLint rowCr1 = rowC[k] & 0x1f; + const GLint rowDr0 = rowD[j] & 0x1f; + const GLint rowDr1 = rowD[k] & 0x1f; + const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; + const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; + const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; + const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; + const GLint rowCg0 = (rowC[j] >> 5) & 0x1f; + const GLint rowCg1 = (rowC[k] >> 5) & 0x1f; + const GLint rowDg0 = (rowD[j] >> 5) & 0x1f; + const GLint rowDg1 = (rowD[k] >> 5) & 0x1f; + const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; + const GLint rowCb0 = (rowC[j] >> 10) & 0x1f; + const GLint rowCb1 = (rowC[k] >> 10) & 0x1f; + const GLint rowDb0 = (rowD[j] >> 10) & 0x1f; + const GLint rowDb1 = (rowD[k] >> 10) & 0x1f; + const GLint rowAa0 = (rowA[j] >> 15) & 0x1; + const GLint rowAa1 = (rowA[k] >> 15) & 0x1; + const GLint rowBa0 = (rowB[j] >> 15) & 0x1; + const GLint rowBa1 = (rowB[k] >> 15) & 0x1; + const GLint rowCa0 = (rowC[j] >> 15) & 0x1; + const GLint rowCa1 = (rowC[k] >> 15) & 0x1; + const GLint rowDa0 = (rowD[j] >> 15) & 0x1; + const GLint rowDa1 = (rowD[k] >> 15) & 0x1; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, + rowCa0, rowCa1, rowDa0, rowDa1); + + dst[i] = (a << 15) | (b << 10) | (g << 5) | r; + } + } + else if ((datatype == GL_UNSIGNED_SHORT_5_5_5_1) && (comps == 4)) { + DECLARE_ROW_POINTERS0(GLushort); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = (rowA[j] >> 11) & 0x1f; + const GLint rowAr1 = (rowA[k] >> 11) & 0x1f; + const GLint rowBr0 = (rowB[j] >> 11) & 0x1f; + const GLint rowBr1 = (rowB[k] >> 11) & 0x1f; + const GLint rowCr0 = (rowC[j] >> 11) & 0x1f; + const GLint rowCr1 = (rowC[k] >> 11) & 0x1f; + const GLint rowDr0 = (rowD[j] >> 11) & 0x1f; + const GLint rowDr1 = (rowD[k] >> 11) & 0x1f; + const GLint rowAg0 = (rowA[j] >> 6) & 0x1f; + const GLint rowAg1 = (rowA[k] >> 6) & 0x1f; + const GLint rowBg0 = (rowB[j] >> 6) & 0x1f; + const GLint rowBg1 = (rowB[k] >> 6) & 0x1f; + const GLint rowCg0 = (rowC[j] >> 6) & 0x1f; + const GLint rowCg1 = (rowC[k] >> 6) & 0x1f; + const GLint rowDg0 = (rowD[j] >> 6) & 0x1f; + const GLint rowDg1 = (rowD[k] >> 6) & 0x1f; + const GLint rowAb0 = (rowA[j] >> 1) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 1) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 1) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 1) & 0x1f; + const GLint rowCb0 = (rowC[j] >> 1) & 0x1f; + const GLint rowCb1 = (rowC[k] >> 1) & 0x1f; + const GLint rowDb0 = (rowD[j] >> 1) & 0x1f; + const GLint rowDb1 = (rowD[k] >> 1) & 0x1f; + const GLint rowAa0 = (rowA[j] & 0x1); + const GLint rowAa1 = (rowA[k] & 0x1); + const GLint rowBa0 = (rowB[j] & 0x1); + const GLint rowBa1 = (rowB[k] & 0x1); + const GLint rowCa0 = (rowC[j] & 0x1); + const GLint rowCa1 = (rowC[k] & 0x1); + const GLint rowDa0 = (rowD[j] & 0x1); + const GLint rowDa1 = (rowD[k] & 0x1); + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, + rowCa0, rowCa1, rowDa0, rowDa1); + + dst[i] = (r << 11) | (g << 6) | (b << 1) | a; + } + } + else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) { + DECLARE_ROW_POINTERS0(GLubyte); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x3; + const GLint rowAr1 = rowA[k] & 0x3; + const GLint rowBr0 = rowB[j] & 0x3; + const GLint rowBr1 = rowB[k] & 0x3; + const GLint rowCr0 = rowC[j] & 0x3; + const GLint rowCr1 = rowC[k] & 0x3; + const GLint rowDr0 = rowD[j] & 0x3; + const GLint rowDr1 = rowD[k] & 0x3; + const GLint rowAg0 = (rowA[j] >> 2) & 0x7; + const GLint rowAg1 = (rowA[k] >> 2) & 0x7; + const GLint rowBg0 = (rowB[j] >> 2) & 0x7; + const GLint rowBg1 = (rowB[k] >> 2) & 0x7; + const GLint rowCg0 = (rowC[j] >> 2) & 0x7; + const GLint rowCg1 = (rowC[k] >> 2) & 0x7; + const GLint rowDg0 = (rowD[j] >> 2) & 0x7; + const GLint rowDg1 = (rowD[k] >> 2) & 0x7; + const GLint rowAb0 = (rowA[j] >> 5) & 0x7; + const GLint rowAb1 = (rowA[k] >> 5) & 0x7; + const GLint rowBb0 = (rowB[j] >> 5) & 0x7; + const GLint rowBb1 = (rowB[k] >> 5) & 0x7; + const GLint rowCb0 = (rowC[j] >> 5) & 0x7; + const GLint rowCb1 = (rowC[k] >> 5) & 0x7; + const GLint rowDb0 = (rowD[j] >> 5) & 0x7; + const GLint rowDb1 = (rowD[k] >> 5) & 0x7; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + dst[i] = (b << 5) | (g << 2) | r; + } + } + else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { + DECLARE_ROW_POINTERS0(GLubyte); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowCr0 = rowC[j] & 0xf; + const GLint rowCr1 = rowC[k] & 0xf; + const GLint rowDr0 = rowD[j] & 0xf; + const GLint rowDr1 = rowD[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint rowCg0 = (rowC[j] >> 4) & 0xf; + const GLint rowCg1 = (rowC[k] >> 4) & 0xf; + const GLint rowDg0 = (rowD[j] >> 4) & 0xf; + const GLint rowDg1 = (rowD[k] >> 4) & 0xf; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + dst[i] = (g << 4) | r; + } + } + else if ((datatype == GL_UNSIGNED_INT_2_10_10_10_REV) && (comps == 4)) { + DECLARE_ROW_POINTERS0(GLuint); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x3ff; + const GLint rowAr1 = rowA[k] & 0x3ff; + const GLint rowBr0 = rowB[j] & 0x3ff; + const GLint rowBr1 = rowB[k] & 0x3ff; + const GLint rowCr0 = rowC[j] & 0x3ff; + const GLint rowCr1 = rowC[k] & 0x3ff; + const GLint rowDr0 = rowD[j] & 0x3ff; + const GLint rowDr1 = rowD[k] & 0x3ff; + const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff; + const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff; + const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff; + const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff; + const GLint rowCg0 = (rowC[j] >> 10) & 0x3ff; + const GLint rowCg1 = (rowC[k] >> 10) & 0x3ff; + const GLint rowDg0 = (rowD[j] >> 10) & 0x3ff; + const GLint rowDg1 = (rowD[k] >> 10) & 0x3ff; + const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff; + const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff; + const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff; + const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff; + const GLint rowCb0 = (rowC[j] >> 20) & 0x3ff; + const GLint rowCb1 = (rowC[k] >> 20) & 0x3ff; + const GLint rowDb0 = (rowD[j] >> 20) & 0x3ff; + const GLint rowDb1 = (rowD[k] >> 20) & 0x3ff; + const GLint rowAa0 = (rowA[j] >> 30) & 0x3; + const GLint rowAa1 = (rowA[k] >> 30) & 0x3; + const GLint rowBa0 = (rowB[j] >> 30) & 0x3; + const GLint rowBa1 = (rowB[k] >> 30) & 0x3; + const GLint rowCa0 = (rowC[j] >> 30) & 0x3; + const GLint rowCa1 = (rowC[k] >> 30) & 0x3; + const GLint rowDa0 = (rowD[j] >> 30) & 0x3; + const GLint rowDa1 = (rowD[k] >> 30) & 0x3; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, + rowCa0, rowCa1, rowDa0, rowDa1); + + dst[i] = (a << 30) | (b << 20) | (g << 10) | r; + } + } + + else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { + DECLARE_ROW_POINTERS0(GLuint); + + GLfloat res[3]; + GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3]; + GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3]; + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + rgb9e5_to_float3(rowA[j], rowAj); + rgb9e5_to_float3(rowB[j], rowBj); + rgb9e5_to_float3(rowC[j], rowCj); + rgb9e5_to_float3(rowD[j], rowDj); + rgb9e5_to_float3(rowA[k], rowAk); + rgb9e5_to_float3(rowB[k], rowBk); + rgb9e5_to_float3(rowC[k], rowCk); + rgb9e5_to_float3(rowD[k], rowDk); + res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] + + rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F; + res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] + + rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F; + res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] + + rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F; + dst[i] = float3_to_rgb9e5(res); + } + } + + else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) { + DECLARE_ROW_POINTERS0(GLuint); + + GLfloat res[3]; + GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3]; + GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3]; + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + r11g11b10f_to_float3(rowA[j], rowAj); + r11g11b10f_to_float3(rowB[j], rowBj); + r11g11b10f_to_float3(rowC[j], rowCj); + r11g11b10f_to_float3(rowD[j], rowDj); + r11g11b10f_to_float3(rowA[k], rowAk); + r11g11b10f_to_float3(rowB[k], rowBk); + r11g11b10f_to_float3(rowC[k], rowCk); + r11g11b10f_to_float3(rowD[k], rowDk); + res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] + + rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F; + res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] + + rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F; + res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] + + rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F; + dst[i] = float3_to_r11g11b10f(res); + } + } + + else { + _mesa_problem(NULL, "bad format in do_row()"); + } +} + + +/* + * These functions generate a 1/2-size mipmap image from a source image. + * Texture borders are handled by copying or averaging the source image's + * border texels, depending on the scale-down factor. + */ + +static void +make_1d_mipmap(GLenum datatype, GLuint comps, GLint border, + GLint srcWidth, const GLubyte *srcPtr, + GLint dstWidth, GLubyte *dstPtr) +{ + const GLint bpt = bytes_per_pixel(datatype, comps); + const GLubyte *src; + GLubyte *dst; + + /* skip the border pixel, if any */ + src = srcPtr + border * bpt; + dst = dstPtr + border * bpt; + + /* we just duplicate the input row, kind of hack, saves code */ + do_row(datatype, comps, srcWidth - 2 * border, src, src, + dstWidth - 2 * border, dst); + + if (border) { + /* copy left-most pixel from source */ + assert(dstPtr); + assert(srcPtr); + memcpy(dstPtr, srcPtr, bpt); + /* copy right-most pixel from source */ + memcpy(dstPtr + (dstWidth - 1) * bpt, + srcPtr + (srcWidth - 1) * bpt, + bpt); + } +} + + +static void +make_2d_mipmap(GLenum datatype, GLuint comps, GLint border, + GLint srcWidth, GLint srcHeight, + const GLubyte *srcPtr, GLint srcRowStride, + GLint dstWidth, GLint dstHeight, + GLubyte *dstPtr, GLint dstRowStride) +{ + const GLint bpt = bytes_per_pixel(datatype, comps); + const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ + const GLint dstWidthNB = dstWidth - 2 * border; + const GLint dstHeightNB = dstHeight - 2 * border; + const GLint srcRowBytes = bpt * srcRowStride; + const GLint dstRowBytes = bpt * dstRowStride; + const GLubyte *srcA, *srcB; + GLubyte *dst; + GLint row, srcRowStep; + + /* Compute src and dst pointers, skipping any border */ + srcA = srcPtr + border * ((srcWidth + 1) * bpt); + if (srcHeight > 1 && srcHeight > dstHeight) { + /* sample from two source rows */ + srcB = srcA + srcRowBytes; + srcRowStep = 2; + } + else { + /* sample from one source row */ + srcB = srcA; + srcRowStep = 1; + } + + dst = dstPtr + border * ((dstWidth + 1) * bpt); + + for (row = 0; row < dstHeightNB; row++) { + do_row(datatype, comps, srcWidthNB, srcA, srcB, + dstWidthNB, dst); + srcA += srcRowStep * srcRowBytes; + srcB += srcRowStep * srcRowBytes; + dst += dstRowBytes; + } + + /* This is ugly but probably won't be used much */ + if (border > 0) { + /* fill in dest border */ + /* lower-left border pixel */ + assert(dstPtr); + assert(srcPtr); + memcpy(dstPtr, srcPtr, bpt); + /* lower-right border pixel */ + memcpy(dstPtr + (dstWidth - 1) * bpt, + srcPtr + (srcWidth - 1) * bpt, bpt); + /* upper-left border pixel */ + memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt, + srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); + /* upper-right border pixel */ + memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt, + srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); + /* lower border */ + do_row(datatype, comps, srcWidthNB, + srcPtr + bpt, + srcPtr + bpt, + dstWidthNB, dstPtr + bpt); + /* upper border */ + do_row(datatype, comps, srcWidthNB, + srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, + srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, + dstWidthNB, + dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); + /* left and right borders */ + if (srcHeight == dstHeight) { + /* copy border pixel from src to dst */ + for (row = 1; row < srcHeight; row++) { + memcpy(dstPtr + dstWidth * row * bpt, + srcPtr + srcWidth * row * bpt, bpt); + memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, + srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); + } + } + else { + /* average two src pixels each dest pixel */ + for (row = 0; row < dstHeightNB; row += 2) { + do_row(datatype, comps, 1, + srcPtr + (srcWidth * (row * 2 + 1)) * bpt, + srcPtr + (srcWidth * (row * 2 + 2)) * bpt, + 1, dstPtr + (dstWidth * row + 1) * bpt); + do_row(datatype, comps, 1, + srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, + srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, + 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); + } + } + } +} + + +static void +make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + const GLubyte *srcPtr, GLint srcRowStride, + GLint dstWidth, GLint dstHeight, GLint dstDepth, + GLubyte *dstPtr, GLint dstRowStride) +{ + const GLint bpt = bytes_per_pixel(datatype, comps); + const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ + const GLint srcDepthNB = srcDepth - 2 * border; + const GLint dstWidthNB = dstWidth - 2 * border; + const GLint dstHeightNB = dstHeight - 2 * border; + const GLint dstDepthNB = dstDepth - 2 * border; + GLint img, row; + GLint bytesPerSrcImage, bytesPerDstImage; + GLint bytesPerSrcRow, bytesPerDstRow; + GLint srcImageOffset, srcRowOffset; + + (void) srcDepthNB; /* silence warnings */ + + + bytesPerSrcImage = srcWidth * srcHeight * bpt; + bytesPerDstImage = dstWidth * dstHeight * bpt; + + bytesPerSrcRow = srcWidth * bpt; + bytesPerDstRow = dstWidth * bpt; + + /* Offset between adjacent src images to be averaged together */ + srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage; + + /* Offset between adjacent src rows to be averaged together */ + srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; + + /* + * Need to average together up to 8 src pixels for each dest pixel. + * Break that down into 3 operations: + * 1. take two rows from source image and average them together. + * 2. take two rows from next source image and average them together. + * 3. take the two averaged rows and average them for the final dst row. + */ + + /* + printf("mip3d %d x %d x %d -> %d x %d x %d\n", + srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); + */ + + for (img = 0; img < dstDepthNB; img++) { + /* first source image pointer, skipping border */ + const GLubyte *imgSrcA = srcPtr + + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border + + img * (bytesPerSrcImage + srcImageOffset); + /* second source image pointer, skipping border */ + const GLubyte *imgSrcB = imgSrcA + srcImageOffset; + /* address of the dest image, skipping border */ + GLubyte *imgDst = dstPtr + + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border + + img * bytesPerDstImage; + + /* setup the four source row pointers and the dest row pointer */ + const GLubyte *srcImgARowA = imgSrcA; + const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; + const GLubyte *srcImgBRowA = imgSrcB; + const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; + GLubyte *dstImgRow = imgDst; + + for (row = 0; row < dstHeightNB; row++) { + do_row_3D(datatype, comps, srcWidthNB, + srcImgARowA, srcImgARowB, + srcImgBRowA, srcImgBRowB, + dstWidthNB, dstImgRow); + + /* advance to next rows */ + srcImgARowA += bytesPerSrcRow + srcRowOffset; + srcImgARowB += bytesPerSrcRow + srcRowOffset; + srcImgBRowA += bytesPerSrcRow + srcRowOffset; + srcImgBRowB += bytesPerSrcRow + srcRowOffset; + dstImgRow += bytesPerDstRow; + } + } + + + /* Luckily we can leverage the make_2d_mipmap() function here! */ + if (border > 0) { + /* do front border image */ + make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride, + dstWidth, dstHeight, dstPtr, dstRowStride); + /* do back border image */ + make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, + srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride, + dstWidth, dstHeight, + dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride); + /* do four remaining border edges that span the image slices */ + if (srcDepth == dstDepth) { + /* just copy border pixels from src to dst */ + for (img = 0; img < dstDepthNB; img++) { + const GLubyte *src; + GLubyte *dst; + + /* do border along [img][row=0][col=0] */ + src = srcPtr + (img + 1) * bytesPerSrcImage; + dst = dstPtr + (img + 1) * bytesPerDstImage; + memcpy(dst, src, bpt); + + /* do border along [img][row=dstHeight-1][col=0] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcHeight - 1) * bytesPerSrcRow; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstHeight - 1) * bytesPerDstRow; + memcpy(dst, src, bpt); + + /* do border along [img][row=0][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcWidth - 1) * bpt; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstWidth - 1) * bpt; + memcpy(dst, src, bpt); + + /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (bytesPerSrcImage - bpt); + dst = dstPtr + (img + 1) * bytesPerDstImage + + (bytesPerDstImage - bpt); + memcpy(dst, src, bpt); + } + } + else { + /* average border pixels from adjacent src image pairs */ + ASSERT(srcDepthNB == 2 * dstDepthNB); + for (img = 0; img < dstDepthNB; img++) { + const GLubyte *src; + GLubyte *dst; + + /* do border along [img][row=0][col=0] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage; + dst = dstPtr + (img + 1) * bytesPerDstImage; + do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); + + /* do border along [img][row=dstHeight-1][col=0] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcHeight - 1) * bytesPerSrcRow; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstHeight - 1) * bytesPerDstRow; + do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); + + /* do border along [img][row=0][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcWidth - 1) * bpt; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstWidth - 1) * bpt; + do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); + + /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (bytesPerSrcImage - bpt); + dst = dstPtr + (img + 1) * bytesPerDstImage + + (bytesPerDstImage - bpt); + do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); + } + } + } +} + + +static void +make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, + GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride, + GLint dstWidth, GLint dstHeight, + GLubyte *dstPtr, GLuint dstRowStride ) +{ + const GLint bpt = bytes_per_pixel(datatype, comps); + const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ + const GLint dstWidthNB = dstWidth - 2 * border; + const GLint dstHeightNB = dstHeight - 2 * border; + const GLint srcRowBytes = bpt * srcRowStride; + const GLint dstRowBytes = bpt * dstRowStride; + const GLubyte *src; + GLubyte *dst; + GLint row; + + /* Compute src and dst pointers, skipping any border */ + src = srcPtr + border * ((srcWidth + 1) * bpt); + dst = dstPtr + border * ((dstWidth + 1) * bpt); + + for (row = 0; row < dstHeightNB; row++) { + do_row(datatype, comps, srcWidthNB, src, src, + dstWidthNB, dst); + src += srcRowBytes; + dst += dstRowBytes; + } + + if (border) { + /* copy left-most pixel from source */ + assert(dstPtr); + assert(srcPtr); + memcpy(dstPtr, srcPtr, bpt); + /* copy right-most pixel from source */ + memcpy(dstPtr + (dstWidth - 1) * bpt, + srcPtr + (srcWidth - 1) * bpt, + bpt); + } +} + + +/** + * \bug + * There is quite a bit of refactoring that could be done with this function + * and \c make_2d_mipmap. + */ +static void +make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, + GLint srcWidth, GLint srcHeight, + const GLubyte *srcPtr, GLint srcRowStride, + GLint dstWidth, GLint dstHeight, GLint dstDepth, + GLubyte *dstPtr, GLint dstRowStride) +{ + const GLint bpt = bytes_per_pixel(datatype, comps); + const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ + const GLint dstWidthNB = dstWidth - 2 * border; + const GLint dstHeightNB = dstHeight - 2 * border; + const GLint dstDepthNB = dstDepth - 2 * border; + const GLint srcRowBytes = bpt * srcRowStride; + const GLint dstRowBytes = bpt * dstRowStride; + const GLubyte *srcA, *srcB; + GLubyte *dst; + GLint layer; + GLint row; + + /* Compute src and dst pointers, skipping any border */ + srcA = srcPtr + border * ((srcWidth + 1) * bpt); + if (srcHeight > 1) + srcB = srcA + srcRowBytes; + else + srcB = srcA; + dst = dstPtr + border * ((dstWidth + 1) * bpt); + + for (layer = 0; layer < dstDepthNB; layer++) { + for (row = 0; row < dstHeightNB; row++) { + do_row(datatype, comps, srcWidthNB, srcA, srcB, + dstWidthNB, dst); + srcA += 2 * srcRowBytes; + srcB += 2 * srcRowBytes; + dst += dstRowBytes; + } + + /* This is ugly but probably won't be used much */ + if (border > 0) { + /* fill in dest border */ + /* lower-left border pixel */ + assert(dstPtr); + assert(srcPtr); + memcpy(dstPtr, srcPtr, bpt); + /* lower-right border pixel */ + memcpy(dstPtr + (dstWidth - 1) * bpt, + srcPtr + (srcWidth - 1) * bpt, bpt); + /* upper-left border pixel */ + memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt, + srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); + /* upper-right border pixel */ + memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt, + srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); + /* lower border */ + do_row(datatype, comps, srcWidthNB, + srcPtr + bpt, + srcPtr + bpt, + dstWidthNB, dstPtr + bpt); + /* upper border */ + do_row(datatype, comps, srcWidthNB, + srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, + srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, + dstWidthNB, + dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); + /* left and right borders */ + if (srcHeight == dstHeight) { + /* copy border pixel from src to dst */ + for (row = 1; row < srcHeight; row++) { + memcpy(dstPtr + dstWidth * row * bpt, + srcPtr + srcWidth * row * bpt, bpt); + memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, + srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); + } + } + else { + /* average two src pixels each dest pixel */ + for (row = 0; row < dstHeightNB; row += 2) { + do_row(datatype, comps, 1, + srcPtr + (srcWidth * (row * 2 + 1)) * bpt, + srcPtr + (srcWidth * (row * 2 + 2)) * bpt, + 1, dstPtr + (dstWidth * row + 1) * bpt); + do_row(datatype, comps, 1, + srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, + srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, + 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); + } + } + } + } +} + + +/** + * Down-sample a texture image to produce the next lower mipmap level. + * \param comps components per texel (1, 2, 3 or 4) + * \param srcRowStride stride between source rows, in texels + * \param dstRowStride stride between destination rows, in texels + */ +void +_mesa_generate_mipmap_level(GLenum target, + GLenum datatype, GLuint comps, + GLint border, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + const GLubyte *srcData, + GLint srcRowStride, + GLint dstWidth, GLint dstHeight, GLint dstDepth, + GLubyte *dstData, + GLint dstRowStride) +{ + /* + * We use simple 2x2 averaging to compute the next mipmap level. + */ + switch (target) { + case GL_TEXTURE_1D: + make_1d_mipmap(datatype, comps, border, + srcWidth, srcData, + dstWidth, dstData); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + make_2d_mipmap(datatype, comps, border, + srcWidth, srcHeight, srcData, srcRowStride, + dstWidth, dstHeight, dstData, dstRowStride); + break; + case GL_TEXTURE_3D: + make_3d_mipmap(datatype, comps, border, + srcWidth, srcHeight, srcDepth, + srcData, srcRowStride, + dstWidth, dstHeight, dstDepth, + dstData, dstRowStride); + break; + case GL_TEXTURE_1D_ARRAY_EXT: + make_1d_stack_mipmap(datatype, comps, border, + srcWidth, srcData, srcRowStride, + dstWidth, dstHeight, + dstData, dstRowStride); + break; + case GL_TEXTURE_2D_ARRAY_EXT: + make_2d_stack_mipmap(datatype, comps, border, + srcWidth, srcHeight, + srcData, srcRowStride, + dstWidth, dstHeight, + dstDepth, dstData, dstRowStride); + break; + case GL_TEXTURE_RECTANGLE_NV: + /* no mipmaps, do nothing */ + break; + default: + _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps"); + return; + } +} + + +/** + * compute next (level+1) image size + * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size) + */ +static GLboolean +next_mipmap_level_size(GLenum target, GLint border, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLint *dstWidth, GLint *dstHeight, GLint *dstDepth) +{ + if (srcWidth - 2 * border > 1) { + *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; + } + else { + *dstWidth = srcWidth; /* can't go smaller */ + } + + if ((srcHeight - 2 * border > 1) && + (target != GL_TEXTURE_1D_ARRAY_EXT)) { + *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; + } + else { + *dstHeight = srcHeight; /* can't go smaller */ + } + + if ((srcDepth - 2 * border > 1) && + (target != GL_TEXTURE_2D_ARRAY_EXT)) { + *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; + } + else { + *dstDepth = srcDepth; /* can't go smaller */ + } + + if (*dstWidth == srcWidth && + *dstHeight == srcHeight && + *dstDepth == srcDepth) { + return GL_FALSE; + } + else { + return GL_TRUE; + } +} + +static void +generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj, + const struct gl_texture_image *srcImage, + GLuint maxLevel) +{ + GLint level; + GLenum datatype; + GLuint comps; + + _mesa_format_to_type_and_comps(srcImage->TexFormat, &datatype, &comps); + + for (level = texObj->BaseLevel; level < maxLevel; level++) { + /* generate image[level+1] from image[level] */ + const struct gl_texture_image *srcImage; + struct gl_texture_image *dstImage; + GLint srcWidth, srcHeight, srcDepth; + GLint dstWidth, dstHeight, dstDepth; + GLint border; + GLboolean nextLevel; + + /* get src image parameters */ + srcImage = _mesa_select_tex_image(ctx, texObj, target, level); + ASSERT(srcImage); + srcWidth = srcImage->Width; + srcHeight = srcImage->Height; + srcDepth = srcImage->Depth; + border = srcImage->Border; + + nextLevel = next_mipmap_level_size(target, border, + srcWidth, srcHeight, srcDepth, + &dstWidth, &dstHeight, &dstDepth); + if (!nextLevel) + return; + + /* get dest gl_texture_image */ + dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); + if (!dstImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; + } + + /* Free old image data */ + if (dstImage->Data) + ctx->Driver.FreeTexImageData(ctx, dstImage); + + /* initialize new image */ + _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, + dstDepth, border, srcImage->InternalFormat, + srcImage->TexFormat); + dstImage->DriverData = NULL; + dstImage->FetchTexelc = srcImage->FetchTexelc; + dstImage->FetchTexelf = srcImage->FetchTexelf; + + /* Alloc new teximage data buffer */ + { + GLuint size = _mesa_format_image_size(dstImage->TexFormat, + dstWidth, dstHeight, dstDepth); + dstImage->Data = _mesa_alloc_texmemory(size); + if (!dstImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; + } + } + + ASSERT(dstImage->TexFormat); + ASSERT(dstImage->FetchTexelc); + ASSERT(dstImage->FetchTexelf); + + _mesa_generate_mipmap_level(target, datatype, comps, border, + srcWidth, srcHeight, srcDepth, + srcImage->Data, srcImage->RowStride, + dstWidth, dstHeight, dstDepth, + dstImage->Data, dstImage->RowStride); + + } /* loop over mipmap levels */ +} + +static void +generate_mipmap_compressed(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj, + const struct gl_texture_image *srcImage, + GLuint maxLevel) +{ + GLint level; + gl_format temp_format; + GLenum datatype; + GLuint comps; + GLuint row; + GLint components; + GLuint temp_src_stride, temp_dst_stride; /* in bytes */ + GLchan *temp_src = NULL, *temp_dst = NULL; + + /* Choose the format we will do _mesa_generate_mipmap_level() in, + * and uncompress the firstImage into a temporary of that format. + */ + assert(texObj->Target == GL_TEXTURE_2D || + texObj->Target == GL_TEXTURE_CUBE_MAP_ARB); + + if (srcImage->_BaseFormat == GL_RGB) { + temp_format = MESA_FORMAT_RGB888; + components = 3; + } else if (srcImage->_BaseFormat == GL_RED) { + temp_format = MESA_FORMAT_R8; + components = 1; + } else if (srcImage->_BaseFormat == GL_RG) { + temp_format = MESA_FORMAT_RG88; + components = 2; + } else if (srcImage->_BaseFormat == GL_RGBA) { + temp_format = MESA_FORMAT_RGBA8888; + components = 4; + } else if (srcImage->_BaseFormat == GL_LUMINANCE) { + temp_format = MESA_FORMAT_L8; + components = 1; + } else if (srcImage->_BaseFormat == GL_LUMINANCE_ALPHA) { + temp_format = MESA_FORMAT_AL88; + components = 2; + } else { + _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps"); + return; + } + + /* allocate storage for uncompressed GL_RGB or GL_RGBA images */ + temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width); + /* 20 extra bytes, just be safe when calling last FetchTexel */ + temp_src = (GLubyte *) malloc(temp_src_stride * srcImage->Height + 20); + if (!temp_src) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + return; + } + + /* decompress base image to the temporary */ + for (row = 0; row < srcImage->Height; row++) { + GLuint col; + GLchan *dst = (GLchan *) temp_src + temp_src_stride * row; + for (col = 0; col < srcImage->Width; col++) { + srcImage->FetchTexelc(srcImage, col, row, 0, dst); + dst += components; + } + } + + _mesa_format_to_type_and_comps(temp_format, &datatype, &comps); + + for (level = texObj->BaseLevel; level < maxLevel; level++) { + /* generate image[level+1] from image[level] */ + const struct gl_texture_image *srcImage; + struct gl_texture_image *dstImage; + GLint srcWidth, srcHeight, srcDepth; + GLint dstWidth, dstHeight, dstDepth; + GLint border; + GLboolean nextLevel; + + /* get src image parameters */ + srcImage = _mesa_select_tex_image(ctx, texObj, target, level); + ASSERT(srcImage); + srcWidth = srcImage->Width; + srcHeight = srcImage->Height; + srcDepth = srcImage->Depth; + border = srcImage->Border; + + nextLevel = next_mipmap_level_size(target, border, + srcWidth, srcHeight, srcDepth, + &dstWidth, &dstHeight, &dstDepth); + if (!nextLevel) + break; + + temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth); + if (!temp_dst) { + temp_dst = (GLubyte *) malloc(temp_dst_stride * dstHeight); + if (!temp_dst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + break; + } + } + + /* get dest gl_texture_image */ + dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); + if (!dstImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; + } + + _mesa_generate_mipmap_level(target, datatype, comps, border, + srcWidth, srcHeight, srcDepth, + temp_src, temp_src_stride / components, + dstWidth, dstHeight, dstDepth, + temp_dst, temp_dst_stride / components); + + /* initialize new image */ + _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, + dstDepth, border, srcImage->InternalFormat, + srcImage->TexFormat); + + ctx->Driver.TexImage2D(ctx, target, level + 1, + srcImage->InternalFormat, + dstWidth, dstHeight, border, + _mesa_get_format_base_format(temp_format), + GL_UNSIGNED_BYTE, + temp_dst, &ctx->DefaultPacking, texObj, dstImage); + + /* swap src and dest pointers */ + { + GLchan *temp = temp_src; + temp_src = temp_dst; + temp_dst = temp; + + temp_src_stride = temp_dst_stride; + } + } /* loop over mipmap levels */ + + free((void *) temp_src); + free(temp_dst); +} + +/** + * Automatic mipmap generation. + * This is the fallback/default function for ctx->Driver.GenerateMipmap(). + * Generate a complete set of mipmaps from texObj's BaseLevel image. + * Stop at texObj's MaxLevel or when we get to the 1x1 texture. + * For cube maps, target will be one of + * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP. + */ +void +_mesa_generate_mipmap(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj) +{ + const struct gl_texture_image *srcImage; + GLint maxLevel; + + ASSERT(texObj); + srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); + ASSERT(srcImage); + + maxLevel = _mesa_max_texture_levels(ctx, texObj->Target) - 1; + ASSERT(maxLevel >= 0); /* bad target */ + + maxLevel = MIN2(maxLevel, texObj->MaxLevel); + + if (_mesa_is_format_compressed(srcImage->TexFormat)) { + generate_mipmap_compressed(ctx, target, texObj, srcImage, maxLevel); + } else { + generate_mipmap_uncompressed(ctx, target, texObj, srcImage, maxLevel); + } +} + + +/** + * Helper function for drivers which need to rescale texture images to + * certain aspect ratios. + * Nearest filtering only (for broken hardware that can't support + * all aspect ratios). This can be made a lot faster, but I don't + * really care enough... + */ +void +_mesa_rescale_teximage2d(GLuint bytesPerPixel, + GLuint srcStrideInPixels, + GLuint dstRowStride, + GLint srcWidth, GLint srcHeight, + GLint dstWidth, GLint dstHeight, + const GLvoid *srcImage, GLvoid *dstImage) +{ + GLint row, col; + +#define INNER_LOOP( TYPE, HOP, WOP ) \ + for ( row = 0 ; row < dstHeight ; row++ ) { \ + GLint srcRow = row HOP hScale; \ + for ( col = 0 ; col < dstWidth ; col++ ) { \ + GLint srcCol = col WOP wScale; \ + dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ + } \ + dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ + } \ + +#define RESCALE_IMAGE( TYPE ) \ +do { \ + const TYPE *src = (const TYPE *)srcImage; \ + TYPE *dst = (TYPE *)dstImage; \ + \ + if ( srcHeight < dstHeight ) { \ + const GLint hScale = dstHeight / srcHeight; \ + if ( srcWidth < dstWidth ) { \ + const GLint wScale = dstWidth / srcWidth; \ + INNER_LOOP( TYPE, /, / ); \ + } \ + else { \ + const GLint wScale = srcWidth / dstWidth; \ + INNER_LOOP( TYPE, /, * ); \ + } \ + } \ + else { \ + const GLint hScale = srcHeight / dstHeight; \ + if ( srcWidth < dstWidth ) { \ + const GLint wScale = dstWidth / srcWidth; \ + INNER_LOOP( TYPE, *, / ); \ + } \ + else { \ + const GLint wScale = srcWidth / dstWidth; \ + INNER_LOOP( TYPE, *, * ); \ + } \ + } \ +} while (0) + + switch ( bytesPerPixel ) { + case 4: + RESCALE_IMAGE( GLuint ); + break; + + case 2: + RESCALE_IMAGE( GLushort ); + break; + + case 1: + RESCALE_IMAGE( GLubyte ); + break; + default: + _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d"); + } +} + + +/** + * Upscale an image by replication, not (typical) stretching. + * We use this when the image width or height is less than a + * certain size (4, 8) and we need to upscale an image. + */ +void +_mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight, + GLsizei outWidth, GLsizei outHeight, + GLint comps, const GLchan *src, GLint srcRowStride, + GLchan *dest ) +{ + GLint i, j, k; + + ASSERT(outWidth >= inWidth); + ASSERT(outHeight >= inHeight); +#if 0 + ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); + ASSERT((outWidth & 3) == 0); + ASSERT((outHeight & 3) == 0); +#endif + + for (i = 0; i < outHeight; i++) { + const GLint ii = i % inHeight; + for (j = 0; j < outWidth; j++) { + const GLint jj = j % inWidth; + for (k = 0; k < comps; k++) { + dest[(i * outWidth + j) * comps + k] + = src[ii * srcRowStride + jj * comps + k]; + } + } + } +} + diff --git a/mesalib/src/mesa/state_tracker/st_atom_blend.c b/mesalib/src/mesa/state_tracker/st_atom_blend.c index d1844e106..4c9a2b95a 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_blend.c +++ b/mesalib/src/mesa/state_tracker/st_atom_blend.c @@ -156,7 +156,7 @@ translate_logicop(GLenum logicop) * Figure out if colormasks are different per rt. */ static GLboolean -colormask_per_rt(struct gl_context *ctx) +colormask_per_rt(const struct gl_context *ctx) { /* a bit suboptimal have to compare lots of values */ unsigned i; @@ -172,7 +172,7 @@ colormask_per_rt(struct gl_context *ctx) * Figure out if blend enables/state are different per rt. */ static GLboolean -blend_per_rt(struct gl_context *ctx) +blend_per_rt(const struct gl_context *ctx) { if (ctx->Color.BlendEnabled && (ctx->Color.BlendEnabled != ((1 << ctx->Const.MaxDrawBuffers) - 1))) { @@ -190,13 +190,14 @@ static void update_blend( struct st_context *st ) { struct pipe_blend_state *blend = &st->state.blend; + const struct gl_context *ctx = st->ctx; unsigned num_state = 1; unsigned i, j; memset(blend, 0, sizeof(*blend)); - if (blend_per_rt(st->ctx) || colormask_per_rt(st->ctx)) { - num_state = st->ctx->Const.MaxDrawBuffers; + if (blend_per_rt(ctx) || colormask_per_rt(ctx)) { + num_state = ctx->Const.MaxDrawBuffers; blend->independent_blend_enable = 1; } /* Note it is impossible to correctly deal with EXT_blend_logic_op and @@ -205,52 +206,52 @@ update_blend( struct st_context *st ) and separate alpha/rgb logicop/blend support respectively. Neither possible in gallium nor most hardware. Assume these combinations don't happen. */ - if (st->ctx->Color.ColorLogicOpEnabled || - (st->ctx->Color.BlendEnabled && - st->ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) { + if (ctx->Color.ColorLogicOpEnabled || + (ctx->Color.BlendEnabled && + ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) { /* logicop enabled */ blend->logicop_enable = 1; - blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp); + blend->logicop_func = translate_logicop(ctx->Color.LogicOp); } - else if (st->ctx->Color.BlendEnabled) { + else if (ctx->Color.BlendEnabled) { /* blending enabled */ for (i = 0, j = 0; i < num_state; i++) { - blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1; + blend->rt[i].blend_enable = (ctx->Color.BlendEnabled >> i) & 0x1; - if (st->ctx->Extensions.ARB_draw_buffers_blend) + if (ctx->Extensions.ARB_draw_buffers_blend) j = i; blend->rt[i].rgb_func = - translate_blend(st->ctx->Color.Blend[j].EquationRGB); + translate_blend(ctx->Color.Blend[j].EquationRGB); - if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN || - st->ctx->Color.Blend[i].EquationRGB == GL_MAX) { + if (ctx->Color.Blend[i].EquationRGB == GL_MIN || + ctx->Color.Blend[i].EquationRGB == GL_MAX) { /* Min/max are special */ blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; } else { blend->rt[i].rgb_src_factor = - translate_blend(st->ctx->Color.Blend[j].SrcRGB); + translate_blend(ctx->Color.Blend[j].SrcRGB); blend->rt[i].rgb_dst_factor = - translate_blend(st->ctx->Color.Blend[j].DstRGB); + translate_blend(ctx->Color.Blend[j].DstRGB); } blend->rt[i].alpha_func = - translate_blend(st->ctx->Color.Blend[j].EquationA); + translate_blend(ctx->Color.Blend[j].EquationA); - if (st->ctx->Color.Blend[i].EquationA == GL_MIN || - st->ctx->Color.Blend[i].EquationA == GL_MAX) { + if (ctx->Color.Blend[i].EquationA == GL_MIN || + ctx->Color.Blend[i].EquationA == GL_MAX) { /* Min/max are special */ blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; } else { blend->rt[i].alpha_src_factor = - translate_blend(st->ctx->Color.Blend[j].SrcA); + translate_blend(ctx->Color.Blend[j].SrcA); blend->rt[i].alpha_dst_factor = - translate_blend(st->ctx->Color.Blend[j].DstA); + translate_blend(ctx->Color.Blend[j].DstA); } } } @@ -260,25 +261,25 @@ update_blend( struct st_context *st ) /* Colormask - maybe reverse these bits? */ for (i = 0; i < num_state; i++) { - if (st->ctx->Color.ColorMask[i][0]) + if (ctx->Color.ColorMask[i][0]) blend->rt[i].colormask |= PIPE_MASK_R; - if (st->ctx->Color.ColorMask[i][1]) + if (ctx->Color.ColorMask[i][1]) blend->rt[i].colormask |= PIPE_MASK_G; - if (st->ctx->Color.ColorMask[i][2]) + if (ctx->Color.ColorMask[i][2]) blend->rt[i].colormask |= PIPE_MASK_B; - if (st->ctx->Color.ColorMask[i][3]) + if (ctx->Color.ColorMask[i][3]) blend->rt[i].colormask |= PIPE_MASK_A; } - if (st->ctx->Color.DitherFlag) + if (ctx->Color.DitherFlag) blend->dither = 1; - if (st->ctx->Multisample.Enabled) { + if (ctx->Multisample.Enabled) { /* unlike in gallium/d3d10 these operations are only performed if msaa is enabled */ - if (st->ctx->Multisample.SampleAlphaToCoverage) + if (ctx->Multisample.SampleAlphaToCoverage) blend->alpha_to_coverage = 1; - if (st->ctx->Multisample.SampleAlphaToOne) + if (ctx->Multisample.SampleAlphaToOne) blend->alpha_to_one = 1; } @@ -286,7 +287,7 @@ update_blend( struct st_context *st ) { struct pipe_blend_color bc; - COPY_4FV(bc.color, st->ctx->Color.BlendColorUnclamped); + COPY_4FV(bc.color, ctx->Color.BlendColorUnclamped); cso_set_blend_color(st->cso_context, &bc); } } diff --git a/mesalib/src/mesa/state_tracker/st_atom_clip.c b/mesalib/src/mesa/state_tracker/st_atom_clip.c index 24d479a74..1330db843 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_clip.c +++ b/mesalib/src/mesa/state_tracker/st_atom_clip.c @@ -1,75 +1,76 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - /* - * Authors: - * Keith Whitwell - */ - - -#include "st_context.h" -#include "pipe/p_context.h" -#include "st_atom.h" - -#include "cso_cache/cso_context.h" - - -/* Second state atom for user clip planes: - */ -static void update_clip( struct st_context *st ) -{ - struct pipe_clip_state clip; - GLuint i; - - memset(&clip, 0, sizeof(clip)); - - for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) { - if (st->ctx->Transform.ClipPlanesEnabled & (1 << i)) { - memcpy(clip.ucp[clip.nr], - st->ctx->Transform._ClipUserPlane[i], - sizeof(clip.ucp[0])); - clip.nr++; - } - } - - clip.depth_clamp = st->ctx->Transform.DepthClamp != GL_FALSE; - - if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) { - st->state.clip = clip; - cso_set_clip(st->cso_context, &clip); - } -} - - -const struct st_tracked_state st_update_clip = { - "st_update_clip", /* name */ - { /* dirty */ - (_NEW_TRANSFORM), /* mesa */ - 0, /* st */ - }, - update_clip /* update */ -}; +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell + */ + + +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" + +#include "cso_cache/cso_context.h" + + +/* Second state atom for user clip planes: + */ +static void update_clip( struct st_context *st ) +{ + struct pipe_clip_state clip; + const struct gl_context *ctx = st->ctx; + GLuint i; + + memset(&clip, 0, sizeof(clip)); + + for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) { + if (ctx->Transform.ClipPlanesEnabled & (1 << i)) { + memcpy(clip.ucp[clip.nr], + ctx->Transform._ClipUserPlane[i], + sizeof(clip.ucp[0])); + clip.nr++; + } + } + + clip.depth_clamp = ctx->Transform.DepthClamp != GL_FALSE; + + if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) { + st->state.clip = clip; + cso_set_clip(st->cso_context, &clip); + } +} + + +const struct st_tracked_state st_update_clip = { + "st_update_clip", /* name */ + { /* dirty */ + (_NEW_TRANSFORM), /* mesa */ + 0, /* st */ + }, + update_clip /* update */ +}; diff --git a/mesalib/src/mesa/state_tracker/st_atom_sampler.c b/mesalib/src/mesa/state_tracker/st_atom_sampler.c index 627a13387..731338f9b 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_sampler.c +++ b/mesalib/src/mesa/state_tracker/st_atom_sampler.c @@ -1,271 +1,279 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - /* - * Authors: - * Keith Whitwell - * Brian Paul - */ - - -#include "main/macros.h" -#include "main/mtypes.h" -#include "main/samplerobj.h" - -#include "st_context.h" -#include "st_cb_texture.h" -#include "st_format.h" -#include "st_atom.h" -#include "st_texture.h" -#include "pipe/p_context.h" -#include "pipe/p_defines.h" - -#include "cso_cache/cso_context.h" - - -/** - * Convert GLenum texcoord wrap tokens to pipe tokens. - */ -static GLuint -gl_wrap_xlate(GLenum wrap) -{ - switch (wrap) { - case GL_REPEAT: - return PIPE_TEX_WRAP_REPEAT; - case GL_CLAMP: - return PIPE_TEX_WRAP_CLAMP; - case GL_CLAMP_TO_EDGE: - return PIPE_TEX_WRAP_CLAMP_TO_EDGE; - case GL_CLAMP_TO_BORDER: - return PIPE_TEX_WRAP_CLAMP_TO_BORDER; - case GL_MIRRORED_REPEAT: - return PIPE_TEX_WRAP_MIRROR_REPEAT; - case GL_MIRROR_CLAMP_EXT: - return PIPE_TEX_WRAP_MIRROR_CLAMP; - case GL_MIRROR_CLAMP_TO_EDGE_EXT: - return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; - case GL_MIRROR_CLAMP_TO_BORDER_EXT: - return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER; - default: - assert(0); - return 0; - } -} - - -static GLuint -gl_filter_to_mip_filter(GLenum filter) -{ - switch (filter) { - case GL_NEAREST: - case GL_LINEAR: - return PIPE_TEX_MIPFILTER_NONE; - - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - return PIPE_TEX_MIPFILTER_NEAREST; - - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return PIPE_TEX_MIPFILTER_LINEAR; - - default: - assert(0); - return PIPE_TEX_MIPFILTER_NONE; - } -} - - -static GLuint -gl_filter_to_img_filter(GLenum filter) -{ - switch (filter) { - case GL_NEAREST: - case GL_NEAREST_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - return PIPE_TEX_FILTER_NEAREST; - - case GL_LINEAR: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_LINEAR: - return PIPE_TEX_FILTER_LINEAR; - - default: - assert(0); - return PIPE_TEX_FILTER_NEAREST; - } -} - -static void convert_sampler(struct st_context *st, - struct pipe_sampler_state *sampler, - GLuint texUnit) -{ - struct gl_texture_object *texobj; - struct gl_sampler_object *msamp; - - texobj = st->ctx->Texture.Unit[texUnit]._Current; - if (!texobj) { - texobj = st_get_default_texture(st); - } - - msamp = _mesa_get_samplerobj(st->ctx, texUnit); - - memset(sampler, 0, sizeof(*sampler)); - sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); - sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); - sampler->wrap_r = gl_wrap_xlate(msamp->WrapR); - - sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter); - sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter); - sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter); - - if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) - sampler->normalized_coords = 1; - - sampler->lod_bias = st->ctx->Texture.Unit[texUnit].LodBias + - msamp->LodBias; - - sampler->min_lod = CLAMP(msamp->MinLod, - 0.0f, - (GLfloat) texobj->MaxLevel - texobj->BaseLevel); - sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel, - msamp->MaxLod); - if (sampler->max_lod < sampler->min_lod) { - /* The GL spec doesn't seem to specify what to do in this case. - * Swap the values. - */ - float tmp = sampler->max_lod; - sampler->max_lod = sampler->min_lod; - sampler->min_lod = tmp; - assert(sampler->min_lod <= sampler->max_lod); - } - - if (msamp->BorderColor.ui[0] || - msamp->BorderColor.ui[1] || - msamp->BorderColor.ui[2] || - msamp->BorderColor.ui[3]) { - struct gl_texture_image *teximg; - - teximg = texobj->Image[0][texobj->BaseLevel]; - - st_translate_color(msamp->BorderColor.f, - teximg ? teximg->_BaseFormat : GL_RGBA, - sampler->border_color); - } - - sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? - 0 : (GLuint) msamp->MaxAnisotropy); - - /* only care about ARB_shadow, not SGI shadow */ - if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { - sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; - sampler->compare_func - = st_compare_func_to_pipe(msamp->CompareFunc); - } - - sampler->seamless_cube_map = - st->ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless; -} - -static void -update_vertex_samplers(struct st_context *st) -{ - struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current; - GLuint su; - - st->state.num_vertex_samplers = 0; - - /* loop over sampler units (aka tex image units) */ - for (su = 0; su < st->ctx->Const.MaxVertexTextureImageUnits; su++) { - struct pipe_sampler_state *sampler = st->state.vertex_samplers + su; - - if (vprog->Base.SamplersUsed & (1 << su)) { - GLuint texUnit; - - texUnit = vprog->Base.SamplerUnits[su]; - - convert_sampler(st, sampler, texUnit); - - st->state.num_vertex_samplers = su + 1; - - cso_single_vertex_sampler(st->cso_context, su, sampler); - } else { - cso_single_vertex_sampler(st->cso_context, su, NULL); - } - } - cso_single_vertex_sampler_done(st->cso_context); -} - -static void -update_fragment_samplers(struct st_context *st) -{ - struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; - GLuint su; - - st->state.num_samplers = 0; - - /* loop over sampler units (aka tex image units) */ - for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { - struct pipe_sampler_state *sampler = st->state.samplers + su; - - - if (fprog->Base.SamplersUsed & (1 << su)) { - GLuint texUnit; - - texUnit = fprog->Base.SamplerUnits[su]; - - convert_sampler(st, sampler, texUnit); - - st->state.num_samplers = su + 1; - - /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/ - cso_single_sampler(st->cso_context, su, sampler); - } - else { - /*printf("%s su=%u null\n", __FUNCTION__, su);*/ - cso_single_sampler(st->cso_context, su, NULL); - } - } - - cso_single_sampler_done(st->cso_context); -} - -static void -update_samplers(struct st_context *st) -{ - update_fragment_samplers(st); - update_vertex_samplers(st); -} - -const struct st_tracked_state st_update_sampler = { - "st_update_sampler", /* name */ - { /* dirty */ - _NEW_TEXTURE, /* mesa */ - 0, /* st */ - }, - update_samplers /* update */ -}; +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell + * Brian Paul + */ + + +#include "main/macros.h" +#include "main/mtypes.h" +#include "main/samplerobj.h" + +#include "st_context.h" +#include "st_cb_texture.h" +#include "st_format.h" +#include "st_atom.h" +#include "st_texture.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + +#include "cso_cache/cso_context.h" + + +/** + * Convert GLenum texcoord wrap tokens to pipe tokens. + */ +static GLuint +gl_wrap_xlate(GLenum wrap) +{ + switch (wrap) { + case GL_REPEAT: + return PIPE_TEX_WRAP_REPEAT; + case GL_CLAMP: + return PIPE_TEX_WRAP_CLAMP; + case GL_CLAMP_TO_EDGE: + return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + case GL_CLAMP_TO_BORDER: + return PIPE_TEX_WRAP_CLAMP_TO_BORDER; + case GL_MIRRORED_REPEAT: + return PIPE_TEX_WRAP_MIRROR_REPEAT; + case GL_MIRROR_CLAMP_EXT: + return PIPE_TEX_WRAP_MIRROR_CLAMP; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + case GL_MIRROR_CLAMP_TO_BORDER_EXT: + return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER; + default: + assert(0); + return 0; + } +} + + +static GLuint +gl_filter_to_mip_filter(GLenum filter) +{ + switch (filter) { + case GL_NEAREST: + case GL_LINEAR: + return PIPE_TEX_MIPFILTER_NONE; + + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + return PIPE_TEX_MIPFILTER_NEAREST; + + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return PIPE_TEX_MIPFILTER_LINEAR; + + default: + assert(0); + return PIPE_TEX_MIPFILTER_NONE; + } +} + + +static GLuint +gl_filter_to_img_filter(GLenum filter) +{ + switch (filter) { + case GL_NEAREST: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + return PIPE_TEX_FILTER_NEAREST; + + case GL_LINEAR: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_LINEAR: + return PIPE_TEX_FILTER_LINEAR; + + default: + assert(0); + return PIPE_TEX_FILTER_NEAREST; + } +} + + +static void +convert_sampler(struct st_context *st, + struct pipe_sampler_state *sampler, + GLuint texUnit) +{ + struct gl_texture_object *texobj; + struct gl_context *ctx = st->ctx; + struct gl_sampler_object *msamp; + + texobj = ctx->Texture.Unit[texUnit]._Current; + if (!texobj) { + texobj = st_get_default_texture(st); + } + + msamp = _mesa_get_samplerobj(ctx, texUnit); + + memset(sampler, 0, sizeof(*sampler)); + sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); + sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); + sampler->wrap_r = gl_wrap_xlate(msamp->WrapR); + + sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter); + sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter); + sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter); + + if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) + sampler->normalized_coords = 1; + + sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias; + + sampler->min_lod = CLAMP(msamp->MinLod, + 0.0f, + (GLfloat) texobj->MaxLevel - texobj->BaseLevel); + sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel, + msamp->MaxLod); + if (sampler->max_lod < sampler->min_lod) { + /* The GL spec doesn't seem to specify what to do in this case. + * Swap the values. + */ + float tmp = sampler->max_lod; + sampler->max_lod = sampler->min_lod; + sampler->min_lod = tmp; + assert(sampler->min_lod <= sampler->max_lod); + } + + if (msamp->BorderColor.ui[0] || + msamp->BorderColor.ui[1] || + msamp->BorderColor.ui[2] || + msamp->BorderColor.ui[3]) { + struct gl_texture_image *teximg; + + teximg = texobj->Image[0][texobj->BaseLevel]; + + st_translate_color(msamp->BorderColor.f, + teximg ? teximg->_BaseFormat : GL_RGBA, + sampler->border_color); + } + + sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? + 0 : (GLuint) msamp->MaxAnisotropy); + + /* only care about ARB_shadow, not SGI shadow */ + if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { + sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; + sampler->compare_func + = st_compare_func_to_pipe(msamp->CompareFunc); + } + + sampler->seamless_cube_map = + ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless; +} + + +static void +update_vertex_samplers(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + struct gl_vertex_program *vprog = ctx->VertexProgram._Current; + GLuint su; + + st->state.num_vertex_samplers = 0; + + /* loop over sampler units (aka tex image units) */ + for (su = 0; su < ctx->Const.MaxVertexTextureImageUnits; su++) { + struct pipe_sampler_state *sampler = st->state.vertex_samplers + su; + + if (vprog->Base.SamplersUsed & (1 << su)) { + GLuint texUnit; + + texUnit = vprog->Base.SamplerUnits[su]; + + convert_sampler(st, sampler, texUnit); + + st->state.num_vertex_samplers = su + 1; + + cso_single_vertex_sampler(st->cso_context, su, sampler); + } else { + cso_single_vertex_sampler(st->cso_context, su, NULL); + } + } + cso_single_vertex_sampler_done(st->cso_context); +} + + +static void +update_fragment_samplers(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; + GLuint su; + + st->state.num_samplers = 0; + + /* loop over sampler units (aka tex image units) */ + for (su = 0; su < ctx->Const.MaxTextureImageUnits; su++) { + struct pipe_sampler_state *sampler = st->state.samplers + su; + + + if (fprog->Base.SamplersUsed & (1 << su)) { + GLuint texUnit; + + texUnit = fprog->Base.SamplerUnits[su]; + + convert_sampler(st, sampler, texUnit); + + st->state.num_samplers = su + 1; + + /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/ + cso_single_sampler(st->cso_context, su, sampler); + } + else { + /*printf("%s su=%u null\n", __FUNCTION__, su);*/ + cso_single_sampler(st->cso_context, su, NULL); + } + } + + cso_single_sampler_done(st->cso_context); +} + + +static void +update_samplers(struct st_context *st) +{ + update_fragment_samplers(st); + update_vertex_samplers(st); +} + + +const struct st_tracked_state st_update_sampler = { + "st_update_sampler", /* name */ + { /* dirty */ + _NEW_TEXTURE, /* mesa */ + 0, /* st */ + }, + update_samplers /* update */ +}; diff --git a/mesalib/src/mesa/state_tracker/st_atom_scissor.c b/mesalib/src/mesa/state_tracker/st_atom_scissor.c index 495a3ea25..eb1387778 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_scissor.c +++ b/mesalib/src/mesa/state_tracker/st_atom_scissor.c @@ -1,100 +1,101 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - /* - * Authors: - * Keith Whitwell - */ - - -#include "main/macros.h" -#include "st_context.h" -#include "pipe/p_context.h" -#include "st_atom.h" - - -/** - * Scissor depends on the scissor box, and the framebuffer dimensions. - */ -static void -update_scissor( struct st_context *st ) -{ - struct pipe_scissor_state scissor; - const struct gl_framebuffer *fb = st->ctx->DrawBuffer; - GLint miny, maxy; - - scissor.minx = 0; - scissor.miny = 0; - scissor.maxx = fb->Width; - scissor.maxy = fb->Height; - - if (st->ctx->Scissor.Enabled) { - /* need to be careful here with xmax or ymax < 0 */ - GLint xmax = MAX2(0, st->ctx->Scissor.X + st->ctx->Scissor.Width); - GLint ymax = MAX2(0, st->ctx->Scissor.Y + st->ctx->Scissor.Height); - - if (st->ctx->Scissor.X > (GLint)scissor.minx) - scissor.minx = st->ctx->Scissor.X; - if (st->ctx->Scissor.Y > (GLint)scissor.miny) - scissor.miny = st->ctx->Scissor.Y; - - if (xmax < (GLint) scissor.maxx) - scissor.maxx = xmax; - if (ymax < (GLint) scissor.maxy) - scissor.maxy = ymax; - - /* check for null space */ - if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy) - scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0; - } - - /* Now invert Y if needed. - * Gallium drivers use the convention Y=0=top for surfaces. - */ - if (st_fb_orientation(fb) == Y_0_TOP) { - miny = fb->Height - scissor.maxy; - maxy = fb->Height - scissor.miny; - scissor.miny = miny; - scissor.maxy = maxy; - } - - if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) { - /* state has changed */ - st->state.scissor = scissor; /* struct copy */ - st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */ - } -} - - -const struct st_tracked_state st_update_scissor = { - "st_update_scissor", /* name */ - { /* dirty */ - (_NEW_SCISSOR | _NEW_BUFFERS), /* mesa */ - 0, /* st */ - }, - update_scissor /* update */ -}; +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell + */ + + +#include "main/macros.h" +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" + + +/** + * Scissor depends on the scissor box, and the framebuffer dimensions. + */ +static void +update_scissor( struct st_context *st ) +{ + struct pipe_scissor_state scissor; + const struct gl_context *ctx = st->ctx; + const struct gl_framebuffer *fb = ctx->DrawBuffer; + GLint miny, maxy; + + scissor.minx = 0; + scissor.miny = 0; + scissor.maxx = fb->Width; + scissor.maxy = fb->Height; + + if (ctx->Scissor.Enabled) { + /* need to be careful here with xmax or ymax < 0 */ + GLint xmax = MAX2(0, ctx->Scissor.X + ctx->Scissor.Width); + GLint ymax = MAX2(0, ctx->Scissor.Y + ctx->Scissor.Height); + + if (ctx->Scissor.X > (GLint)scissor.minx) + scissor.minx = ctx->Scissor.X; + if (ctx->Scissor.Y > (GLint)scissor.miny) + scissor.miny = ctx->Scissor.Y; + + if (xmax < (GLint) scissor.maxx) + scissor.maxx = xmax; + if (ymax < (GLint) scissor.maxy) + scissor.maxy = ymax; + + /* check for null space */ + if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy) + scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0; + } + + /* Now invert Y if needed. + * Gallium drivers use the convention Y=0=top for surfaces. + */ + if (st_fb_orientation(fb) == Y_0_TOP) { + miny = fb->Height - scissor.maxy; + maxy = fb->Height - scissor.miny; + scissor.miny = miny; + scissor.maxy = maxy; + } + + if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) { + /* state has changed */ + st->state.scissor = scissor; /* struct copy */ + st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */ + } +} + + +const struct st_tracked_state st_update_scissor = { + "st_update_scissor", /* name */ + { /* dirty */ + (_NEW_SCISSOR | _NEW_BUFFERS), /* mesa */ + 0, /* st */ + }, + update_scissor /* update */ +}; diff --git a/mesalib/src/mesa/state_tracker/st_atom_stipple.c b/mesalib/src/mesa/state_tracker/st_atom_stipple.c index 5efea315c..b3e0dc7f1 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_stipple.c +++ b/mesalib/src/mesa/state_tracker/st_atom_stipple.c @@ -1,93 +1,94 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - /* - * \brief polygon stipple state - * - * Authors: - * Brian Paul - */ - - -#include - -#include "st_context.h" -#include "st_atom.h" -#include "pipe/p_context.h" -#include "pipe/p_defines.h" - - -/** - * OpenGL's polygon stipple is indexed with window coordinates in which - * the origin (0,0) is the lower-left corner of the window. - * With Gallium, the origin is the upper-left corner of the window. - * To convert GL's polygon stipple to what gallium expects we need to - * invert the pattern vertically and rotate the stipple rows according - * to the window height. - */ -static void -invert_stipple(GLuint dest[32], const GLuint src[32], GLuint winHeight) -{ - GLuint i; - - for (i = 0; i < 32; i++) { - dest[i] = src[(winHeight - 1 - i) & 0x1f]; - } -} - - - -static void -update_stipple( struct st_context *st ) -{ - const GLuint sz = sizeof(st->state.poly_stipple); - assert(sz == sizeof(st->ctx->PolygonStipple)); - - if (memcmp(st->state.poly_stipple, st->ctx->PolygonStipple, sz)) { - /* state has changed */ - struct pipe_poly_stipple newStipple; - - memcpy(st->state.poly_stipple, st->ctx->PolygonStipple, sz); - - invert_stipple(newStipple.stipple, st->ctx->PolygonStipple, - st->ctx->DrawBuffer->Height); - - st->pipe->set_polygon_stipple(st->pipe, &newStipple); - } -} - - -/** Update the stipple when the pattern or window height changes */ -const struct st_tracked_state st_update_polygon_stipple = { - "st_update_polygon_stipple", /* name */ - { /* dirty */ - (_NEW_POLYGONSTIPPLE | - _NEW_BUFFERS), /* mesa */ - 0, /* st */ - }, - update_stipple /* update */ -}; +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * \brief polygon stipple state + * + * Authors: + * Brian Paul + */ + + +#include + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + + +/** + * OpenGL's polygon stipple is indexed with window coordinates in which + * the origin (0,0) is the lower-left corner of the window. + * With Gallium, the origin is the upper-left corner of the window. + * To convert GL's polygon stipple to what gallium expects we need to + * invert the pattern vertically and rotate the stipple rows according + * to the window height. + */ +static void +invert_stipple(GLuint dest[32], const GLuint src[32], GLuint winHeight) +{ + GLuint i; + + for (i = 0; i < 32; i++) { + dest[i] = src[(winHeight - 1 - i) & 0x1f]; + } +} + + + +static void +update_stipple( struct st_context *st ) +{ + const struct gl_context *ctx = st->ctx; + const GLuint sz = sizeof(st->state.poly_stipple); + assert(sz == sizeof(ctx->PolygonStipple)); + + if (memcmp(st->state.poly_stipple, ctx->PolygonStipple, sz)) { + /* state has changed */ + struct pipe_poly_stipple newStipple; + + memcpy(st->state.poly_stipple, ctx->PolygonStipple, sz); + + invert_stipple(newStipple.stipple, ctx->PolygonStipple, + ctx->DrawBuffer->Height); + + st->pipe->set_polygon_stipple(st->pipe, &newStipple); + } +} + + +/** Update the stipple when the pattern or window height changes */ +const struct st_tracked_state st_update_polygon_stipple = { + "st_update_polygon_stipple", /* name */ + { /* dirty */ + (_NEW_POLYGONSTIPPLE | + _NEW_BUFFERS), /* mesa */ + 0, /* st */ + }, + update_stipple /* update */ +}; diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c index 7bb950a76..800a9f1f0 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_texture.c +++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c @@ -1,379 +1,383 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - /* - * Authors: - * Keith Whitwell - * Brian Paul - */ - - -#include "main/macros.h" -#include "main/mtypes.h" -#include "main/samplerobj.h" -#include "program/prog_instruction.h" - -#include "st_context.h" -#include "st_atom.h" -#include "st_texture.h" -#include "st_format.h" -#include "st_cb_texture.h" -#include "pipe/p_context.h" -#include "util/u_format.h" -#include "util/u_inlines.h" -#include "cso_cache/cso_context.h" - - -/** - * Combine depth texture mode with "swizzle" so that depth mode swizzling - * takes place before texture swizzling, and return the resulting swizzle. - * If the format is not a depth format, return "swizzle" unchanged. - * - * \param format PIPE_FORMAT_*. - * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. - * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED. - */ -static GLuint -apply_depthmode(enum pipe_format format, GLuint swizzle, GLenum depthmode) -{ - const struct util_format_description *desc = - util_format_description(format); - unsigned char swiz[4]; - unsigned i; - - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS || - desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) { - /* Not a depth format. */ - return swizzle; - } - - for (i = 0; i < 4; i++) - swiz[i] = GET_SWZ(swizzle, i); - - switch (depthmode) { - case GL_LUMINANCE: - /* Rewrite reads from W to ONE, and reads from XYZ to XXX. */ - for (i = 0; i < 4; i++) - if (swiz[i] == SWIZZLE_W) - swiz[i] = SWIZZLE_ONE; - else if (swiz[i] < SWIZZLE_W) - swiz[i] = SWIZZLE_X; - break; - - case GL_INTENSITY: - /* Rewrite reads from XYZW to XXXX. */ - for (i = 0; i < 4; i++) - if (swiz[i] <= SWIZZLE_W) - swiz[i] = SWIZZLE_X; - break; - - case GL_ALPHA: - /* Rewrite reads from W to X, and reads from XYZ to 000. */ - for (i = 0; i < 4; i++) - if (swiz[i] == SWIZZLE_W) - swiz[i] = SWIZZLE_X; - else if (swiz[i] < SWIZZLE_W) - swiz[i] = SWIZZLE_ZERO; - break; - case GL_RED: - /* Rewrite reads W to 1, XYZ to X00 */ - for (i = 0; i < 4; i++) - if (swiz[i] == SWIZZLE_W) - swiz[i] = SWIZZLE_ONE; - else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z) - swiz[i] = SWIZZLE_ZERO; - break; - } - - return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); -} - - -/** - * Return TRUE if the swizzling described by "swizzle" and - * "depthmode" (for depth textures only) is different from the swizzling - * set in the given sampler view. - * - * \param sv A sampler view. - * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. - * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA. - */ -static boolean -check_sampler_swizzle(struct pipe_sampler_view *sv, - GLuint swizzle, GLenum depthmode) -{ - swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode); - - if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || - (sv->swizzle_g != GET_SWZ(swizzle, 1)) || - (sv->swizzle_b != GET_SWZ(swizzle, 2)) || - (sv->swizzle_a != GET_SWZ(swizzle, 3))) - return TRUE; - return FALSE; -} - - -static INLINE struct pipe_sampler_view * -st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, - struct st_texture_object *stObj, - const struct gl_sampler_object *samp, - enum pipe_format format) -{ - struct pipe_sampler_view templ; - GLuint swizzle = apply_depthmode(stObj->pt->format, - stObj->base._Swizzle, - samp->DepthMode); - - u_sampler_view_default_template(&templ, - stObj->pt, - format); - templ.u.tex.first_level = stObj->base.BaseLevel; - - if (swizzle != SWIZZLE_NOOP) { - templ.swizzle_r = GET_SWZ(swizzle, 0); - templ.swizzle_g = GET_SWZ(swizzle, 1); - templ.swizzle_b = GET_SWZ(swizzle, 2); - templ.swizzle_a = GET_SWZ(swizzle, 3); - } - - return pipe->create_sampler_view(pipe, stObj->pt, &templ); -} - - -static INLINE struct pipe_sampler_view * -st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj, - struct pipe_context *pipe, - const struct gl_sampler_object *samp, - enum pipe_format format) -{ - if (!stObj || !stObj->pt) { - return NULL; - } - - if (!stObj->sampler_view) { - stObj->sampler_view = - st_create_texture_sampler_view_from_stobj(pipe, stObj, samp, format); - } - - return stObj->sampler_view; -} - -static GLboolean -update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, - GLuint texUnit) -{ - struct pipe_context *pipe = st->pipe; - const struct gl_sampler_object *samp; - struct gl_texture_object *texObj; - struct st_texture_object *stObj; - enum pipe_format st_view_format; - GLboolean retval; - - samp = _mesa_get_samplerobj(st->ctx, texUnit); - - texObj = st->ctx->Texture.Unit[texUnit]._Current; - - if (!texObj) { - texObj = st_get_default_texture(st); - samp = &texObj->Sampler; - } - stObj = st_texture_object(texObj); - - retval = st_finalize_texture(st->ctx, st->pipe, texObj); - if (!retval) { - /* out of mem */ - return GL_FALSE; - } - - /* Determine the format of the texture sampler view */ - st_view_format = stObj->pt->format; - { - const struct st_texture_image *firstImage = - st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); - const gl_format texFormat = firstImage->base.TexFormat; - enum pipe_format firstImageFormat = - st_mesa_format_to_pipe_format(texFormat); - - if ((samp->sRGBDecode == GL_SKIP_DECODE_EXT) && - (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) { - /* don't do sRGB->RGB conversion. Interpret the texture - * texture data as linear values. - */ - const gl_format linearFormat = - _mesa_get_srgb_format_linear(texFormat); - firstImageFormat = st_mesa_format_to_pipe_format(linearFormat); - } - - if (firstImageFormat != stObj->pt->format) - st_view_format = firstImageFormat; - } - - - /* if sampler view has changed dereference it */ - if (stObj->sampler_view) { - if (check_sampler_swizzle(stObj->sampler_view, - stObj->base._Swizzle, - samp->DepthMode) || - (st_view_format != stObj->sampler_view->format) || - stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) { - pipe_sampler_view_reference(&stObj->sampler_view, NULL); - } - } - - *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, - samp, - st_view_format); - return GL_TRUE; -} - -static void -update_vertex_textures(struct st_context *st) -{ - struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current; - GLuint su; - - st->state.num_vertex_textures = 0; - - /* loop over sampler units (aka tex image units) */ - for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { - struct pipe_sampler_view *sampler_view = NULL; - if (vprog->Base.SamplersUsed & (1 << su)) { - GLboolean retval; - GLuint texUnit; - - texUnit = vprog->Base.SamplerUnits[su]; - - retval = update_single_texture(st, &sampler_view, texUnit); - if (retval == GL_FALSE) - continue; - - st->state.num_vertex_textures = su + 1; - - } - pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], sampler_view); - } - - if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { - GLuint numUnits = MIN2(st->state.num_vertex_textures, - st->ctx->Const.MaxVertexTextureImageUnits); - cso_set_vertex_sampler_views(st->cso_context, - numUnits, - st->state.sampler_vertex_views); - } -} - -static void -update_fragment_textures(struct st_context *st) -{ - struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; - GLuint su; - - st->state.num_textures = 0; - - /* loop over sampler units (aka tex image units) */ - for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { - struct pipe_sampler_view *sampler_view = NULL; - if (fprog->Base.SamplersUsed & (1 << su)) { - GLboolean retval; - GLuint texUnit; - - texUnit = fprog->Base.SamplerUnits[su]; - - retval = update_single_texture(st, &sampler_view, texUnit); - if (retval == GL_FALSE) - continue; - - st->state.num_textures = su + 1; - } - pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); - } - - cso_set_fragment_sampler_views(st->cso_context, - st->state.num_textures, - st->state.sampler_views); -} - -const struct st_tracked_state st_update_texture = { - "st_update_texture", /* name */ - { /* dirty */ - _NEW_TEXTURE, /* mesa */ - ST_NEW_FRAGMENT_PROGRAM, /* st */ - }, - update_fragment_textures /* update */ -}; - -const struct st_tracked_state st_update_vertex_texture = { - "st_update_vertex_texture", /* name */ - { /* dirty */ - _NEW_TEXTURE, /* mesa */ - ST_NEW_VERTEX_PROGRAM, /* st */ - }, - update_vertex_textures /* update */ -}; - -static void -finalize_textures(struct st_context *st) -{ - struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; - const GLboolean prev_missing_textures = st->missing_textures; - GLuint su; - - st->missing_textures = GL_FALSE; - - for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) { - if (fprog->Base.SamplersUsed & (1 << su)) { - const GLuint texUnit = fprog->Base.SamplerUnits[su]; - struct gl_texture_object *texObj - = st->ctx->Texture.Unit[texUnit]._Current; - - if (texObj) { - GLboolean retval; - - retval = st_finalize_texture(st->ctx, st->pipe, texObj); - if (!retval) { - /* out of mem */ - st->missing_textures = GL_TRUE; - continue; - } - } - } - } - - if (prev_missing_textures != st->missing_textures) - st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; -} - - - -const struct st_tracked_state st_finalize_textures = { - "st_finalize_textures", /* name */ - { /* dirty */ - _NEW_TEXTURE, /* mesa */ - 0, /* st */ - }, - finalize_textures /* update */ -}; +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell + * Brian Paul + */ + + +#include "main/macros.h" +#include "main/mtypes.h" +#include "main/samplerobj.h" +#include "program/prog_instruction.h" + +#include "st_context.h" +#include "st_atom.h" +#include "st_texture.h" +#include "st_format.h" +#include "st_cb_texture.h" +#include "pipe/p_context.h" +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "cso_cache/cso_context.h" + + +/** + * Combine depth texture mode with "swizzle" so that depth mode swizzling + * takes place before texture swizzling, and return the resulting swizzle. + * If the format is not a depth format, return "swizzle" unchanged. + * + * \param format PIPE_FORMAT_*. + * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. + * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED. + */ +static GLuint +apply_depthmode(enum pipe_format format, GLuint swizzle, GLenum depthmode) +{ + const struct util_format_description *desc = + util_format_description(format); + unsigned char swiz[4]; + unsigned i; + + if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS || + desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) { + /* Not a depth format. */ + return swizzle; + } + + for (i = 0; i < 4; i++) + swiz[i] = GET_SWZ(swizzle, i); + + switch (depthmode) { + case GL_LUMINANCE: + /* Rewrite reads from W to ONE, and reads from XYZ to XXX. */ + for (i = 0; i < 4; i++) + if (swiz[i] == SWIZZLE_W) + swiz[i] = SWIZZLE_ONE; + else if (swiz[i] < SWIZZLE_W) + swiz[i] = SWIZZLE_X; + break; + + case GL_INTENSITY: + /* Rewrite reads from XYZW to XXXX. */ + for (i = 0; i < 4; i++) + if (swiz[i] <= SWIZZLE_W) + swiz[i] = SWIZZLE_X; + break; + + case GL_ALPHA: + /* Rewrite reads from W to X, and reads from XYZ to 000. */ + for (i = 0; i < 4; i++) + if (swiz[i] == SWIZZLE_W) + swiz[i] = SWIZZLE_X; + else if (swiz[i] < SWIZZLE_W) + swiz[i] = SWIZZLE_ZERO; + break; + case GL_RED: + /* Rewrite reads W to 1, XYZ to X00 */ + for (i = 0; i < 4; i++) + if (swiz[i] == SWIZZLE_W) + swiz[i] = SWIZZLE_ONE; + else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z) + swiz[i] = SWIZZLE_ZERO; + break; + } + + return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); +} + + +/** + * Return TRUE if the swizzling described by "swizzle" and + * "depthmode" (for depth textures only) is different from the swizzling + * set in the given sampler view. + * + * \param sv A sampler view. + * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. + * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA. + */ +static boolean +check_sampler_swizzle(struct pipe_sampler_view *sv, + GLuint swizzle, GLenum depthmode) +{ + swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode); + + if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || + (sv->swizzle_g != GET_SWZ(swizzle, 1)) || + (sv->swizzle_b != GET_SWZ(swizzle, 2)) || + (sv->swizzle_a != GET_SWZ(swizzle, 3))) + return TRUE; + return FALSE; +} + + +static INLINE struct pipe_sampler_view * +st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, + struct st_texture_object *stObj, + const struct gl_sampler_object *samp, + enum pipe_format format) +{ + struct pipe_sampler_view templ; + GLuint swizzle = apply_depthmode(stObj->pt->format, + stObj->base._Swizzle, + samp->DepthMode); + + u_sampler_view_default_template(&templ, + stObj->pt, + format); + templ.u.tex.first_level = stObj->base.BaseLevel; + + if (swizzle != SWIZZLE_NOOP) { + templ.swizzle_r = GET_SWZ(swizzle, 0); + templ.swizzle_g = GET_SWZ(swizzle, 1); + templ.swizzle_b = GET_SWZ(swizzle, 2); + templ.swizzle_a = GET_SWZ(swizzle, 3); + } + + return pipe->create_sampler_view(pipe, stObj->pt, &templ); +} + + +static INLINE struct pipe_sampler_view * +st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj, + struct pipe_context *pipe, + const struct gl_sampler_object *samp, + enum pipe_format format) +{ + if (!stObj || !stObj->pt) { + return NULL; + } + + if (!stObj->sampler_view) { + stObj->sampler_view = + st_create_texture_sampler_view_from_stobj(pipe, stObj, samp, format); + } + + return stObj->sampler_view; +} + +static GLboolean +update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, + GLuint texUnit) +{ + struct pipe_context *pipe = st->pipe; + struct gl_context *ctx = st->ctx; + const struct gl_sampler_object *samp; + struct gl_texture_object *texObj; + struct st_texture_object *stObj; + enum pipe_format st_view_format; + GLboolean retval; + + samp = _mesa_get_samplerobj(ctx, texUnit); + + texObj = ctx->Texture.Unit[texUnit]._Current; + + if (!texObj) { + texObj = st_get_default_texture(st); + samp = &texObj->Sampler; + } + stObj = st_texture_object(texObj); + + retval = st_finalize_texture(ctx, st->pipe, texObj); + if (!retval) { + /* out of mem */ + return GL_FALSE; + } + + /* Determine the format of the texture sampler view */ + st_view_format = stObj->pt->format; + { + const struct st_texture_image *firstImage = + st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); + const gl_format texFormat = firstImage->base.TexFormat; + enum pipe_format firstImageFormat = + st_mesa_format_to_pipe_format(texFormat); + + if ((samp->sRGBDecode == GL_SKIP_DECODE_EXT) && + (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) { + /* don't do sRGB->RGB conversion. Interpret the texture + * texture data as linear values. + */ + const gl_format linearFormat = + _mesa_get_srgb_format_linear(texFormat); + firstImageFormat = st_mesa_format_to_pipe_format(linearFormat); + } + + if (firstImageFormat != stObj->pt->format) + st_view_format = firstImageFormat; + } + + + /* if sampler view has changed dereference it */ + if (stObj->sampler_view) { + if (check_sampler_swizzle(stObj->sampler_view, + stObj->base._Swizzle, + samp->DepthMode) || + (st_view_format != stObj->sampler_view->format) || + stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) { + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + } + } + + *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, + samp, + st_view_format); + return GL_TRUE; +} + +static void +update_vertex_textures(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + struct gl_vertex_program *vprog = ctx->VertexProgram._Current; + GLuint su; + + st->state.num_vertex_textures = 0; + + /* loop over sampler units (aka tex image units) */ + for (su = 0; su < ctx->Const.MaxTextureImageUnits; su++) { + struct pipe_sampler_view *sampler_view = NULL; + if (vprog->Base.SamplersUsed & (1 << su)) { + GLboolean retval; + GLuint texUnit; + + texUnit = vprog->Base.SamplerUnits[su]; + + retval = update_single_texture(st, &sampler_view, texUnit); + if (retval == GL_FALSE) + continue; + + st->state.num_vertex_textures = su + 1; + + } + pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], sampler_view); + } + + if (ctx->Const.MaxVertexTextureImageUnits > 0) { + GLuint numUnits = MIN2(st->state.num_vertex_textures, + ctx->Const.MaxVertexTextureImageUnits); + cso_set_vertex_sampler_views(st->cso_context, + numUnits, + st->state.sampler_vertex_views); + } +} + +static void +update_fragment_textures(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; + GLuint su; + + st->state.num_textures = 0; + + /* loop over sampler units (aka tex image units) */ + for (su = 0; su < ctx->Const.MaxTextureImageUnits; su++) { + struct pipe_sampler_view *sampler_view = NULL; + if (fprog->Base.SamplersUsed & (1 << su)) { + GLboolean retval; + GLuint texUnit; + + texUnit = fprog->Base.SamplerUnits[su]; + + retval = update_single_texture(st, &sampler_view, texUnit); + if (retval == GL_FALSE) + continue; + + st->state.num_textures = su + 1; + } + pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); + } + + cso_set_fragment_sampler_views(st->cso_context, + st->state.num_textures, + st->state.sampler_views); +} + +const struct st_tracked_state st_update_texture = { + "st_update_texture", /* name */ + { /* dirty */ + _NEW_TEXTURE, /* mesa */ + ST_NEW_FRAGMENT_PROGRAM, /* st */ + }, + update_fragment_textures /* update */ +}; + +const struct st_tracked_state st_update_vertex_texture = { + "st_update_vertex_texture", /* name */ + { /* dirty */ + _NEW_TEXTURE, /* mesa */ + ST_NEW_VERTEX_PROGRAM, /* st */ + }, + update_vertex_textures /* update */ +}; + +static void +finalize_textures(struct st_context *st) +{ + struct gl_context *ctx = st->ctx; + struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; + const GLboolean prev_missing_textures = st->missing_textures; + GLuint su; + + st->missing_textures = GL_FALSE; + + for (su = 0; su < ctx->Const.MaxTextureCoordUnits; su++) { + if (fprog->Base.SamplersUsed & (1 << su)) { + const GLuint texUnit = fprog->Base.SamplerUnits[su]; + struct gl_texture_object *texObj + = ctx->Texture.Unit[texUnit]._Current; + + if (texObj) { + GLboolean retval; + + retval = st_finalize_texture(ctx, st->pipe, texObj); + if (!retval) { + /* out of mem */ + st->missing_textures = GL_TRUE; + continue; + } + } + } + } + + if (prev_missing_textures != st->missing_textures) + st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; +} + + + +const struct st_tracked_state st_finalize_textures = { + "st_finalize_textures", /* name */ + { /* dirty */ + _NEW_TEXTURE, /* mesa */ + 0, /* st */ + }, + finalize_textures /* update */ +}; diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index dd26db2f6..fac0ab7a1 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -33,7 +33,7 @@ * * We basically convert the VBO's vertex attribute/array information into * Gallium vertex state, bind the vertex buffer objects and call - * pipe->draw_elements(), pipe->draw_range_elements() or pipe->draw_arrays(). + * pipe->draw_vbo(). * * Authors: * Keith Whitwell @@ -237,7 +237,6 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, /** * Examine the active arrays to determine if we have interleaved * vertex arrays all living in one VBO, or all living in user space. - * \param userSpace returns whether the arrays are in user space. */ static GLboolean is_interleaved_arrays(const struct st_vertex_program *vp, @@ -247,8 +246,8 @@ is_interleaved_arrays(const struct st_vertex_program *vp, GLuint attr; const struct gl_buffer_object *firstBufObj = NULL; GLint firstStride = -1; - const GLubyte *client_addr = NULL; - GLboolean user_memory = GL_FALSE; + const GLubyte *firstPtr = NULL; + GLboolean userSpaceBuffer = GL_FALSE; for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; @@ -256,37 +255,26 @@ is_interleaved_arrays(const struct st_vertex_program *vp, const struct gl_buffer_object *bufObj = array->BufferObj; const GLsizei stride = array->StrideB; /* in bytes */ - if (firstStride < 0) { + if (attr == 0) { + /* save info about the first array */ firstStride = stride; - user_memory = !bufObj || !bufObj->Name; - } - else if (firstStride != stride) { - return GL_FALSE; - } - - if (!bufObj || !bufObj->Name) { - /* Try to detect if the client-space arrays are - * "close" to each other. - */ - if (!user_memory) { - return GL_FALSE; - } - if (!client_addr) { - client_addr = array->Ptr; - } - else if (abs(array->Ptr - client_addr) > firstStride) { - /* arrays start too far apart */ - return GL_FALSE; - } - } - else if (!firstBufObj) { - if (user_memory) { - return GL_FALSE; - } + firstPtr = array->Ptr; firstBufObj = bufObj; + userSpaceBuffer = !bufObj || !bufObj->Name; } - else if (bufObj != firstBufObj) { - return GL_FALSE; + else { + /* check if other arrays interleave with the first, in same buffer */ + if (stride != firstStride) + return GL_FALSE; /* strides don't match */ + + if (bufObj != firstBufObj) + return GL_FALSE; /* arrays in different VBOs */ + + if (abs(array->Ptr - firstPtr) > firstStride) + return GL_FALSE; /* arrays start too far apart */ + + if ((!bufObj || !_mesa_is_bufferobj(bufObj)) != userSpaceBuffer) + return GL_FALSE; /* mix of VBO and user-space arrays */ } } @@ -510,6 +498,7 @@ setup_index_buffer(struct gl_context *ctx, } } + /** * Prior to drawing, check that any uniforms referenced by the * current shader have been set. If a uniform has not been set, @@ -556,8 +545,8 @@ translate_prim(const struct gl_context *ctx, unsigned prim) assert(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); /* Avoid quadstrips if it's easy to do so: - * Note: it's imporant to do the correct trimming if we change the prim type! - * We do that wherever this function is called. + * Note: it's important to do the correct trimming if we change the + * prim type! We do that wherever this function is called. */ if (prim == GL_QUAD_STRIP && ctx->Light.ShadeModel != GL_FLAT && @@ -739,8 +728,8 @@ st_draw_vbo(struct gl_context *ctx, } } - info.primitive_restart = st->ctx->Array.PrimitiveRestart; - info.restart_index = st->ctx->Array.RestartIndex; + info.primitive_restart = ctx->Array.PrimitiveRestart; + info.restart_index = ctx->Array.RestartIndex; /* do actual drawing */ for (i = 0; i < nr_prims; i++) { -- cgit v1.2.3