From 1ccf18dc09e288ddf937aa890b50c8d0a9df4319 Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 29 May 2011 15:02:10 +0200 Subject: libX11 mesa mkfontscale pixman xserver git update 29 Mar 2011 --- mesalib/src/mesa/main/atifragshader.c | 4 +- mesalib/src/mesa/main/buffers.c | 1068 +++++++------- mesalib/src/mesa/main/dlist.c | 427 +++++- mesalib/src/mesa/main/fbobject.c | 2 +- mesalib/src/mesa/main/queryobj.c | 1248 ++++++++-------- mesalib/src/mesa/main/queryobj.h | 174 +-- mesalib/src/mesa/main/shaderapi.c | 8 +- mesalib/src/mesa/main/texformat.c | 1528 ++++++++++---------- mesalib/src/mesa/main/teximage.c | 2 +- mesalib/src/mesa/program/ir_to_mesa.cpp | 3 +- mesalib/src/mesa/program/prog_parameter_layout.c | 1 + .../src/mesa/state_tracker/st_atom_pixeltransfer.c | 2 +- mesalib/src/mesa/state_tracker/st_cb_accum.c | 694 ++++----- .../src/mesa/state_tracker/st_cb_bufferobjects.c | 3 +- mesalib/src/mesa/state_tracker/st_cb_drawpixels.c | 26 +- mesalib/src/mesa/state_tracker/st_cb_readpixels.c | 9 +- mesalib/src/mesa/state_tracker/st_cb_texture.c | 4 +- mesalib/src/mesa/state_tracker/st_gen_mipmap.c | 902 ++++++------ 18 files changed, 3248 insertions(+), 2857 deletions(-) (limited to 'mesalib/src/mesa') diff --git a/mesalib/src/mesa/main/atifragshader.c b/mesalib/src/mesa/main/atifragshader.c index 1707f0b95..ff7b042d2 100644 --- a/mesalib/src/mesa/main/atifragshader.c +++ b/mesalib/src/mesa/main/atifragshader.c @@ -494,7 +494,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) } } - curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); + curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); new_tex_inst(curProg); /* add the instructions */ @@ -567,7 +567,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) } } - curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); + curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); new_tex_inst(curProg); /* add the instructions */ diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index 928450f0f..63f53e2b0 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -1,526 +1,542 @@ -/* - * 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 buffers.c - * glReadBuffer, DrawBuffer functions. - */ - - - -#include "glheader.h" -#include "buffers.h" -#include "colormac.h" -#include "context.h" -#include "enums.h" -#include "mtypes.h" - - -#define BAD_MASK ~0u - - -/** - * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are - * available to the rendering context (for drawing or reading). - * This depends on the type of framebuffer. For window system framebuffers - * we look at the framebuffer's visual. But for user-create framebuffers we - * look at the number of supported color attachments. - * \param fb the framebuffer to draw to, or read from - * \return bitmask of BUFFER_BIT_* flags - */ -static GLbitfield -supported_buffer_bitmask(const struct gl_context *ctx, const struct gl_framebuffer *fb) -{ - GLbitfield mask = 0x0; - - if (fb->Name > 0) { - /* A user-created renderbuffer */ - GLuint i; - ASSERT(ctx->Extensions.EXT_framebuffer_object); - for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { - mask |= (BUFFER_BIT_COLOR0 << i); - } - } - else { - /* A window system framebuffer */ - GLint i; - mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ - if (fb->Visual.stereoMode) { - mask |= BUFFER_BIT_FRONT_RIGHT; - if (fb->Visual.doubleBufferMode) { - mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; - } - } - else if (fb->Visual.doubleBufferMode) { - mask |= BUFFER_BIT_BACK_LEFT; - } - - for (i = 0; i < fb->Visual.numAuxBuffers; i++) { - mask |= (BUFFER_BIT_AUX0 << i); - } - } - - return mask; -} - - -/** - * Helper routine used by glDrawBuffer and glDrawBuffersARB. - * Given a GLenum naming one or more color buffers (such as - * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. - */ -static GLbitfield -draw_buffer_enum_to_bitmask(GLenum buffer) -{ - switch (buffer) { - case GL_NONE: - return 0; - case GL_FRONT: - return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; - case GL_BACK: - return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; - case GL_RIGHT: - return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; - case GL_FRONT_RIGHT: - return BUFFER_BIT_FRONT_RIGHT; - case GL_BACK_RIGHT: - return BUFFER_BIT_BACK_RIGHT; - case GL_BACK_LEFT: - return BUFFER_BIT_BACK_LEFT; - case GL_FRONT_AND_BACK: - return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT - | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; - case GL_LEFT: - return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; - case GL_FRONT_LEFT: - return BUFFER_BIT_FRONT_LEFT; - case GL_AUX0: - return BUFFER_BIT_AUX0; - case GL_AUX1: - case GL_AUX2: - case GL_AUX3: - return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */ - case GL_COLOR_ATTACHMENT0_EXT: - return BUFFER_BIT_COLOR0; - case GL_COLOR_ATTACHMENT1_EXT: - return BUFFER_BIT_COLOR1; - case GL_COLOR_ATTACHMENT2_EXT: - return BUFFER_BIT_COLOR2; - case GL_COLOR_ATTACHMENT3_EXT: - return BUFFER_BIT_COLOR3; - case GL_COLOR_ATTACHMENT4_EXT: - return BUFFER_BIT_COLOR4; - case GL_COLOR_ATTACHMENT5_EXT: - return BUFFER_BIT_COLOR5; - case GL_COLOR_ATTACHMENT6_EXT: - return BUFFER_BIT_COLOR6; - case GL_COLOR_ATTACHMENT7_EXT: - return BUFFER_BIT_COLOR7; - default: - /* error */ - return BAD_MASK; - } -} - - -/** - * Helper routine used by glReadBuffer. - * Given a GLenum naming a color buffer, return the index of the corresponding - * renderbuffer (a BUFFER_* value). - * return -1 for an invalid buffer. - */ -static GLint -read_buffer_enum_to_index(GLenum buffer) -{ - switch (buffer) { - case GL_FRONT: - return BUFFER_FRONT_LEFT; - case GL_BACK: - return BUFFER_BACK_LEFT; - case GL_RIGHT: - return BUFFER_FRONT_RIGHT; - case GL_FRONT_RIGHT: - return BUFFER_FRONT_RIGHT; - case GL_BACK_RIGHT: - return BUFFER_BACK_RIGHT; - case GL_BACK_LEFT: - return BUFFER_BACK_LEFT; - case GL_LEFT: - return BUFFER_FRONT_LEFT; - case GL_FRONT_LEFT: - return BUFFER_FRONT_LEFT; - case GL_AUX0: - return BUFFER_AUX0; - case GL_AUX1: - case GL_AUX2: - case GL_AUX3: - return BUFFER_COUNT; /* invalid, but not -1 */ - case GL_COLOR_ATTACHMENT0_EXT: - return BUFFER_COLOR0; - case GL_COLOR_ATTACHMENT1_EXT: - return BUFFER_COLOR1; - case GL_COLOR_ATTACHMENT2_EXT: - return BUFFER_COLOR2; - case GL_COLOR_ATTACHMENT3_EXT: - return BUFFER_COLOR3; - case GL_COLOR_ATTACHMENT4_EXT: - return BUFFER_COLOR4; - case GL_COLOR_ATTACHMENT5_EXT: - return BUFFER_COLOR5; - case GL_COLOR_ATTACHMENT6_EXT: - return BUFFER_COLOR6; - case GL_COLOR_ATTACHMENT7_EXT: - return BUFFER_COLOR7; - default: - /* error */ - return -1; - } -} - - -/** - * Called by glDrawBuffer(). - * Specify which renderbuffer(s) to draw into for the first color output. - * can name zero, one, two or four renderbuffers! - * \sa _mesa_DrawBuffersARB - * - * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. - * - * Note that the behaviour of this function depends on whether the - * current ctx->DrawBuffer is a window-system framebuffer (Name=0) or - * a user-created framebuffer object (Name!=0). - * In the former case, we update the per-context ctx->Color.DrawBuffer - * state var _and_ the FB's ColorDrawBuffer state. - * In the later case, we update the FB's ColorDrawBuffer state only. - * - * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the - * new FB is a window system FB, we need to re-update the FB's - * ColorDrawBuffer state to match the context. This is handled in - * _mesa_update_framebuffer(). - * - * See the GL_EXT_framebuffer_object spec for more info. - */ -void GLAPIENTRY -_mesa_DrawBuffer(GLenum buffer) -{ - GLbitfield destMask; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ - - if (MESA_VERBOSE & VERBOSE_API) { - _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - } - - if (buffer == GL_NONE) { - destMask = 0x0; - } - else { - const GLbitfield supportedMask - = supported_buffer_bitmask(ctx, ctx->DrawBuffer); - destMask = draw_buffer_enum_to_bitmask(buffer); - if (destMask == BAD_MASK) { - /* totally bogus buffer */ - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer=0x%x)", buffer); - return; - } - destMask &= supportedMask; - if (destMask == 0x0) { - /* none of the named color buffers exist! */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffer(buffer=0x%x)", buffer); - return; - } - } - - /* if we get here, there's no error so set new state */ - _mesa_drawbuffers(ctx, 1, &buffer, &destMask); - - /* - * Call device driver function. - */ - if (ctx->Driver.DrawBuffers) - ctx->Driver.DrawBuffers(ctx, 1, &buffer); - else if (ctx->Driver.DrawBuffer) - ctx->Driver.DrawBuffer(ctx, buffer); -} - - -/** - * Called by glDrawBuffersARB; specifies the destination color renderbuffers - * for N fragment program color outputs. - * \sa _mesa_DrawBuffer - * \param n number of outputs - * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the - * names cannot specify more than one buffer. For example, - * GL_FRONT_AND_BACK is illegal. - */ -void GLAPIENTRY -_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) -{ - GLint output; - GLbitfield usedBufferMask, supportedMask; - GLbitfield destMask[MAX_DRAW_BUFFERS]; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - /* Turns out n==0 is a valid input that should not produce an error. - * The remaining code below correctly handles the n==0 case. - */ - if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); - return; - } - - supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); - usedBufferMask = 0x0; - - /* complicated error checking... */ - for (output = 0; output < n; output++) { - if (buffers[output] == GL_NONE) { - destMask[output] = 0x0; - } - else { - destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); - if (destMask[output] == BAD_MASK - || _mesa_bitcount(destMask[output]) > 1) { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); - return; - } - destMask[output] &= supportedMask; - if (destMask[output] == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffersARB(unsupported buffer)"); - return; - } - if (destMask[output] & usedBufferMask) { - /* can't specify a dest buffer more than once! */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffersARB(duplicated buffer)"); - return; - } - - /* update bitmask */ - usedBufferMask |= destMask[output]; - } - } - - /* OK, if we get here, there were no errors so set the new state */ - _mesa_drawbuffers(ctx, n, buffers, destMask); - - /* - * Call device driver function. Note that n can be equal to 0, - * in which case we don't want to reference buffers[0], which - * may not be valid. - */ - if (ctx->Driver.DrawBuffers) - ctx->Driver.DrawBuffers(ctx, n, buffers); - else if (ctx->Driver.DrawBuffer) - ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); -} - - -/** - * Helper function to set the GL_DRAW_BUFFER state in the context and - * current FBO. Called via glDrawBuffer(), glDrawBuffersARB() - * - * All error checking will have been done prior to calling this function - * so nothing should go wrong at this point. - * - * \param ctx current context - * \param n number of color outputs to set - * \param buffers array[n] of colorbuffer names, like GL_LEFT. - * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the - * colorbuffer names. (i.e. GL_FRONT_AND_BACK => - * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). - */ -void -_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, - const GLbitfield *destMask) -{ - struct gl_framebuffer *fb = ctx->DrawBuffer; - GLbitfield mask[MAX_DRAW_BUFFERS]; - GLboolean newState = GL_FALSE; - - if (!destMask) { - /* compute destMask values now */ - const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb); - GLuint output; - for (output = 0; output < n; output++) { - mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); - ASSERT(mask[output] != BAD_MASK); - mask[output] &= supportedMask; - } - destMask = mask; - } - - /* - * If n==1, destMask[0] may have up to four bits set. - * Otherwise, destMask[x] can only have one bit set. - */ - if (n == 1) { - GLuint count = 0, destMask0 = destMask[0]; - while (destMask0) { - GLint bufIndex = _mesa_ffs(destMask0) - 1; - if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { - fb->_ColorDrawBufferIndexes[count] = bufIndex; - newState = GL_TRUE; - } - count++; - destMask0 &= ~(1 << bufIndex); - } - fb->ColorDrawBuffer[0] = buffers[0]; - if (fb->_NumColorDrawBuffers != count) { - fb->_NumColorDrawBuffers = count; - newState = GL_TRUE; - } - } - else { - GLuint buf, count = 0; - for (buf = 0; buf < n; buf++ ) { - if (destMask[buf]) { - GLint bufIndex = _mesa_ffs(destMask[buf]) - 1; - /* only one bit should be set in the destMask[buf] field */ - ASSERT(_mesa_bitcount(destMask[buf]) == 1); - if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { - fb->_ColorDrawBufferIndexes[buf] = bufIndex; - newState = GL_TRUE; - } - count = buf + 1; - } - else { - if (fb->_ColorDrawBufferIndexes[buf] != -1) { - fb->_ColorDrawBufferIndexes[buf] = -1; - newState = GL_TRUE; - } - } - fb->ColorDrawBuffer[buf] = buffers[buf]; - } - /* set remaining outputs to -1 (GL_NONE) */ - while (buf < ctx->Const.MaxDrawBuffers) { - if (fb->_ColorDrawBufferIndexes[buf] != -1) { - fb->_ColorDrawBufferIndexes[buf] = -1; - newState = GL_TRUE; - } - fb->ColorDrawBuffer[buf] = GL_NONE; - buf++; - } - fb->_NumColorDrawBuffers = count; - } - - if (fb->Name == 0) { - /* also set context drawbuffer state */ - GLuint buf; - for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { - if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { - ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; - newState = GL_TRUE; - } - } - } - - if (newState) - FLUSH_VERTICES(ctx, _NEW_BUFFERS); -} - - -/** - * Like \sa _mesa_drawbuffers(), this is a helper function for setting - * GL_READ_BUFFER state in the context and current FBO. - * \param ctx the rendering context - * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc. - * \param bufferIndex the numerical index corresponding to 'buffer' - */ -void -_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) -{ - struct gl_framebuffer *fb = ctx->ReadBuffer; - - if (fb->Name == 0) { - /* Only update the per-context READ_BUFFER state if we're bound to - * a window-system framebuffer. - */ - ctx->Pixel.ReadBuffer = buffer; - } - - fb->ColorReadBuffer = buffer; - fb->_ColorReadBufferIndex = bufferIndex; - - ctx->NewState |= _NEW_BUFFERS; -} - - - -/** - * Called by glReadBuffer to set the source renderbuffer for reading pixels. - * \param mode color buffer such as GL_FRONT, GL_BACK, etc. - */ -void GLAPIENTRY -_mesa_ReadBuffer(GLenum buffer) -{ - struct gl_framebuffer *fb; - GLbitfield supportedMask; - GLint srcBuffer; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - - fb = ctx->ReadBuffer; - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - - if (fb->Name > 0 && buffer == GL_NONE) { - /* This is legal for user-created framebuffer objects */ - srcBuffer = -1; - } - else { - /* general case / window-system framebuffer */ - srcBuffer = read_buffer_enum_to_index(buffer); - if (srcBuffer == -1) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glReadBuffer(buffer=0x%x)", buffer); - return; - } - supportedMask = supported_buffer_bitmask(ctx, fb); - if (((1 << srcBuffer) & supportedMask) == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadBuffer(buffer=0x%x)", buffer); - return; - } - } - - /* OK, all error checking has been completed now */ - - _mesa_readbuffer(ctx, buffer, srcBuffer); - ctx->NewState |= _NEW_BUFFERS; - - /* - * Call device driver function. - */ - if (ctx->Driver.ReadBuffer) - (*ctx->Driver.ReadBuffer)(ctx, buffer); -} +/* + * 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 buffers.c + * glReadBuffer, DrawBuffer functions. + */ + + + +#include "glheader.h" +#include "buffers.h" +#include "colormac.h" +#include "context.h" +#include "enums.h" +#include "mtypes.h" + + +#define BAD_MASK ~0u + + +/** + * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are + * available to the rendering context (for drawing or reading). + * This depends on the type of framebuffer. For window system framebuffers + * we look at the framebuffer's visual. But for user-create framebuffers we + * look at the number of supported color attachments. + * \param fb the framebuffer to draw to, or read from + * \return bitmask of BUFFER_BIT_* flags + */ +static GLbitfield +supported_buffer_bitmask(const struct gl_context *ctx, const struct gl_framebuffer *fb) +{ + GLbitfield mask = 0x0; + + if (fb->Name > 0) { + /* A user-created renderbuffer */ + GLuint i; + ASSERT(ctx->Extensions.EXT_framebuffer_object); + for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { + mask |= (BUFFER_BIT_COLOR0 << i); + } + } + else { + /* A window system framebuffer */ + GLint i; + mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ + if (fb->Visual.stereoMode) { + mask |= BUFFER_BIT_FRONT_RIGHT; + if (fb->Visual.doubleBufferMode) { + mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; + } + } + else if (fb->Visual.doubleBufferMode) { + mask |= BUFFER_BIT_BACK_LEFT; + } + + for (i = 0; i < fb->Visual.numAuxBuffers; i++) { + mask |= (BUFFER_BIT_AUX0 << i); + } + } + + return mask; +} + + +/** + * Helper routine used by glDrawBuffer and glDrawBuffersARB. + * Given a GLenum naming one or more color buffers (such as + * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. + */ +static GLbitfield +draw_buffer_enum_to_bitmask(GLenum buffer) +{ + switch (buffer) { + case GL_NONE: + return 0; + case GL_FRONT: + return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; + case GL_BACK: + return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; + case GL_RIGHT: + return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; + case GL_FRONT_RIGHT: + return BUFFER_BIT_FRONT_RIGHT; + case GL_BACK_RIGHT: + return BUFFER_BIT_BACK_RIGHT; + case GL_BACK_LEFT: + return BUFFER_BIT_BACK_LEFT; + case GL_FRONT_AND_BACK: + return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT + | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; + case GL_LEFT: + return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; + case GL_FRONT_LEFT: + return BUFFER_BIT_FRONT_LEFT; + case GL_AUX0: + return BUFFER_BIT_AUX0; + case GL_AUX1: + case GL_AUX2: + case GL_AUX3: + return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */ + case GL_COLOR_ATTACHMENT0_EXT: + return BUFFER_BIT_COLOR0; + case GL_COLOR_ATTACHMENT1_EXT: + return BUFFER_BIT_COLOR1; + case GL_COLOR_ATTACHMENT2_EXT: + return BUFFER_BIT_COLOR2; + case GL_COLOR_ATTACHMENT3_EXT: + return BUFFER_BIT_COLOR3; + case GL_COLOR_ATTACHMENT4_EXT: + return BUFFER_BIT_COLOR4; + case GL_COLOR_ATTACHMENT5_EXT: + return BUFFER_BIT_COLOR5; + case GL_COLOR_ATTACHMENT6_EXT: + return BUFFER_BIT_COLOR6; + case GL_COLOR_ATTACHMENT7_EXT: + return BUFFER_BIT_COLOR7; + default: + /* error */ + return BAD_MASK; + } +} + + +/** + * Helper routine used by glReadBuffer. + * Given a GLenum naming a color buffer, return the index of the corresponding + * renderbuffer (a BUFFER_* value). + * return -1 for an invalid buffer. + */ +static GLint +read_buffer_enum_to_index(GLenum buffer) +{ + switch (buffer) { + case GL_FRONT: + return BUFFER_FRONT_LEFT; + case GL_BACK: + return BUFFER_BACK_LEFT; + case GL_RIGHT: + return BUFFER_FRONT_RIGHT; + case GL_FRONT_RIGHT: + return BUFFER_FRONT_RIGHT; + case GL_BACK_RIGHT: + return BUFFER_BACK_RIGHT; + case GL_BACK_LEFT: + return BUFFER_BACK_LEFT; + case GL_LEFT: + return BUFFER_FRONT_LEFT; + case GL_FRONT_LEFT: + return BUFFER_FRONT_LEFT; + case GL_AUX0: + return BUFFER_AUX0; + case GL_AUX1: + case GL_AUX2: + case GL_AUX3: + return BUFFER_COUNT; /* invalid, but not -1 */ + case GL_COLOR_ATTACHMENT0_EXT: + return BUFFER_COLOR0; + case GL_COLOR_ATTACHMENT1_EXT: + return BUFFER_COLOR1; + case GL_COLOR_ATTACHMENT2_EXT: + return BUFFER_COLOR2; + case GL_COLOR_ATTACHMENT3_EXT: + return BUFFER_COLOR3; + case GL_COLOR_ATTACHMENT4_EXT: + return BUFFER_COLOR4; + case GL_COLOR_ATTACHMENT5_EXT: + return BUFFER_COLOR5; + case GL_COLOR_ATTACHMENT6_EXT: + return BUFFER_COLOR6; + case GL_COLOR_ATTACHMENT7_EXT: + return BUFFER_COLOR7; + default: + /* error */ + return -1; + } +} + + +/** + * Called by glDrawBuffer(). + * Specify which renderbuffer(s) to draw into for the first color output. + * can name zero, one, two or four renderbuffers! + * \sa _mesa_DrawBuffersARB + * + * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. + * + * Note that the behaviour of this function depends on whether the + * current ctx->DrawBuffer is a window-system framebuffer (Name=0) or + * a user-created framebuffer object (Name!=0). + * In the former case, we update the per-context ctx->Color.DrawBuffer + * state var _and_ the FB's ColorDrawBuffer state. + * In the later case, we update the FB's ColorDrawBuffer state only. + * + * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the + * new FB is a window system FB, we need to re-update the FB's + * ColorDrawBuffer state to match the context. This is handled in + * _mesa_update_framebuffer(). + * + * See the GL_EXT_framebuffer_object spec for more info. + */ +void GLAPIENTRY +_mesa_DrawBuffer(GLenum buffer) +{ + GLbitfield destMask; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ + + if (MESA_VERBOSE & VERBOSE_API) { + _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + } + + if (buffer == GL_NONE) { + destMask = 0x0; + } + else { + const GLbitfield supportedMask + = supported_buffer_bitmask(ctx, ctx->DrawBuffer); + destMask = draw_buffer_enum_to_bitmask(buffer); + if (destMask == BAD_MASK) { + /* totally bogus buffer */ + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer=0x%x)", buffer); + return; + } + destMask &= supportedMask; + if (destMask == 0x0) { + /* none of the named color buffers exist! */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawBuffer(buffer=0x%x)", buffer); + return; + } + } + + /* if we get here, there's no error so set new state */ + _mesa_drawbuffers(ctx, 1, &buffer, &destMask); + + /* + * Call device driver function. + */ + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, 1, &buffer); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, buffer); +} + + +/** + * Called by glDrawBuffersARB; specifies the destination color renderbuffers + * for N fragment program color outputs. + * \sa _mesa_DrawBuffer + * \param n number of outputs + * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the + * names cannot specify more than one buffer. For example, + * GL_FRONT_AND_BACK is illegal. + */ +void GLAPIENTRY +_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) +{ + GLint output; + GLbitfield usedBufferMask, supportedMask; + GLbitfield destMask[MAX_DRAW_BUFFERS]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + /* Turns out n==0 is a valid input that should not produce an error. + * The remaining code below correctly handles the n==0 case. + */ + if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); + return; + } + + supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); + usedBufferMask = 0x0; + + /* complicated error checking... */ + for (output = 0; output < n; output++) { + if (buffers[output] == GL_NONE) { + destMask[output] = 0x0; + } + else { + destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); + if (destMask[output] == BAD_MASK + || _mesa_bitcount(destMask[output]) > 1) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); + return; + } + destMask[output] &= supportedMask; + if (destMask[output] == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawBuffersARB(unsupported buffer)"); + return; + } + if (destMask[output] & usedBufferMask) { + /* can't specify a dest buffer more than once! */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawBuffersARB(duplicated buffer)"); + return; + } + + /* update bitmask */ + usedBufferMask |= destMask[output]; + } + } + + /* OK, if we get here, there were no errors so set the new state */ + _mesa_drawbuffers(ctx, n, buffers, destMask); + + /* + * Call device driver function. Note that n can be equal to 0, + * in which case we don't want to reference buffers[0], which + * may not be valid. + */ + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, n, buffers); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); +} + +/** + * Performs necessary state updates when _mesa_drawbuffers makes an + * actual change. + */ +static void +updated_drawbuffers(struct gl_context *ctx) +{ + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + +#if FEATURE_GL + if (ctx->API == API_OPENGL && !ctx->Extensions.ARB_ES2_compatibility) { + struct gl_framebuffer *fb = ctx->DrawBuffer; + + /* Flag the FBO as requiring validation. */ + if (fb->Name != 0) { + fb->_Status = 0; + } + } +#endif +} + +/** + * Helper function to set the GL_DRAW_BUFFER state in the context and + * current FBO. Called via glDrawBuffer(), glDrawBuffersARB() + * + * All error checking will have been done prior to calling this function + * so nothing should go wrong at this point. + * + * \param ctx current context + * \param n number of color outputs to set + * \param buffers array[n] of colorbuffer names, like GL_LEFT. + * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the + * colorbuffer names. (i.e. GL_FRONT_AND_BACK => + * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). + */ +void +_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, + const GLbitfield *destMask) +{ + struct gl_framebuffer *fb = ctx->DrawBuffer; + GLbitfield mask[MAX_DRAW_BUFFERS]; + + if (!destMask) { + /* compute destMask values now */ + const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb); + GLuint output; + for (output = 0; output < n; output++) { + mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); + ASSERT(mask[output] != BAD_MASK); + mask[output] &= supportedMask; + } + destMask = mask; + } + + /* + * If n==1, destMask[0] may have up to four bits set. + * Otherwise, destMask[x] can only have one bit set. + */ + if (n == 1) { + GLuint count = 0, destMask0 = destMask[0]; + while (destMask0) { + GLint bufIndex = _mesa_ffs(destMask0) - 1; + if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { + updated_drawbuffers(ctx); + fb->_ColorDrawBufferIndexes[count] = bufIndex; + } + count++; + destMask0 &= ~(1 << bufIndex); + } + fb->ColorDrawBuffer[0] = buffers[0]; + if (fb->_NumColorDrawBuffers != count) { + updated_drawbuffers(ctx); + fb->_NumColorDrawBuffers = count; + } + } + else { + GLuint buf, count = 0; + for (buf = 0; buf < n; buf++ ) { + if (destMask[buf]) { + GLint bufIndex = _mesa_ffs(destMask[buf]) - 1; + /* only one bit should be set in the destMask[buf] field */ + ASSERT(_mesa_bitcount(destMask[buf]) == 1); + if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { + updated_drawbuffers(ctx); + fb->_ColorDrawBufferIndexes[buf] = bufIndex; + } + count = buf + 1; + } + else { + if (fb->_ColorDrawBufferIndexes[buf] != -1) { + updated_drawbuffers(ctx); + fb->_ColorDrawBufferIndexes[buf] = -1; + } + } + fb->ColorDrawBuffer[buf] = buffers[buf]; + } + /* set remaining outputs to -1 (GL_NONE) */ + while (buf < ctx->Const.MaxDrawBuffers) { + if (fb->_ColorDrawBufferIndexes[buf] != -1) { + updated_drawbuffers(ctx); + fb->_ColorDrawBufferIndexes[buf] = -1; + } + fb->ColorDrawBuffer[buf] = GL_NONE; + buf++; + } + fb->_NumColorDrawBuffers = count; + } + + if (fb->Name == 0) { + /* also set context drawbuffer state */ + GLuint buf; + for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { + if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { + updated_drawbuffers(ctx); + ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; + } + } + } +} + + +/** + * Like \sa _mesa_drawbuffers(), this is a helper function for setting + * GL_READ_BUFFER state in the context and current FBO. + * \param ctx the rendering context + * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc. + * \param bufferIndex the numerical index corresponding to 'buffer' + */ +void +_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) +{ + struct gl_framebuffer *fb = ctx->ReadBuffer; + + if (fb->Name == 0) { + /* Only update the per-context READ_BUFFER state if we're bound to + * a window-system framebuffer. + */ + ctx->Pixel.ReadBuffer = buffer; + } + + fb->ColorReadBuffer = buffer; + fb->_ColorReadBufferIndex = bufferIndex; + + ctx->NewState |= _NEW_BUFFERS; +} + + + +/** + * Called by glReadBuffer to set the source renderbuffer for reading pixels. + * \param mode color buffer such as GL_FRONT, GL_BACK, etc. + */ +void GLAPIENTRY +_mesa_ReadBuffer(GLenum buffer) +{ + struct gl_framebuffer *fb; + GLbitfield supportedMask; + GLint srcBuffer; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + + fb = ctx->ReadBuffer; + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + + if (fb->Name > 0 && buffer == GL_NONE) { + /* This is legal for user-created framebuffer objects */ + srcBuffer = -1; + } + else { + /* general case / window-system framebuffer */ + srcBuffer = read_buffer_enum_to_index(buffer); + if (srcBuffer == -1) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glReadBuffer(buffer=0x%x)", buffer); + return; + } + supportedMask = supported_buffer_bitmask(ctx, fb); + if (((1 << srcBuffer) & supportedMask) == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glReadBuffer(buffer=0x%x)", buffer); + return; + } + } + + /* OK, all error checking has been completed now */ + + _mesa_readbuffer(ctx, buffer, srcBuffer); + ctx->NewState |= _NEW_BUFFERS; + + /* + * Call device driver function. + */ + if (ctx->Driver.ReadBuffer) + (*ctx->Driver.ReadBuffer)(ctx, buffer); +} diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c index 2aba82fc0..c23593bc3 100644 --- a/mesalib/src/mesa/main/dlist.c +++ b/mesalib/src/mesa/main/dlist.c @@ -57,6 +57,9 @@ #include "pack.h" #include "pbo.h" #include "queryobj.h" +#include "samplerobj.h" +#include "shaderapi.h" +#include "syncobj.h" #include "teximage.h" #include "mtypes.h" #include "varray.h" @@ -421,6 +424,10 @@ typedef enum /* GL_EXT_transform_feedback */ OPCODE_BEGIN_TRANSFORM_FEEDBACK, OPCODE_END_TRANSFORM_FEEDBACK, + OPCODE_BIND_TRANSFORM_FEEDBACK, + OPCODE_PAUSE_TRANSFORM_FEEDBACK, + OPCODE_RESUME_TRANSFORM_FEEDBACK, + OPCODE_DRAW_TRANSFORM_FEEDBACK, /* GL_EXT_texture_integer */ OPCODE_CLEARCOLOR_I, @@ -440,6 +447,18 @@ typedef enum /* GL_ARB_sampler_object */ OPCODE_BIND_SAMPLER, + OPCODE_SAMPLER_PARAMETERIV, + OPCODE_SAMPLER_PARAMETERFV, + OPCODE_SAMPLER_PARAMETERIIV, + OPCODE_SAMPLER_PARAMETERUIV, + + /* GL_ARB_geometry_shader4 */ + OPCODE_PROGRAM_PARAMETERI, + OPCODE_FRAMEBUFFER_TEXTURE, + OPCODE_FRAMEBUFFER_TEXTURE_FACE, + + /* GL_ARB_sync */ + OPCODE_WAIT_SYNC, /* The following three are meta instructions */ OPCODE_ERROR, /* raise compiled-in error */ @@ -481,6 +500,17 @@ union gl_dlist_node typedef union gl_dlist_node Node; +/** + * Used to store a 64-bit uint in a pair of "Nodes" for the sake of 32-bit + * environment. In 64-bit env, sizeof(Node)==8 anyway. + */ +union uint64_pair +{ + GLuint64 uint64; + GLuint uint32[2]; +}; + + /** * How many nodes to allocate at a time. * @@ -6263,6 +6293,69 @@ save_EndTransformFeedback(void) } } +static void GLAPIENTRY +save_TransformFeedbackVaryings(GLuint program, GLsizei count, + const GLchar **varyings, GLenum bufferMode) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_problem(ctx, + "glTransformFeedbackVarying() display list support not done"); +} + +static void GLAPIENTRY +save_BindTransformFeedback(GLenum target, GLuint name) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_BIND_TRANSFORM_FEEDBACK, 2); + if (n) { + n[1].e = target; + n[2].ui = name; + } + if (ctx->ExecuteFlag) { + CALL_BindTransformFeedback(ctx->Exec, (target, name)); + } +} + +static void GLAPIENTRY +save_PauseTransformFeedback(void) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) alloc_instruction(ctx, OPCODE_PAUSE_TRANSFORM_FEEDBACK, 0); + if (ctx->ExecuteFlag) { + CALL_PauseTransformFeedback(ctx->Exec, ()); + } +} + +static void GLAPIENTRY +save_ResumeTransformFeedback(void) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) alloc_instruction(ctx, OPCODE_RESUME_TRANSFORM_FEEDBACK, 0); + if (ctx->ExecuteFlag) { + CALL_ResumeTransformFeedback(ctx->Exec, ()); + } +} + +static void GLAPIENTRY +save_DrawTransformFeedback(GLenum mode, GLuint name) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_DRAW_TRANSFORM_FEEDBACK, 2); + if (n) { + n[1].e = mode; + n[2].ui = name; + } + if (ctx->ExecuteFlag) { + CALL_DrawTransformFeedback(ctx->Exec, (mode, name)); + } +} + /* aka UseProgram() */ static void GLAPIENTRY @@ -7087,6 +7180,198 @@ save_BindSampler(GLuint unit, GLuint sampler) } } +static void GLAPIENTRY +save_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_SAMPLER_PARAMETERIV, 6); + if (n) { + n[1].ui = sampler; + n[2].e = pname; + n[3].i = params[0]; + if (pname == GL_TEXTURE_BORDER_COLOR) { + n[4].i = params[1]; + n[5].i = params[2]; + n[6].i = params[3]; + } + else { + n[4].i = n[5].i = n[6].i = 0; + } + } + if (ctx->ExecuteFlag) { + CALL_SamplerParameteriv(ctx->Exec, (sampler, pname, params)); + } +} + +static void GLAPIENTRY +save_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) +{ + save_SamplerParameteriv(sampler, pname, ¶m); +} + +static void GLAPIENTRY +save_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_SAMPLER_PARAMETERFV, 6); + if (n) { + n[1].ui = sampler; + n[2].e = pname; + n[3].f = params[0]; + if (pname == GL_TEXTURE_BORDER_COLOR) { + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + else { + n[4].f = n[5].f = n[6].f = 0.0F; + } + } + if (ctx->ExecuteFlag) { + CALL_SamplerParameterfv(ctx->Exec, (sampler, pname, params)); + } +} + +static void GLAPIENTRY +save_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) +{ + save_SamplerParameterfv(sampler, pname, ¶m); +} + +static void GLAPIENTRY +save_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_SAMPLER_PARAMETERIIV, 6); + if (n) { + n[1].ui = sampler; + n[2].e = pname; + n[3].i = params[0]; + if (pname == GL_TEXTURE_BORDER_COLOR) { + n[4].i = params[1]; + n[5].i = params[2]; + n[6].i = params[3]; + } + else { + n[4].i = n[5].i = n[6].i = 0; + } + } + if (ctx->ExecuteFlag) { + CALL_SamplerParameterIiv(ctx->Exec, (sampler, pname, params)); + } +} + +static void GLAPIENTRY +save_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_SAMPLER_PARAMETERUIV, 6); + if (n) { + n[1].ui = sampler; + n[2].e = pname; + n[3].ui = params[0]; + if (pname == GL_TEXTURE_BORDER_COLOR) { + n[4].ui = params[1]; + n[5].ui = params[2]; + n[6].ui = params[3]; + } + else { + n[4].ui = n[5].ui = n[6].ui = 0; + } + } + if (ctx->ExecuteFlag) { + CALL_SamplerParameterIuiv(ctx->Exec, (sampler, pname, params)); + } +} + +/* GL_ARB_geometry_shader4 */ +static void GLAPIENTRY +save_ProgramParameteri(GLuint program, GLenum pname, GLint value) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_PROGRAM_PARAMETERI, 3); + if (n) { + n[1].ui = program; + n[2].e = pname; + n[3].i = value; + } + if (ctx->ExecuteFlag) { + CALL_ProgramParameteriARB(ctx->Exec, (program, pname, value)); + } +} + +static void GLAPIENTRY +save_FramebufferTexture(GLenum target, GLenum attachment, + GLuint texture, GLint level) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_FRAMEBUFFER_TEXTURE, 4); + if (n) { + n[1].e = target; + n[2].e = attachment; + n[3].ui = texture; + n[4].i = level; + } + if (ctx->ExecuteFlag) { + CALL_FramebufferTextureARB(ctx->Exec, (target, attachment, texture, level)); + } +} + +static void GLAPIENTRY +save_FramebufferTextureFace(GLenum target, GLenum attachment, + GLuint texture, GLint level, GLenum face) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_FRAMEBUFFER_TEXTURE_FACE, 5); + if (n) { + n[1].e = target; + n[2].e = attachment; + n[3].ui = texture; + n[4].i = level; + n[5].e = face; + } + if (ctx->ExecuteFlag) { + CALL_FramebufferTextureFaceARB(ctx->Exec, (target, attachment, texture, + level, face)); + } +} + + + +static void GLAPIENTRY +save_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + Node *n; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = alloc_instruction(ctx, OPCODE_WAIT_SYNC, 4); + if (n) { + union uint64_pair p; + p.uint64 = timeout; + n[1].data = sync; + n[2].e = flags; + n[3].ui = p.uint32[0]; + n[4].ui = p.uint32[1]; + } + if (ctx->ExecuteFlag) { + CALL_WaitSync(ctx->Exec, (sync, flags, timeout)); + } +} + /** * Save an error-generating command into display list. @@ -7715,12 +8000,6 @@ execute_list(struct gl_context *ctx, GLuint list) case OPCODE_PROVOKING_VERTEX: CALL_ProvokingVertexEXT(ctx->Exec, (n[1].e)); break; - case OPCODE_BEGIN_TRANSFORM_FEEDBACK: - CALL_BeginTransformFeedbackEXT(ctx->Exec, (n[1].e)); - break; - case OPCODE_END_TRANSFORM_FEEDBACK: - CALL_EndTransformFeedbackEXT(ctx->Exec, ()); - break; case OPCODE_STENCIL_FUNC: CALL_StencilFunc(ctx->Exec, (n[1].e, n[2].i, n[3].ui)); break; @@ -8271,9 +8550,93 @@ execute_list(struct gl_context *ctx, GLuint list) CALL_TextureBarrierNV(ctx->Exec, ()); break; + /* GL_EXT/ARB_transform_feedback */ + case OPCODE_BEGIN_TRANSFORM_FEEDBACK: + CALL_BeginTransformFeedbackEXT(ctx->Exec, (n[1].e)); + break; + case OPCODE_END_TRANSFORM_FEEDBACK: + CALL_EndTransformFeedbackEXT(ctx->Exec, ()); + break; + case OPCODE_BIND_TRANSFORM_FEEDBACK: + CALL_BindTransformFeedback(ctx->Exec, (n[1].e, n[2].ui)); + break; + case OPCODE_PAUSE_TRANSFORM_FEEDBACK: + CALL_PauseTransformFeedback(ctx->Exec, ()); + break; + case OPCODE_RESUME_TRANSFORM_FEEDBACK: + CALL_ResumeTransformFeedback(ctx->Exec, ()); + break; + case OPCODE_DRAW_TRANSFORM_FEEDBACK: + CALL_DrawTransformFeedback(ctx->Exec, (n[1].e, n[2].ui)); + break; + + case OPCODE_BIND_SAMPLER: CALL_BindSampler(ctx->Exec, (n[1].ui, n[2].ui)); break; + case OPCODE_SAMPLER_PARAMETERIV: + { + GLint params[4]; + params[0] = n[3].i; + params[1] = n[4].i; + params[2] = n[5].i; + params[3] = n[6].i; + CALL_SamplerParameteriv(ctx->Exec, (n[1].ui, n[2].e, params)); + } + break; + case OPCODE_SAMPLER_PARAMETERFV: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + CALL_SamplerParameterfv(ctx->Exec, (n[1].ui, n[2].e, params)); + } + break; + case OPCODE_SAMPLER_PARAMETERIIV: + { + GLint params[4]; + params[0] = n[3].i; + params[1] = n[4].i; + params[2] = n[5].i; + params[3] = n[6].i; + CALL_SamplerParameterIiv(ctx->Exec, (n[1].ui, n[2].e, params)); + } + break; + case OPCODE_SAMPLER_PARAMETERUIV: + { + GLuint params[4]; + params[0] = n[3].ui; + params[1] = n[4].ui; + params[2] = n[5].ui; + params[3] = n[6].ui; + CALL_SamplerParameterIuiv(ctx->Exec, (n[1].ui, n[2].e, params)); + } + break; + + /* GL_ARB_geometry_shader4 */ + case OPCODE_PROGRAM_PARAMETERI: + CALL_ProgramParameteriARB(ctx->Exec, (n[1].ui, n[2].e, n[3].i)); + break; + case OPCODE_FRAMEBUFFER_TEXTURE: + CALL_FramebufferTextureARB(ctx->Exec, (n[1].e, n[2].e, + n[3].ui, n[4].i)); + break; + case OPCODE_FRAMEBUFFER_TEXTURE_FACE: + CALL_FramebufferTextureFaceARB(ctx->Exec, (n[1].e, n[2].e, + n[3].ui, n[4].i, n[5].e)); + break; + + /* GL_ARB_sync */ + case OPCODE_WAIT_SYNC: + { + union uint64_pair p; + p.uint32[0] = n[3].ui; + p.uint32[1] = n[4].ui; + CALL_WaitSync(ctx->Exec, (n[1].data, n[2].bf, p.uint64)); + } + break; case OPCODE_CONTINUE: n = (Node *) n[1].next; @@ -9741,6 +10104,10 @@ _mesa_create_save_table(void) SET_GenVertexArraysAPPLE(table, _mesa_GenVertexArraysAPPLE); SET_IsVertexArrayAPPLE(table, _mesa_IsVertexArrayAPPLE); + /* GL_ARB_vertex_array_object */ + SET_BindVertexArray(table, _mesa_BindVertexArray); + SET_GenVertexArrays(table, _mesa_GenVertexArrays); + /* ???. GL_EXT_depth_bounds_test */ SET_DepthBoundsEXT(table, save_DepthBoundsEXT); @@ -9823,15 +10190,11 @@ _mesa_create_save_table(void) #endif #if FEATURE_queryobj + _mesa_init_queryobj_dispatch(table); /* glGetQuery, etc */ SET_BeginQueryARB(table, save_BeginQueryARB); SET_EndQueryARB(table, save_EndQueryARB); - SET_GenQueriesARB(table, _mesa_GenQueriesARB); - SET_DeleteQueriesARB(table, _mesa_DeleteQueriesARB); - SET_IsQueryARB(table, _mesa_IsQueryARB); - SET_GetQueryivARB(table, _mesa_GetQueryivARB); - SET_GetQueryObjectivARB(table, _mesa_GetQueryObjectivARB); - SET_GetQueryObjectuivARB(table, _mesa_GetQueryObjectuivARB); #endif + SET_DrawBuffersARB(table, save_DrawBuffersARB); #if FEATURE_EXT_framebuffer_blit @@ -9839,6 +10202,7 @@ _mesa_create_save_table(void) #endif /* GL_ARB_shader_objects */ + _mesa_init_shader_dispatch(table); /* Plug in glCreate/Delete/Get, etc */ SET_UseProgramObjectARB(table, save_UseProgramObjectARB); SET_Uniform1fARB(table, save_Uniform1fARB); SET_Uniform2fARB(table, save_Uniform2fARB); @@ -9890,12 +10254,6 @@ _mesa_create_save_table(void) /* ARB 59. GL_ARB_copy_buffer */ SET_CopyBufferSubData(table, _mesa_CopyBufferSubData); /* no dlist save */ - /* 352. GL_EXT_transform_feedback */ -#if FEATURE_EXT_transform_feedback - SET_BeginTransformFeedbackEXT(table, save_BeginTransformFeedback); - SET_EndTransformFeedbackEXT(table, save_EndTransformFeedback); -#endif - /* 364. GL_EXT_provoking_vertex */ SET_ProvokingVertexEXT(table, save_ProvokingVertexEXT); @@ -9903,6 +10261,7 @@ _mesa_create_save_table(void) #if FEATURE_APPLE_object_purgeable SET_ObjectPurgeableAPPLE(table, _mesa_ObjectPurgeableAPPLE); SET_ObjectUnpurgeableAPPLE(table, _mesa_ObjectUnpurgeableAPPLE); + SET_GetObjectParameterivAPPLE(table, _mesa_GetObjectParameterivAPPLE); #endif /* GL_EXT_texture_integer */ @@ -9922,11 +10281,11 @@ _mesa_create_save_table(void) SET_ClampColor(table, save_ClampColorARB); /* GL 3.0 */ -#if 0 SET_ClearBufferiv(table, save_ClearBufferiv); SET_ClearBufferuiv(table, save_ClearBufferuiv); SET_ClearBufferfv(table, save_ClearBufferfv); SET_ClearBufferfi(table, save_ClearBufferfi); +#if 0 SET_Uniform1ui(table, save_Uniform1ui); SET_Uniform2ui(table, save_Uniform2ui); SET_Uniform3ui(table, save_Uniform3ui); @@ -9936,10 +10295,6 @@ _mesa_create_save_table(void) SET_Uniform3uiv(table, save_Uniform3uiv); SET_Uniform4uiv(table, save_Uniform4uiv); #else - (void) save_ClearBufferiv; - (void) save_ClearBufferuiv; - (void) save_ClearBufferfv; - (void) save_ClearBufferfi; (void) save_Uniform1ui; (void) save_Uniform2ui; (void) save_Uniform3ui; @@ -9950,6 +10305,16 @@ _mesa_create_save_table(void) (void) save_Uniform4uiv; #endif +#if FEATURE_EXT_transform_feedback + SET_BeginTransformFeedbackEXT(table, save_BeginTransformFeedback); + SET_EndTransformFeedbackEXT(table, save_EndTransformFeedback); + SET_TransformFeedbackVaryingsEXT(table, save_TransformFeedbackVaryings); + SET_BindTransformFeedback(table, save_BindTransformFeedback); + SET_PauseTransformFeedback(table, save_PauseTransformFeedback); + SET_ResumeTransformFeedback(table, save_ResumeTransformFeedback); + SET_DrawTransformFeedback(table, save_DrawTransformFeedback); +#endif + /* GL_ARB_instanced_arrays */ SET_VertexAttribDivisorARB(table, save_VertexAttribDivisor); @@ -9957,7 +10322,14 @@ _mesa_create_save_table(void) SET_TextureBarrierNV(table, save_TextureBarrierNV); /* GL_ARB_sampler_objects */ + _mesa_init_sampler_object_dispatch(table); /* plug in Gen/Get/etc functions */ SET_BindSampler(table, save_BindSampler); + SET_SamplerParameteri(table, save_SamplerParameteri); + SET_SamplerParameterf(table, save_SamplerParameterf); + SET_SamplerParameteriv(table, save_SamplerParameteriv); + SET_SamplerParameterfv(table, save_SamplerParameterfv); + SET_SamplerParameterIiv(table, save_SamplerParameterIiv); + SET_SamplerParameterIuiv(table, save_SamplerParameterIuiv); /* GL_ARB_draw_buffer_blend */ SET_BlendFunciARB(table, save_BlendFunci); @@ -9965,6 +10337,15 @@ _mesa_create_save_table(void) SET_BlendEquationiARB(table, save_BlendEquationi); SET_BlendEquationSeparateiARB(table, save_BlendEquationSeparatei); + /* GL_ARB_geometry_shader4 */ + SET_ProgramParameteriARB(table, save_ProgramParameteri); + SET_FramebufferTextureARB(table, save_FramebufferTexture); + SET_FramebufferTextureFaceARB(table, save_FramebufferTextureFace); + + /* GL_ARB_sync */ + _mesa_init_sync_dispatch(table); + SET_WaitSync(table, save_WaitSync); + return table; } diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 67df53b88..739d03e93 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -795,7 +795,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, } #if FEATURE_GL - if (ctx->API == API_OPENGL) { + if (ctx->API == API_OPENGL && !ctx->Extensions.ARB_ES2_compatibility) { /* Check that all DrawBuffers are present */ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { if (fb->ColorDrawBuffer[j] != GL_NONE) { diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c index 25ec31fd4..f0a9a7922 100644 --- a/mesalib/src/mesa/main/queryobj.c +++ b/mesalib/src/mesa/main/queryobj.c @@ -1,624 +1,624 @@ -/* - * 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. - */ - - -#include "glheader.h" -#include "context.h" -#include "enums.h" -#include "hash.h" -#include "imports.h" -#include "queryobj.h" -#include "mfeatures.h" -#include "mtypes.h" -#include "main/dispatch.h" - - -#if FEATURE_queryobj - - -/** - * Allocate a new query object. This is a fallback routine called via - * ctx->Driver.NewQueryObject(). - * \param ctx - rendering context - * \param id - the new object's ID - * \return pointer to new query_object object or NULL if out of memory. - */ -static struct gl_query_object * -_mesa_new_query_object(struct gl_context *ctx, GLuint id) -{ - struct gl_query_object *q = MALLOC_STRUCT(gl_query_object); - (void) ctx; - if (q) { - q->Id = id; - q->Result = 0; - q->Active = GL_FALSE; - q->Ready = GL_TRUE; /* correct, see spec */ - } - return q; -} - - -/** - * Begin a query. Software driver fallback. - * Called via ctx->Driver.BeginQuery(). - */ -static void -_mesa_begin_query(struct gl_context *ctx, struct gl_query_object *q) -{ - /* no-op */ -} - - -/** - * End a query. Software driver fallback. - * Called via ctx->Driver.EndQuery(). - */ -static void -_mesa_end_query(struct gl_context *ctx, struct gl_query_object *q) -{ - q->Ready = GL_TRUE; -} - - -/** - * Wait for query to complete. Software driver fallback. - * Called via ctx->Driver.WaitQuery(). - */ -static void -_mesa_wait_query(struct gl_context *ctx, struct gl_query_object *q) -{ - /* For software drivers, _mesa_end_query() should have completed the query. - * For real hardware, implement a proper WaitQuery() driver function, - * which may require issuing a flush. - */ - assert(q->Ready); -} - - -/** - * Check if a query results are ready. Software driver fallback. - * Called via ctx->Driver.CheckQuery(). - */ -static void -_mesa_check_query(struct gl_context *ctx, struct gl_query_object *q) -{ - /* No-op for sw rendering. - * HW drivers may need to flush at this time. - */ -} - - -/** - * Delete a query object. Called via ctx->Driver.DeleteQuery(). - * Not removed from hash table here. - */ -static void -_mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q) -{ - free(q); -} - - -void -_mesa_init_query_object_functions(struct dd_function_table *driver) -{ - driver->NewQueryObject = _mesa_new_query_object; - driver->DeleteQuery = _mesa_delete_query; - driver->BeginQuery = _mesa_begin_query; - driver->EndQuery = _mesa_end_query; - driver->WaitQuery = _mesa_wait_query; - driver->CheckQuery = _mesa_check_query; -} - - -/** - * Return pointer to the query object binding point for the given target. - * \return NULL if invalid target, else the address of binding point - */ -static struct gl_query_object ** -get_query_binding_point(struct gl_context *ctx, GLenum target) -{ - switch (target) { - case GL_SAMPLES_PASSED_ARB: - if (ctx->Extensions.ARB_occlusion_query) - return &ctx->Query.CurrentOcclusionObject; - else - return NULL; - case GL_ANY_SAMPLES_PASSED: - if (ctx->Extensions.ARB_occlusion_query2) - return &ctx->Query.CurrentOcclusionObject; - else - return NULL; - case GL_TIME_ELAPSED_EXT: - if (ctx->Extensions.EXT_timer_query) - return &ctx->Query.CurrentTimerObject; - else - return NULL; -#if FEATURE_EXT_transform_feedback - case GL_PRIMITIVES_GENERATED: - if (ctx->Extensions.EXT_transform_feedback) - return &ctx->Query.PrimitivesGenerated; - else - return NULL; - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: - if (ctx->Extensions.EXT_transform_feedback) - return &ctx->Query.PrimitivesWritten; - else - return NULL; -#endif - default: - return NULL; - } -} - - -void GLAPIENTRY -_mesa_GenQueriesARB(GLsizei n, GLuint *ids) -{ - GLuint first; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGenQueries(%d)\n", n); - - if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); - return; - } - - /* No query objects can be active at this time! */ - if (ctx->Query.CurrentOcclusionObject || - ctx->Query.CurrentTimerObject) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); - return; - } - - first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); - if (first) { - GLsizei i; - for (i = 0; i < n; i++) { - struct gl_query_object *q - = ctx->Driver.NewQueryObject(ctx, first + i); - if (!q) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); - return; - } - ids[i] = first + i; - _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); - } - } -} - - -void GLAPIENTRY -_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) -{ - GLint i; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, 0); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n); - - if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); - return; - } - - /* No query objects can be active at this time! */ - if (ctx->Query.CurrentOcclusionObject || - ctx->Query.CurrentTimerObject) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); - return; - } - - for (i = 0; i < n; i++) { - if (ids[i] > 0) { - struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]); - if (q) { - ASSERT(!q->Active); /* should be caught earlier */ - _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); - ctx->Driver.DeleteQuery(ctx, q); - } - } - } -} - - -GLboolean GLAPIENTRY -_mesa_IsQueryARB(GLuint id) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glIsQuery(%u)\n", id); - - if (id && _mesa_lookup_query_object(ctx, id)) - return GL_TRUE; - else - return GL_FALSE; -} - - -static void GLAPIENTRY -_mesa_BeginQueryARB(GLenum target, GLuint id) -{ - struct gl_query_object *q, **bindpt; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBeginQuery(%s, %u)\n", - _mesa_lookup_enum_by_nr(target), id); - - FLUSH_VERTICES(ctx, _NEW_DEPTH); - - bindpt = get_query_binding_point(ctx, target); - if (!bindpt) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); - return; - } - - if (id == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); - return; - } - - q = _mesa_lookup_query_object(ctx, id); - if (!q) { - /* create new object */ - q = ctx->Driver.NewQueryObject(ctx, id); - if (!q) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); - return; - } - _mesa_HashInsert(ctx->Query.QueryObjects, id, q); - } - else { - /* pre-existing object */ - if (q->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBeginQueryARB(query already active)"); - return; - } - } - - q->Target = target; - q->Active = GL_TRUE; - q->Result = 0; - q->Ready = GL_FALSE; - - /* XXX should probably refcount query objects */ - *bindpt = q; - - ctx->Driver.BeginQuery(ctx, q); -} - - -static void GLAPIENTRY -_mesa_EndQueryARB(GLenum target) -{ - struct gl_query_object *q, **bindpt; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target)); - - FLUSH_VERTICES(ctx, _NEW_DEPTH); - - bindpt = get_query_binding_point(ctx, target); - if (!bindpt) { - _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); - return; - } - - /* XXX should probably refcount query objects */ - q = *bindpt; - *bindpt = NULL; - - if (!q || !q->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glEndQueryARB(no matching glBeginQueryARB)"); - return; - } - - q->Active = GL_FALSE; - ctx->Driver.EndQuery(ctx, q); -} - - -void GLAPIENTRY -_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) -{ - struct gl_query_object *q, **bindpt; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n", - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(pname)); - - bindpt = get_query_binding_point(ctx, target); - if (!bindpt) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); - return; - } - - q = *bindpt; - - switch (pname) { - case GL_QUERY_COUNTER_BITS_ARB: - *params = 8 * sizeof(q->Result); - break; - case GL_CURRENT_QUERY_ARB: - *params = q ? q->Id : 0; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); - return; - } -} - - -void GLAPIENTRY -_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) -{ - struct gl_query_object *q = NULL; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); - - if (id) - q = _mesa_lookup_query_object(ctx, id); - - if (!q || q->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetQueryObjectivARB(id=%d is invalid or active)", id); - return; - } - - switch (pname) { - case GL_QUERY_RESULT_ARB: - if (!q->Ready) - ctx->Driver.WaitQuery(ctx, q); - /* if result is too large for returned type, clamp to max value */ - if (q->Target == GL_ANY_SAMPLES_PASSED) { - if (q->Result) - *params = GL_TRUE; - else - *params = GL_FALSE; - } else { - if (q->Result > 0x7fffffff) { - *params = 0x7fffffff; - } - else { - *params = (GLint)q->Result; - } - } - break; - case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); - *params = q->Ready; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); - return; - } -} - - -void GLAPIENTRY -_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) -{ - struct gl_query_object *q = NULL; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); - - if (id) - q = _mesa_lookup_query_object(ctx, id); - - if (!q || q->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetQueryObjectuivARB(id=%d is invalid or active)", id); - return; - } - - switch (pname) { - case GL_QUERY_RESULT_ARB: - if (!q->Ready) - ctx->Driver.WaitQuery(ctx, q); - /* if result is too large for returned type, clamp to max value */ - if (q->Target == GL_ANY_SAMPLES_PASSED) { - if (q->Result) - *params = GL_TRUE; - else - *params = GL_FALSE; - } else { - if (q->Result > 0xffffffff) { - *params = 0xffffffff; - } - else { - *params = (GLuint)q->Result; - } - } - break; - case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); - *params = q->Ready; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); - return; - } -} - - -/** - * New with GL_EXT_timer_query - */ -static void GLAPIENTRY -_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) -{ - struct gl_query_object *q = NULL; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); - - if (id) - q = _mesa_lookup_query_object(ctx, id); - - if (!q || q->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetQueryObjectui64vARB(id=%d is invalid or active)", id); - return; - } - - switch (pname) { - case GL_QUERY_RESULT_ARB: - if (!q->Ready) - ctx->Driver.WaitQuery(ctx, q); - *params = q->Result; - break; - case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); - *params = q->Ready; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)"); - return; - } -} - - -/** - * New with GL_EXT_timer_query - */ -static void GLAPIENTRY -_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) -{ - struct gl_query_object *q = NULL; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id, - _mesa_lookup_enum_by_nr(pname)); - - if (id) - q = _mesa_lookup_query_object(ctx, id); - - if (!q || q->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id); - return; - } - - switch (pname) { - case GL_QUERY_RESULT_ARB: - if (!q->Ready) - ctx->Driver.WaitQuery(ctx, q); - *params = q->Result; - break; - case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); - *params = q->Ready; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)"); - return; - } -} - - -void -_mesa_init_queryobj_dispatch(struct _glapi_table *disp) -{ - SET_GenQueriesARB(disp, _mesa_GenQueriesARB); - SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB); - SET_IsQueryARB(disp, _mesa_IsQueryARB); - SET_BeginQueryARB(disp, _mesa_BeginQueryARB); - SET_EndQueryARB(disp, _mesa_EndQueryARB); - SET_GetQueryivARB(disp, _mesa_GetQueryivARB); - SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB); - SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB); - - SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT); - SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT); -} - - -#endif /* FEATURE_queryobj */ - - -/** - * Allocate/init the context state related to query objects. - */ -void -_mesa_init_queryobj(struct gl_context *ctx) -{ - ctx->Query.QueryObjects = _mesa_NewHashTable(); - ctx->Query.CurrentOcclusionObject = NULL; -} - - -/** - * Callback for deleting a query object. Called by _mesa_HashDeleteAll(). - */ -static void -delete_queryobj_cb(GLuint id, void *data, void *userData) -{ - struct gl_query_object *q= (struct gl_query_object *) data; - struct gl_context *ctx = (struct gl_context *)userData; - ctx->Driver.DeleteQuery(ctx, q); -} - - -/** - * Free the context state related to query objects. - */ -void -_mesa_free_queryobj_data(struct gl_context *ctx) -{ - _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx); - _mesa_DeleteHashTable(ctx->Query.QueryObjects); -} +/* + * 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. + */ + + +#include "glheader.h" +#include "context.h" +#include "enums.h" +#include "hash.h" +#include "imports.h" +#include "queryobj.h" +#include "mfeatures.h" +#include "mtypes.h" +#include "main/dispatch.h" + + +#if FEATURE_queryobj + + +/** + * Allocate a new query object. This is a fallback routine called via + * ctx->Driver.NewQueryObject(). + * \param ctx - rendering context + * \param id - the new object's ID + * \return pointer to new query_object object or NULL if out of memory. + */ +static struct gl_query_object * +_mesa_new_query_object(struct gl_context *ctx, GLuint id) +{ + struct gl_query_object *q = MALLOC_STRUCT(gl_query_object); + (void) ctx; + if (q) { + q->Id = id; + q->Result = 0; + q->Active = GL_FALSE; + q->Ready = GL_TRUE; /* correct, see spec */ + } + return q; +} + + +/** + * Begin a query. Software driver fallback. + * Called via ctx->Driver.BeginQuery(). + */ +static void +_mesa_begin_query(struct gl_context *ctx, struct gl_query_object *q) +{ + /* no-op */ +} + + +/** + * End a query. Software driver fallback. + * Called via ctx->Driver.EndQuery(). + */ +static void +_mesa_end_query(struct gl_context *ctx, struct gl_query_object *q) +{ + q->Ready = GL_TRUE; +} + + +/** + * Wait for query to complete. Software driver fallback. + * Called via ctx->Driver.WaitQuery(). + */ +static void +_mesa_wait_query(struct gl_context *ctx, struct gl_query_object *q) +{ + /* For software drivers, _mesa_end_query() should have completed the query. + * For real hardware, implement a proper WaitQuery() driver function, + * which may require issuing a flush. + */ + assert(q->Ready); +} + + +/** + * Check if a query results are ready. Software driver fallback. + * Called via ctx->Driver.CheckQuery(). + */ +static void +_mesa_check_query(struct gl_context *ctx, struct gl_query_object *q) +{ + /* No-op for sw rendering. + * HW drivers may need to flush at this time. + */ +} + + +/** + * Delete a query object. Called via ctx->Driver.DeleteQuery(). + * Not removed from hash table here. + */ +static void +_mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q) +{ + free(q); +} + + +void +_mesa_init_query_object_functions(struct dd_function_table *driver) +{ + driver->NewQueryObject = _mesa_new_query_object; + driver->DeleteQuery = _mesa_delete_query; + driver->BeginQuery = _mesa_begin_query; + driver->EndQuery = _mesa_end_query; + driver->WaitQuery = _mesa_wait_query; + driver->CheckQuery = _mesa_check_query; +} + + +/** + * Return pointer to the query object binding point for the given target. + * \return NULL if invalid target, else the address of binding point + */ +static struct gl_query_object ** +get_query_binding_point(struct gl_context *ctx, GLenum target) +{ + switch (target) { + case GL_SAMPLES_PASSED_ARB: + if (ctx->Extensions.ARB_occlusion_query) + return &ctx->Query.CurrentOcclusionObject; + else + return NULL; + case GL_ANY_SAMPLES_PASSED: + if (ctx->Extensions.ARB_occlusion_query2) + return &ctx->Query.CurrentOcclusionObject; + else + return NULL; + case GL_TIME_ELAPSED_EXT: + if (ctx->Extensions.EXT_timer_query) + return &ctx->Query.CurrentTimerObject; + else + return NULL; +#if FEATURE_EXT_transform_feedback + case GL_PRIMITIVES_GENERATED: + if (ctx->Extensions.EXT_transform_feedback) + return &ctx->Query.PrimitivesGenerated; + else + return NULL; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + if (ctx->Extensions.EXT_transform_feedback) + return &ctx->Query.PrimitivesWritten; + else + return NULL; +#endif + default: + return NULL; + } +} + + +static void GLAPIENTRY +_mesa_GenQueriesARB(GLsizei n, GLuint *ids) +{ + GLuint first; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGenQueries(%d)\n", n); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); + return; + } + + /* No query objects can be active at this time! */ + if (ctx->Query.CurrentOcclusionObject || + ctx->Query.CurrentTimerObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); + return; + } + + first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); + if (first) { + GLsizei i; + for (i = 0; i < n; i++) { + struct gl_query_object *q + = ctx->Driver.NewQueryObject(ctx, first + i); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); + return; + } + ids[i] = first + i; + _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); + } + } +} + + +static void GLAPIENTRY +_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, 0); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); + return; + } + + /* No query objects can be active at this time! */ + if (ctx->Query.CurrentOcclusionObject || + ctx->Query.CurrentTimerObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); + return; + } + + for (i = 0; i < n; i++) { + if (ids[i] > 0) { + struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]); + if (q) { + ASSERT(!q->Active); /* should be caught earlier */ + _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); + ctx->Driver.DeleteQuery(ctx, q); + } + } + } +} + + +static GLboolean GLAPIENTRY +_mesa_IsQueryARB(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glIsQuery(%u)\n", id); + + if (id && _mesa_lookup_query_object(ctx, id)) + return GL_TRUE; + else + return GL_FALSE; +} + + +static void GLAPIENTRY +_mesa_BeginQueryARB(GLenum target, GLuint id) +{ + struct gl_query_object *q, **bindpt; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBeginQuery(%s, %u)\n", + _mesa_lookup_enum_by_nr(target), id); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + bindpt = get_query_binding_point(ctx, target); + if (!bindpt) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + return; + } + + if (id == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); + return; + } + + q = _mesa_lookup_query_object(ctx, id); + if (!q) { + /* create new object */ + q = ctx->Driver.NewQueryObject(ctx, id); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); + return; + } + _mesa_HashInsert(ctx->Query.QueryObjects, id, q); + } + else { + /* pre-existing object */ + if (q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginQueryARB(query already active)"); + return; + } + } + + q->Target = target; + q->Active = GL_TRUE; + q->Result = 0; + q->Ready = GL_FALSE; + + /* XXX should probably refcount query objects */ + *bindpt = q; + + ctx->Driver.BeginQuery(ctx, q); +} + + +static void GLAPIENTRY +_mesa_EndQueryARB(GLenum target) +{ + struct gl_query_object *q, **bindpt; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target)); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + bindpt = get_query_binding_point(ctx, target); + if (!bindpt) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + + /* XXX should probably refcount query objects */ + q = *bindpt; + *bindpt = NULL; + + if (!q || !q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEndQueryARB(no matching glBeginQueryARB)"); + return; + } + + q->Active = GL_FALSE; + ctx->Driver.EndQuery(ctx, q); +} + + +static void GLAPIENTRY +_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) +{ + struct gl_query_object *q, **bindpt; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(pname)); + + bindpt = get_query_binding_point(ctx, target); + if (!bindpt) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); + return; + } + + q = *bindpt; + + switch (pname) { + case GL_QUERY_COUNTER_BITS_ARB: + *params = 8 * sizeof(q->Result); + break; + case GL_CURRENT_QUERY_ARB: + *params = q ? q->Id : 0; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); + return; + } +} + + +static void GLAPIENTRY +_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + + if (id) + q = _mesa_lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectivARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + if (!q->Ready) + ctx->Driver.WaitQuery(ctx, q); + /* if result is too large for returned type, clamp to max value */ + if (q->Target == GL_ANY_SAMPLES_PASSED) { + if (q->Result) + *params = GL_TRUE; + else + *params = GL_FALSE; + } else { + if (q->Result > 0x7fffffff) { + *params = 0x7fffffff; + } + else { + *params = (GLint)q->Result; + } + } + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); + return; + } +} + + +static void GLAPIENTRY +_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + + if (id) + q = _mesa_lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectuivARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + if (!q->Ready) + ctx->Driver.WaitQuery(ctx, q); + /* if result is too large for returned type, clamp to max value */ + if (q->Target == GL_ANY_SAMPLES_PASSED) { + if (q->Result) + *params = GL_TRUE; + else + *params = GL_FALSE; + } else { + if (q->Result > 0xffffffff) { + *params = 0xffffffff; + } + else { + *params = (GLuint)q->Result; + } + } + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); + return; + } +} + + +/** + * New with GL_EXT_timer_query + */ +static void GLAPIENTRY +_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + + if (id) + q = _mesa_lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectui64vARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + if (!q->Ready) + ctx->Driver.WaitQuery(ctx, q); + *params = q->Result; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)"); + return; + } +} + + +/** + * New with GL_EXT_timer_query + */ +static void GLAPIENTRY +_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + + if (id) + q = _mesa_lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + if (!q->Ready) + ctx->Driver.WaitQuery(ctx, q); + *params = q->Result; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)"); + return; + } +} + + +void +_mesa_init_queryobj_dispatch(struct _glapi_table *disp) +{ + SET_GenQueriesARB(disp, _mesa_GenQueriesARB); + SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB); + SET_IsQueryARB(disp, _mesa_IsQueryARB); + SET_BeginQueryARB(disp, _mesa_BeginQueryARB); + SET_EndQueryARB(disp, _mesa_EndQueryARB); + SET_GetQueryivARB(disp, _mesa_GetQueryivARB); + SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB); + SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB); + + SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT); + SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT); +} + + +#endif /* FEATURE_queryobj */ + + +/** + * Allocate/init the context state related to query objects. + */ +void +_mesa_init_queryobj(struct gl_context *ctx) +{ + ctx->Query.QueryObjects = _mesa_NewHashTable(); + ctx->Query.CurrentOcclusionObject = NULL; +} + + +/** + * Callback for deleting a query object. Called by _mesa_HashDeleteAll(). + */ +static void +delete_queryobj_cb(GLuint id, void *data, void *userData) +{ + struct gl_query_object *q= (struct gl_query_object *) data; + struct gl_context *ctx = (struct gl_context *)userData; + ctx->Driver.DeleteQuery(ctx, q); +} + + +/** + * Free the context state related to query objects. + */ +void +_mesa_free_queryobj_data(struct gl_context *ctx) +{ + _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx); + _mesa_DeleteHashTable(ctx->Query.QueryObjects); +} diff --git a/mesalib/src/mesa/main/queryobj.h b/mesalib/src/mesa/main/queryobj.h index 4e8a1455b..16962e55a 100644 --- a/mesalib/src/mesa/main/queryobj.h +++ b/mesalib/src/mesa/main/queryobj.h @@ -1,96 +1,78 @@ -/* - * 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. - */ - - -#ifndef QUERYOBJ_H -#define QUERYOBJ_H - - -#include "main/mfeatures.h" -#include "main/mtypes.h" -#include "main/hash.h" - - -#if FEATURE_queryobj - -static INLINE struct gl_query_object * -_mesa_lookup_query_object(struct gl_context *ctx, GLuint id) -{ - return (struct gl_query_object *) - _mesa_HashLookup(ctx->Query.QueryObjects, id); -} - - -extern void GLAPIENTRY -_mesa_GenQueriesARB(GLsizei n, GLuint *ids); - -extern void GLAPIENTRY -_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids); - -extern GLboolean GLAPIENTRY -_mesa_IsQueryARB(GLuint id); - -extern void GLAPIENTRY -_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params); - -extern void GLAPIENTRY -_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params); - -extern void GLAPIENTRY -_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params); - -extern void -_mesa_init_query_object_functions(struct dd_function_table *driver); - -extern void -_mesa_init_queryobj_dispatch(struct _glapi_table *disp); - -#else /* FEATURE_queryobj */ - -static INLINE struct gl_query_object * -_mesa_lookup_query_object(struct gl_context *ctx, GLuint id) -{ - return NULL; -} - -static INLINE void -_mesa_init_query_object_functions(struct dd_function_table *driver) -{ -} - -static INLINE void -_mesa_init_queryobj_dispatch(struct _glapi_table *disp) -{ -} - -#endif /* FEATURE_queryobj */ - -extern void -_mesa_init_queryobj(struct gl_context *ctx); - -extern void -_mesa_free_queryobj_data(struct gl_context *ctx); - - -#endif /* QUERYOBJ_H */ +/* + * 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. + */ + + +#ifndef QUERYOBJ_H +#define QUERYOBJ_H + + +#include "main/mfeatures.h" +#include "main/mtypes.h" +#include "main/hash.h" + + +#if FEATURE_queryobj + +static INLINE struct gl_query_object * +_mesa_lookup_query_object(struct gl_context *ctx, GLuint id) +{ + return (struct gl_query_object *) + _mesa_HashLookup(ctx->Query.QueryObjects, id); +} + + +extern void +_mesa_init_query_object_functions(struct dd_function_table *driver); + +extern void +_mesa_init_queryobj_dispatch(struct _glapi_table *disp); + +#else /* FEATURE_queryobj */ + +static INLINE struct gl_query_object * +_mesa_lookup_query_object(struct gl_context *ctx, GLuint id) +{ + return NULL; +} + +static INLINE void +_mesa_init_query_object_functions(struct dd_function_table *driver) +{ +} + +static INLINE void +_mesa_init_queryobj_dispatch(struct _glapi_table *disp) +{ +} + +#endif /* FEATURE_queryobj */ + +extern void +_mesa_init_queryobj(struct gl_context *ctx); + +extern void +_mesa_free_queryobj_data(struct gl_context *ctx); + + +#endif /* QUERYOBJ_H */ diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 514eed5d0..03155b7ac 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -1519,7 +1519,8 @@ _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count, for (i = 0; i < count; i++) { if (string[i] == NULL) { free((GLvoid *) offsets); - _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderSourceARB(null string)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glShaderSourceARB(null string)"); return; } if (length == NULL || length[i] < 0) @@ -1570,7 +1571,7 @@ _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count, free(source); source = newSource; } - } + } shader_source(ctx, shaderObj, source); @@ -1709,8 +1710,7 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, #if FEATURE_ARB_geometry_shader4 void GLAPIENTRY -_mesa_ProgramParameteriARB(GLuint program, GLenum pname, - GLint value) +_mesa_ProgramParameteriARB(GLuint program, GLenum pname, GLint value) { struct gl_shader_program *shProg; GET_CURRENT_CONTEXT(ctx); diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index 41d9e9599..8cbb021d8 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -1,763 +1,765 @@ -/* - * Mesa 3-D graphics library - * Version: 7.7 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (c) 2008-2009 VMware, Inc. - * - * 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 texformat.c - * Texture formats. - * - * \author Gareth Hughes - * \author Brian Paul - */ - - -#include "context.h" -#include "mfeatures.h" -#include "mtypes.h" -#include "texcompress.h" -#include "texformat.h" - -#define RETURN_IF_SUPPORTED(f) do { \ - if (ctx->TextureFormatSupported[f]) \ - return f; \ -} while (0) - -/** - * Choose an appropriate texture format given the format, type and - * internalFormat parameters passed to glTexImage(). - * - * \param ctx the GL context. - * \param internalFormat user's prefered internal texture format. - * \param format incoming image pixel format. - * \param type incoming image data type. - * - * \return a pointer to a gl_texture_format object which describes the - * choosen texture format, or NULL on failure. - * - * This is called via dd_function_table::ChooseTextureFormat. Hardware drivers - * will typically override this function with a specialized version. - */ -gl_format -_mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, - GLenum format, GLenum type ) -{ - (void) format; - (void) type; - - switch (internalFormat) { - /* shallow RGBA formats */ - case 4: - case GL_RGBA: - if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) { - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); - } else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) { - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555); - } - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - - case GL_RGBA8: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - case GL_RGB5_A1: - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555); - break; - case GL_RGBA2: - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444_REV); /* just to test another format*/ - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); - break; - case GL_RGBA4: - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); - break; - - /* deep RGBA formats */ - case GL_RGB10_A2: - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - case GL_RGBA12: - case GL_RGBA16: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - - /* shallow RGB formats */ - case 3: - case GL_RGB: - case GL_RGB8: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); - RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - case GL_R3_G3_B2: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB332); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); - RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - case GL_RGB4: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565_REV); /* just to test another format */ - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); - break; - case GL_RGB5: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); - break; - - /* deep RGB formats */ - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); - RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - - /* Alpha formats */ - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - RETURN_IF_SUPPORTED(MESA_FORMAT_A8); - break; - - case GL_ALPHA12: - case GL_ALPHA16: - RETURN_IF_SUPPORTED(MESA_FORMAT_A16); - RETURN_IF_SUPPORTED(MESA_FORMAT_A8); - break; - - /* Luminance formats */ - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - RETURN_IF_SUPPORTED(MESA_FORMAT_L8); - break; - - case GL_LUMINANCE12: - case GL_LUMINANCE16: - RETURN_IF_SUPPORTED(MESA_FORMAT_L16); - RETURN_IF_SUPPORTED(MESA_FORMAT_L8); - break; - - /* Luminance/Alpha formats */ - case GL_LUMINANCE4_ALPHA4: - RETURN_IF_SUPPORTED(MESA_FORMAT_AL44); - RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); - break; - - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); - break; - - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - RETURN_IF_SUPPORTED(MESA_FORMAT_AL1616); - RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); - break; - - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - RETURN_IF_SUPPORTED(MESA_FORMAT_I8); - break; - - case GL_INTENSITY12: - case GL_INTENSITY16: - RETURN_IF_SUPPORTED(MESA_FORMAT_I16); - RETURN_IF_SUPPORTED(MESA_FORMAT_I8); - break; - - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - case GL_COLOR_INDEX8_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_CI8); - break; - - default: - ; /* fallthrough */ - } - - if (ctx->Extensions.ARB_depth_texture) { - switch (internalFormat) { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - RETURN_IF_SUPPORTED(MESA_FORMAT_Z32); - RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); - break; - case GL_DEPTH_COMPONENT16: - RETURN_IF_SUPPORTED(MESA_FORMAT_Z16); - RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); - default: - ; /* fallthrough */ - } - } - - switch (internalFormat) { - case GL_COMPRESSED_ALPHA_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_A8); - break; - case GL_COMPRESSED_LUMINANCE_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_L8); - break; - case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); - break; - case GL_COMPRESSED_INTENSITY_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_I8); - break; - case GL_COMPRESSED_RGB_ARB: - if (ctx->Extensions.EXT_texture_compression_s3tc || - ctx->Extensions.S3_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); - if (ctx->Extensions.TDFX_texture_compression_FXT1) - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); - RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - case GL_COMPRESSED_RGBA_ARB: - if (ctx->Extensions.EXT_texture_compression_s3tc || - ctx->Extensions.S3_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */ - if (ctx->Extensions.TDFX_texture_compression_FXT1) - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - default: - ; /* fallthrough */ - } - - if (ctx->Extensions.MESA_ycbcr_texture) { - if (internalFormat == GL_YCBCR_MESA) { - if (type == GL_UNSIGNED_SHORT_8_8_MESA) - RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR); - else - RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR_REV); - } - } - -#if FEATURE_texture_fxt1 - if (ctx->Extensions.TDFX_texture_compression_FXT1) { - switch (internalFormat) { - case GL_COMPRESSED_RGB_FXT1_3DFX: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1); - break; - case GL_COMPRESSED_RGBA_FXT1_3DFX: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1); - break; - default: - ; /* fallthrough */ - } - } -#endif - -#if FEATURE_texture_s3tc - if (ctx->Extensions.EXT_texture_compression_s3tc) { - switch (internalFormat) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); - break; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT1); - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT5); - break; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.S3_s3tc) { - switch (internalFormat) { - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); - break; - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); - break; - default: - ; /* fallthrough */ - } - } -#endif - - if (ctx->Extensions.ARB_texture_float) { - switch (internalFormat) { - case GL_ALPHA16F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_ALPHA32F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_LUMINANCE16F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_LUMINANCE32F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_LUMINANCE_ALPHA16F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_LUMINANCE_ALPHA32F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_INTENSITY16F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_INTENSITY32F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_RGB16F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_RGB32F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_RGBA16F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_RGBA32F_ARB: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_shared_exponent) { - switch (internalFormat) { - case GL_RGB9_E5: - ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_RGB9_E5_FLOAT]); - return MESA_FORMAT_RGB9_E5_FLOAT; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_packed_float) { - switch (internalFormat) { - case GL_R11F_G11F_B10F: - ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_R11_G11_B10_FLOAT]); - return MESA_FORMAT_R11_G11_B10_FLOAT; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_packed_depth_stencil) { - switch (internalFormat) { - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_S8); - RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); - break; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ATI_envmap_bumpmap) { - switch (internalFormat) { - case GL_DUDV_ATI: - case GL_DU8DV8_ATI: - RETURN_IF_SUPPORTED(MESA_FORMAT_DUDV8); - break; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_snorm) { - switch (internalFormat) { - case GL_RED_SNORM: - case GL_R8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R8); - break; - case GL_RG_SNORM: - case GL_RG8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG88_REV); - break; - case GL_RGB_SNORM: - case GL_RGB8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); - /* FALLTHROUGH */ - case GL_RGBA_SNORM: - case GL_RGBA8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_ALPHA_SNORM: - case GL_ALPHA8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_LUMINANCE_SNORM: - case GL_LUMINANCE8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_LUMINANCE_ALPHA_SNORM: - case GL_LUMINANCE8_ALPHA8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL88); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_INTENSITY_SNORM: - case GL_INTENSITY8_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_R16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R16); - break; - case GL_RG16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_GR1616); - break; - case GL_RGB16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGB_16); - /* FALLTHROUGH */ - case GL_RGBA16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_ALPHA16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A16); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_LUMINANCE16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L16); - /* FALLTHROUGH */ - case GL_LUMINANCE16_ALPHA16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL1616); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - case GL_INTENSITY16_SNORM: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I16); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); - break; - default: - ; /* fall-through */ - } - } - -#if FEATURE_EXT_texture_sRGB - if (ctx->Extensions.EXT_texture_sRGB) { - switch (internalFormat) { - case GL_SRGB_EXT: - case GL_SRGB8_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_SRGB_ALPHA_EXT: - case GL_SRGB8_ALPHA8_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_SLUMINANCE_EXT: - case GL_SLUMINANCE8_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SL8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_SLUMINANCE_ALPHA_EXT: - case GL_SLUMINANCE8_ALPHA8_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_COMPRESSED_SLUMINANCE_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SL8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_COMPRESSED_SRGB_EXT: -#if FEATURE_texture_s3tc - if (ctx->Extensions.EXT_texture_compression_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1); -#endif - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_COMPRESSED_SRGB_ALPHA_EXT: -#if FEATURE_texture_s3tc - if (ctx->Extensions.EXT_texture_compression_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */ -#endif - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; -#if FEATURE_texture_s3tc - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - if (ctx->Extensions.EXT_texture_compression_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - if (ctx->Extensions.EXT_texture_compression_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT1); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - if (ctx->Extensions.EXT_texture_compression_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - if (ctx->Extensions.EXT_texture_compression_s3tc) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT5); - RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); - break; -#endif - default: - ; /* fallthrough */ - } - } -#endif /* FEATURE_EXT_texture_sRGB */ - - if (ctx->Extensions.EXT_texture_integer) { - switch (internalFormat) { - case GL_RGBA32UI_EXT: - case GL_RGB32UI_EXT: - case GL_ALPHA32UI_EXT: - case GL_INTENSITY32UI_EXT: - case GL_LUMINANCE32UI_EXT: - case GL_LUMINANCE_ALPHA32UI_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); - break; - case GL_RGBA16UI_EXT: - case GL_RGB16UI_EXT: - case GL_ALPHA16UI_EXT: - case GL_INTENSITY16UI_EXT: - case GL_LUMINANCE16UI_EXT: - case GL_LUMINANCE_ALPHA16UI_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); - break; - case GL_RGBA8UI_EXT: - case GL_RGB8UI_EXT: - case GL_ALPHA8UI_EXT: - case GL_INTENSITY8UI_EXT: - case GL_LUMINANCE8UI_EXT: - case GL_LUMINANCE_ALPHA8UI_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); - break; - case GL_RGBA32I_EXT: - case GL_RGB32I_EXT: - case GL_ALPHA32I_EXT: - case GL_INTENSITY32I_EXT: - case GL_LUMINANCE32I_EXT: - case GL_LUMINANCE_ALPHA32I_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); - break; - case GL_RGBA16I_EXT: - case GL_RGB16I_EXT: - case GL_ALPHA16I_EXT: - case GL_INTENSITY16I_EXT: - case GL_LUMINANCE16I_EXT: - case GL_LUMINANCE_ALPHA16I_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); - break; - case GL_RGBA8I_EXT: - case GL_RGB8I_EXT: - case GL_ALPHA8I_EXT: - case GL_INTENSITY8I_EXT: - case GL_LUMINANCE8I_EXT: - case GL_LUMINANCE_ALPHA8I_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); - break; - } - } - - if (ctx->Extensions.ARB_texture_rg) { - switch (internalFormat) { - case GL_R8: - case GL_RED: - RETURN_IF_SUPPORTED(MESA_FORMAT_R8); - break; - - case GL_COMPRESSED_RED: - RETURN_IF_SUPPORTED(MESA_FORMAT_RED_RGTC1); - RETURN_IF_SUPPORTED(MESA_FORMAT_R8); - break; - - case GL_R16: - RETURN_IF_SUPPORTED(MESA_FORMAT_R16); - break; - - case GL_RG: - case GL_RG8: - RETURN_IF_SUPPORTED(MESA_FORMAT_RG88); - break; - - case GL_COMPRESSED_RG: - RETURN_IF_SUPPORTED(MESA_FORMAT_RG_RGTC2); - RETURN_IF_SUPPORTED(MESA_FORMAT_RG88); - break; - - case GL_RG16: - RETURN_IF_SUPPORTED(MESA_FORMAT_RG1616); - break; - - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ARB_texture_rg && ctx->Extensions.ARB_texture_float) { - switch (internalFormat) { - case GL_R16F: - RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_R32F: - RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_RG16F: - RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16); - RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - case GL_RG32F: - RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); - break; - - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_format_BGRA8888) { - switch (internalFormat) { - case GL_BGRA: - RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); - break; - - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ARB_texture_compression_rgtc) { - switch (internalFormat) { - case GL_COMPRESSED_RED_RGTC1: - RETURN_IF_SUPPORTED(MESA_FORMAT_RED_RGTC1); - break; - case GL_COMPRESSED_SIGNED_RED_RGTC1: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RED_RGTC1); - break; - case GL_COMPRESSED_RG_RGTC2: - RETURN_IF_SUPPORTED(MESA_FORMAT_RG_RGTC2); - break; - case GL_COMPRESSED_SIGNED_RG_RGTC2: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG_RGTC2); - break; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_compression_latc) { - switch (internalFormat) { - case GL_COMPRESSED_LUMINANCE_LATC1_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_L_LATC1); - break; - case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L_LATC1); - break; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_LA_LATC2); - break; - case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: - RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_LA_LATC2); - break; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ATI_texture_compression_3dc) { - switch (internalFormat) { - case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: - RETURN_IF_SUPPORTED(MESA_FORMAT_LA_LATC2); - break; - default: - ; /* fallthrough */ - } - } - - _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()"); - return MESA_FORMAT_NONE; -} - +/* + * Mesa 3-D graphics library + * Version: 7.7 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (c) 2008-2009 VMware, Inc. + * + * 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 texformat.c + * Texture formats. + * + * \author Gareth Hughes + * \author Brian Paul + */ + + +#include "context.h" +#include "mfeatures.h" +#include "mtypes.h" +#include "texcompress.h" +#include "texformat.h" + +#define RETURN_IF_SUPPORTED(f) do { \ + if (ctx->TextureFormatSupported[f]) \ + return f; \ +} while (0) + +/** + * Choose an appropriate texture format given the format, type and + * internalFormat parameters passed to glTexImage(). + * + * \param ctx the GL context. + * \param internalFormat user's prefered internal texture format. + * \param format incoming image pixel format. + * \param type incoming image data type. + * + * \return a pointer to a gl_texture_format object which describes the + * choosen texture format, or NULL on failure. + * + * This is called via dd_function_table::ChooseTextureFormat. Hardware drivers + * will typically override this function with a specialized version. + */ +gl_format +_mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, + GLenum format, GLenum type ) +{ + (void) format; + (void) type; + + switch (internalFormat) { + /* shallow RGBA formats */ + case 4: + case GL_RGBA: + if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) { + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); + } else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) { + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555); + } + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + + case GL_RGBA8: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + case GL_RGB5_A1: + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555); + break; + case GL_RGBA2: + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444_REV); /* just to test another format*/ + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); + break; + case GL_RGBA4: + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444); + break; + + /* deep RGBA formats */ + case GL_RGB10_A2: + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + case GL_RGBA12: + case GL_RGBA16: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + + /* shallow RGB formats */ + case 3: + case GL_RGB: + case GL_RGB8: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); + RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + case GL_R3_G3_B2: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB332); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); + RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + case GL_RGB4: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565_REV); /* just to test another format */ + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); + break; + case GL_RGB5: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565); + break; + + /* deep RGB formats */ + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + + /* Alpha formats */ + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + RETURN_IF_SUPPORTED(MESA_FORMAT_A8); + break; + + case GL_ALPHA12: + case GL_ALPHA16: + RETURN_IF_SUPPORTED(MESA_FORMAT_A16); + RETURN_IF_SUPPORTED(MESA_FORMAT_A8); + break; + + /* Luminance formats */ + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + RETURN_IF_SUPPORTED(MESA_FORMAT_L8); + break; + + case GL_LUMINANCE12: + case GL_LUMINANCE16: + RETURN_IF_SUPPORTED(MESA_FORMAT_L16); + RETURN_IF_SUPPORTED(MESA_FORMAT_L8); + break; + + /* Luminance/Alpha formats */ + case GL_LUMINANCE4_ALPHA4: + RETURN_IF_SUPPORTED(MESA_FORMAT_AL44); + RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); + break; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); + break; + + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + RETURN_IF_SUPPORTED(MESA_FORMAT_AL1616); + RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); + break; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + RETURN_IF_SUPPORTED(MESA_FORMAT_I8); + break; + + case GL_INTENSITY12: + case GL_INTENSITY16: + RETURN_IF_SUPPORTED(MESA_FORMAT_I16); + RETURN_IF_SUPPORTED(MESA_FORMAT_I8); + break; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + case GL_COLOR_INDEX8_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_CI8); + break; + + default: + ; /* fallthrough */ + } + + if (ctx->Extensions.ARB_depth_texture) { + switch (internalFormat) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + RETURN_IF_SUPPORTED(MESA_FORMAT_Z32); + RETURN_IF_SUPPORTED(MESA_FORMAT_X8_Z24); + RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); + break; + case GL_DEPTH_COMPONENT16: + RETURN_IF_SUPPORTED(MESA_FORMAT_Z16); + RETURN_IF_SUPPORTED(MESA_FORMAT_X8_Z24); + RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); + default: + ; /* fallthrough */ + } + } + + switch (internalFormat) { + case GL_COMPRESSED_ALPHA_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_A8); + break; + case GL_COMPRESSED_LUMINANCE_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_L8); + break; + case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_AL88); + break; + case GL_COMPRESSED_INTENSITY_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_I8); + break; + case GL_COMPRESSED_RGB_ARB: + if (ctx->Extensions.EXT_texture_compression_s3tc || + ctx->Extensions.S3_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); + if (ctx->Extensions.TDFX_texture_compression_FXT1) + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888); + RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + case GL_COMPRESSED_RGBA_ARB: + if (ctx->Extensions.EXT_texture_compression_s3tc || + ctx->Extensions.S3_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */ + if (ctx->Extensions.TDFX_texture_compression_FXT1) + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + default: + ; /* fallthrough */ + } + + if (ctx->Extensions.MESA_ycbcr_texture) { + if (internalFormat == GL_YCBCR_MESA) { + if (type == GL_UNSIGNED_SHORT_8_8_MESA) + RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR); + else + RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR_REV); + } + } + +#if FEATURE_texture_fxt1 + if (ctx->Extensions.TDFX_texture_compression_FXT1) { + switch (internalFormat) { + case GL_COMPRESSED_RGB_FXT1_3DFX: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1); + break; + case GL_COMPRESSED_RGBA_FXT1_3DFX: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1); + break; + default: + ; /* fallthrough */ + } + } +#endif + +#if FEATURE_texture_s3tc + if (ctx->Extensions.EXT_texture_compression_s3tc) { + switch (internalFormat) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); + break; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT1); + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT5); + break; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.S3_s3tc) { + switch (internalFormat) { + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); + break; + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); + break; + default: + ; /* fallthrough */ + } + } +#endif + + if (ctx->Extensions.ARB_texture_float) { + switch (internalFormat) { + case GL_ALPHA16F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_ALPHA32F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_LUMINANCE16F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_LUMINANCE32F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_LUMINANCE_ALPHA16F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_LUMINANCE_ALPHA32F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_INTENSITY16F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_INTENSITY32F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_RGB16F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_RGB32F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_RGBA16F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_RGBA32F_ARB: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_texture_shared_exponent) { + switch (internalFormat) { + case GL_RGB9_E5: + ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_RGB9_E5_FLOAT]); + return MESA_FORMAT_RGB9_E5_FLOAT; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_packed_float) { + switch (internalFormat) { + case GL_R11F_G11F_B10F: + ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_R11_G11_B10_FLOAT]); + return MESA_FORMAT_R11_G11_B10_FLOAT; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_packed_depth_stencil) { + switch (internalFormat) { + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_S8); + RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24); + break; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.ATI_envmap_bumpmap) { + switch (internalFormat) { + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + RETURN_IF_SUPPORTED(MESA_FORMAT_DUDV8); + break; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_texture_snorm) { + switch (internalFormat) { + case GL_RED_SNORM: + case GL_R8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R8); + break; + case GL_RG_SNORM: + case GL_RG8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG88_REV); + break; + case GL_RGB_SNORM: + case GL_RGB8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); + /* FALLTHROUGH */ + case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_ALPHA_SNORM: + case GL_ALPHA8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_LUMINANCE_SNORM: + case GL_LUMINANCE8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_LUMINANCE_ALPHA_SNORM: + case GL_LUMINANCE8_ALPHA8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL88); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_INTENSITY_SNORM: + case GL_INTENSITY8_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_R16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R16); + break; + case GL_RG16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_GR1616); + break; + case GL_RGB16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGB_16); + /* FALLTHROUGH */ + case GL_RGBA16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_ALPHA16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_LUMINANCE16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L16); + /* FALLTHROUGH */ + case GL_LUMINANCE16_ALPHA16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL1616); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + case GL_INTENSITY16_SNORM: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); + break; + default: + ; /* fall-through */ + } + } + +#if FEATURE_EXT_texture_sRGB + if (ctx->Extensions.EXT_texture_sRGB) { + switch (internalFormat) { + case GL_SRGB_EXT: + case GL_SRGB8_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_SRGB_ALPHA_EXT: + case GL_SRGB8_ALPHA8_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_SLUMINANCE_EXT: + case GL_SLUMINANCE8_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SL8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_SLUMINANCE_ALPHA_EXT: + case GL_SLUMINANCE8_ALPHA8_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_COMPRESSED_SLUMINANCE_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SL8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_COMPRESSED_SRGB_EXT: +#if FEATURE_texture_s3tc + if (ctx->Extensions.EXT_texture_compression_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1); +#endif + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_COMPRESSED_SRGB_ALPHA_EXT: +#if FEATURE_texture_s3tc + if (ctx->Extensions.EXT_texture_compression_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */ +#endif + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; +#if FEATURE_texture_s3tc + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + if (ctx->Extensions.EXT_texture_compression_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + if (ctx->Extensions.EXT_texture_compression_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT1); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + if (ctx->Extensions.EXT_texture_compression_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + if (ctx->Extensions.EXT_texture_compression_s3tc) + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT5); + RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8); + break; +#endif + default: + ; /* fallthrough */ + } + } +#endif /* FEATURE_EXT_texture_sRGB */ + + if (ctx->Extensions.EXT_texture_integer) { + switch (internalFormat) { + case GL_RGBA32UI_EXT: + case GL_RGB32UI_EXT: + case GL_ALPHA32UI_EXT: + case GL_INTENSITY32UI_EXT: + case GL_LUMINANCE32UI_EXT: + case GL_LUMINANCE_ALPHA32UI_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32); + break; + case GL_RGBA16UI_EXT: + case GL_RGB16UI_EXT: + case GL_ALPHA16UI_EXT: + case GL_INTENSITY16UI_EXT: + case GL_LUMINANCE16UI_EXT: + case GL_LUMINANCE_ALPHA16UI_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16); + break; + case GL_RGBA8UI_EXT: + case GL_RGB8UI_EXT: + case GL_ALPHA8UI_EXT: + case GL_INTENSITY8UI_EXT: + case GL_LUMINANCE8UI_EXT: + case GL_LUMINANCE_ALPHA8UI_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8); + break; + case GL_RGBA32I_EXT: + case GL_RGB32I_EXT: + case GL_ALPHA32I_EXT: + case GL_INTENSITY32I_EXT: + case GL_LUMINANCE32I_EXT: + case GL_LUMINANCE_ALPHA32I_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32); + break; + case GL_RGBA16I_EXT: + case GL_RGB16I_EXT: + case GL_ALPHA16I_EXT: + case GL_INTENSITY16I_EXT: + case GL_LUMINANCE16I_EXT: + case GL_LUMINANCE_ALPHA16I_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16); + break; + case GL_RGBA8I_EXT: + case GL_RGB8I_EXT: + case GL_ALPHA8I_EXT: + case GL_INTENSITY8I_EXT: + case GL_LUMINANCE8I_EXT: + case GL_LUMINANCE_ALPHA8I_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8); + break; + } + } + + if (ctx->Extensions.ARB_texture_rg) { + switch (internalFormat) { + case GL_R8: + case GL_RED: + RETURN_IF_SUPPORTED(MESA_FORMAT_R8); + break; + + case GL_COMPRESSED_RED: + RETURN_IF_SUPPORTED(MESA_FORMAT_RED_RGTC1); + RETURN_IF_SUPPORTED(MESA_FORMAT_R8); + break; + + case GL_R16: + RETURN_IF_SUPPORTED(MESA_FORMAT_R16); + break; + + case GL_RG: + case GL_RG8: + RETURN_IF_SUPPORTED(MESA_FORMAT_RG88); + break; + + case GL_COMPRESSED_RG: + RETURN_IF_SUPPORTED(MESA_FORMAT_RG_RGTC2); + RETURN_IF_SUPPORTED(MESA_FORMAT_RG88); + break; + + case GL_RG16: + RETURN_IF_SUPPORTED(MESA_FORMAT_RG1616); + break; + + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.ARB_texture_rg && ctx->Extensions.ARB_texture_float) { + switch (internalFormat) { + case GL_R16F: + RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_R32F: + RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_RG16F: + RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16); + RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + case GL_RG32F: + RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32); + break; + + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_texture_format_BGRA8888) { + switch (internalFormat) { + case GL_BGRA: + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.ARB_texture_compression_rgtc) { + switch (internalFormat) { + case GL_COMPRESSED_RED_RGTC1: + RETURN_IF_SUPPORTED(MESA_FORMAT_RED_RGTC1); + break; + case GL_COMPRESSED_SIGNED_RED_RGTC1: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RED_RGTC1); + break; + case GL_COMPRESSED_RG_RGTC2: + RETURN_IF_SUPPORTED(MESA_FORMAT_RG_RGTC2); + break; + case GL_COMPRESSED_SIGNED_RG_RGTC2: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG_RGTC2); + break; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_texture_compression_latc) { + switch (internalFormat) { + case GL_COMPRESSED_LUMINANCE_LATC1_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_L_LATC1); + break; + case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L_LATC1); + break; + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_LA_LATC2); + break; + case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_LA_LATC2); + break; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.ATI_texture_compression_3dc) { + switch (internalFormat) { + case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: + RETURN_IF_SUPPORTED(MESA_FORMAT_LA_LATC2); + break; + default: + ; /* fallthrough */ + } + } + + _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()"); + return MESA_FORMAT_NONE; +} + diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 8fb54c693..4ea9a483c 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -2693,7 +2693,7 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, format, type, texImage)) { /* error was recorded */ } - else if (width > 0 && height > 0 && height > 0) { + else if (width > 0 && height > 0 && depth > 0) { /* If we have a border, offset=-1 is legal. Bias by border width. */ switch (dims) { case 3: diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 510aeab82..00869979d 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -3172,7 +3172,8 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) &ctx->Extensions, ctx->API); if (ctx->Shader.Flags & GLSL_DUMP) { - printf("GLSL source for shader %d:\n", shader->Name); + printf("GLSL source for %s shader %d:\n", + _mesa_glsl_shader_target_name(state->target), shader->Name); printf("%s\n", shader->Source); } diff --git a/mesalib/src/mesa/program/prog_parameter_layout.c b/mesalib/src/mesa/program/prog_parameter_layout.c index d7dc97edb..90a977108 100644 --- a/mesalib/src/mesa/program/prog_parameter_layout.c +++ b/mesalib/src/mesa/program/prog_parameter_layout.c @@ -207,6 +207,7 @@ _mesa_layout_parameters(struct asm_parser_state *state) } } + layout->StateFlags = state->prog->Parameters->StateFlags; _mesa_free_parameter_list(state->prog->Parameters); state->prog->Parameters = layout; diff --git a/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c b/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c index 57430b36f..95b706cb9 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -121,7 +121,7 @@ load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt) uint *dest; uint i, j; - transfer = pipe_get_transfer(st_context(ctx)->pipe, + transfer = pipe_get_transfer(pipe, pt, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, texSize, texSize); dest = (uint *) pipe_transfer_map(pipe, transfer); diff --git a/mesalib/src/mesa/state_tracker/st_cb_accum.c b/mesalib/src/mesa/state_tracker/st_cb_accum.c index 66e5312d9..3e3659d15 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_accum.c +++ b/mesalib/src/mesa/state_tracker/st_cb_accum.c @@ -1,347 +1,347 @@ -/************************************************************************** - * - * 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: - * Brian Paul - */ - -#include "main/imports.h" -#include "main/image.h" -#include "main/macros.h" -#include "main/mfeatures.h" - -#include "st_debug.h" -#include "st_context.h" -#include "st_cb_accum.h" -#include "st_cb_fbo.h" -#include "st_texture.h" -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "util/u_format.h" -#include "util/u_inlines.h" -#include "util/u_tile.h" - - -#if FEATURE_accum - -/** - * For hardware that supports deep color buffers, we could accelerate - * most/all the accum operations with blending/texturing. - * For now, just use the get/put_tile() functions and do things in software. - */ - - -void -st_clear_accum_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb) -{ - struct st_renderbuffer *acc_strb = st_renderbuffer(rb); - const GLint xpos = ctx->DrawBuffer->_Xmin; - const GLint ypos = ctx->DrawBuffer->_Ymin; - const GLint width = ctx->DrawBuffer->_Xmax - xpos; - const GLint height = ctx->DrawBuffer->_Ymax - ypos; - size_t stride = acc_strb->stride; - GLubyte *data = acc_strb->data; - - if(!data) - return; - - switch (acc_strb->format) { - case PIPE_FORMAT_R16G16B16A16_SNORM: - { - GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]); - GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]); - GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]); - GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]); - int i, j; - for (i = 0; i < height; i++) { - GLshort *dst = (GLshort *) (data + (ypos + i) * stride + xpos * 8); - for (j = 0; j < width; j++) { - dst[0] = r; - dst[1] = g; - dst[2] = b; - dst[3] = a; - dst += 4; - } - } - } - break; - default: - _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()"); - } -} - - -/** For ADD/MULT */ -static void -accum_mad(struct gl_context *ctx, GLfloat scale, GLfloat bias, - GLint xpos, GLint ypos, GLint width, GLint height, - struct st_renderbuffer *acc_strb) -{ - size_t stride = acc_strb->stride; - GLubyte *data = acc_strb->data; - - switch (acc_strb->format) { - case PIPE_FORMAT_R16G16B16A16_SNORM: - { - int i, j; - for (i = 0; i < height; i++) { - GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); - for (j = 0; j < width * 4; j++) { - float val = SHORT_TO_FLOAT(*acc) * scale + bias; - *acc++ = FLOAT_TO_SHORT(val); - } - } - } - break; - default: - _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); - } -} - - -static void -accum_accum(struct st_context *st, GLfloat value, - GLint xpos, GLint ypos, GLint width, GLint height, - struct st_renderbuffer *acc_strb, - struct st_renderbuffer *color_strb) -{ - struct pipe_context *pipe = st->pipe; - struct pipe_transfer *color_trans; - size_t stride = acc_strb->stride; - GLubyte *data = acc_strb->data; - GLfloat *buf; - - if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback processing\n", __FUNCTION__); - - color_trans = pipe_get_transfer(st->pipe, - color_strb->texture, - 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); - - buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - - pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, - util_format_linear(color_strb->texture->format), - buf); - - switch (acc_strb->format) { - case PIPE_FORMAT_R16G16B16A16_SNORM: - { - const GLfloat *color = buf; - int i, j; - for (i = 0; i < height; i++) { - GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); - for (j = 0; j < width * 4; j++) { - float val = *color++ * value; - *acc++ += FLOAT_TO_SHORT(val); - } - } - } - break; - default: - _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); - } - - free(buf); - pipe->transfer_destroy(pipe, color_trans); -} - - -static void -accum_load(struct st_context *st, GLfloat value, - GLint xpos, GLint ypos, GLint width, GLint height, - struct st_renderbuffer *acc_strb, - struct st_renderbuffer *color_strb) -{ - struct pipe_context *pipe = st->pipe; - struct pipe_transfer *color_trans; - size_t stride = acc_strb->stride; - GLubyte *data = acc_strb->data; - GLfloat *buf; - - if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback processing\n", __FUNCTION__); - - color_trans = pipe_get_transfer(st->pipe, color_strb->texture, - 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); - - buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - - pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, - util_format_linear(color_strb->texture->format), - buf); - - switch (acc_strb->format) { - case PIPE_FORMAT_R16G16B16A16_SNORM: - { - const GLfloat *color = buf; - int i, j; - for (i = 0; i < height; i++) { - GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); - for (j = 0; j < width * 4; j++) { - float val = *color++ * value; - *acc++ = FLOAT_TO_SHORT(val); - } - } - } - break; - default: - _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); - } - - free(buf); - pipe->transfer_destroy(pipe, color_trans); -} - - -static void -accum_return(struct gl_context *ctx, GLfloat value, - GLint xpos, GLint ypos, GLint width, GLint height, - struct st_renderbuffer *acc_strb, - struct st_renderbuffer *color_strb) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - const GLubyte *colormask = ctx->Color.ColorMask[0]; - enum pipe_transfer_usage usage; - struct pipe_transfer *color_trans; - size_t stride = acc_strb->stride; - const GLubyte *data = acc_strb->data; - GLfloat *buf; - enum pipe_format format = util_format_linear(color_strb->texture->format); - - if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback processing\n", __FUNCTION__); - - buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - - if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) - usage = PIPE_TRANSFER_READ_WRITE; - else - usage = PIPE_TRANSFER_WRITE; - - color_trans = pipe_get_transfer(st_context(ctx)->pipe, - color_strb->texture, 0, 0, - usage, - xpos, ypos, - width, height); - - if (usage & PIPE_TRANSFER_READ) - pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, - format, buf); - - switch (acc_strb->format) { - case PIPE_FORMAT_R16G16B16A16_SNORM: - { - GLfloat *color = buf; - int i, j, ch; - for (i = 0; i < height; i++) { - const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8); - for (j = 0; j < width; j++) { - for (ch = 0; ch < 4; ch++) { - if (colormask[ch]) { - GLfloat val = SHORT_TO_FLOAT(*acc * value); - *color = CLAMP(val, 0.0f, 1.0f); - } - else { - /* No change */ - } - ++acc; - ++color; - } - } - } - } - break; - default: - _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); - } - - pipe_put_tile_rgba_format(pipe, color_trans, 0, 0, width, height, - format, buf); - - free(buf); - pipe->transfer_destroy(pipe, color_trans); -} - - -static void -st_Accum(struct gl_context *ctx, GLenum op, GLfloat value) -{ - struct st_context *st = st_context(ctx); - struct st_renderbuffer *acc_strb - = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); - struct st_renderbuffer *color_strb - = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); - - const GLint xpos = ctx->DrawBuffer->_Xmin; - const GLint ypos = ctx->DrawBuffer->_Ymin; - const GLint width = ctx->DrawBuffer->_Xmax - xpos; - const GLint height = ctx->DrawBuffer->_Ymax - ypos; - - if(!acc_strb->data) - return; - - switch (op) { - case GL_ADD: - if (value != 0.0F) { - accum_mad(ctx, 1.0, value, xpos, ypos, width, height, acc_strb); - } - break; - case GL_MULT: - if (value != 1.0F) { - accum_mad(ctx, value, 0.0, xpos, ypos, width, height, acc_strb); - } - break; - case GL_ACCUM: - if (value != 0.0F) { - accum_accum(st, value, xpos, ypos, width, height, acc_strb, color_strb); - } - break; - case GL_LOAD: - accum_load(st, value, xpos, ypos, width, height, acc_strb, color_strb); - break; - case GL_RETURN: - accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb); - break; - default: - assert(0); - } -} - - - -void st_init_accum_functions(struct dd_function_table *functions) -{ - functions->Accum = st_Accum; -} - -#endif /* FEATURE_accum */ +/************************************************************************** + * + * 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: + * Brian Paul + */ + +#include "main/imports.h" +#include "main/image.h" +#include "main/macros.h" +#include "main/mfeatures.h" + +#include "st_debug.h" +#include "st_context.h" +#include "st_cb_accum.h" +#include "st_cb_fbo.h" +#include "st_texture.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_tile.h" + + +#if FEATURE_accum + +/** + * For hardware that supports deep color buffers, we could accelerate + * most/all the accum operations with blending/texturing. + * For now, just use the get/put_tile() functions and do things in software. + */ + + +void +st_clear_accum_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb) +{ + struct st_renderbuffer *acc_strb = st_renderbuffer(rb); + const GLint xpos = ctx->DrawBuffer->_Xmin; + const GLint ypos = ctx->DrawBuffer->_Ymin; + const GLint width = ctx->DrawBuffer->_Xmax - xpos; + const GLint height = ctx->DrawBuffer->_Ymax - ypos; + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; + + if(!data) + return; + + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]); + GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]); + GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]); + GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]); + int i, j; + for (i = 0; i < height; i++) { + GLshort *dst = (GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width; j++) { + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = a; + dst += 4; + } + } + } + break; + default: + _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()"); + } +} + + +/** For ADD/MULT */ +static void +accum_mad(struct gl_context *ctx, GLfloat scale, GLfloat bias, + GLint xpos, GLint ypos, GLint width, GLint height, + struct st_renderbuffer *acc_strb) +{ + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; + + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + int i, j; + for (i = 0; i < height; i++) { + GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width * 4; j++) { + float val = SHORT_TO_FLOAT(*acc) * scale + bias; + *acc++ = FLOAT_TO_SHORT(val); + } + } + } + break; + default: + _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); + } +} + + +static void +accum_accum(struct st_context *st, GLfloat value, + GLint xpos, GLint ypos, GLint width, GLint height, + struct st_renderbuffer *acc_strb, + struct st_renderbuffer *color_strb) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_transfer *color_trans; + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; + GLfloat *buf; + + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + + color_trans = pipe_get_transfer(st->pipe, + color_strb->texture, + 0, 0, + PIPE_TRANSFER_READ, xpos, ypos, + width, height); + + buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); + + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); + + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + const GLfloat *color = buf; + int i, j; + for (i = 0; i < height; i++) { + GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width * 4; j++) { + float val = *color++ * value; + *acc++ += FLOAT_TO_SHORT(val); + } + } + } + break; + default: + _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); + } + + free(buf); + pipe->transfer_destroy(pipe, color_trans); +} + + +static void +accum_load(struct st_context *st, GLfloat value, + GLint xpos, GLint ypos, GLint width, GLint height, + struct st_renderbuffer *acc_strb, + struct st_renderbuffer *color_strb) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_transfer *color_trans; + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; + GLfloat *buf; + + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + + color_trans = pipe_get_transfer(st->pipe, color_strb->texture, + 0, 0, + PIPE_TRANSFER_READ, xpos, ypos, + width, height); + + buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); + + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); + + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + const GLfloat *color = buf; + int i, j; + for (i = 0; i < height; i++) { + GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width * 4; j++) { + float val = *color++ * value; + *acc++ = FLOAT_TO_SHORT(val); + } + } + } + break; + default: + _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); + } + + free(buf); + pipe->transfer_destroy(pipe, color_trans); +} + + +static void +accum_return(struct gl_context *ctx, GLfloat value, + GLint xpos, GLint ypos, GLint width, GLint height, + struct st_renderbuffer *acc_strb, + struct st_renderbuffer *color_strb) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + const GLubyte *colormask = ctx->Color.ColorMask[0]; + enum pipe_transfer_usage usage; + struct pipe_transfer *color_trans; + size_t stride = acc_strb->stride; + const GLubyte *data = acc_strb->data; + GLfloat *buf; + enum pipe_format format = util_format_linear(color_strb->texture->format); + + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + + buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); + + if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) + usage = PIPE_TRANSFER_READ_WRITE; + else + usage = PIPE_TRANSFER_WRITE; + + color_trans = pipe_get_transfer(pipe, + color_strb->texture, 0, 0, + usage, + xpos, ypos, + width, height); + + if (usage & PIPE_TRANSFER_READ) + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); + + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + GLfloat *color = buf; + int i, j, ch; + for (i = 0; i < height; i++) { + const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width; j++) { + for (ch = 0; ch < 4; ch++) { + if (colormask[ch]) { + GLfloat val = SHORT_TO_FLOAT(*acc * value); + *color = CLAMP(val, 0.0f, 1.0f); + } + else { + /* No change */ + } + ++acc; + ++color; + } + } + } + } + break; + default: + _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); + } + + pipe_put_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); + + free(buf); + pipe->transfer_destroy(pipe, color_trans); +} + + +static void +st_Accum(struct gl_context *ctx, GLenum op, GLfloat value) +{ + struct st_context *st = st_context(ctx); + struct st_renderbuffer *acc_strb + = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); + struct st_renderbuffer *color_strb + = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); + + const GLint xpos = ctx->DrawBuffer->_Xmin; + const GLint ypos = ctx->DrawBuffer->_Ymin; + const GLint width = ctx->DrawBuffer->_Xmax - xpos; + const GLint height = ctx->DrawBuffer->_Ymax - ypos; + + if(!acc_strb->data) + return; + + switch (op) { + case GL_ADD: + if (value != 0.0F) { + accum_mad(ctx, 1.0, value, xpos, ypos, width, height, acc_strb); + } + break; + case GL_MULT: + if (value != 1.0F) { + accum_mad(ctx, value, 0.0, xpos, ypos, width, height, acc_strb); + } + break; + case GL_ACCUM: + if (value != 0.0F) { + accum_accum(st, value, xpos, ypos, width, height, acc_strb, color_strb); + } + break; + case GL_LOAD: + accum_load(st, value, xpos, ypos, width, height, acc_strb, color_strb); + break; + case GL_RETURN: + accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb); + break; + default: + assert(0); + } +} + + + +void st_init_accum_functions(struct dd_function_table *functions) +{ + functions->Accum = st_Accum; +} + +#endif /* FEATURE_accum */ diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index 1e489b29d..7374bb0ac 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -222,8 +222,7 @@ st_bufferobj_data(struct gl_context *ctx, } if (data) - pipe_buffer_write(st_context(ctx)->pipe, st_obj->buffer, 0, - size, data); + pipe_buffer_write(pipe, st_obj->buffer, 0, size, data); return GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index 9948f8d2b..29c1df4ae 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -793,9 +793,10 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, else usage = PIPE_TRANSFER_WRITE; - pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, - usage, x, y, - width, height); + pt = pipe_get_transfer(pipe, strb->texture, + strb->rtt_level, strb->rtt_face + strb->rtt_slice, + usage, x, y, + width, height); stmap = pipe_transfer_map(pipe, pt); @@ -1130,8 +1131,10 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, dsty = rbDraw->Base.Height - dsty - height; } - ptDraw = pipe_get_transfer(st_context(ctx)->pipe, - rbDraw->texture, 0, 0, + ptDraw = pipe_get_transfer(pipe, + rbDraw->texture, + rbDraw->rtt_level, + rbDraw->rtt_face + rbDraw->rtt_slice, usage, dstx, dsty, width, height); @@ -1291,8 +1294,10 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, u_box_2d(readX, readY, readW, readH, &srcBox); pipe->resource_copy_region(pipe, - rbDraw->texture, 0, drawX, drawY, 0, - rbRead->texture, 0, &srcBox); + rbDraw->texture, + rbDraw->rtt_level, drawX, drawY, 0, + rbRead->texture, + rbRead->rtt_level, &srcBox); return GL_TRUE; } } @@ -1444,10 +1449,10 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, /* copy source framebuffer surface into mipmap/texture */ pipe->resource_copy_region(pipe, pt, /* dest tex */ - 0, + 0, /* dest lvl */ pack.SkipPixels, pack.SkipRows, 0, /* dest pos */ rbRead->texture, /* src tex */ - 0, + rbRead->rtt_level, /* src lvl */ &src_box); } @@ -1455,7 +1460,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = pipe_get_transfer(st->pipe, rbRead->texture, - 0, 0, /* level, layer */ + rbRead->rtt_level, + rbRead->rtt_face + rbRead->rtt_slice, PIPE_TRANSFER_READ, readX, readY, readW, readH); struct pipe_transfer *ptTex; diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index 2a63799bd..67926e392 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -82,7 +82,8 @@ st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, /* Create a read transfer from the renderbuffer's texture */ pt = pipe_get_transfer(pipe, strb->texture, - 0, 0, + strb->rtt_level, + strb->rtt_face + strb->rtt_slice, PIPE_TRANSFER_READ, x, y, width, height); @@ -250,7 +251,8 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, } trans = pipe_get_transfer(pipe, strb->texture, - 0, 0, + strb->rtt_level, + strb->rtt_face + strb->rtt_slice, PIPE_TRANSFER_READ, x, y, width, height); if (!trans) { @@ -445,7 +447,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h /* Create a read transfer from the renderbuffer's texture */ trans = pipe_get_transfer(pipe, strb->texture, - 0, 0, + strb->rtt_level, /* level */ + strb->rtt_face + strb->rtt_slice, /* layer */ PIPE_TRANSFER_READ, x, y, width, height); diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index a27c30e51..9d824b46c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -807,7 +807,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, PIPE_TEX_MIPFILTER_NEAREST); /* map the dst_surface so we can read from it */ - tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, + tex_xfer = pipe_get_transfer(pipe, dst_texture, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height); @@ -1228,7 +1228,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, srcY = strb->Base.Height - srcY - height; } - src_trans = pipe_get_transfer(st_context(ctx)->pipe, + src_trans = pipe_get_transfer(pipe, strb->texture, 0, 0, PIPE_TRANSFER_READ, diff --git a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c index 2c37c1107..b34794f1b 100644 --- a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c +++ b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c @@ -1,451 +1,451 @@ -/************************************************************************** - * - * Copyright 2008 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. - * - **************************************************************************/ - - -#include "main/imports.h" -#include "main/mipmap.h" -#include "main/teximage.h" - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_gen_mipmap.h" - -#include "st_debug.h" -#include "st_context.h" -#include "st_texture.h" -#include "st_gen_mipmap.h" -#include "st_cb_texture.h" - - -/** - * one-time init for generate mipmap - * XXX Note: there may be other times we need no-op/simple state like this. - * In that case, some code refactoring would be good. - */ -void -st_init_generate_mipmap(struct st_context *st) -{ - st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context); -} - - -void -st_destroy_generate_mipmap(struct st_context *st) -{ - util_destroy_gen_mipmap(st->gen_mipmap); - st->gen_mipmap = NULL; -} - - -/** - * Generate mipmap levels using hardware rendering. - * \return TRUE if successful, FALSE if not possible - */ -static boolean -st_render_mipmap(struct st_context *st, - GLenum target, - struct st_texture_object *stObj, - uint baseLevel, uint lastLevel) -{ - struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; - struct pipe_sampler_view *psv = st_get_texture_sampler_view(stObj, pipe); - const uint face = _mesa_tex_target_to_face(target); - - assert(psv->texture == stObj->pt); -#if 0 - assert(target != GL_TEXTURE_3D); /* implemented but untested */ -#endif - - /* check if we can render in the texture's format */ - /* XXX should probably kill this and always use util_gen_mipmap - since this implements a sw fallback as well */ - if (!screen->is_format_supported(screen, psv->format, psv->texture->target, - 0, PIPE_BIND_RENDER_TARGET)) { - return FALSE; - } - - util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel, - PIPE_TEX_FILTER_LINEAR); - - return TRUE; -} - - -/** - * Helper function to decompress an image. The result is a 32-bpp RGBA - * image with stride==width. - */ -static void -decompress_image(enum pipe_format format, int datatype, - const uint8_t *src, void *dst, - unsigned width, unsigned height, unsigned src_stride) -{ - const struct util_format_description *desc = util_format_description(format); - const uint bw = util_format_get_blockwidth(format); - const uint bh = util_format_get_blockheight(format); - uint dst_stride = 4 * MAX2(width, bw); - - if (datatype == GL_FLOAT) { - desc->unpack_rgba_float((float *)dst, dst_stride * sizeof(GLfloat), src, src_stride, width, height); - if (width < bw || height < bh) { - float *dst_p = (float *)dst; - /* We're decompressing an image smaller than the compression - * block size. We don't want garbage pixel values in the region - * outside (width x height) so replicate pixels from the (width - * x height) region to fill out the (bw x bh) block size. - */ - uint x, y; - for (y = 0; y < bh; y++) { - for (x = 0; x < bw; x++) { - if (x >= width || y >= height) { - uint p = (y * bw + x) * 4; - dst_p[p + 0] = dst_p[0]; - dst_p[p + 1] = dst_p[1]; - dst_p[p + 2] = dst_p[2]; - dst_p[p + 3] = dst_p[3]; - } - } - } - } - } else { - desc->unpack_rgba_8unorm((uint8_t *)dst, dst_stride, src, src_stride, width, height); - if (width < bw || height < bh) { - uint8_t *dst_p = (uint8_t *)dst; - /* We're decompressing an image smaller than the compression - * block size. We don't want garbage pixel values in the region - * outside (width x height) so replicate pixels from the (width - * x height) region to fill out the (bw x bh) block size. - */ - uint x, y; - for (y = 0; y < bh; y++) { - for (x = 0; x < bw; x++) { - if (x >= width || y >= height) { - uint p = (y * bw + x) * 4; - dst_p[p + 0] = dst_p[0]; - dst_p[p + 1] = dst_p[1]; - dst_p[p + 2] = dst_p[2]; - dst_p[p + 3] = dst_p[3]; - } - } - } - } - } -} - -/** - * Helper function to compress an image. The source is a 32-bpp RGBA image - * with stride==width. - */ -static void -compress_image(enum pipe_format format, int datatype, - const void *src, uint8_t *dst, - unsigned width, unsigned height, unsigned dst_stride) -{ - const struct util_format_description *desc = util_format_description(format); - const uint src_stride = 4 * width; - - if (datatype == GL_FLOAT) - desc->pack_rgba_float(dst, dst_stride, (GLfloat *)src, src_stride * sizeof(GLfloat), width, height); - else - desc->pack_rgba_8unorm(dst, dst_stride, (uint8_t *)src, src_stride, width, height); -} - - -/** - * Software fallback for generate mipmap levels. - */ -static void -fallback_generate_mipmap(struct gl_context *ctx, GLenum target, - struct gl_texture_object *texObj) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - struct pipe_resource *pt = st_get_texobj_resource(texObj); - const uint baseLevel = texObj->BaseLevel; - const uint lastLevel = pt->last_level; - const uint face = _mesa_tex_target_to_face(target); - uint dstLevel; - GLenum datatype; - GLuint comps; - GLboolean compressed; - - if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback processing\n", __FUNCTION__); - - assert(target != GL_TEXTURE_3D); /* not done yet */ - - compressed = - _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat); - - if (compressed) { - GLenum type = - _mesa_get_format_datatype(texObj->Image[face][baseLevel]->TexFormat); - - datatype = type == GL_UNSIGNED_NORMALIZED ? GL_UNSIGNED_BYTE : GL_FLOAT; - comps = 4; - } - else { - _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat, - &datatype, &comps); - assert(comps > 0 && "bad texture format in fallback_generate_mipmap()"); - } - - for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { - const uint srcLevel = dstLevel - 1; - const uint srcWidth = u_minify(pt->width0, srcLevel); - const uint srcHeight = u_minify(pt->height0, srcLevel); - const uint srcDepth = u_minify(pt->depth0, srcLevel); - const uint dstWidth = u_minify(pt->width0, dstLevel); - const uint dstHeight = u_minify(pt->height0, dstLevel); - const uint dstDepth = u_minify(pt->depth0, dstLevel); - struct pipe_transfer *srcTrans, *dstTrans; - const ubyte *srcData; - ubyte *dstData; - int srcStride, dstStride; - - srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, srcLevel, - face, - PIPE_TRANSFER_READ, 0, 0, - srcWidth, srcHeight); - - dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, dstLevel, - face, - PIPE_TRANSFER_WRITE, 0, 0, - dstWidth, dstHeight); - - srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans); - dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans); - - srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format); - dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format); - - /* this cannot work correctly for 3d since it does - not respect layerStride. */ - if (compressed) { - const enum pipe_format format = pt->format; - const uint bw = util_format_get_blockwidth(format); - const uint bh = util_format_get_blockheight(format); - const uint srcWidth2 = align(srcWidth, bw); - const uint srcHeight2 = align(srcHeight, bh); - const uint dstWidth2 = align(dstWidth, bw); - const uint dstHeight2 = align(dstHeight, bh); - uint8_t *srcTemp, *dstTemp; - - assert(comps == 4); - - srcTemp = malloc(srcWidth2 * srcHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); - dstTemp = malloc(dstWidth2 * dstHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); - - /* decompress the src image: srcData -> srcTemp */ - decompress_image(format, datatype, srcData, srcTemp, srcWidth2, srcHeight2, srcTrans->stride); - - _mesa_generate_mipmap_level(target, datatype, comps, - 0 /*border*/, - srcWidth2, srcHeight2, srcDepth, - srcTemp, - srcWidth2, /* stride in texels */ - dstWidth2, dstHeight2, dstDepth, - dstTemp, - dstWidth2); /* stride in texels */ - - /* compress the new image: dstTemp -> dstData */ - compress_image(format, datatype, dstTemp, dstData, dstWidth2, dstHeight2, dstTrans->stride); - - free(srcTemp); - free(dstTemp); - } - else { - _mesa_generate_mipmap_level(target, datatype, comps, - 0 /*border*/, - srcWidth, srcHeight, srcDepth, - srcData, - srcStride, /* stride in texels */ - dstWidth, dstHeight, dstDepth, - dstData, - dstStride); /* stride in texels */ - } - - pipe_transfer_unmap(pipe, srcTrans); - pipe_transfer_unmap(pipe, dstTrans); - - pipe->transfer_destroy(pipe, srcTrans); - pipe->transfer_destroy(pipe, dstTrans); - } -} - - -/** - * Compute the expected number of mipmap levels in the texture given - * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/ - * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap - * levels should be generated. - */ -static GLuint -compute_num_levels(struct gl_context *ctx, - struct gl_texture_object *texObj, - GLenum target) -{ - if (target == GL_TEXTURE_RECTANGLE_ARB) { - return 1; - } - else { - const struct gl_texture_image *baseImage = - _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel); - GLuint size, numLevels; - - size = MAX2(baseImage->Width2, baseImage->Height2); - size = MAX2(size, baseImage->Depth2); - - numLevels = texObj->BaseLevel; - - while (size > 0) { - numLevels++; - size >>= 1; - } - - numLevels = MIN2(numLevels, texObj->MaxLevel + 1); - - assert(numLevels >= 1); - - return numLevels; - } -} - - -/** - * Called via ctx->Driver.GenerateMipmap(). - */ -void -st_generate_mipmap(struct gl_context *ctx, GLenum target, - struct gl_texture_object *texObj) -{ - struct st_context *st = st_context(ctx); - struct st_texture_object *stObj = st_texture_object(texObj); - struct pipe_resource *pt = st_get_texobj_resource(texObj); - const uint baseLevel = texObj->BaseLevel; - uint lastLevel; - uint dstLevel; - - if (!pt) - return; - - /* not sure if this ultimately actually should work, - but we're not supporting multisampled textures yet. */ - assert(pt->nr_samples < 2); - - /* find expected last mipmap level to generate*/ - lastLevel = compute_num_levels(ctx, texObj, target) - 1; - - if (lastLevel == 0) - return; - - /* The texture isn't in a "complete" state yet so set the expected - * lastLevel here, since it won't get done in st_finalize_texture(). - */ - stObj->lastLevel = lastLevel; - - if (pt->last_level < lastLevel) { - /* The current gallium texture doesn't have space for all the - * mipmap levels we need to generate. So allocate a new texture. - */ - struct pipe_resource *oldTex = stObj->pt; - - /* create new texture with space for more levels */ - stObj->pt = st_texture_create(st, - oldTex->target, - oldTex->format, - lastLevel, - oldTex->width0, - oldTex->height0, - oldTex->depth0, - oldTex->array_size, - oldTex->bind); - - /* This will copy the old texture's base image into the new texture - * which we just allocated. - */ - st_finalize_texture(ctx, st->pipe, texObj); - - /* release the old tex (will likely be freed too) */ - pipe_resource_reference(&oldTex, NULL); - pipe_sampler_view_reference(&stObj->sampler_view, NULL); - } - else { - /* Make sure that the base texture image data is present in the - * texture buffer. - */ - st_finalize_texture(ctx, st->pipe, texObj); - } - - pt = stObj->pt; - - assert(pt->last_level >= lastLevel); - - /* Try to generate the mipmap by rendering/texturing. If that fails, - * use the software fallback. - */ - if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) { - /* since the util code actually also has a fallback, should - probably make it never fail and kill this */ - fallback_generate_mipmap(ctx, target, texObj); - } - - /* Fill in the Mesa gl_texture_image fields */ - for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { - const uint srcLevel = dstLevel - 1; - const struct gl_texture_image *srcImage - = _mesa_get_tex_image(ctx, texObj, target, srcLevel); - struct gl_texture_image *dstImage; - struct st_texture_image *stImage; - uint dstWidth = u_minify(pt->width0, dstLevel); - uint dstHeight = u_minify(pt->height0, dstLevel); - uint dstDepth = u_minify(pt->depth0, dstLevel); - uint border = srcImage->Border; - - dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); - 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); - - stImage = st_texture_image(dstImage); - stImage->level = dstLevel; - - pipe_resource_reference(&stImage->pt, pt); - } -} +/************************************************************************** + * + * Copyright 2008 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. + * + **************************************************************************/ + + +#include "main/imports.h" +#include "main/mipmap.h" +#include "main/teximage.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_gen_mipmap.h" + +#include "st_debug.h" +#include "st_context.h" +#include "st_texture.h" +#include "st_gen_mipmap.h" +#include "st_cb_texture.h" + + +/** + * one-time init for generate mipmap + * XXX Note: there may be other times we need no-op/simple state like this. + * In that case, some code refactoring would be good. + */ +void +st_init_generate_mipmap(struct st_context *st) +{ + st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context); +} + + +void +st_destroy_generate_mipmap(struct st_context *st) +{ + util_destroy_gen_mipmap(st->gen_mipmap); + st->gen_mipmap = NULL; +} + + +/** + * Generate mipmap levels using hardware rendering. + * \return TRUE if successful, FALSE if not possible + */ +static boolean +st_render_mipmap(struct st_context *st, + GLenum target, + struct st_texture_object *stObj, + uint baseLevel, uint lastLevel) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_sampler_view *psv = st_get_texture_sampler_view(stObj, pipe); + const uint face = _mesa_tex_target_to_face(target); + + assert(psv->texture == stObj->pt); +#if 0 + assert(target != GL_TEXTURE_3D); /* implemented but untested */ +#endif + + /* check if we can render in the texture's format */ + /* XXX should probably kill this and always use util_gen_mipmap + since this implements a sw fallback as well */ + if (!screen->is_format_supported(screen, psv->format, psv->texture->target, + 0, PIPE_BIND_RENDER_TARGET)) { + return FALSE; + } + + util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel, + PIPE_TEX_FILTER_LINEAR); + + return TRUE; +} + + +/** + * Helper function to decompress an image. The result is a 32-bpp RGBA + * image with stride==width. + */ +static void +decompress_image(enum pipe_format format, int datatype, + const uint8_t *src, void *dst, + unsigned width, unsigned height, unsigned src_stride) +{ + const struct util_format_description *desc = util_format_description(format); + const uint bw = util_format_get_blockwidth(format); + const uint bh = util_format_get_blockheight(format); + uint dst_stride = 4 * MAX2(width, bw); + + if (datatype == GL_FLOAT) { + desc->unpack_rgba_float((float *)dst, dst_stride * sizeof(GLfloat), src, src_stride, width, height); + if (width < bw || height < bh) { + float *dst_p = (float *)dst; + /* We're decompressing an image smaller than the compression + * block size. We don't want garbage pixel values in the region + * outside (width x height) so replicate pixels from the (width + * x height) region to fill out the (bw x bh) block size. + */ + uint x, y; + for (y = 0; y < bh; y++) { + for (x = 0; x < bw; x++) { + if (x >= width || y >= height) { + uint p = (y * bw + x) * 4; + dst_p[p + 0] = dst_p[0]; + dst_p[p + 1] = dst_p[1]; + dst_p[p + 2] = dst_p[2]; + dst_p[p + 3] = dst_p[3]; + } + } + } + } + } else { + desc->unpack_rgba_8unorm((uint8_t *)dst, dst_stride, src, src_stride, width, height); + if (width < bw || height < bh) { + uint8_t *dst_p = (uint8_t *)dst; + /* We're decompressing an image smaller than the compression + * block size. We don't want garbage pixel values in the region + * outside (width x height) so replicate pixels from the (width + * x height) region to fill out the (bw x bh) block size. + */ + uint x, y; + for (y = 0; y < bh; y++) { + for (x = 0; x < bw; x++) { + if (x >= width || y >= height) { + uint p = (y * bw + x) * 4; + dst_p[p + 0] = dst_p[0]; + dst_p[p + 1] = dst_p[1]; + dst_p[p + 2] = dst_p[2]; + dst_p[p + 3] = dst_p[3]; + } + } + } + } + } +} + +/** + * Helper function to compress an image. The source is a 32-bpp RGBA image + * with stride==width. + */ +static void +compress_image(enum pipe_format format, int datatype, + const void *src, uint8_t *dst, + unsigned width, unsigned height, unsigned dst_stride) +{ + const struct util_format_description *desc = util_format_description(format); + const uint src_stride = 4 * width; + + if (datatype == GL_FLOAT) + desc->pack_rgba_float(dst, dst_stride, (GLfloat *)src, src_stride * sizeof(GLfloat), width, height); + else + desc->pack_rgba_8unorm(dst, dst_stride, (uint8_t *)src, src_stride, width, height); +} + + +/** + * Software fallback for generate mipmap levels. + */ +static void +fallback_generate_mipmap(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + struct pipe_resource *pt = st_get_texobj_resource(texObj); + const uint baseLevel = texObj->BaseLevel; + const uint lastLevel = pt->last_level; + const uint face = _mesa_tex_target_to_face(target); + uint dstLevel; + GLenum datatype; + GLuint comps; + GLboolean compressed; + + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + + assert(target != GL_TEXTURE_3D); /* not done yet */ + + compressed = + _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat); + + if (compressed) { + GLenum type = + _mesa_get_format_datatype(texObj->Image[face][baseLevel]->TexFormat); + + datatype = type == GL_UNSIGNED_NORMALIZED ? GL_UNSIGNED_BYTE : GL_FLOAT; + comps = 4; + } + else { + _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat, + &datatype, &comps); + assert(comps > 0 && "bad texture format in fallback_generate_mipmap()"); + } + + for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { + const uint srcLevel = dstLevel - 1; + const uint srcWidth = u_minify(pt->width0, srcLevel); + const uint srcHeight = u_minify(pt->height0, srcLevel); + const uint srcDepth = u_minify(pt->depth0, srcLevel); + const uint dstWidth = u_minify(pt->width0, dstLevel); + const uint dstHeight = u_minify(pt->height0, dstLevel); + const uint dstDepth = u_minify(pt->depth0, dstLevel); + struct pipe_transfer *srcTrans, *dstTrans; + const ubyte *srcData; + ubyte *dstData; + int srcStride, dstStride; + + srcTrans = pipe_get_transfer(pipe, pt, srcLevel, + face, + PIPE_TRANSFER_READ, 0, 0, + srcWidth, srcHeight); + + dstTrans = pipe_get_transfer(pipe, pt, dstLevel, + face, + PIPE_TRANSFER_WRITE, 0, 0, + dstWidth, dstHeight); + + srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans); + dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans); + + srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format); + dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format); + + /* this cannot work correctly for 3d since it does + not respect layerStride. */ + if (compressed) { + const enum pipe_format format = pt->format; + const uint bw = util_format_get_blockwidth(format); + const uint bh = util_format_get_blockheight(format); + const uint srcWidth2 = align(srcWidth, bw); + const uint srcHeight2 = align(srcHeight, bh); + const uint dstWidth2 = align(dstWidth, bw); + const uint dstHeight2 = align(dstHeight, bh); + uint8_t *srcTemp, *dstTemp; + + assert(comps == 4); + + srcTemp = malloc(srcWidth2 * srcHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); + dstTemp = malloc(dstWidth2 * dstHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); + + /* decompress the src image: srcData -> srcTemp */ + decompress_image(format, datatype, srcData, srcTemp, srcWidth2, srcHeight2, srcTrans->stride); + + _mesa_generate_mipmap_level(target, datatype, comps, + 0 /*border*/, + srcWidth2, srcHeight2, srcDepth, + srcTemp, + srcWidth2, /* stride in texels */ + dstWidth2, dstHeight2, dstDepth, + dstTemp, + dstWidth2); /* stride in texels */ + + /* compress the new image: dstTemp -> dstData */ + compress_image(format, datatype, dstTemp, dstData, dstWidth2, dstHeight2, dstTrans->stride); + + free(srcTemp); + free(dstTemp); + } + else { + _mesa_generate_mipmap_level(target, datatype, comps, + 0 /*border*/, + srcWidth, srcHeight, srcDepth, + srcData, + srcStride, /* stride in texels */ + dstWidth, dstHeight, dstDepth, + dstData, + dstStride); /* stride in texels */ + } + + pipe_transfer_unmap(pipe, srcTrans); + pipe_transfer_unmap(pipe, dstTrans); + + pipe->transfer_destroy(pipe, srcTrans); + pipe->transfer_destroy(pipe, dstTrans); + } +} + + +/** + * Compute the expected number of mipmap levels in the texture given + * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/ + * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap + * levels should be generated. + */ +static GLuint +compute_num_levels(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target) +{ + if (target == GL_TEXTURE_RECTANGLE_ARB) { + return 1; + } + else { + const struct gl_texture_image *baseImage = + _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel); + GLuint size, numLevels; + + size = MAX2(baseImage->Width2, baseImage->Height2); + size = MAX2(size, baseImage->Depth2); + + numLevels = texObj->BaseLevel; + + while (size > 0) { + numLevels++; + size >>= 1; + } + + numLevels = MIN2(numLevels, texObj->MaxLevel + 1); + + assert(numLevels >= 1); + + return numLevels; + } +} + + +/** + * Called via ctx->Driver.GenerateMipmap(). + */ +void +st_generate_mipmap(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj) +{ + struct st_context *st = st_context(ctx); + struct st_texture_object *stObj = st_texture_object(texObj); + struct pipe_resource *pt = st_get_texobj_resource(texObj); + const uint baseLevel = texObj->BaseLevel; + uint lastLevel; + uint dstLevel; + + if (!pt) + return; + + /* not sure if this ultimately actually should work, + but we're not supporting multisampled textures yet. */ + assert(pt->nr_samples < 2); + + /* find expected last mipmap level to generate*/ + lastLevel = compute_num_levels(ctx, texObj, target) - 1; + + if (lastLevel == 0) + return; + + /* The texture isn't in a "complete" state yet so set the expected + * lastLevel here, since it won't get done in st_finalize_texture(). + */ + stObj->lastLevel = lastLevel; + + if (pt->last_level < lastLevel) { + /* The current gallium texture doesn't have space for all the + * mipmap levels we need to generate. So allocate a new texture. + */ + struct pipe_resource *oldTex = stObj->pt; + + /* create new texture with space for more levels */ + stObj->pt = st_texture_create(st, + oldTex->target, + oldTex->format, + lastLevel, + oldTex->width0, + oldTex->height0, + oldTex->depth0, + oldTex->array_size, + oldTex->bind); + + /* This will copy the old texture's base image into the new texture + * which we just allocated. + */ + st_finalize_texture(ctx, st->pipe, texObj); + + /* release the old tex (will likely be freed too) */ + pipe_resource_reference(&oldTex, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + } + else { + /* Make sure that the base texture image data is present in the + * texture buffer. + */ + st_finalize_texture(ctx, st->pipe, texObj); + } + + pt = stObj->pt; + + assert(pt->last_level >= lastLevel); + + /* Try to generate the mipmap by rendering/texturing. If that fails, + * use the software fallback. + */ + if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) { + /* since the util code actually also has a fallback, should + probably make it never fail and kill this */ + fallback_generate_mipmap(ctx, target, texObj); + } + + /* Fill in the Mesa gl_texture_image fields */ + for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { + const uint srcLevel = dstLevel - 1; + const struct gl_texture_image *srcImage + = _mesa_get_tex_image(ctx, texObj, target, srcLevel); + struct gl_texture_image *dstImage; + struct st_texture_image *stImage; + uint dstWidth = u_minify(pt->width0, dstLevel); + uint dstHeight = u_minify(pt->height0, dstLevel); + uint dstDepth = u_minify(pt->depth0, dstLevel); + uint border = srcImage->Border; + + dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); + 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); + + stImage = st_texture_image(dstImage); + stImage->level = dstLevel; + + pipe_resource_reference(&stImage->pt, pt); + } +} -- cgit v1.2.3