aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa')
-rw-r--r--mesalib/src/mesa/main/mipmap.c4442
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_blend.c61
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_clip.c151
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_sampler.c550
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_scissor.c201
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_stipple.c187
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_texture.c762
-rw-r--r--mesalib/src/mesa/state_tracker/st_draw.c61
8 files changed, 3229 insertions, 3186 deletions
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 c22d4c42e..c02ea3ffa 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 <keith@tungstengraphics.com>
- */
-
-
-#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 <keith@tungstengraphics.com>
+ */
+
+
+#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 <keith@tungstengraphics.com>
- * 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 <keith@tungstengraphics.com>
+ * 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 <keith@tungstengraphics.com>
- */
-
-
-#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 <keith@tungstengraphics.com>
+ */
+
+
+#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 <assert.h>
-
-#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 <assert.h>
+
+#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 <keith@tungstengraphics.com>
- * 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 <keith@tungstengraphics.com>
+ * 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 6eceba1da..6d86e1310 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 <keith@tungstengraphics.com>
@@ -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++) {