aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2011-03-01 07:17:23 +0000
committermarha <marha@users.sourceforge.net>2011-03-01 07:17:23 +0000
commita18769801e521ccb5a409c377ac0a6a1141f5776 (patch)
treecfc3429a80c2f996cb5592512acdebe7719d608c /mesalib/src/mesa/main
parentfeee2b5ceb37101bd1c4162e49805e6ad63e28ae (diff)
downloadvcxsrv-a18769801e521ccb5a409c377ac0a6a1141f5776.tar.gz
vcxsrv-a18769801e521ccb5a409c377ac0a6a1141f5776.tar.bz2
vcxsrv-a18769801e521ccb5a409c377ac0a6a1141f5776.zip
pixman mesa git update 1 Mar 2011
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/attrib.c3121
-rw-r--r--mesalib/src/mesa/main/bufferobj.c242
-rw-r--r--mesalib/src/mesa/main/bufferobj.h339
-rw-r--r--mesalib/src/mesa/main/colortab.c1755
-rw-r--r--mesalib/src/mesa/main/dlist.c1
-rw-r--r--mesalib/src/mesa/main/drawpix.c607
-rw-r--r--mesalib/src/mesa/main/enable.c2988
-rw-r--r--mesalib/src/mesa/main/extensions.c5
-rw-r--r--mesalib/src/mesa/main/fbobject.c4932
-rw-r--r--mesalib/src/mesa/main/framebuffer.c5
-rw-r--r--mesalib/src/mesa/main/get.c5060
-rw-r--r--mesalib/src/mesa/main/mtypes.h6722
-rw-r--r--mesalib/src/mesa/main/pbo.c372
-rw-r--r--mesalib/src/mesa/main/pbo.h92
-rw-r--r--mesalib/src/mesa/main/pixel.c1400
-rw-r--r--mesalib/src/mesa/main/polygon.c644
-rw-r--r--mesalib/src/mesa/main/readpix.c487
-rw-r--r--mesalib/src/mesa/main/texcompress_rgtc.c727
-rw-r--r--mesalib/src/mesa/main/texcompress_rgtc_tmp.h376
-rw-r--r--mesalib/src/mesa/main/texgetimage.c1835
-rw-r--r--mesalib/src/mesa/main/teximage.c7004
-rw-r--r--mesalib/src/mesa/main/texstate.c1685
-rw-r--r--mesalib/src/mesa/main/texstore.c89
-rw-r--r--mesalib/src/mesa/main/texstore.h18
24 files changed, 20037 insertions, 20469 deletions
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
index f97ec08e5..ae7f633b8 100644
--- a/mesalib/src/mesa/main/attrib.c
+++ b/mesalib/src/mesa/main/attrib.c
@@ -1,1566 +1,1555 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.6
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009 VMware, Inc. 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 "imports.h"
-#include "accum.h"
-#include "arrayobj.h"
-#include "attrib.h"
-#include "blend.h"
-#include "buffers.h"
-#include "bufferobj.h"
-#include "clear.h"
-#include "colormac.h"
-#include "context.h"
-#include "depth.h"
-#include "enable.h"
-#include "enums.h"
-#include "fog.h"
-#include "hint.h"
-#include "light.h"
-#include "lines.h"
-#include "macros.h"
-#include "matrix.h"
-#include "mfeatures.h"
-#include "multisample.h"
-#include "points.h"
-#include "polygon.h"
-#include "scissor.h"
-#include "stencil.h"
-#include "texenv.h"
-#include "texgen.h"
-#include "texobj.h"
-#include "texparam.h"
-#include "texstate.h"
-#include "varray.h"
-#include "viewport.h"
-#include "mtypes.h"
-#include "main/dispatch.h"
-
-
-/**
- * glEnable()/glDisable() attribute group (GL_ENABLE_BIT).
- */
-struct gl_enable_attrib
-{
- GLboolean AlphaTest;
- GLboolean AutoNormal;
- GLboolean Blend;
- GLbitfield ClipPlanes;
- GLboolean ColorMaterial;
- GLboolean CullFace;
- GLboolean DepthClamp;
- GLboolean DepthTest;
- GLboolean Dither;
- GLboolean Fog;
- GLboolean Light[MAX_LIGHTS];
- GLboolean Lighting;
- GLboolean LineSmooth;
- GLboolean LineStipple;
- GLboolean IndexLogicOp;
- GLboolean ColorLogicOp;
-
- GLboolean Map1Color4;
- GLboolean Map1Index;
- GLboolean Map1Normal;
- GLboolean Map1TextureCoord1;
- GLboolean Map1TextureCoord2;
- GLboolean Map1TextureCoord3;
- GLboolean Map1TextureCoord4;
- GLboolean Map1Vertex3;
- GLboolean Map1Vertex4;
- GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
- GLboolean Map2Color4;
- GLboolean Map2Index;
- GLboolean Map2Normal;
- GLboolean Map2TextureCoord1;
- GLboolean Map2TextureCoord2;
- GLboolean Map2TextureCoord3;
- GLboolean Map2TextureCoord4;
- GLboolean Map2Vertex3;
- GLboolean Map2Vertex4;
- GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
-
- GLboolean Normalize;
- GLboolean PixelTexture;
- GLboolean PointSmooth;
- GLboolean PolygonOffsetPoint;
- GLboolean PolygonOffsetLine;
- GLboolean PolygonOffsetFill;
- GLboolean PolygonSmooth;
- GLboolean PolygonStipple;
- GLboolean RescaleNormals;
- GLboolean Scissor;
- GLboolean Stencil;
- GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */
- GLboolean MultisampleEnabled; /* GL_ARB_multisample */
- GLboolean SampleAlphaToCoverage; /* GL_ARB_multisample */
- GLboolean SampleAlphaToOne; /* GL_ARB_multisample */
- GLboolean SampleCoverage; /* GL_ARB_multisample */
- GLboolean SampleCoverageInvert; /* GL_ARB_multisample */
- GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */
-
- GLbitfield Texture[MAX_TEXTURE_UNITS];
- GLbitfield TexGen[MAX_TEXTURE_UNITS];
-
- /* SGI_texture_color_table */
- GLboolean TextureColorTable[MAX_TEXTURE_UNITS];
-
- /* GL_ARB_vertex_program / GL_NV_vertex_program */
- GLboolean VertexProgram;
- GLboolean VertexProgramPointSize;
- GLboolean VertexProgramTwoSide;
-
- /* GL_ARB_point_sprite / GL_NV_point_sprite */
- GLboolean PointSprite;
- GLboolean FragmentShaderATI;
-};
-
-
-/**
- * Node for the attribute stack.
- */
-struct gl_attrib_node
-{
- GLbitfield kind;
- void *data;
- struct gl_attrib_node *next;
-};
-
-
-
-/**
- * Special struct for saving/restoring texture state (GL_TEXTURE_BIT)
- */
-struct texture_state
-{
- struct gl_texture_attrib Texture; /**< The usual context state */
-
- /** to save per texture object state (wrap modes, filters, etc): */
- struct gl_texture_object SavedObj[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS];
-
- /**
- * To save references to texture objects (so they don't get accidentally
- * deleted while saved in the attribute stack).
- */
- struct gl_texture_object *SavedTexRef[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS];
-};
-
-
-#if FEATURE_attrib_stack
-
-
-/**
- * Allocate new attribute node of given type/kind. Attach payload data.
- * Insert it into the linked list named by 'head'.
- */
-static void
-save_attrib_data(struct gl_attrib_node **head,
- GLbitfield kind, void *payload)
-{
- struct gl_attrib_node *n = MALLOC_STRUCT(gl_attrib_node);
- if (n) {
- n->kind = kind;
- n->data = payload;
- /* insert at head */
- n->next = *head;
- *head = n;
- }
- else {
- /* out of memory! */
- }
-}
-
-
-void GLAPIENTRY
-_mesa_PushAttrib(GLbitfield mask)
-{
- struct gl_attrib_node *head;
-
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glPushAttrib %x\n", (int) mask);
-
- if (ctx->AttribStackDepth >= MAX_ATTRIB_STACK_DEPTH) {
- _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushAttrib" );
- return;
- }
-
- /* Build linked list of attribute nodes which save all attribute */
- /* groups specified by the mask. */
- head = NULL;
-
- if (mask & GL_ACCUM_BUFFER_BIT) {
- struct gl_accum_attrib *attr;
- attr = MALLOC_STRUCT( gl_accum_attrib );
- memcpy( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) );
- save_attrib_data(&head, GL_ACCUM_BUFFER_BIT, attr);
- }
-
- if (mask & GL_COLOR_BUFFER_BIT) {
- GLuint i;
- struct gl_colorbuffer_attrib *attr;
- attr = MALLOC_STRUCT( gl_colorbuffer_attrib );
- memcpy( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) );
- /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++)
- attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i];
- save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr);
- }
-
- if (mask & GL_CURRENT_BIT) {
- struct gl_current_attrib *attr;
- FLUSH_CURRENT( ctx, 0 );
- attr = MALLOC_STRUCT( gl_current_attrib );
- memcpy( attr, &ctx->Current, sizeof(struct gl_current_attrib) );
- save_attrib_data(&head, GL_CURRENT_BIT, attr);
- }
-
- if (mask & GL_DEPTH_BUFFER_BIT) {
- struct gl_depthbuffer_attrib *attr;
- attr = MALLOC_STRUCT( gl_depthbuffer_attrib );
- memcpy( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) );
- save_attrib_data(&head, GL_DEPTH_BUFFER_BIT, attr);
- }
-
- if (mask & GL_ENABLE_BIT) {
- struct gl_enable_attrib *attr;
- GLuint i;
- attr = MALLOC_STRUCT( gl_enable_attrib );
- /* Copy enable flags from all other attributes into the enable struct. */
- attr->AlphaTest = ctx->Color.AlphaEnabled;
- attr->AutoNormal = ctx->Eval.AutoNormal;
- attr->Blend = ctx->Color.BlendEnabled;
- attr->ClipPlanes = ctx->Transform.ClipPlanesEnabled;
- attr->ColorMaterial = ctx->Light.ColorMaterialEnabled;
- attr->CullFace = ctx->Polygon.CullFlag;
- attr->DepthClamp = ctx->Transform.DepthClamp;
- attr->DepthTest = ctx->Depth.Test;
- attr->Dither = ctx->Color.DitherFlag;
- attr->Fog = ctx->Fog.Enabled;
- for (i = 0; i < ctx->Const.MaxLights; i++) {
- attr->Light[i] = ctx->Light.Light[i].Enabled;
- }
- attr->Lighting = ctx->Light.Enabled;
- attr->LineSmooth = ctx->Line.SmoothFlag;
- attr->LineStipple = ctx->Line.StippleFlag;
- attr->IndexLogicOp = ctx->Color.IndexLogicOpEnabled;
- attr->ColorLogicOp = ctx->Color.ColorLogicOpEnabled;
- attr->Map1Color4 = ctx->Eval.Map1Color4;
- attr->Map1Index = ctx->Eval.Map1Index;
- attr->Map1Normal = ctx->Eval.Map1Normal;
- attr->Map1TextureCoord1 = ctx->Eval.Map1TextureCoord1;
- attr->Map1TextureCoord2 = ctx->Eval.Map1TextureCoord2;
- attr->Map1TextureCoord3 = ctx->Eval.Map1TextureCoord3;
- attr->Map1TextureCoord4 = ctx->Eval.Map1TextureCoord4;
- attr->Map1Vertex3 = ctx->Eval.Map1Vertex3;
- attr->Map1Vertex4 = ctx->Eval.Map1Vertex4;
- memcpy(attr->Map1Attrib, ctx->Eval.Map1Attrib, sizeof(ctx->Eval.Map1Attrib));
- attr->Map2Color4 = ctx->Eval.Map2Color4;
- attr->Map2Index = ctx->Eval.Map2Index;
- attr->Map2Normal = ctx->Eval.Map2Normal;
- attr->Map2TextureCoord1 = ctx->Eval.Map2TextureCoord1;
- attr->Map2TextureCoord2 = ctx->Eval.Map2TextureCoord2;
- attr->Map2TextureCoord3 = ctx->Eval.Map2TextureCoord3;
- attr->Map2TextureCoord4 = ctx->Eval.Map2TextureCoord4;
- attr->Map2Vertex3 = ctx->Eval.Map2Vertex3;
- attr->Map2Vertex4 = ctx->Eval.Map2Vertex4;
- memcpy(attr->Map2Attrib, ctx->Eval.Map2Attrib, sizeof(ctx->Eval.Map2Attrib));
- attr->Normalize = ctx->Transform.Normalize;
- attr->RasterPositionUnclipped = ctx->Transform.RasterPositionUnclipped;
- attr->PointSmooth = ctx->Point.SmoothFlag;
- attr->PointSprite = ctx->Point.PointSprite;
- attr->PolygonOffsetPoint = ctx->Polygon.OffsetPoint;
- attr->PolygonOffsetLine = ctx->Polygon.OffsetLine;
- attr->PolygonOffsetFill = ctx->Polygon.OffsetFill;
- attr->PolygonSmooth = ctx->Polygon.SmoothFlag;
- attr->PolygonStipple = ctx->Polygon.StippleFlag;
- attr->RescaleNormals = ctx->Transform.RescaleNormals;
- attr->Scissor = ctx->Scissor.Enabled;
- attr->Stencil = ctx->Stencil.Enabled;
- attr->StencilTwoSide = ctx->Stencil.TestTwoSide;
- attr->MultisampleEnabled = ctx->Multisample.Enabled;
- attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage;
- attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne;
- attr->SampleCoverage = ctx->Multisample.SampleCoverage;
- attr->SampleCoverageInvert = ctx->Multisample.SampleCoverageInvert;
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- attr->Texture[i] = ctx->Texture.Unit[i].Enabled;
- attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled;
- attr->TextureColorTable[i] = ctx->Texture.Unit[i].ColorTableEnabled;
- }
- /* GL_NV_vertex_program */
- attr->VertexProgram = ctx->VertexProgram.Enabled;
- attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled;
- attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled;
- save_attrib_data(&head, GL_ENABLE_BIT, attr);
- }
-
- if (mask & GL_EVAL_BIT) {
- struct gl_eval_attrib *attr;
- attr = MALLOC_STRUCT( gl_eval_attrib );
- memcpy( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) );
- save_attrib_data(&head, GL_EVAL_BIT, attr);
- }
-
- if (mask & GL_FOG_BIT) {
- struct gl_fog_attrib *attr;
- attr = MALLOC_STRUCT( gl_fog_attrib );
- memcpy( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) );
- save_attrib_data(&head, GL_FOG_BIT, attr);
- }
-
- if (mask & GL_HINT_BIT) {
- struct gl_hint_attrib *attr;
- attr = MALLOC_STRUCT( gl_hint_attrib );
- memcpy( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) );
- save_attrib_data(&head, GL_HINT_BIT, attr);
- }
-
- if (mask & GL_LIGHTING_BIT) {
- struct gl_light_attrib *attr;
- FLUSH_CURRENT(ctx, 0); /* flush material changes */
- attr = MALLOC_STRUCT( gl_light_attrib );
- memcpy( attr, &ctx->Light, sizeof(struct gl_light_attrib) );
- save_attrib_data(&head, GL_LIGHTING_BIT, attr);
- }
-
- if (mask & GL_LINE_BIT) {
- struct gl_line_attrib *attr;
- attr = MALLOC_STRUCT( gl_line_attrib );
- memcpy( attr, &ctx->Line, sizeof(struct gl_line_attrib) );
- save_attrib_data(&head, GL_LINE_BIT, attr);
- }
-
- if (mask & GL_LIST_BIT) {
- struct gl_list_attrib *attr;
- attr = MALLOC_STRUCT( gl_list_attrib );
- memcpy( attr, &ctx->List, sizeof(struct gl_list_attrib) );
- save_attrib_data(&head, GL_LIST_BIT, attr);
- }
-
- if (mask & GL_PIXEL_MODE_BIT) {
- struct gl_pixel_attrib *attr;
- attr = MALLOC_STRUCT( gl_pixel_attrib );
- memcpy( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) );
- /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */
- attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer;
- save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr);
- }
-
- if (mask & GL_POINT_BIT) {
- struct gl_point_attrib *attr;
- attr = MALLOC_STRUCT( gl_point_attrib );
- memcpy( attr, &ctx->Point, sizeof(struct gl_point_attrib) );
- save_attrib_data(&head, GL_POINT_BIT, attr);
- }
-
- if (mask & GL_POLYGON_BIT) {
- struct gl_polygon_attrib *attr;
- attr = MALLOC_STRUCT( gl_polygon_attrib );
- memcpy( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) );
- save_attrib_data(&head, GL_POLYGON_BIT, attr);
- }
-
- if (mask & GL_POLYGON_STIPPLE_BIT) {
- GLuint *stipple;
- stipple = (GLuint *) MALLOC( 32*sizeof(GLuint) );
- memcpy( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) );
- save_attrib_data(&head, GL_POLYGON_STIPPLE_BIT, stipple);
- }
-
- if (mask & GL_SCISSOR_BIT) {
- struct gl_scissor_attrib *attr;
- attr = MALLOC_STRUCT( gl_scissor_attrib );
- memcpy( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) );
- save_attrib_data(&head, GL_SCISSOR_BIT, attr);
- }
-
- if (mask & GL_STENCIL_BUFFER_BIT) {
- struct gl_stencil_attrib *attr;
- attr = MALLOC_STRUCT( gl_stencil_attrib );
- memcpy( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) );
- save_attrib_data(&head, GL_STENCIL_BUFFER_BIT, attr);
- }
-
- if (mask & GL_TEXTURE_BIT) {
- struct texture_state *texstate = CALLOC_STRUCT(texture_state);
- GLuint u, tex;
-
- if (!texstate) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)");
- goto end;
- }
-
- _mesa_lock_context_textures(ctx);
-
- /* copy/save the bulk of texture state here */
- memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture));
-
- /* Save references to the currently bound texture objects so they don't
- * accidentally get deleted while referenced in the attribute stack.
- */
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
- _mesa_reference_texobj(&texstate->SavedTexRef[u][tex],
- ctx->Texture.Unit[u].CurrentTex[tex]);
- }
- }
-
- /* copy state/contents of the currently bound texture objects */
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
- _mesa_copy_texture_object(&texstate->SavedObj[u][tex],
- ctx->Texture.Unit[u].CurrentTex[tex]);
- }
- }
-
- _mesa_unlock_context_textures(ctx);
-
- save_attrib_data(&head, GL_TEXTURE_BIT, texstate);
- }
-
- if (mask & GL_TRANSFORM_BIT) {
- struct gl_transform_attrib *attr;
- attr = MALLOC_STRUCT( gl_transform_attrib );
- memcpy( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) );
- save_attrib_data(&head, GL_TRANSFORM_BIT, attr);
- }
-
- if (mask & GL_VIEWPORT_BIT) {
- struct gl_viewport_attrib *attr;
- attr = MALLOC_STRUCT( gl_viewport_attrib );
- memcpy( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) );
- save_attrib_data(&head, GL_VIEWPORT_BIT, attr);
- }
-
- /* GL_ARB_multisample */
- if (mask & GL_MULTISAMPLE_BIT_ARB) {
- struct gl_multisample_attrib *attr;
- attr = MALLOC_STRUCT( gl_multisample_attrib );
- memcpy( attr, &ctx->Multisample, sizeof(struct gl_multisample_attrib) );
- save_attrib_data(&head, GL_MULTISAMPLE_BIT_ARB, attr);
- }
-
-end:
- ctx->AttribStack[ctx->AttribStackDepth] = head;
- ctx->AttribStackDepth++;
-}
-
-
-
-static void
-pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
-{
- const GLuint curTexUnitSave = ctx->Texture.CurrentUnit;
- GLuint i;
-
-#define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \
- if ((VALUE) != (NEWVALUE)) { \
- _mesa_set_enable( ctx, ENUM, (NEWVALUE) ); \
- }
-
- TEST_AND_UPDATE(ctx->Color.AlphaEnabled, enable->AlphaTest, GL_ALPHA_TEST);
- if (ctx->Color.BlendEnabled != enable->Blend) {
- if (ctx->Extensions.EXT_draw_buffers2) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- _mesa_set_enablei(ctx, GL_BLEND, i, (enable->Blend >> i) & 1);
- }
- }
- else {
- _mesa_set_enable(ctx, GL_BLEND, (enable->Blend & 1));
- }
- }
-
- for (i=0;i<MAX_CLIP_PLANES;i++) {
- const GLuint mask = 1 << i;
- if ((ctx->Transform.ClipPlanesEnabled & mask) != (enable->ClipPlanes & mask))
- _mesa_set_enable(ctx, (GLenum) (GL_CLIP_PLANE0 + i),
- (GLboolean) ((enable->ClipPlanes & mask) ? GL_TRUE : GL_FALSE));
- }
-
- TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial,
- GL_COLOR_MATERIAL);
- TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE);
- TEST_AND_UPDATE(ctx->Transform.DepthClamp, enable->DepthClamp,
- GL_DEPTH_CLAMP);
- TEST_AND_UPDATE(ctx->Depth.Test, enable->DepthTest, GL_DEPTH_TEST);
- TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER);
- TEST_AND_UPDATE(ctx->Fog.Enabled, enable->Fog, GL_FOG);
- TEST_AND_UPDATE(ctx->Light.Enabled, enable->Lighting, GL_LIGHTING);
- TEST_AND_UPDATE(ctx->Line.SmoothFlag, enable->LineSmooth, GL_LINE_SMOOTH);
- TEST_AND_UPDATE(ctx->Line.StippleFlag, enable->LineStipple,
- GL_LINE_STIPPLE);
- TEST_AND_UPDATE(ctx->Color.IndexLogicOpEnabled, enable->IndexLogicOp,
- GL_INDEX_LOGIC_OP);
- TEST_AND_UPDATE(ctx->Color.ColorLogicOpEnabled, enable->ColorLogicOp,
- GL_COLOR_LOGIC_OP);
-
- TEST_AND_UPDATE(ctx->Eval.Map1Color4, enable->Map1Color4, GL_MAP1_COLOR_4);
- TEST_AND_UPDATE(ctx->Eval.Map1Index, enable->Map1Index, GL_MAP1_INDEX);
- TEST_AND_UPDATE(ctx->Eval.Map1Normal, enable->Map1Normal, GL_MAP1_NORMAL);
- TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord1, enable->Map1TextureCoord1,
- GL_MAP1_TEXTURE_COORD_1);
- TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord2, enable->Map1TextureCoord2,
- GL_MAP1_TEXTURE_COORD_2);
- TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord3, enable->Map1TextureCoord3,
- GL_MAP1_TEXTURE_COORD_3);
- TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord4, enable->Map1TextureCoord4,
- GL_MAP1_TEXTURE_COORD_4);
- TEST_AND_UPDATE(ctx->Eval.Map1Vertex3, enable->Map1Vertex3,
- GL_MAP1_VERTEX_3);
- TEST_AND_UPDATE(ctx->Eval.Map1Vertex4, enable->Map1Vertex4,
- GL_MAP1_VERTEX_4);
- for (i = 0; i < 16; i++) {
- TEST_AND_UPDATE(ctx->Eval.Map1Attrib[i], enable->Map1Attrib[i],
- GL_MAP1_VERTEX_ATTRIB0_4_NV + i);
- }
-
- TEST_AND_UPDATE(ctx->Eval.Map2Color4, enable->Map2Color4, GL_MAP2_COLOR_4);
- TEST_AND_UPDATE(ctx->Eval.Map2Index, enable->Map2Index, GL_MAP2_INDEX);
- TEST_AND_UPDATE(ctx->Eval.Map2Normal, enable->Map2Normal, GL_MAP2_NORMAL);
- TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord1, enable->Map2TextureCoord1,
- GL_MAP2_TEXTURE_COORD_1);
- TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord2, enable->Map2TextureCoord2,
- GL_MAP2_TEXTURE_COORD_2);
- TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord3, enable->Map2TextureCoord3,
- GL_MAP2_TEXTURE_COORD_3);
- TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord4, enable->Map2TextureCoord4,
- GL_MAP2_TEXTURE_COORD_4);
- TEST_AND_UPDATE(ctx->Eval.Map2Vertex3, enable->Map2Vertex3,
- GL_MAP2_VERTEX_3);
- TEST_AND_UPDATE(ctx->Eval.Map2Vertex4, enable->Map2Vertex4,
- GL_MAP2_VERTEX_4);
- for (i = 0; i < 16; i++) {
- TEST_AND_UPDATE(ctx->Eval.Map2Attrib[i], enable->Map2Attrib[i],
- GL_MAP2_VERTEX_ATTRIB0_4_NV + i);
- }
-
- TEST_AND_UPDATE(ctx->Eval.AutoNormal, enable->AutoNormal, GL_AUTO_NORMAL);
- TEST_AND_UPDATE(ctx->Transform.Normalize, enable->Normalize, GL_NORMALIZE);
- TEST_AND_UPDATE(ctx->Transform.RescaleNormals, enable->RescaleNormals,
- GL_RESCALE_NORMAL_EXT);
- TEST_AND_UPDATE(ctx->Transform.RasterPositionUnclipped,
- enable->RasterPositionUnclipped,
- GL_RASTER_POSITION_UNCLIPPED_IBM);
- TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth,
- GL_POINT_SMOOTH);
- if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) {
- TEST_AND_UPDATE(ctx->Point.PointSprite, enable->PointSprite,
- GL_POINT_SPRITE_NV);
- }
- TEST_AND_UPDATE(ctx->Polygon.OffsetPoint, enable->PolygonOffsetPoint,
- GL_POLYGON_OFFSET_POINT);
- TEST_AND_UPDATE(ctx->Polygon.OffsetLine, enable->PolygonOffsetLine,
- GL_POLYGON_OFFSET_LINE);
- TEST_AND_UPDATE(ctx->Polygon.OffsetFill, enable->PolygonOffsetFill,
- GL_POLYGON_OFFSET_FILL);
- TEST_AND_UPDATE(ctx->Polygon.SmoothFlag, enable->PolygonSmooth,
- GL_POLYGON_SMOOTH);
- TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple,
- GL_POLYGON_STIPPLE);
- TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST);
- TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST);
- if (ctx->Extensions.EXT_stencil_two_side) {
- TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT);
- }
- TEST_AND_UPDATE(ctx->Multisample.Enabled, enable->MultisampleEnabled,
- GL_MULTISAMPLE_ARB);
- TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage,
- enable->SampleAlphaToCoverage,
- GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
- TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToOne,
- enable->SampleAlphaToOne,
- GL_SAMPLE_ALPHA_TO_ONE_ARB);
- TEST_AND_UPDATE(ctx->Multisample.SampleCoverage,
- enable->SampleCoverage,
- GL_SAMPLE_COVERAGE_ARB);
- TEST_AND_UPDATE(ctx->Multisample.SampleCoverageInvert,
- enable->SampleCoverageInvert,
- GL_SAMPLE_COVERAGE_INVERT_ARB);
- /* GL_ARB_vertex_program, GL_NV_vertex_program */
- TEST_AND_UPDATE(ctx->VertexProgram.Enabled,
- enable->VertexProgram,
- GL_VERTEX_PROGRAM_ARB);
- TEST_AND_UPDATE(ctx->VertexProgram.PointSizeEnabled,
- enable->VertexProgramPointSize,
- GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
- TEST_AND_UPDATE(ctx->VertexProgram.TwoSideEnabled,
- enable->VertexProgramTwoSide,
- GL_VERTEX_PROGRAM_TWO_SIDE_ARB);
-
-#undef TEST_AND_UPDATE
-
- /* texture unit enables */
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- const GLbitfield enabled = enable->Texture[i];
- const GLbitfield genEnabled = enable->TexGen[i];
-
- if (ctx->Texture.Unit[i].Enabled != enabled) {
- _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
-
- _mesa_set_enable(ctx, GL_TEXTURE_1D,
- (enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_2D,
- (enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_3D,
- (enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE);
- if (ctx->Extensions.NV_texture_rectangle) {
- _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_ARB,
- (enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
- }
- if (ctx->Extensions.ARB_texture_cube_map) {
- _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP,
- (enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE);
- }
- if (ctx->Extensions.MESA_texture_array) {
- _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
- (enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
- (enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
- }
- }
-
- if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) {
- _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
- (genEnabled & S_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_T,
- (genEnabled & T_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_R,
- (genEnabled & R_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q,
- (genEnabled & Q_BIT) ? GL_TRUE : GL_FALSE);
- }
-
- /* GL_SGI_texture_color_table */
- ctx->Texture.Unit[i].ColorTableEnabled = enable->TextureColorTable[i];
- }
-
- _mesa_ActiveTextureARB(GL_TEXTURE0 + curTexUnitSave);
-}
-
-
-/**
- * Pop/restore texture attribute/group state.
- */
-static void
-pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
-{
- GLuint u;
-
- _mesa_lock_context_textures(ctx);
-
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- const struct gl_texture_unit *unit = &texstate->Texture.Unit[u];
- GLuint tgt;
-
- _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u);
- _mesa_set_enable(ctx, GL_TEXTURE_1D,
- (unit->Enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_2D,
- (unit->Enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_3D,
- (unit->Enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE);
- if (ctx->Extensions.ARB_texture_cube_map) {
- _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB,
- (unit->Enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE);
- }
- if (ctx->Extensions.NV_texture_rectangle) {
- _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV,
- (unit->Enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
- }
- if (ctx->Extensions.MESA_texture_array) {
- _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
- (unit->Enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
- (unit->Enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
- }
-
- if (ctx->Extensions.SGI_texture_color_table) {
- _mesa_set_enable(ctx, GL_TEXTURE_COLOR_TABLE_SGI,
- unit->ColorTableEnabled);
- }
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode);
- _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor);
- _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode);
- _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenT.Mode);
- _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenR.Mode);
- _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenQ.Mode);
- _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->GenS.ObjectPlane);
- _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->GenT.ObjectPlane);
- _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->GenR.ObjectPlane);
- _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->GenQ.ObjectPlane);
- /* Eye plane done differently to avoid re-transformation */
- {
- struct gl_texture_unit *destUnit = &ctx->Texture.Unit[u];
- COPY_4FV(destUnit->GenS.EyePlane, unit->GenS.EyePlane);
- COPY_4FV(destUnit->GenT.EyePlane, unit->GenT.EyePlane);
- COPY_4FV(destUnit->GenR.EyePlane, unit->GenR.EyePlane);
- COPY_4FV(destUnit->GenQ.EyePlane, unit->GenQ.EyePlane);
- if (ctx->Driver.TexGen) {
- ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->GenS.EyePlane);
- ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->GenT.EyePlane);
- ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->GenR.EyePlane);
- ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->GenQ.EyePlane);
- }
- }
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
- ((unit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE));
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_T,
- ((unit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE));
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_R,
- ((unit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE));
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q,
- ((unit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE));
- if (ctx->Extensions.EXT_texture_lod_bias) {
- _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
- GL_TEXTURE_LOD_BIAS_EXT, unit->LodBias);
- }
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,
- unit->Combine.ModeRGB);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,
- unit->Combine.ModeA);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB,
- unit->Combine.SourceRGB[0]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB,
- unit->Combine.SourceRGB[1]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB,
- unit->Combine.SourceRGB[2]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA,
- unit->Combine.SourceA[0]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA,
- unit->Combine.SourceA[1]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA,
- unit->Combine.SourceA[2]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB,
- unit->Combine.OperandRGB[0]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB,
- unit->Combine.OperandRGB[1]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,
- unit->Combine.OperandRGB[2]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA,
- unit->Combine.OperandA[0]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA,
- unit->Combine.OperandA[1]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
- unit->Combine.OperandA[2]);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE,
- 1 << unit->Combine.ScaleShiftRGB);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE,
- 1 << unit->Combine.ScaleShiftA);
- }
-
- /* Restore texture object state for each target */
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
- const struct gl_texture_object *obj = NULL;
- GLenum target;
-
- obj = &texstate->SavedObj[u][tgt];
-
- /* don't restore state for unsupported targets to prevent
- * raising GL errors.
- */
- if (obj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
- !ctx->Extensions.ARB_texture_cube_map) {
- continue;
- }
- else if (obj->Target == GL_TEXTURE_RECTANGLE_NV &&
- !ctx->Extensions.NV_texture_rectangle) {
- continue;
- }
- else if ((obj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
- obj->Target == GL_TEXTURE_2D_ARRAY_EXT) &&
- !ctx->Extensions.MESA_texture_array) {
- continue;
- }
-
- target = obj->Target;
-
- _mesa_BindTexture(target, obj->Name);
-
- _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, obj->BorderColor.f);
- _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, obj->WrapR);
- _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, obj->MinFilter);
- _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, obj->MagFilter);
- _mesa_TexParameterf(target, GL_TEXTURE_MIN_LOD, obj->MinLod);
- _mesa_TexParameterf(target, GL_TEXTURE_MAX_LOD, obj->MaxLod);
- _mesa_TexParameterf(target, GL_TEXTURE_LOD_BIAS, obj->LodBias);
- _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, obj->BaseLevel);
- if (target != GL_TEXTURE_RECTANGLE_ARB)
- _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel);
- if (ctx->Extensions.EXT_texture_filter_anisotropic) {
- _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- obj->MaxAnisotropy);
- }
- if (ctx->Extensions.ARB_shadow_ambient) {
- _mesa_TexParameterf(target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
- obj->CompareFailValue);
- }
- }
-
- /* remove saved references to the texture objects */
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
- _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL);
- }
- }
-
- _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit);
-
- _mesa_unlock_context_textures(ctx);
-}
-
-
-/*
- * This function is kind of long just because we have to call a lot
- * of device driver functions to update device driver state.
- *
- * XXX As it is now, most of the pop-code calls immediate-mode Mesa functions
- * in order to restore GL state. This isn't terribly efficient but it
- * ensures that dirty flags and any derived state gets updated correctly.
- * We could at least check if the value to restore equals the current value
- * and then skip the Mesa call.
- */
-void GLAPIENTRY
-_mesa_PopAttrib(void)
-{
- struct gl_attrib_node *attr, *next;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (ctx->AttribStackDepth == 0) {
- _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" );
- return;
- }
-
- ctx->AttribStackDepth--;
- attr = ctx->AttribStack[ctx->AttribStackDepth];
-
- while (attr) {
-
- if (MESA_VERBOSE & VERBOSE_API) {
- _mesa_debug(ctx, "glPopAttrib %s\n",
- _mesa_lookup_enum_by_nr(attr->kind));
- }
-
- switch (attr->kind) {
- case GL_ACCUM_BUFFER_BIT:
- {
- const struct gl_accum_attrib *accum;
- accum = (const struct gl_accum_attrib *) attr->data;
- _mesa_ClearAccum(accum->ClearColor[0],
- accum->ClearColor[1],
- accum->ClearColor[2],
- accum->ClearColor[3]);
- }
- break;
- case GL_COLOR_BUFFER_BIT:
- {
- const struct gl_colorbuffer_attrib *color;
-
- color = (const struct gl_colorbuffer_attrib *) attr->data;
- _mesa_ClearIndex((GLfloat) color->ClearIndex);
- _mesa_ClearColor(color->ClearColor[0],
- color->ClearColor[1],
- color->ClearColor[2],
- color->ClearColor[3]);
- _mesa_IndexMask(color->IndexMask);
- if (!ctx->Extensions.EXT_draw_buffers2) {
- _mesa_ColorMask((GLboolean) (color->ColorMask[0][0] != 0),
- (GLboolean) (color->ColorMask[0][1] != 0),
- (GLboolean) (color->ColorMask[0][2] != 0),
- (GLboolean) (color->ColorMask[0][3] != 0));
- }
- else {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- _mesa_ColorMaskIndexed(i,
- (GLboolean) (color->ColorMask[i][0] != 0),
- (GLboolean) (color->ColorMask[i][1] != 0),
- (GLboolean) (color->ColorMask[i][2] != 0),
- (GLboolean) (color->ColorMask[i][3] != 0));
- }
- }
- {
- /* Need to determine if more than one color output is
- * specified. If so, call glDrawBuffersARB, else call
- * glDrawBuffer(). This is a subtle, but essential point
- * since GL_FRONT (for example) is illegal for the former
- * function, but legal for the later.
- */
- GLboolean multipleBuffers = GL_FALSE;
- GLuint i;
-
- for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
- if (color->DrawBuffer[i] != GL_NONE) {
- multipleBuffers = GL_TRUE;
- break;
- }
- }
- /* Call the API_level functions, not _mesa_drawbuffers()
- * since we need to do error checking on the pop'd
- * GL_DRAW_BUFFER.
- * Ex: if GL_FRONT were pushed, but we're popping with a
- * user FBO bound, GL_FRONT will be illegal and we'll need
- * to record that error. Per OpenGL ARB decision.
- */
- if (multipleBuffers)
- _mesa_DrawBuffersARB(ctx->Const.MaxDrawBuffers,
- color->DrawBuffer);
- else
- _mesa_DrawBuffer(color->DrawBuffer[0]);
- }
- _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled);
- _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRef);
- if (ctx->Color.BlendEnabled != color->BlendEnabled) {
- if (ctx->Extensions.EXT_draw_buffers2) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- _mesa_set_enablei(ctx, GL_BLEND, i,
- (color->BlendEnabled >> i) & 1);
- }
- }
- else {
- _mesa_set_enable(ctx, GL_BLEND, (color->BlendEnabled & 1));
- }
- }
- if (ctx->Color._BlendFuncPerBuffer ||
- ctx->Color._BlendEquationPerBuffer) {
- /* set blend per buffer */
- GLuint buf;
- for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
- _mesa_BlendFuncSeparatei(buf, color->Blend[buf].SrcRGB,
- color->Blend[buf].DstRGB,
- color->Blend[buf].SrcA,
- color->Blend[buf].DstA);
- _mesa_BlendEquationSeparatei(buf,
- color->Blend[buf].EquationRGB,
- color->Blend[buf].EquationA);
- }
- }
- else {
- /* set same blend modes for all buffers */
- _mesa_BlendFuncSeparateEXT(color->Blend[0].SrcRGB,
- color->Blend[0].DstRGB,
- color->Blend[0].SrcA,
- color->Blend[0].DstA);
- /* This special case is because glBlendEquationSeparateEXT
- * cannot take GL_LOGIC_OP as a parameter.
- */
- if (color->Blend[0].EquationRGB ==
- color->Blend[0].EquationA) {
- _mesa_BlendEquation(color->Blend[0].EquationRGB);
- }
- else {
- _mesa_BlendEquationSeparateEXT(
- color->Blend[0].EquationRGB,
- color->Blend[0].EquationA);
- }
- }
- _mesa_BlendColor(color->BlendColor[0],
- color->BlendColor[1],
- color->BlendColor[2],
- color->BlendColor[3]);
- _mesa_LogicOp(color->LogicOp);
- _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP,
- color->ColorLogicOpEnabled);
- _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP,
- color->IndexLogicOpEnabled);
- _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag);
- }
- break;
- case GL_CURRENT_BIT:
- FLUSH_CURRENT( ctx, 0 );
- memcpy( &ctx->Current, attr->data,
- sizeof(struct gl_current_attrib) );
- break;
- case GL_DEPTH_BUFFER_BIT:
- {
- const struct gl_depthbuffer_attrib *depth;
- depth = (const struct gl_depthbuffer_attrib *) attr->data;
- _mesa_DepthFunc(depth->Func);
- _mesa_ClearDepth(depth->Clear);
- _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test);
- _mesa_DepthMask(depth->Mask);
- }
- break;
- case GL_ENABLE_BIT:
- {
- const struct gl_enable_attrib *enable;
- enable = (const struct gl_enable_attrib *) attr->data;
- pop_enable_group(ctx, enable);
- ctx->NewState |= _NEW_ALL;
- }
- break;
- case GL_EVAL_BIT:
- memcpy( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) );
- ctx->NewState |= _NEW_EVAL;
- break;
- case GL_FOG_BIT:
- {
- const struct gl_fog_attrib *fog;
- fog = (const struct gl_fog_attrib *) attr->data;
- _mesa_set_enable(ctx, GL_FOG, fog->Enabled);
- _mesa_Fogfv(GL_FOG_COLOR, fog->Color);
- _mesa_Fogf(GL_FOG_DENSITY, fog->Density);
- _mesa_Fogf(GL_FOG_START, fog->Start);
- _mesa_Fogf(GL_FOG_END, fog->End);
- _mesa_Fogf(GL_FOG_INDEX, fog->Index);
- _mesa_Fogi(GL_FOG_MODE, fog->Mode);
- }
- break;
- case GL_HINT_BIT:
- {
- const struct gl_hint_attrib *hint;
- hint = (const struct gl_hint_attrib *) attr->data;
- _mesa_Hint(GL_PERSPECTIVE_CORRECTION_HINT,
- hint->PerspectiveCorrection );
- _mesa_Hint(GL_POINT_SMOOTH_HINT, hint->PointSmooth);
- _mesa_Hint(GL_LINE_SMOOTH_HINT, hint->LineSmooth);
- _mesa_Hint(GL_POLYGON_SMOOTH_HINT, hint->PolygonSmooth);
- _mesa_Hint(GL_FOG_HINT, hint->Fog);
- _mesa_Hint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT,
- hint->ClipVolumeClipping);
- _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB,
- hint->TextureCompression);
- }
- break;
- case GL_LIGHTING_BIT:
- {
- GLuint i;
- const struct gl_light_attrib *light;
- light = (const struct gl_light_attrib *) attr->data;
- /* lighting enable */
- _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled);
- /* per-light state */
- if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top))
- _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
-
- for (i = 0; i < ctx->Const.MaxLights; i++) {
- const struct gl_light *l = &light->Light[i];
- _mesa_set_enable(ctx, GL_LIGHT0 + i, l->Enabled);
- _mesa_light(ctx, i, GL_AMBIENT, l->Ambient);
- _mesa_light(ctx, i, GL_DIFFUSE, l->Diffuse);
- _mesa_light(ctx, i, GL_SPECULAR, l->Specular );
- _mesa_light(ctx, i, GL_POSITION, l->EyePosition);
- _mesa_light(ctx, i, GL_SPOT_DIRECTION, l->SpotDirection);
- {
- GLfloat p[4] = { 0 };
- p[0] = l->SpotExponent;
- _mesa_light(ctx, i, GL_SPOT_EXPONENT, p);
- }
- {
- GLfloat p[4] = { 0 };
- p[0] = l->SpotCutoff;
- _mesa_light(ctx, i, GL_SPOT_CUTOFF, p);
- }
- {
- GLfloat p[4] = { 0 };
- p[0] = l->ConstantAttenuation;
- _mesa_light(ctx, i, GL_CONSTANT_ATTENUATION, p);
- }
- {
- GLfloat p[4] = { 0 };
- p[0] = l->LinearAttenuation;
- _mesa_light(ctx, i, GL_LINEAR_ATTENUATION, p);
- }
- {
- GLfloat p[4] = { 0 };
- p[0] = l->QuadraticAttenuation;
- _mesa_light(ctx, i, GL_QUADRATIC_ATTENUATION, p);
- }
- }
- /* light model */
- _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT,
- light->Model.Ambient);
- _mesa_LightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,
- (GLfloat) light->Model.LocalViewer);
- _mesa_LightModelf(GL_LIGHT_MODEL_TWO_SIDE,
- (GLfloat) light->Model.TwoSide);
- _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL,
- (GLfloat) light->Model.ColorControl);
- /* shade model */
- _mesa_ShadeModel(light->ShadeModel);
- /* color material */
- _mesa_ColorMaterial(light->ColorMaterialFace,
- light->ColorMaterialMode);
- _mesa_set_enable(ctx, GL_COLOR_MATERIAL,
- light->ColorMaterialEnabled);
- /* materials */
- memcpy(&ctx->Light.Material, &light->Material,
- sizeof(struct gl_material));
- }
- break;
- case GL_LINE_BIT:
- {
- const struct gl_line_attrib *line;
- line = (const struct gl_line_attrib *) attr->data;
- _mesa_set_enable(ctx, GL_LINE_SMOOTH, line->SmoothFlag);
- _mesa_set_enable(ctx, GL_LINE_STIPPLE, line->StippleFlag);
- _mesa_LineStipple(line->StippleFactor, line->StipplePattern);
- _mesa_LineWidth(line->Width);
- }
- break;
- case GL_LIST_BIT:
- memcpy( &ctx->List, attr->data, sizeof(struct gl_list_attrib) );
- break;
- case GL_PIXEL_MODE_BIT:
- memcpy( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) );
- /* XXX what other pixel state needs to be set by function calls? */
- _mesa_ReadBuffer(ctx->Pixel.ReadBuffer);
- ctx->NewState |= _NEW_PIXEL;
- break;
- case GL_POINT_BIT:
- {
- const struct gl_point_attrib *point;
- point = (const struct gl_point_attrib *) attr->data;
- _mesa_PointSize(point->Size);
- _mesa_set_enable(ctx, GL_POINT_SMOOTH, point->SmoothFlag);
- if (ctx->Extensions.EXT_point_parameters) {
- _mesa_PointParameterfv(GL_DISTANCE_ATTENUATION_EXT,
- point->Params);
- _mesa_PointParameterf(GL_POINT_SIZE_MIN_EXT,
- point->MinSize);
- _mesa_PointParameterf(GL_POINT_SIZE_MAX_EXT,
- point->MaxSize);
- _mesa_PointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT,
- point->Threshold);
- }
- if (ctx->Extensions.NV_point_sprite
- || ctx->Extensions.ARB_point_sprite) {
- GLuint u;
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- _mesa_TexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV,
- (GLint) point->CoordReplace[u]);
- }
- _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite);
- if (ctx->Extensions.NV_point_sprite)
- _mesa_PointParameteri(GL_POINT_SPRITE_R_MODE_NV,
- ctx->Point.SpriteRMode);
- _mesa_PointParameterf(GL_POINT_SPRITE_COORD_ORIGIN,
- (GLfloat)ctx->Point.SpriteOrigin);
- }
- }
- break;
- case GL_POLYGON_BIT:
- {
- const struct gl_polygon_attrib *polygon;
- polygon = (const struct gl_polygon_attrib *) attr->data;
- _mesa_CullFace(polygon->CullFaceMode);
- _mesa_FrontFace(polygon->FrontFace);
- _mesa_PolygonMode(GL_FRONT, polygon->FrontMode);
- _mesa_PolygonMode(GL_BACK, polygon->BackMode);
- _mesa_PolygonOffset(polygon->OffsetFactor,
- polygon->OffsetUnits);
- _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, polygon->SmoothFlag);
- _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, polygon->StippleFlag);
- _mesa_set_enable(ctx, GL_CULL_FACE, polygon->CullFlag);
- _mesa_set_enable(ctx, GL_POLYGON_OFFSET_POINT,
- polygon->OffsetPoint);
- _mesa_set_enable(ctx, GL_POLYGON_OFFSET_LINE,
- polygon->OffsetLine);
- _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL,
- polygon->OffsetFill);
- }
- break;
- case GL_POLYGON_STIPPLE_BIT:
- memcpy( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) );
- ctx->NewState |= _NEW_POLYGONSTIPPLE;
- if (ctx->Driver.PolygonStipple)
- ctx->Driver.PolygonStipple( ctx, (const GLubyte *) attr->data );
- break;
- case GL_SCISSOR_BIT:
- {
- const struct gl_scissor_attrib *scissor;
- scissor = (const struct gl_scissor_attrib *) attr->data;
- _mesa_Scissor(scissor->X, scissor->Y,
- scissor->Width, scissor->Height);
- _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->Enabled);
- }
- break;
- case GL_STENCIL_BUFFER_BIT:
- {
- const struct gl_stencil_attrib *stencil;
- stencil = (const struct gl_stencil_attrib *) attr->data;
- _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
- _mesa_ClearStencil(stencil->Clear);
- if (ctx->Extensions.EXT_stencil_two_side) {
- _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
- stencil->TestTwoSide);
- _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
- ? GL_BACK : GL_FRONT);
- }
- /* front state */
- _mesa_StencilFuncSeparate(GL_FRONT,
- stencil->Function[0],
- stencil->Ref[0],
- stencil->ValueMask[0]);
- _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
- _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
- stencil->ZFailFunc[0],
- stencil->ZPassFunc[0]);
- /* back state */
- _mesa_StencilFuncSeparate(GL_BACK,
- stencil->Function[1],
- stencil->Ref[1],
- stencil->ValueMask[1]);
- _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
- _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
- stencil->ZFailFunc[1],
- stencil->ZPassFunc[1]);
- }
- break;
- case GL_TRANSFORM_BIT:
- {
- GLuint i;
- const struct gl_transform_attrib *xform;
- xform = (const struct gl_transform_attrib *) attr->data;
- _mesa_MatrixMode(xform->MatrixMode);
- if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
- _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
-
- /* restore clip planes */
- for (i = 0; i < MAX_CLIP_PLANES; i++) {
- const GLuint mask = 1 << i;
- const GLfloat *eyePlane = xform->EyeUserPlane[i];
- COPY_4V(ctx->Transform.EyeUserPlane[i], eyePlane);
- if (xform->ClipPlanesEnabled & mask) {
- _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
- }
- else {
- _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
- }
- if (ctx->Driver.ClipPlane)
- ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, eyePlane );
- }
-
- /* normalize/rescale */
- if (xform->Normalize != ctx->Transform.Normalize)
- _mesa_set_enable(ctx, GL_NORMALIZE,ctx->Transform.Normalize);
- if (xform->RescaleNormals != ctx->Transform.RescaleNormals)
- _mesa_set_enable(ctx, GL_RESCALE_NORMAL_EXT,
- ctx->Transform.RescaleNormals);
- if (xform->DepthClamp != ctx->Transform.DepthClamp)
- _mesa_set_enable(ctx, GL_DEPTH_CLAMP,
- ctx->Transform.DepthClamp);
- }
- break;
- case GL_TEXTURE_BIT:
- /* Take care of texture object reference counters */
- {
- struct texture_state *texstate
- = (struct texture_state *) attr->data;
- pop_texture_group(ctx, texstate);
- ctx->NewState |= _NEW_TEXTURE;
- }
- break;
- case GL_VIEWPORT_BIT:
- {
- const struct gl_viewport_attrib *vp;
- vp = (const struct gl_viewport_attrib *) attr->data;
- _mesa_Viewport(vp->X, vp->Y, vp->Width, vp->Height);
- _mesa_DepthRange(vp->Near, vp->Far);
- }
- break;
- case GL_MULTISAMPLE_BIT_ARB:
- {
- const struct gl_multisample_attrib *ms;
- ms = (const struct gl_multisample_attrib *) attr->data;
- _mesa_SampleCoverageARB(ms->SampleCoverageValue,
- ms->SampleCoverageInvert);
- }
- break;
-
- default:
- _mesa_problem( ctx, "Bad attrib flag in PopAttrib");
- break;
- }
-
- next = attr->next;
- FREE( attr->data );
- FREE( attr );
- attr = next;
- }
-}
-
-
-/**
- * Helper for incrementing/decrementing vertex buffer object reference
- * counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
- */
-static void
-adjust_buffer_object_ref_counts(struct gl_array_object *arrayObj, GLint step)
-{
- GLuint i;
-
- arrayObj->Vertex.BufferObj->RefCount += step;
- arrayObj->Weight.BufferObj->RefCount += step;
- arrayObj->Normal.BufferObj->RefCount += step;
- arrayObj->Color.BufferObj->RefCount += step;
- arrayObj->SecondaryColor.BufferObj->RefCount += step;
- arrayObj->FogCoord.BufferObj->RefCount += step;
- arrayObj->Index.BufferObj->RefCount += step;
- arrayObj->EdgeFlag.BufferObj->RefCount += step;
- for (i = 0; i < Elements(arrayObj->TexCoord); i++)
- arrayObj->TexCoord[i].BufferObj->RefCount += step;
- for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
- arrayObj->VertexAttrib[i].BufferObj->RefCount += step;
-}
-
-
-/**
- * Copy gl_pixelstore_attrib from src to dst, updating buffer
- * object refcounts.
- */
-static void
-copy_pixelstore(struct gl_context *ctx,
- struct gl_pixelstore_attrib *dst,
- const struct gl_pixelstore_attrib *src)
-{
- dst->Alignment = src->Alignment;
- dst->RowLength = src->RowLength;
- dst->SkipPixels = src->SkipPixels;
- dst->SkipRows = src->SkipRows;
- dst->ImageHeight = src->ImageHeight;
- dst->SkipImages = src->SkipImages;
- dst->SwapBytes = src->SwapBytes;
- dst->LsbFirst = src->LsbFirst;
- dst->ClientStorage = src->ClientStorage;
- dst->Invert = src->Invert;
- _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
-}
-
-
-#define GL_CLIENT_PACK_BIT (1<<20)
-#define GL_CLIENT_UNPACK_BIT (1<<21)
-
-
-void GLAPIENTRY
-_mesa_PushClientAttrib(GLbitfield mask)
-{
- struct gl_attrib_node *head;
-
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (ctx->ClientAttribStackDepth >= MAX_CLIENT_ATTRIB_STACK_DEPTH) {
- _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushClientAttrib" );
- return;
- }
-
- /* Build linked list of attribute nodes which save all attribute
- * groups specified by the mask.
- */
- head = NULL;
-
- if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
- struct gl_pixelstore_attrib *attr;
- /* packing attribs */
- attr = CALLOC_STRUCT( gl_pixelstore_attrib );
- copy_pixelstore(ctx, attr, &ctx->Pack);
- save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr);
- /* unpacking attribs */
- attr = CALLOC_STRUCT( gl_pixelstore_attrib );
- copy_pixelstore(ctx, attr, &ctx->Unpack);
- save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr);
- }
-
- if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
- struct gl_array_attrib *attr;
- struct gl_array_object *obj;
-
- attr = MALLOC_STRUCT( gl_array_attrib );
- obj = MALLOC_STRUCT( gl_array_object );
-
-#if FEATURE_ARB_vertex_buffer_object
- /* increment ref counts since we're copying pointers to these objects */
- ctx->Array.ArrayBufferObj->RefCount++;
- ctx->Array.ElementArrayBufferObj->RefCount++;
-#endif
-
- memcpy( attr, &ctx->Array, sizeof(struct gl_array_attrib) );
- memcpy( obj, ctx->Array.ArrayObj, sizeof(struct gl_array_object) );
-
- attr->ArrayObj = obj;
-
- save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr);
-
- /* bump reference counts on buffer objects */
- adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, 1);
- }
-
- ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
- ctx->ClientAttribStackDepth++;
-}
-
-
-
-
-void GLAPIENTRY
-_mesa_PopClientAttrib(void)
-{
- struct gl_attrib_node *node, *next;
-
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (ctx->ClientAttribStackDepth == 0) {
- _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" );
- return;
- }
-
- ctx->ClientAttribStackDepth--;
- node = ctx->ClientAttribStack[ctx->ClientAttribStackDepth];
-
- while (node) {
- switch (node->kind) {
- case GL_CLIENT_PACK_BIT:
- {
- struct gl_pixelstore_attrib *store =
- (struct gl_pixelstore_attrib *) node->data;
- copy_pixelstore(ctx, &ctx->Pack, store);
- _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
- }
- ctx->NewState |= _NEW_PACKUNPACK;
- break;
- case GL_CLIENT_UNPACK_BIT:
- {
- struct gl_pixelstore_attrib *store =
- (struct gl_pixelstore_attrib *) node->data;
- copy_pixelstore(ctx, &ctx->Unpack, store);
- _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
- }
- ctx->NewState |= _NEW_PACKUNPACK;
- break;
- case GL_CLIENT_VERTEX_ARRAY_BIT: {
- struct gl_array_attrib * data =
- (struct gl_array_attrib *) node->data;
-
- adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, -1);
-
- ctx->Array.ActiveTexture = data->ActiveTexture;
- if (data->LockCount != 0)
- _mesa_LockArraysEXT(data->LockFirst, data->LockCount);
- else if (ctx->Array.LockCount)
- _mesa_UnlockArraysEXT();
-
- _mesa_BindVertexArrayAPPLE( data->ArrayObj->Name );
-
-#if FEATURE_ARB_vertex_buffer_object
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
- data->ArrayBufferObj->Name);
- _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
- data->ElementArrayBufferObj->Name);
-#endif
-
- memcpy( ctx->Array.ArrayObj, data->ArrayObj,
- sizeof( struct gl_array_object ) );
-
- FREE( data->ArrayObj );
-
- /* FIXME: Should some bits in ctx->Array->NewState also be set
- * FIXME: here? It seems like it should be set to inclusive-or
- * FIXME: of the old ArrayObj->_Enabled and the new _Enabled.
- */
-
- ctx->NewState |= _NEW_ARRAY;
- break;
- }
- default:
- _mesa_problem( ctx, "Bad attrib flag in PopClientAttrib");
- break;
- }
-
- next = node->next;
- FREE( node->data );
- FREE( node );
- node = next;
- }
-}
-
-
-void
-_mesa_init_attrib_dispatch(struct _glapi_table *disp)
-{
- SET_PopAttrib(disp, _mesa_PopAttrib);
- SET_PushAttrib(disp, _mesa_PushAttrib);
- SET_PopClientAttrib(disp, _mesa_PopClientAttrib);
- SET_PushClientAttrib(disp, _mesa_PushClientAttrib);
-}
-
-
-#endif /* FEATURE_attrib_stack */
-
-
-/**
- * Free any attribute state data that might be attached to the context.
- */
-void
-_mesa_free_attrib_data(struct gl_context *ctx)
-{
- while (ctx->AttribStackDepth > 0) {
- struct gl_attrib_node *attr, *next;
-
- ctx->AttribStackDepth--;
- attr = ctx->AttribStack[ctx->AttribStackDepth];
-
- while (attr) {
- if (attr->kind == GL_TEXTURE_BIT) {
- struct texture_state *texstate = (struct texture_state*)attr->data;
- GLuint u, tgt;
- /* clear references to the saved texture objects */
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
- _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL);
- }
- }
- }
- else {
- /* any other chunks of state that requires special handling? */
- }
-
- next = attr->next;
- free(attr->data);
- free(attr);
- attr = next;
- }
- }
-}
-
-
-void _mesa_init_attrib( struct gl_context *ctx )
-{
- /* Renderer and client attribute stacks */
- ctx->AttribStackDepth = 0;
- ctx->ClientAttribStackDepth = 0;
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. 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 "imports.h"
+#include "accum.h"
+#include "arrayobj.h"
+#include "attrib.h"
+#include "blend.h"
+#include "buffers.h"
+#include "bufferobj.h"
+#include "clear.h"
+#include "colormac.h"
+#include "context.h"
+#include "depth.h"
+#include "enable.h"
+#include "enums.h"
+#include "fog.h"
+#include "hint.h"
+#include "light.h"
+#include "lines.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mfeatures.h"
+#include "multisample.h"
+#include "points.h"
+#include "polygon.h"
+#include "scissor.h"
+#include "stencil.h"
+#include "texenv.h"
+#include "texgen.h"
+#include "texobj.h"
+#include "texparam.h"
+#include "texstate.h"
+#include "varray.h"
+#include "viewport.h"
+#include "mtypes.h"
+#include "main/dispatch.h"
+
+
+/**
+ * glEnable()/glDisable() attribute group (GL_ENABLE_BIT).
+ */
+struct gl_enable_attrib
+{
+ GLboolean AlphaTest;
+ GLboolean AutoNormal;
+ GLboolean Blend;
+ GLbitfield ClipPlanes;
+ GLboolean ColorMaterial;
+ GLboolean CullFace;
+ GLboolean DepthClamp;
+ GLboolean DepthTest;
+ GLboolean Dither;
+ GLboolean Fog;
+ GLboolean Light[MAX_LIGHTS];
+ GLboolean Lighting;
+ GLboolean LineSmooth;
+ GLboolean LineStipple;
+ GLboolean IndexLogicOp;
+ GLboolean ColorLogicOp;
+
+ GLboolean Map1Color4;
+ GLboolean Map1Index;
+ GLboolean Map1Normal;
+ GLboolean Map1TextureCoord1;
+ GLboolean Map1TextureCoord2;
+ GLboolean Map1TextureCoord3;
+ GLboolean Map1TextureCoord4;
+ GLboolean Map1Vertex3;
+ GLboolean Map1Vertex4;
+ GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean Map2Color4;
+ GLboolean Map2Index;
+ GLboolean Map2Normal;
+ GLboolean Map2TextureCoord1;
+ GLboolean Map2TextureCoord2;
+ GLboolean Map2TextureCoord3;
+ GLboolean Map2TextureCoord4;
+ GLboolean Map2Vertex3;
+ GLboolean Map2Vertex4;
+ GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
+
+ GLboolean Normalize;
+ GLboolean PixelTexture;
+ GLboolean PointSmooth;
+ GLboolean PolygonOffsetPoint;
+ GLboolean PolygonOffsetLine;
+ GLboolean PolygonOffsetFill;
+ GLboolean PolygonSmooth;
+ GLboolean PolygonStipple;
+ GLboolean RescaleNormals;
+ GLboolean Scissor;
+ GLboolean Stencil;
+ GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */
+ GLboolean MultisampleEnabled; /* GL_ARB_multisample */
+ GLboolean SampleAlphaToCoverage; /* GL_ARB_multisample */
+ GLboolean SampleAlphaToOne; /* GL_ARB_multisample */
+ GLboolean SampleCoverage; /* GL_ARB_multisample */
+ GLboolean SampleCoverageInvert; /* GL_ARB_multisample */
+ GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */
+
+ GLbitfield Texture[MAX_TEXTURE_UNITS];
+ GLbitfield TexGen[MAX_TEXTURE_UNITS];
+
+ /* GL_ARB_vertex_program / GL_NV_vertex_program */
+ GLboolean VertexProgram;
+ GLboolean VertexProgramPointSize;
+ GLboolean VertexProgramTwoSide;
+
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ GLboolean PointSprite;
+ GLboolean FragmentShaderATI;
+};
+
+
+/**
+ * Node for the attribute stack.
+ */
+struct gl_attrib_node
+{
+ GLbitfield kind;
+ void *data;
+ struct gl_attrib_node *next;
+};
+
+
+
+/**
+ * Special struct for saving/restoring texture state (GL_TEXTURE_BIT)
+ */
+struct texture_state
+{
+ struct gl_texture_attrib Texture; /**< The usual context state */
+
+ /** to save per texture object state (wrap modes, filters, etc): */
+ struct gl_texture_object SavedObj[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS];
+
+ /**
+ * To save references to texture objects (so they don't get accidentally
+ * deleted while saved in the attribute stack).
+ */
+ struct gl_texture_object *SavedTexRef[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS];
+};
+
+
+#if FEATURE_attrib_stack
+
+
+/**
+ * Allocate new attribute node of given type/kind. Attach payload data.
+ * Insert it into the linked list named by 'head'.
+ */
+static void
+save_attrib_data(struct gl_attrib_node **head,
+ GLbitfield kind, void *payload)
+{
+ struct gl_attrib_node *n = MALLOC_STRUCT(gl_attrib_node);
+ if (n) {
+ n->kind = kind;
+ n->data = payload;
+ /* insert at head */
+ n->next = *head;
+ *head = n;
+ }
+ else {
+ /* out of memory! */
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_PushAttrib(GLbitfield mask)
+{
+ struct gl_attrib_node *head;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glPushAttrib %x\n", (int) mask);
+
+ if (ctx->AttribStackDepth >= MAX_ATTRIB_STACK_DEPTH) {
+ _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushAttrib" );
+ return;
+ }
+
+ /* Build linked list of attribute nodes which save all attribute */
+ /* groups specified by the mask. */
+ head = NULL;
+
+ if (mask & GL_ACCUM_BUFFER_BIT) {
+ struct gl_accum_attrib *attr;
+ attr = MALLOC_STRUCT( gl_accum_attrib );
+ memcpy( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) );
+ save_attrib_data(&head, GL_ACCUM_BUFFER_BIT, attr);
+ }
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ GLuint i;
+ struct gl_colorbuffer_attrib *attr;
+ attr = MALLOC_STRUCT( gl_colorbuffer_attrib );
+ memcpy( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) );
+ /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++)
+ attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i];
+ save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr);
+ }
+
+ if (mask & GL_CURRENT_BIT) {
+ struct gl_current_attrib *attr;
+ FLUSH_CURRENT( ctx, 0 );
+ attr = MALLOC_STRUCT( gl_current_attrib );
+ memcpy( attr, &ctx->Current, sizeof(struct gl_current_attrib) );
+ save_attrib_data(&head, GL_CURRENT_BIT, attr);
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ struct gl_depthbuffer_attrib *attr;
+ attr = MALLOC_STRUCT( gl_depthbuffer_attrib );
+ memcpy( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) );
+ save_attrib_data(&head, GL_DEPTH_BUFFER_BIT, attr);
+ }
+
+ if (mask & GL_ENABLE_BIT) {
+ struct gl_enable_attrib *attr;
+ GLuint i;
+ attr = MALLOC_STRUCT( gl_enable_attrib );
+ /* Copy enable flags from all other attributes into the enable struct. */
+ attr->AlphaTest = ctx->Color.AlphaEnabled;
+ attr->AutoNormal = ctx->Eval.AutoNormal;
+ attr->Blend = ctx->Color.BlendEnabled;
+ attr->ClipPlanes = ctx->Transform.ClipPlanesEnabled;
+ attr->ColorMaterial = ctx->Light.ColorMaterialEnabled;
+ attr->CullFace = ctx->Polygon.CullFlag;
+ attr->DepthClamp = ctx->Transform.DepthClamp;
+ attr->DepthTest = ctx->Depth.Test;
+ attr->Dither = ctx->Color.DitherFlag;
+ attr->Fog = ctx->Fog.Enabled;
+ for (i = 0; i < ctx->Const.MaxLights; i++) {
+ attr->Light[i] = ctx->Light.Light[i].Enabled;
+ }
+ attr->Lighting = ctx->Light.Enabled;
+ attr->LineSmooth = ctx->Line.SmoothFlag;
+ attr->LineStipple = ctx->Line.StippleFlag;
+ attr->IndexLogicOp = ctx->Color.IndexLogicOpEnabled;
+ attr->ColorLogicOp = ctx->Color.ColorLogicOpEnabled;
+ attr->Map1Color4 = ctx->Eval.Map1Color4;
+ attr->Map1Index = ctx->Eval.Map1Index;
+ attr->Map1Normal = ctx->Eval.Map1Normal;
+ attr->Map1TextureCoord1 = ctx->Eval.Map1TextureCoord1;
+ attr->Map1TextureCoord2 = ctx->Eval.Map1TextureCoord2;
+ attr->Map1TextureCoord3 = ctx->Eval.Map1TextureCoord3;
+ attr->Map1TextureCoord4 = ctx->Eval.Map1TextureCoord4;
+ attr->Map1Vertex3 = ctx->Eval.Map1Vertex3;
+ attr->Map1Vertex4 = ctx->Eval.Map1Vertex4;
+ memcpy(attr->Map1Attrib, ctx->Eval.Map1Attrib, sizeof(ctx->Eval.Map1Attrib));
+ attr->Map2Color4 = ctx->Eval.Map2Color4;
+ attr->Map2Index = ctx->Eval.Map2Index;
+ attr->Map2Normal = ctx->Eval.Map2Normal;
+ attr->Map2TextureCoord1 = ctx->Eval.Map2TextureCoord1;
+ attr->Map2TextureCoord2 = ctx->Eval.Map2TextureCoord2;
+ attr->Map2TextureCoord3 = ctx->Eval.Map2TextureCoord3;
+ attr->Map2TextureCoord4 = ctx->Eval.Map2TextureCoord4;
+ attr->Map2Vertex3 = ctx->Eval.Map2Vertex3;
+ attr->Map2Vertex4 = ctx->Eval.Map2Vertex4;
+ memcpy(attr->Map2Attrib, ctx->Eval.Map2Attrib, sizeof(ctx->Eval.Map2Attrib));
+ attr->Normalize = ctx->Transform.Normalize;
+ attr->RasterPositionUnclipped = ctx->Transform.RasterPositionUnclipped;
+ attr->PointSmooth = ctx->Point.SmoothFlag;
+ attr->PointSprite = ctx->Point.PointSprite;
+ attr->PolygonOffsetPoint = ctx->Polygon.OffsetPoint;
+ attr->PolygonOffsetLine = ctx->Polygon.OffsetLine;
+ attr->PolygonOffsetFill = ctx->Polygon.OffsetFill;
+ attr->PolygonSmooth = ctx->Polygon.SmoothFlag;
+ attr->PolygonStipple = ctx->Polygon.StippleFlag;
+ attr->RescaleNormals = ctx->Transform.RescaleNormals;
+ attr->Scissor = ctx->Scissor.Enabled;
+ attr->Stencil = ctx->Stencil.Enabled;
+ attr->StencilTwoSide = ctx->Stencil.TestTwoSide;
+ attr->MultisampleEnabled = ctx->Multisample.Enabled;
+ attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage;
+ attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne;
+ attr->SampleCoverage = ctx->Multisample.SampleCoverage;
+ attr->SampleCoverageInvert = ctx->Multisample.SampleCoverageInvert;
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ attr->Texture[i] = ctx->Texture.Unit[i].Enabled;
+ attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled;
+ }
+ /* GL_NV_vertex_program */
+ attr->VertexProgram = ctx->VertexProgram.Enabled;
+ attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled;
+ attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled;
+ save_attrib_data(&head, GL_ENABLE_BIT, attr);
+ }
+
+ if (mask & GL_EVAL_BIT) {
+ struct gl_eval_attrib *attr;
+ attr = MALLOC_STRUCT( gl_eval_attrib );
+ memcpy( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) );
+ save_attrib_data(&head, GL_EVAL_BIT, attr);
+ }
+
+ if (mask & GL_FOG_BIT) {
+ struct gl_fog_attrib *attr;
+ attr = MALLOC_STRUCT( gl_fog_attrib );
+ memcpy( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) );
+ save_attrib_data(&head, GL_FOG_BIT, attr);
+ }
+
+ if (mask & GL_HINT_BIT) {
+ struct gl_hint_attrib *attr;
+ attr = MALLOC_STRUCT( gl_hint_attrib );
+ memcpy( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) );
+ save_attrib_data(&head, GL_HINT_BIT, attr);
+ }
+
+ if (mask & GL_LIGHTING_BIT) {
+ struct gl_light_attrib *attr;
+ FLUSH_CURRENT(ctx, 0); /* flush material changes */
+ attr = MALLOC_STRUCT( gl_light_attrib );
+ memcpy( attr, &ctx->Light, sizeof(struct gl_light_attrib) );
+ save_attrib_data(&head, GL_LIGHTING_BIT, attr);
+ }
+
+ if (mask & GL_LINE_BIT) {
+ struct gl_line_attrib *attr;
+ attr = MALLOC_STRUCT( gl_line_attrib );
+ memcpy( attr, &ctx->Line, sizeof(struct gl_line_attrib) );
+ save_attrib_data(&head, GL_LINE_BIT, attr);
+ }
+
+ if (mask & GL_LIST_BIT) {
+ struct gl_list_attrib *attr;
+ attr = MALLOC_STRUCT( gl_list_attrib );
+ memcpy( attr, &ctx->List, sizeof(struct gl_list_attrib) );
+ save_attrib_data(&head, GL_LIST_BIT, attr);
+ }
+
+ if (mask & GL_PIXEL_MODE_BIT) {
+ struct gl_pixel_attrib *attr;
+ attr = MALLOC_STRUCT( gl_pixel_attrib );
+ memcpy( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) );
+ /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */
+ attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer;
+ save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr);
+ }
+
+ if (mask & GL_POINT_BIT) {
+ struct gl_point_attrib *attr;
+ attr = MALLOC_STRUCT( gl_point_attrib );
+ memcpy( attr, &ctx->Point, sizeof(struct gl_point_attrib) );
+ save_attrib_data(&head, GL_POINT_BIT, attr);
+ }
+
+ if (mask & GL_POLYGON_BIT) {
+ struct gl_polygon_attrib *attr;
+ attr = MALLOC_STRUCT( gl_polygon_attrib );
+ memcpy( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) );
+ save_attrib_data(&head, GL_POLYGON_BIT, attr);
+ }
+
+ if (mask & GL_POLYGON_STIPPLE_BIT) {
+ GLuint *stipple;
+ stipple = (GLuint *) MALLOC( 32*sizeof(GLuint) );
+ memcpy( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) );
+ save_attrib_data(&head, GL_POLYGON_STIPPLE_BIT, stipple);
+ }
+
+ if (mask & GL_SCISSOR_BIT) {
+ struct gl_scissor_attrib *attr;
+ attr = MALLOC_STRUCT( gl_scissor_attrib );
+ memcpy( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) );
+ save_attrib_data(&head, GL_SCISSOR_BIT, attr);
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ struct gl_stencil_attrib *attr;
+ attr = MALLOC_STRUCT( gl_stencil_attrib );
+ memcpy( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) );
+ save_attrib_data(&head, GL_STENCIL_BUFFER_BIT, attr);
+ }
+
+ if (mask & GL_TEXTURE_BIT) {
+ struct texture_state *texstate = CALLOC_STRUCT(texture_state);
+ GLuint u, tex;
+
+ if (!texstate) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)");
+ goto end;
+ }
+
+ _mesa_lock_context_textures(ctx);
+
+ /* copy/save the bulk of texture state here */
+ memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture));
+
+ /* Save references to the currently bound texture objects so they don't
+ * accidentally get deleted while referenced in the attribute stack.
+ */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texstate->SavedTexRef[u][tex],
+ ctx->Texture.Unit[u].CurrentTex[tex]);
+ }
+ }
+
+ /* copy state/contents of the currently bound texture objects */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_copy_texture_object(&texstate->SavedObj[u][tex],
+ ctx->Texture.Unit[u].CurrentTex[tex]);
+ }
+ }
+
+ _mesa_unlock_context_textures(ctx);
+
+ save_attrib_data(&head, GL_TEXTURE_BIT, texstate);
+ }
+
+ if (mask & GL_TRANSFORM_BIT) {
+ struct gl_transform_attrib *attr;
+ attr = MALLOC_STRUCT( gl_transform_attrib );
+ memcpy( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) );
+ save_attrib_data(&head, GL_TRANSFORM_BIT, attr);
+ }
+
+ if (mask & GL_VIEWPORT_BIT) {
+ struct gl_viewport_attrib *attr;
+ attr = MALLOC_STRUCT( gl_viewport_attrib );
+ memcpy( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) );
+ save_attrib_data(&head, GL_VIEWPORT_BIT, attr);
+ }
+
+ /* GL_ARB_multisample */
+ if (mask & GL_MULTISAMPLE_BIT_ARB) {
+ struct gl_multisample_attrib *attr;
+ attr = MALLOC_STRUCT( gl_multisample_attrib );
+ memcpy( attr, &ctx->Multisample, sizeof(struct gl_multisample_attrib) );
+ save_attrib_data(&head, GL_MULTISAMPLE_BIT_ARB, attr);
+ }
+
+end:
+ ctx->AttribStack[ctx->AttribStackDepth] = head;
+ ctx->AttribStackDepth++;
+}
+
+
+
+static void
+pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
+{
+ const GLuint curTexUnitSave = ctx->Texture.CurrentUnit;
+ GLuint i;
+
+#define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \
+ if ((VALUE) != (NEWVALUE)) { \
+ _mesa_set_enable( ctx, ENUM, (NEWVALUE) ); \
+ }
+
+ TEST_AND_UPDATE(ctx->Color.AlphaEnabled, enable->AlphaTest, GL_ALPHA_TEST);
+ if (ctx->Color.BlendEnabled != enable->Blend) {
+ if (ctx->Extensions.EXT_draw_buffers2) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ _mesa_set_enablei(ctx, GL_BLEND, i, (enable->Blend >> i) & 1);
+ }
+ }
+ else {
+ _mesa_set_enable(ctx, GL_BLEND, (enable->Blend & 1));
+ }
+ }
+
+ for (i=0;i<MAX_CLIP_PLANES;i++) {
+ const GLuint mask = 1 << i;
+ if ((ctx->Transform.ClipPlanesEnabled & mask) != (enable->ClipPlanes & mask))
+ _mesa_set_enable(ctx, (GLenum) (GL_CLIP_PLANE0 + i),
+ (GLboolean) ((enable->ClipPlanes & mask) ? GL_TRUE : GL_FALSE));
+ }
+
+ TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial,
+ GL_COLOR_MATERIAL);
+ TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE);
+ TEST_AND_UPDATE(ctx->Transform.DepthClamp, enable->DepthClamp,
+ GL_DEPTH_CLAMP);
+ TEST_AND_UPDATE(ctx->Depth.Test, enable->DepthTest, GL_DEPTH_TEST);
+ TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER);
+ TEST_AND_UPDATE(ctx->Fog.Enabled, enable->Fog, GL_FOG);
+ TEST_AND_UPDATE(ctx->Light.Enabled, enable->Lighting, GL_LIGHTING);
+ TEST_AND_UPDATE(ctx->Line.SmoothFlag, enable->LineSmooth, GL_LINE_SMOOTH);
+ TEST_AND_UPDATE(ctx->Line.StippleFlag, enable->LineStipple,
+ GL_LINE_STIPPLE);
+ TEST_AND_UPDATE(ctx->Color.IndexLogicOpEnabled, enable->IndexLogicOp,
+ GL_INDEX_LOGIC_OP);
+ TEST_AND_UPDATE(ctx->Color.ColorLogicOpEnabled, enable->ColorLogicOp,
+ GL_COLOR_LOGIC_OP);
+
+ TEST_AND_UPDATE(ctx->Eval.Map1Color4, enable->Map1Color4, GL_MAP1_COLOR_4);
+ TEST_AND_UPDATE(ctx->Eval.Map1Index, enable->Map1Index, GL_MAP1_INDEX);
+ TEST_AND_UPDATE(ctx->Eval.Map1Normal, enable->Map1Normal, GL_MAP1_NORMAL);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord1, enable->Map1TextureCoord1,
+ GL_MAP1_TEXTURE_COORD_1);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord2, enable->Map1TextureCoord2,
+ GL_MAP1_TEXTURE_COORD_2);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord3, enable->Map1TextureCoord3,
+ GL_MAP1_TEXTURE_COORD_3);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord4, enable->Map1TextureCoord4,
+ GL_MAP1_TEXTURE_COORD_4);
+ TEST_AND_UPDATE(ctx->Eval.Map1Vertex3, enable->Map1Vertex3,
+ GL_MAP1_VERTEX_3);
+ TEST_AND_UPDATE(ctx->Eval.Map1Vertex4, enable->Map1Vertex4,
+ GL_MAP1_VERTEX_4);
+ for (i = 0; i < 16; i++) {
+ TEST_AND_UPDATE(ctx->Eval.Map1Attrib[i], enable->Map1Attrib[i],
+ GL_MAP1_VERTEX_ATTRIB0_4_NV + i);
+ }
+
+ TEST_AND_UPDATE(ctx->Eval.Map2Color4, enable->Map2Color4, GL_MAP2_COLOR_4);
+ TEST_AND_UPDATE(ctx->Eval.Map2Index, enable->Map2Index, GL_MAP2_INDEX);
+ TEST_AND_UPDATE(ctx->Eval.Map2Normal, enable->Map2Normal, GL_MAP2_NORMAL);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord1, enable->Map2TextureCoord1,
+ GL_MAP2_TEXTURE_COORD_1);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord2, enable->Map2TextureCoord2,
+ GL_MAP2_TEXTURE_COORD_2);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord3, enable->Map2TextureCoord3,
+ GL_MAP2_TEXTURE_COORD_3);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord4, enable->Map2TextureCoord4,
+ GL_MAP2_TEXTURE_COORD_4);
+ TEST_AND_UPDATE(ctx->Eval.Map2Vertex3, enable->Map2Vertex3,
+ GL_MAP2_VERTEX_3);
+ TEST_AND_UPDATE(ctx->Eval.Map2Vertex4, enable->Map2Vertex4,
+ GL_MAP2_VERTEX_4);
+ for (i = 0; i < 16; i++) {
+ TEST_AND_UPDATE(ctx->Eval.Map2Attrib[i], enable->Map2Attrib[i],
+ GL_MAP2_VERTEX_ATTRIB0_4_NV + i);
+ }
+
+ TEST_AND_UPDATE(ctx->Eval.AutoNormal, enable->AutoNormal, GL_AUTO_NORMAL);
+ TEST_AND_UPDATE(ctx->Transform.Normalize, enable->Normalize, GL_NORMALIZE);
+ TEST_AND_UPDATE(ctx->Transform.RescaleNormals, enable->RescaleNormals,
+ GL_RESCALE_NORMAL_EXT);
+ TEST_AND_UPDATE(ctx->Transform.RasterPositionUnclipped,
+ enable->RasterPositionUnclipped,
+ GL_RASTER_POSITION_UNCLIPPED_IBM);
+ TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth,
+ GL_POINT_SMOOTH);
+ if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) {
+ TEST_AND_UPDATE(ctx->Point.PointSprite, enable->PointSprite,
+ GL_POINT_SPRITE_NV);
+ }
+ TEST_AND_UPDATE(ctx->Polygon.OffsetPoint, enable->PolygonOffsetPoint,
+ GL_POLYGON_OFFSET_POINT);
+ TEST_AND_UPDATE(ctx->Polygon.OffsetLine, enable->PolygonOffsetLine,
+ GL_POLYGON_OFFSET_LINE);
+ TEST_AND_UPDATE(ctx->Polygon.OffsetFill, enable->PolygonOffsetFill,
+ GL_POLYGON_OFFSET_FILL);
+ TEST_AND_UPDATE(ctx->Polygon.SmoothFlag, enable->PolygonSmooth,
+ GL_POLYGON_SMOOTH);
+ TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple,
+ GL_POLYGON_STIPPLE);
+ TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST);
+ TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST);
+ if (ctx->Extensions.EXT_stencil_two_side) {
+ TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT);
+ }
+ TEST_AND_UPDATE(ctx->Multisample.Enabled, enable->MultisampleEnabled,
+ GL_MULTISAMPLE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage,
+ enable->SampleAlphaToCoverage,
+ GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToOne,
+ enable->SampleAlphaToOne,
+ GL_SAMPLE_ALPHA_TO_ONE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleCoverage,
+ enable->SampleCoverage,
+ GL_SAMPLE_COVERAGE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleCoverageInvert,
+ enable->SampleCoverageInvert,
+ GL_SAMPLE_COVERAGE_INVERT_ARB);
+ /* GL_ARB_vertex_program, GL_NV_vertex_program */
+ TEST_AND_UPDATE(ctx->VertexProgram.Enabled,
+ enable->VertexProgram,
+ GL_VERTEX_PROGRAM_ARB);
+ TEST_AND_UPDATE(ctx->VertexProgram.PointSizeEnabled,
+ enable->VertexProgramPointSize,
+ GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
+ TEST_AND_UPDATE(ctx->VertexProgram.TwoSideEnabled,
+ enable->VertexProgramTwoSide,
+ GL_VERTEX_PROGRAM_TWO_SIDE_ARB);
+
+#undef TEST_AND_UPDATE
+
+ /* texture unit enables */
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ const GLbitfield enabled = enable->Texture[i];
+ const GLbitfield genEnabled = enable->TexGen[i];
+
+ if (ctx->Texture.Unit[i].Enabled != enabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+
+ _mesa_set_enable(ctx, GL_TEXTURE_1D,
+ (enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D,
+ (enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D,
+ (enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE);
+ if (ctx->Extensions.NV_texture_rectangle) {
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_ARB,
+ (enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP,
+ (enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.MESA_texture_array) {
+ _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
+ (enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
+ (enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ }
+
+ if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
+ (genEnabled & S_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T,
+ (genEnabled & T_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R,
+ (genEnabled & R_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q,
+ (genEnabled & Q_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ }
+
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + curTexUnitSave);
+}
+
+
+/**
+ * Pop/restore texture attribute/group state.
+ */
+static void
+pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
+{
+ GLuint u;
+
+ _mesa_lock_context_textures(ctx);
+
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ const struct gl_texture_unit *unit = &texstate->Texture.Unit[u];
+ GLuint tgt;
+
+ _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u);
+ _mesa_set_enable(ctx, GL_TEXTURE_1D,
+ (unit->Enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D,
+ (unit->Enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D,
+ (unit->Enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE);
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB,
+ (unit->Enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.NV_texture_rectangle) {
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV,
+ (unit->Enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.MESA_texture_array) {
+ _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
+ (unit->Enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
+ (unit->Enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ }
+
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode);
+ _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor);
+ _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode);
+ _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenT.Mode);
+ _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenR.Mode);
+ _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenQ.Mode);
+ _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->GenS.ObjectPlane);
+ _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->GenT.ObjectPlane);
+ _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->GenR.ObjectPlane);
+ _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->GenQ.ObjectPlane);
+ /* Eye plane done differently to avoid re-transformation */
+ {
+ struct gl_texture_unit *destUnit = &ctx->Texture.Unit[u];
+ COPY_4FV(destUnit->GenS.EyePlane, unit->GenS.EyePlane);
+ COPY_4FV(destUnit->GenT.EyePlane, unit->GenT.EyePlane);
+ COPY_4FV(destUnit->GenR.EyePlane, unit->GenR.EyePlane);
+ COPY_4FV(destUnit->GenQ.EyePlane, unit->GenQ.EyePlane);
+ if (ctx->Driver.TexGen) {
+ ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->GenS.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->GenT.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->GenR.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->GenQ.EyePlane);
+ }
+ }
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
+ ((unit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE));
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T,
+ ((unit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE));
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R,
+ ((unit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE));
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q,
+ ((unit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE));
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
+ GL_TEXTURE_LOD_BIAS_EXT, unit->LodBias);
+ }
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,
+ unit->Combine.ModeRGB);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,
+ unit->Combine.ModeA);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB,
+ unit->Combine.SourceRGB[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB,
+ unit->Combine.SourceRGB[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB,
+ unit->Combine.SourceRGB[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA,
+ unit->Combine.SourceA[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA,
+ unit->Combine.SourceA[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA,
+ unit->Combine.SourceA[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB,
+ unit->Combine.OperandRGB[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB,
+ unit->Combine.OperandRGB[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,
+ unit->Combine.OperandRGB[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA,
+ unit->Combine.OperandA[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA,
+ unit->Combine.OperandA[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
+ unit->Combine.OperandA[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE,
+ 1 << unit->Combine.ScaleShiftRGB);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE,
+ 1 << unit->Combine.ScaleShiftA);
+ }
+
+ /* Restore texture object state for each target */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ const struct gl_texture_object *obj = NULL;
+ GLenum target;
+
+ obj = &texstate->SavedObj[u][tgt];
+
+ /* don't restore state for unsupported targets to prevent
+ * raising GL errors.
+ */
+ if (obj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
+ !ctx->Extensions.ARB_texture_cube_map) {
+ continue;
+ }
+ else if (obj->Target == GL_TEXTURE_RECTANGLE_NV &&
+ !ctx->Extensions.NV_texture_rectangle) {
+ continue;
+ }
+ else if ((obj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
+ obj->Target == GL_TEXTURE_2D_ARRAY_EXT) &&
+ !ctx->Extensions.MESA_texture_array) {
+ continue;
+ }
+
+ target = obj->Target;
+
+ _mesa_BindTexture(target, obj->Name);
+
+ _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, obj->BorderColor.f);
+ _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, obj->WrapR);
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, obj->MinFilter);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, obj->MagFilter);
+ _mesa_TexParameterf(target, GL_TEXTURE_MIN_LOD, obj->MinLod);
+ _mesa_TexParameterf(target, GL_TEXTURE_MAX_LOD, obj->MaxLod);
+ _mesa_TexParameterf(target, GL_TEXTURE_LOD_BIAS, obj->LodBias);
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, obj->BaseLevel);
+ if (target != GL_TEXTURE_RECTANGLE_ARB)
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel);
+ if (ctx->Extensions.EXT_texture_filter_anisotropic) {
+ _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ obj->MaxAnisotropy);
+ }
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ _mesa_TexParameterf(target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
+ obj->CompareFailValue);
+ }
+ }
+
+ /* remove saved references to the texture objects */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL);
+ }
+ }
+
+ _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit);
+
+ _mesa_unlock_context_textures(ctx);
+}
+
+
+/*
+ * This function is kind of long just because we have to call a lot
+ * of device driver functions to update device driver state.
+ *
+ * XXX As it is now, most of the pop-code calls immediate-mode Mesa functions
+ * in order to restore GL state. This isn't terribly efficient but it
+ * ensures that dirty flags and any derived state gets updated correctly.
+ * We could at least check if the value to restore equals the current value
+ * and then skip the Mesa call.
+ */
+void GLAPIENTRY
+_mesa_PopAttrib(void)
+{
+ struct gl_attrib_node *attr, *next;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (ctx->AttribStackDepth == 0) {
+ _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" );
+ return;
+ }
+
+ ctx->AttribStackDepth--;
+ attr = ctx->AttribStack[ctx->AttribStackDepth];
+
+ while (attr) {
+
+ if (MESA_VERBOSE & VERBOSE_API) {
+ _mesa_debug(ctx, "glPopAttrib %s\n",
+ _mesa_lookup_enum_by_nr(attr->kind));
+ }
+
+ switch (attr->kind) {
+ case GL_ACCUM_BUFFER_BIT:
+ {
+ const struct gl_accum_attrib *accum;
+ accum = (const struct gl_accum_attrib *) attr->data;
+ _mesa_ClearAccum(accum->ClearColor[0],
+ accum->ClearColor[1],
+ accum->ClearColor[2],
+ accum->ClearColor[3]);
+ }
+ break;
+ case GL_COLOR_BUFFER_BIT:
+ {
+ const struct gl_colorbuffer_attrib *color;
+
+ color = (const struct gl_colorbuffer_attrib *) attr->data;
+ _mesa_ClearIndex((GLfloat) color->ClearIndex);
+ _mesa_ClearColor(color->ClearColor[0],
+ color->ClearColor[1],
+ color->ClearColor[2],
+ color->ClearColor[3]);
+ _mesa_IndexMask(color->IndexMask);
+ if (!ctx->Extensions.EXT_draw_buffers2) {
+ _mesa_ColorMask((GLboolean) (color->ColorMask[0][0] != 0),
+ (GLboolean) (color->ColorMask[0][1] != 0),
+ (GLboolean) (color->ColorMask[0][2] != 0),
+ (GLboolean) (color->ColorMask[0][3] != 0));
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ _mesa_ColorMaskIndexed(i,
+ (GLboolean) (color->ColorMask[i][0] != 0),
+ (GLboolean) (color->ColorMask[i][1] != 0),
+ (GLboolean) (color->ColorMask[i][2] != 0),
+ (GLboolean) (color->ColorMask[i][3] != 0));
+ }
+ }
+ {
+ /* Need to determine if more than one color output is
+ * specified. If so, call glDrawBuffersARB, else call
+ * glDrawBuffer(). This is a subtle, but essential point
+ * since GL_FRONT (for example) is illegal for the former
+ * function, but legal for the later.
+ */
+ GLboolean multipleBuffers = GL_FALSE;
+ GLuint i;
+
+ for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (color->DrawBuffer[i] != GL_NONE) {
+ multipleBuffers = GL_TRUE;
+ break;
+ }
+ }
+ /* Call the API_level functions, not _mesa_drawbuffers()
+ * since we need to do error checking on the pop'd
+ * GL_DRAW_BUFFER.
+ * Ex: if GL_FRONT were pushed, but we're popping with a
+ * user FBO bound, GL_FRONT will be illegal and we'll need
+ * to record that error. Per OpenGL ARB decision.
+ */
+ if (multipleBuffers)
+ _mesa_DrawBuffersARB(ctx->Const.MaxDrawBuffers,
+ color->DrawBuffer);
+ else
+ _mesa_DrawBuffer(color->DrawBuffer[0]);
+ }
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled);
+ _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRef);
+ if (ctx->Color.BlendEnabled != color->BlendEnabled) {
+ if (ctx->Extensions.EXT_draw_buffers2) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ _mesa_set_enablei(ctx, GL_BLEND, i,
+ (color->BlendEnabled >> i) & 1);
+ }
+ }
+ else {
+ _mesa_set_enable(ctx, GL_BLEND, (color->BlendEnabled & 1));
+ }
+ }
+ if (ctx->Color._BlendFuncPerBuffer ||
+ ctx->Color._BlendEquationPerBuffer) {
+ /* set blend per buffer */
+ GLuint buf;
+ for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
+ _mesa_BlendFuncSeparatei(buf, color->Blend[buf].SrcRGB,
+ color->Blend[buf].DstRGB,
+ color->Blend[buf].SrcA,
+ color->Blend[buf].DstA);
+ _mesa_BlendEquationSeparatei(buf,
+ color->Blend[buf].EquationRGB,
+ color->Blend[buf].EquationA);
+ }
+ }
+ else {
+ /* set same blend modes for all buffers */
+ _mesa_BlendFuncSeparateEXT(color->Blend[0].SrcRGB,
+ color->Blend[0].DstRGB,
+ color->Blend[0].SrcA,
+ color->Blend[0].DstA);
+ /* This special case is because glBlendEquationSeparateEXT
+ * cannot take GL_LOGIC_OP as a parameter.
+ */
+ if (color->Blend[0].EquationRGB ==
+ color->Blend[0].EquationA) {
+ _mesa_BlendEquation(color->Blend[0].EquationRGB);
+ }
+ else {
+ _mesa_BlendEquationSeparateEXT(
+ color->Blend[0].EquationRGB,
+ color->Blend[0].EquationA);
+ }
+ }
+ _mesa_BlendColor(color->BlendColor[0],
+ color->BlendColor[1],
+ color->BlendColor[2],
+ color->BlendColor[3]);
+ _mesa_LogicOp(color->LogicOp);
+ _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP,
+ color->ColorLogicOpEnabled);
+ _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP,
+ color->IndexLogicOpEnabled);
+ _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag);
+ }
+ break;
+ case GL_CURRENT_BIT:
+ FLUSH_CURRENT( ctx, 0 );
+ memcpy( &ctx->Current, attr->data,
+ sizeof(struct gl_current_attrib) );
+ break;
+ case GL_DEPTH_BUFFER_BIT:
+ {
+ const struct gl_depthbuffer_attrib *depth;
+ depth = (const struct gl_depthbuffer_attrib *) attr->data;
+ _mesa_DepthFunc(depth->Func);
+ _mesa_ClearDepth(depth->Clear);
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test);
+ _mesa_DepthMask(depth->Mask);
+ }
+ break;
+ case GL_ENABLE_BIT:
+ {
+ const struct gl_enable_attrib *enable;
+ enable = (const struct gl_enable_attrib *) attr->data;
+ pop_enable_group(ctx, enable);
+ ctx->NewState |= _NEW_ALL;
+ }
+ break;
+ case GL_EVAL_BIT:
+ memcpy( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) );
+ ctx->NewState |= _NEW_EVAL;
+ break;
+ case GL_FOG_BIT:
+ {
+ const struct gl_fog_attrib *fog;
+ fog = (const struct gl_fog_attrib *) attr->data;
+ _mesa_set_enable(ctx, GL_FOG, fog->Enabled);
+ _mesa_Fogfv(GL_FOG_COLOR, fog->Color);
+ _mesa_Fogf(GL_FOG_DENSITY, fog->Density);
+ _mesa_Fogf(GL_FOG_START, fog->Start);
+ _mesa_Fogf(GL_FOG_END, fog->End);
+ _mesa_Fogf(GL_FOG_INDEX, fog->Index);
+ _mesa_Fogi(GL_FOG_MODE, fog->Mode);
+ }
+ break;
+ case GL_HINT_BIT:
+ {
+ const struct gl_hint_attrib *hint;
+ hint = (const struct gl_hint_attrib *) attr->data;
+ _mesa_Hint(GL_PERSPECTIVE_CORRECTION_HINT,
+ hint->PerspectiveCorrection );
+ _mesa_Hint(GL_POINT_SMOOTH_HINT, hint->PointSmooth);
+ _mesa_Hint(GL_LINE_SMOOTH_HINT, hint->LineSmooth);
+ _mesa_Hint(GL_POLYGON_SMOOTH_HINT, hint->PolygonSmooth);
+ _mesa_Hint(GL_FOG_HINT, hint->Fog);
+ _mesa_Hint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT,
+ hint->ClipVolumeClipping);
+ _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB,
+ hint->TextureCompression);
+ }
+ break;
+ case GL_LIGHTING_BIT:
+ {
+ GLuint i;
+ const struct gl_light_attrib *light;
+ light = (const struct gl_light_attrib *) attr->data;
+ /* lighting enable */
+ _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled);
+ /* per-light state */
+ if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top))
+ _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
+
+ for (i = 0; i < ctx->Const.MaxLights; i++) {
+ const struct gl_light *l = &light->Light[i];
+ _mesa_set_enable(ctx, GL_LIGHT0 + i, l->Enabled);
+ _mesa_light(ctx, i, GL_AMBIENT, l->Ambient);
+ _mesa_light(ctx, i, GL_DIFFUSE, l->Diffuse);
+ _mesa_light(ctx, i, GL_SPECULAR, l->Specular );
+ _mesa_light(ctx, i, GL_POSITION, l->EyePosition);
+ _mesa_light(ctx, i, GL_SPOT_DIRECTION, l->SpotDirection);
+ {
+ GLfloat p[4] = { 0 };
+ p[0] = l->SpotExponent;
+ _mesa_light(ctx, i, GL_SPOT_EXPONENT, p);
+ }
+ {
+ GLfloat p[4] = { 0 };
+ p[0] = l->SpotCutoff;
+ _mesa_light(ctx, i, GL_SPOT_CUTOFF, p);
+ }
+ {
+ GLfloat p[4] = { 0 };
+ p[0] = l->ConstantAttenuation;
+ _mesa_light(ctx, i, GL_CONSTANT_ATTENUATION, p);
+ }
+ {
+ GLfloat p[4] = { 0 };
+ p[0] = l->LinearAttenuation;
+ _mesa_light(ctx, i, GL_LINEAR_ATTENUATION, p);
+ }
+ {
+ GLfloat p[4] = { 0 };
+ p[0] = l->QuadraticAttenuation;
+ _mesa_light(ctx, i, GL_QUADRATIC_ATTENUATION, p);
+ }
+ }
+ /* light model */
+ _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT,
+ light->Model.Ambient);
+ _mesa_LightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,
+ (GLfloat) light->Model.LocalViewer);
+ _mesa_LightModelf(GL_LIGHT_MODEL_TWO_SIDE,
+ (GLfloat) light->Model.TwoSide);
+ _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL,
+ (GLfloat) light->Model.ColorControl);
+ /* shade model */
+ _mesa_ShadeModel(light->ShadeModel);
+ /* color material */
+ _mesa_ColorMaterial(light->ColorMaterialFace,
+ light->ColorMaterialMode);
+ _mesa_set_enable(ctx, GL_COLOR_MATERIAL,
+ light->ColorMaterialEnabled);
+ /* materials */
+ memcpy(&ctx->Light.Material, &light->Material,
+ sizeof(struct gl_material));
+ }
+ break;
+ case GL_LINE_BIT:
+ {
+ const struct gl_line_attrib *line;
+ line = (const struct gl_line_attrib *) attr->data;
+ _mesa_set_enable(ctx, GL_LINE_SMOOTH, line->SmoothFlag);
+ _mesa_set_enable(ctx, GL_LINE_STIPPLE, line->StippleFlag);
+ _mesa_LineStipple(line->StippleFactor, line->StipplePattern);
+ _mesa_LineWidth(line->Width);
+ }
+ break;
+ case GL_LIST_BIT:
+ memcpy( &ctx->List, attr->data, sizeof(struct gl_list_attrib) );
+ break;
+ case GL_PIXEL_MODE_BIT:
+ memcpy( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) );
+ /* XXX what other pixel state needs to be set by function calls? */
+ _mesa_ReadBuffer(ctx->Pixel.ReadBuffer);
+ ctx->NewState |= _NEW_PIXEL;
+ break;
+ case GL_POINT_BIT:
+ {
+ const struct gl_point_attrib *point;
+ point = (const struct gl_point_attrib *) attr->data;
+ _mesa_PointSize(point->Size);
+ _mesa_set_enable(ctx, GL_POINT_SMOOTH, point->SmoothFlag);
+ if (ctx->Extensions.EXT_point_parameters) {
+ _mesa_PointParameterfv(GL_DISTANCE_ATTENUATION_EXT,
+ point->Params);
+ _mesa_PointParameterf(GL_POINT_SIZE_MIN_EXT,
+ point->MinSize);
+ _mesa_PointParameterf(GL_POINT_SIZE_MAX_EXT,
+ point->MaxSize);
+ _mesa_PointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT,
+ point->Threshold);
+ }
+ if (ctx->Extensions.NV_point_sprite
+ || ctx->Extensions.ARB_point_sprite) {
+ GLuint u;
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ _mesa_TexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV,
+ (GLint) point->CoordReplace[u]);
+ }
+ _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite);
+ if (ctx->Extensions.NV_point_sprite)
+ _mesa_PointParameteri(GL_POINT_SPRITE_R_MODE_NV,
+ ctx->Point.SpriteRMode);
+ _mesa_PointParameterf(GL_POINT_SPRITE_COORD_ORIGIN,
+ (GLfloat)ctx->Point.SpriteOrigin);
+ }
+ }
+ break;
+ case GL_POLYGON_BIT:
+ {
+ const struct gl_polygon_attrib *polygon;
+ polygon = (const struct gl_polygon_attrib *) attr->data;
+ _mesa_CullFace(polygon->CullFaceMode);
+ _mesa_FrontFace(polygon->FrontFace);
+ _mesa_PolygonMode(GL_FRONT, polygon->FrontMode);
+ _mesa_PolygonMode(GL_BACK, polygon->BackMode);
+ _mesa_PolygonOffset(polygon->OffsetFactor,
+ polygon->OffsetUnits);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, polygon->SmoothFlag);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, polygon->StippleFlag);
+ _mesa_set_enable(ctx, GL_CULL_FACE, polygon->CullFlag);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_POINT,
+ polygon->OffsetPoint);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_LINE,
+ polygon->OffsetLine);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL,
+ polygon->OffsetFill);
+ }
+ break;
+ case GL_POLYGON_STIPPLE_BIT:
+ memcpy( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) );
+ ctx->NewState |= _NEW_POLYGONSTIPPLE;
+ if (ctx->Driver.PolygonStipple)
+ ctx->Driver.PolygonStipple( ctx, (const GLubyte *) attr->data );
+ break;
+ case GL_SCISSOR_BIT:
+ {
+ const struct gl_scissor_attrib *scissor;
+ scissor = (const struct gl_scissor_attrib *) attr->data;
+ _mesa_Scissor(scissor->X, scissor->Y,
+ scissor->Width, scissor->Height);
+ _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->Enabled);
+ }
+ break;
+ case GL_STENCIL_BUFFER_BIT:
+ {
+ const struct gl_stencil_attrib *stencil;
+ stencil = (const struct gl_stencil_attrib *) attr->data;
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
+ _mesa_ClearStencil(stencil->Clear);
+ if (ctx->Extensions.EXT_stencil_two_side) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
+ stencil->TestTwoSide);
+ _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
+ ? GL_BACK : GL_FRONT);
+ }
+ /* front state */
+ _mesa_StencilFuncSeparate(GL_FRONT,
+ stencil->Function[0],
+ stencil->Ref[0],
+ stencil->ValueMask[0]);
+ _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
+ _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
+ stencil->ZFailFunc[0],
+ stencil->ZPassFunc[0]);
+ /* back state */
+ _mesa_StencilFuncSeparate(GL_BACK,
+ stencil->Function[1],
+ stencil->Ref[1],
+ stencil->ValueMask[1]);
+ _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
+ _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
+ stencil->ZFailFunc[1],
+ stencil->ZPassFunc[1]);
+ }
+ break;
+ case GL_TRANSFORM_BIT:
+ {
+ GLuint i;
+ const struct gl_transform_attrib *xform;
+ xform = (const struct gl_transform_attrib *) attr->data;
+ _mesa_MatrixMode(xform->MatrixMode);
+ if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
+ /* restore clip planes */
+ for (i = 0; i < MAX_CLIP_PLANES; i++) {
+ const GLuint mask = 1 << i;
+ const GLfloat *eyePlane = xform->EyeUserPlane[i];
+ COPY_4V(ctx->Transform.EyeUserPlane[i], eyePlane);
+ if (xform->ClipPlanesEnabled & mask) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
+ }
+ else {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
+ }
+ if (ctx->Driver.ClipPlane)
+ ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, eyePlane );
+ }
+
+ /* normalize/rescale */
+ if (xform->Normalize != ctx->Transform.Normalize)
+ _mesa_set_enable(ctx, GL_NORMALIZE,ctx->Transform.Normalize);
+ if (xform->RescaleNormals != ctx->Transform.RescaleNormals)
+ _mesa_set_enable(ctx, GL_RESCALE_NORMAL_EXT,
+ ctx->Transform.RescaleNormals);
+ if (xform->DepthClamp != ctx->Transform.DepthClamp)
+ _mesa_set_enable(ctx, GL_DEPTH_CLAMP,
+ ctx->Transform.DepthClamp);
+ }
+ break;
+ case GL_TEXTURE_BIT:
+ /* Take care of texture object reference counters */
+ {
+ struct texture_state *texstate
+ = (struct texture_state *) attr->data;
+ pop_texture_group(ctx, texstate);
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ break;
+ case GL_VIEWPORT_BIT:
+ {
+ const struct gl_viewport_attrib *vp;
+ vp = (const struct gl_viewport_attrib *) attr->data;
+ _mesa_Viewport(vp->X, vp->Y, vp->Width, vp->Height);
+ _mesa_DepthRange(vp->Near, vp->Far);
+ }
+ break;
+ case GL_MULTISAMPLE_BIT_ARB:
+ {
+ const struct gl_multisample_attrib *ms;
+ ms = (const struct gl_multisample_attrib *) attr->data;
+ _mesa_SampleCoverageARB(ms->SampleCoverageValue,
+ ms->SampleCoverageInvert);
+ }
+ break;
+
+ default:
+ _mesa_problem( ctx, "Bad attrib flag in PopAttrib");
+ break;
+ }
+
+ next = attr->next;
+ FREE( attr->data );
+ FREE( attr );
+ attr = next;
+ }
+}
+
+
+/**
+ * Helper for incrementing/decrementing vertex buffer object reference
+ * counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
+ */
+static void
+adjust_buffer_object_ref_counts(struct gl_array_object *arrayObj, GLint step)
+{
+ GLuint i;
+
+ arrayObj->Vertex.BufferObj->RefCount += step;
+ arrayObj->Weight.BufferObj->RefCount += step;
+ arrayObj->Normal.BufferObj->RefCount += step;
+ arrayObj->Color.BufferObj->RefCount += step;
+ arrayObj->SecondaryColor.BufferObj->RefCount += step;
+ arrayObj->FogCoord.BufferObj->RefCount += step;
+ arrayObj->Index.BufferObj->RefCount += step;
+ arrayObj->EdgeFlag.BufferObj->RefCount += step;
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ arrayObj->TexCoord[i].BufferObj->RefCount += step;
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ arrayObj->VertexAttrib[i].BufferObj->RefCount += step;
+}
+
+
+/**
+ * Copy gl_pixelstore_attrib from src to dst, updating buffer
+ * object refcounts.
+ */
+static void
+copy_pixelstore(struct gl_context *ctx,
+ struct gl_pixelstore_attrib *dst,
+ const struct gl_pixelstore_attrib *src)
+{
+ dst->Alignment = src->Alignment;
+ dst->RowLength = src->RowLength;
+ dst->SkipPixels = src->SkipPixels;
+ dst->SkipRows = src->SkipRows;
+ dst->ImageHeight = src->ImageHeight;
+ dst->SkipImages = src->SkipImages;
+ dst->SwapBytes = src->SwapBytes;
+ dst->LsbFirst = src->LsbFirst;
+ dst->ClientStorage = src->ClientStorage;
+ dst->Invert = src->Invert;
+ _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
+}
+
+
+#define GL_CLIENT_PACK_BIT (1<<20)
+#define GL_CLIENT_UNPACK_BIT (1<<21)
+
+
+void GLAPIENTRY
+_mesa_PushClientAttrib(GLbitfield mask)
+{
+ struct gl_attrib_node *head;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->ClientAttribStackDepth >= MAX_CLIENT_ATTRIB_STACK_DEPTH) {
+ _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushClientAttrib" );
+ return;
+ }
+
+ /* Build linked list of attribute nodes which save all attribute
+ * groups specified by the mask.
+ */
+ head = NULL;
+
+ if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
+ struct gl_pixelstore_attrib *attr;
+ /* packing attribs */
+ attr = CALLOC_STRUCT( gl_pixelstore_attrib );
+ copy_pixelstore(ctx, attr, &ctx->Pack);
+ save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr);
+ /* unpacking attribs */
+ attr = CALLOC_STRUCT( gl_pixelstore_attrib );
+ copy_pixelstore(ctx, attr, &ctx->Unpack);
+ save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr);
+ }
+
+ if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+ struct gl_array_attrib *attr;
+ struct gl_array_object *obj;
+
+ attr = MALLOC_STRUCT( gl_array_attrib );
+ obj = MALLOC_STRUCT( gl_array_object );
+
+#if FEATURE_ARB_vertex_buffer_object
+ /* increment ref counts since we're copying pointers to these objects */
+ ctx->Array.ArrayBufferObj->RefCount++;
+ ctx->Array.ElementArrayBufferObj->RefCount++;
+#endif
+
+ memcpy( attr, &ctx->Array, sizeof(struct gl_array_attrib) );
+ memcpy( obj, ctx->Array.ArrayObj, sizeof(struct gl_array_object) );
+
+ attr->ArrayObj = obj;
+
+ save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr);
+
+ /* bump reference counts on buffer objects */
+ adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, 1);
+ }
+
+ ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
+ ctx->ClientAttribStackDepth++;
+}
+
+
+
+
+void GLAPIENTRY
+_mesa_PopClientAttrib(void)
+{
+ struct gl_attrib_node *node, *next;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (ctx->ClientAttribStackDepth == 0) {
+ _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" );
+ return;
+ }
+
+ ctx->ClientAttribStackDepth--;
+ node = ctx->ClientAttribStack[ctx->ClientAttribStackDepth];
+
+ while (node) {
+ switch (node->kind) {
+ case GL_CLIENT_PACK_BIT:
+ {
+ struct gl_pixelstore_attrib *store =
+ (struct gl_pixelstore_attrib *) node->data;
+ copy_pixelstore(ctx, &ctx->Pack, store);
+ _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
+ }
+ ctx->NewState |= _NEW_PACKUNPACK;
+ break;
+ case GL_CLIENT_UNPACK_BIT:
+ {
+ struct gl_pixelstore_attrib *store =
+ (struct gl_pixelstore_attrib *) node->data;
+ copy_pixelstore(ctx, &ctx->Unpack, store);
+ _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
+ }
+ ctx->NewState |= _NEW_PACKUNPACK;
+ break;
+ case GL_CLIENT_VERTEX_ARRAY_BIT: {
+ struct gl_array_attrib * data =
+ (struct gl_array_attrib *) node->data;
+
+ adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, -1);
+
+ ctx->Array.ActiveTexture = data->ActiveTexture;
+ if (data->LockCount != 0)
+ _mesa_LockArraysEXT(data->LockFirst, data->LockCount);
+ else if (ctx->Array.LockCount)
+ _mesa_UnlockArraysEXT();
+
+ _mesa_BindVertexArrayAPPLE( data->ArrayObj->Name );
+
+#if FEATURE_ARB_vertex_buffer_object
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ data->ArrayBufferObj->Name);
+ _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
+ data->ElementArrayBufferObj->Name);
+#endif
+
+ memcpy( ctx->Array.ArrayObj, data->ArrayObj,
+ sizeof( struct gl_array_object ) );
+
+ FREE( data->ArrayObj );
+
+ /* FIXME: Should some bits in ctx->Array->NewState also be set
+ * FIXME: here? It seems like it should be set to inclusive-or
+ * FIXME: of the old ArrayObj->_Enabled and the new _Enabled.
+ */
+
+ ctx->NewState |= _NEW_ARRAY;
+ break;
+ }
+ default:
+ _mesa_problem( ctx, "Bad attrib flag in PopClientAttrib");
+ break;
+ }
+
+ next = node->next;
+ FREE( node->data );
+ FREE( node );
+ node = next;
+ }
+}
+
+
+void
+_mesa_init_attrib_dispatch(struct _glapi_table *disp)
+{
+ SET_PopAttrib(disp, _mesa_PopAttrib);
+ SET_PushAttrib(disp, _mesa_PushAttrib);
+ SET_PopClientAttrib(disp, _mesa_PopClientAttrib);
+ SET_PushClientAttrib(disp, _mesa_PushClientAttrib);
+}
+
+
+#endif /* FEATURE_attrib_stack */
+
+
+/**
+ * Free any attribute state data that might be attached to the context.
+ */
+void
+_mesa_free_attrib_data(struct gl_context *ctx)
+{
+ while (ctx->AttribStackDepth > 0) {
+ struct gl_attrib_node *attr, *next;
+
+ ctx->AttribStackDepth--;
+ attr = ctx->AttribStack[ctx->AttribStackDepth];
+
+ while (attr) {
+ if (attr->kind == GL_TEXTURE_BIT) {
+ struct texture_state *texstate = (struct texture_state*)attr->data;
+ GLuint u, tgt;
+ /* clear references to the saved texture objects */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL);
+ }
+ }
+ }
+ else {
+ /* any other chunks of state that requires special handling? */
+ }
+
+ next = attr->next;
+ free(attr->data);
+ free(attr);
+ attr = next;
+ }
+ }
+}
+
+
+void _mesa_init_attrib( struct gl_context *ctx )
+{
+ /* Renderer and client attribute stacks */
+ ctx->AttribStackDepth = 0;
+ ctx->ClientAttribStackDepth = 0;
+}
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 75afae0ad..35d92616f 100644
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -658,248 +658,6 @@ _mesa_update_default_objects_buffer_objects(struct gl_context *ctx)
}
-/**
- * When we're about to read pixel data out of a PBO (via glDrawPixels,
- * glTexImage, etc) or write data into a PBO (via glReadPixels,
- * glGetTexImage, etc) we call this function to check that we're not
- * going to read out of bounds.
- *
- * XXX This would also be a convenient time to check that the PBO isn't
- * currently mapped. Whoever calls this function should check for that.
- * Remember, we can't use a PBO when it's mapped!
- *
- * If we're not using a PBO, this is a no-op.
- *
- * \param width width of image to read/write
- * \param height height of image to read/write
- * \param depth depth of image to read/write
- * \param format format of image to read/write
- * \param type datatype of image to read/write
- * \param ptr the user-provided pointer/offset
- * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
- * go out of bounds.
- */
-GLboolean
-_mesa_validate_pbo_access(GLuint dimensions,
- const struct gl_pixelstore_attrib *pack,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *ptr)
-{
- GLvoid *start, *end;
- const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
-
- if (!_mesa_is_bufferobj(pack->BufferObj))
- return GL_TRUE; /* no PBO, OK */
-
- if (pack->BufferObj->Size == 0)
- /* no buffer! */
- return GL_FALSE;
-
- /* get address of first pixel we'll read */
- start = _mesa_image_address(dimensions, pack, ptr, width, height,
- format, type, 0, 0, 0);
-
- /* get address just past the last pixel we'll read */
- end = _mesa_image_address(dimensions, pack, ptr, width, height,
- format, type, depth-1, height-1, width);
-
-
- sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
-
- if ((const GLubyte *) start > sizeAddr) {
- /* This will catch negative values / wrap-around */
- return GL_FALSE;
- }
- if ((const GLubyte *) end > sizeAddr) {
- /* Image read goes beyond end of buffer */
- return GL_FALSE;
- }
-
- /* OK! */
- return GL_TRUE;
-}
-
-
-/**
- * For commands that read from a PBO (glDrawPixels, glTexImage,
- * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
- * and return the pointer into the PBO. If we're not reading from a
- * PBO, return \p src as-is.
- * If non-null return, must call _mesa_unmap_pbo_source() when done.
- *
- * \return NULL if error, else pointer to start of data
- */
-const GLvoid *
-_mesa_map_pbo_source(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *src)
-{
- const GLubyte *buf;
-
- if (_mesa_is_bufferobj(unpack->BufferObj)) {
- /* unpack from PBO */
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- unpack->BufferObj);
- if (!buf)
- return NULL;
-
- buf = ADD_POINTERS(buf, src);
- }
- else {
- /* unpack from normal memory */
- buf = src;
- }
-
- return buf;
-}
-
-
-/**
- * Combine PBO-read validation and mapping.
- * If any GL errors are detected, they'll be recorded and NULL returned.
- * \sa _mesa_validate_pbo_access
- * \sa _mesa_map_pbo_source
- * A call to this function should have a matching call to
- * _mesa_unmap_pbo_source().
- */
-const GLvoid *
-_mesa_map_validate_pbo_source(struct gl_context *ctx,
- GLuint dimensions,
- const struct gl_pixelstore_attrib *unpack,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *ptr,
- const char *where)
-{
- ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
-
- if (!_mesa_is_bufferobj(unpack->BufferObj)) {
- /* non-PBO access: no validation to be done */
- return ptr;
- }
-
- if (!_mesa_validate_pbo_access(dimensions, unpack,
- width, height, depth, format, type, ptr)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(out of bounds PBO access)", where);
- return NULL;
- }
-
- if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
- return NULL;
- }
-
- ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
- return ptr;
-}
-
-
-/**
- * Counterpart to _mesa_map_pbo_source()
- */
-void
-_mesa_unmap_pbo_source(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *unpack)
-{
- ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
- if (_mesa_is_bufferobj(unpack->BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- unpack->BufferObj);
- }
-}
-
-
-/**
- * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
- * if we're writing to a PBO, map it write-only and return the pointer
- * into the PBO. If we're not writing to a PBO, return \p dst as-is.
- * If non-null return, must call _mesa_unmap_pbo_dest() when done.
- *
- * \return NULL if error, else pointer to start of data
- */
-void *
-_mesa_map_pbo_dest(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *pack,
- GLvoid *dest)
-{
- void *buf;
-
- if (_mesa_is_bufferobj(pack->BufferObj)) {
- /* pack into PBO */
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- pack->BufferObj);
- if (!buf)
- return NULL;
-
- buf = ADD_POINTERS(buf, dest);
- }
- else {
- /* pack to normal memory */
- buf = dest;
- }
-
- return buf;
-}
-
-
-/**
- * Combine PBO-write validation and mapping.
- * If any GL errors are detected, they'll be recorded and NULL returned.
- * \sa _mesa_validate_pbo_access
- * \sa _mesa_map_pbo_dest
- * A call to this function should have a matching call to
- * _mesa_unmap_pbo_dest().
- */
-GLvoid *
-_mesa_map_validate_pbo_dest(struct gl_context *ctx,
- GLuint dimensions,
- const struct gl_pixelstore_attrib *unpack,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, GLvoid *ptr,
- const char *where)
-{
- ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
-
- if (!_mesa_is_bufferobj(unpack->BufferObj)) {
- /* non-PBO access: no validation to be done */
- return ptr;
- }
-
- if (!_mesa_validate_pbo_access(dimensions, unpack,
- width, height, depth, format, type, ptr)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(out of bounds PBO access)", where);
- return NULL;
- }
-
- if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
- return NULL;
- }
-
- ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
- return ptr;
-}
-
-
-/**
- * Counterpart to _mesa_map_pbo_dest()
- */
-void
-_mesa_unmap_pbo_dest(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *pack)
-{
- ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
- if (_mesa_is_bufferobj(pack->BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
- }
-}
-
-
/**
* Return the gl_buffer_object for the given ID.
diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h
index cf43ad9a2..91fa073b6 100644
--- a/mesalib/src/mesa/main/bufferobj.h
+++ b/mesalib/src/mesa/main/bufferobj.h
@@ -1,190 +1,149 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.6
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009 VMware, Inc. 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 BUFFEROBJ_H
-#define BUFFEROBJ_H
-
-
-#include "mfeatures.h"
-#include "mtypes.h"
-
-
-/*
- * Internal functions
- */
-
-
-/** Is the given buffer object currently mapped? */
-static INLINE GLboolean
-_mesa_bufferobj_mapped(const struct gl_buffer_object *obj)
-{
- return obj->Pointer != NULL;
-}
-
-/**
- * Is the given buffer object a user-created buffer object?
- * Mesa uses default buffer objects in several places. Default buffers
- * always have Name==0. User created buffers have Name!=0.
- */
-static INLINE GLboolean
-_mesa_is_bufferobj(const struct gl_buffer_object *obj)
-{
- return obj->Name != 0;
-}
-
-
-extern void
-_mesa_init_buffer_objects( struct gl_context *ctx );
-
-extern void
-_mesa_free_buffer_objects( struct gl_context *ctx );
-
-extern void
-_mesa_update_default_objects_buffer_objects(struct gl_context *ctx);
-
-
-extern struct gl_buffer_object *
-_mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer);
-
-extern void
-_mesa_initialize_buffer_object( struct gl_buffer_object *obj,
- GLuint name, GLenum target );
-
-extern void
-_mesa_reference_buffer_object(struct gl_context *ctx,
- struct gl_buffer_object **ptr,
- struct gl_buffer_object *bufObj);
-
-extern GLboolean
-_mesa_validate_pbo_access(GLuint dimensions,
- const struct gl_pixelstore_attrib *pack,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *ptr);
-
-extern const GLvoid *
-_mesa_map_pbo_source(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *src);
-
-extern const GLvoid *
-_mesa_map_validate_pbo_source(struct gl_context *ctx,
- GLuint dimensions,
- const struct gl_pixelstore_attrib *unpack,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *ptr,
- const char *where);
-
-extern void
-_mesa_unmap_pbo_source(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *unpack);
-
-extern void *
-_mesa_map_pbo_dest(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *pack,
- GLvoid *dest);
-
-extern GLvoid *
-_mesa_map_validate_pbo_dest(struct gl_context *ctx,
- GLuint dimensions,
- const struct gl_pixelstore_attrib *unpack,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, GLvoid *ptr,
- const char *where);
-
-extern void
-_mesa_unmap_pbo_dest(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *pack);
-
-
-extern void
-_mesa_init_buffer_object_functions(struct dd_function_table *driver);
-
-
-/*
- * API functions
- */
-
-extern void GLAPIENTRY
-_mesa_BindBufferARB(GLenum target, GLuint buffer);
-
-extern void GLAPIENTRY
-_mesa_DeleteBuffersARB(GLsizei n, const GLuint * buffer);
-
-extern void GLAPIENTRY
-_mesa_GenBuffersARB(GLsizei n, GLuint * buffer);
-
-extern GLboolean GLAPIENTRY
-_mesa_IsBufferARB(GLuint buffer);
-
-extern void GLAPIENTRY
-_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
-
-extern void GLAPIENTRY
-_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
-
-extern void GLAPIENTRY
-_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data);
-
-extern void * GLAPIENTRY
-_mesa_MapBufferARB(GLenum target, GLenum access);
-
-extern GLboolean GLAPIENTRY
-_mesa_UnmapBufferARB(GLenum target);
-
-extern void GLAPIENTRY
-_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params);
-
-extern void GLAPIENTRY
-_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params);
-
-extern void GLAPIENTRY
-_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params);
-
-extern void GLAPIENTRY
-_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
- GLintptr readOffset, GLintptr writeOffset,
- GLsizeiptr size);
-
-extern void * GLAPIENTRY
-_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
- GLbitfield access);
-
-extern void GLAPIENTRY
-_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
-
-#if FEATURE_APPLE_object_purgeable
-extern GLenum GLAPIENTRY
-_mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option);
-
-extern GLenum GLAPIENTRY
-_mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option);
-
-extern void GLAPIENTRY
-_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, GLint* params);
-#endif
-
-#endif
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. 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 BUFFEROBJ_H
+#define BUFFEROBJ_H
+
+
+#include "mfeatures.h"
+#include "mtypes.h"
+
+
+/*
+ * Internal functions
+ */
+
+
+/** Is the given buffer object currently mapped? */
+static INLINE GLboolean
+_mesa_bufferobj_mapped(const struct gl_buffer_object *obj)
+{
+ return obj->Pointer != NULL;
+}
+
+/**
+ * Is the given buffer object a user-created buffer object?
+ * Mesa uses default buffer objects in several places. Default buffers
+ * always have Name==0. User created buffers have Name!=0.
+ */
+static INLINE GLboolean
+_mesa_is_bufferobj(const struct gl_buffer_object *obj)
+{
+ return obj->Name != 0;
+}
+
+
+extern void
+_mesa_init_buffer_objects( struct gl_context *ctx );
+
+extern void
+_mesa_free_buffer_objects( struct gl_context *ctx );
+
+extern void
+_mesa_update_default_objects_buffer_objects(struct gl_context *ctx);
+
+
+extern struct gl_buffer_object *
+_mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer);
+
+extern void
+_mesa_initialize_buffer_object( struct gl_buffer_object *obj,
+ GLuint name, GLenum target );
+
+extern void
+_mesa_reference_buffer_object(struct gl_context *ctx,
+ struct gl_buffer_object **ptr,
+ struct gl_buffer_object *bufObj);
+
+extern void
+_mesa_init_buffer_object_functions(struct dd_function_table *driver);
+
+
+/*
+ * API functions
+ */
+
+extern void GLAPIENTRY
+_mesa_BindBufferARB(GLenum target, GLuint buffer);
+
+extern void GLAPIENTRY
+_mesa_DeleteBuffersARB(GLsizei n, const GLuint * buffer);
+
+extern void GLAPIENTRY
+_mesa_GenBuffersARB(GLsizei n, GLuint * buffer);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsBufferARB(GLuint buffer);
+
+extern void GLAPIENTRY
+_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
+
+extern void GLAPIENTRY
+_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
+
+extern void GLAPIENTRY
+_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data);
+
+extern void * GLAPIENTRY
+_mesa_MapBufferARB(GLenum target, GLenum access);
+
+extern GLboolean GLAPIENTRY
+_mesa_UnmapBufferARB(GLenum target);
+
+extern void GLAPIENTRY
+_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params);
+
+extern void GLAPIENTRY
+_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params);
+
+extern void GLAPIENTRY
+_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size);
+
+extern void * GLAPIENTRY
+_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access);
+
+extern void GLAPIENTRY
+_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+
+#if FEATURE_APPLE_object_purgeable
+extern GLenum GLAPIENTRY
+_mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option);
+
+extern GLenum GLAPIENTRY
+_mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option);
+
+extern void GLAPIENTRY
+_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, GLint* params);
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/colortab.c b/mesalib/src/mesa/main/colortab.c
index 9c23e253b..d0c865735 100644
--- a/mesalib/src/mesa/main/colortab.c
+++ b/mesalib/src/mesa/main/colortab.c
@@ -1,934 +1,821 @@
-/*
- * 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 "bufferobj.h"
-#include "colortab.h"
-#include "context.h"
-#include "image.h"
-#include "macros.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "pack.h"
-#include "state.h"
-#include "teximage.h"
-#include "texstate.h"
-#include "main/dispatch.h"
-
-
-#if FEATURE_colortable
-
-
-/**
- * Given an internalFormat token passed to glColorTable,
- * return the corresponding base format.
- * Return -1 if invalid token.
- */
-static GLint
-base_colortab_format( GLenum format )
-{
- switch (format) {
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- return GL_ALPHA;
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- return GL_LUMINANCE;
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE4_ALPHA4:
- case GL_LUMINANCE6_ALPHA2:
- case GL_LUMINANCE8_ALPHA8:
- case GL_LUMINANCE12_ALPHA4:
- case GL_LUMINANCE12_ALPHA12:
- case GL_LUMINANCE16_ALPHA16:
- return GL_LUMINANCE_ALPHA;
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- return GL_INTENSITY;
- case GL_RGB:
- case GL_R3_G3_B2:
- case GL_RGB4:
- case GL_RGB5:
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- return GL_RGB;
- case GL_RGBA:
- case GL_RGBA2:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- return GL_RGBA;
- default:
- return -1; /* error */
- }
-}
-
-
-
-/**
- * Examine table's format and set the component sizes accordingly.
- */
-static void
-set_component_sizes( struct gl_color_table *table )
-{
- /* assuming the ubyte table */
- const GLubyte sz = 8;
-
- switch (table->_BaseFormat) {
- case GL_ALPHA:
- table->RedSize = 0;
- table->GreenSize = 0;
- table->BlueSize = 0;
- table->AlphaSize = sz;
- table->IntensitySize = 0;
- table->LuminanceSize = 0;
- break;
- case GL_LUMINANCE:
- table->RedSize = 0;
- table->GreenSize = 0;
- table->BlueSize = 0;
- table->AlphaSize = 0;
- table->IntensitySize = 0;
- table->LuminanceSize = sz;
- break;
- case GL_LUMINANCE_ALPHA:
- table->RedSize = 0;
- table->GreenSize = 0;
- table->BlueSize = 0;
- table->AlphaSize = sz;
- table->IntensitySize = 0;
- table->LuminanceSize = sz;
- break;
- case GL_INTENSITY:
- table->RedSize = 0;
- table->GreenSize = 0;
- table->BlueSize = 0;
- table->AlphaSize = 0;
- table->IntensitySize = sz;
- table->LuminanceSize = 0;
- break;
- case GL_RGB:
- table->RedSize = sz;
- table->GreenSize = sz;
- table->BlueSize = sz;
- table->AlphaSize = 0;
- table->IntensitySize = 0;
- table->LuminanceSize = 0;
- break;
- case GL_RGBA:
- table->RedSize = sz;
- table->GreenSize = sz;
- table->BlueSize = sz;
- table->AlphaSize = sz;
- table->IntensitySize = 0;
- table->LuminanceSize = 0;
- break;
- default:
- _mesa_problem(NULL, "unexpected format in set_component_sizes");
- }
-}
-
-
-
-/**
- * Update/replace all or part of a color table. Helper function
- * used by _mesa_ColorTable() and _mesa_ColorSubTable().
- * The table->Table buffer should already be allocated.
- * \param start first entry to update
- * \param count number of entries to update
- * \param format format of user-provided table data
- * \param type datatype of user-provided table data
- * \param data user-provided table data
- * \param [rgba]Scale - RGBA scale factors
- * \param [rgba]Bias - RGBA bias factors
- */
-static void
-store_colortable_entries(struct gl_context *ctx, struct gl_color_table *table,
- GLsizei start, GLsizei count,
- GLenum format, GLenum type, const GLvoid *data,
- GLfloat rScale, GLfloat rBias,
- GLfloat gScale, GLfloat gBias,
- GLfloat bScale, GLfloat bBias,
- GLfloat aScale, GLfloat aBias)
-{
- data = _mesa_map_validate_pbo_source(ctx,
- 1, &ctx->Unpack, count, 1, 1,
- format, type, data,
- "glColor[Sub]Table");
- if (!data)
- return;
-
- {
- /* convert user-provided data to GLfloat values */
- GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4];
- GLfloat *tableF;
- GLint i;
-
- _mesa_unpack_color_span_float(ctx,
- count, /* number of pixels */
- table->_BaseFormat, /* dest format */
- tempTab, /* dest address */
- format, type, /* src format/type */
- data, /* src data */
- &ctx->Unpack,
- IMAGE_CLAMP_BIT); /* transfer ops */
-
- /* the destination */
- tableF = table->TableF;
-
- /* Apply scale & bias & clamp now */
- switch (table->_BaseFormat) {
- case GL_INTENSITY:
- for (i = 0; i < count; i++) {
- GLuint j = start + i;
- tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
- }
- break;
- case GL_LUMINANCE:
- for (i = 0; i < count; i++) {
- GLuint j = start + i;
- tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
- }
- break;
- case GL_ALPHA:
- for (i = 0; i < count; i++) {
- GLuint j = start + i;
- tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F);
- }
- break;
- case GL_LUMINANCE_ALPHA:
- for (i = 0; i < count; i++) {
- GLuint j = start + i;
- tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F);
- tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F);
- }
- break;
- case GL_RGB:
- for (i = 0; i < count; i++) {
- GLuint j = start + i;
- tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F);
- tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F);
- tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F);
- }
- break;
- case GL_RGBA:
- for (i = 0; i < count; i++) {
- GLuint j = start + i;
- tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F);
- tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F);
- tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F);
- tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F);
- }
- break;
- default:
- _mesa_problem(ctx, "Bad format in store_colortable_entries");
- return;
- }
- }
-
- /* update the ubyte table */
- {
- const GLint comps = _mesa_components_in_format(table->_BaseFormat);
- const GLfloat *tableF = table->TableF + start * comps;
- GLubyte *tableUB = table->TableUB + start * comps;
- GLint i;
- for (i = 0; i < count * comps; i++) {
- CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]);
- }
- }
-
- _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
-}
-
-
-
-void GLAPIENTRY
-_mesa_ColorTable( GLenum target, GLenum internalFormat,
- GLsizei width, GLenum format, GLenum type,
- const GLvoid *data )
-{
- static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
- static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
- GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- struct gl_texture_object *texObj = NULL;
- struct gl_color_table *table = NULL;
- GLboolean proxy = GL_FALSE;
- GLint baseFormat;
- const GLfloat *scale = one, *bias = zero;
- GLint comps;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
-
- switch (target) {
- case GL_SHARED_TEXTURE_PALETTE_EXT:
- table = &ctx->Texture.Palette;
- break;
- case GL_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
- return;
- }
- table = &(texUnit->ColorTable);
- scale = ctx->Pixel.TextureColorTableScale;
- bias = ctx->Pixel.TextureColorTableBias;
- break;
- case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
- return;
- }
- table = &(texUnit->ProxyColorTable);
- proxy = GL_TRUE;
- break;
- default:
- /* try texture targets */
- {
- struct gl_texture_object *texobj
- = _mesa_select_tex_object(ctx, texUnit, target);
- if (texobj) {
- table = &texobj->Palette;
- proxy = _mesa_is_proxy_texture(target);
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
- return;
- }
- }
- }
-
- assert(table);
-
- if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
- format == GL_INTENSITY) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)");
- return;
- }
-
- baseFormat = base_colortab_format(internalFormat);
- if (baseFormat < 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)");
- return;
- }
-
- if (width < 0 || (width != 0 && !_mesa_is_pow_two(width))) {
- /* error */
- if (proxy) {
- table->Size = 0;
- table->InternalFormat = (GLenum) 0;
- table->_BaseFormat = (GLenum) 0;
- }
- else {
- _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width);
- }
- return;
- }
-
- if (width > (GLsizei) ctx->Const.MaxColorTableSize) {
- if (proxy) {
- table->Size = 0;
- table->InternalFormat = (GLenum) 0;
- table->_BaseFormat = (GLenum) 0;
- }
- else {
- _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)");
- }
- return;
- }
-
- table->Size = width;
- table->InternalFormat = internalFormat;
- table->_BaseFormat = (GLenum) baseFormat;
-
- comps = _mesa_components_in_format(table->_BaseFormat);
- assert(comps > 0); /* error should have been caught sooner */
-
- if (!proxy) {
- _mesa_free_colortable_data(table);
-
- if (width > 0) {
- table->TableF = (GLfloat *) malloc(comps * width * sizeof(GLfloat));
- table->TableUB = (GLubyte *) malloc(comps * width * sizeof(GLubyte));
-
- if (!table->TableF || !table->TableUB) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable");
- return;
- }
-
- store_colortable_entries(ctx, table,
- 0, width, /* start, count */
- format, type, data,
- scale[0], bias[0],
- scale[1], bias[1],
- scale[2], bias[2],
- scale[3], bias[3]);
- }
- } /* proxy */
-
- /* do this after the table's Type and Format are set */
- set_component_sizes(table);
-
- if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
- /* texture object palette, texObj==NULL means the shared palette */
- if (ctx->Driver.UpdateTexturePalette) {
- (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
- }
- }
-
- ctx->NewState |= _NEW_PIXEL;
-}
-
-
-
-void GLAPIENTRY
-_mesa_ColorSubTable( GLenum target, GLsizei start,
- GLsizei count, GLenum format, GLenum type,
- const GLvoid *data )
-{
- static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
- static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
- GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- struct gl_texture_object *texObj = NULL;
- struct gl_color_table *table = NULL;
- const GLfloat *scale = one, *bias = zero;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- switch (target) {
- case GL_SHARED_TEXTURE_PALETTE_EXT:
- table = &ctx->Texture.Palette;
- break;
- case GL_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
- return;
- }
- table = &(texUnit->ColorTable);
- scale = ctx->Pixel.TextureColorTableScale;
- bias = ctx->Pixel.TextureColorTableBias;
- break;
- default:
- /* try texture targets */
- texObj = _mesa_select_tex_object(ctx, texUnit, target);
- if (texObj && !_mesa_is_proxy_texture(target)) {
- table = &texObj->Palette;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
- return;
- }
- }
-
- assert(table);
-
- if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
- format == GL_INTENSITY) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable(format or type)");
- return;
- }
-
- if (count < 1) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
- return;
- }
-
- /* error should have been caught sooner */
- assert(_mesa_components_in_format(table->_BaseFormat) > 0);
-
- if (start + count > (GLint) table->Size) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
- return;
- }
-
- if (!table->TableF || !table->TableUB) {
- /* a GL_OUT_OF_MEMORY error would have been recorded previously */
- return;
- }
-
- store_colortable_entries(ctx, table, start, count,
- format, type, data,
- scale[0], bias[0],
- scale[1], bias[1],
- scale[2], bias[2],
- scale[3], bias[3]);
-
- if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
- /* per-texture object palette */
- if (ctx->Driver.UpdateTexturePalette) {
- (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
- }
- }
-
- ctx->NewState |= _NEW_PIXEL;
-}
-
-
-
-static void GLAPIENTRY
-_mesa_CopyColorTable(GLenum target, GLenum internalformat,
- GLint x, GLint y, GLsizei width)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (!ctx->ReadBuffer->_ColorReadBuffer) {
- return; /* no readbuffer - OK */
- }
-
- ctx->Driver.CopyColorTable( ctx, target, internalformat, x, y, width );
-}
-
-
-
-static void GLAPIENTRY
-_mesa_CopyColorSubTable(GLenum target, GLsizei start,
- GLint x, GLint y, GLsizei width)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (!ctx->ReadBuffer->_ColorReadBuffer) {
- return; /* no readbuffer - OK */
- }
-
- ctx->Driver.CopyColorSubTable( ctx, target, start, x, y, width );
-}
-
-
-
-static void GLAPIENTRY
-_mesa_GetColorTable( GLenum target, GLenum format,
- GLenum type, GLvoid *data )
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- struct gl_color_table *table = NULL;
- GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (ctx->NewState) {
- _mesa_update_state(ctx);
- }
-
- switch (target) {
- case GL_SHARED_TEXTURE_PALETTE_EXT:
- table = &ctx->Texture.Palette;
- break;
- case GL_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
- return;
- }
- table = &(texUnit->ColorTable);
- break;
- default:
- /* try texture targets */
- {
- struct gl_texture_object *texobj
- = _mesa_select_tex_object(ctx, texUnit, target);
- if (texobj && !_mesa_is_proxy_texture(target)) {
- table = &texobj->Palette;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
- return;
- }
- }
- }
-
- ASSERT(table);
-
- if (table->Size <= 0) {
- return;
- }
-
- switch (table->_BaseFormat) {
- case GL_ALPHA:
- {
- GLuint i;
- for (i = 0; i < table->Size; i++) {
- rgba[i][RCOMP] = 0;
- rgba[i][GCOMP] = 0;
- rgba[i][BCOMP] = 0;
- rgba[i][ACOMP] = table->TableF[i];
- }
- }
- break;
- case GL_LUMINANCE:
- {
- GLuint i;
- for (i = 0; i < table->Size; i++) {
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = table->TableF[i];
- rgba[i][ACOMP] = 1.0F;
- }
- }
- break;
- case GL_LUMINANCE_ALPHA:
- {
- GLuint i;
- for (i = 0; i < table->Size; i++) {
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = table->TableF[i*2+0];
- rgba[i][ACOMP] = table->TableF[i*2+1];
- }
- }
- break;
- case GL_INTENSITY:
- {
- GLuint i;
- for (i = 0; i < table->Size; i++) {
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] =
- rgba[i][ACOMP] = table->TableF[i];
- }
- }
- break;
- case GL_RGB:
- {
- GLuint i;
- for (i = 0; i < table->Size; i++) {
- rgba[i][RCOMP] = table->TableF[i*3+0];
- rgba[i][GCOMP] = table->TableF[i*3+1];
- rgba[i][BCOMP] = table->TableF[i*3+2];
- rgba[i][ACOMP] = 1.0F;
- }
- }
- break;
- case GL_RGBA:
- memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat));
- break;
- default:
- _mesa_problem(ctx, "bad table format in glGetColorTable");
- return;
- }
-
- data = _mesa_map_validate_pbo_dest(ctx,
- 1, &ctx->Pack, table->Size, 1, 1,
- format, type, data,
- "glGetColorTable");
- if (!data)
- return;
-
- _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
- format, type, data, &ctx->Pack, 0x0);
-
- _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
-}
-
-
-
-static void GLAPIENTRY
-_mesa_ColorTableParameterfv(GLenum target, GLenum pname, const GLfloat *params)
-{
- GLfloat *scale, *bias;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- switch (target) {
- case GL_TEXTURE_COLOR_TABLE_SGI:
- scale = ctx->Pixel.TextureColorTableScale;
- bias = ctx->Pixel.TextureColorTableBias;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameter(target)");
- return;
- }
-
- if (pname == GL_COLOR_TABLE_SCALE_SGI) {
- COPY_4V(scale, params);
- }
- else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
- COPY_4V(bias, params);
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)");
- return;
- }
-
- ctx->NewState |= _NEW_PIXEL;
-}
-
-
-
-static void GLAPIENTRY
-_mesa_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params)
-{
- GLfloat fparams[4];
- if (pname == GL_TEXTURE_COLOR_TABLE_SGI) {
- /* four values */
- fparams[0] = (GLfloat) params[0];
- fparams[1] = (GLfloat) params[1];
- fparams[2] = (GLfloat) params[2];
- fparams[3] = (GLfloat) params[3];
- }
- else {
- /* one values */
- fparams[0] = (GLfloat) params[0];
- }
- _mesa_ColorTableParameterfv(target, pname, fparams);
-}
-
-
-
-static void GLAPIENTRY
-_mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params )
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- struct gl_color_table *table = NULL;
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- switch (target) {
- case GL_SHARED_TEXTURE_PALETTE_EXT:
- table = &ctx->Texture.Palette;
- break;
- case GL_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
- return;
- }
- table = &(texUnit->ColorTable);
- if (pname == GL_COLOR_TABLE_SCALE_SGI) {
- COPY_4V(params, ctx->Pixel.TextureColorTableScale);
- return;
- }
- else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
- COPY_4V(params, ctx->Pixel.TextureColorTableBias);
- return;
- }
- break;
- case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
- return;
- }
- table = &(texUnit->ProxyColorTable);
- break;
- default:
- /* try texture targets */
- {
- struct gl_texture_object *texobj
- = _mesa_select_tex_object(ctx, texUnit, target);
- if (texobj) {
- table = &texobj->Palette;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetColorTableParameterfv(target)");
- return;
- }
- }
- }
-
- assert(table);
-
- switch (pname) {
- case GL_COLOR_TABLE_FORMAT:
- *params = (GLfloat) table->InternalFormat;
- break;
- case GL_COLOR_TABLE_WIDTH:
- *params = (GLfloat) table->Size;
- break;
- case GL_COLOR_TABLE_RED_SIZE:
- *params = (GLfloat) table->RedSize;
- break;
- case GL_COLOR_TABLE_GREEN_SIZE:
- *params = (GLfloat) table->GreenSize;
- break;
- case GL_COLOR_TABLE_BLUE_SIZE:
- *params = (GLfloat) table->BlueSize;
- break;
- case GL_COLOR_TABLE_ALPHA_SIZE:
- *params = (GLfloat) table->AlphaSize;
- break;
- case GL_COLOR_TABLE_LUMINANCE_SIZE:
- *params = (GLfloat) table->LuminanceSize;
- break;
- case GL_COLOR_TABLE_INTENSITY_SIZE:
- *params = (GLfloat) table->IntensitySize;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(pname)" );
- return;
- }
-}
-
-
-
-static void GLAPIENTRY
-_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params )
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- struct gl_color_table *table = NULL;
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- switch (target) {
- case GL_SHARED_TEXTURE_PALETTE_EXT:
- table = &ctx->Texture.Palette;
- break;
- case GL_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
- return;
- }
- table = &(texUnit->ColorTable);
- if (pname == GL_COLOR_TABLE_SCALE_SGI) {
- params[0] = (GLint) ctx->Pixel.TextureColorTableScale[0];
- params[1] = (GLint) ctx->Pixel.TextureColorTableScale[1];
- params[2] = (GLint) ctx->Pixel.TextureColorTableScale[2];
- params[3] = (GLint) ctx->Pixel.TextureColorTableScale[3];
- return;
- }
- else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
- params[0] = (GLint) ctx->Pixel.TextureColorTableBias[0];
- params[1] = (GLint) ctx->Pixel.TextureColorTableBias[1];
- params[2] = (GLint) ctx->Pixel.TextureColorTableBias[2];
- params[3] = (GLint) ctx->Pixel.TextureColorTableBias[3];
- return;
- }
- break;
- case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
- if (!ctx->Extensions.SGI_texture_color_table) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
- return;
- }
- table = &(texUnit->ProxyColorTable);
- break;
- default:
- /* Try texture targets */
- {
- struct gl_texture_object *texobj
- = _mesa_select_tex_object(ctx, texUnit, target);
- if (texobj) {
- table = &texobj->Palette;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetColorTableParameteriv(target)");
- return;
- }
- }
- }
-
- assert(table);
-
- switch (pname) {
- case GL_COLOR_TABLE_FORMAT:
- *params = table->InternalFormat;
- break;
- case GL_COLOR_TABLE_WIDTH:
- *params = table->Size;
- break;
- case GL_COLOR_TABLE_RED_SIZE:
- *params = table->RedSize;
- break;
- case GL_COLOR_TABLE_GREEN_SIZE:
- *params = table->GreenSize;
- break;
- case GL_COLOR_TABLE_BLUE_SIZE:
- *params = table->BlueSize;
- break;
- case GL_COLOR_TABLE_ALPHA_SIZE:
- *params = table->AlphaSize;
- break;
- case GL_COLOR_TABLE_LUMINANCE_SIZE:
- *params = table->LuminanceSize;
- break;
- case GL_COLOR_TABLE_INTENSITY_SIZE:
- *params = table->IntensitySize;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(pname)" );
- return;
- }
-}
-
-
-void
-_mesa_init_colortable_dispatch(struct _glapi_table *disp)
-{
- SET_ColorSubTable(disp, _mesa_ColorSubTable);
- SET_ColorTable(disp, _mesa_ColorTable);
- SET_ColorTableParameterfv(disp, _mesa_ColorTableParameterfv);
- SET_ColorTableParameteriv(disp, _mesa_ColorTableParameteriv);
- SET_CopyColorSubTable(disp, _mesa_CopyColorSubTable);
- SET_CopyColorTable(disp, _mesa_CopyColorTable);
- SET_GetColorTable(disp, _mesa_GetColorTable);
- SET_GetColorTableParameterfv(disp, _mesa_GetColorTableParameterfv);
- SET_GetColorTableParameteriv(disp, _mesa_GetColorTableParameteriv);
-}
-
-
-#endif /* FEATURE_colortable */
-
-
-/**********************************************************************/
-/***** Initialization *****/
-/**********************************************************************/
-
-
-void
-_mesa_init_colortable( struct gl_color_table *p )
-{
- p->TableF = NULL;
- p->TableUB = NULL;
- p->Size = 0;
- p->InternalFormat = GL_RGBA;
-}
-
-
-
-void
-_mesa_free_colortable_data( struct gl_color_table *p )
-{
- if (p->TableF) {
- free(p->TableF);
- p->TableF = NULL;
- }
- if (p->TableUB) {
- free(p->TableUB);
- p->TableUB = NULL;
- }
-}
+/*
+ * 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 "bufferobj.h"
+#include "colortab.h"
+#include "context.h"
+#include "image.h"
+#include "macros.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "pack.h"
+#include "pbo.h"
+#include "state.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "main/dispatch.h"
+
+
+#if FEATURE_colortable
+
+
+/**
+ * Given an internalFormat token passed to glColorTable,
+ * return the corresponding base format.
+ * Return -1 if invalid token.
+ */
+static GLint
+base_colortab_format( GLenum format )
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return GL_ALPHA;
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return GL_LUMINANCE_ALPHA;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return GL_INTENSITY;
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return GL_RGB;
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return GL_RGBA;
+ default:
+ return -1; /* error */
+ }
+}
+
+
+
+/**
+ * Examine table's format and set the component sizes accordingly.
+ */
+static void
+set_component_sizes( struct gl_color_table *table )
+{
+ /* assuming the ubyte table */
+ const GLubyte sz = 8;
+
+ switch (table->_BaseFormat) {
+ case GL_ALPHA:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = sz;
+ table->IntensitySize = 0;
+ table->LuminanceSize = 0;
+ break;
+ case GL_LUMINANCE:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = 0;
+ table->IntensitySize = 0;
+ table->LuminanceSize = sz;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = sz;
+ table->IntensitySize = 0;
+ table->LuminanceSize = sz;
+ break;
+ case GL_INTENSITY:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = 0;
+ table->IntensitySize = sz;
+ table->LuminanceSize = 0;
+ break;
+ case GL_RGB:
+ table->RedSize = sz;
+ table->GreenSize = sz;
+ table->BlueSize = sz;
+ table->AlphaSize = 0;
+ table->IntensitySize = 0;
+ table->LuminanceSize = 0;
+ break;
+ case GL_RGBA:
+ table->RedSize = sz;
+ table->GreenSize = sz;
+ table->BlueSize = sz;
+ table->AlphaSize = sz;
+ table->IntensitySize = 0;
+ table->LuminanceSize = 0;
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in set_component_sizes");
+ }
+}
+
+
+
+/**
+ * Update/replace all or part of a color table. Helper function
+ * used by _mesa_ColorTable() and _mesa_ColorSubTable().
+ * The table->Table buffer should already be allocated.
+ * \param start first entry to update
+ * \param count number of entries to update
+ * \param format format of user-provided table data
+ * \param type datatype of user-provided table data
+ * \param data user-provided table data
+ * \param [rgba]Scale - RGBA scale factors
+ * \param [rgba]Bias - RGBA bias factors
+ */
+static void
+store_colortable_entries(struct gl_context *ctx, struct gl_color_table *table,
+ GLsizei start, GLsizei count,
+ GLenum format, GLenum type, const GLvoid *data,
+ GLfloat rScale, GLfloat rBias,
+ GLfloat gScale, GLfloat gBias,
+ GLfloat bScale, GLfloat bBias,
+ GLfloat aScale, GLfloat aBias)
+{
+ data = _mesa_map_validate_pbo_source(ctx,
+ 1, &ctx->Unpack, count, 1, 1,
+ format, type, data,
+ "glColor[Sub]Table");
+ if (!data)
+ return;
+
+ {
+ /* convert user-provided data to GLfloat values */
+ GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4];
+ GLfloat *tableF;
+ GLint i;
+
+ _mesa_unpack_color_span_float(ctx,
+ count, /* number of pixels */
+ table->_BaseFormat, /* dest format */
+ tempTab, /* dest address */
+ format, type, /* src format/type */
+ data, /* src data */
+ &ctx->Unpack,
+ IMAGE_CLAMP_BIT); /* transfer ops */
+
+ /* the destination */
+ tableF = table->TableF;
+
+ /* Apply scale & bias & clamp now */
+ switch (table->_BaseFormat) {
+ case GL_INTENSITY:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_LUMINANCE:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_ALPHA:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F);
+ tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_RGB:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F);
+ tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F);
+ tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_RGBA:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F);
+ tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F);
+ tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F);
+ tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad format in store_colortable_entries");
+ return;
+ }
+ }
+
+ /* update the ubyte table */
+ {
+ const GLint comps = _mesa_components_in_format(table->_BaseFormat);
+ const GLfloat *tableF = table->TableF + start * comps;
+ GLubyte *tableUB = table->TableUB + start * comps;
+ GLint i;
+ for (i = 0; i < count * comps; i++) {
+ CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]);
+ }
+ }
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+}
+
+
+
+void GLAPIENTRY
+_mesa_ColorTable( GLenum target, GLenum internalFormat,
+ GLsizei width, GLenum format, GLenum type,
+ const GLvoid *data )
+{
+ static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
+ static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ struct gl_texture_object *texObj = NULL;
+ struct gl_color_table *table = NULL;
+ GLboolean proxy = GL_FALSE;
+ GLint baseFormat;
+ const GLfloat *scale = one, *bias = zero;
+ GLint comps;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ default:
+ /* try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj) {
+ table = &texobj->Palette;
+ proxy = _mesa_is_proxy_texture(target);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
+ return;
+ }
+ }
+ }
+
+ assert(table);
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
+ format == GL_INTENSITY) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)");
+ return;
+ }
+
+ baseFormat = base_colortab_format(internalFormat);
+ if (baseFormat < 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)");
+ return;
+ }
+
+ if (width < 0 || (width != 0 && !_mesa_is_pow_two(width))) {
+ /* error */
+ if (proxy) {
+ table->Size = 0;
+ table->InternalFormat = (GLenum) 0;
+ table->_BaseFormat = (GLenum) 0;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width);
+ }
+ return;
+ }
+
+ if (width > (GLsizei) ctx->Const.MaxColorTableSize) {
+ if (proxy) {
+ table->Size = 0;
+ table->InternalFormat = (GLenum) 0;
+ table->_BaseFormat = (GLenum) 0;
+ }
+ else {
+ _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)");
+ }
+ return;
+ }
+
+ table->Size = width;
+ table->InternalFormat = internalFormat;
+ table->_BaseFormat = (GLenum) baseFormat;
+
+ comps = _mesa_components_in_format(table->_BaseFormat);
+ assert(comps > 0); /* error should have been caught sooner */
+
+ if (!proxy) {
+ _mesa_free_colortable_data(table);
+
+ if (width > 0) {
+ table->TableF = (GLfloat *) malloc(comps * width * sizeof(GLfloat));
+ table->TableUB = (GLubyte *) malloc(comps * width * sizeof(GLubyte));
+
+ if (!table->TableF || !table->TableUB) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable");
+ return;
+ }
+
+ store_colortable_entries(ctx, table,
+ 0, width, /* start, count */
+ format, type, data,
+ scale[0], bias[0],
+ scale[1], bias[1],
+ scale[2], bias[2],
+ scale[3], bias[3]);
+ }
+ } /* proxy */
+
+ /* do this after the table's Type and Format are set */
+ set_component_sizes(table);
+
+ if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
+ /* texture object palette, texObj==NULL means the shared palette */
+ if (ctx->Driver.UpdateTexturePalette) {
+ (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
+ }
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+
+void GLAPIENTRY
+_mesa_ColorSubTable( GLenum target, GLsizei start,
+ GLsizei count, GLenum format, GLenum type,
+ const GLvoid *data )
+{
+ static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
+ static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ struct gl_texture_object *texObj = NULL;
+ struct gl_color_table *table = NULL;
+ const GLfloat *scale = one, *bias = zero;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ default:
+ /* try texture targets */
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texObj && !_mesa_is_proxy_texture(target)) {
+ table = &texObj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
+ return;
+ }
+ }
+
+ assert(table);
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
+ format == GL_INTENSITY) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable(format or type)");
+ return;
+ }
+
+ if (count < 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
+ return;
+ }
+
+ /* error should have been caught sooner */
+ assert(_mesa_components_in_format(table->_BaseFormat) > 0);
+
+ if (start + count > (GLint) table->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
+ return;
+ }
+
+ if (!table->TableF || !table->TableUB) {
+ /* a GL_OUT_OF_MEMORY error would have been recorded previously */
+ return;
+ }
+
+ store_colortable_entries(ctx, table, start, count,
+ format, type, data,
+ scale[0], bias[0],
+ scale[1], bias[1],
+ scale[2], bias[2],
+ scale[3], bias[3]);
+
+ if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
+ /* per-texture object palette */
+ if (ctx->Driver.UpdateTexturePalette) {
+ (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
+ }
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+
+static void GLAPIENTRY
+_mesa_CopyColorTable(GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ return; /* no readbuffer - OK */
+ }
+
+ ctx->Driver.CopyColorTable( ctx, target, internalformat, x, y, width );
+}
+
+
+
+static void GLAPIENTRY
+_mesa_CopyColorSubTable(GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ return; /* no readbuffer - OK */
+ }
+
+ ctx->Driver.CopyColorSubTable( ctx, target, start, x, y, width );
+}
+
+
+
+static void GLAPIENTRY
+_mesa_GetColorTable( GLenum target, GLenum format,
+ GLenum type, GLvoid *data )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ struct gl_color_table *table = NULL;
+ GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ default:
+ /* try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj && !_mesa_is_proxy_texture(target)) {
+ table = &texobj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
+ return;
+ }
+ }
+ }
+
+ ASSERT(table);
+
+ if (table->Size <= 0) {
+ return;
+ }
+
+ switch (table->_BaseFormat) {
+ case GL_ALPHA:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] = 0;
+ rgba[i][GCOMP] = 0;
+ rgba[i][BCOMP] = 0;
+ rgba[i][ACOMP] = table->TableF[i];
+ }
+ }
+ break;
+ case GL_LUMINANCE:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = table->TableF[i];
+ rgba[i][ACOMP] = 1.0F;
+ }
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = table->TableF[i*2+0];
+ rgba[i][ACOMP] = table->TableF[i*2+1];
+ }
+ }
+ break;
+ case GL_INTENSITY:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] =
+ rgba[i][ACOMP] = table->TableF[i];
+ }
+ }
+ break;
+ case GL_RGB:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] = table->TableF[i*3+0];
+ rgba[i][GCOMP] = table->TableF[i*3+1];
+ rgba[i][BCOMP] = table->TableF[i*3+2];
+ rgba[i][ACOMP] = 1.0F;
+ }
+ }
+ break;
+ case GL_RGBA:
+ memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat));
+ break;
+ default:
+ _mesa_problem(ctx, "bad table format in glGetColorTable");
+ return;
+ }
+
+ data = _mesa_map_validate_pbo_dest(ctx,
+ 1, &ctx->Pack, table->Size, 1, 1,
+ format, type, data,
+ "glGetColorTable");
+ if (!data)
+ return;
+
+ _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
+ format, type, data, &ctx->Pack, 0x0);
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+
+static void GLAPIENTRY
+_mesa_ColorTableParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ /* no extensions use this function */
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(target)");
+}
+
+
+
+static void GLAPIENTRY
+_mesa_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ /* no extensions use this function */
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameteriv(target)");
+}
+
+
+
+static void GLAPIENTRY
+_mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ struct gl_color_table *table = NULL;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ default:
+ /* try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj) {
+ table = &texobj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetColorTableParameterfv(target)");
+ return;
+ }
+ }
+ }
+
+ assert(table);
+
+ switch (pname) {
+ case GL_COLOR_TABLE_FORMAT:
+ *params = (GLfloat) table->InternalFormat;
+ break;
+ case GL_COLOR_TABLE_WIDTH:
+ *params = (GLfloat) table->Size;
+ break;
+ case GL_COLOR_TABLE_RED_SIZE:
+ *params = (GLfloat) table->RedSize;
+ break;
+ case GL_COLOR_TABLE_GREEN_SIZE:
+ *params = (GLfloat) table->GreenSize;
+ break;
+ case GL_COLOR_TABLE_BLUE_SIZE:
+ *params = (GLfloat) table->BlueSize;
+ break;
+ case GL_COLOR_TABLE_ALPHA_SIZE:
+ *params = (GLfloat) table->AlphaSize;
+ break;
+ case GL_COLOR_TABLE_LUMINANCE_SIZE:
+ *params = (GLfloat) table->LuminanceSize;
+ break;
+ case GL_COLOR_TABLE_INTENSITY_SIZE:
+ *params = (GLfloat) table->IntensitySize;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(pname)" );
+ return;
+ }
+}
+
+
+
+static void GLAPIENTRY
+_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ struct gl_color_table *table = NULL;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ default:
+ /* Try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj) {
+ table = &texobj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetColorTableParameteriv(target)");
+ return;
+ }
+ }
+ }
+
+ assert(table);
+
+ switch (pname) {
+ case GL_COLOR_TABLE_FORMAT:
+ *params = table->InternalFormat;
+ break;
+ case GL_COLOR_TABLE_WIDTH:
+ *params = table->Size;
+ break;
+ case GL_COLOR_TABLE_RED_SIZE:
+ *params = table->RedSize;
+ break;
+ case GL_COLOR_TABLE_GREEN_SIZE:
+ *params = table->GreenSize;
+ break;
+ case GL_COLOR_TABLE_BLUE_SIZE:
+ *params = table->BlueSize;
+ break;
+ case GL_COLOR_TABLE_ALPHA_SIZE:
+ *params = table->AlphaSize;
+ break;
+ case GL_COLOR_TABLE_LUMINANCE_SIZE:
+ *params = table->LuminanceSize;
+ break;
+ case GL_COLOR_TABLE_INTENSITY_SIZE:
+ *params = table->IntensitySize;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(pname)" );
+ return;
+ }
+}
+
+
+void
+_mesa_init_colortable_dispatch(struct _glapi_table *disp)
+{
+ SET_ColorSubTable(disp, _mesa_ColorSubTable);
+ SET_ColorTable(disp, _mesa_ColorTable);
+ SET_ColorTableParameterfv(disp, _mesa_ColorTableParameterfv);
+ SET_ColorTableParameteriv(disp, _mesa_ColorTableParameteriv);
+ SET_CopyColorSubTable(disp, _mesa_CopyColorSubTable);
+ SET_CopyColorTable(disp, _mesa_CopyColorTable);
+ SET_GetColorTable(disp, _mesa_GetColorTable);
+ SET_GetColorTableParameterfv(disp, _mesa_GetColorTableParameterfv);
+ SET_GetColorTableParameteriv(disp, _mesa_GetColorTableParameteriv);
+}
+
+
+#endif /* FEATURE_colortable */
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+
+void
+_mesa_init_colortable( struct gl_color_table *p )
+{
+ p->TableF = NULL;
+ p->TableUB = NULL;
+ p->Size = 0;
+ p->InternalFormat = GL_RGBA;
+}
+
+
+
+void
+_mesa_free_colortable_data( struct gl_color_table *p )
+{
+ if (p->TableF) {
+ free(p->TableF);
+ p->TableF = NULL;
+ }
+ if (p->TableUB) {
+ free(p->TableUB);
+ p->TableUB = NULL;
+ }
+}
diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c
index 8e904c778..4e463dd06 100644
--- a/mesalib/src/mesa/main/dlist.c
+++ b/mesalib/src/mesa/main/dlist.c
@@ -54,6 +54,7 @@
#include "light.h"
#include "macros.h"
#include "pack.h"
+#include "pbo.h"
#include "queryobj.h"
#include "teximage.h"
#include "mtypes.h"
diff --git a/mesalib/src/mesa/main/drawpix.c b/mesalib/src/mesa/main/drawpix.c
index 554d7a84a..98e82ef85 100644
--- a/mesalib/src/mesa/main/drawpix.c
+++ b/mesalib/src/mesa/main/drawpix.c
@@ -1,303 +1,304 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2008 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 "imports.h"
-#include "bufferobj.h"
-#include "context.h"
-#include "drawpix.h"
-#include "enums.h"
-#include "feedback.h"
-#include "framebuffer.h"
-#include "mfeatures.h"
-#include "readpix.h"
-#include "state.h"
-#include "dispatch.h"
-
-
-#if FEATURE_drawpix
-
-
-/*
- * Execute glDrawPixels
- */
-static void GLAPIENTRY
-_mesa_DrawPixels( GLsizei width, GLsizei height,
- GLenum format, GLenum type, const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n",
- width, height,
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type),
- pixels,
- _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
- IROUND(ctx->Current.RasterPos[0]),
- IROUND(ctx->Current.RasterPos[1]));
-
-
- if (width < 0 || height < 0) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
- return;
- }
-
- /* We're not using the current vertex program, and the driver may install
- * its own. Note: this may dirty some state.
- */
- _mesa_set_vp_override(ctx, GL_TRUE);
-
- /* Note: this call does state validation */
- if (!_mesa_valid_to_render(ctx, "glDrawPixels")) {
- goto end; /* the error code was recorded */
- }
-
- if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) {
- goto end; /* the error code was recorded */
- }
-
- if (!ctx->Current.RasterPosValid) {
- goto end; /* no-op, not an error */
- }
-
- if (ctx->RenderMode == GL_RENDER) {
- if (width > 0 && height > 0) {
- /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
- GLint x = IROUND(ctx->Current.RasterPos[0]);
- GLint y = IROUND(ctx->Current.RasterPos[1]);
-
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack from PBO */
- if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawPixels(invalid PBO access)");
- goto end;
- }
- if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
- /* buffer is mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawPixels(PBO is mapped)");
- goto end;
- }
- }
-
- ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
- &ctx->Unpack, pixels);
- }
- }
- else if (ctx->RenderMode == GL_FEEDBACK) {
- /* Feedback the current raster pos info */
- FLUSH_CURRENT( ctx, 0 );
- _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
- _mesa_feedback_vertex( ctx,
- ctx->Current.RasterPos,
- ctx->Current.RasterColor,
- ctx->Current.RasterTexCoords[0] );
- }
- else {
- ASSERT(ctx->RenderMode == GL_SELECT);
- /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
- }
-
-end:
- _mesa_set_vp_override(ctx, GL_FALSE);
-}
-
-
-static void GLAPIENTRY
-_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
- GLenum type )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- _mesa_finish(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx,
- "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n",
- srcx, srcy, width, height,
- _mesa_lookup_enum_by_nr(type),
- _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer),
- _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
- IROUND(ctx->Current.RasterPos[0]),
- IROUND(ctx->Current.RasterPos[1]));
-
- if (width < 0 || height < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
- return;
- }
-
- /* Note: more detailed 'type' checking is done by the
- * _mesa_source/dest_buffer_exists() calls below. That's where we
- * check if the stencil buffer exists, etc.
- */
- if (type != GL_COLOR &&
- type != GL_DEPTH &&
- type != GL_STENCIL &&
- type != GL_DEPTH_STENCIL) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)",
- _mesa_lookup_enum_by_nr(type));
- return;
- }
-
- /* We're not using the current vertex program, and the driver may install
- * it's own. Note: this may dirty some state.
- */
- _mesa_set_vp_override(ctx, GL_TRUE);
-
- /* Note: this call does state validation */
- if (!_mesa_valid_to_render(ctx, "glCopyPixels")) {
- goto end; /* the error code was recorded */
- }
-
- /* Check read buffer's status (draw buffer was already checked) */
- if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glCopyPixels(incomplete framebuffer)" );
- goto end;
- }
-
- if (!_mesa_source_buffer_exists(ctx, type) ||
- !_mesa_dest_buffer_exists(ctx, type)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyPixels(missing source or dest buffer)");
- goto end;
- }
-
- if (!ctx->Current.RasterPosValid || width ==0 || height == 0) {
- goto end; /* no-op, not an error */
- }
-
- if (ctx->RenderMode == GL_RENDER) {
- /* Round to satisfy conformance tests (matches SGI's OpenGL) */
- if (width > 0 && height > 0) {
- GLint destx = IROUND(ctx->Current.RasterPos[0]);
- GLint desty = IROUND(ctx->Current.RasterPos[1]);
- ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
- type );
- }
- }
- else if (ctx->RenderMode == GL_FEEDBACK) {
- FLUSH_CURRENT( ctx, 0 );
- _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
- _mesa_feedback_vertex( ctx,
- ctx->Current.RasterPos,
- ctx->Current.RasterColor,
- ctx->Current.RasterTexCoords[0] );
- }
- else {
- ASSERT(ctx->RenderMode == GL_SELECT);
- /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
- }
-
-end:
- _mesa_set_vp_override(ctx, GL_FALSE);
-}
-
-
-static void GLAPIENTRY
-_mesa_Bitmap( GLsizei width, GLsizei height,
- GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
- const GLubyte *bitmap )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (width < 0 || height < 0) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
- return;
- }
-
- if (!ctx->Current.RasterPosValid) {
- return; /* do nothing */
- }
-
- /* Note: this call does state validation */
- if (!_mesa_valid_to_render(ctx, "glBitmap")) {
- /* the error code was recorded */
- return;
- }
-
- if (ctx->RenderMode == GL_RENDER) {
- /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
- if (width > 0 && height > 0) {
- const GLfloat epsilon = 0.0001F;
- GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
- GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
-
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack from PBO */
- if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
- GL_COLOR_INDEX, GL_BITMAP,
- (GLvoid *) bitmap)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBitmap(invalid PBO access)");
- return;
- }
- if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
- /* buffer is mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBitmap(PBO is mapped)");
- return;
- }
- }
-
- ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
- }
- }
-#if _HAVE_FULL_GL
- else if (ctx->RenderMode == GL_FEEDBACK) {
- FLUSH_CURRENT(ctx, 0);
- _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
- _mesa_feedback_vertex( ctx,
- ctx->Current.RasterPos,
- ctx->Current.RasterColor,
- ctx->Current.RasterTexCoords[0] );
- }
- else {
- ASSERT(ctx->RenderMode == GL_SELECT);
- /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
- }
-#endif
-
- /* update raster position */
- ctx->Current.RasterPos[0] += xmove;
- ctx->Current.RasterPos[1] += ymove;
-}
-
-
-void
-_mesa_init_drawpix_dispatch(struct _glapi_table *disp)
-{
- SET_Bitmap(disp, _mesa_Bitmap);
- SET_CopyPixels(disp, _mesa_CopyPixels);
- SET_DrawPixels(disp, _mesa_DrawPixels);
-}
-
-
-#endif /* FEATURE_drawpix */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "imports.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "drawpix.h"
+#include "enums.h"
+#include "feedback.h"
+#include "framebuffer.h"
+#include "mfeatures.h"
+#include "pbo.h"
+#include "readpix.h"
+#include "state.h"
+#include "dispatch.h"
+
+
+#if FEATURE_drawpix
+
+
+/*
+ * Execute glDrawPixels
+ */
+static void GLAPIENTRY
+_mesa_DrawPixels( GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n",
+ width, height,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type),
+ pixels,
+ _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
+ IROUND(ctx->Current.RasterPos[0]),
+ IROUND(ctx->Current.RasterPos[1]));
+
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
+ return;
+ }
+
+ /* We're not using the current vertex program, and the driver may install
+ * its own. Note: this may dirty some state.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
+
+ /* Note: this call does state validation */
+ if (!_mesa_valid_to_render(ctx, "glDrawPixels")) {
+ goto end; /* the error code was recorded */
+ }
+
+ if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) {
+ goto end; /* the error code was recorded */
+ }
+
+ if (!ctx->Current.RasterPosValid) {
+ goto end; /* no-op, not an error */
+ }
+
+ if (ctx->RenderMode == GL_RENDER) {
+ if (width > 0 && height > 0) {
+ /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
+ GLint x = IROUND(ctx->Current.RasterPos[0]);
+ GLint y = IROUND(ctx->Current.RasterPos[1]);
+
+ if (ctx->Unpack.BufferObj->Name) {
+ /* unpack from PBO */
+ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(invalid PBO access)");
+ goto end;
+ }
+ if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(PBO is mapped)");
+ goto end;
+ }
+ }
+
+ ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
+ &ctx->Unpack, pixels);
+ }
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ /* Feedback the current raster pos info */
+ FLUSH_CURRENT( ctx, 0 );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
+ }
+
+end:
+ _mesa_set_vp_override(ctx, GL_FALSE);
+}
+
+
+static void GLAPIENTRY
+_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+ GLenum type )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ _mesa_finish(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n",
+ srcx, srcy, width, height,
+ _mesa_lookup_enum_by_nr(type),
+ _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer),
+ _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
+ IROUND(ctx->Current.RasterPos[0]),
+ IROUND(ctx->Current.RasterPos[1]));
+
+ if (width < 0 || height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
+ return;
+ }
+
+ /* Note: more detailed 'type' checking is done by the
+ * _mesa_source/dest_buffer_exists() calls below. That's where we
+ * check if the stencil buffer exists, etc.
+ */
+ if (type != GL_COLOR &&
+ type != GL_DEPTH &&
+ type != GL_STENCIL &&
+ type != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ /* We're not using the current vertex program, and the driver may install
+ * it's own. Note: this may dirty some state.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
+
+ /* Note: this call does state validation */
+ if (!_mesa_valid_to_render(ctx, "glCopyPixels")) {
+ goto end; /* the error code was recorded */
+ }
+
+ /* Check read buffer's status (draw buffer was already checked) */
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyPixels(incomplete framebuffer)" );
+ goto end;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, type) ||
+ !_mesa_dest_buffer_exists(ctx, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyPixels(missing source or dest buffer)");
+ goto end;
+ }
+
+ if (!ctx->Current.RasterPosValid || width ==0 || height == 0) {
+ goto end; /* no-op, not an error */
+ }
+
+ if (ctx->RenderMode == GL_RENDER) {
+ /* Round to satisfy conformance tests (matches SGI's OpenGL) */
+ if (width > 0 && height > 0) {
+ GLint destx = IROUND(ctx->Current.RasterPos[0]);
+ GLint desty = IROUND(ctx->Current.RasterPos[1]);
+ ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
+ type );
+ }
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ FLUSH_CURRENT( ctx, 0 );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
+ }
+
+end:
+ _mesa_set_vp_override(ctx, GL_FALSE);
+}
+
+
+static void GLAPIENTRY
+_mesa_Bitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
+ return;
+ }
+
+ if (!ctx->Current.RasterPosValid) {
+ return; /* do nothing */
+ }
+
+ /* Note: this call does state validation */
+ if (!_mesa_valid_to_render(ctx, "glBitmap")) {
+ /* the error code was recorded */
+ return;
+ }
+
+ if (ctx->RenderMode == GL_RENDER) {
+ /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
+ if (width > 0 && height > 0) {
+ const GLfloat epsilon = 0.0001F;
+ GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
+ GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
+
+ if (ctx->Unpack.BufferObj->Name) {
+ /* unpack from PBO */
+ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+ GL_COLOR_INDEX, GL_BITMAP,
+ (GLvoid *) bitmap)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBitmap(invalid PBO access)");
+ return;
+ }
+ if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBitmap(PBO is mapped)");
+ return;
+ }
+ }
+
+ ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
+ }
+ }
+#if _HAVE_FULL_GL
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ FLUSH_CURRENT(ctx, 0);
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
+ }
+#endif
+
+ /* update raster position */
+ ctx->Current.RasterPos[0] += xmove;
+ ctx->Current.RasterPos[1] += ymove;
+}
+
+
+void
+_mesa_init_drawpix_dispatch(struct _glapi_table *disp)
+{
+ SET_Bitmap(disp, _mesa_Bitmap);
+ SET_CopyPixels(disp, _mesa_CopyPixels);
+ SET_DrawPixels(disp, _mesa_DrawPixels);
+}
+
+
+#endif /* FEATURE_drawpix */
diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c
index 231278bee..f24709241 100644
--- a/mesalib/src/mesa/main/enable.c
+++ b/mesalib/src/mesa/main/enable.c
@@ -1,1501 +1,1487 @@
-/**
- * \file enable.c
- * Enable/disable/query GL capabilities.
- */
-
-/*
- * Mesa 3-D graphics library
- * Version: 7.0.3
- *
- * 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 "enable.h"
-#include "light.h"
-#include "simple_list.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "enums.h"
-#include "api_arrayelt.h"
-#include "texstate.h"
-
-
-
-#define CHECK_EXTENSION(EXTNAME, CAP) \
- if (!ctx->Extensions.EXTNAME) { \
- goto invalid_enum_error; \
- }
-
-
-/**
- * Helper to enable/disable client-side state.
- */
-static void
-client_state(struct gl_context *ctx, GLenum cap, GLboolean state)
-{
- struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
- GLuint flag;
- GLboolean *var;
-
- switch (cap) {
- case GL_VERTEX_ARRAY:
- var = &arrayObj->Vertex.Enabled;
- flag = _NEW_ARRAY_VERTEX;
- break;
- case GL_NORMAL_ARRAY:
- var = &arrayObj->Normal.Enabled;
- flag = _NEW_ARRAY_NORMAL;
- break;
- case GL_COLOR_ARRAY:
- var = &arrayObj->Color.Enabled;
- flag = _NEW_ARRAY_COLOR0;
- break;
- case GL_INDEX_ARRAY:
- var = &arrayObj->Index.Enabled;
- flag = _NEW_ARRAY_INDEX;
- break;
- case GL_TEXTURE_COORD_ARRAY:
- var = &arrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled;
- flag = _NEW_ARRAY_TEXCOORD(ctx->Array.ActiveTexture);
- break;
- case GL_EDGE_FLAG_ARRAY:
- var = &arrayObj->EdgeFlag.Enabled;
- flag = _NEW_ARRAY_EDGEFLAG;
- break;
- case GL_FOG_COORDINATE_ARRAY_EXT:
- var = &arrayObj->FogCoord.Enabled;
- flag = _NEW_ARRAY_FOGCOORD;
- break;
- case GL_SECONDARY_COLOR_ARRAY_EXT:
- var = &arrayObj->SecondaryColor.Enabled;
- flag = _NEW_ARRAY_COLOR1;
- break;
-
-#if FEATURE_point_size_array
- case GL_POINT_SIZE_ARRAY_OES:
- var = &arrayObj->PointSize.Enabled;
- flag = _NEW_ARRAY_POINT_SIZE;
- break;
-#endif
-
-#if FEATURE_NV_vertex_program
- case GL_VERTEX_ATTRIB_ARRAY0_NV:
- case GL_VERTEX_ATTRIB_ARRAY1_NV:
- case GL_VERTEX_ATTRIB_ARRAY2_NV:
- case GL_VERTEX_ATTRIB_ARRAY3_NV:
- case GL_VERTEX_ATTRIB_ARRAY4_NV:
- case GL_VERTEX_ATTRIB_ARRAY5_NV:
- case GL_VERTEX_ATTRIB_ARRAY6_NV:
- case GL_VERTEX_ATTRIB_ARRAY7_NV:
- case GL_VERTEX_ATTRIB_ARRAY8_NV:
- case GL_VERTEX_ATTRIB_ARRAY9_NV:
- case GL_VERTEX_ATTRIB_ARRAY10_NV:
- case GL_VERTEX_ATTRIB_ARRAY11_NV:
- case GL_VERTEX_ATTRIB_ARRAY12_NV:
- case GL_VERTEX_ATTRIB_ARRAY13_NV:
- case GL_VERTEX_ATTRIB_ARRAY14_NV:
- case GL_VERTEX_ATTRIB_ARRAY15_NV:
- CHECK_EXTENSION(NV_vertex_program, cap);
- {
- GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
- ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
- var = &arrayObj->VertexAttrib[n].Enabled;
- flag = _NEW_ARRAY_ATTRIB(n);
- }
- break;
-#endif /* FEATURE_NV_vertex_program */
-
- /* GL_NV_primitive_restart */
- case GL_PRIMITIVE_RESTART_NV:
- if (!ctx->Extensions.NV_primitive_restart) {
- goto invalid_enum_error;
- }
- var = &ctx->Array.PrimitiveRestart;
- flag = 0;
- break;
-
- default:
- goto invalid_enum_error;
- }
-
- if (*var == state)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_ARRAY);
- ctx->Array.NewState |= flag;
-
- _ae_invalidate_state(ctx, _NEW_ARRAY);
-
- *var = state;
-
- if (state)
- ctx->Array.ArrayObj->_Enabled |= flag;
- else
- ctx->Array.ArrayObj->_Enabled &= ~flag;
-
- if (ctx->Driver.Enable) {
- ctx->Driver.Enable( ctx, cap, state );
- }
-
- return;
-
-invalid_enum_error:
- _mesa_error(ctx, GL_INVALID_ENUM, "gl%sClientState(0x%x)",
- state ? "Enable" : "Disable", cap);
-}
-
-
-/**
- * Enable GL capability.
- * \param cap state to enable/disable.
- *
- * Get's the current context, assures that we're outside glBegin()/glEnd() and
- * calls client_state().
- */
-void GLAPIENTRY
-_mesa_EnableClientState( GLenum cap )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- client_state( ctx, cap, GL_TRUE );
-}
-
-
-/**
- * Disable GL capability.
- * \param cap state to enable/disable.
- *
- * Get's the current context, assures that we're outside glBegin()/glEnd() and
- * calls client_state().
- */
-void GLAPIENTRY
-_mesa_DisableClientState( GLenum cap )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- client_state( ctx, cap, GL_FALSE );
-}
-
-
-#undef CHECK_EXTENSION
-#define CHECK_EXTENSION(EXTNAME, CAP) \
- if (!ctx->Extensions.EXTNAME) { \
- goto invalid_enum_error; \
- }
-
-#define CHECK_EXTENSION2(EXT1, EXT2, CAP) \
- if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
- goto invalid_enum_error; \
- }
-
-
-
-/**
- * Return pointer to current texture unit for setting/getting coordinate
- * state.
- * Note that we'll set GL_INVALID_OPERATION if the active texture unit is
- * higher than the number of supported coordinate units. And we'll return NULL.
- */
-static struct gl_texture_unit *
-get_texcoord_unit(struct gl_context *ctx)
-{
- if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glEnable/Disable(texcoord unit)");
- return NULL;
- }
- else {
- return &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- }
-}
-
-
-/**
- * Helper function to enable or disable a texture target.
- * \param bit one of the TEXTURE_x_BIT values
- * \return GL_TRUE if state is changing or GL_FALSE if no change
- */
-static GLboolean
-enable_texture(struct gl_context *ctx, GLboolean state, GLbitfield texBit)
-{
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- const GLbitfield newenabled = state
- ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit);
-
- if (texUnit->Enabled == newenabled)
- return GL_FALSE;
-
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Enabled = newenabled;
- return GL_TRUE;
-}
-
-
-/**
- * Helper function to enable or disable state.
- *
- * \param ctx GL context.
- * \param cap the state to enable/disable
- * \param state whether to enable or disable the specified capability.
- *
- * Updates the current context and flushes the vertices as needed. For
- * capabilities associated with extensions it verifies that those extensions
- * are effectivly present before updating. Notifies the driver via
- * dd_function_table::Enable.
- */
-void
-_mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
-{
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "%s %s (newstate is %x)\n",
- state ? "glEnable" : "glDisable",
- _mesa_lookup_enum_by_nr(cap),
- ctx->NewState);
-
- switch (cap) {
- case GL_ALPHA_TEST:
- if (ctx->Color.AlphaEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.AlphaEnabled = state;
- break;
- case GL_AUTO_NORMAL:
- if (ctx->Eval.AutoNormal == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.AutoNormal = state;
- break;
- case GL_BLEND:
- {
- GLbitfield newEnabled = state * ((1 << ctx->Const.MaxDrawBuffers) - 1);
- if (newEnabled != ctx->Color.BlendEnabled) {
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.BlendEnabled = newEnabled;
- }
- }
- break;
-#if FEATURE_userclip
- case GL_CLIP_PLANE0:
- case GL_CLIP_PLANE1:
- case GL_CLIP_PLANE2:
- case GL_CLIP_PLANE3:
- case GL_CLIP_PLANE4:
- case GL_CLIP_PLANE5:
- {
- const GLuint p = cap - GL_CLIP_PLANE0;
-
- if ((ctx->Transform.ClipPlanesEnabled & (1 << p)) == ((GLuint) state << p))
- return;
-
- FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
-
- if (state) {
- ctx->Transform.ClipPlanesEnabled |= (1 << p);
-
- if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
- _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
-
- /* This derived state also calculated in clip.c and
- * from _mesa_update_state() on changes to EyeUserPlane
- * and ctx->ProjectionMatrix respectively.
- */
- _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
- ctx->Transform.EyeUserPlane[p],
- ctx->ProjectionMatrixStack.Top->inv );
- }
- else {
- ctx->Transform.ClipPlanesEnabled &= ~(1 << p);
- }
- }
- break;
-#endif
- case GL_COLOR_MATERIAL:
- if (ctx->Light.ColorMaterialEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_LIGHT);
- FLUSH_CURRENT(ctx, 0);
- ctx->Light.ColorMaterialEnabled = state;
- if (state) {
- _mesa_update_color_material( ctx,
- ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
- }
- break;
- case GL_CULL_FACE:
- if (ctx->Polygon.CullFlag == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.CullFlag = state;
- break;
- case GL_DEPTH_TEST:
- if (ctx->Depth.Test == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_DEPTH);
- ctx->Depth.Test = state;
- break;
- case GL_DITHER:
- if (ctx->Color.DitherFlag == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.DitherFlag = state;
- break;
- case GL_FOG:
- if (ctx->Fog.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_FOG);
- ctx->Fog.Enabled = state;
- break;
- case GL_LIGHT0:
- case GL_LIGHT1:
- case GL_LIGHT2:
- case GL_LIGHT3:
- case GL_LIGHT4:
- case GL_LIGHT5:
- case GL_LIGHT6:
- case GL_LIGHT7:
- if (ctx->Light.Light[cap-GL_LIGHT0].Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_LIGHT);
- ctx->Light.Light[cap-GL_LIGHT0].Enabled = state;
- if (state) {
- insert_at_tail(&ctx->Light.EnabledList,
- &ctx->Light.Light[cap-GL_LIGHT0]);
- }
- else {
- remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]);
- }
- break;
- case GL_LIGHTING:
- if (ctx->Light.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_LIGHT);
- ctx->Light.Enabled = state;
- if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
- ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
- else
- ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
- break;
- case GL_LINE_SMOOTH:
- if (ctx->Line.SmoothFlag == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_LINE);
- ctx->Line.SmoothFlag = state;
- ctx->_TriangleCaps ^= DD_LINE_SMOOTH;
- break;
- case GL_LINE_STIPPLE:
- if (ctx->Line.StippleFlag == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_LINE);
- ctx->Line.StippleFlag = state;
- ctx->_TriangleCaps ^= DD_LINE_STIPPLE;
- break;
- case GL_INDEX_LOGIC_OP:
- if (ctx->Color.IndexLogicOpEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.IndexLogicOpEnabled = state;
- break;
- case GL_COLOR_LOGIC_OP:
- if (ctx->Color.ColorLogicOpEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.ColorLogicOpEnabled = state;
- break;
- case GL_MAP1_COLOR_4:
- if (ctx->Eval.Map1Color4 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1Color4 = state;
- break;
- case GL_MAP1_INDEX:
- if (ctx->Eval.Map1Index == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1Index = state;
- break;
- case GL_MAP1_NORMAL:
- if (ctx->Eval.Map1Normal == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1Normal = state;
- break;
- case GL_MAP1_TEXTURE_COORD_1:
- if (ctx->Eval.Map1TextureCoord1 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1TextureCoord1 = state;
- break;
- case GL_MAP1_TEXTURE_COORD_2:
- if (ctx->Eval.Map1TextureCoord2 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1TextureCoord2 = state;
- break;
- case GL_MAP1_TEXTURE_COORD_3:
- if (ctx->Eval.Map1TextureCoord3 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1TextureCoord3 = state;
- break;
- case GL_MAP1_TEXTURE_COORD_4:
- if (ctx->Eval.Map1TextureCoord4 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1TextureCoord4 = state;
- break;
- case GL_MAP1_VERTEX_3:
- if (ctx->Eval.Map1Vertex3 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1Vertex3 = state;
- break;
- case GL_MAP1_VERTEX_4:
- if (ctx->Eval.Map1Vertex4 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1Vertex4 = state;
- break;
- case GL_MAP2_COLOR_4:
- if (ctx->Eval.Map2Color4 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2Color4 = state;
- break;
- case GL_MAP2_INDEX:
- if (ctx->Eval.Map2Index == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2Index = state;
- break;
- case GL_MAP2_NORMAL:
- if (ctx->Eval.Map2Normal == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2Normal = state;
- break;
- case GL_MAP2_TEXTURE_COORD_1:
- if (ctx->Eval.Map2TextureCoord1 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2TextureCoord1 = state;
- break;
- case GL_MAP2_TEXTURE_COORD_2:
- if (ctx->Eval.Map2TextureCoord2 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2TextureCoord2 = state;
- break;
- case GL_MAP2_TEXTURE_COORD_3:
- if (ctx->Eval.Map2TextureCoord3 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2TextureCoord3 = state;
- break;
- case GL_MAP2_TEXTURE_COORD_4:
- if (ctx->Eval.Map2TextureCoord4 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2TextureCoord4 = state;
- break;
- case GL_MAP2_VERTEX_3:
- if (ctx->Eval.Map2Vertex3 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2Vertex3 = state;
- break;
- case GL_MAP2_VERTEX_4:
- if (ctx->Eval.Map2Vertex4 == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2Vertex4 = state;
- break;
- case GL_NORMALIZE:
- if (ctx->Transform.Normalize == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
- ctx->Transform.Normalize = state;
- break;
- case GL_POINT_SMOOTH:
- if (ctx->Point.SmoothFlag == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POINT);
- ctx->Point.SmoothFlag = state;
- ctx->_TriangleCaps ^= DD_POINT_SMOOTH;
- break;
- case GL_POLYGON_SMOOTH:
- if (ctx->Polygon.SmoothFlag == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.SmoothFlag = state;
- ctx->_TriangleCaps ^= DD_TRI_SMOOTH;
- break;
- case GL_POLYGON_STIPPLE:
- if (ctx->Polygon.StippleFlag == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.StippleFlag = state;
- ctx->_TriangleCaps ^= DD_TRI_STIPPLE;
- break;
- case GL_POLYGON_OFFSET_POINT:
- if (ctx->Polygon.OffsetPoint == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.OffsetPoint = state;
- break;
- case GL_POLYGON_OFFSET_LINE:
- if (ctx->Polygon.OffsetLine == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.OffsetLine = state;
- break;
- case GL_POLYGON_OFFSET_FILL:
- /*case GL_POLYGON_OFFSET_EXT:*/
- if (ctx->Polygon.OffsetFill == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.OffsetFill = state;
- break;
- case GL_RESCALE_NORMAL_EXT:
- if (ctx->Transform.RescaleNormals == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
- ctx->Transform.RescaleNormals = state;
- break;
- case GL_SCISSOR_TEST:
- if (ctx->Scissor.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_SCISSOR);
- ctx->Scissor.Enabled = state;
- break;
- case GL_SHARED_TEXTURE_PALETTE_EXT:
- if (ctx->Texture.SharedPalette == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- ctx->Texture.SharedPalette = state;
- break;
- case GL_STENCIL_TEST:
- if (ctx->Stencil.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_STENCIL);
- ctx->Stencil.Enabled = state;
- break;
- case GL_TEXTURE_1D:
- if (!enable_texture(ctx, state, TEXTURE_1D_BIT)) {
- return;
- }
- break;
- case GL_TEXTURE_2D:
- if (!enable_texture(ctx, state, TEXTURE_2D_BIT)) {
- return;
- }
- break;
- case GL_TEXTURE_3D:
- if (!enable_texture(ctx, state, TEXTURE_3D_BIT)) {
- return;
- }
- break;
- case GL_TEXTURE_GEN_Q:
- {
- struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- GLuint newenabled = texUnit->TexGenEnabled & ~Q_BIT;
- if (state)
- newenabled |= Q_BIT;
- if (texUnit->TexGenEnabled == newenabled)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->TexGenEnabled = newenabled;
- }
- }
- break;
- case GL_TEXTURE_GEN_R:
- {
- struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- GLuint newenabled = texUnit->TexGenEnabled & ~R_BIT;
- if (state)
- newenabled |= R_BIT;
- if (texUnit->TexGenEnabled == newenabled)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->TexGenEnabled = newenabled;
- }
- }
- break;
- case GL_TEXTURE_GEN_S:
- {
- struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- GLuint newenabled = texUnit->TexGenEnabled & ~S_BIT;
- if (state)
- newenabled |= S_BIT;
- if (texUnit->TexGenEnabled == newenabled)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->TexGenEnabled = newenabled;
- }
- }
- break;
- case GL_TEXTURE_GEN_T:
- {
- struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- GLuint newenabled = texUnit->TexGenEnabled & ~T_BIT;
- if (state)
- newenabled |= T_BIT;
- if (texUnit->TexGenEnabled == newenabled)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->TexGenEnabled = newenabled;
- }
- }
- break;
-
-#if FEATURE_ES1
- case GL_TEXTURE_GEN_STR_OES:
- /* disable S, T, and R at the same time */
- {
- struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- GLuint newenabled =
- texUnit->TexGenEnabled & ~STR_BITS;
- if (state)
- newenabled |= STR_BITS;
- if (texUnit->TexGenEnabled == newenabled)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->TexGenEnabled = newenabled;
- }
- }
- break;
-#endif
-
- /*
- * CLIENT STATE!!!
- */
- case GL_VERTEX_ARRAY:
- case GL_NORMAL_ARRAY:
- case GL_COLOR_ARRAY:
- case GL_INDEX_ARRAY:
- case GL_TEXTURE_COORD_ARRAY:
- case GL_EDGE_FLAG_ARRAY:
- case GL_FOG_COORDINATE_ARRAY_EXT:
- case GL_SECONDARY_COLOR_ARRAY_EXT:
- case GL_POINT_SIZE_ARRAY_OES:
- client_state( ctx, cap, state );
- return;
-
- /* GL_SGI_texture_color_table */
- case GL_TEXTURE_COLOR_TABLE_SGI:
- CHECK_EXTENSION(SGI_texture_color_table, cap);
- if (ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled = state;
- break;
-
- /* GL_ARB_texture_cube_map */
- case GL_TEXTURE_CUBE_MAP_ARB:
- CHECK_EXTENSION(ARB_texture_cube_map, cap);
- if (!enable_texture(ctx, state, TEXTURE_CUBE_BIT)) {
- return;
- }
- break;
-
- /* GL_EXT_secondary_color */
- case GL_COLOR_SUM_EXT:
- CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program, cap);
- if (ctx->Fog.ColorSumEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_FOG);
- ctx->Fog.ColorSumEnabled = state;
- break;
-
- /* GL_ARB_multisample */
- case GL_MULTISAMPLE_ARB:
- if (ctx->Multisample.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
- ctx->Multisample.Enabled = state;
- break;
- case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
- if (ctx->Multisample.SampleAlphaToCoverage == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
- ctx->Multisample.SampleAlphaToCoverage = state;
- break;
- case GL_SAMPLE_ALPHA_TO_ONE_ARB:
- if (ctx->Multisample.SampleAlphaToOne == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
- ctx->Multisample.SampleAlphaToOne = state;
- break;
- case GL_SAMPLE_COVERAGE_ARB:
- if (ctx->Multisample.SampleCoverage == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
- ctx->Multisample.SampleCoverage = state;
- break;
- case GL_SAMPLE_COVERAGE_INVERT_ARB:
- if (ctx->Multisample.SampleCoverageInvert == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
- ctx->Multisample.SampleCoverageInvert = state;
- break;
-
- /* GL_IBM_rasterpos_clip */
- case GL_RASTER_POSITION_UNCLIPPED_IBM:
- CHECK_EXTENSION(IBM_rasterpos_clip, cap);
- if (ctx->Transform.RasterPositionUnclipped == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
- ctx->Transform.RasterPositionUnclipped = state;
- break;
-
- /* GL_NV_point_sprite */
- case GL_POINT_SPRITE_NV:
- CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite, cap);
- if (ctx->Point.PointSprite == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_POINT);
- ctx->Point.PointSprite = state;
- break;
-
-#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
- case GL_VERTEX_PROGRAM_ARB:
- CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
- if (ctx->VertexProgram.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- ctx->VertexProgram.Enabled = state;
- break;
- case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
- CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
- if (ctx->VertexProgram.PointSizeEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- ctx->VertexProgram.PointSizeEnabled = state;
- break;
- case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
- CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
- if (ctx->VertexProgram.TwoSideEnabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- ctx->VertexProgram.TwoSideEnabled = state;
- break;
-#endif
-#if FEATURE_NV_vertex_program
- case GL_MAP1_VERTEX_ATTRIB0_4_NV:
- case GL_MAP1_VERTEX_ATTRIB1_4_NV:
- case GL_MAP1_VERTEX_ATTRIB2_4_NV:
- case GL_MAP1_VERTEX_ATTRIB3_4_NV:
- case GL_MAP1_VERTEX_ATTRIB4_4_NV:
- case GL_MAP1_VERTEX_ATTRIB5_4_NV:
- case GL_MAP1_VERTEX_ATTRIB6_4_NV:
- case GL_MAP1_VERTEX_ATTRIB7_4_NV:
- case GL_MAP1_VERTEX_ATTRIB8_4_NV:
- case GL_MAP1_VERTEX_ATTRIB9_4_NV:
- case GL_MAP1_VERTEX_ATTRIB10_4_NV:
- case GL_MAP1_VERTEX_ATTRIB11_4_NV:
- case GL_MAP1_VERTEX_ATTRIB12_4_NV:
- case GL_MAP1_VERTEX_ATTRIB13_4_NV:
- case GL_MAP1_VERTEX_ATTRIB14_4_NV:
- case GL_MAP1_VERTEX_ATTRIB15_4_NV:
- CHECK_EXTENSION(NV_vertex_program, cap);
- {
- const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map1Attrib[map] = state;
- }
- break;
- case GL_MAP2_VERTEX_ATTRIB0_4_NV:
- case GL_MAP2_VERTEX_ATTRIB1_4_NV:
- case GL_MAP2_VERTEX_ATTRIB2_4_NV:
- case GL_MAP2_VERTEX_ATTRIB3_4_NV:
- case GL_MAP2_VERTEX_ATTRIB4_4_NV:
- case GL_MAP2_VERTEX_ATTRIB5_4_NV:
- case GL_MAP2_VERTEX_ATTRIB6_4_NV:
- case GL_MAP2_VERTEX_ATTRIB7_4_NV:
- case GL_MAP2_VERTEX_ATTRIB8_4_NV:
- case GL_MAP2_VERTEX_ATTRIB9_4_NV:
- case GL_MAP2_VERTEX_ATTRIB10_4_NV:
- case GL_MAP2_VERTEX_ATTRIB11_4_NV:
- case GL_MAP2_VERTEX_ATTRIB12_4_NV:
- case GL_MAP2_VERTEX_ATTRIB13_4_NV:
- case GL_MAP2_VERTEX_ATTRIB14_4_NV:
- case GL_MAP2_VERTEX_ATTRIB15_4_NV:
- CHECK_EXTENSION(NV_vertex_program, cap);
- {
- const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
- FLUSH_VERTICES(ctx, _NEW_EVAL);
- ctx->Eval.Map2Attrib[map] = state;
- }
- break;
-#endif /* FEATURE_NV_vertex_program */
-
-#if FEATURE_NV_fragment_program
- case GL_FRAGMENT_PROGRAM_NV:
- CHECK_EXTENSION(NV_fragment_program, cap);
- if (ctx->FragmentProgram.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- ctx->FragmentProgram.Enabled = state;
- break;
-#endif /* FEATURE_NV_fragment_program */
-
- /* GL_NV_texture_rectangle */
- case GL_TEXTURE_RECTANGLE_NV:
- CHECK_EXTENSION(NV_texture_rectangle, cap);
- if (!enable_texture(ctx, state, TEXTURE_RECT_BIT)) {
- return;
- }
- break;
-
- /* GL_EXT_stencil_two_side */
- case GL_STENCIL_TEST_TWO_SIDE_EXT:
- CHECK_EXTENSION(EXT_stencil_two_side, cap);
- if (ctx->Stencil.TestTwoSide == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_STENCIL);
- ctx->Stencil.TestTwoSide = state;
- if (state) {
- ctx->Stencil._BackFace = 2;
- ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
- } else {
- ctx->Stencil._BackFace = 1;
- ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL;
- }
- break;
-
-#if FEATURE_ARB_fragment_program
- case GL_FRAGMENT_PROGRAM_ARB:
- CHECK_EXTENSION(ARB_fragment_program, cap);
- if (ctx->FragmentProgram.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- ctx->FragmentProgram.Enabled = state;
- break;
-#endif /* FEATURE_ARB_fragment_program */
-
- /* GL_EXT_depth_bounds_test */
- case GL_DEPTH_BOUNDS_TEST_EXT:
- CHECK_EXTENSION(EXT_depth_bounds_test, cap);
- if (ctx->Depth.BoundsTest == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_DEPTH);
- ctx->Depth.BoundsTest = state;
- break;
-
- case GL_DEPTH_CLAMP:
- if (ctx->Transform.DepthClamp == state)
- return;
- CHECK_EXTENSION(ARB_depth_clamp, cap);
- FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
- ctx->Transform.DepthClamp = state;
- break;
-
-#if FEATURE_ATI_fragment_shader
- case GL_FRAGMENT_SHADER_ATI:
- CHECK_EXTENSION(ATI_fragment_shader, cap);
- if (ctx->ATIFragmentShader.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- ctx->ATIFragmentShader.Enabled = state;
- break;
-#endif
-
- /* GL_MESA_texture_array */
- case GL_TEXTURE_1D_ARRAY_EXT:
- CHECK_EXTENSION(MESA_texture_array, cap);
- if (!enable_texture(ctx, state, TEXTURE_1D_ARRAY_BIT)) {
- return;
- }
- break;
-
- case GL_TEXTURE_2D_ARRAY_EXT:
- CHECK_EXTENSION(MESA_texture_array, cap);
- if (!enable_texture(ctx, state, TEXTURE_2D_ARRAY_BIT)) {
- return;
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_SEAMLESS:
- CHECK_EXTENSION(ARB_seamless_cube_map, cap);
- ctx->Texture.CubeMapSeamless = state;
- break;
-
-#if FEATURE_EXT_transform_feedback
- case GL_RASTERIZER_DISCARD:
- CHECK_EXTENSION(EXT_transform_feedback, cap);
- if (ctx->TransformFeedback.RasterDiscard != state) {
- ctx->TransformFeedback.RasterDiscard = state;
- FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
- }
- break;
-#endif
-
- /* GL 3.1 primitive restart. Note: this enum is different from
- * GL_PRIMITIVE_RESTART_NV (which is client state).
- */
- case GL_PRIMITIVE_RESTART:
- if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
- goto invalid_enum_error;
- }
- if (ctx->Array.PrimitiveRestart != state) {
- FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
- ctx->Array.PrimitiveRestart = state;
- }
- break;
-
- /* GL3.0 - GL_framebuffer_sRGB */
- case GL_FRAMEBUFFER_SRGB_EXT:
- CHECK_EXTENSION(EXT_framebuffer_sRGB, cap);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
- ctx->Color.sRGBEnabled = state;
- break;
-
- default:
- goto invalid_enum_error;
- }
-
- if (ctx->Driver.Enable) {
- ctx->Driver.Enable( ctx, cap, state );
- }
-
- return;
-
-invalid_enum_error:
- _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)",
- state ? "Enable" : "Disable", cap);
-}
-
-
-/**
- * Enable GL capability. Called by glEnable()
- * \param cap state to enable.
- */
-void GLAPIENTRY
-_mesa_Enable( GLenum cap )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- _mesa_set_enable( ctx, cap, GL_TRUE );
-}
-
-
-/**
- * Disable GL capability. Called by glDisable()
- * \param cap state to disable.
- */
-void GLAPIENTRY
-_mesa_Disable( GLenum cap )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- _mesa_set_enable( ctx, cap, GL_FALSE );
-}
-
-
-
-/**
- * Enable/disable an indexed state var.
- */
-void
-_mesa_set_enablei(struct gl_context *ctx, GLenum cap, GLuint index, GLboolean state)
-{
- ASSERT(state == 0 || state == 1);
- switch (cap) {
- case GL_BLEND:
- if (!ctx->Extensions.EXT_draw_buffers2) {
- goto invalid_enum_error;
- }
- if (index >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)",
- state ? "glEnableIndexed" : "glDisableIndexed", index);
- return;
- }
- if (((ctx->Color.BlendEnabled >> index) & 1) != state) {
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- if (state)
- ctx->Color.BlendEnabled |= (1 << index);
- else
- ctx->Color.BlendEnabled &= ~(1 << index);
- }
- break;
- default:
- goto invalid_enum_error;
- }
- return;
-
-invalid_enum_error:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(cap=%s)",
- state ? "glEnablei" : "glDisablei",
- _mesa_lookup_enum_by_nr(cap));
-}
-
-
-void GLAPIENTRY
-_mesa_DisableIndexed( GLenum cap, GLuint index )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- _mesa_set_enablei(ctx, cap, index, GL_FALSE);
-}
-
-
-void GLAPIENTRY
-_mesa_EnableIndexed( GLenum cap, GLuint index )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- _mesa_set_enablei(ctx, cap, index, GL_TRUE);
-}
-
-
-GLboolean GLAPIENTRY
-_mesa_IsEnabledIndexed( GLenum cap, GLuint index )
-{
- GET_CURRENT_CONTEXT(ctx);
- switch (cap) {
- case GL_BLEND:
- if (index >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glIsEnabledIndexed(index=%u)",
- index);
- return GL_FALSE;
- }
- return (ctx->Color.BlendEnabled >> index) & 1;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabledIndexed(cap=%s)",
- _mesa_lookup_enum_by_nr(cap));
- return GL_FALSE;
- }
-}
-
-
-
-
-#undef CHECK_EXTENSION
-#define CHECK_EXTENSION(EXTNAME) \
- if (!ctx->Extensions.EXTNAME) { \
- goto invalid_enum_error; \
- }
-
-#undef CHECK_EXTENSION2
-#define CHECK_EXTENSION2(EXT1, EXT2) \
- if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
- goto invalid_enum_error; \
- }
-
-
-/**
- * Helper function to determine whether a texture target is enabled.
- */
-static GLboolean
-is_texture_enabled(struct gl_context *ctx, GLbitfield bit)
-{
- const struct gl_texture_unit *const texUnit =
- &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- return (texUnit->Enabled & bit) ? GL_TRUE : GL_FALSE;
-}
-
-
-/**
- * Return simple enable/disable state.
- *
- * \param cap state variable to query.
- *
- * Returns the state of the specified capability from the current GL context.
- * For the capabilities associated with extensions verifies that those
- * extensions are effectively present before reporting.
- */
-GLboolean GLAPIENTRY
-_mesa_IsEnabled( GLenum cap )
-{
- GET_CURRENT_CONTEXT(ctx);
- switch (cap) {
- case GL_ALPHA_TEST:
- return ctx->Color.AlphaEnabled;
- case GL_AUTO_NORMAL:
- return ctx->Eval.AutoNormal;
- case GL_BLEND:
- return ctx->Color.BlendEnabled & 1; /* return state for buffer[0] */
- case GL_CLIP_PLANE0:
- case GL_CLIP_PLANE1:
- case GL_CLIP_PLANE2:
- case GL_CLIP_PLANE3:
- case GL_CLIP_PLANE4:
- case GL_CLIP_PLANE5:
- return (ctx->Transform.ClipPlanesEnabled >> (cap - GL_CLIP_PLANE0)) & 1;
- case GL_COLOR_MATERIAL:
- return ctx->Light.ColorMaterialEnabled;
- case GL_CULL_FACE:
- return ctx->Polygon.CullFlag;
- case GL_DEPTH_TEST:
- return ctx->Depth.Test;
- case GL_DITHER:
- return ctx->Color.DitherFlag;
- case GL_FOG:
- return ctx->Fog.Enabled;
- case GL_LIGHTING:
- return ctx->Light.Enabled;
- case GL_LIGHT0:
- case GL_LIGHT1:
- case GL_LIGHT2:
- case GL_LIGHT3:
- case GL_LIGHT4:
- case GL_LIGHT5:
- case GL_LIGHT6:
- case GL_LIGHT7:
- return ctx->Light.Light[cap-GL_LIGHT0].Enabled;
- case GL_LINE_SMOOTH:
- return ctx->Line.SmoothFlag;
- case GL_LINE_STIPPLE:
- return ctx->Line.StippleFlag;
- case GL_INDEX_LOGIC_OP:
- return ctx->Color.IndexLogicOpEnabled;
- case GL_COLOR_LOGIC_OP:
- return ctx->Color.ColorLogicOpEnabled;
- case GL_MAP1_COLOR_4:
- return ctx->Eval.Map1Color4;
- case GL_MAP1_INDEX:
- return ctx->Eval.Map1Index;
- case GL_MAP1_NORMAL:
- return ctx->Eval.Map1Normal;
- case GL_MAP1_TEXTURE_COORD_1:
- return ctx->Eval.Map1TextureCoord1;
- case GL_MAP1_TEXTURE_COORD_2:
- return ctx->Eval.Map1TextureCoord2;
- case GL_MAP1_TEXTURE_COORD_3:
- return ctx->Eval.Map1TextureCoord3;
- case GL_MAP1_TEXTURE_COORD_4:
- return ctx->Eval.Map1TextureCoord4;
- case GL_MAP1_VERTEX_3:
- return ctx->Eval.Map1Vertex3;
- case GL_MAP1_VERTEX_4:
- return ctx->Eval.Map1Vertex4;
- case GL_MAP2_COLOR_4:
- return ctx->Eval.Map2Color4;
- case GL_MAP2_INDEX:
- return ctx->Eval.Map2Index;
- case GL_MAP2_NORMAL:
- return ctx->Eval.Map2Normal;
- case GL_MAP2_TEXTURE_COORD_1:
- return ctx->Eval.Map2TextureCoord1;
- case GL_MAP2_TEXTURE_COORD_2:
- return ctx->Eval.Map2TextureCoord2;
- case GL_MAP2_TEXTURE_COORD_3:
- return ctx->Eval.Map2TextureCoord3;
- case GL_MAP2_TEXTURE_COORD_4:
- return ctx->Eval.Map2TextureCoord4;
- case GL_MAP2_VERTEX_3:
- return ctx->Eval.Map2Vertex3;
- case GL_MAP2_VERTEX_4:
- return ctx->Eval.Map2Vertex4;
- case GL_NORMALIZE:
- return ctx->Transform.Normalize;
- case GL_POINT_SMOOTH:
- return ctx->Point.SmoothFlag;
- case GL_POLYGON_SMOOTH:
- return ctx->Polygon.SmoothFlag;
- case GL_POLYGON_STIPPLE:
- return ctx->Polygon.StippleFlag;
- case GL_POLYGON_OFFSET_POINT:
- return ctx->Polygon.OffsetPoint;
- case GL_POLYGON_OFFSET_LINE:
- return ctx->Polygon.OffsetLine;
- case GL_POLYGON_OFFSET_FILL:
- /*case GL_POLYGON_OFFSET_EXT:*/
- return ctx->Polygon.OffsetFill;
- case GL_RESCALE_NORMAL_EXT:
- return ctx->Transform.RescaleNormals;
- case GL_SCISSOR_TEST:
- return ctx->Scissor.Enabled;
- case GL_SHARED_TEXTURE_PALETTE_EXT:
- return ctx->Texture.SharedPalette;
- case GL_STENCIL_TEST:
- return ctx->Stencil.Enabled;
- case GL_TEXTURE_1D:
- return is_texture_enabled(ctx, TEXTURE_1D_BIT);
- case GL_TEXTURE_2D:
- return is_texture_enabled(ctx, TEXTURE_2D_BIT);
- case GL_TEXTURE_3D:
- return is_texture_enabled(ctx, TEXTURE_3D_BIT);
- case GL_TEXTURE_GEN_Q:
- {
- const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- return (texUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE;
- }
- }
- return GL_FALSE;
- case GL_TEXTURE_GEN_R:
- {
- const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- return (texUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE;
- }
- }
- return GL_FALSE;
- case GL_TEXTURE_GEN_S:
- {
- const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- return (texUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE;
- }
- }
- return GL_FALSE;
- case GL_TEXTURE_GEN_T:
- {
- const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- return (texUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE;
- }
- }
- return GL_FALSE;
-#if FEATURE_ES1
- case GL_TEXTURE_GEN_STR_OES:
- {
- const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
- if (texUnit) {
- return (texUnit->TexGenEnabled & STR_BITS) == STR_BITS ? GL_TRUE : GL_FALSE;
- }
- }
-#endif
-
- /*
- * CLIENT STATE!!!
- */
- case GL_VERTEX_ARRAY:
- return (ctx->Array.ArrayObj->Vertex.Enabled != 0);
- case GL_NORMAL_ARRAY:
- return (ctx->Array.ArrayObj->Normal.Enabled != 0);
- case GL_COLOR_ARRAY:
- return (ctx->Array.ArrayObj->Color.Enabled != 0);
- case GL_INDEX_ARRAY:
- return (ctx->Array.ArrayObj->Index.Enabled != 0);
- case GL_TEXTURE_COORD_ARRAY:
- return (ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled != 0);
- case GL_EDGE_FLAG_ARRAY:
- return (ctx->Array.ArrayObj->EdgeFlag.Enabled != 0);
- case GL_FOG_COORDINATE_ARRAY_EXT:
- CHECK_EXTENSION(EXT_fog_coord);
- return (ctx->Array.ArrayObj->FogCoord.Enabled != 0);
- case GL_SECONDARY_COLOR_ARRAY_EXT:
- CHECK_EXTENSION(EXT_secondary_color);
- return (ctx->Array.ArrayObj->SecondaryColor.Enabled != 0);
-#if FEATURE_point_size_array
- case GL_POINT_SIZE_ARRAY_OES:
- return (ctx->Array.ArrayObj->PointSize.Enabled != 0);
-#endif
-
- /* GL_SGI_texture_color_table */
- case GL_TEXTURE_COLOR_TABLE_SGI:
- CHECK_EXTENSION(SGI_texture_color_table);
- return ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled;
-
- /* GL_ARB_texture_cube_map */
- case GL_TEXTURE_CUBE_MAP_ARB:
- CHECK_EXTENSION(ARB_texture_cube_map);
- return is_texture_enabled(ctx, TEXTURE_CUBE_BIT);
-
- /* GL_EXT_secondary_color */
- case GL_COLOR_SUM_EXT:
- CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program);
- return ctx->Fog.ColorSumEnabled;
-
- /* GL_ARB_multisample */
- case GL_MULTISAMPLE_ARB:
- return ctx->Multisample.Enabled;
- case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
- return ctx->Multisample.SampleAlphaToCoverage;
- case GL_SAMPLE_ALPHA_TO_ONE_ARB:
- return ctx->Multisample.SampleAlphaToOne;
- case GL_SAMPLE_COVERAGE_ARB:
- return ctx->Multisample.SampleCoverage;
- case GL_SAMPLE_COVERAGE_INVERT_ARB:
- return ctx->Multisample.SampleCoverageInvert;
-
- /* GL_IBM_rasterpos_clip */
- case GL_RASTER_POSITION_UNCLIPPED_IBM:
- CHECK_EXTENSION(IBM_rasterpos_clip);
- return ctx->Transform.RasterPositionUnclipped;
-
- /* GL_NV_point_sprite */
- case GL_POINT_SPRITE_NV:
- CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite)
- return ctx->Point.PointSprite;
-
-#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
- case GL_VERTEX_PROGRAM_ARB:
- CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
- return ctx->VertexProgram.Enabled;
- case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
- CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
- return ctx->VertexProgram.PointSizeEnabled;
- case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
- CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
- return ctx->VertexProgram.TwoSideEnabled;
-#endif
-#if FEATURE_NV_vertex_program
- case GL_VERTEX_ATTRIB_ARRAY0_NV:
- case GL_VERTEX_ATTRIB_ARRAY1_NV:
- case GL_VERTEX_ATTRIB_ARRAY2_NV:
- case GL_VERTEX_ATTRIB_ARRAY3_NV:
- case GL_VERTEX_ATTRIB_ARRAY4_NV:
- case GL_VERTEX_ATTRIB_ARRAY5_NV:
- case GL_VERTEX_ATTRIB_ARRAY6_NV:
- case GL_VERTEX_ATTRIB_ARRAY7_NV:
- case GL_VERTEX_ATTRIB_ARRAY8_NV:
- case GL_VERTEX_ATTRIB_ARRAY9_NV:
- case GL_VERTEX_ATTRIB_ARRAY10_NV:
- case GL_VERTEX_ATTRIB_ARRAY11_NV:
- case GL_VERTEX_ATTRIB_ARRAY12_NV:
- case GL_VERTEX_ATTRIB_ARRAY13_NV:
- case GL_VERTEX_ATTRIB_ARRAY14_NV:
- case GL_VERTEX_ATTRIB_ARRAY15_NV:
- CHECK_EXTENSION(NV_vertex_program);
- {
- GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
- ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
- return (ctx->Array.ArrayObj->VertexAttrib[n].Enabled != 0);
- }
- case GL_MAP1_VERTEX_ATTRIB0_4_NV:
- case GL_MAP1_VERTEX_ATTRIB1_4_NV:
- case GL_MAP1_VERTEX_ATTRIB2_4_NV:
- case GL_MAP1_VERTEX_ATTRIB3_4_NV:
- case GL_MAP1_VERTEX_ATTRIB4_4_NV:
- case GL_MAP1_VERTEX_ATTRIB5_4_NV:
- case GL_MAP1_VERTEX_ATTRIB6_4_NV:
- case GL_MAP1_VERTEX_ATTRIB7_4_NV:
- case GL_MAP1_VERTEX_ATTRIB8_4_NV:
- case GL_MAP1_VERTEX_ATTRIB9_4_NV:
- case GL_MAP1_VERTEX_ATTRIB10_4_NV:
- case GL_MAP1_VERTEX_ATTRIB11_4_NV:
- case GL_MAP1_VERTEX_ATTRIB12_4_NV:
- case GL_MAP1_VERTEX_ATTRIB13_4_NV:
- case GL_MAP1_VERTEX_ATTRIB14_4_NV:
- case GL_MAP1_VERTEX_ATTRIB15_4_NV:
- CHECK_EXTENSION(NV_vertex_program);
- {
- const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
- return ctx->Eval.Map1Attrib[map];
- }
- case GL_MAP2_VERTEX_ATTRIB0_4_NV:
- case GL_MAP2_VERTEX_ATTRIB1_4_NV:
- case GL_MAP2_VERTEX_ATTRIB2_4_NV:
- case GL_MAP2_VERTEX_ATTRIB3_4_NV:
- case GL_MAP2_VERTEX_ATTRIB4_4_NV:
- case GL_MAP2_VERTEX_ATTRIB5_4_NV:
- case GL_MAP2_VERTEX_ATTRIB6_4_NV:
- case GL_MAP2_VERTEX_ATTRIB7_4_NV:
- case GL_MAP2_VERTEX_ATTRIB8_4_NV:
- case GL_MAP2_VERTEX_ATTRIB9_4_NV:
- case GL_MAP2_VERTEX_ATTRIB10_4_NV:
- case GL_MAP2_VERTEX_ATTRIB11_4_NV:
- case GL_MAP2_VERTEX_ATTRIB12_4_NV:
- case GL_MAP2_VERTEX_ATTRIB13_4_NV:
- case GL_MAP2_VERTEX_ATTRIB14_4_NV:
- case GL_MAP2_VERTEX_ATTRIB15_4_NV:
- CHECK_EXTENSION(NV_vertex_program);
- {
- const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
- return ctx->Eval.Map2Attrib[map];
- }
-#endif /* FEATURE_NV_vertex_program */
-
-#if FEATURE_NV_fragment_program
- case GL_FRAGMENT_PROGRAM_NV:
- CHECK_EXTENSION(NV_fragment_program);
- return ctx->FragmentProgram.Enabled;
-#endif /* FEATURE_NV_fragment_program */
-
- /* GL_NV_texture_rectangle */
- case GL_TEXTURE_RECTANGLE_NV:
- CHECK_EXTENSION(NV_texture_rectangle);
- return is_texture_enabled(ctx, TEXTURE_RECT_BIT);
-
- /* GL_EXT_stencil_two_side */
- case GL_STENCIL_TEST_TWO_SIDE_EXT:
- CHECK_EXTENSION(EXT_stencil_two_side);
- return ctx->Stencil.TestTwoSide;
-
-#if FEATURE_ARB_fragment_program
- case GL_FRAGMENT_PROGRAM_ARB:
- return ctx->FragmentProgram.Enabled;
-#endif /* FEATURE_ARB_fragment_program */
-
- /* GL_EXT_depth_bounds_test */
- case GL_DEPTH_BOUNDS_TEST_EXT:
- CHECK_EXTENSION(EXT_depth_bounds_test);
- return ctx->Depth.BoundsTest;
-
- /* GL_ARB_depth_clamp */
- case GL_DEPTH_CLAMP:
- CHECK_EXTENSION(ARB_depth_clamp);
- return ctx->Transform.DepthClamp;
-
-#if FEATURE_ATI_fragment_shader
- case GL_FRAGMENT_SHADER_ATI:
- CHECK_EXTENSION(ATI_fragment_shader);
- return ctx->ATIFragmentShader.Enabled;
-#endif /* FEATURE_ATI_fragment_shader */
-
- case GL_TEXTURE_CUBE_MAP_SEAMLESS:
- CHECK_EXTENSION(ARB_seamless_cube_map);
- return ctx->Texture.CubeMapSeamless;
-
-#if FEATURE_EXT_transform_feedback
- case GL_RASTERIZER_DISCARD:
- CHECK_EXTENSION(EXT_transform_feedback);
- return ctx->TransformFeedback.RasterDiscard;
-#endif
-
- /* GL_NV_primitive_restart */
- case GL_PRIMITIVE_RESTART_NV:
- if (!ctx->Extensions.NV_primitive_restart) {
- goto invalid_enum_error;
- }
- return ctx->Array.PrimitiveRestart;
-
- /* GL 3.1 primitive restart */
- case GL_PRIMITIVE_RESTART:
- if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
- goto invalid_enum_error;
- }
- return ctx->Array.PrimitiveRestart;
-
- /* GL3.0 - GL_framebuffer_sRGB */
- case GL_FRAMEBUFFER_SRGB_EXT:
- CHECK_EXTENSION(EXT_framebuffer_sRGB);
- return ctx->Color.sRGBEnabled;
-
- default:
- goto invalid_enum_error;
- }
-
- return GL_FALSE;
-
-invalid_enum_error:
- _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap);
- return GL_FALSE;
-}
+/**
+ * \file enable.c
+ * Enable/disable/query GL capabilities.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0.3
+ *
+ * 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 "enable.h"
+#include "light.h"
+#include "simple_list.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "enums.h"
+#include "api_arrayelt.h"
+#include "texstate.h"
+
+
+
+#define CHECK_EXTENSION(EXTNAME, CAP) \
+ if (!ctx->Extensions.EXTNAME) { \
+ goto invalid_enum_error; \
+ }
+
+
+/**
+ * Helper to enable/disable client-side state.
+ */
+static void
+client_state(struct gl_context *ctx, GLenum cap, GLboolean state)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint flag;
+ GLboolean *var;
+
+ switch (cap) {
+ case GL_VERTEX_ARRAY:
+ var = &arrayObj->Vertex.Enabled;
+ flag = _NEW_ARRAY_VERTEX;
+ break;
+ case GL_NORMAL_ARRAY:
+ var = &arrayObj->Normal.Enabled;
+ flag = _NEW_ARRAY_NORMAL;
+ break;
+ case GL_COLOR_ARRAY:
+ var = &arrayObj->Color.Enabled;
+ flag = _NEW_ARRAY_COLOR0;
+ break;
+ case GL_INDEX_ARRAY:
+ var = &arrayObj->Index.Enabled;
+ flag = _NEW_ARRAY_INDEX;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ var = &arrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled;
+ flag = _NEW_ARRAY_TEXCOORD(ctx->Array.ActiveTexture);
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ var = &arrayObj->EdgeFlag.Enabled;
+ flag = _NEW_ARRAY_EDGEFLAG;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ var = &arrayObj->FogCoord.Enabled;
+ flag = _NEW_ARRAY_FOGCOORD;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ var = &arrayObj->SecondaryColor.Enabled;
+ flag = _NEW_ARRAY_COLOR1;
+ break;
+
+#if FEATURE_point_size_array
+ case GL_POINT_SIZE_ARRAY_OES:
+ var = &arrayObj->PointSize.Enabled;
+ flag = _NEW_ARRAY_POINT_SIZE;
+ break;
+#endif
+
+#if FEATURE_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ var = &arrayObj->VertexAttrib[n].Enabled;
+ flag = _NEW_ARRAY_ATTRIB(n);
+ }
+ break;
+#endif /* FEATURE_NV_vertex_program */
+
+ /* GL_NV_primitive_restart */
+ case GL_PRIMITIVE_RESTART_NV:
+ if (!ctx->Extensions.NV_primitive_restart) {
+ goto invalid_enum_error;
+ }
+ var = &ctx->Array.PrimitiveRestart;
+ flag = 0;
+ break;
+
+ default:
+ goto invalid_enum_error;
+ }
+
+ if (*var == state)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ ctx->Array.NewState |= flag;
+
+ _ae_invalidate_state(ctx, _NEW_ARRAY);
+
+ *var = state;
+
+ if (state)
+ ctx->Array.ArrayObj->_Enabled |= flag;
+ else
+ ctx->Array.ArrayObj->_Enabled &= ~flag;
+
+ if (ctx->Driver.Enable) {
+ ctx->Driver.Enable( ctx, cap, state );
+ }
+
+ return;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%sClientState(0x%x)",
+ state ? "Enable" : "Disable", cap);
+}
+
+
+/**
+ * Enable GL capability.
+ * \param cap state to enable/disable.
+ *
+ * Get's the current context, assures that we're outside glBegin()/glEnd() and
+ * calls client_state().
+ */
+void GLAPIENTRY
+_mesa_EnableClientState( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ client_state( ctx, cap, GL_TRUE );
+}
+
+
+/**
+ * Disable GL capability.
+ * \param cap state to enable/disable.
+ *
+ * Get's the current context, assures that we're outside glBegin()/glEnd() and
+ * calls client_state().
+ */
+void GLAPIENTRY
+_mesa_DisableClientState( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ client_state( ctx, cap, GL_FALSE );
+}
+
+
+#undef CHECK_EXTENSION
+#define CHECK_EXTENSION(EXTNAME, CAP) \
+ if (!ctx->Extensions.EXTNAME) { \
+ goto invalid_enum_error; \
+ }
+
+#define CHECK_EXTENSION2(EXT1, EXT2, CAP) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
+ goto invalid_enum_error; \
+ }
+
+
+
+/**
+ * Return pointer to current texture unit for setting/getting coordinate
+ * state.
+ * Note that we'll set GL_INVALID_OPERATION if the active texture unit is
+ * higher than the number of supported coordinate units. And we'll return NULL.
+ */
+static struct gl_texture_unit *
+get_texcoord_unit(struct gl_context *ctx)
+{
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEnable/Disable(texcoord unit)");
+ return NULL;
+ }
+ else {
+ return &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ }
+}
+
+
+/**
+ * Helper function to enable or disable a texture target.
+ * \param bit one of the TEXTURE_x_BIT values
+ * \return GL_TRUE if state is changing or GL_FALSE if no change
+ */
+static GLboolean
+enable_texture(struct gl_context *ctx, GLboolean state, GLbitfield texBit)
+{
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ const GLbitfield newenabled = state
+ ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit);
+
+ if (texUnit->Enabled == newenabled)
+ return GL_FALSE;
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Enabled = newenabled;
+ return GL_TRUE;
+}
+
+
+/**
+ * Helper function to enable or disable state.
+ *
+ * \param ctx GL context.
+ * \param cap the state to enable/disable
+ * \param state whether to enable or disable the specified capability.
+ *
+ * Updates the current context and flushes the vertices as needed. For
+ * capabilities associated with extensions it verifies that those extensions
+ * are effectivly present before updating. Notifies the driver via
+ * dd_function_table::Enable.
+ */
+void
+_mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
+{
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "%s %s (newstate is %x)\n",
+ state ? "glEnable" : "glDisable",
+ _mesa_lookup_enum_by_nr(cap),
+ ctx->NewState);
+
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ if (ctx->Color.AlphaEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.AlphaEnabled = state;
+ break;
+ case GL_AUTO_NORMAL:
+ if (ctx->Eval.AutoNormal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.AutoNormal = state;
+ break;
+ case GL_BLEND:
+ {
+ GLbitfield newEnabled = state * ((1 << ctx->Const.MaxDrawBuffers) - 1);
+ if (newEnabled != ctx->Color.BlendEnabled) {
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.BlendEnabled = newEnabled;
+ }
+ }
+ break;
+#if FEATURE_userclip
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ {
+ const GLuint p = cap - GL_CLIP_PLANE0;
+
+ if ((ctx->Transform.ClipPlanesEnabled & (1 << p)) == ((GLuint) state << p))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+
+ if (state) {
+ ctx->Transform.ClipPlanesEnabled |= (1 << p);
+
+ if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
+ /* This derived state also calculated in clip.c and
+ * from _mesa_update_state() on changes to EyeUserPlane
+ * and ctx->ProjectionMatrix respectively.
+ */
+ _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrixStack.Top->inv );
+ }
+ else {
+ ctx->Transform.ClipPlanesEnabled &= ~(1 << p);
+ }
+ }
+ break;
+#endif
+ case GL_COLOR_MATERIAL:
+ if (ctx->Light.ColorMaterialEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ FLUSH_CURRENT(ctx, 0);
+ ctx->Light.ColorMaterialEnabled = state;
+ if (state) {
+ _mesa_update_color_material( ctx,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+ }
+ break;
+ case GL_CULL_FACE:
+ if (ctx->Polygon.CullFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.CullFlag = state;
+ break;
+ case GL_DEPTH_TEST:
+ if (ctx->Depth.Test == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.Test = state;
+ break;
+ case GL_DITHER:
+ if (ctx->Color.DitherFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.DitherFlag = state;
+ break;
+ case GL_FOG:
+ if (ctx->Fog.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Enabled = state;
+ break;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ if (ctx->Light.Light[cap-GL_LIGHT0].Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Light[cap-GL_LIGHT0].Enabled = state;
+ if (state) {
+ insert_at_tail(&ctx->Light.EnabledList,
+ &ctx->Light.Light[cap-GL_LIGHT0]);
+ }
+ else {
+ remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]);
+ }
+ break;
+ case GL_LIGHTING:
+ if (ctx->Light.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Enabled = state;
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
+ ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
+ else
+ ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
+ break;
+ case GL_LINE_SMOOTH:
+ if (ctx->Line.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_LINE_SMOOTH;
+ break;
+ case GL_LINE_STIPPLE:
+ if (ctx->Line.StippleFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.StippleFlag = state;
+ ctx->_TriangleCaps ^= DD_LINE_STIPPLE;
+ break;
+ case GL_INDEX_LOGIC_OP:
+ if (ctx->Color.IndexLogicOpEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.IndexLogicOpEnabled = state;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ if (ctx->Color.ColorLogicOpEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.ColorLogicOpEnabled = state;
+ break;
+ case GL_MAP1_COLOR_4:
+ if (ctx->Eval.Map1Color4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Color4 = state;
+ break;
+ case GL_MAP1_INDEX:
+ if (ctx->Eval.Map1Index == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Index = state;
+ break;
+ case GL_MAP1_NORMAL:
+ if (ctx->Eval.Map1Normal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Normal = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ if (ctx->Eval.Map1TextureCoord1 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord1 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ if (ctx->Eval.Map1TextureCoord2 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord2 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ if (ctx->Eval.Map1TextureCoord3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord3 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ if (ctx->Eval.Map1TextureCoord4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord4 = state;
+ break;
+ case GL_MAP1_VERTEX_3:
+ if (ctx->Eval.Map1Vertex3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Vertex3 = state;
+ break;
+ case GL_MAP1_VERTEX_4:
+ if (ctx->Eval.Map1Vertex4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Vertex4 = state;
+ break;
+ case GL_MAP2_COLOR_4:
+ if (ctx->Eval.Map2Color4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Color4 = state;
+ break;
+ case GL_MAP2_INDEX:
+ if (ctx->Eval.Map2Index == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Index = state;
+ break;
+ case GL_MAP2_NORMAL:
+ if (ctx->Eval.Map2Normal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Normal = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ if (ctx->Eval.Map2TextureCoord1 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord1 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ if (ctx->Eval.Map2TextureCoord2 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord2 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ if (ctx->Eval.Map2TextureCoord3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord3 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ if (ctx->Eval.Map2TextureCoord4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord4 = state;
+ break;
+ case GL_MAP2_VERTEX_3:
+ if (ctx->Eval.Map2Vertex3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Vertex3 = state;
+ break;
+ case GL_MAP2_VERTEX_4:
+ if (ctx->Eval.Map2Vertex4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Vertex4 = state;
+ break;
+ case GL_NORMALIZE:
+ if (ctx->Transform.Normalize == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.Normalize = state;
+ break;
+ case GL_POINT_SMOOTH:
+ if (ctx->Point.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_POINT_SMOOTH;
+ break;
+ case GL_POLYGON_SMOOTH:
+ if (ctx->Polygon.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_TRI_SMOOTH;
+ break;
+ case GL_POLYGON_STIPPLE:
+ if (ctx->Polygon.StippleFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.StippleFlag = state;
+ ctx->_TriangleCaps ^= DD_TRI_STIPPLE;
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ if (ctx->Polygon.OffsetPoint == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetPoint = state;
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ if (ctx->Polygon.OffsetLine == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetLine = state;
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ /*case GL_POLYGON_OFFSET_EXT:*/
+ if (ctx->Polygon.OffsetFill == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetFill = state;
+ break;
+ case GL_RESCALE_NORMAL_EXT:
+ if (ctx->Transform.RescaleNormals == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.RescaleNormals = state;
+ break;
+ case GL_SCISSOR_TEST:
+ if (ctx->Scissor.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_SCISSOR);
+ ctx->Scissor.Enabled = state;
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ if (ctx->Texture.SharedPalette == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ ctx->Texture.SharedPalette = state;
+ break;
+ case GL_STENCIL_TEST:
+ if (ctx->Stencil.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.Enabled = state;
+ break;
+ case GL_TEXTURE_1D:
+ if (!enable_texture(ctx, state, TEXTURE_1D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_2D:
+ if (!enable_texture(ctx, state, TEXTURE_2D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_3D:
+ if (!enable_texture(ctx, state, TEXTURE_3D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_GEN_Q:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~Q_BIT;
+ if (state)
+ newenabled |= Q_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+ case GL_TEXTURE_GEN_R:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~R_BIT;
+ if (state)
+ newenabled |= R_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+ case GL_TEXTURE_GEN_S:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~S_BIT;
+ if (state)
+ newenabled |= S_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+ case GL_TEXTURE_GEN_T:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~T_BIT;
+ if (state)
+ newenabled |= T_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+
+#if FEATURE_ES1
+ case GL_TEXTURE_GEN_STR_OES:
+ /* disable S, T, and R at the same time */
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled =
+ texUnit->TexGenEnabled & ~STR_BITS;
+ if (state)
+ newenabled |= STR_BITS;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+#endif
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ case GL_NORMAL_ARRAY:
+ case GL_COLOR_ARRAY:
+ case GL_INDEX_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY:
+ case GL_EDGE_FLAG_ARRAY:
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ case GL_POINT_SIZE_ARRAY_OES:
+ client_state( ctx, cap, state );
+ return;
+
+ /* GL_ARB_texture_cube_map */
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXTENSION(ARB_texture_cube_map, cap);
+ if (!enable_texture(ctx, state, TEXTURE_CUBE_BIT)) {
+ return;
+ }
+ break;
+
+ /* GL_EXT_secondary_color */
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program, cap);
+ if (ctx->Fog.ColorSumEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.ColorSumEnabled = state;
+ break;
+
+ /* GL_ARB_multisample */
+ case GL_MULTISAMPLE_ARB:
+ if (ctx->Multisample.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.Enabled = state;
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ if (ctx->Multisample.SampleAlphaToCoverage == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleAlphaToCoverage = state;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ if (ctx->Multisample.SampleAlphaToOne == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleAlphaToOne = state;
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ if (ctx->Multisample.SampleCoverage == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleCoverage = state;
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ if (ctx->Multisample.SampleCoverageInvert == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleCoverageInvert = state;
+ break;
+
+ /* GL_IBM_rasterpos_clip */
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXTENSION(IBM_rasterpos_clip, cap);
+ if (ctx->Transform.RasterPositionUnclipped == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.RasterPositionUnclipped = state;
+ break;
+
+ /* GL_NV_point_sprite */
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite, cap);
+ if (ctx->Point.PointSprite == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.PointSprite = state;
+ break;
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.Enabled = state;
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.PointSizeEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.PointSizeEnabled = state;
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.TwoSideEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.TwoSideEnabled = state;
+ break;
+#endif
+#if FEATURE_NV_vertex_program
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Attrib[map] = state;
+ }
+ break;
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Attrib[map] = state;
+ }
+ break;
+#endif /* FEATURE_NV_vertex_program */
+
+#if FEATURE_NV_fragment_program
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXTENSION(NV_fragment_program, cap);
+ if (ctx->FragmentProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->FragmentProgram.Enabled = state;
+ break;
+#endif /* FEATURE_NV_fragment_program */
+
+ /* GL_NV_texture_rectangle */
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXTENSION(NV_texture_rectangle, cap);
+ if (!enable_texture(ctx, state, TEXTURE_RECT_BIT)) {
+ return;
+ }
+ break;
+
+ /* GL_EXT_stencil_two_side */
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXTENSION(EXT_stencil_two_side, cap);
+ if (ctx->Stencil.TestTwoSide == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.TestTwoSide = state;
+ if (state) {
+ ctx->Stencil._BackFace = 2;
+ ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
+ } else {
+ ctx->Stencil._BackFace = 1;
+ ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL;
+ }
+ break;
+
+#if FEATURE_ARB_fragment_program
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXTENSION(ARB_fragment_program, cap);
+ if (ctx->FragmentProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->FragmentProgram.Enabled = state;
+ break;
+#endif /* FEATURE_ARB_fragment_program */
+
+ /* GL_EXT_depth_bounds_test */
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXTENSION(EXT_depth_bounds_test, cap);
+ if (ctx->Depth.BoundsTest == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.BoundsTest = state;
+ break;
+
+ case GL_DEPTH_CLAMP:
+ if (ctx->Transform.DepthClamp == state)
+ return;
+ CHECK_EXTENSION(ARB_depth_clamp, cap);
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.DepthClamp = state;
+ break;
+
+#if FEATURE_ATI_fragment_shader
+ case GL_FRAGMENT_SHADER_ATI:
+ CHECK_EXTENSION(ATI_fragment_shader, cap);
+ if (ctx->ATIFragmentShader.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->ATIFragmentShader.Enabled = state;
+ break;
+#endif
+
+ /* GL_MESA_texture_array */
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXTENSION(MESA_texture_array, cap);
+ if (!enable_texture(ctx, state, TEXTURE_1D_ARRAY_BIT)) {
+ return;
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXTENSION(MESA_texture_array, cap);
+ if (!enable_texture(ctx, state, TEXTURE_2D_ARRAY_BIT)) {
+ return;
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map, cap);
+ ctx->Texture.CubeMapSeamless = state;
+ break;
+
+#if FEATURE_EXT_transform_feedback
+ case GL_RASTERIZER_DISCARD:
+ CHECK_EXTENSION(EXT_transform_feedback, cap);
+ if (ctx->TransformFeedback.RasterDiscard != state) {
+ ctx->TransformFeedback.RasterDiscard = state;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ }
+ break;
+#endif
+
+ /* GL 3.1 primitive restart. Note: this enum is different from
+ * GL_PRIMITIVE_RESTART_NV (which is client state).
+ */
+ case GL_PRIMITIVE_RESTART:
+ if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
+ goto invalid_enum_error;
+ }
+ if (ctx->Array.PrimitiveRestart != state) {
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Array.PrimitiveRestart = state;
+ }
+ break;
+
+ /* GL3.0 - GL_framebuffer_sRGB */
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ CHECK_EXTENSION(EXT_framebuffer_sRGB, cap);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ ctx->Color.sRGBEnabled = state;
+ break;
+
+ default:
+ goto invalid_enum_error;
+ }
+
+ if (ctx->Driver.Enable) {
+ ctx->Driver.Enable( ctx, cap, state );
+ }
+
+ return;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)",
+ state ? "Enable" : "Disable", cap);
+}
+
+
+/**
+ * Enable GL capability. Called by glEnable()
+ * \param cap state to enable.
+ */
+void GLAPIENTRY
+_mesa_Enable( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_set_enable( ctx, cap, GL_TRUE );
+}
+
+
+/**
+ * Disable GL capability. Called by glDisable()
+ * \param cap state to disable.
+ */
+void GLAPIENTRY
+_mesa_Disable( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_set_enable( ctx, cap, GL_FALSE );
+}
+
+
+
+/**
+ * Enable/disable an indexed state var.
+ */
+void
+_mesa_set_enablei(struct gl_context *ctx, GLenum cap, GLuint index, GLboolean state)
+{
+ ASSERT(state == 0 || state == 1);
+ switch (cap) {
+ case GL_BLEND:
+ if (!ctx->Extensions.EXT_draw_buffers2) {
+ goto invalid_enum_error;
+ }
+ if (index >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)",
+ state ? "glEnableIndexed" : "glDisableIndexed", index);
+ return;
+ }
+ if (((ctx->Color.BlendEnabled >> index) & 1) != state) {
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ if (state)
+ ctx->Color.BlendEnabled |= (1 << index);
+ else
+ ctx->Color.BlendEnabled &= ~(1 << index);
+ }
+ break;
+ default:
+ goto invalid_enum_error;
+ }
+ return;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(cap=%s)",
+ state ? "glEnablei" : "glDisablei",
+ _mesa_lookup_enum_by_nr(cap));
+}
+
+
+void GLAPIENTRY
+_mesa_DisableIndexed( GLenum cap, GLuint index )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ _mesa_set_enablei(ctx, cap, index, GL_FALSE);
+}
+
+
+void GLAPIENTRY
+_mesa_EnableIndexed( GLenum cap, GLuint index )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ _mesa_set_enablei(ctx, cap, index, GL_TRUE);
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsEnabledIndexed( GLenum cap, GLuint index )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ switch (cap) {
+ case GL_BLEND:
+ if (index >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glIsEnabledIndexed(index=%u)",
+ index);
+ return GL_FALSE;
+ }
+ return (ctx->Color.BlendEnabled >> index) & 1;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabledIndexed(cap=%s)",
+ _mesa_lookup_enum_by_nr(cap));
+ return GL_FALSE;
+ }
+}
+
+
+
+
+#undef CHECK_EXTENSION
+#define CHECK_EXTENSION(EXTNAME) \
+ if (!ctx->Extensions.EXTNAME) { \
+ goto invalid_enum_error; \
+ }
+
+#undef CHECK_EXTENSION2
+#define CHECK_EXTENSION2(EXT1, EXT2) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
+ goto invalid_enum_error; \
+ }
+
+
+/**
+ * Helper function to determine whether a texture target is enabled.
+ */
+static GLboolean
+is_texture_enabled(struct gl_context *ctx, GLbitfield bit)
+{
+ const struct gl_texture_unit *const texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->Enabled & bit) ? GL_TRUE : GL_FALSE;
+}
+
+
+/**
+ * Return simple enable/disable state.
+ *
+ * \param cap state variable to query.
+ *
+ * Returns the state of the specified capability from the current GL context.
+ * For the capabilities associated with extensions verifies that those
+ * extensions are effectively present before reporting.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsEnabled( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ return ctx->Color.AlphaEnabled;
+ case GL_AUTO_NORMAL:
+ return ctx->Eval.AutoNormal;
+ case GL_BLEND:
+ return ctx->Color.BlendEnabled & 1; /* return state for buffer[0] */
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ return (ctx->Transform.ClipPlanesEnabled >> (cap - GL_CLIP_PLANE0)) & 1;
+ case GL_COLOR_MATERIAL:
+ return ctx->Light.ColorMaterialEnabled;
+ case GL_CULL_FACE:
+ return ctx->Polygon.CullFlag;
+ case GL_DEPTH_TEST:
+ return ctx->Depth.Test;
+ case GL_DITHER:
+ return ctx->Color.DitherFlag;
+ case GL_FOG:
+ return ctx->Fog.Enabled;
+ case GL_LIGHTING:
+ return ctx->Light.Enabled;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ return ctx->Light.Light[cap-GL_LIGHT0].Enabled;
+ case GL_LINE_SMOOTH:
+ return ctx->Line.SmoothFlag;
+ case GL_LINE_STIPPLE:
+ return ctx->Line.StippleFlag;
+ case GL_INDEX_LOGIC_OP:
+ return ctx->Color.IndexLogicOpEnabled;
+ case GL_COLOR_LOGIC_OP:
+ return ctx->Color.ColorLogicOpEnabled;
+ case GL_MAP1_COLOR_4:
+ return ctx->Eval.Map1Color4;
+ case GL_MAP1_INDEX:
+ return ctx->Eval.Map1Index;
+ case GL_MAP1_NORMAL:
+ return ctx->Eval.Map1Normal;
+ case GL_MAP1_TEXTURE_COORD_1:
+ return ctx->Eval.Map1TextureCoord1;
+ case GL_MAP1_TEXTURE_COORD_2:
+ return ctx->Eval.Map1TextureCoord2;
+ case GL_MAP1_TEXTURE_COORD_3:
+ return ctx->Eval.Map1TextureCoord3;
+ case GL_MAP1_TEXTURE_COORD_4:
+ return ctx->Eval.Map1TextureCoord4;
+ case GL_MAP1_VERTEX_3:
+ return ctx->Eval.Map1Vertex3;
+ case GL_MAP1_VERTEX_4:
+ return ctx->Eval.Map1Vertex4;
+ case GL_MAP2_COLOR_4:
+ return ctx->Eval.Map2Color4;
+ case GL_MAP2_INDEX:
+ return ctx->Eval.Map2Index;
+ case GL_MAP2_NORMAL:
+ return ctx->Eval.Map2Normal;
+ case GL_MAP2_TEXTURE_COORD_1:
+ return ctx->Eval.Map2TextureCoord1;
+ case GL_MAP2_TEXTURE_COORD_2:
+ return ctx->Eval.Map2TextureCoord2;
+ case GL_MAP2_TEXTURE_COORD_3:
+ return ctx->Eval.Map2TextureCoord3;
+ case GL_MAP2_TEXTURE_COORD_4:
+ return ctx->Eval.Map2TextureCoord4;
+ case GL_MAP2_VERTEX_3:
+ return ctx->Eval.Map2Vertex3;
+ case GL_MAP2_VERTEX_4:
+ return ctx->Eval.Map2Vertex4;
+ case GL_NORMALIZE:
+ return ctx->Transform.Normalize;
+ case GL_POINT_SMOOTH:
+ return ctx->Point.SmoothFlag;
+ case GL_POLYGON_SMOOTH:
+ return ctx->Polygon.SmoothFlag;
+ case GL_POLYGON_STIPPLE:
+ return ctx->Polygon.StippleFlag;
+ case GL_POLYGON_OFFSET_POINT:
+ return ctx->Polygon.OffsetPoint;
+ case GL_POLYGON_OFFSET_LINE:
+ return ctx->Polygon.OffsetLine;
+ case GL_POLYGON_OFFSET_FILL:
+ /*case GL_POLYGON_OFFSET_EXT:*/
+ return ctx->Polygon.OffsetFill;
+ case GL_RESCALE_NORMAL_EXT:
+ return ctx->Transform.RescaleNormals;
+ case GL_SCISSOR_TEST:
+ return ctx->Scissor.Enabled;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ return ctx->Texture.SharedPalette;
+ case GL_STENCIL_TEST:
+ return ctx->Stencil.Enabled;
+ case GL_TEXTURE_1D:
+ return is_texture_enabled(ctx, TEXTURE_1D_BIT);
+ case GL_TEXTURE_2D:
+ return is_texture_enabled(ctx, TEXTURE_2D_BIT);
+ case GL_TEXTURE_3D:
+ return is_texture_enabled(ctx, TEXTURE_3D_BIT);
+ case GL_TEXTURE_GEN_Q:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+ case GL_TEXTURE_GEN_R:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+ case GL_TEXTURE_GEN_S:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+ case GL_TEXTURE_GEN_T:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+#if FEATURE_ES1
+ case GL_TEXTURE_GEN_STR_OES:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & STR_BITS) == STR_BITS ? GL_TRUE : GL_FALSE;
+ }
+ }
+#endif
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ return (ctx->Array.ArrayObj->Vertex.Enabled != 0);
+ case GL_NORMAL_ARRAY:
+ return (ctx->Array.ArrayObj->Normal.Enabled != 0);
+ case GL_COLOR_ARRAY:
+ return (ctx->Array.ArrayObj->Color.Enabled != 0);
+ case GL_INDEX_ARRAY:
+ return (ctx->Array.ArrayObj->Index.Enabled != 0);
+ case GL_TEXTURE_COORD_ARRAY:
+ return (ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled != 0);
+ case GL_EDGE_FLAG_ARRAY:
+ return (ctx->Array.ArrayObj->EdgeFlag.Enabled != 0);
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXTENSION(EXT_fog_coord);
+ return (ctx->Array.ArrayObj->FogCoord.Enabled != 0);
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXTENSION(EXT_secondary_color);
+ return (ctx->Array.ArrayObj->SecondaryColor.Enabled != 0);
+#if FEATURE_point_size_array
+ case GL_POINT_SIZE_ARRAY_OES:
+ return (ctx->Array.ArrayObj->PointSize.Enabled != 0);
+#endif
+
+ /* GL_ARB_texture_cube_map */
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXTENSION(ARB_texture_cube_map);
+ return is_texture_enabled(ctx, TEXTURE_CUBE_BIT);
+
+ /* GL_EXT_secondary_color */
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program);
+ return ctx->Fog.ColorSumEnabled;
+
+ /* GL_ARB_multisample */
+ case GL_MULTISAMPLE_ARB:
+ return ctx->Multisample.Enabled;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ return ctx->Multisample.SampleAlphaToCoverage;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ return ctx->Multisample.SampleAlphaToOne;
+ case GL_SAMPLE_COVERAGE_ARB:
+ return ctx->Multisample.SampleCoverage;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ return ctx->Multisample.SampleCoverageInvert;
+
+ /* GL_IBM_rasterpos_clip */
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXTENSION(IBM_rasterpos_clip);
+ return ctx->Transform.RasterPositionUnclipped;
+
+ /* GL_NV_point_sprite */
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite)
+ return ctx->Point.PointSprite;
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.Enabled;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.PointSizeEnabled;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.TwoSideEnabled;
+#endif
+#if FEATURE_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ return (ctx->Array.ArrayObj->VertexAttrib[n].Enabled != 0);
+ }
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
+ return ctx->Eval.Map1Attrib[map];
+ }
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
+ return ctx->Eval.Map2Attrib[map];
+ }
+#endif /* FEATURE_NV_vertex_program */
+
+#if FEATURE_NV_fragment_program
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXTENSION(NV_fragment_program);
+ return ctx->FragmentProgram.Enabled;
+#endif /* FEATURE_NV_fragment_program */
+
+ /* GL_NV_texture_rectangle */
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXTENSION(NV_texture_rectangle);
+ return is_texture_enabled(ctx, TEXTURE_RECT_BIT);
+
+ /* GL_EXT_stencil_two_side */
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXTENSION(EXT_stencil_two_side);
+ return ctx->Stencil.TestTwoSide;
+
+#if FEATURE_ARB_fragment_program
+ case GL_FRAGMENT_PROGRAM_ARB:
+ return ctx->FragmentProgram.Enabled;
+#endif /* FEATURE_ARB_fragment_program */
+
+ /* GL_EXT_depth_bounds_test */
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXTENSION(EXT_depth_bounds_test);
+ return ctx->Depth.BoundsTest;
+
+ /* GL_ARB_depth_clamp */
+ case GL_DEPTH_CLAMP:
+ CHECK_EXTENSION(ARB_depth_clamp);
+ return ctx->Transform.DepthClamp;
+
+#if FEATURE_ATI_fragment_shader
+ case GL_FRAGMENT_SHADER_ATI:
+ CHECK_EXTENSION(ATI_fragment_shader);
+ return ctx->ATIFragmentShader.Enabled;
+#endif /* FEATURE_ATI_fragment_shader */
+
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map);
+ return ctx->Texture.CubeMapSeamless;
+
+#if FEATURE_EXT_transform_feedback
+ case GL_RASTERIZER_DISCARD:
+ CHECK_EXTENSION(EXT_transform_feedback);
+ return ctx->TransformFeedback.RasterDiscard;
+#endif
+
+ /* GL_NV_primitive_restart */
+ case GL_PRIMITIVE_RESTART_NV:
+ if (!ctx->Extensions.NV_primitive_restart) {
+ goto invalid_enum_error;
+ }
+ return ctx->Array.PrimitiveRestart;
+
+ /* GL 3.1 primitive restart */
+ case GL_PRIMITIVE_RESTART:
+ if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
+ goto invalid_enum_error;
+ }
+ return ctx->Array.PrimitiveRestart;
+
+ /* GL3.0 - GL_framebuffer_sRGB */
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ CHECK_EXTENSION(EXT_framebuffer_sRGB);
+ return ctx->Color.sRGBEnabled;
+
+ default:
+ goto invalid_enum_error;
+ }
+
+ return GL_FALSE;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap);
+ return GL_FALSE;
+}
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 310740b0d..3840cdc5d 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -241,8 +241,7 @@ static const struct extension extension_table[] = {
{ "GL_OES_stencil4", o(dummy_false), DISABLE },
{ "GL_OES_stencil8", o(EXT_framebuffer_object), ES1 | ES2 },
{ "GL_OES_stencil_wrap", o(EXT_stencil_wrap), ES1 },
- /* GL_OES_texture_3D is disabled due to missing GLSL support. */
- { "GL_OES_texture_3D", o(EXT_texture3D), DISABLE },
+ { "GL_OES_texture_3D", o(EXT_texture3D), ES2 },
{ "GL_OES_texture_cube_map", o(ARB_texture_cube_map), ES1 },
{ "GL_OES_texture_env_crossbar", o(ARB_texture_env_crossbar), ES1 },
{ "GL_OES_texture_mirrored_repeat", o(ARB_texture_mirrored_repeat), ES1 },
@@ -291,7 +290,6 @@ static const struct extension extension_table[] = {
{ "GL_SGIS_texture_border_clamp", o(ARB_texture_border_clamp), GL },
{ "GL_SGIS_texture_edge_clamp", o(SGIS_texture_edge_clamp), GL },
{ "GL_SGIS_texture_lod", o(SGIS_texture_lod), GL },
- { "GL_SGI_texture_color_table", o(SGI_texture_color_table), GL },
{ "GL_SUN_multi_draw_arrays", o(EXT_multi_draw_arrays), GL },
{ 0, 0, 0 },
@@ -521,7 +519,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx)
#if FEATURE_NV_fragment_program && FEATURE_ARB_fragment_program
ctx->Extensions.NV_fragment_program_option = GL_TRUE;
#endif
- ctx->Extensions.SGI_texture_color_table = GL_TRUE;
/*ctx->Extensions.SGIS_generate_mipmap = GL_TRUE;*/
ctx->Extensions.SGIS_texture_edge_clamp = GL_TRUE;
#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index b2ff4dc29..c242e568d 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -1,2494 +1,2438 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 1999-2009 VMware, Inc. 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.
- */
-
-
-/*
- * GL_EXT/ARB_framebuffer_object extensions
- *
- * Authors:
- * Brian Paul
- */
-
-
-#include "buffers.h"
-#include "context.h"
-#include "enums.h"
-#include "fbobject.h"
-#include "formats.h"
-#include "framebuffer.h"
-#include "hash.h"
-#include "macros.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "renderbuffer.h"
-#include "state.h"
-#include "teximage.h"
-#include "texobj.h"
-
-
-/** Set this to 1 to help debug FBO incompleteness problems */
-#define DEBUG_FBO 0
-
-/** Set this to 1 to debug/log glBlitFramebuffer() calls */
-#define DEBUG_BLIT 0
-
-
-/**
- * Notes:
- *
- * None of the GL_EXT_framebuffer_object functions are compiled into
- * display lists.
- */
-
-
-
-/*
- * When glGenRender/FramebuffersEXT() is called we insert pointers to
- * these placeholder objects into the hash table.
- * Later, when the object ID is first bound, we replace the placeholder
- * with the real frame/renderbuffer.
- */
-static struct gl_framebuffer DummyFramebuffer;
-static struct gl_renderbuffer DummyRenderbuffer;
-
-/* We bind this framebuffer when applications pass a NULL
- * drawable/surface in make current. */
-static struct gl_framebuffer IncompleteFramebuffer;
-
-
-#define IS_CUBE_FACE(TARGET) \
- ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
- (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
-
-
-static void
-delete_dummy_renderbuffer(struct gl_renderbuffer *rb)
-{
- /* no op */
-}
-
-static void
-delete_dummy_framebuffer(struct gl_framebuffer *fb)
-{
- /* no op */
-}
-
-
-void
-_mesa_init_fbobjects(struct gl_context *ctx)
-{
- _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
- _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
- _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex);
- DummyFramebuffer.Delete = delete_dummy_framebuffer;
- DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
- IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
-}
-
-struct gl_framebuffer *
-_mesa_get_incomplete_framebuffer(void)
-{
- return &IncompleteFramebuffer;
-}
-
-/**
- * Helper routine for getting a gl_renderbuffer.
- */
-struct gl_renderbuffer *
-_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
-{
- struct gl_renderbuffer *rb;
-
- if (id == 0)
- return NULL;
-
- rb = (struct gl_renderbuffer *)
- _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
- return rb;
-}
-
-
-/**
- * Helper routine for getting a gl_framebuffer.
- */
-struct gl_framebuffer *
-_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
-{
- struct gl_framebuffer *fb;
-
- if (id == 0)
- return NULL;
-
- fb = (struct gl_framebuffer *)
- _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
- return fb;
-}
-
-
-/**
- * Mark the given framebuffer as invalid. This will force the
- * test for framebuffer completeness to be done before the framebuffer
- * is used.
- */
-static void
-invalidate_framebuffer(struct gl_framebuffer *fb)
-{
- fb->_Status = 0; /* "indeterminate" */
-}
-
-
-/**
- * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
- * gl_renderbuffer_attachment object.
- * This function is only used for user-created FB objects, not the
- * default / window-system FB object.
- * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
- * the depth buffer attachment point.
- */
-struct gl_renderbuffer_attachment *
-_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
- GLenum attachment)
-{
- GLuint i;
-
- assert(fb->Name > 0);
-
- switch (attachment) {
- case GL_COLOR_ATTACHMENT0_EXT:
- case GL_COLOR_ATTACHMENT1_EXT:
- case GL_COLOR_ATTACHMENT2_EXT:
- case GL_COLOR_ATTACHMENT3_EXT:
- case GL_COLOR_ATTACHMENT4_EXT:
- case GL_COLOR_ATTACHMENT5_EXT:
- case GL_COLOR_ATTACHMENT6_EXT:
- case GL_COLOR_ATTACHMENT7_EXT:
- case GL_COLOR_ATTACHMENT8_EXT:
- case GL_COLOR_ATTACHMENT9_EXT:
- case GL_COLOR_ATTACHMENT10_EXT:
- case GL_COLOR_ATTACHMENT11_EXT:
- case GL_COLOR_ATTACHMENT12_EXT:
- case GL_COLOR_ATTACHMENT13_EXT:
- case GL_COLOR_ATTACHMENT14_EXT:
- case GL_COLOR_ATTACHMENT15_EXT:
- i = attachment - GL_COLOR_ATTACHMENT0_EXT;
- if (i >= ctx->Const.MaxColorAttachments) {
- return NULL;
- }
- return &fb->Attachment[BUFFER_COLOR0 + i];
- case GL_DEPTH_STENCIL_ATTACHMENT:
- /* fall-through */
- case GL_DEPTH_BUFFER:
- /* fall-through / new in GL 3.0 */
- case GL_DEPTH_ATTACHMENT_EXT:
- return &fb->Attachment[BUFFER_DEPTH];
- case GL_STENCIL_BUFFER:
- /* fall-through / new in GL 3.0 */
- case GL_STENCIL_ATTACHMENT_EXT:
- return &fb->Attachment[BUFFER_STENCIL];
- default:
- return NULL;
- }
-}
-
-
-/**
- * As above, but only used for getting attachments of the default /
- * window-system framebuffer (not user-created framebuffer objects).
- */
-static struct gl_renderbuffer_attachment *
-_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
- GLenum attachment)
-{
- assert(fb->Name == 0);
-
- switch (attachment) {
- case GL_FRONT_LEFT:
- return &fb->Attachment[BUFFER_FRONT_LEFT];
- case GL_FRONT_RIGHT:
- return &fb->Attachment[BUFFER_FRONT_RIGHT];
- case GL_BACK_LEFT:
- return &fb->Attachment[BUFFER_BACK_LEFT];
- case GL_BACK_RIGHT:
- return &fb->Attachment[BUFFER_BACK_RIGHT];
- case GL_AUX0:
- if (fb->Visual.numAuxBuffers == 1) {
- return &fb->Attachment[BUFFER_AUX0];
- }
- return NULL;
- case GL_DEPTH_BUFFER:
- /* fall-through / new in GL 3.0 */
- case GL_DEPTH_ATTACHMENT_EXT:
- return &fb->Attachment[BUFFER_DEPTH];
- case GL_STENCIL_BUFFER:
- /* fall-through / new in GL 3.0 */
- case GL_STENCIL_ATTACHMENT_EXT:
- return &fb->Attachment[BUFFER_STENCIL];
- default:
- return NULL;
- }
-}
-
-
-
-/**
- * Remove any texture or renderbuffer attached to the given attachment
- * point. Update reference counts, etc.
- */
-void
-_mesa_remove_attachment(struct gl_context *ctx,
- struct gl_renderbuffer_attachment *att)
-{
- if (att->Type == GL_TEXTURE) {
- ASSERT(att->Texture);
- if (ctx->Driver.FinishRenderTexture) {
- /* tell driver that we're done rendering to this texture. */
- ctx->Driver.FinishRenderTexture(ctx, att);
- }
- _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
- ASSERT(!att->Texture);
- }
- if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
- ASSERT(!att->Texture);
- _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
- ASSERT(!att->Renderbuffer);
- }
- att->Type = GL_NONE;
- att->Complete = GL_TRUE;
-}
-
-
-/**
- * Bind a texture object to an attachment point.
- * The previous binding, if any, will be removed first.
- */
-void
-_mesa_set_texture_attachment(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- struct gl_renderbuffer_attachment *att,
- struct gl_texture_object *texObj,
- GLenum texTarget, GLuint level, GLuint zoffset)
-{
- if (att->Texture == texObj) {
- /* re-attaching same texture */
- ASSERT(att->Type == GL_TEXTURE);
- if (ctx->Driver.FinishRenderTexture)
- ctx->Driver.FinishRenderTexture(ctx, att);
- }
- else {
- /* new attachment */
- if (ctx->Driver.FinishRenderTexture && att->Texture)
- ctx->Driver.FinishRenderTexture(ctx, att);
- _mesa_remove_attachment(ctx, att);
- att->Type = GL_TEXTURE;
- assert(!att->Texture);
- _mesa_reference_texobj(&att->Texture, texObj);
- }
-
- /* always update these fields */
- att->TextureLevel = level;
- att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
- att->Zoffset = zoffset;
- att->Complete = GL_FALSE;
-
- if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
- ctx->Driver.RenderTexture(ctx, fb, att);
- }
-
- invalidate_framebuffer(fb);
-}
-
-
-/**
- * Bind a renderbuffer to an attachment point.
- * The previous binding, if any, will be removed first.
- */
-void
-_mesa_set_renderbuffer_attachment(struct gl_context *ctx,
- struct gl_renderbuffer_attachment *att,
- struct gl_renderbuffer *rb)
-{
- /* XXX check if re-doing same attachment, exit early */
- _mesa_remove_attachment(ctx, att);
- att->Type = GL_RENDERBUFFER_EXT;
- att->Texture = NULL; /* just to be safe */
- att->Complete = GL_FALSE;
- _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
-}
-
-
-/**
- * Fallback for ctx->Driver.FramebufferRenderbuffer()
- * Attach a renderbuffer object to a framebuffer object.
- */
-void
-_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- GLenum attachment, struct gl_renderbuffer *rb)
-{
- struct gl_renderbuffer_attachment *att;
-
- _glthread_LOCK_MUTEX(fb->Mutex);
-
- att = _mesa_get_attachment(ctx, fb, attachment);
- ASSERT(att);
- if (rb) {
- _mesa_set_renderbuffer_attachment(ctx, att, rb);
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
- /* do stencil attachment here (depth already done above) */
- att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
- assert(att);
- _mesa_set_renderbuffer_attachment(ctx, att, rb);
- }
- }
- else {
- _mesa_remove_attachment(ctx, att);
- }
-
- invalidate_framebuffer(fb);
-
- _glthread_UNLOCK_MUTEX(fb->Mutex);
-}
-
-
-/**
- * Fallback for ctx->Driver.ValidateFramebuffer()
- * Check if the renderbuffer's formats are supported by the software
- * renderer.
- * Drivers should probably override this.
- */
-void
-_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
-{
- gl_buffer_index buf;
- for (buf = 0; buf < BUFFER_COUNT; buf++) {
- const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
- if (rb) {
- switch (rb->_BaseFormat) {
- case GL_ALPHA:
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE:
- case GL_INTENSITY:
- case GL_RED:
- case GL_RG:
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
- return;
- default:
- /* render buffer format is supported by software rendering */
- ;
- }
- }
- }
-}
-
-
-/**
- * For debug only.
- */
-static void
-att_incomplete(const char *msg)
-{
-#if DEBUG_FBO
- _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
-#else
- (void) msg;
-#endif
-}
-
-
-/**
- * For debug only.
- */
-static void
-fbo_incomplete(const char *msg, int index)
-{
-#if DEBUG_FBO
- _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
-#else
- (void) msg;
- (void) index;
-#endif
-}
-
-
-/**
- * Is the given base format a legal format for a color renderbuffer?
- */
-GLboolean
-_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
-{
- switch (baseFormat) {
- case GL_RGB:
- case GL_RGBA:
- return GL_TRUE;
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_INTENSITY:
- case GL_ALPHA:
- return ctx->Extensions.ARB_framebuffer_object;
- case GL_RED:
- case GL_RG:
- return ctx->Extensions.ARB_texture_rg;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Is the given base format a legal format for a depth/stencil renderbuffer?
- */
-static GLboolean
-is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
-{
- switch (baseFormat) {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if an attachment point is complete and update its Complete field.
- * \param format if GL_COLOR, this is a color attachment point,
- * if GL_DEPTH, this is a depth component attachment point,
- * if GL_STENCIL, this is a stencil component attachment point.
- */
-static void
-test_attachment_completeness(const struct gl_context *ctx, GLenum format,
- struct gl_renderbuffer_attachment *att)
-{
- assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
-
- /* assume complete */
- att->Complete = GL_TRUE;
-
- /* Look for reasons why the attachment might be incomplete */
- if (att->Type == GL_TEXTURE) {
- const struct gl_texture_object *texObj = att->Texture;
- struct gl_texture_image *texImage;
- GLenum baseFormat;
-
- if (!texObj) {
- att_incomplete("no texobj");
- att->Complete = GL_FALSE;
- return;
- }
-
- texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
- if (!texImage) {
- att_incomplete("no teximage");
- att->Complete = GL_FALSE;
- return;
- }
- if (texImage->Width < 1 || texImage->Height < 1) {
- att_incomplete("teximage width/height=0");
- printf("texobj = %u\n", texObj->Name);
- printf("level = %d\n", att->TextureLevel);
- att->Complete = GL_FALSE;
- return;
- }
- if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
- att_incomplete("bad z offset");
- att->Complete = GL_FALSE;
- return;
- }
-
- baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
-
- if (format == GL_COLOR) {
- if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
- att_incomplete("bad format");
- att->Complete = GL_FALSE;
- return;
- }
- if (_mesa_is_format_compressed(texImage->TexFormat)) {
- att_incomplete("compressed internalformat");
- att->Complete = GL_FALSE;
- return;
- }
- }
- else if (format == GL_DEPTH) {
- if (baseFormat == GL_DEPTH_COMPONENT) {
- /* OK */
- }
- else if (ctx->Extensions.EXT_packed_depth_stencil &&
- ctx->Extensions.ARB_depth_texture &&
- baseFormat == GL_DEPTH_STENCIL_EXT) {
- /* OK */
- }
- else {
- att->Complete = GL_FALSE;
- att_incomplete("bad depth format");
- return;
- }
- }
- else {
- ASSERT(format == GL_STENCIL);
- if (ctx->Extensions.EXT_packed_depth_stencil &&
- ctx->Extensions.ARB_depth_texture &&
- baseFormat == GL_DEPTH_STENCIL_EXT) {
- /* OK */
- }
- else {
- /* no such thing as stencil-only textures */
- att_incomplete("illegal stencil texture");
- att->Complete = GL_FALSE;
- return;
- }
- }
- }
- else if (att->Type == GL_RENDERBUFFER_EXT) {
- const GLenum baseFormat =
- _mesa_get_format_base_format(att->Renderbuffer->Format);
-
- ASSERT(att->Renderbuffer);
- if (!att->Renderbuffer->InternalFormat ||
- att->Renderbuffer->Width < 1 ||
- att->Renderbuffer->Height < 1) {
- att_incomplete("0x0 renderbuffer");
- att->Complete = GL_FALSE;
- return;
- }
- if (format == GL_COLOR) {
- if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
- att_incomplete("bad renderbuffer color format");
- att->Complete = GL_FALSE;
- return;
- }
- }
- else if (format == GL_DEPTH) {
- if (baseFormat == GL_DEPTH_COMPONENT) {
- /* OK */
- }
- else if (ctx->Extensions.EXT_packed_depth_stencil &&
- baseFormat == GL_DEPTH_STENCIL_EXT) {
- /* OK */
- }
- else {
- att_incomplete("bad renderbuffer depth format");
- att->Complete = GL_FALSE;
- return;
- }
- }
- else {
- assert(format == GL_STENCIL);
- if (baseFormat == GL_STENCIL_INDEX) {
- /* OK */
- }
- else if (ctx->Extensions.EXT_packed_depth_stencil &&
- baseFormat == GL_DEPTH_STENCIL_EXT) {
- /* OK */
- }
- else {
- att->Complete = GL_FALSE;
- att_incomplete("bad renderbuffer stencil format");
- return;
- }
- }
- }
- else {
- ASSERT(att->Type == GL_NONE);
- /* complete */
- return;
- }
-}
-
-
-/**
- * Test if the given framebuffer object is complete and update its
- * Status field with the results.
- * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
- * driver to make hardware-specific validation/completeness checks.
- * Also update the framebuffer's Width and Height fields if the
- * framebuffer is complete.
- */
-void
-_mesa_test_framebuffer_completeness(struct gl_context *ctx,
- struct gl_framebuffer *fb)
-{
- GLuint numImages;
- GLenum intFormat = GL_NONE; /* color buffers' internal format */
- GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
- GLint numSamples = -1;
- GLint i;
- GLuint j;
-
- assert(fb->Name != 0);
-
- numImages = 0;
- fb->Width = 0;
- fb->Height = 0;
-
- /* Start at -2 to more easily loop over all attachment points.
- * -2: depth buffer
- * -1: stencil buffer
- * >=0: color buffer
- */
- for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
- struct gl_renderbuffer_attachment *att;
- GLenum f;
- gl_format mesaFormat;
-
- /*
- * XXX for ARB_fbo, only check color buffers that are named by
- * GL_READ_BUFFER and GL_DRAW_BUFFERi.
- */
-
- /* check for attachment completeness
- */
- if (i == -2) {
- att = &fb->Attachment[BUFFER_DEPTH];
- test_attachment_completeness(ctx, GL_DEPTH, att);
- if (!att->Complete) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
- fbo_incomplete("depth attachment incomplete", -1);
- return;
- }
- }
- else if (i == -1) {
- att = &fb->Attachment[BUFFER_STENCIL];
- test_attachment_completeness(ctx, GL_STENCIL, att);
- if (!att->Complete) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
- fbo_incomplete("stencil attachment incomplete", -1);
- return;
- }
- }
- else {
- att = &fb->Attachment[BUFFER_COLOR0 + i];
- test_attachment_completeness(ctx, GL_COLOR, att);
- if (!att->Complete) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
- fbo_incomplete("color attachment incomplete", i);
- return;
- }
- }
-
- /* get width, height, format of the renderbuffer/texture
- */
- if (att->Type == GL_TEXTURE) {
- const struct gl_texture_image *texImg
- = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
- minWidth = MIN2(minWidth, texImg->Width);
- maxWidth = MAX2(maxWidth, texImg->Width);
- minHeight = MIN2(minHeight, texImg->Height);
- maxHeight = MAX2(maxHeight, texImg->Height);
- f = texImg->_BaseFormat;
- mesaFormat = texImg->TexFormat;
- numImages++;
- if (!_mesa_is_legal_color_format(ctx, f) &&
- !is_legal_depth_format(ctx, f)) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
- fbo_incomplete("texture attachment incomplete", -1);
- return;
- }
- }
- else if (att->Type == GL_RENDERBUFFER_EXT) {
- minWidth = MIN2(minWidth, att->Renderbuffer->Width);
- maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
- minHeight = MIN2(minHeight, att->Renderbuffer->Height);
- maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
- f = att->Renderbuffer->InternalFormat;
- mesaFormat = att->Renderbuffer->Format;
- numImages++;
- }
- else {
- assert(att->Type == GL_NONE);
- continue;
- }
-
- if (numSamples < 0) {
- /* first buffer */
- numSamples = att->Renderbuffer->NumSamples;
- }
-
- /* check if integer color */
- fb->_IntegerColor = _mesa_is_format_integer_color(mesaFormat);
-
- /* Error-check width, height, format, samples
- */
- if (numImages == 1) {
- /* save format, num samples */
- if (i >= 0) {
- intFormat = f;
- }
- }
- else {
- if (!ctx->Extensions.ARB_framebuffer_object) {
- /* check that width, height, format are same */
- if (minWidth != maxWidth || minHeight != maxHeight) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
- fbo_incomplete("width or height mismatch", -1);
- return;
- }
- /* check that all color buffer have same format */
- if (intFormat != GL_NONE && f != intFormat) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
- fbo_incomplete("format mismatch", -1);
- return;
- }
- }
- if (att->Renderbuffer &&
- att->Renderbuffer->NumSamples != numSamples) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
- fbo_incomplete("inconsistant number of samples", i);
- return;
- }
-
- }
- }
-
-#if FEATURE_GL
- if (ctx->API == API_OPENGL) {
- /* Check that all DrawBuffers are present */
- for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
- if (fb->ColorDrawBuffer[j] != GL_NONE) {
- const struct gl_renderbuffer_attachment *att
- = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
- assert(att);
- if (att->Type == GL_NONE) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
- fbo_incomplete("missing drawbuffer", j);
- return;
- }
- }
- }
-
- /* Check that the ReadBuffer is present */
- if (fb->ColorReadBuffer != GL_NONE) {
- const struct gl_renderbuffer_attachment *att
- = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
- assert(att);
- if (att->Type == GL_NONE) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
- fbo_incomplete("missing readbuffer", -1);
- return;
- }
- }
- }
-#else
- (void) j;
-#endif
-
- if (numImages == 0) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
- fbo_incomplete("no attachments", -1);
- return;
- }
-
- /* Provisionally set status = COMPLETE ... */
- fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
-
- /* ... but the driver may say the FB is incomplete.
- * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
- * if anything.
- */
- if (ctx->Driver.ValidateFramebuffer) {
- ctx->Driver.ValidateFramebuffer(ctx, fb);
- if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- fbo_incomplete("driver marked FBO as incomplete", -1);
- }
- }
-
- if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
- /*
- * Note that if ARB_framebuffer_object is supported and the attached
- * renderbuffers/textures are different sizes, the framebuffer
- * width/height will be set to the smallest width/height.
- */
- fb->Width = minWidth;
- fb->Height = minHeight;
-
- /* finally, update the visual info for the framebuffer */
- _mesa_update_framebuffer_visual(ctx, fb);
- }
-}
-
-
-GLboolean GLAPIENTRY
-_mesa_IsRenderbufferEXT(GLuint renderbuffer)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
- if (renderbuffer) {
- struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
- if (rb != NULL && rb != &DummyRenderbuffer)
- return GL_TRUE;
- }
- return GL_FALSE;
-}
-
-
-void GLAPIENTRY
-_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
-{
- struct gl_renderbuffer *newRb;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
- return;
- }
-
- /* No need to flush here since the render buffer binding has no
- * effect on rendering state.
- */
-
- if (renderbuffer) {
- newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
- if (newRb == &DummyRenderbuffer) {
- /* ID was reserved, but no real renderbuffer object made yet */
- newRb = NULL;
- }
- else if (!newRb && ctx->Extensions.ARB_framebuffer_object) {
- /* All RB IDs must be Gen'd */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
- return;
- }
-
- if (!newRb) {
- /* create new renderbuffer object */
- newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
- if (!newRb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
- return;
- }
- ASSERT(newRb->AllocStorage);
- _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
- newRb->RefCount = 1; /* referenced by hash table */
- }
- }
- else {
- newRb = NULL;
- }
-
- ASSERT(newRb != &DummyRenderbuffer);
-
- _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
-}
-
-
-/**
- * If the given renderbuffer is anywhere attached to the framebuffer, detach
- * the renderbuffer.
- * This is used when a renderbuffer object is deleted.
- * The spec calls for unbinding.
- */
-static void
-detach_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- struct gl_renderbuffer *rb)
-{
- GLuint i;
- for (i = 0; i < BUFFER_COUNT; i++) {
- if (fb->Attachment[i].Renderbuffer == rb) {
- _mesa_remove_attachment(ctx, &fb->Attachment[i]);
- }
- }
- invalidate_framebuffer(fb);
-}
-
-
-void GLAPIENTRY
-_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
-{
- GLint i;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- for (i = 0; i < n; i++) {
- if (renderbuffers[i] > 0) {
- struct gl_renderbuffer *rb;
- rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
- if (rb) {
- /* check if deleting currently bound renderbuffer object */
- if (rb == ctx->CurrentRenderbuffer) {
- /* bind default */
- ASSERT(rb->RefCount >= 2);
- _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
- }
-
- if (ctx->DrawBuffer->Name) {
- detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
- }
- if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) {
- detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
- }
-
- /* Remove from hash table immediately, to free the ID.
- * But the object will not be freed until it's no longer
- * referenced anywhere else.
- */
- _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
-
- if (rb != &DummyRenderbuffer) {
- /* no longer referenced by hash table */
- _mesa_reference_renderbuffer(&rb, NULL);
- }
- }
- }
- }
-}
-
-
-void GLAPIENTRY
-_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLuint first;
- GLint i;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
- return;
- }
-
- if (!renderbuffers)
- return;
-
- first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
-
- for (i = 0; i < n; i++) {
- GLuint name = first + i;
- renderbuffers[i] = name;
- /* insert dummy placeholder into hash table */
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
- _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
- }
-}
-
-
-/**
- * Given an internal format token for a render buffer, return the
- * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
- * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
- * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
- *
- * This is similar to _mesa_base_tex_format() but the set of valid
- * internal formats is different.
- *
- * Note that even if a format is determined to be legal here, validation
- * of the FBO may fail if the format is not supported by the driver/GPU.
- *
- * \param internalFormat as passed to glRenderbufferStorage()
- * \return the base internal format, or 0 if internalFormat is illegal
- */
-GLenum
-_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
-{
- /*
- * Notes: some formats such as alpha, luminance, etc. were added
- * with GL_ARB_framebuffer_object.
- */
- switch (internalFormat) {
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE4_ALPHA4:
- case GL_LUMINANCE6_ALPHA2:
- case GL_LUMINANCE8_ALPHA8:
- case GL_LUMINANCE12_ALPHA4:
- case GL_LUMINANCE12_ALPHA12:
- case GL_LUMINANCE16_ALPHA16:
- return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
- case GL_RGB:
- case GL_R3_G3_B2:
- case GL_RGB4:
- case GL_RGB5:
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- case GL_SRGB8_EXT:
- return GL_RGB;
- case GL_RGBA:
- case GL_RGBA2:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- case GL_RGBA16_SNORM:
- case GL_SRGB8_ALPHA8_EXT:
- return GL_RGBA;
- case GL_STENCIL_INDEX:
- case GL_STENCIL_INDEX1_EXT:
- case GL_STENCIL_INDEX4_EXT:
- case GL_STENCIL_INDEX8_EXT:
- case GL_STENCIL_INDEX16_EXT:
- return GL_STENCIL_INDEX;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- return GL_DEPTH_COMPONENT;
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- if (ctx->Extensions.EXT_packed_depth_stencil)
- return GL_DEPTH_STENCIL_EXT;
- else
- return 0;
- case GL_RED:
- case GL_R8:
- case GL_R16:
- return ctx->Extensions.ARB_texture_rg ? GL_RED : 0;
- case GL_RG:
- case GL_RG8:
- case GL_RG16:
- return ctx->Extensions.ARB_texture_rg ? GL_RG : 0;
- /* XXX add floating point and integer formats eventually */
- default:
- return 0;
- }
-}
-
-
-/** sentinal value, see below */
-#define NO_SAMPLES 1000
-
-
-/**
- * Helper function used by _mesa_RenderbufferStorageEXT() and
- * _mesa_RenderbufferStorageMultisample().
- * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT().
- */
-static void
-renderbuffer_storage(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height, GLsizei samples)
-{
- const char *func = samples == NO_SAMPLES ?
- "glRenderbufferStorage" : "RenderbufferStorageMultisample";
- struct gl_renderbuffer *rb;
- GLenum baseFormat;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
- return;
- }
-
- baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
- if (baseFormat == 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
- return;
- }
-
- if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
- return;
- }
-
- if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
- return;
- }
-
- if (samples == NO_SAMPLES) {
- /* NumSamples == 0 indicates non-multisampling */
- samples = 0;
- }
- else if (samples > (GLsizei) ctx->Const.MaxSamples) {
- /* note: driver may choose to use more samples than what's requested */
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
- return;
- }
-
- rb = ctx->CurrentRenderbuffer;
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
- return;
- }
-
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- if (rb->InternalFormat == internalFormat &&
- rb->Width == (GLuint) width &&
- rb->Height == (GLuint) height) {
- /* no change in allocation needed */
- return;
- }
-
- /* These MUST get set by the AllocStorage func */
- rb->Format = MESA_FORMAT_NONE;
- rb->NumSamples = samples;
-
- /* Now allocate the storage */
- ASSERT(rb->AllocStorage);
- if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
- /* No error - check/set fields now */
- assert(rb->Format != MESA_FORMAT_NONE);
- assert(rb->Width == (GLuint) width);
- assert(rb->Height == (GLuint) height);
- rb->InternalFormat = internalFormat;
- rb->_BaseFormat = baseFormat;
- assert(rb->_BaseFormat != 0);
- }
- else {
- /* Probably ran out of memory - clear the fields */
- rb->Width = 0;
- rb->Height = 0;
- rb->Format = MESA_FORMAT_NONE;
- rb->InternalFormat = GL_NONE;
- rb->_BaseFormat = GL_NONE;
- rb->NumSamples = 0;
- }
-
- /*
- test_framebuffer_completeness(ctx, fb);
- */
- /* XXX if this renderbuffer is attached anywhere, invalidate attachment
- * points???
- */
-}
-
-
-#if FEATURE_OES_EGL_image
-void GLAPIENTRY
-_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
-{
- struct gl_renderbuffer *rb;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (!ctx->Extensions.OES_EGL_image) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glEGLImageTargetRenderbufferStorageOES(unsupported)");
- return;
- }
-
- if (target != GL_RENDERBUFFER) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "EGLImageTargetRenderbufferStorageOES");
- return;
- }
-
- rb = ctx->CurrentRenderbuffer;
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "EGLImageTargetRenderbufferStorageOES");
- return;
- }
-
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
-}
-#endif
-
-
-/**
- * Helper function for _mesa_GetRenderbufferParameterivEXT() and
- * _mesa_GetFramebufferAttachmentParameterivEXT()
- * We have to be careful to respect the base format. For example, if a
- * renderbuffer/texture was created with internalFormat=GL_RGB but the
- * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
- * we need to return zero.
- */
-static GLint
-get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
-{
- switch (pname) {
- case GL_RENDERBUFFER_RED_SIZE_EXT:
- case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
- if (baseFormat == GL_RGB || baseFormat == GL_RGBA ||
- baseFormat == GL_RG || baseFormat == GL_RED)
- return _mesa_get_format_bits(format, pname);
- else
- return 0;
- case GL_RENDERBUFFER_GREEN_SIZE_EXT:
- case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
- if (baseFormat == GL_RGB || baseFormat == GL_RGBA || baseFormat == GL_RG)
- return _mesa_get_format_bits(format, pname);
- else
- return 0;
- case GL_RENDERBUFFER_BLUE_SIZE_EXT:
- case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
- if (baseFormat == GL_RGB || baseFormat == GL_RGBA)
- return _mesa_get_format_bits(format, pname);
- else
- return 0;
- case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
- case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
- if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA ||
- baseFormat == GL_LUMINANCE_ALPHA)
- return _mesa_get_format_bits(format, pname);
- else
- return 0;
- case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
- case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
- if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL)
- return _mesa_get_format_bits(format, pname);
- else
- return 0;
- case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
- case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- if (baseFormat == GL_STENCIL_INDEX || baseFormat == GL_DEPTH_STENCIL)
- return _mesa_get_format_bits(format, pname);
- else
- return 0;
- default:
- return 0;
- }
-}
-
-
-
-void GLAPIENTRY
-_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height)
-{
- /* GL_ARB_fbo says calling this function is equivalent to calling
- * glRenderbufferStorageMultisample() with samples=0. We pass in
- * a token value here just for error reporting purposes.
- */
- renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
-}
-
-
-void GLAPIENTRY
-_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
- GLenum internalFormat,
- GLsizei width, GLsizei height)
-{
- renderbuffer_storage(target, internalFormat, width, height, samples);
-}
-
-
-/**
- * OpenGL ES version of glRenderBufferStorage.
- */
-void GLAPIENTRY
-_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height)
-{
- switch (internalFormat) {
- case GL_RGB565:
- /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
- /* choose a closest format */
- internalFormat = GL_RGB5;
- break;
- default:
- break;
- }
-
- renderbuffer_storage(target, internalFormat, width, height, 0);
-}
-
-
-void GLAPIENTRY
-_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
-{
- struct gl_renderbuffer *rb;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetRenderbufferParameterivEXT(target)");
- return;
- }
-
- rb = ctx->CurrentRenderbuffer;
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetRenderbufferParameterivEXT");
- return;
- }
-
- /* No need to flush here since we're just quering state which is
- * not effected by rendering.
- */
-
- switch (pname) {
- case GL_RENDERBUFFER_WIDTH_EXT:
- *params = rb->Width;
- return;
- case GL_RENDERBUFFER_HEIGHT_EXT:
- *params = rb->Height;
- return;
- case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
- *params = rb->InternalFormat;
- return;
- case GL_RENDERBUFFER_RED_SIZE_EXT:
- case GL_RENDERBUFFER_GREEN_SIZE_EXT:
- case GL_RENDERBUFFER_BLUE_SIZE_EXT:
- case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
- case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
- case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
- *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
- break;
- case GL_RENDERBUFFER_SAMPLES:
- if (ctx->Extensions.ARB_framebuffer_object) {
- *params = rb->NumSamples;
- break;
- }
- /* fallthrough */
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetRenderbufferParameterivEXT(target)");
- return;
- }
-}
-
-
-GLboolean GLAPIENTRY
-_mesa_IsFramebufferEXT(GLuint framebuffer)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
- if (framebuffer) {
- struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
- if (rb != NULL && rb != &DummyFramebuffer)
- return GL_TRUE;
- }
- return GL_FALSE;
-}
-
-
-/**
- * Check if any of the attachments of the given framebuffer are textures
- * (render to texture). Call ctx->Driver.RenderTexture() for such
- * attachments.
- */
-static void
-check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
-{
- GLuint i;
- ASSERT(ctx->Driver.RenderTexture);
-
- if (fb->Name == 0)
- return; /* can't render to texture with winsys framebuffers */
-
- for (i = 0; i < BUFFER_COUNT; i++) {
- struct gl_renderbuffer_attachment *att = fb->Attachment + i;
- struct gl_texture_object *texObj = att->Texture;
- if (texObj
- && texObj->Image[att->CubeMapFace][att->TextureLevel]) {
- ctx->Driver.RenderTexture(ctx, fb, att);
- }
- }
-}
-
-
-/**
- * Examine all the framebuffer's attachments to see if any are textures.
- * If so, call ctx->Driver.FinishRenderTexture() for each texture to
- * notify the device driver that the texture image may have changed.
- */
-static void
-check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
-{
- if (fb->Name == 0)
- return; /* can't render to texture with winsys framebuffers */
-
- if (ctx->Driver.FinishRenderTexture) {
- GLuint i;
- for (i = 0; i < BUFFER_COUNT; i++) {
- struct gl_renderbuffer_attachment *att = fb->Attachment + i;
- if (att->Texture && att->Renderbuffer) {
- ctx->Driver.FinishRenderTexture(ctx, att);
- }
- }
- }
-}
-
-
-void GLAPIENTRY
-_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
-{
- struct gl_framebuffer *newDrawFb, *newReadFb;
- struct gl_framebuffer *oldDrawFb, *oldReadFb;
- GLboolean bindReadBuf, bindDrawBuf;
- GET_CURRENT_CONTEXT(ctx);
-
-#ifdef DEBUG
- if (ctx->Extensions.ARB_framebuffer_object) {
- ASSERT(ctx->Extensions.EXT_framebuffer_object);
- ASSERT(ctx->Extensions.EXT_framebuffer_blit);
- }
-#endif
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (!ctx->Extensions.EXT_framebuffer_object) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindFramebufferEXT(unsupported)");
- return;
- }
-
- switch (target) {
-#if FEATURE_EXT_framebuffer_blit
- case GL_DRAW_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
- return;
- }
- bindDrawBuf = GL_TRUE;
- bindReadBuf = GL_FALSE;
- break;
- case GL_READ_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
- return;
- }
- bindDrawBuf = GL_FALSE;
- bindReadBuf = GL_TRUE;
- break;
-#endif
- case GL_FRAMEBUFFER_EXT:
- bindDrawBuf = GL_TRUE;
- bindReadBuf = GL_TRUE;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
- return;
- }
-
- if (framebuffer) {
- /* Binding a user-created framebuffer object */
- newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
- if (newDrawFb == &DummyFramebuffer) {
- /* ID was reserved, but no real framebuffer object made yet */
- newDrawFb = NULL;
- }
- else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) {
- /* All FBO IDs must be Gen'd */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
- return;
- }
-
- if (!newDrawFb) {
- /* create new framebuffer object */
- newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
- if (!newDrawFb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
- return;
- }
- _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
- }
- newReadFb = newDrawFb;
- }
- else {
- /* Binding the window system framebuffer (which was originally set
- * with MakeCurrent).
- */
- newDrawFb = ctx->WinSysDrawBuffer;
- newReadFb = ctx->WinSysReadBuffer;
- }
-
- ASSERT(newDrawFb);
- ASSERT(newDrawFb != &DummyFramebuffer);
-
- /* save pointers to current/old framebuffers */
- oldDrawFb = ctx->DrawBuffer;
- oldReadFb = ctx->ReadBuffer;
-
- /* check if really changing bindings */
- if (oldDrawFb == newDrawFb)
- bindDrawBuf = GL_FALSE;
- if (oldReadFb == newReadFb)
- bindReadBuf = GL_FALSE;
-
- /*
- * OK, now bind the new Draw/Read framebuffers, if they're changing.
- *
- * We also check if we're beginning and/or ending render-to-texture.
- * When a framebuffer with texture attachments is unbound, call
- * ctx->Driver.FinishRenderTexture().
- * When a framebuffer with texture attachments is bound, call
- * ctx->Driver.RenderTexture().
- *
- * Note that if the ReadBuffer has texture attachments we don't consider
- * that a render-to-texture case.
- */
- if (bindReadBuf) {
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- /* check if old readbuffer was render-to-texture */
- check_end_texture_render(ctx, oldReadFb);
-
- _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
- }
-
- if (bindDrawBuf) {
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- /* check if old read/draw buffers were render-to-texture */
- if (!bindReadBuf)
- check_end_texture_render(ctx, oldReadFb);
-
- if (oldDrawFb != oldReadFb)
- check_end_texture_render(ctx, oldDrawFb);
-
- /* check if newly bound framebuffer has any texture attachments */
- check_begin_texture_render(ctx, newDrawFb);
-
- _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
- }
-
- if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
- ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
- }
-}
-
-
-void GLAPIENTRY
-_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
-{
- GLint i;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- for (i = 0; i < n; i++) {
- if (framebuffers[i] > 0) {
- struct gl_framebuffer *fb;
- fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
- if (fb) {
- ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
-
- /* check if deleting currently bound framebuffer object */
- if (ctx->Extensions.EXT_framebuffer_blit) {
- /* separate draw/read binding points */
- if (fb == ctx->DrawBuffer) {
- /* bind default */
- ASSERT(fb->RefCount >= 2);
- _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
- }
- if (fb == ctx->ReadBuffer) {
- /* bind default */
- ASSERT(fb->RefCount >= 2);
- _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
- }
- }
- else {
- /* only one binding point for read/draw buffers */
- if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
- /* bind default */
- ASSERT(fb->RefCount >= 2);
- _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- }
- }
-
- /* remove from hash table immediately, to free the ID */
- _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
-
- if (fb != &DummyFramebuffer) {
- /* But the object will not be freed until it's no longer
- * bound in any context.
- */
- _mesa_reference_framebuffer(&fb, NULL);
- }
- }
- }
- }
-}
-
-
-void GLAPIENTRY
-_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLuint first;
- GLint i;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
- return;
- }
-
- if (!framebuffers)
- return;
-
- first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
-
- for (i = 0; i < n; i++) {
- GLuint name = first + i;
- framebuffers[i] = name;
- /* insert dummy placeholder into hash table */
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
- _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
- }
-}
-
-
-
-GLenum GLAPIENTRY
-_mesa_CheckFramebufferStatusEXT(GLenum target)
-{
- struct gl_framebuffer *buffer;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
-
- switch (target) {
-#if FEATURE_EXT_framebuffer_blit
- case GL_DRAW_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
- return 0;
- }
- buffer = ctx->DrawBuffer;
- break;
- case GL_READ_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
- return 0;
- }
- buffer = ctx->ReadBuffer;
- break;
-#endif
- case GL_FRAMEBUFFER_EXT:
- buffer = ctx->DrawBuffer;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
- return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
- }
-
- if (buffer->Name == 0) {
- /* The window system / default framebuffer is always complete */
- return GL_FRAMEBUFFER_COMPLETE_EXT;
- }
-
- /* No need to flush here */
-
- if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
- _mesa_test_framebuffer_completeness(ctx, buffer);
- }
-
- return buffer->_Status;
-}
-
-
-
-/**
- * Common code called by glFramebufferTexture1D/2D/3DEXT().
- */
-static void
-framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
- GLenum attachment, GLenum textarget, GLuint texture,
- GLint level, GLint zoffset)
-{
- struct gl_renderbuffer_attachment *att;
- struct gl_texture_object *texObj = NULL;
- struct gl_framebuffer *fb;
- GLboolean error = GL_FALSE;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- switch (target) {
- case GL_READ_FRAMEBUFFER_EXT:
- error = !ctx->Extensions.EXT_framebuffer_blit;
- fb = ctx->ReadBuffer;
- break;
- case GL_DRAW_FRAMEBUFFER_EXT:
- error = !ctx->Extensions.EXT_framebuffer_blit;
- /* fall-through */
- case GL_FRAMEBUFFER_EXT:
- fb = ctx->DrawBuffer;
- break;
- default:
- error = GL_TRUE;
- }
-
- if (error) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
- return;
- }
-
- ASSERT(fb);
-
- /* check framebuffer binding */
- if (fb->Name == 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%sEXT", caller);
- return;
- }
-
-
- /* The textarget, level, and zoffset parameters are only validated if
- * texture is non-zero.
- */
- if (texture) {
- GLboolean err = GL_TRUE;
-
- texObj = _mesa_lookup_texture(ctx, texture);
- if (texObj != NULL) {
- if (textarget == 0) {
- /* XXX what's the purpose of this? */
- err = (texObj->Target != GL_TEXTURE_3D) &&
- (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
- (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT);
- }
- else {
- err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
- ? !IS_CUBE_FACE(textarget)
- : (texObj->Target != textarget);
- }
- }
- else {
- /* can't render to a non-existant texture */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%sEXT(non existant texture)",
- caller);
- return;
- }
-
- if (err) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%sEXT(texture target mismatch)",
- caller);
- return;
- }
-
- if (texObj->Target == GL_TEXTURE_3D) {
- const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
- if (zoffset < 0 || zoffset >= maxSize) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%sEXT(zoffset)", caller);
- return;
- }
- }
- else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
- (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
- if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%sEXT(layer)", caller);
- return;
- }
- }
-
- if ((level < 0) ||
- (level >= _mesa_max_texture_levels(ctx, texObj->Target))) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%sEXT(level)", caller);
- return;
- }
- }
-
- att = _mesa_get_attachment(ctx, fb, attachment);
- if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%sEXT(attachment)", caller);
- return;
- }
-
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- _glthread_LOCK_MUTEX(fb->Mutex);
- if (texObj) {
- _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
- level, zoffset);
- /* Set the render-to-texture flag. We'll check this flag in
- * glTexImage() and friends to determine if we need to revalidate
- * any FBOs that might be rendering into this texture.
- * This flag never gets cleared since it's non-trivial to determine
- * when all FBOs might be done rendering to this texture. That's OK
- * though since it's uncommon to render to a texture then repeatedly
- * call glTexImage() to change images in the texture.
- */
- texObj->_RenderToTexture = GL_TRUE;
- }
- else {
- _mesa_remove_attachment(ctx, att);
- }
-
- invalidate_framebuffer(fb);
-
- _glthread_UNLOCK_MUTEX(fb->Mutex);
-}
-
-
-
-void GLAPIENTRY
-_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if ((texture != 0) && (textarget != GL_TEXTURE_1D)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture1DEXT(textarget)");
- return;
- }
-
- framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
- level, 0);
-}
-
-
-void GLAPIENTRY
-_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if ((texture != 0) &&
- (textarget != GL_TEXTURE_2D) &&
- (textarget != GL_TEXTURE_RECTANGLE_ARB) &&
- (!IS_CUBE_FACE(textarget))) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture2DEXT(textarget=0x%x)", textarget);
- return;
- }
-
- framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
- level, 0);
-}
-
-
-void GLAPIENTRY
-_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture,
- GLint level, GLint zoffset)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture3DEXT(textarget)");
- return;
- }
-
- framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
- level, zoffset);
-}
-
-
-void GLAPIENTRY
-_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLint layer)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
- level, layer);
-}
-
-
-void GLAPIENTRY
-_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
- GLenum renderbufferTarget,
- GLuint renderbuffer)
-{
- struct gl_renderbuffer_attachment *att;
- struct gl_framebuffer *fb;
- struct gl_renderbuffer *rb;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- switch (target) {
-#if FEATURE_EXT_framebuffer_blit
- case GL_DRAW_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(target)");
- return;
- }
- fb = ctx->DrawBuffer;
- break;
- case GL_READ_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(target)");
- return;
- }
- fb = ctx->ReadBuffer;
- break;
-#endif
- case GL_FRAMEBUFFER_EXT:
- fb = ctx->DrawBuffer;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(target)");
- return;
- }
-
- if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(renderbufferTarget)");
- return;
- }
-
- if (fb->Name == 0) {
- /* Can't attach new renderbuffers to a window system framebuffer */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
- return;
- }
-
- att = _mesa_get_attachment(ctx, fb, attachment);
- if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(invalid attachment %s)",
- _mesa_lookup_enum_by_nr(attachment));
- return;
- }
-
- if (renderbuffer) {
- rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbufferEXT(non-existant"
- " renderbuffer %u)", renderbuffer);
- return;
- }
- else if (rb == &DummyRenderbuffer) {
- /* This is what NVIDIA does */
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferRenderbufferEXT(renderbuffer %u)",
- renderbuffer);
- return;
- }
- }
- else {
- /* remove renderbuffer attachment */
- rb = NULL;
- }
-
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
- rb && rb->Format != MESA_FORMAT_NONE) {
- /* make sure the renderbuffer is a depth/stencil format */
- const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
- if (baseFormat != GL_DEPTH_STENCIL) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbufferEXT(renderbuffer"
- " is not DEPTH_STENCIL format)");
- return;
- }
- }
-
-
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- assert(ctx->Driver.FramebufferRenderbuffer);
- ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
-
- /* Some subsequent GL commands may depend on the framebuffer's visual
- * after the binding is updated. Update visual info now.
- */
- _mesa_update_framebuffer_visual(ctx, fb);
-}
-
-
-void GLAPIENTRY
-_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
- GLenum pname, GLint *params)
-{
- const struct gl_renderbuffer_attachment *att;
- struct gl_framebuffer *buffer;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- switch (target) {
-#if FEATURE_EXT_framebuffer_blit
- case GL_DRAW_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(target)");
- return;
- }
- buffer = ctx->DrawBuffer;
- break;
- case GL_READ_FRAMEBUFFER_EXT:
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(target)");
- return;
- }
- buffer = ctx->ReadBuffer;
- break;
-#endif
- case GL_FRAMEBUFFER_EXT:
- buffer = ctx->DrawBuffer;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(target)");
- return;
- }
-
- if (buffer->Name == 0) {
- /* the default / window-system FBO */
- att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
- }
- else {
- /* user-created framebuffer FBO */
- att = _mesa_get_attachment(ctx, buffer, attachment);
- }
-
- if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(attachment)");
- return;
- }
-
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
- /* the depth and stencil attachments must point to the same buffer */
- const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
- depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
- stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
- if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
- " attachments differ)");
- return;
- }
- }
-
- /* No need to flush here */
-
- switch (pname) {
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
- *params = buffer->Name == 0 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
- return;
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
- if (att->Type == GL_RENDERBUFFER_EXT) {
- *params = att->Renderbuffer->Name;
- }
- else if (att->Type == GL_TEXTURE) {
- *params = att->Texture->Name;
- }
- else {
- assert(att->Type == GL_NONE);
- *params = 0;
- }
- return;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
- if (att->Type == GL_TEXTURE) {
- *params = att->TextureLevel;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
- }
- return;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
- if (att->Type == GL_TEXTURE) {
- if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
- *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
- }
- else {
- *params = 0;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
- }
- return;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
- if (att->Type == GL_TEXTURE) {
- if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
- *params = att->Zoffset;
- }
- else {
- *params = 0;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
- }
- return;
- case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
- if (!ctx->Extensions.ARB_framebuffer_object) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
- }
- else {
- if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) {
- *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
- }
- else {
- /* According to ARB_framebuffer_sRGB, we should return LINEAR
- * if the sRGB conversion is unsupported. */
- *params = GL_LINEAR;
- }
- }
- return;
- case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
- if (!ctx->Extensions.ARB_framebuffer_object) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
- return;
- }
- else {
- gl_format format = att->Renderbuffer->Format;
- if (format == MESA_FORMAT_CI8 || format == MESA_FORMAT_S8) {
- /* special cases */
- *params = GL_INDEX;
- }
- else {
- *params = _mesa_get_format_datatype(format);
- }
- }
- return;
- case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- if (!ctx->Extensions.ARB_framebuffer_object) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
- }
- else if (att->Texture) {
- const struct gl_texture_image *texImage =
- _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
- att->TextureLevel);
- if (texImage) {
- *params = get_component_bits(pname, texImage->_BaseFormat,
- texImage->TexFormat);
- }
- else {
- *params = 0;
- }
- }
- else if (att->Renderbuffer) {
- *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
- att->Renderbuffer->Format);
- }
- else {
- *params = 0;
- }
- return;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameterivEXT(pname)");
- return;
- }
-}
-
-
-void GLAPIENTRY
-_mesa_GenerateMipmapEXT(GLenum target)
-{
- struct gl_texture_object *texObj;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_TEXTURE_CUBE_MAP:
- /* OK, legal value */
- break;
- default:
- /* XXX need to implement GL_TEXTURE_1D_ARRAY and GL_TEXTURE_2D_ARRAY */
- _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");
- return;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- if (texObj->BaseLevel >= texObj->MaxLevel) {
- /* nothing to do */
- return;
- }
-
- if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
- !_mesa_cube_complete(texObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGenerateMipmap(incomplete cube map)");
- return;
- }
-
- _mesa_lock_texture(ctx, texObj);
- if (target == GL_TEXTURE_CUBE_MAP) {
- GLuint face;
- for (face = 0; face < 6; face++)
- ctx->Driver.GenerateMipmap(ctx,
- GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
- texObj);
- }
- else {
- ctx->Driver.GenerateMipmap(ctx, target, texObj);
- }
- _mesa_unlock_texture(ctx, texObj);
-}
-
-
-#if FEATURE_EXT_framebuffer_blit
-
-static const struct gl_renderbuffer_attachment *
-find_attachment(const struct gl_framebuffer *fb,
- const struct gl_renderbuffer *rb)
-{
- GLuint i;
- for (i = 0; i < Elements(fb->Attachment); i++) {
- if (fb->Attachment[i].Renderbuffer == rb)
- return &fb->Attachment[i];
- }
- return NULL;
-}
-
-
-
-/**
- * Blit rectangular region, optionally from one framebuffer to another.
- *
- * Note, if the src buffer is multisampled and the dest is not, this is
- * when the samples must be resolved to a single color.
- */
-void GLAPIENTRY
-_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
- GL_DEPTH_BUFFER_BIT |
- GL_STENCIL_BUFFER_BIT);
- const struct gl_framebuffer *readFb, *drawFb;
- const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx,
- "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, _mesa_lookup_enum_by_nr(filter));
-
- if (ctx->NewState) {
- _mesa_update_state(ctx);
- }
-
- readFb = ctx->ReadBuffer;
- drawFb = ctx->DrawBuffer;
-
- if (!readFb || !drawFb) {
- /* This will normally never happen but someday we may want to
- * support MakeCurrent() with no drawables.
- */
- return;
- }
-
- /* check for complete framebuffers */
- if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
- readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glBlitFramebufferEXT(incomplete draw/read buffers)");
- return;
- }
-
- if (filter != GL_NEAREST && filter != GL_LINEAR) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
- return;
- }
-
- if (mask & ~legalMaskBits) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
- return;
- }
-
- /* depth/stencil must be blitted with nearest filtering */
- if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
- && filter != GL_NEAREST) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter");
- return;
- }
-
- /* get color read/draw renderbuffers */
- if (mask & GL_COLOR_BUFFER_BIT) {
- colorReadRb = readFb->_ColorReadBuffer;
- colorDrawRb = drawFb->_ColorDrawBuffers[0];
- }
- else {
- colorReadRb = colorDrawRb = NULL;
- }
-
- if (mask & GL_STENCIL_BUFFER_BIT) {
- struct gl_renderbuffer *readRb = readFb->_StencilBuffer;
- struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer;
- if (!readRb ||
- !drawRb ||
- _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
- _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(stencil buffer size mismatch");
- return;
- }
- }
-
- if (mask & GL_DEPTH_BUFFER_BIT) {
- struct gl_renderbuffer *readRb = readFb->_DepthBuffer;
- struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer;
- if (!readRb ||
- !drawRb ||
- _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
- _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(depth buffer size mismatch");
- return;
- }
- }
-
- if (readFb->Visual.samples > 0 &&
- drawFb->Visual.samples > 0 &&
- readFb->Visual.samples != drawFb->Visual.samples) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(mismatched samples");
- return;
- }
-
- /* extra checks for multisample copies... */
- if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
- /* src and dest region sizes must be the same */
- if (srcX1 - srcX0 != dstX1 - dstX0 ||
- srcY1 - srcY0 != dstY1 - dstY0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(bad src/dst multisample region sizes");
- return;
- }
-
- /* color formats must match */
- if (colorReadRb &&
- colorDrawRb &&
- colorReadRb->Format != colorDrawRb->Format) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(bad src/dst multisample pixel formats");
- return;
- }
- }
-
- if (!ctx->Extensions.EXT_framebuffer_blit) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
- return;
- }
-
- /* Debug code */
- if (DEBUG_BLIT) {
- printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
- " 0x%x, 0x%x)\n",
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, filter);
- if (colorReadRb) {
- const struct gl_renderbuffer_attachment *att;
-
- att = find_attachment(readFb, colorReadRb);
- printf(" Src FBO %u RB %u (%dx%d) ",
- readFb->Name, colorReadRb->Name,
- colorReadRb->Width, colorReadRb->Height);
- if (att && att->Texture) {
- printf("Tex %u tgt 0x%x level %u face %u",
- att->Texture->Name,
- att->Texture->Target,
- att->TextureLevel,
- att->CubeMapFace);
- }
- printf("\n");
-
- att = find_attachment(drawFb, colorDrawRb);
- printf(" Dst FBO %u RB %u (%dx%d) ",
- drawFb->Name, colorDrawRb->Name,
- colorDrawRb->Width, colorDrawRb->Height);
- if (att && att->Texture) {
- printf("Tex %u tgt 0x%x level %u face %u",
- att->Texture->Name,
- att->Texture->Target,
- att->TextureLevel,
- att->CubeMapFace);
- }
- printf("\n");
- }
- }
-
- ASSERT(ctx->Driver.BlitFramebuffer);
- ctx->Driver.BlitFramebuffer(ctx,
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, filter);
-}
-#endif /* FEATURE_EXT_framebuffer_blit */
-
-#if FEATURE_ARB_geometry_shader4
-void GLAPIENTRY
-_mesa_FramebufferTextureARB(GLenum target, GLenum attachment,
- GLuint texture, GLint level)
-{
- GET_CURRENT_CONTEXT(ctx);
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTextureARB "
- "not implemented!");
-}
-
-void GLAPIENTRY
-_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLenum face)
-{
- GET_CURRENT_CONTEXT(ctx);
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTextureFaceARB "
- "not implemented!");
-}
-#endif /* FEATURE_ARB_geometry_shader4 */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2009 VMware, Inc. 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.
+ */
+
+
+/*
+ * GL_EXT/ARB_framebuffer_object extensions
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#include "buffers.h"
+#include "context.h"
+#include "enums.h"
+#include "fbobject.h"
+#include "formats.h"
+#include "framebuffer.h"
+#include "hash.h"
+#include "macros.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "renderbuffer.h"
+#include "state.h"
+#include "teximage.h"
+#include "texobj.h"
+
+
+/** Set this to 1 to help debug FBO incompleteness problems */
+#define DEBUG_FBO 0
+
+/** Set this to 1 to debug/log glBlitFramebuffer() calls */
+#define DEBUG_BLIT 0
+
+
+/**
+ * Notes:
+ *
+ * None of the GL_EXT_framebuffer_object functions are compiled into
+ * display lists.
+ */
+
+
+
+/*
+ * When glGenRender/FramebuffersEXT() is called we insert pointers to
+ * these placeholder objects into the hash table.
+ * Later, when the object ID is first bound, we replace the placeholder
+ * with the real frame/renderbuffer.
+ */
+static struct gl_framebuffer DummyFramebuffer;
+static struct gl_renderbuffer DummyRenderbuffer;
+
+/* We bind this framebuffer when applications pass a NULL
+ * drawable/surface in make current. */
+static struct gl_framebuffer IncompleteFramebuffer;
+
+
+#define IS_CUBE_FACE(TARGET) \
+ ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
+ (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
+
+
+static void
+delete_dummy_renderbuffer(struct gl_renderbuffer *rb)
+{
+ /* no op */
+}
+
+static void
+delete_dummy_framebuffer(struct gl_framebuffer *fb)
+{
+ /* no op */
+}
+
+
+void
+_mesa_init_fbobjects(struct gl_context *ctx)
+{
+ _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
+ _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
+ _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex);
+ DummyFramebuffer.Delete = delete_dummy_framebuffer;
+ DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
+ IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
+}
+
+struct gl_framebuffer *
+_mesa_get_incomplete_framebuffer(void)
+{
+ return &IncompleteFramebuffer;
+}
+
+/**
+ * Helper routine for getting a gl_renderbuffer.
+ */
+struct gl_renderbuffer *
+_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
+{
+ struct gl_renderbuffer *rb;
+
+ if (id == 0)
+ return NULL;
+
+ rb = (struct gl_renderbuffer *)
+ _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
+ return rb;
+}
+
+
+/**
+ * Helper routine for getting a gl_framebuffer.
+ */
+struct gl_framebuffer *
+_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
+{
+ struct gl_framebuffer *fb;
+
+ if (id == 0)
+ return NULL;
+
+ fb = (struct gl_framebuffer *)
+ _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
+ return fb;
+}
+
+
+/**
+ * Mark the given framebuffer as invalid. This will force the
+ * test for framebuffer completeness to be done before the framebuffer
+ * is used.
+ */
+static void
+invalidate_framebuffer(struct gl_framebuffer *fb)
+{
+ fb->_Status = 0; /* "indeterminate" */
+}
+
+
+/**
+ * Return the gl_framebuffer object which corresponds to the given
+ * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
+ * Check support for GL_EXT_framebuffer_blit to determine if certain
+ * targets are legal.
+ * \return gl_framebuffer pointer or NULL if target is illegal
+ */
+static struct gl_framebuffer *
+get_framebuffer_target(struct gl_context *ctx, GLenum target)
+{
+ switch (target) {
+ case GL_DRAW_FRAMEBUFFER:
+ return ctx->Extensions.EXT_framebuffer_blit ? ctx->DrawBuffer : NULL;
+ case GL_READ_FRAMEBUFFER:
+ return ctx->Extensions.EXT_framebuffer_blit ? ctx->ReadBuffer : NULL;
+ case GL_FRAMEBUFFER_EXT:
+ return ctx->DrawBuffer;
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
+ * gl_renderbuffer_attachment object.
+ * This function is only used for user-created FB objects, not the
+ * default / window-system FB object.
+ * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
+ * the depth buffer attachment point.
+ */
+struct gl_renderbuffer_attachment *
+_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment)
+{
+ GLuint i;
+
+ assert(fb->Name > 0);
+
+ switch (attachment) {
+ case GL_COLOR_ATTACHMENT0_EXT:
+ case GL_COLOR_ATTACHMENT1_EXT:
+ case GL_COLOR_ATTACHMENT2_EXT:
+ case GL_COLOR_ATTACHMENT3_EXT:
+ case GL_COLOR_ATTACHMENT4_EXT:
+ case GL_COLOR_ATTACHMENT5_EXT:
+ case GL_COLOR_ATTACHMENT6_EXT:
+ case GL_COLOR_ATTACHMENT7_EXT:
+ case GL_COLOR_ATTACHMENT8_EXT:
+ case GL_COLOR_ATTACHMENT9_EXT:
+ case GL_COLOR_ATTACHMENT10_EXT:
+ case GL_COLOR_ATTACHMENT11_EXT:
+ case GL_COLOR_ATTACHMENT12_EXT:
+ case GL_COLOR_ATTACHMENT13_EXT:
+ case GL_COLOR_ATTACHMENT14_EXT:
+ case GL_COLOR_ATTACHMENT15_EXT:
+ i = attachment - GL_COLOR_ATTACHMENT0_EXT;
+ if (i >= ctx->Const.MaxColorAttachments) {
+ return NULL;
+ }
+ return &fb->Attachment[BUFFER_COLOR0 + i];
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ /* fall-through */
+ case GL_DEPTH_BUFFER:
+ /* fall-through / new in GL 3.0 */
+ case GL_DEPTH_ATTACHMENT_EXT:
+ return &fb->Attachment[BUFFER_DEPTH];
+ case GL_STENCIL_BUFFER:
+ /* fall-through / new in GL 3.0 */
+ case GL_STENCIL_ATTACHMENT_EXT:
+ return &fb->Attachment[BUFFER_STENCIL];
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * As above, but only used for getting attachments of the default /
+ * window-system framebuffer (not user-created framebuffer objects).
+ */
+static struct gl_renderbuffer_attachment *
+_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment)
+{
+ assert(fb->Name == 0);
+
+ switch (attachment) {
+ case GL_FRONT_LEFT:
+ return &fb->Attachment[BUFFER_FRONT_LEFT];
+ case GL_FRONT_RIGHT:
+ return &fb->Attachment[BUFFER_FRONT_RIGHT];
+ case GL_BACK_LEFT:
+ return &fb->Attachment[BUFFER_BACK_LEFT];
+ case GL_BACK_RIGHT:
+ return &fb->Attachment[BUFFER_BACK_RIGHT];
+ case GL_AUX0:
+ if (fb->Visual.numAuxBuffers == 1) {
+ return &fb->Attachment[BUFFER_AUX0];
+ }
+ return NULL;
+ case GL_DEPTH_BUFFER:
+ /* fall-through / new in GL 3.0 */
+ case GL_DEPTH_ATTACHMENT_EXT:
+ return &fb->Attachment[BUFFER_DEPTH];
+ case GL_STENCIL_BUFFER:
+ /* fall-through / new in GL 3.0 */
+ case GL_STENCIL_ATTACHMENT_EXT:
+ return &fb->Attachment[BUFFER_STENCIL];
+ default:
+ return NULL;
+ }
+}
+
+
+
+/**
+ * Remove any texture or renderbuffer attached to the given attachment
+ * point. Update reference counts, etc.
+ */
+void
+_mesa_remove_attachment(struct gl_context *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+ if (att->Type == GL_TEXTURE) {
+ ASSERT(att->Texture);
+ if (ctx->Driver.FinishRenderTexture) {
+ /* tell driver that we're done rendering to this texture. */
+ ctx->Driver.FinishRenderTexture(ctx, att);
+ }
+ _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
+ ASSERT(!att->Texture);
+ }
+ if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
+ ASSERT(!att->Texture);
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
+ ASSERT(!att->Renderbuffer);
+ }
+ att->Type = GL_NONE;
+ att->Complete = GL_TRUE;
+}
+
+
+/**
+ * Bind a texture object to an attachment point.
+ * The previous binding, if any, will be removed first.
+ */
+void
+_mesa_set_texture_attachment(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_texture_object *texObj,
+ GLenum texTarget, GLuint level, GLuint zoffset)
+{
+ if (att->Texture == texObj) {
+ /* re-attaching same texture */
+ ASSERT(att->Type == GL_TEXTURE);
+ if (ctx->Driver.FinishRenderTexture)
+ ctx->Driver.FinishRenderTexture(ctx, att);
+ }
+ else {
+ /* new attachment */
+ if (ctx->Driver.FinishRenderTexture && att->Texture)
+ ctx->Driver.FinishRenderTexture(ctx, att);
+ _mesa_remove_attachment(ctx, att);
+ att->Type = GL_TEXTURE;
+ assert(!att->Texture);
+ _mesa_reference_texobj(&att->Texture, texObj);
+ }
+
+ /* always update these fields */
+ att->TextureLevel = level;
+ att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
+ att->Zoffset = zoffset;
+ att->Complete = GL_FALSE;
+
+ if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
+ ctx->Driver.RenderTexture(ctx, fb, att);
+ }
+
+ invalidate_framebuffer(fb);
+}
+
+
+/**
+ * Bind a renderbuffer to an attachment point.
+ * The previous binding, if any, will be removed first.
+ */
+void
+_mesa_set_renderbuffer_attachment(struct gl_context *ctx,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_renderbuffer *rb)
+{
+ /* XXX check if re-doing same attachment, exit early */
+ _mesa_remove_attachment(ctx, att);
+ att->Type = GL_RENDERBUFFER_EXT;
+ att->Texture = NULL; /* just to be safe */
+ att->Complete = GL_FALSE;
+ _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+}
+
+
+/**
+ * Fallback for ctx->Driver.FramebufferRenderbuffer()
+ * Attach a renderbuffer object to a framebuffer object.
+ */
+void
+_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment, struct gl_renderbuffer *rb)
+{
+ struct gl_renderbuffer_attachment *att;
+
+ _glthread_LOCK_MUTEX(fb->Mutex);
+
+ att = _mesa_get_attachment(ctx, fb, attachment);
+ ASSERT(att);
+ if (rb) {
+ _mesa_set_renderbuffer_attachment(ctx, att, rb);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* do stencil attachment here (depth already done above) */
+ att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
+ assert(att);
+ _mesa_set_renderbuffer_attachment(ctx, att, rb);
+ }
+ }
+ else {
+ _mesa_remove_attachment(ctx, att);
+ }
+
+ invalidate_framebuffer(fb);
+
+ _glthread_UNLOCK_MUTEX(fb->Mutex);
+}
+
+
+/**
+ * Fallback for ctx->Driver.ValidateFramebuffer()
+ * Check if the renderbuffer's formats are supported by the software
+ * renderer.
+ * Drivers should probably override this.
+ */
+void
+_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
+{
+ gl_buffer_index buf;
+ for (buf = 0; buf < BUFFER_COUNT; buf++) {
+ const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
+ if (rb) {
+ switch (rb->_BaseFormat) {
+ case GL_ALPHA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE:
+ case GL_INTENSITY:
+ case GL_RED:
+ case GL_RG:
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
+ return;
+ default:
+ /* render buffer format is supported by software rendering */
+ ;
+ }
+ }
+ }
+}
+
+
+/**
+ * For debug only.
+ */
+static void
+att_incomplete(const char *msg)
+{
+#if DEBUG_FBO
+ _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
+#else
+ (void) msg;
+#endif
+}
+
+
+/**
+ * For debug only.
+ */
+static void
+fbo_incomplete(const char *msg, int index)
+{
+#if DEBUG_FBO
+ _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
+#else
+ (void) msg;
+ (void) index;
+#endif
+}
+
+
+/**
+ * Is the given base format a legal format for a color renderbuffer?
+ */
+GLboolean
+_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
+{
+ switch (baseFormat) {
+ case GL_RGB:
+ case GL_RGBA:
+ return GL_TRUE;
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_ALPHA:
+ return ctx->Extensions.ARB_framebuffer_object;
+ case GL_RED:
+ case GL_RG:
+ return ctx->Extensions.ARB_texture_rg;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Is the given base format a legal format for a depth/stencil renderbuffer?
+ */
+static GLboolean
+is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
+{
+ switch (baseFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if an attachment point is complete and update its Complete field.
+ * \param format if GL_COLOR, this is a color attachment point,
+ * if GL_DEPTH, this is a depth component attachment point,
+ * if GL_STENCIL, this is a stencil component attachment point.
+ */
+static void
+test_attachment_completeness(const struct gl_context *ctx, GLenum format,
+ struct gl_renderbuffer_attachment *att)
+{
+ assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
+
+ /* assume complete */
+ att->Complete = GL_TRUE;
+
+ /* Look for reasons why the attachment might be incomplete */
+ if (att->Type == GL_TEXTURE) {
+ const struct gl_texture_object *texObj = att->Texture;
+ struct gl_texture_image *texImage;
+ GLenum baseFormat;
+
+ if (!texObj) {
+ att_incomplete("no texobj");
+ att->Complete = GL_FALSE;
+ return;
+ }
+
+ texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
+ if (!texImage) {
+ att_incomplete("no teximage");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (texImage->Width < 1 || texImage->Height < 1) {
+ att_incomplete("teximage width/height=0");
+ printf("texobj = %u\n", texObj->Name);
+ printf("level = %d\n", att->TextureLevel);
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
+ att_incomplete("bad z offset");
+ att->Complete = GL_FALSE;
+ return;
+ }
+
+ baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
+
+ if (format == GL_COLOR) {
+ if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
+ att_incomplete("bad format");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (_mesa_is_format_compressed(texImage->TexFormat)) {
+ att_incomplete("compressed internalformat");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ }
+ else if (format == GL_DEPTH) {
+ if (baseFormat == GL_DEPTH_COMPONENT) {
+ /* OK */
+ }
+ else if (ctx->Extensions.EXT_packed_depth_stencil &&
+ ctx->Extensions.ARB_depth_texture &&
+ baseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* OK */
+ }
+ else {
+ att->Complete = GL_FALSE;
+ att_incomplete("bad depth format");
+ return;
+ }
+ }
+ else {
+ ASSERT(format == GL_STENCIL);
+ if (ctx->Extensions.EXT_packed_depth_stencil &&
+ ctx->Extensions.ARB_depth_texture &&
+ baseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* OK */
+ }
+ else {
+ /* no such thing as stencil-only textures */
+ att_incomplete("illegal stencil texture");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ }
+ }
+ else if (att->Type == GL_RENDERBUFFER_EXT) {
+ const GLenum baseFormat =
+ _mesa_get_format_base_format(att->Renderbuffer->Format);
+
+ ASSERT(att->Renderbuffer);
+ if (!att->Renderbuffer->InternalFormat ||
+ att->Renderbuffer->Width < 1 ||
+ att->Renderbuffer->Height < 1) {
+ att_incomplete("0x0 renderbuffer");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (format == GL_COLOR) {
+ if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
+ att_incomplete("bad renderbuffer color format");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ }
+ else if (format == GL_DEPTH) {
+ if (baseFormat == GL_DEPTH_COMPONENT) {
+ /* OK */
+ }
+ else if (ctx->Extensions.EXT_packed_depth_stencil &&
+ baseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* OK */
+ }
+ else {
+ att_incomplete("bad renderbuffer depth format");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ }
+ else {
+ assert(format == GL_STENCIL);
+ if (baseFormat == GL_STENCIL_INDEX) {
+ /* OK */
+ }
+ else if (ctx->Extensions.EXT_packed_depth_stencil &&
+ baseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* OK */
+ }
+ else {
+ att->Complete = GL_FALSE;
+ att_incomplete("bad renderbuffer stencil format");
+ return;
+ }
+ }
+ }
+ else {
+ ASSERT(att->Type == GL_NONE);
+ /* complete */
+ return;
+ }
+}
+
+
+/**
+ * Test if the given framebuffer object is complete and update its
+ * Status field with the results.
+ * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
+ * driver to make hardware-specific validation/completeness checks.
+ * Also update the framebuffer's Width and Height fields if the
+ * framebuffer is complete.
+ */
+void
+_mesa_test_framebuffer_completeness(struct gl_context *ctx,
+ struct gl_framebuffer *fb)
+{
+ GLuint numImages;
+ GLenum intFormat = GL_NONE; /* color buffers' internal format */
+ GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
+ GLint numSamples = -1;
+ GLint i;
+ GLuint j;
+
+ assert(fb->Name != 0);
+
+ numImages = 0;
+ fb->Width = 0;
+ fb->Height = 0;
+
+ /* Start at -2 to more easily loop over all attachment points.
+ * -2: depth buffer
+ * -1: stencil buffer
+ * >=0: color buffer
+ */
+ for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
+ struct gl_renderbuffer_attachment *att;
+ GLenum f;
+ gl_format attFormat;
+
+ /*
+ * XXX for ARB_fbo, only check color buffers that are named by
+ * GL_READ_BUFFER and GL_DRAW_BUFFERi.
+ */
+
+ /* check for attachment completeness
+ */
+ if (i == -2) {
+ att = &fb->Attachment[BUFFER_DEPTH];
+ test_attachment_completeness(ctx, GL_DEPTH, att);
+ if (!att->Complete) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fbo_incomplete("depth attachment incomplete", -1);
+ return;
+ }
+ }
+ else if (i == -1) {
+ att = &fb->Attachment[BUFFER_STENCIL];
+ test_attachment_completeness(ctx, GL_STENCIL, att);
+ if (!att->Complete) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fbo_incomplete("stencil attachment incomplete", -1);
+ return;
+ }
+ }
+ else {
+ att = &fb->Attachment[BUFFER_COLOR0 + i];
+ test_attachment_completeness(ctx, GL_COLOR, att);
+ if (!att->Complete) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fbo_incomplete("color attachment incomplete", i);
+ return;
+ }
+ }
+
+ /* get width, height, format of the renderbuffer/texture
+ */
+ if (att->Type == GL_TEXTURE) {
+ const struct gl_texture_image *texImg
+ = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ minWidth = MIN2(minWidth, texImg->Width);
+ maxWidth = MAX2(maxWidth, texImg->Width);
+ minHeight = MIN2(minHeight, texImg->Height);
+ maxHeight = MAX2(maxHeight, texImg->Height);
+ f = texImg->_BaseFormat;
+ attFormat = texImg->TexFormat;
+ numImages++;
+ if (!_mesa_is_legal_color_format(ctx, f) &&
+ !is_legal_depth_format(ctx, f)) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+ fbo_incomplete("texture attachment incomplete", -1);
+ return;
+ }
+ }
+ else if (att->Type == GL_RENDERBUFFER_EXT) {
+ minWidth = MIN2(minWidth, att->Renderbuffer->Width);
+ maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
+ minHeight = MIN2(minHeight, att->Renderbuffer->Height);
+ maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
+ f = att->Renderbuffer->InternalFormat;
+ attFormat = att->Renderbuffer->Format;
+ numImages++;
+ }
+ else {
+ assert(att->Type == GL_NONE);
+ continue;
+ }
+
+ if (numSamples < 0) {
+ /* first buffer */
+ numSamples = att->Renderbuffer->NumSamples;
+ }
+
+ /* check if integer color */
+ fb->_IntegerColor = _mesa_is_format_integer_color(attFormat);
+
+ /* Error-check width, height, format, samples
+ */
+ if (numImages == 1) {
+ /* save format, num samples */
+ if (i >= 0) {
+ intFormat = f;
+ }
+ }
+ else {
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ /* check that width, height, format are same */
+ if (minWidth != maxWidth || minHeight != maxHeight) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
+ fbo_incomplete("width or height mismatch", -1);
+ return;
+ }
+ /* check that all color buffer have same format */
+ if (intFormat != GL_NONE && f != intFormat) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+ fbo_incomplete("format mismatch", -1);
+ return;
+ }
+ }
+ if (att->Renderbuffer &&
+ att->Renderbuffer->NumSamples != numSamples) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete("inconsistant number of samples", i);
+ return;
+ }
+
+ }
+ }
+
+#if FEATURE_GL
+ if (ctx->API == API_OPENGL) {
+ /* Check that all DrawBuffers are present */
+ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
+ if (fb->ColorDrawBuffer[j] != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
+ fbo_incomplete("missing drawbuffer", j);
+ return;
+ }
+ }
+ }
+
+ /* Check that the ReadBuffer is present */
+ if (fb->ColorReadBuffer != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
+ fbo_incomplete("missing readbuffer", -1);
+ return;
+ }
+ }
+ }
+#else
+ (void) j;
+#endif
+
+ if (numImages == 0) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
+ fbo_incomplete("no attachments", -1);
+ return;
+ }
+
+ /* Provisionally set status = COMPLETE ... */
+ fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
+
+ /* ... but the driver may say the FB is incomplete.
+ * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
+ * if anything.
+ */
+ if (ctx->Driver.ValidateFramebuffer) {
+ ctx->Driver.ValidateFramebuffer(ctx, fb);
+ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ fbo_incomplete("driver marked FBO as incomplete", -1);
+ }
+ }
+
+ if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
+ /*
+ * Note that if ARB_framebuffer_object is supported and the attached
+ * renderbuffers/textures are different sizes, the framebuffer
+ * width/height will be set to the smallest width/height.
+ */
+ fb->Width = minWidth;
+ fb->Height = minHeight;
+
+ /* finally, update the visual info for the framebuffer */
+ _mesa_update_framebuffer_visual(ctx, fb);
+ }
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsRenderbufferEXT(GLuint renderbuffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+ if (renderbuffer) {
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (rb != NULL && rb != &DummyRenderbuffer)
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
+{
+ struct gl_renderbuffer *newRb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
+ return;
+ }
+
+ /* No need to flush here since the render buffer binding has no
+ * effect on rendering state.
+ */
+
+ if (renderbuffer) {
+ newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (newRb == &DummyRenderbuffer) {
+ /* ID was reserved, but no real renderbuffer object made yet */
+ newRb = NULL;
+ }
+ else if (!newRb && ctx->Extensions.ARB_framebuffer_object) {
+ /* All RB IDs must be Gen'd */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
+ return;
+ }
+
+ if (!newRb) {
+ /* create new renderbuffer object */
+ newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
+ if (!newRb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
+ return;
+ }
+ ASSERT(newRb->AllocStorage);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
+ newRb->RefCount = 1; /* referenced by hash table */
+ }
+ }
+ else {
+ newRb = NULL;
+ }
+
+ ASSERT(newRb != &DummyRenderbuffer);
+
+ _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
+}
+
+
+/**
+ * If the given renderbuffer is anywhere attached to the framebuffer, detach
+ * the renderbuffer.
+ * This is used when a renderbuffer object is deleted.
+ * The spec calls for unbinding.
+ */
+static void
+detach_renderbuffer(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer *rb)
+{
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (fb->Attachment[i].Renderbuffer == rb) {
+ _mesa_remove_attachment(ctx, &fb->Attachment[i]);
+ }
+ }
+ invalidate_framebuffer(fb);
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ for (i = 0; i < n; i++) {
+ if (renderbuffers[i] > 0) {
+ struct gl_renderbuffer *rb;
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
+ if (rb) {
+ /* check if deleting currently bound renderbuffer object */
+ if (rb == ctx->CurrentRenderbuffer) {
+ /* bind default */
+ ASSERT(rb->RefCount >= 2);
+ _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ }
+
+ if (ctx->DrawBuffer->Name) {
+ detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
+ }
+ if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) {
+ detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
+ }
+
+ /* Remove from hash table immediately, to free the ID.
+ * But the object will not be freed until it's no longer
+ * referenced anywhere else.
+ */
+ _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
+
+ if (rb != &DummyRenderbuffer) {
+ /* no longer referenced by hash table */
+ _mesa_reference_renderbuffer(&rb, NULL);
+ }
+ }
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint first;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
+ return;
+ }
+
+ if (!renderbuffers)
+ return;
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
+
+ for (i = 0; i < n; i++) {
+ GLuint name = first + i;
+ renderbuffers[i] = name;
+ /* insert dummy placeholder into hash table */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+}
+
+
+/**
+ * Given an internal format token for a render buffer, return the
+ * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
+ * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
+ * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
+ *
+ * This is similar to _mesa_base_tex_format() but the set of valid
+ * internal formats is different.
+ *
+ * Note that even if a format is determined to be legal here, validation
+ * of the FBO may fail if the format is not supported by the driver/GPU.
+ *
+ * \param internalFormat as passed to glRenderbufferStorage()
+ * \return the base internal format, or 0 if internalFormat is illegal
+ */
+GLenum
+_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
+{
+ /*
+ * Notes: some formats such as alpha, luminance, etc. were added
+ * with GL_ARB_framebuffer_object.
+ */
+ switch (internalFormat) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ case GL_SRGB8_EXT:
+ return GL_RGB;
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ case GL_RGBA16_SNORM:
+ case GL_SRGB8_ALPHA8_EXT:
+ return GL_RGBA;
+ case GL_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ case GL_STENCIL_INDEX16_EXT:
+ return GL_STENCIL_INDEX;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return GL_DEPTH_COMPONENT;
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ if (ctx->Extensions.EXT_packed_depth_stencil)
+ return GL_DEPTH_STENCIL_EXT;
+ else
+ return 0;
+ case GL_RED:
+ case GL_R8:
+ case GL_R16:
+ return ctx->Extensions.ARB_texture_rg ? GL_RED : 0;
+ case GL_RG:
+ case GL_RG8:
+ case GL_RG16:
+ return ctx->Extensions.ARB_texture_rg ? GL_RG : 0;
+ /* XXX add floating point and integer formats eventually */
+ default:
+ return 0;
+ }
+}
+
+
+/** sentinal value, see below */
+#define NO_SAMPLES 1000
+
+
+/**
+ * Helper function used by _mesa_RenderbufferStorageEXT() and
+ * _mesa_RenderbufferStorageMultisample().
+ * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT().
+ */
+static void
+renderbuffer_storage(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei samples)
+{
+ const char *func = samples == NO_SAMPLES ?
+ "glRenderbufferStorage" : "RenderbufferStorageMultisample";
+ struct gl_renderbuffer *rb;
+ GLenum baseFormat;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
+ return;
+ }
+
+ baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
+ if (baseFormat == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
+ return;
+ }
+
+ if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
+ return;
+ }
+
+ if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
+ return;
+ }
+
+ if (samples == NO_SAMPLES) {
+ /* NumSamples == 0 indicates non-multisampling */
+ samples = 0;
+ }
+ else if (samples > (GLsizei) ctx->Const.MaxSamples) {
+ /* note: driver may choose to use more samples than what's requested */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
+ return;
+ }
+
+ rb = ctx->CurrentRenderbuffer;
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ if (rb->InternalFormat == internalFormat &&
+ rb->Width == (GLuint) width &&
+ rb->Height == (GLuint) height) {
+ /* no change in allocation needed */
+ return;
+ }
+
+ /* These MUST get set by the AllocStorage func */
+ rb->Format = MESA_FORMAT_NONE;
+ rb->NumSamples = samples;
+
+ /* Now allocate the storage */
+ ASSERT(rb->AllocStorage);
+ if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
+ /* No error - check/set fields now */
+ assert(rb->Format != MESA_FORMAT_NONE);
+ assert(rb->Width == (GLuint) width);
+ assert(rb->Height == (GLuint) height);
+ rb->InternalFormat = internalFormat;
+ rb->_BaseFormat = baseFormat;
+ assert(rb->_BaseFormat != 0);
+ }
+ else {
+ /* Probably ran out of memory - clear the fields */
+ rb->Width = 0;
+ rb->Height = 0;
+ rb->Format = MESA_FORMAT_NONE;
+ rb->InternalFormat = GL_NONE;
+ rb->_BaseFormat = GL_NONE;
+ rb->NumSamples = 0;
+ }
+
+ /*
+ test_framebuffer_completeness(ctx, fb);
+ */
+ /* XXX if this renderbuffer is attached anywhere, invalidate attachment
+ * points???
+ */
+}
+
+
+#if FEATURE_OES_EGL_image
+void GLAPIENTRY
+_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+ struct gl_renderbuffer *rb;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.OES_EGL_image) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEGLImageTargetRenderbufferStorageOES(unsupported)");
+ return;
+ }
+
+ if (target != GL_RENDERBUFFER) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "EGLImageTargetRenderbufferStorageOES");
+ return;
+ }
+
+ rb = ctx->CurrentRenderbuffer;
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "EGLImageTargetRenderbufferStorageOES");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
+}
+#endif
+
+
+/**
+ * Helper function for _mesa_GetRenderbufferParameterivEXT() and
+ * _mesa_GetFramebufferAttachmentParameterivEXT()
+ * We have to be careful to respect the base format. For example, if a
+ * renderbuffer/texture was created with internalFormat=GL_RGB but the
+ * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
+ * we need to return zero.
+ */
+static GLint
+get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
+{
+ switch (pname) {
+ case GL_RENDERBUFFER_RED_SIZE_EXT:
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ if (baseFormat == GL_RGB || baseFormat == GL_RGBA ||
+ baseFormat == GL_RG || baseFormat == GL_RED)
+ return _mesa_get_format_bits(format, pname);
+ else
+ return 0;
+ case GL_RENDERBUFFER_GREEN_SIZE_EXT:
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ if (baseFormat == GL_RGB || baseFormat == GL_RGBA || baseFormat == GL_RG)
+ return _mesa_get_format_bits(format, pname);
+ else
+ return 0;
+ case GL_RENDERBUFFER_BLUE_SIZE_EXT:
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ if (baseFormat == GL_RGB || baseFormat == GL_RGBA)
+ return _mesa_get_format_bits(format, pname);
+ else
+ return 0;
+ case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA ||
+ baseFormat == GL_LUMINANCE_ALPHA)
+ return _mesa_get_format_bits(format, pname);
+ else
+ return 0;
+ case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL)
+ return _mesa_get_format_bits(format, pname);
+ else
+ return 0;
+ case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ if (baseFormat == GL_STENCIL_INDEX || baseFormat == GL_DEPTH_STENCIL)
+ return _mesa_get_format_bits(format, pname);
+ else
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
+
+void GLAPIENTRY
+_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ /* GL_ARB_fbo says calling this function is equivalent to calling
+ * glRenderbufferStorageMultisample() with samples=0. We pass in
+ * a token value here just for error reporting purposes.
+ */
+ renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
+}
+
+
+void GLAPIENTRY
+_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ renderbuffer_storage(target, internalFormat, width, height, samples);
+}
+
+
+/**
+ * OpenGL ES version of glRenderBufferStorage.
+ */
+void GLAPIENTRY
+_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ switch (internalFormat) {
+ case GL_RGB565:
+ /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
+ /* choose a closest format */
+ internalFormat = GL_RGB5;
+ break;
+ default:
+ break;
+ }
+
+ renderbuffer_storage(target, internalFormat, width, height, 0);
+}
+
+
+void GLAPIENTRY
+_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
+{
+ struct gl_renderbuffer *rb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetRenderbufferParameterivEXT(target)");
+ return;
+ }
+
+ rb = ctx->CurrentRenderbuffer;
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetRenderbufferParameterivEXT");
+ return;
+ }
+
+ /* No need to flush here since we're just quering state which is
+ * not effected by rendering.
+ */
+
+ switch (pname) {
+ case GL_RENDERBUFFER_WIDTH_EXT:
+ *params = rb->Width;
+ return;
+ case GL_RENDERBUFFER_HEIGHT_EXT:
+ *params = rb->Height;
+ return;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
+ *params = rb->InternalFormat;
+ return;
+ case GL_RENDERBUFFER_RED_SIZE_EXT:
+ case GL_RENDERBUFFER_GREEN_SIZE_EXT:
+ case GL_RENDERBUFFER_BLUE_SIZE_EXT:
+ case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
+ case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
+ case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
+ *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
+ break;
+ case GL_RENDERBUFFER_SAMPLES:
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ *params = rb->NumSamples;
+ break;
+ }
+ /* fallthrough */
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetRenderbufferParameterivEXT(target)");
+ return;
+ }
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsFramebufferEXT(GLuint framebuffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+ if (framebuffer) {
+ struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
+ if (rb != NULL && rb != &DummyFramebuffer)
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Check if any of the attachments of the given framebuffer are textures
+ * (render to texture). Call ctx->Driver.RenderTexture() for such
+ * attachments.
+ */
+static void
+check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
+{
+ GLuint i;
+ ASSERT(ctx->Driver.RenderTexture);
+
+ if (fb->Name == 0)
+ return; /* can't render to texture with winsys framebuffers */
+
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ struct gl_texture_object *texObj = att->Texture;
+ if (texObj
+ && texObj->Image[att->CubeMapFace][att->TextureLevel]) {
+ ctx->Driver.RenderTexture(ctx, fb, att);
+ }
+ }
+}
+
+
+/**
+ * Examine all the framebuffer's attachments to see if any are textures.
+ * If so, call ctx->Driver.FinishRenderTexture() for each texture to
+ * notify the device driver that the texture image may have changed.
+ */
+static void
+check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
+{
+ if (fb->Name == 0)
+ return; /* can't render to texture with winsys framebuffers */
+
+ if (ctx->Driver.FinishRenderTexture) {
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ if (att->Texture && att->Renderbuffer) {
+ ctx->Driver.FinishRenderTexture(ctx, att);
+ }
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
+{
+ struct gl_framebuffer *newDrawFb, *newReadFb;
+ struct gl_framebuffer *oldDrawFb, *oldReadFb;
+ GLboolean bindReadBuf, bindDrawBuf;
+ GET_CURRENT_CONTEXT(ctx);
+
+#ifdef DEBUG
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ ASSERT(ctx->Extensions.EXT_framebuffer_object);
+ ASSERT(ctx->Extensions.EXT_framebuffer_blit);
+ }
+#endif
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindFramebufferEXT(unsupported)");
+ return;
+ }
+
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+ bindDrawBuf = GL_TRUE;
+ bindReadBuf = GL_FALSE;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+ bindDrawBuf = GL_FALSE;
+ bindReadBuf = GL_TRUE;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ bindDrawBuf = GL_TRUE;
+ bindReadBuf = GL_TRUE;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+
+ if (framebuffer) {
+ /* Binding a user-created framebuffer object */
+ newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
+ if (newDrawFb == &DummyFramebuffer) {
+ /* ID was reserved, but no real framebuffer object made yet */
+ newDrawFb = NULL;
+ }
+ else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) {
+ /* All FBO IDs must be Gen'd */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
+ return;
+ }
+
+ if (!newDrawFb) {
+ /* create new framebuffer object */
+ newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
+ if (!newDrawFb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
+ }
+ newReadFb = newDrawFb;
+ }
+ else {
+ /* Binding the window system framebuffer (which was originally set
+ * with MakeCurrent).
+ */
+ newDrawFb = ctx->WinSysDrawBuffer;
+ newReadFb = ctx->WinSysReadBuffer;
+ }
+
+ ASSERT(newDrawFb);
+ ASSERT(newDrawFb != &DummyFramebuffer);
+
+ /* save pointers to current/old framebuffers */
+ oldDrawFb = ctx->DrawBuffer;
+ oldReadFb = ctx->ReadBuffer;
+
+ /* check if really changing bindings */
+ if (oldDrawFb == newDrawFb)
+ bindDrawBuf = GL_FALSE;
+ if (oldReadFb == newReadFb)
+ bindReadBuf = GL_FALSE;
+
+ /*
+ * OK, now bind the new Draw/Read framebuffers, if they're changing.
+ *
+ * We also check if we're beginning and/or ending render-to-texture.
+ * When a framebuffer with texture attachments is unbound, call
+ * ctx->Driver.FinishRenderTexture().
+ * When a framebuffer with texture attachments is bound, call
+ * ctx->Driver.RenderTexture().
+ *
+ * Note that if the ReadBuffer has texture attachments we don't consider
+ * that a render-to-texture case.
+ */
+ if (bindReadBuf) {
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ /* check if old readbuffer was render-to-texture */
+ check_end_texture_render(ctx, oldReadFb);
+
+ _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
+ }
+
+ if (bindDrawBuf) {
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ /* check if old read/draw buffers were render-to-texture */
+ if (!bindReadBuf)
+ check_end_texture_render(ctx, oldReadFb);
+
+ if (oldDrawFb != oldReadFb)
+ check_end_texture_render(ctx, oldDrawFb);
+
+ /* check if newly bound framebuffer has any texture attachments */
+ check_begin_texture_render(ctx, newDrawFb);
+
+ _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
+ }
+
+ if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
+ ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ for (i = 0; i < n; i++) {
+ if (framebuffers[i] > 0) {
+ struct gl_framebuffer *fb;
+ fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
+ if (fb) {
+ ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
+
+ /* check if deleting currently bound framebuffer object */
+ if (ctx->Extensions.EXT_framebuffer_blit) {
+ /* separate draw/read binding points */
+ if (fb == ctx->DrawBuffer) {
+ /* bind default */
+ ASSERT(fb->RefCount >= 2);
+ _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ }
+ if (fb == ctx->ReadBuffer) {
+ /* bind default */
+ ASSERT(fb->RefCount >= 2);
+ _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
+ }
+ }
+ else {
+ /* only one binding point for read/draw buffers */
+ if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
+ /* bind default */
+ ASSERT(fb->RefCount >= 2);
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+ }
+
+ /* remove from hash table immediately, to free the ID */
+ _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
+
+ if (fb != &DummyFramebuffer) {
+ /* But the object will not be freed until it's no longer
+ * bound in any context.
+ */
+ _mesa_reference_framebuffer(&fb, NULL);
+ }
+ }
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint first;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
+ return;
+ }
+
+ if (!framebuffers)
+ return;
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
+
+ for (i = 0; i < n; i++) {
+ GLuint name = first + i;
+ framebuffers[i] = name;
+ /* insert dummy placeholder into hash table */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+}
+
+
+
+GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatusEXT(GLenum target)
+{
+ struct gl_framebuffer *buffer;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+ buffer = get_framebuffer_target(ctx, target);
+ if (!buffer) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+ return 0;
+ }
+
+ if (buffer->Name == 0) {
+ /* The window system / default framebuffer is always complete */
+ return GL_FRAMEBUFFER_COMPLETE_EXT;
+ }
+
+ /* No need to flush here */
+
+ if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
+ _mesa_test_framebuffer_completeness(ctx, buffer);
+ }
+
+ return buffer->_Status;
+}
+
+
+
+/**
+ * Common code called by glFramebufferTexture1D/2D/3DEXT().
+ */
+static void
+framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
+ GLenum attachment, GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset)
+{
+ struct gl_renderbuffer_attachment *att;
+ struct gl_texture_object *texObj = NULL;
+ struct gl_framebuffer *fb;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
+ return;
+ }
+
+ /* check framebuffer binding */
+ if (fb->Name == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture%sEXT", caller);
+ return;
+ }
+
+
+ /* The textarget, level, and zoffset parameters are only validated if
+ * texture is non-zero.
+ */
+ if (texture) {
+ GLboolean err = GL_TRUE;
+
+ texObj = _mesa_lookup_texture(ctx, texture);
+ if (texObj != NULL) {
+ if (textarget == 0) {
+ /* XXX what's the purpose of this? */
+ err = (texObj->Target != GL_TEXTURE_3D) &&
+ (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
+ (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT);
+ }
+ else {
+ err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
+ ? !IS_CUBE_FACE(textarget)
+ : (texObj->Target != textarget);
+ }
+ }
+ else {
+ /* can't render to a non-existant texture */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture%sEXT(non existant texture)",
+ caller);
+ return;
+ }
+
+ if (err) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture%sEXT(texture target mismatch)",
+ caller);
+ return;
+ }
+
+ if (texObj->Target == GL_TEXTURE_3D) {
+ const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ if (zoffset < 0 || zoffset >= maxSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glFramebufferTexture%sEXT(zoffset)", caller);
+ return;
+ }
+ }
+ else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
+ (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
+ if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glFramebufferTexture%sEXT(layer)", caller);
+ return;
+ }
+ }
+
+ if ((level < 0) ||
+ (level >= _mesa_max_texture_levels(ctx, texObj->Target))) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glFramebufferTexture%sEXT(level)", caller);
+ return;
+ }
+ }
+
+ att = _mesa_get_attachment(ctx, fb, attachment);
+ if (att == NULL) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture%sEXT(attachment)", caller);
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ _glthread_LOCK_MUTEX(fb->Mutex);
+ if (texObj) {
+ _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
+ level, zoffset);
+ /* Set the render-to-texture flag. We'll check this flag in
+ * glTexImage() and friends to determine if we need to revalidate
+ * any FBOs that might be rendering into this texture.
+ * This flag never gets cleared since it's non-trivial to determine
+ * when all FBOs might be done rendering to this texture. That's OK
+ * though since it's uncommon to render to a texture then repeatedly
+ * call glTexImage() to change images in the texture.
+ */
+ texObj->_RenderToTexture = GL_TRUE;
+ }
+ else {
+ _mesa_remove_attachment(ctx, att);
+ }
+
+ invalidate_framebuffer(fb);
+
+ _glthread_UNLOCK_MUTEX(fb->Mutex);
+}
+
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((texture != 0) && (textarget != GL_TEXTURE_1D)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture1DEXT(textarget)");
+ return;
+ }
+
+ framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
+ level, 0);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((texture != 0) &&
+ (textarget != GL_TEXTURE_2D) &&
+ (textarget != GL_TEXTURE_RECTANGLE_ARB) &&
+ (!IS_CUBE_FACE(textarget))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture2DEXT(textarget=0x%x)", textarget);
+ return;
+ }
+
+ framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
+ level, 0);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture3DEXT(textarget)");
+ return;
+ }
+
+ framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
+ level, zoffset);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
+ level, layer);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
+ GLenum renderbufferTarget,
+ GLuint renderbuffer)
+{
+ struct gl_renderbuffer_attachment *att;
+ struct gl_framebuffer *fb;
+ struct gl_renderbuffer *rb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
+ return;
+ }
+
+ if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(renderbufferTarget)");
+ return;
+ }
+
+ if (fb->Name == 0) {
+ /* Can't attach new renderbuffers to a window system framebuffer */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
+ return;
+ }
+
+ att = _mesa_get_attachment(ctx, fb, attachment);
+ if (att == NULL) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(invalid attachment %s)",
+ _mesa_lookup_enum_by_nr(attachment));
+ return;
+ }
+
+ if (renderbuffer) {
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbufferEXT(non-existant"
+ " renderbuffer %u)", renderbuffer);
+ return;
+ }
+ else if (rb == &DummyRenderbuffer) {
+ /* This is what NVIDIA does */
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glFramebufferRenderbufferEXT(renderbuffer %u)",
+ renderbuffer);
+ return;
+ }
+ }
+ else {
+ /* remove renderbuffer attachment */
+ rb = NULL;
+ }
+
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
+ rb && rb->Format != MESA_FORMAT_NONE) {
+ /* make sure the renderbuffer is a depth/stencil format */
+ const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
+ if (baseFormat != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbufferEXT(renderbuffer"
+ " is not DEPTH_STENCIL format)");
+ return;
+ }
+ }
+
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ assert(ctx->Driver.FramebufferRenderbuffer);
+ ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
+
+ /* Some subsequent GL commands may depend on the framebuffer's visual
+ * after the binding is updated. Update visual info now.
+ */
+ _mesa_update_framebuffer_visual(ctx, fb);
+}
+
+
+void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ const struct gl_renderbuffer_attachment *att;
+ struct gl_framebuffer *buffer;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ buffer = get_framebuffer_target(ctx, target);
+ if (!buffer) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(target)");
+ return;
+ }
+
+ if (buffer->Name == 0) {
+ /* the default / window-system FBO */
+ att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
+ }
+ else {
+ /* user-created framebuffer FBO */
+ att = _mesa_get_attachment(ctx, buffer, attachment);
+ }
+
+ if (att == NULL) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(attachment)");
+ return;
+ }
+
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* the depth and stencil attachments must point to the same buffer */
+ const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
+ depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
+ stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
+ if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
+ " attachments differ)");
+ return;
+ }
+ }
+
+ /* No need to flush here */
+
+ switch (pname) {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
+ *params = buffer->Name == 0 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
+ if (att->Type == GL_RENDERBUFFER_EXT) {
+ *params = att->Renderbuffer->Name;
+ }
+ else if (att->Type == GL_TEXTURE) {
+ *params = att->Texture->Name;
+ }
+ else {
+ assert(att->Type == GL_NONE);
+ *params = 0;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
+ if (att->Type == GL_TEXTURE) {
+ *params = att->TextureLevel;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
+ if (att->Type == GL_TEXTURE) {
+ if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
+ *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
+ }
+ else {
+ *params = 0;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
+ if (att->Type == GL_TEXTURE) {
+ if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
+ *params = att->Zoffset;
+ }
+ else {
+ *params = 0;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) {
+ *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
+ }
+ else {
+ /* According to ARB_framebuffer_sRGB, we should return LINEAR
+ * if the sRGB conversion is unsupported. */
+ *params = GL_LINEAR;
+ }
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ return;
+ }
+ else {
+ gl_format format = att->Renderbuffer->Format;
+ if (format == MESA_FORMAT_CI8 || format == MESA_FORMAT_S8) {
+ /* special cases */
+ *params = GL_INDEX;
+ }
+ else {
+ *params = _mesa_get_format_datatype(format);
+ }
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else if (att->Texture) {
+ const struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
+ att->TextureLevel);
+ if (texImage) {
+ *params = get_component_bits(pname, texImage->_BaseFormat,
+ texImage->TexFormat);
+ }
+ else {
+ *params = 0;
+ }
+ }
+ else if (att->Renderbuffer) {
+ *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
+ att->Renderbuffer->Format);
+ }
+ else {
+ *params = 0;
+ }
+ return;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GenerateMipmapEXT(GLenum target)
+{
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ /* OK, legal value */
+ break;
+ default:
+ /* XXX need to implement GL_TEXTURE_1D_ARRAY and GL_TEXTURE_2D_ARRAY */
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ if (texObj->BaseLevel >= texObj->MaxLevel) {
+ /* nothing to do */
+ return;
+ }
+
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
+ !_mesa_cube_complete(texObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGenerateMipmap(incomplete cube map)");
+ return;
+ }
+
+ _mesa_lock_texture(ctx, texObj);
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ GLuint face;
+ for (face = 0; face < 6; face++)
+ ctx->Driver.GenerateMipmap(ctx,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
+ texObj);
+ }
+ else {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+#if FEATURE_EXT_framebuffer_blit
+
+static const struct gl_renderbuffer_attachment *
+find_attachment(const struct gl_framebuffer *fb,
+ const struct gl_renderbuffer *rb)
+{
+ GLuint i;
+ for (i = 0; i < Elements(fb->Attachment); i++) {
+ if (fb->Attachment[i].Renderbuffer == rb)
+ return &fb->Attachment[i];
+ }
+ return NULL;
+}
+
+
+
+/**
+ * Blit rectangular region, optionally from one framebuffer to another.
+ *
+ * Note, if the src buffer is multisampled and the dest is not, this is
+ * when the samples must be resolved to a single color.
+ */
+void GLAPIENTRY
+_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
+ GL_DEPTH_BUFFER_BIT |
+ GL_STENCIL_BUFFER_BIT);
+ const struct gl_framebuffer *readFb, *drawFb;
+ const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, _mesa_lookup_enum_by_nr(filter));
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ readFb = ctx->ReadBuffer;
+ drawFb = ctx->DrawBuffer;
+
+ if (!readFb || !drawFb) {
+ /* This will normally never happen but someday we may want to
+ * support MakeCurrent() with no drawables.
+ */
+ return;
+ }
+
+ /* check for complete framebuffers */
+ if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+ readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glBlitFramebufferEXT(incomplete draw/read buffers)");
+ return;
+ }
+
+ if (filter != GL_NEAREST && filter != GL_LINEAR) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
+ return;
+ }
+
+ if (mask & ~legalMaskBits) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
+ return;
+ }
+
+ /* depth/stencil must be blitted with nearest filtering */
+ if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+ && filter != GL_NEAREST) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter");
+ return;
+ }
+
+ /* get color read/draw renderbuffers */
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ colorReadRb = readFb->_ColorReadBuffer;
+ colorDrawRb = drawFb->_ColorDrawBuffers[0];
+ }
+ else {
+ colorReadRb = colorDrawRb = NULL;
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ struct gl_renderbuffer *readRb = readFb->_StencilBuffer;
+ struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer;
+ if (!readRb ||
+ !drawRb ||
+ _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
+ _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(stencil buffer size mismatch");
+ return;
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ struct gl_renderbuffer *readRb = readFb->_DepthBuffer;
+ struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer;
+ if (!readRb ||
+ !drawRb ||
+ _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
+ _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(depth buffer size mismatch");
+ return;
+ }
+ }
+
+ if (readFb->Visual.samples > 0 &&
+ drawFb->Visual.samples > 0 &&
+ readFb->Visual.samples != drawFb->Visual.samples) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(mismatched samples");
+ return;
+ }
+
+ /* extra checks for multisample copies... */
+ if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
+ /* src and dest region sizes must be the same */
+ if (srcX1 - srcX0 != dstX1 - dstX0 ||
+ srcY1 - srcY0 != dstY1 - dstY0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(bad src/dst multisample region sizes");
+ return;
+ }
+
+ /* color formats must match */
+ if (colorReadRb &&
+ colorDrawRb &&
+ colorReadRb->Format != colorDrawRb->Format) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(bad src/dst multisample pixel formats");
+ return;
+ }
+ }
+
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
+ return;
+ }
+
+ /* Debug code */
+ if (DEBUG_BLIT) {
+ printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
+ " 0x%x, 0x%x)\n",
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+ if (colorReadRb) {
+ const struct gl_renderbuffer_attachment *att;
+
+ att = find_attachment(readFb, colorReadRb);
+ printf(" Src FBO %u RB %u (%dx%d) ",
+ readFb->Name, colorReadRb->Name,
+ colorReadRb->Width, colorReadRb->Height);
+ if (att && att->Texture) {
+ printf("Tex %u tgt 0x%x level %u face %u",
+ att->Texture->Name,
+ att->Texture->Target,
+ att->TextureLevel,
+ att->CubeMapFace);
+ }
+ printf("\n");
+
+ att = find_attachment(drawFb, colorDrawRb);
+ printf(" Dst FBO %u RB %u (%dx%d) ",
+ drawFb->Name, colorDrawRb->Name,
+ colorDrawRb->Width, colorDrawRb->Height);
+ if (att && att->Texture) {
+ printf("Tex %u tgt 0x%x level %u face %u",
+ att->Texture->Name,
+ att->Texture->Target,
+ att->TextureLevel,
+ att->CubeMapFace);
+ }
+ printf("\n");
+ }
+ }
+
+ ASSERT(ctx->Driver.BlitFramebuffer);
+ ctx->Driver.BlitFramebuffer(ctx,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+}
+#endif /* FEATURE_EXT_framebuffer_blit */
+
+#if FEATURE_ARB_geometry_shader4
+void GLAPIENTRY
+_mesa_FramebufferTextureARB(GLenum target, GLenum attachment,
+ GLuint texture, GLint level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTextureARB "
+ "not implemented!");
+}
+
+void GLAPIENTRY
+_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLenum face)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTextureFaceARB "
+ "not implemented!");
+}
+#endif /* FEATURE_ARB_geometry_shader4 */
diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c
index 948b3b7b5..227b214a5 100644
--- a/mesalib/src/mesa/main/framebuffer.c
+++ b/mesalib/src/mesa/main/framebuffer.c
@@ -794,15 +794,12 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
_mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
ctx->Color.DrawBuffer, NULL);
}
- if (fb->ColorReadBuffer != ctx->Pixel.ReadBuffer) {
-
- }
}
else {
/* This is a user-created framebuffer.
* Completeness only matters for user-created framebuffers.
*/
- if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
+ if (fb->_Status == 0) {
_mesa_test_framebuffer_completeness(ctx, fb);
}
}
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 3e5ddfcfd..336304c59 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -1,2533 +1,2527 @@
-/*
- * Copyright (C) 2010 Brian Paul All Rights Reserved.
- * Copyright (C) 2010 Intel Corporation
- *
- * 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.
- *
- * Author: Kristian Høgsberg <krh@bitplanet.net>
- */
-
-#include "glheader.h"
-#include "context.h"
-#include "enable.h"
-#include "enums.h"
-#include "extensions.h"
-#include "get.h"
-#include "macros.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "state.h"
-#include "texcompress.h"
-#include "framebuffer.h"
-
-/* This is a table driven implemetation of the glGet*v() functions.
- * The basic idea is that most getters just look up an int somewhere
- * in struct gl_context and then convert it to a bool or float according to
- * which of glGetIntegerv() glGetBooleanv() etc is being called.
- * Instead of generating code to do this, we can just record the enum
- * value and the offset into struct gl_context in an array of structs. Then
- * in glGet*(), we lookup the struct for the enum in question, and use
- * the offset to get the int we need.
- *
- * Sometimes we need to look up a float, a boolean, a bit in a
- * bitfield, a matrix or other types instead, so we need to track the
- * type of the value in struct gl_context. And sometimes the value isn't in
- * struct gl_context but in the drawbuffer, the array object, current texture
- * unit, or maybe it's a computed value. So we need to also track
- * where or how to find the value. Finally, we sometimes need to
- * check that one of a number of extensions are enabled, the GL
- * version or flush or call _mesa_update_state(). This is done by
- * attaching optional extra information to the value description
- * struct, it's sort of like an array of opcodes that describe extra
- * checks or actions.
- *
- * Putting all this together we end up with struct value_desc below,
- * and with a couple of macros to help, the table of struct value_desc
- * is about as concise as the specification in the old python script.
- */
-
-#undef CONST
-
-#define FLOAT_TO_BOOLEAN(X) ( (X) ? GL_TRUE : GL_FALSE )
-#define FLOAT_TO_FIXED(F) ( ((F) * 65536.0f > INT_MAX) ? INT_MAX : \
- ((F) * 65536.0f < INT_MIN) ? INT_MIN : \
- (GLint) ((F) * 65536.0f) )
-
-#define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
-#define INT_TO_FIXED(I) ( ((I) > SHRT_MAX) ? INT_MAX : \
- ((I) < SHRT_MIN) ? INT_MIN : \
- (GLint) ((I) * 65536) )
-
-#define INT64_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
-#define INT64_TO_INT(I) ( (GLint)((I > INT_MAX) ? INT_MAX : ((I < INT_MIN) ? INT_MIN : (I))) )
-
-#define BOOLEAN_TO_INT(B) ( (GLint) (B) )
-#define BOOLEAN_TO_INT64(B) ( (GLint64) (B) )
-#define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F )
-#define BOOLEAN_TO_FIXED(B) ( (GLint) ((B) ? 1 : 0) << 16 )
-
-#define ENUM_TO_INT64(E) ( (GLint64) (E) )
-#define ENUM_TO_FIXED(E) (E)
-
-enum value_type {
- TYPE_INVALID,
- TYPE_API_MASK,
- TYPE_INT,
- TYPE_INT_2,
- TYPE_INT_3,
- TYPE_INT_4,
- TYPE_INT_N,
- TYPE_INT64,
- TYPE_ENUM,
- TYPE_ENUM_2,
- TYPE_BOOLEAN,
- TYPE_BIT_0,
- TYPE_BIT_1,
- TYPE_BIT_2,
- TYPE_BIT_3,
- TYPE_BIT_4,
- TYPE_BIT_5,
- TYPE_FLOAT,
- TYPE_FLOAT_2,
- TYPE_FLOAT_3,
- TYPE_FLOAT_4,
- TYPE_FLOATN,
- TYPE_FLOATN_2,
- TYPE_FLOATN_3,
- TYPE_FLOATN_4,
- TYPE_DOUBLEN,
- TYPE_MATRIX,
- TYPE_MATRIX_T,
- TYPE_CONST
-};
-
-enum value_location {
- LOC_BUFFER,
- LOC_CONTEXT,
- LOC_ARRAY,
- LOC_TEXUNIT,
- LOC_CUSTOM
-};
-
-enum value_extra {
- EXTRA_END = 0x8000,
- EXTRA_VERSION_30,
- EXTRA_VERSION_31,
- EXTRA_VERSION_32,
- EXTRA_VERSION_ES2,
- EXTRA_NEW_BUFFERS,
- EXTRA_VALID_DRAW_BUFFER,
- EXTRA_VALID_TEXTURE_UNIT,
- EXTRA_FLUSH_CURRENT,
-};
-
-#define NO_EXTRA NULL
-#define NO_OFFSET 0
-
-struct value_desc {
- GLenum pname;
- GLubyte location; /**< enum value_location */
- GLubyte type; /**< enum value_type */
- int offset;
- const int *extra;
-};
-
-union value {
- GLfloat value_float;
- GLfloat value_float_4[4];
- GLmatrix *value_matrix;
- GLint value_int;
- GLint value_int_4[4];
- GLint64 value_int64;
- GLenum value_enum;
-
- /* Sigh, see GL_COMPRESSED_TEXTURE_FORMATS_ARB handling */
- struct {
- GLint n, ints[100];
- } value_int_n;
- GLboolean value_bool;
-};
-
-#define BUFFER_FIELD(field, type) \
- LOC_BUFFER, type, offsetof(struct gl_framebuffer, field)
-#define CONTEXT_FIELD(field, type) \
- LOC_CONTEXT, type, offsetof(struct gl_context, field)
-#define ARRAY_FIELD(field, type) \
- LOC_ARRAY, type, offsetof(struct gl_array_object, field)
-#define CONST(value) \
- LOC_CONTEXT, TYPE_CONST, value
-
-#define BUFFER_INT(field) BUFFER_FIELD(field, TYPE_INT)
-#define BUFFER_ENUM(field) BUFFER_FIELD(field, TYPE_ENUM)
-#define BUFFER_BOOL(field) BUFFER_FIELD(field, TYPE_BOOLEAN)
-
-#define CONTEXT_INT(field) CONTEXT_FIELD(field, TYPE_INT)
-#define CONTEXT_INT2(field) CONTEXT_FIELD(field, TYPE_INT_2)
-#define CONTEXT_INT64(field) CONTEXT_FIELD(field, TYPE_INT64)
-#define CONTEXT_ENUM(field) CONTEXT_FIELD(field, TYPE_ENUM)
-#define CONTEXT_ENUM2(field) CONTEXT_FIELD(field, TYPE_ENUM_2)
-#define CONTEXT_BOOL(field) CONTEXT_FIELD(field, TYPE_BOOLEAN)
-#define CONTEXT_BIT0(field) CONTEXT_FIELD(field, TYPE_BIT_0)
-#define CONTEXT_BIT1(field) CONTEXT_FIELD(field, TYPE_BIT_1)
-#define CONTEXT_BIT2(field) CONTEXT_FIELD(field, TYPE_BIT_2)
-#define CONTEXT_BIT3(field) CONTEXT_FIELD(field, TYPE_BIT_3)
-#define CONTEXT_BIT4(field) CONTEXT_FIELD(field, TYPE_BIT_4)
-#define CONTEXT_BIT5(field) CONTEXT_FIELD(field, TYPE_BIT_5)
-#define CONTEXT_FLOAT(field) CONTEXT_FIELD(field, TYPE_FLOAT)
-#define CONTEXT_FLOAT2(field) CONTEXT_FIELD(field, TYPE_FLOAT_2)
-#define CONTEXT_FLOAT3(field) CONTEXT_FIELD(field, TYPE_FLOAT_3)
-#define CONTEXT_FLOAT4(field) CONTEXT_FIELD(field, TYPE_FLOAT_4)
-#define CONTEXT_MATRIX(field) CONTEXT_FIELD(field, TYPE_MATRIX)
-#define CONTEXT_MATRIX_T(field) CONTEXT_FIELD(field, TYPE_MATRIX_T)
-
-#define ARRAY_INT(field) ARRAY_FIELD(field, TYPE_INT)
-#define ARRAY_ENUM(field) ARRAY_FIELD(field, TYPE_ENUM)
-#define ARRAY_BOOL(field) ARRAY_FIELD(field, TYPE_BOOLEAN)
-
-#define EXT(f) \
- offsetof(struct gl_extensions, f)
-
-#define EXTRA_EXT(e) \
- static const int extra_##e[] = { \
- EXT(e), EXTRA_END \
- }
-
-#define EXTRA_EXT2(e1, e2) \
- static const int extra_##e1##_##e2[] = { \
- EXT(e1), EXT(e2), EXTRA_END \
- }
-
-/* The 'extra' mechanism is a way to specify extra checks (such as
- * extensions or specific gl versions) or actions (flush current, new
- * buffers) that we need to do before looking up an enum. We need to
- * declare them all up front so we can refer to them in the value_desc
- * structs below. */
-
-static const int extra_new_buffers[] = {
- EXTRA_NEW_BUFFERS,
- EXTRA_END
-};
-
-static const int extra_valid_draw_buffer[] = {
- EXTRA_VALID_DRAW_BUFFER,
- EXTRA_END
-};
-
-static const int extra_valid_texture_unit[] = {
- EXTRA_VALID_TEXTURE_UNIT,
- EXTRA_END
-};
-
-static const int extra_flush_current_valid_texture_unit[] = {
- EXTRA_FLUSH_CURRENT,
- EXTRA_VALID_TEXTURE_UNIT,
- EXTRA_END
-};
-
-static const int extra_flush_current[] = {
- EXTRA_FLUSH_CURRENT,
- EXTRA_END
-};
-
-static const int extra_new_buffers_OES_read_format[] = {
- EXTRA_NEW_BUFFERS,
- EXT(OES_read_format),
- EXTRA_END
-};
-
-static const int extra_EXT_secondary_color_flush_current[] = {
- EXT(EXT_secondary_color),
- EXTRA_FLUSH_CURRENT,
- EXTRA_END
-};
-
-static const int extra_EXT_fog_coord_flush_current[] = {
- EXT(EXT_fog_coord),
- EXTRA_FLUSH_CURRENT,
- EXTRA_END
-};
-
-static const int extra_EXT_texture_integer[] = {
- EXT(EXT_texture_integer),
- EXTRA_END
-};
-
-static const int extra_EXT_gpu_shader4[] = {
- EXT(EXT_gpu_shader4),
- EXTRA_END
-};
-
-
-EXTRA_EXT(ARB_ES2_compatibility);
-EXTRA_EXT(ARB_multitexture);
-EXTRA_EXT(ARB_texture_cube_map);
-EXTRA_EXT(MESA_texture_array);
-EXTRA_EXT2(EXT_secondary_color, ARB_vertex_program);
-EXTRA_EXT(EXT_secondary_color);
-EXTRA_EXT(EXT_fog_coord);
-EXTRA_EXT(EXT_texture_lod_bias);
-EXTRA_EXT(EXT_texture_filter_anisotropic);
-EXTRA_EXT(IBM_rasterpos_clip);
-EXTRA_EXT(NV_point_sprite);
-EXTRA_EXT(SGIS_generate_mipmap);
-EXTRA_EXT(NV_vertex_program);
-EXTRA_EXT(NV_fragment_program);
-EXTRA_EXT(NV_texture_rectangle);
-EXTRA_EXT(EXT_stencil_two_side);
-EXTRA_EXT(NV_light_max_exponent);
-EXTRA_EXT(SGI_texture_color_table);
-EXTRA_EXT(EXT_depth_bounds_test);
-EXTRA_EXT(ARB_depth_clamp);
-EXTRA_EXT(ATI_fragment_shader);
-EXTRA_EXT(EXT_framebuffer_blit);
-EXTRA_EXT(ARB_shader_objects);
-EXTRA_EXT(EXT_provoking_vertex);
-EXTRA_EXT(ARB_fragment_shader);
-EXTRA_EXT(ARB_fragment_program);
-EXTRA_EXT2(ARB_framebuffer_object, EXT_framebuffer_multisample);
-EXTRA_EXT(EXT_framebuffer_object);
-EXTRA_EXT(APPLE_vertex_array_object);
-EXTRA_EXT(ARB_seamless_cube_map);
-EXTRA_EXT(EXT_compiled_vertex_array);
-EXTRA_EXT(ARB_sync);
-EXTRA_EXT(ARB_vertex_shader);
-EXTRA_EXT(EXT_transform_feedback);
-EXTRA_EXT(ARB_transform_feedback2);
-EXTRA_EXT(EXT_pixel_buffer_object);
-EXTRA_EXT(ARB_vertex_program);
-EXTRA_EXT2(NV_point_sprite, ARB_point_sprite);
-EXTRA_EXT2(ARB_fragment_program, NV_fragment_program);
-EXTRA_EXT2(ARB_vertex_program, NV_vertex_program);
-EXTRA_EXT2(ARB_vertex_program, ARB_fragment_program);
-EXTRA_EXT(ARB_vertex_buffer_object);
-EXTRA_EXT(ARB_geometry_shader4);
-EXTRA_EXT(ARB_copy_buffer);
-EXTRA_EXT(EXT_framebuffer_sRGB);
-
-static const int
-extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program[] = {
- EXT(ARB_vertex_program),
- EXT(ARB_fragment_program),
- EXT(NV_vertex_program),
- EXTRA_END
-};
-
-static const int
-extra_NV_vertex_program_ARB_vertex_program_ARB_fragment_program_NV_vertex_program[] = {
- EXT(NV_vertex_program),
- EXT(ARB_vertex_program),
- EXT(ARB_fragment_program),
- EXT(NV_vertex_program),
- EXTRA_END
-};
-
-static const int
-extra_NV_primitive_restart[] = {
- EXT(NV_primitive_restart),
- EXTRA_END
-};
-
-static const int extra_version_30[] = { EXTRA_VERSION_30, EXTRA_END };
-static const int extra_version_31[] = { EXTRA_VERSION_31, EXTRA_END };
-static const int extra_version_32[] = { EXTRA_VERSION_32, EXTRA_END };
-
-static const int
-extra_ARB_vertex_program_version_es2[] = {
- EXT(ARB_vertex_program),
- EXTRA_VERSION_ES2,
- EXTRA_END
-};
-
-#define API_OPENGL_BIT (1 << API_OPENGL)
-#define API_OPENGLES_BIT (1 << API_OPENGLES)
-#define API_OPENGLES2_BIT (1 << API_OPENGLES2)
-
-/* This is the big table describing all the enums we accept in
- * glGet*v(). The table is partitioned into six parts: enums
- * understood by all GL APIs (OpenGL, GLES and GLES2), enums shared
- * between OpenGL and GLES, enums exclusive to GLES, etc for the
- * remaining combinations. When we add the enums to the hash table in
- * _mesa_init_get_hash(), we only add the enums for the API we're
- * instantiating and the different sections are guarded by #if
- * FEATURE_GL etc to make sure we only compile in the enums we may
- * need. */
-
-static const struct value_desc values[] = {
- /* Enums shared between OpenGL, GLES1 and GLES2 */
- { 0, 0, TYPE_API_MASK,
- API_OPENGL_BIT | API_OPENGLES_BIT | API_OPENGLES2_BIT, NO_EXTRA},
- { GL_ALPHA_BITS, BUFFER_INT(Visual.alphaBits), extra_new_buffers },
- { GL_BLEND, CONTEXT_BIT0(Color.BlendEnabled), NO_EXTRA },
- { GL_BLEND_SRC, CONTEXT_ENUM(Color.Blend[0].SrcRGB), NO_EXTRA },
- { GL_BLUE_BITS, BUFFER_INT(Visual.blueBits), extra_new_buffers },
- { GL_COLOR_CLEAR_VALUE, CONTEXT_FIELD(Color.ClearColor[0], TYPE_FLOATN_4), NO_EXTRA },
- { GL_COLOR_WRITEMASK, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA },
- { GL_CULL_FACE, CONTEXT_BOOL(Polygon.CullFlag), NO_EXTRA },
- { GL_CULL_FACE_MODE, CONTEXT_ENUM(Polygon.CullFaceMode), NO_EXTRA },
- { GL_DEPTH_BITS, BUFFER_INT(Visual.depthBits), NO_EXTRA },
- { GL_DEPTH_CLEAR_VALUE, CONTEXT_FIELD(Depth.Clear, TYPE_DOUBLEN), NO_EXTRA },
- { GL_DEPTH_FUNC, CONTEXT_ENUM(Depth.Func), NO_EXTRA },
- { GL_DEPTH_RANGE, CONTEXT_FIELD(Viewport.Near, TYPE_FLOATN_2), NO_EXTRA },
- { GL_DEPTH_TEST, CONTEXT_BOOL(Depth.Test), NO_EXTRA },
- { GL_DEPTH_WRITEMASK, CONTEXT_BOOL(Depth.Mask), NO_EXTRA },
- { GL_DITHER, CONTEXT_BOOL(Color.DitherFlag), NO_EXTRA },
- { GL_FRONT_FACE, CONTEXT_ENUM(Polygon.FrontFace), NO_EXTRA },
- { GL_GREEN_BITS, BUFFER_INT(Visual.greenBits), extra_new_buffers },
- { GL_LINE_WIDTH, CONTEXT_FLOAT(Line.Width), NO_EXTRA },
- { GL_ALIASED_LINE_WIDTH_RANGE, CONTEXT_FLOAT2(Const.MinLineWidth), NO_EXTRA },
- { GL_MAX_ELEMENTS_VERTICES, CONTEXT_INT(Const.MaxArrayLockSize), NO_EXTRA },
- { GL_MAX_ELEMENTS_INDICES, CONTEXT_INT(Const.MaxArrayLockSize), NO_EXTRA },
- { GL_MAX_TEXTURE_SIZE, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_context, Const.MaxTextureLevels), NO_EXTRA },
- { GL_MAX_VIEWPORT_DIMS, CONTEXT_INT2(Const.MaxViewportWidth), NO_EXTRA },
- { GL_PACK_ALIGNMENT, CONTEXT_INT(Pack.Alignment), NO_EXTRA },
- { GL_ALIASED_POINT_SIZE_RANGE, CONTEXT_FLOAT2(Const.MinPointSize), NO_EXTRA },
- { GL_POLYGON_OFFSET_FACTOR, CONTEXT_FLOAT(Polygon.OffsetFactor ), NO_EXTRA },
- { GL_POLYGON_OFFSET_UNITS, CONTEXT_FLOAT(Polygon.OffsetUnits ), NO_EXTRA },
- { GL_POLYGON_OFFSET_FILL, CONTEXT_BOOL(Polygon.OffsetFill), NO_EXTRA },
- { GL_RED_BITS, BUFFER_INT(Visual.redBits), extra_new_buffers },
- { GL_SCISSOR_BOX, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA },
- { GL_SCISSOR_TEST, CONTEXT_BOOL(Scissor.Enabled), NO_EXTRA },
- { GL_STENCIL_BITS, BUFFER_INT(Visual.stencilBits), NO_EXTRA },
- { GL_STENCIL_CLEAR_VALUE, CONTEXT_INT(Stencil.Clear), NO_EXTRA },
- { GL_STENCIL_FAIL, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
- { GL_STENCIL_FUNC, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
- { GL_STENCIL_PASS_DEPTH_FAIL, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
- { GL_STENCIL_PASS_DEPTH_PASS, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
- { GL_STENCIL_REF, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
- { GL_STENCIL_TEST, CONTEXT_BOOL(Stencil.Enabled), NO_EXTRA },
- { GL_STENCIL_VALUE_MASK, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
- { GL_STENCIL_WRITEMASK, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
- { GL_SUBPIXEL_BITS, CONTEXT_INT(Const.SubPixelBits), NO_EXTRA },
- { GL_TEXTURE_BINDING_2D, LOC_CUSTOM, TYPE_INT, TEXTURE_2D_INDEX, NO_EXTRA },
- { GL_UNPACK_ALIGNMENT, CONTEXT_INT(Unpack.Alignment), NO_EXTRA },
- { GL_VIEWPORT, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA },
-
- /* GL_ARB_multitexture */
- { GL_ACTIVE_TEXTURE_ARB,
- LOC_CUSTOM, TYPE_INT, 0, extra_ARB_multitexture },
-
- /* Note that all the OES_* extensions require that the Mesa "struct
- * gl_extensions" include a member with the name of the extension.
- * That structure does not yet include OES extensions (and we're
- * not sure whether it will). If it does, all the OES_*
- * extensions below should mark the dependency. */
-
- /* GL_ARB_texture_cube_map */
- { GL_TEXTURE_BINDING_CUBE_MAP_ARB, LOC_CUSTOM, TYPE_INT,
- TEXTURE_CUBE_INDEX, extra_ARB_texture_cube_map },
- { GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_context, Const.MaxCubeTextureLevels),
- extra_ARB_texture_cube_map }, /* XXX: OES_texture_cube_map */
-
- /* XXX: OES_blend_subtract */
- { GL_BLEND_SRC_RGB_EXT, CONTEXT_ENUM(Color.Blend[0].SrcRGB), NO_EXTRA },
- { GL_BLEND_DST_RGB_EXT, CONTEXT_ENUM(Color.Blend[0].DstRGB), NO_EXTRA },
- { GL_BLEND_SRC_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].SrcA), NO_EXTRA },
- { GL_BLEND_DST_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].DstA), NO_EXTRA },
-
- /* GL_BLEND_EQUATION_RGB, which is what we're really after, is
- * defined identically to GL_BLEND_EQUATION. */
- { GL_BLEND_EQUATION, CONTEXT_ENUM(Color.Blend[0].EquationRGB), NO_EXTRA },
- { GL_BLEND_EQUATION_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].EquationA), NO_EXTRA },
-
- /* GL_ARB_texture_compression */
- { GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
- { GL_COMPRESSED_TEXTURE_FORMATS_ARB, LOC_CUSTOM, TYPE_INT_N, 0, NO_EXTRA },
-
- /* GL_ARB_multisample */
- { GL_SAMPLE_ALPHA_TO_COVERAGE_ARB,
- CONTEXT_BOOL(Multisample.SampleAlphaToCoverage), NO_EXTRA },
- { GL_SAMPLE_COVERAGE_ARB, CONTEXT_BOOL(Multisample.SampleCoverage), NO_EXTRA },
- { GL_SAMPLE_COVERAGE_VALUE_ARB,
- CONTEXT_FLOAT(Multisample.SampleCoverageValue), NO_EXTRA },
- { GL_SAMPLE_COVERAGE_INVERT_ARB,
- CONTEXT_BOOL(Multisample.SampleCoverageInvert), NO_EXTRA },
- { GL_SAMPLE_BUFFERS_ARB, BUFFER_INT(Visual.sampleBuffers), NO_EXTRA },
- { GL_SAMPLES_ARB, BUFFER_INT(Visual.samples), NO_EXTRA },
-
- /* GL_SGIS_generate_mipmap */
- { GL_GENERATE_MIPMAP_HINT_SGIS, CONTEXT_ENUM(Hint.GenerateMipmap),
- extra_SGIS_generate_mipmap },
-
- /* GL_ARB_vertex_buffer_object */
- { GL_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
-
- /* GL_ARB_vertex_buffer_object */
- /* GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB - not supported */
- { GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT, 0,
- extra_ARB_vertex_buffer_object },
-
- /* GL_ARB_copy_buffer */
- { GL_COPY_READ_BUFFER, LOC_CUSTOM, TYPE_INT, 0, extra_ARB_copy_buffer },
- { GL_COPY_WRITE_BUFFER, LOC_CUSTOM, TYPE_INT, 0, extra_ARB_copy_buffer },
-
- /* GL_OES_read_format */
- { GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, LOC_CUSTOM, TYPE_INT, 0,
- extra_new_buffers_OES_read_format },
- { GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, LOC_CUSTOM, TYPE_INT, 0,
- extra_new_buffers_OES_read_format },
-
- /* GL_EXT_framebuffer_object */
- { GL_FRAMEBUFFER_BINDING_EXT, BUFFER_INT(Name),
- extra_EXT_framebuffer_object },
- { GL_RENDERBUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
- extra_EXT_framebuffer_object },
- { GL_MAX_RENDERBUFFER_SIZE_EXT, CONTEXT_INT(Const.MaxRenderbufferSize),
- extra_EXT_framebuffer_object },
-
- /* This entry isn't spec'ed for GLES 2, but is needed for Mesa's
- * GLSL: */
- { GL_MAX_CLIP_PLANES, CONTEXT_INT(Const.MaxClipPlanes), NO_EXTRA },
-
-#if FEATURE_GL || FEATURE_ES1
- /* Enums in OpenGL and GLES1 */
- { 0, 0, TYPE_API_MASK, API_OPENGL_BIT | API_OPENGLES_BIT, NO_EXTRA },
- { GL_LIGHT0, CONTEXT_BOOL(Light.Light[0].Enabled), NO_EXTRA },
- { GL_LIGHT1, CONTEXT_BOOL(Light.Light[1].Enabled), NO_EXTRA },
- { GL_LIGHT2, CONTEXT_BOOL(Light.Light[2].Enabled), NO_EXTRA },
- { GL_LIGHT3, CONTEXT_BOOL(Light.Light[3].Enabled), NO_EXTRA },
- { GL_LIGHT4, CONTEXT_BOOL(Light.Light[4].Enabled), NO_EXTRA },
- { GL_LIGHT5, CONTEXT_BOOL(Light.Light[5].Enabled), NO_EXTRA },
- { GL_LIGHT6, CONTEXT_BOOL(Light.Light[6].Enabled), NO_EXTRA },
- { GL_LIGHT7, CONTEXT_BOOL(Light.Light[7].Enabled), NO_EXTRA },
- { GL_LIGHTING, CONTEXT_BOOL(Light.Enabled), NO_EXTRA },
- { GL_LIGHT_MODEL_AMBIENT,
- CONTEXT_FIELD(Light.Model.Ambient[0], TYPE_FLOATN_4), NO_EXTRA },
- { GL_LIGHT_MODEL_TWO_SIDE, CONTEXT_BOOL(Light.Model.TwoSide), NO_EXTRA },
- { GL_ALPHA_TEST, CONTEXT_BOOL(Color.AlphaEnabled), NO_EXTRA },
- { GL_ALPHA_TEST_FUNC, CONTEXT_ENUM(Color.AlphaFunc), NO_EXTRA },
- { GL_ALPHA_TEST_REF, CONTEXT_FIELD(Color.AlphaRef, TYPE_FLOATN), NO_EXTRA },
- { GL_BLEND_DST, CONTEXT_ENUM(Color.Blend[0].DstRGB), NO_EXTRA },
- { GL_CLIP_PLANE0, CONTEXT_BIT0(Transform.ClipPlanesEnabled), NO_EXTRA },
- { GL_CLIP_PLANE1, CONTEXT_BIT1(Transform.ClipPlanesEnabled), NO_EXTRA },
- { GL_CLIP_PLANE2, CONTEXT_BIT2(Transform.ClipPlanesEnabled), NO_EXTRA },
- { GL_CLIP_PLANE3, CONTEXT_BIT3(Transform.ClipPlanesEnabled), NO_EXTRA },
- { GL_CLIP_PLANE4, CONTEXT_BIT4(Transform.ClipPlanesEnabled), NO_EXTRA },
- { GL_CLIP_PLANE5, CONTEXT_BIT5(Transform.ClipPlanesEnabled), NO_EXTRA },
- { GL_COLOR_MATERIAL, CONTEXT_BOOL(Light.ColorMaterialEnabled), NO_EXTRA },
- { GL_CURRENT_COLOR,
- CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_COLOR0][0], TYPE_FLOATN_4),
- extra_flush_current },
- { GL_CURRENT_NORMAL,
- CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_NORMAL][0], TYPE_FLOATN_3),
- extra_flush_current },
- { GL_CURRENT_TEXTURE_COORDS, LOC_CUSTOM, TYPE_FLOAT_4, 0,
- extra_flush_current_valid_texture_unit },
- { GL_DISTANCE_ATTENUATION_EXT, CONTEXT_FLOAT3(Point.Params[0]), NO_EXTRA },
- { GL_FOG, CONTEXT_BOOL(Fog.Enabled), NO_EXTRA },
- { GL_FOG_COLOR, CONTEXT_FIELD(Fog.Color[0], TYPE_FLOATN_4), NO_EXTRA },
- { GL_FOG_DENSITY, CONTEXT_FLOAT(Fog.Density), NO_EXTRA },
- { GL_FOG_END, CONTEXT_FLOAT(Fog.End), NO_EXTRA },
- { GL_FOG_HINT, CONTEXT_ENUM(Hint.Fog), NO_EXTRA },
- { GL_FOG_MODE, CONTEXT_ENUM(Fog.Mode), NO_EXTRA },
- { GL_FOG_START, CONTEXT_FLOAT(Fog.Start), NO_EXTRA },
- { GL_LINE_SMOOTH, CONTEXT_BOOL(Line.SmoothFlag), NO_EXTRA },
- { GL_LINE_SMOOTH_HINT, CONTEXT_ENUM(Hint.LineSmooth), NO_EXTRA },
- { GL_LINE_WIDTH_RANGE, CONTEXT_FLOAT2(Const.MinLineWidthAA), NO_EXTRA },
- { GL_COLOR_LOGIC_OP, CONTEXT_BOOL(Color.ColorLogicOpEnabled), NO_EXTRA },
- { GL_LOGIC_OP_MODE, CONTEXT_ENUM(Color.LogicOp), NO_EXTRA },
- { GL_MATRIX_MODE, CONTEXT_ENUM(Transform.MatrixMode), NO_EXTRA },
- { GL_MAX_MODELVIEW_STACK_DEPTH, CONST(MAX_MODELVIEW_STACK_DEPTH), NO_EXTRA },
- { GL_MAX_PROJECTION_STACK_DEPTH, CONST(MAX_PROJECTION_STACK_DEPTH), NO_EXTRA },
- { GL_MAX_TEXTURE_STACK_DEPTH, CONST(MAX_TEXTURE_STACK_DEPTH), NO_EXTRA },
- { GL_MODELVIEW_MATRIX, CONTEXT_MATRIX(ModelviewMatrixStack.Top), NO_EXTRA },
- { GL_MODELVIEW_STACK_DEPTH, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_context, ModelviewMatrixStack.Depth), NO_EXTRA },
- { GL_NORMALIZE, CONTEXT_BOOL(Transform.Normalize), NO_EXTRA },
- { GL_PACK_SKIP_IMAGES_EXT, CONTEXT_INT(Pack.SkipImages), NO_EXTRA },
- { GL_PERSPECTIVE_CORRECTION_HINT, CONTEXT_ENUM(Hint.PerspectiveCorrection), NO_EXTRA },
- { GL_POINT_SIZE, CONTEXT_FLOAT(Point.Size), NO_EXTRA },
- { GL_POINT_SIZE_RANGE, CONTEXT_FLOAT2(Const.MinPointSizeAA), NO_EXTRA },
- { GL_POINT_SMOOTH, CONTEXT_BOOL(Point.SmoothFlag), NO_EXTRA },
- { GL_POINT_SMOOTH_HINT, CONTEXT_ENUM(Hint.PointSmooth), NO_EXTRA },
- { GL_POINT_SIZE_MIN_EXT, CONTEXT_FLOAT(Point.MinSize), NO_EXTRA },
- { GL_POINT_SIZE_MAX_EXT, CONTEXT_FLOAT(Point.MaxSize), NO_EXTRA },
- { GL_POINT_FADE_THRESHOLD_SIZE_EXT, CONTEXT_FLOAT(Point.Threshold), NO_EXTRA },
- { GL_PROJECTION_MATRIX, CONTEXT_MATRIX(ProjectionMatrixStack.Top), NO_EXTRA },
- { GL_PROJECTION_STACK_DEPTH, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_context, ProjectionMatrixStack.Depth), NO_EXTRA },
- { GL_RESCALE_NORMAL, CONTEXT_BOOL(Transform.RescaleNormals), NO_EXTRA },
- { GL_SHADE_MODEL, CONTEXT_ENUM(Light.ShadeModel), NO_EXTRA },
- { GL_TEXTURE_2D, LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA },
- { GL_TEXTURE_MATRIX, LOC_CUSTOM, TYPE_MATRIX, 0, extra_valid_texture_unit },
- { GL_TEXTURE_STACK_DEPTH, LOC_CUSTOM, TYPE_INT, 0,
- extra_valid_texture_unit },
-
- { GL_VERTEX_ARRAY, ARRAY_BOOL(Vertex.Enabled), NO_EXTRA },
- { GL_VERTEX_ARRAY_SIZE, ARRAY_INT(Vertex.Size), NO_EXTRA },
- { GL_VERTEX_ARRAY_TYPE, ARRAY_ENUM(Vertex.Type), NO_EXTRA },
- { GL_VERTEX_ARRAY_STRIDE, ARRAY_INT(Vertex.Stride), NO_EXTRA },
- { GL_NORMAL_ARRAY, ARRAY_ENUM(Normal.Enabled), NO_EXTRA },
- { GL_NORMAL_ARRAY_TYPE, ARRAY_ENUM(Normal.Type), NO_EXTRA },
- { GL_NORMAL_ARRAY_STRIDE, ARRAY_INT(Normal.Stride), NO_EXTRA },
- { GL_COLOR_ARRAY, ARRAY_BOOL(Color.Enabled), NO_EXTRA },
- { GL_COLOR_ARRAY_SIZE, ARRAY_INT(Color.Size), NO_EXTRA },
- { GL_COLOR_ARRAY_TYPE, ARRAY_ENUM(Color.Type), NO_EXTRA },
- { GL_COLOR_ARRAY_STRIDE, ARRAY_INT(Color.Stride), NO_EXTRA },
- { GL_TEXTURE_COORD_ARRAY,
- LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Enabled), NO_EXTRA },
- { GL_TEXTURE_COORD_ARRAY_SIZE,
- LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Size), NO_EXTRA },
- { GL_TEXTURE_COORD_ARRAY_TYPE,
- LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Type), NO_EXTRA },
- { GL_TEXTURE_COORD_ARRAY_STRIDE,
- LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Stride), NO_EXTRA },
-
- /* GL_ARB_ES2_compatibility */
- { GL_SHADER_COMPILER, CONST(1), extra_ARB_ES2_compatibility },
- { GL_MAX_VARYING_VECTORS, CONTEXT_INT(Const.MaxVarying),
- extra_ARB_ES2_compatibility },
- { GL_MAX_VERTEX_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0,
- extra_ARB_ES2_compatibility },
- { GL_MAX_FRAGMENT_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0,
- extra_ARB_ES2_compatibility },
-
- /* GL_ARB_multitexture */
- { GL_MAX_TEXTURE_UNITS_ARB,
- CONTEXT_INT(Const.MaxTextureUnits), extra_ARB_multitexture },
- { GL_CLIENT_ACTIVE_TEXTURE_ARB,
- LOC_CUSTOM, TYPE_INT, 0, extra_ARB_multitexture },
-
- /* GL_ARB_texture_cube_map */
- { GL_TEXTURE_CUBE_MAP_ARB, LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA },
- /* S, T, and R are always set at the same time */
- { GL_TEXTURE_GEN_STR_OES, LOC_TEXUNIT, TYPE_BIT_0,
- offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
-
- /* GL_ARB_multisample */
- { GL_MULTISAMPLE_ARB, CONTEXT_BOOL(Multisample.Enabled), NO_EXTRA },
- { GL_SAMPLE_ALPHA_TO_ONE_ARB, CONTEXT_BOOL(Multisample.SampleAlphaToOne), NO_EXTRA },
-
- /* GL_ARB_vertex_buffer_object */
- { GL_VERTEX_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_array_object, Vertex.BufferObj), NO_EXTRA },
- { GL_NORMAL_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_array_object, Normal.BufferObj), NO_EXTRA },
- { GL_COLOR_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_array_object, Color.BufferObj), NO_EXTRA },
- { GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
-
- /* GL_OES_point_sprite */
- { GL_POINT_SPRITE_NV,
- CONTEXT_BOOL(Point.PointSprite),
- extra_NV_point_sprite_ARB_point_sprite },
-
- /* GL_ARB_fragment_shader */
- { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB,
- CONTEXT_INT(Const.FragmentProgram.MaxUniformComponents),
- extra_ARB_fragment_shader },
-
- /* GL_ARB_vertex_shader */
- { GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB,
- CONTEXT_INT(Const.VertexProgram.MaxUniformComponents),
- extra_ARB_vertex_shader },
- { GL_MAX_VARYING_FLOATS_ARB, LOC_CUSTOM, TYPE_INT, 0,
- extra_ARB_vertex_shader },
-
- /* GL_EXT_texture_lod_bias */
- { GL_MAX_TEXTURE_LOD_BIAS_EXT, CONTEXT_FLOAT(Const.MaxTextureLodBias),
- extra_EXT_texture_lod_bias },
-
- /* GL_EXT_texture_filter_anisotropic */
- { GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,
- CONTEXT_FLOAT(Const.MaxTextureMaxAnisotropy),
- extra_EXT_texture_filter_anisotropic },
-#endif /* FEATURE_GL || FEATURE_ES1 */
-
-#if FEATURE_ES1
- { 0, 0, TYPE_API_MASK, API_OPENGLES_BIT },
- /* XXX: OES_matrix_get */
- { GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES },
- { GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES },
- { GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES },
-
- /* OES_point_size_array */
- { GL_POINT_SIZE_ARRAY_OES, ARRAY_FIELD(PointSize.Enabled, TYPE_BOOLEAN) },
- { GL_POINT_SIZE_ARRAY_TYPE_OES, ARRAY_FIELD(PointSize.Type, TYPE_ENUM) },
- { GL_POINT_SIZE_ARRAY_STRIDE_OES, ARRAY_FIELD(PointSize.Stride, TYPE_INT) },
- { GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES, LOC_CUSTOM, TYPE_INT, 0 },
-#endif /* FEATURE_ES1 */
-
-#if FEATURE_GL || FEATURE_ES2
- { 0, 0, TYPE_API_MASK, API_OPENGL_BIT | API_OPENGLES2_BIT, NO_EXTRA },
- /* This entry isn't spec'ed for GLES 2, but is needed for Mesa's GLSL: */
- { GL_MAX_LIGHTS, CONTEXT_INT(Const.MaxLights), NO_EXTRA },
- { GL_MAX_TEXTURE_COORDS_ARB, /* == GL_MAX_TEXTURE_COORDS_NV */
- CONTEXT_INT(Const.MaxTextureCoordUnits),
- extra_ARB_fragment_program_NV_fragment_program },
-
- /* GL_ARB_draw_buffers */
- { GL_MAX_DRAW_BUFFERS_ARB, CONTEXT_INT(Const.MaxDrawBuffers), NO_EXTRA },
-
- { GL_BLEND_COLOR_EXT, CONTEXT_FIELD(Color.BlendColor[0], TYPE_FLOATN_4), NO_EXTRA },
- /* GL_ARB_fragment_program */
- { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, /* == GL_MAX_TEXTURE_IMAGE_UNITS_NV */
- CONTEXT_INT(Const.MaxTextureImageUnits),
- extra_ARB_fragment_program_NV_fragment_program },
- { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB,
- CONTEXT_INT(Const.MaxVertexTextureImageUnits), extra_ARB_vertex_shader },
- { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB,
- CONTEXT_INT(Const.MaxCombinedTextureImageUnits),
- extra_ARB_vertex_shader },
-
- /* GL_ARB_shader_objects
- * Actually, this token isn't part of GL_ARB_shader_objects, but is
- * close enough for now. */
- { GL_CURRENT_PROGRAM, LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_objects },
-
- /* OpenGL 2.0 */
- { GL_STENCIL_BACK_FUNC, CONTEXT_ENUM(Stencil.Function[1]), NO_EXTRA },
- { GL_STENCIL_BACK_VALUE_MASK, CONTEXT_INT(Stencil.ValueMask[1]), NO_EXTRA },
- { GL_STENCIL_BACK_WRITEMASK, CONTEXT_INT(Stencil.WriteMask[1]), NO_EXTRA },
- { GL_STENCIL_BACK_REF, CONTEXT_INT(Stencil.Ref[1]), NO_EXTRA },
- { GL_STENCIL_BACK_FAIL, CONTEXT_ENUM(Stencil.FailFunc[1]), NO_EXTRA },
- { GL_STENCIL_BACK_PASS_DEPTH_FAIL, CONTEXT_ENUM(Stencil.ZFailFunc[1]), NO_EXTRA },
- { GL_STENCIL_BACK_PASS_DEPTH_PASS, CONTEXT_ENUM(Stencil.ZPassFunc[1]), NO_EXTRA },
-
- { GL_MAX_VERTEX_ATTRIBS_ARB,
- CONTEXT_INT(Const.VertexProgram.MaxAttribs),
- extra_ARB_vertex_program_version_es2 },
-
- /* OES_texture_3D */
- { GL_TEXTURE_BINDING_3D, LOC_CUSTOM, TYPE_INT, TEXTURE_3D_INDEX, NO_EXTRA },
- { GL_MAX_3D_TEXTURE_SIZE, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_context, Const.Max3DTextureLevels), NO_EXTRA },
-
- /* GL_ARB_fragment_program/OES_standard_derivatives */
- { GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB,
- CONTEXT_ENUM(Hint.FragmentShaderDerivative), extra_ARB_fragment_shader },
-#endif /* FEATURE_GL || FEATURE_ES2 */
-
-#if FEATURE_ES2
- /* Enums unique to OpenGL ES 2.0 */
- { 0, 0, TYPE_API_MASK, API_OPENGLES2_BIT, NO_EXTRA },
- { GL_MAX_FRAGMENT_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
- { GL_MAX_VARYING_VECTORS, CONTEXT_INT(Const.MaxVarying), NO_EXTRA },
- { GL_MAX_VERTEX_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
- { GL_SHADER_COMPILER, CONST(1), NO_EXTRA },
- /* OES_get_program_binary */
- { GL_NUM_SHADER_BINARY_FORMATS, CONST(0), NO_EXTRA },
- { GL_SHADER_BINARY_FORMATS, CONST(0), NO_EXTRA },
-#endif /* FEATURE_ES2 */
-
-#if FEATURE_GL
- /* Remaining enums are only in OpenGL */
- { 0, 0, TYPE_API_MASK, API_OPENGL_BIT, NO_EXTRA },
- { GL_ACCUM_RED_BITS, BUFFER_INT(Visual.accumRedBits), NO_EXTRA },
- { GL_ACCUM_GREEN_BITS, BUFFER_INT(Visual.accumGreenBits), NO_EXTRA },
- { GL_ACCUM_BLUE_BITS, BUFFER_INT(Visual.accumBlueBits), NO_EXTRA },
- { GL_ACCUM_ALPHA_BITS, BUFFER_INT(Visual.accumAlphaBits), NO_EXTRA },
- { GL_ACCUM_CLEAR_VALUE, CONTEXT_FIELD(Accum.ClearColor[0], TYPE_FLOATN_4), NO_EXTRA },
- { GL_ALPHA_BIAS, CONTEXT_FLOAT(Pixel.AlphaBias), NO_EXTRA },
- { GL_ALPHA_SCALE, CONTEXT_FLOAT(Pixel.AlphaScale), NO_EXTRA },
- { GL_ATTRIB_STACK_DEPTH, CONTEXT_INT(AttribStackDepth), NO_EXTRA },
- { GL_AUTO_NORMAL, CONTEXT_BOOL(Eval.AutoNormal), NO_EXTRA },
- { GL_AUX_BUFFERS, BUFFER_INT(Visual.numAuxBuffers), NO_EXTRA },
- { GL_BLUE_BIAS, CONTEXT_FLOAT(Pixel.BlueBias), NO_EXTRA },
- { GL_BLUE_SCALE, CONTEXT_FLOAT(Pixel.BlueScale), NO_EXTRA },
- { GL_CLIENT_ATTRIB_STACK_DEPTH, CONTEXT_INT(ClientAttribStackDepth), NO_EXTRA },
- { GL_COLOR_MATERIAL_FACE, CONTEXT_ENUM(Light.ColorMaterialFace), NO_EXTRA },
- { GL_COLOR_MATERIAL_PARAMETER, CONTEXT_ENUM(Light.ColorMaterialMode), NO_EXTRA },
- { GL_CURRENT_INDEX,
- CONTEXT_FLOAT(Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0]),
- extra_flush_current },
- { GL_CURRENT_RASTER_COLOR,
- CONTEXT_FIELD(Current.RasterColor[0], TYPE_FLOATN_4), NO_EXTRA },
- { GL_CURRENT_RASTER_DISTANCE, CONTEXT_FLOAT(Current.RasterDistance), NO_EXTRA },
- { GL_CURRENT_RASTER_INDEX, CONST(1), NO_EXTRA },
- { GL_CURRENT_RASTER_POSITION, CONTEXT_FLOAT4(Current.RasterPos[0]), NO_EXTRA },
- { GL_CURRENT_RASTER_SECONDARY_COLOR,
- CONTEXT_FIELD(Current.RasterSecondaryColor[0], TYPE_FLOATN_4), NO_EXTRA },
- { GL_CURRENT_RASTER_TEXTURE_COORDS, LOC_CUSTOM, TYPE_FLOAT_4, 0,
- extra_valid_texture_unit },
- { GL_CURRENT_RASTER_POSITION_VALID, CONTEXT_BOOL(Current.RasterPosValid), NO_EXTRA },
- { GL_DEPTH_BIAS, CONTEXT_FLOAT(Pixel.DepthBias), NO_EXTRA },
- { GL_DEPTH_SCALE, CONTEXT_FLOAT(Pixel.DepthScale), NO_EXTRA },
- { GL_DOUBLEBUFFER, BUFFER_INT(Visual.doubleBufferMode), NO_EXTRA },
- { GL_DRAW_BUFFER, BUFFER_ENUM(ColorDrawBuffer[0]), NO_EXTRA },
- { GL_EDGE_FLAG, LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA },
- { GL_FEEDBACK_BUFFER_SIZE, CONTEXT_INT(Feedback.BufferSize), NO_EXTRA },
- { GL_FEEDBACK_BUFFER_TYPE, CONTEXT_ENUM(Feedback.Type), NO_EXTRA },
- { GL_FOG_INDEX, CONTEXT_FLOAT(Fog.Index), NO_EXTRA },
- { GL_GREEN_BIAS, CONTEXT_FLOAT(Pixel.GreenBias), NO_EXTRA },
- { GL_GREEN_SCALE, CONTEXT_FLOAT(Pixel.GreenScale), NO_EXTRA },
- { GL_INDEX_BITS, BUFFER_INT(Visual.indexBits), extra_new_buffers },
- { GL_INDEX_CLEAR_VALUE, CONTEXT_INT(Color.ClearIndex), NO_EXTRA },
- { GL_INDEX_MODE, CONST(0) , NO_EXTRA},
- { GL_INDEX_OFFSET, CONTEXT_INT(Pixel.IndexOffset), NO_EXTRA },
- { GL_INDEX_SHIFT, CONTEXT_INT(Pixel.IndexShift), NO_EXTRA },
- { GL_INDEX_WRITEMASK, CONTEXT_INT(Color.IndexMask), NO_EXTRA },
- { GL_LIGHT_MODEL_COLOR_CONTROL, CONTEXT_ENUM(Light.Model.ColorControl), NO_EXTRA },
- { GL_LIGHT_MODEL_LOCAL_VIEWER, CONTEXT_BOOL(Light.Model.LocalViewer), NO_EXTRA },
- { GL_LINE_STIPPLE, CONTEXT_BOOL(Line.StippleFlag), NO_EXTRA },
- { GL_LINE_STIPPLE_PATTERN, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
- { GL_LINE_STIPPLE_REPEAT, CONTEXT_INT(Line.StippleFactor), NO_EXTRA },
- { GL_LINE_WIDTH_GRANULARITY, CONTEXT_FLOAT(Const.LineWidthGranularity), NO_EXTRA },
- { GL_LIST_BASE, CONTEXT_INT(List.ListBase), NO_EXTRA },
- { GL_LIST_INDEX, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
- { GL_LIST_MODE, LOC_CUSTOM, TYPE_ENUM, 0, NO_EXTRA },
- { GL_INDEX_LOGIC_OP, CONTEXT_BOOL(Color.IndexLogicOpEnabled), NO_EXTRA },
- { GL_MAP1_COLOR_4, CONTEXT_BOOL(Eval.Map1Color4), NO_EXTRA },
- { GL_MAP1_GRID_DOMAIN, CONTEXT_FLOAT2(Eval.MapGrid1u1), NO_EXTRA },
- { GL_MAP1_GRID_SEGMENTS, CONTEXT_INT(Eval.MapGrid1un), NO_EXTRA },
- { GL_MAP1_INDEX, CONTEXT_BOOL(Eval.Map1Index), NO_EXTRA },
- { GL_MAP1_NORMAL, CONTEXT_BOOL(Eval.Map1Normal), NO_EXTRA },
- { GL_MAP1_TEXTURE_COORD_1, CONTEXT_BOOL(Eval.Map1TextureCoord1), NO_EXTRA },
- { GL_MAP1_TEXTURE_COORD_2, CONTEXT_BOOL(Eval.Map1TextureCoord2), NO_EXTRA },
- { GL_MAP1_TEXTURE_COORD_3, CONTEXT_BOOL(Eval.Map1TextureCoord3), NO_EXTRA },
- { GL_MAP1_TEXTURE_COORD_4, CONTEXT_BOOL(Eval.Map1TextureCoord4), NO_EXTRA },
- { GL_MAP1_VERTEX_3, CONTEXT_BOOL(Eval.Map1Vertex3), NO_EXTRA },
- { GL_MAP1_VERTEX_4, CONTEXT_BOOL(Eval.Map1Vertex4), NO_EXTRA },
- { GL_MAP2_COLOR_4, CONTEXT_BOOL(Eval.Map2Color4), NO_EXTRA },
- { GL_MAP2_GRID_DOMAIN, LOC_CUSTOM, TYPE_FLOAT_4, 0, NO_EXTRA },
- { GL_MAP2_GRID_SEGMENTS, CONTEXT_INT2(Eval.MapGrid2un), NO_EXTRA },
- { GL_MAP2_INDEX, CONTEXT_BOOL(Eval.Map2Index), NO_EXTRA },
- { GL_MAP2_NORMAL, CONTEXT_BOOL(Eval.Map2Normal), NO_EXTRA },
- { GL_MAP2_TEXTURE_COORD_1, CONTEXT_BOOL(Eval.Map2TextureCoord1), NO_EXTRA },
- { GL_MAP2_TEXTURE_COORD_2, CONTEXT_BOOL(Eval.Map2TextureCoord2), NO_EXTRA },
- { GL_MAP2_TEXTURE_COORD_3, CONTEXT_BOOL(Eval.Map2TextureCoord3), NO_EXTRA },
- { GL_MAP2_TEXTURE_COORD_4, CONTEXT_BOOL(Eval.Map2TextureCoord4), NO_EXTRA },
- { GL_MAP2_VERTEX_3, CONTEXT_BOOL(Eval.Map2Vertex3), NO_EXTRA },
- { GL_MAP2_VERTEX_4, CONTEXT_BOOL(Eval.Map2Vertex4), NO_EXTRA },
- { GL_MAP_COLOR, CONTEXT_BOOL(Pixel.MapColorFlag), NO_EXTRA },
- { GL_MAP_STENCIL, CONTEXT_BOOL(Pixel.MapStencilFlag), NO_EXTRA },
- { GL_MAX_ATTRIB_STACK_DEPTH, CONST(MAX_ATTRIB_STACK_DEPTH), NO_EXTRA },
- { GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, CONST(MAX_CLIENT_ATTRIB_STACK_DEPTH), NO_EXTRA },
-
- { GL_MAX_EVAL_ORDER, CONST(MAX_EVAL_ORDER), NO_EXTRA },
- { GL_MAX_LIST_NESTING, CONST(MAX_LIST_NESTING), NO_EXTRA },
- { GL_MAX_NAME_STACK_DEPTH, CONST(MAX_NAME_STACK_DEPTH), NO_EXTRA },
- { GL_MAX_PIXEL_MAP_TABLE, CONST(MAX_PIXEL_MAP_TABLE), NO_EXTRA },
- { GL_NAME_STACK_DEPTH, CONTEXT_INT(Select.NameStackDepth), NO_EXTRA },
- { GL_PACK_LSB_FIRST, CONTEXT_BOOL(Pack.LsbFirst), NO_EXTRA },
- { GL_PACK_ROW_LENGTH, CONTEXT_INT(Pack.RowLength), NO_EXTRA },
- { GL_PACK_SKIP_PIXELS, CONTEXT_INT(Pack.SkipPixels), NO_EXTRA },
- { GL_PACK_SKIP_ROWS, CONTEXT_INT(Pack.SkipRows), NO_EXTRA },
- { GL_PACK_SWAP_BYTES, CONTEXT_BOOL(Pack.SwapBytes), NO_EXTRA },
- { GL_PACK_IMAGE_HEIGHT_EXT, CONTEXT_INT(Pack.ImageHeight), NO_EXTRA },
- { GL_PACK_INVERT_MESA, CONTEXT_BOOL(Pack.Invert), NO_EXTRA },
- { GL_PIXEL_MAP_A_TO_A_SIZE, CONTEXT_INT(PixelMaps.AtoA.Size), NO_EXTRA },
- { GL_PIXEL_MAP_B_TO_B_SIZE, CONTEXT_INT(PixelMaps.BtoB.Size), NO_EXTRA },
- { GL_PIXEL_MAP_G_TO_G_SIZE, CONTEXT_INT(PixelMaps.GtoG.Size), NO_EXTRA },
- { GL_PIXEL_MAP_I_TO_A_SIZE, CONTEXT_INT(PixelMaps.ItoA.Size), NO_EXTRA },
- { GL_PIXEL_MAP_I_TO_B_SIZE, CONTEXT_INT(PixelMaps.ItoB.Size), NO_EXTRA },
- { GL_PIXEL_MAP_I_TO_G_SIZE, CONTEXT_INT(PixelMaps.ItoG.Size), NO_EXTRA },
- { GL_PIXEL_MAP_I_TO_I_SIZE, CONTEXT_INT(PixelMaps.ItoI.Size), NO_EXTRA },
- { GL_PIXEL_MAP_I_TO_R_SIZE, CONTEXT_INT(PixelMaps.ItoR.Size), NO_EXTRA },
- { GL_PIXEL_MAP_R_TO_R_SIZE, CONTEXT_INT(PixelMaps.RtoR.Size), NO_EXTRA },
- { GL_PIXEL_MAP_S_TO_S_SIZE, CONTEXT_INT(PixelMaps.StoS.Size), NO_EXTRA },
- { GL_POINT_SIZE_GRANULARITY, CONTEXT_FLOAT(Const.PointSizeGranularity), NO_EXTRA },
- { GL_POLYGON_MODE, CONTEXT_ENUM2(Polygon.FrontMode), NO_EXTRA },
- { GL_POLYGON_OFFSET_BIAS_EXT, CONTEXT_FLOAT(Polygon.OffsetUnits), NO_EXTRA },
- { GL_POLYGON_OFFSET_POINT, CONTEXT_BOOL(Polygon.OffsetPoint), NO_EXTRA },
- { GL_POLYGON_OFFSET_LINE, CONTEXT_BOOL(Polygon.OffsetLine), NO_EXTRA },
- { GL_POLYGON_SMOOTH, CONTEXT_BOOL(Polygon.SmoothFlag), NO_EXTRA },
- { GL_POLYGON_SMOOTH_HINT, CONTEXT_ENUM(Hint.PolygonSmooth), NO_EXTRA },
- { GL_POLYGON_STIPPLE, CONTEXT_BOOL(Polygon.StippleFlag), NO_EXTRA },
- { GL_READ_BUFFER, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
- { GL_RED_BIAS, CONTEXT_FLOAT(Pixel.RedBias), NO_EXTRA },
- { GL_RED_SCALE, CONTEXT_FLOAT(Pixel.RedScale), NO_EXTRA },
- { GL_RENDER_MODE, CONTEXT_ENUM(RenderMode), NO_EXTRA },
- { GL_RGBA_MODE, CONST(1), NO_EXTRA },
- { GL_SELECTION_BUFFER_SIZE, CONTEXT_INT(Select.BufferSize), NO_EXTRA },
- { GL_SHARED_TEXTURE_PALETTE_EXT, CONTEXT_BOOL(Texture.SharedPalette), NO_EXTRA },
-
- { GL_STEREO, BUFFER_INT(Visual.stereoMode), NO_EXTRA },
-
- { GL_TEXTURE_1D, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
- { GL_TEXTURE_3D, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
- { GL_TEXTURE_1D_ARRAY_EXT, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
- { GL_TEXTURE_2D_ARRAY_EXT, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
-
- { GL_TEXTURE_BINDING_1D, LOC_CUSTOM, TYPE_INT, TEXTURE_1D_INDEX, NO_EXTRA },
- { GL_TEXTURE_BINDING_1D_ARRAY, LOC_CUSTOM, TYPE_INT,
- TEXTURE_1D_ARRAY_INDEX, extra_MESA_texture_array },
- { GL_TEXTURE_BINDING_2D_ARRAY, LOC_CUSTOM, TYPE_INT,
- TEXTURE_1D_ARRAY_INDEX, extra_MESA_texture_array },
- { GL_MAX_ARRAY_TEXTURE_LAYERS_EXT,
- CONTEXT_INT(Const.MaxArrayTextureLayers), extra_MESA_texture_array },
-
- { GL_TEXTURE_GEN_S, LOC_TEXUNIT, TYPE_BIT_0,
- offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
- { GL_TEXTURE_GEN_T, LOC_TEXUNIT, TYPE_BIT_1,
- offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
- { GL_TEXTURE_GEN_R, LOC_TEXUNIT, TYPE_BIT_2,
- offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
- { GL_TEXTURE_GEN_Q, LOC_TEXUNIT, TYPE_BIT_3,
- offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
- { GL_UNPACK_LSB_FIRST, CONTEXT_BOOL(Unpack.LsbFirst), NO_EXTRA },
- { GL_UNPACK_ROW_LENGTH, CONTEXT_INT(Unpack.RowLength), NO_EXTRA },
- { GL_UNPACK_SKIP_PIXELS, CONTEXT_INT(Unpack.SkipPixels), NO_EXTRA },
- { GL_UNPACK_SKIP_ROWS, CONTEXT_INT(Unpack.SkipRows), NO_EXTRA },
- { GL_UNPACK_SWAP_BYTES, CONTEXT_BOOL(Unpack.SwapBytes), NO_EXTRA },
- { GL_UNPACK_SKIP_IMAGES_EXT, CONTEXT_INT(Unpack.SkipImages), NO_EXTRA },
- { GL_UNPACK_IMAGE_HEIGHT_EXT, CONTEXT_INT(Unpack.ImageHeight), NO_EXTRA },
- { GL_UNPACK_CLIENT_STORAGE_APPLE, CONTEXT_BOOL(Unpack.ClientStorage), NO_EXTRA },
- { GL_ZOOM_X, CONTEXT_FLOAT(Pixel.ZoomX), NO_EXTRA },
- { GL_ZOOM_Y, CONTEXT_FLOAT(Pixel.ZoomY), NO_EXTRA },
-
- /* Vertex arrays */
- { GL_VERTEX_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
- { GL_NORMAL_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
- { GL_COLOR_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
- { GL_INDEX_ARRAY, ARRAY_BOOL(Index.Enabled), NO_EXTRA },
- { GL_INDEX_ARRAY_TYPE, ARRAY_ENUM(Index.Type), NO_EXTRA },
- { GL_INDEX_ARRAY_STRIDE, ARRAY_INT(Index.Stride), NO_EXTRA },
- { GL_INDEX_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
- { GL_TEXTURE_COORD_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
- { GL_EDGE_FLAG_ARRAY, ARRAY_BOOL(EdgeFlag.Enabled), NO_EXTRA },
- { GL_EDGE_FLAG_ARRAY_STRIDE, ARRAY_INT(EdgeFlag.Stride), NO_EXTRA },
- { GL_EDGE_FLAG_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
-
- /* GL_ARB_texture_compression */
- { GL_TEXTURE_COMPRESSION_HINT_ARB, CONTEXT_INT(Hint.TextureCompression), NO_EXTRA },
-
- /* GL_EXT_compiled_vertex_array */
- { GL_ARRAY_ELEMENT_LOCK_FIRST_EXT, CONTEXT_INT(Array.LockFirst),
- extra_EXT_compiled_vertex_array },
- { GL_ARRAY_ELEMENT_LOCK_COUNT_EXT, CONTEXT_INT(Array.LockCount),
- extra_EXT_compiled_vertex_array },
-
- /* GL_ARB_transpose_matrix */
- { GL_TRANSPOSE_MODELVIEW_MATRIX_ARB,
- CONTEXT_MATRIX_T(ModelviewMatrixStack), NO_EXTRA },
- { GL_TRANSPOSE_PROJECTION_MATRIX_ARB,
- CONTEXT_MATRIX_T(ProjectionMatrixStack.Top), NO_EXTRA },
- { GL_TRANSPOSE_TEXTURE_MATRIX_ARB, CONTEXT_MATRIX_T(TextureMatrixStack), NO_EXTRA },
-
- /* GL_SGI_texture_color_table */
- { GL_TEXTURE_COLOR_TABLE_SGI, LOC_TEXUNIT, TYPE_BOOLEAN,
- offsetof(struct gl_texture_unit, ColorTableEnabled),
- extra_SGI_texture_color_table },
-
- /* GL_EXT_secondary_color */
- { GL_COLOR_SUM_EXT, CONTEXT_BOOL(Fog.ColorSumEnabled),
- extra_EXT_secondary_color_ARB_vertex_program },
- { GL_CURRENT_SECONDARY_COLOR_EXT,
- CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_COLOR1][0], TYPE_FLOATN_4),
- extra_EXT_secondary_color_flush_current },
- { GL_SECONDARY_COLOR_ARRAY_EXT, ARRAY_BOOL(SecondaryColor.Enabled),
- extra_EXT_secondary_color },
- { GL_SECONDARY_COLOR_ARRAY_TYPE_EXT, ARRAY_ENUM(SecondaryColor.Type),
- extra_EXT_secondary_color },
- { GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT, ARRAY_INT(SecondaryColor.Stride),
- extra_EXT_secondary_color },
- { GL_SECONDARY_COLOR_ARRAY_SIZE_EXT, ARRAY_INT(SecondaryColor.Size),
- extra_EXT_secondary_color },
-
- /* GL_EXT_fog_coord */
- { GL_CURRENT_FOG_COORDINATE_EXT,
- CONTEXT_FLOAT(Current.Attrib[VERT_ATTRIB_FOG][0]),
- extra_EXT_fog_coord_flush_current },
- { GL_FOG_COORDINATE_ARRAY_EXT, ARRAY_BOOL(FogCoord.Enabled),
- extra_EXT_fog_coord },
- { GL_FOG_COORDINATE_ARRAY_TYPE_EXT, ARRAY_ENUM(FogCoord.Type),
- extra_EXT_fog_coord },
- { GL_FOG_COORDINATE_ARRAY_STRIDE_EXT, ARRAY_INT(FogCoord.Stride),
- extra_EXT_fog_coord },
- { GL_FOG_COORDINATE_SOURCE_EXT, CONTEXT_ENUM(Fog.FogCoordinateSource),
- extra_EXT_fog_coord },
-
- /* GL_IBM_rasterpos_clip */
- { GL_RASTER_POSITION_UNCLIPPED_IBM,
- CONTEXT_BOOL(Transform.RasterPositionUnclipped),
- extra_IBM_rasterpos_clip },
-
- /* GL_NV_point_sprite */
- { GL_POINT_SPRITE_R_MODE_NV,
- CONTEXT_ENUM(Point.SpriteRMode), extra_NV_point_sprite },
- { GL_POINT_SPRITE_COORD_ORIGIN, CONTEXT_ENUM(Point.SpriteOrigin),
- extra_NV_point_sprite_ARB_point_sprite },
-
- /* GL_NV_vertex_program */
- { GL_VERTEX_PROGRAM_BINDING_NV, LOC_CUSTOM, TYPE_INT, 0,
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY0_NV, ARRAY_BOOL(VertexAttrib[0].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY1_NV, ARRAY_BOOL(VertexAttrib[1].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY2_NV, ARRAY_BOOL(VertexAttrib[2].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY3_NV, ARRAY_BOOL(VertexAttrib[3].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY4_NV, ARRAY_BOOL(VertexAttrib[4].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY5_NV, ARRAY_BOOL(VertexAttrib[5].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY6_NV, ARRAY_BOOL(VertexAttrib[6].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY7_NV, ARRAY_BOOL(VertexAttrib[7].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY8_NV, ARRAY_BOOL(VertexAttrib[8].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY9_NV, ARRAY_BOOL(VertexAttrib[9].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY10_NV, ARRAY_BOOL(VertexAttrib[10].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY11_NV, ARRAY_BOOL(VertexAttrib[11].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY12_NV, ARRAY_BOOL(VertexAttrib[12].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY13_NV, ARRAY_BOOL(VertexAttrib[13].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY14_NV, ARRAY_BOOL(VertexAttrib[14].Enabled),
- extra_NV_vertex_program },
- { GL_VERTEX_ATTRIB_ARRAY15_NV, ARRAY_BOOL(VertexAttrib[15].Enabled),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB0_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[0]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB1_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[1]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB2_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[2]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB3_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[3]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB4_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[4]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB5_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[5]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB6_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[6]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB7_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[7]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB8_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[8]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB9_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[9]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB10_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[10]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB11_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[11]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB12_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[12]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB13_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[13]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB14_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[14]),
- extra_NV_vertex_program },
- { GL_MAP1_VERTEX_ATTRIB15_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[15]),
- extra_NV_vertex_program },
-
- /* GL_NV_fragment_program */
- { GL_FRAGMENT_PROGRAM_NV, CONTEXT_BOOL(FragmentProgram.Enabled),
- extra_NV_fragment_program },
- { GL_FRAGMENT_PROGRAM_BINDING_NV, LOC_CUSTOM, TYPE_INT, 0,
- extra_NV_fragment_program },
- { GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV,
- CONST(MAX_NV_FRAGMENT_PROGRAM_PARAMS),
- extra_NV_fragment_program },
-
- /* GL_NV_texture_rectangle */
- { GL_TEXTURE_RECTANGLE_NV,
- LOC_CUSTOM, TYPE_BOOLEAN, 0, extra_NV_texture_rectangle },
- { GL_TEXTURE_BINDING_RECTANGLE_NV,
- LOC_CUSTOM, TYPE_INT, TEXTURE_RECT_INDEX, extra_NV_texture_rectangle },
- { GL_MAX_RECTANGLE_TEXTURE_SIZE_NV,
- CONTEXT_INT(Const.MaxTextureRectSize), extra_NV_texture_rectangle },
-
- /* GL_EXT_stencil_two_side */
- { GL_STENCIL_TEST_TWO_SIDE_EXT, CONTEXT_BOOL(Stencil.TestTwoSide),
- extra_EXT_stencil_two_side },
- { GL_ACTIVE_STENCIL_FACE_EXT, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
-
- /* GL_NV_light_max_exponent */
- { GL_MAX_SHININESS_NV, CONTEXT_FLOAT(Const.MaxShininess),
- extra_NV_light_max_exponent },
- { GL_MAX_SPOT_EXPONENT_NV, CONTEXT_FLOAT(Const.MaxSpotExponent),
- extra_NV_light_max_exponent },
-
- /* GL_NV_primitive_restart */
- { GL_PRIMITIVE_RESTART_NV, CONTEXT_BOOL(Array.PrimitiveRestart),
- extra_NV_primitive_restart },
- { GL_PRIMITIVE_RESTART_INDEX_NV, CONTEXT_INT(Array.RestartIndex),
- extra_NV_primitive_restart },
-
- /* GL_ARB_vertex_buffer_object */
- { GL_INDEX_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_array_object, Index.BufferObj), NO_EXTRA },
- { GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_array_object, EdgeFlag.BufferObj), NO_EXTRA },
- { GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_array_object, SecondaryColor.BufferObj), NO_EXTRA },
- { GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
- offsetof(struct gl_array_object, FogCoord.BufferObj), NO_EXTRA },
-
- /* GL_EXT_pixel_buffer_object */
- { GL_PIXEL_PACK_BUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
- extra_EXT_pixel_buffer_object },
- { GL_PIXEL_UNPACK_BUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
- extra_EXT_pixel_buffer_object },
-
- /* GL_ARB_vertex_program */
- { GL_VERTEX_PROGRAM_ARB, /* == GL_VERTEX_PROGRAM_NV */
- CONTEXT_BOOL(VertexProgram.Enabled),
- extra_ARB_vertex_program_NV_vertex_program },
- { GL_VERTEX_PROGRAM_POINT_SIZE_ARB, /* == GL_VERTEX_PROGRAM_POINT_SIZE_NV*/
- CONTEXT_BOOL(VertexProgram.PointSizeEnabled),
- extra_ARB_vertex_program_NV_vertex_program },
- { GL_VERTEX_PROGRAM_TWO_SIDE_ARB, /* == GL_VERTEX_PROGRAM_TWO_SIDE_NV */
- CONTEXT_BOOL(VertexProgram.TwoSideEnabled),
- extra_ARB_vertex_program_NV_vertex_program },
- { GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB, /* == GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV */
- CONTEXT_INT(Const.MaxProgramMatrixStackDepth),
- extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
- { GL_MAX_PROGRAM_MATRICES_ARB, /* == GL_MAX_TRACK_MATRICES_NV */
- CONTEXT_INT(Const.MaxProgramMatrices),
- extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
- { GL_CURRENT_MATRIX_STACK_DEPTH_ARB, /* == GL_CURRENT_MATRIX_STACK_DEPTH_NV */
- LOC_CUSTOM, TYPE_INT, 0,
- extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
-
- { GL_CURRENT_MATRIX_ARB, /* == GL_CURRENT_MATRIX_NV */
- LOC_CUSTOM, TYPE_MATRIX, 0,
- extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
- { GL_TRANSPOSE_CURRENT_MATRIX_ARB, /* == GL_CURRENT_MATRIX_NV */
- LOC_CUSTOM, TYPE_MATRIX, 0,
- extra_ARB_vertex_program_ARB_fragment_program },
-
- { GL_PROGRAM_ERROR_POSITION_ARB, /* == GL_PROGRAM_ERROR_POSITION_NV */
- CONTEXT_INT(Program.ErrorPos),
- extra_NV_vertex_program_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
-
- /* GL_ARB_fragment_program */
- { GL_FRAGMENT_PROGRAM_ARB, CONTEXT_BOOL(FragmentProgram.Enabled),
- extra_ARB_fragment_program },
-
- /* GL_EXT_depth_bounds_test */
- { GL_DEPTH_BOUNDS_TEST_EXT, CONTEXT_BOOL(Depth.BoundsTest),
- extra_EXT_depth_bounds_test },
- { GL_DEPTH_BOUNDS_EXT, CONTEXT_FLOAT2(Depth.BoundsMin),
- extra_EXT_depth_bounds_test },
-
- /* GL_ARB_depth_clamp*/
- { GL_DEPTH_CLAMP, CONTEXT_BOOL(Transform.DepthClamp),
- extra_ARB_depth_clamp },
-
- /* GL_ARB_draw_buffers */
- { GL_DRAW_BUFFER0_ARB, BUFFER_ENUM(ColorDrawBuffer[0]), NO_EXTRA },
- { GL_DRAW_BUFFER1_ARB, BUFFER_ENUM(ColorDrawBuffer[1]),
- extra_valid_draw_buffer },
- { GL_DRAW_BUFFER2_ARB, BUFFER_ENUM(ColorDrawBuffer[2]),
- extra_valid_draw_buffer },
- { GL_DRAW_BUFFER3_ARB, BUFFER_ENUM(ColorDrawBuffer[3]),
- extra_valid_draw_buffer },
- { GL_DRAW_BUFFER4_ARB, BUFFER_ENUM(ColorDrawBuffer[4]),
- extra_valid_draw_buffer },
- { GL_DRAW_BUFFER5_ARB, BUFFER_ENUM(ColorDrawBuffer[5]),
- extra_valid_draw_buffer },
- { GL_DRAW_BUFFER6_ARB, BUFFER_ENUM(ColorDrawBuffer[6]),
- extra_valid_draw_buffer },
- { GL_DRAW_BUFFER7_ARB, BUFFER_ENUM(ColorDrawBuffer[7]),
- extra_valid_draw_buffer },
-
- /* GL_ATI_fragment_shader */
- { GL_NUM_FRAGMENT_REGISTERS_ATI, CONST(6), extra_ATI_fragment_shader },
- { GL_NUM_FRAGMENT_CONSTANTS_ATI, CONST(8), extra_ATI_fragment_shader },
- { GL_NUM_PASSES_ATI, CONST(2), extra_ATI_fragment_shader },
- { GL_NUM_INSTRUCTIONS_PER_PASS_ATI, CONST(8), extra_ATI_fragment_shader },
- { GL_NUM_INSTRUCTIONS_TOTAL_ATI, CONST(16), extra_ATI_fragment_shader },
- { GL_COLOR_ALPHA_PAIRING_ATI, CONST(GL_TRUE), extra_ATI_fragment_shader },
- { GL_NUM_LOOPBACK_COMPONENTS_ATI, CONST(3), extra_ATI_fragment_shader },
- { GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI,
- CONST(3), extra_ATI_fragment_shader },
-
- /* GL_EXT_framebuffer_object */
- { GL_MAX_COLOR_ATTACHMENTS_EXT, CONTEXT_INT(Const.MaxColorAttachments),
- extra_EXT_framebuffer_object },
-
- /* GL_EXT_framebuffer_blit
- * NOTE: GL_DRAW_FRAMEBUFFER_BINDING_EXT == GL_FRAMEBUFFER_BINDING_EXT */
- { GL_READ_FRAMEBUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
- extra_EXT_framebuffer_blit },
-
- /* GL_EXT_provoking_vertex */
- { GL_PROVOKING_VERTEX_EXT,
- CONTEXT_BOOL(Light.ProvokingVertex), extra_EXT_provoking_vertex },
- { GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT,
- CONTEXT_BOOL(Const.QuadsFollowProvokingVertexConvention),
- extra_EXT_provoking_vertex },
-
- /* GL_ARB_framebuffer_object */
- { GL_MAX_SAMPLES, CONTEXT_INT(Const.MaxSamples),
- extra_ARB_framebuffer_object_EXT_framebuffer_multisample },
-
- /* GL_APPLE_vertex_array_object */
- { GL_VERTEX_ARRAY_BINDING_APPLE, ARRAY_INT(Name),
- extra_APPLE_vertex_array_object },
-
- /* GL_ARB_seamless_cube_map */
- { GL_TEXTURE_CUBE_MAP_SEAMLESS,
- CONTEXT_BOOL(Texture.CubeMapSeamless), extra_ARB_seamless_cube_map },
-
- /* GL_ARB_sync */
- { GL_MAX_SERVER_WAIT_TIMEOUT,
- CONTEXT_INT64(Const.MaxServerWaitTimeout), extra_ARB_sync },
-
- /* GL_EXT_texture_integer */
- { GL_RGBA_INTEGER_MODE_EXT, BUFFER_BOOL(_IntegerColor),
- extra_EXT_texture_integer },
-
- /* GL_EXT_transform_feedback */
- { GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, LOC_CUSTOM, TYPE_INT, 0,
- extra_EXT_transform_feedback },
- { GL_RASTERIZER_DISCARD, CONTEXT_BOOL(TransformFeedback.RasterDiscard),
- extra_EXT_transform_feedback },
- { GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
- CONTEXT_INT(Const.MaxTransformFeedbackInterleavedComponents),
- extra_EXT_transform_feedback },
- { GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
- CONTEXT_INT(Const.MaxTransformFeedbackSeparateAttribs),
- extra_EXT_transform_feedback },
- { GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
- CONTEXT_INT(Const.MaxTransformFeedbackSeparateComponents),
- extra_EXT_transform_feedback },
-
- /* GL_ARB_transform_feedback2 */
- { GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED, LOC_CUSTOM, TYPE_BOOLEAN, 0,
- extra_ARB_transform_feedback2 },
- { GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE, LOC_CUSTOM, TYPE_BOOLEAN, 0,
- extra_ARB_transform_feedback2 },
- { GL_TRANSFORM_FEEDBACK_BINDING, LOC_CUSTOM, TYPE_INT, 0,
- extra_ARB_transform_feedback2 },
-
- /* GL_ARB_geometry_shader4 */
- { GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB,
- CONTEXT_INT(Const.GeometryProgram.MaxGeometryTextureImageUnits),
- extra_ARB_geometry_shader4 },
- { GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB,
- CONTEXT_INT(Const.GeometryProgram.MaxGeometryOutputVertices),
- extra_ARB_geometry_shader4 },
- { GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB,
- CONTEXT_INT(Const.GeometryProgram.MaxGeometryTotalOutputComponents),
- extra_ARB_geometry_shader4 },
- { GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB,
- CONTEXT_INT(Const.GeometryProgram.MaxGeometryUniformComponents),
- extra_ARB_geometry_shader4 },
- { GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB,
- CONTEXT_INT(Const.GeometryProgram.MaxGeometryVaryingComponents),
- extra_ARB_geometry_shader4 },
- { GL_MAX_VERTEX_VARYING_COMPONENTS_ARB,
- CONTEXT_INT(Const.GeometryProgram.MaxVertexVaryingComponents),
- extra_ARB_geometry_shader4 },
-
- /* GL_EXT_gpu_shader4 / GL 3.0 */
- { GL_MIN_PROGRAM_TEXEL_OFFSET,
- CONTEXT_INT(Const.MinProgramTexelOffset),
- extra_EXT_gpu_shader4 },
- { GL_MAX_PROGRAM_TEXEL_OFFSET,
- CONTEXT_INT(Const.MaxProgramTexelOffset),
- extra_EXT_gpu_shader4 },
-
- /* GL 3.0 */
- { GL_NUM_EXTENSIONS, LOC_CUSTOM, TYPE_INT, 0, extra_version_30 },
- { GL_MAJOR_VERSION, CONTEXT_INT(VersionMajor), extra_version_30 },
- { GL_MINOR_VERSION, CONTEXT_INT(VersionMinor), extra_version_30 },
- { GL_CONTEXT_FLAGS, CONTEXT_INT(Const.ContextFlags), extra_version_30 },
-
- /* GL3.0 / GL_EXT_framebuffer_sRGB */
- { GL_FRAMEBUFFER_SRGB_EXT, CONTEXT_BOOL(Color.sRGBEnabled), extra_EXT_framebuffer_sRGB },
- { GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, BUFFER_INT(Visual.sRGBCapable), extra_EXT_framebuffer_sRGB },
-
- /* GL 3.1 */
- /* NOTE: different enum values for GL_PRIMITIVE_RESTART_NV
- * vs. GL_PRIMITIVE_RESTART!
- */
- { GL_PRIMITIVE_RESTART, CONTEXT_BOOL(Array.PrimitiveRestart),
- extra_version_31 },
- { GL_PRIMITIVE_RESTART_INDEX, CONTEXT_INT(Array.RestartIndex),
- extra_version_31 },
-
-
- /* GL 3.2 */
- { GL_CONTEXT_PROFILE_MASK, CONTEXT_INT(Const.ProfileMask),
- extra_version_32 },
-#endif /* FEATURE_GL */
-};
-
-/* All we need now is a way to look up the value struct from the enum.
- * The code generated by gcc for the old generated big switch
- * statement is a big, balanced, open coded if/else tree, essentially
- * an unrolled binary search. It would be natural to sort the new
- * enum table and use bsearch(), but we will use a read-only hash
- * table instead. bsearch() has a nice guaranteed worst case
- * performance, but we're also guaranteed to hit that worst case
- * (log2(n) iterations) for about half the enums. Instead, using an
- * open addressing hash table, we can find the enum on the first try
- * for 80% of the enums, 1 collision for 10% and never more than 5
- * collisions for any enum (typical numbers). And the code is very
- * simple, even though it feels a little magic. */
-
-static unsigned short table[1024];
-static const int prime_factor = 89, prime_step = 281;
-
-#ifdef GET_DEBUG
-static void
-print_table_stats(void)
-{
- int i, j, collisions[11], count, hash, mask;
- const struct value_desc *d;
-
- count = 0;
- mask = Elements(table) - 1;
- memset(collisions, 0, sizeof collisions);
-
- for (i = 0; i < Elements(table); i++) {
- if (!table[i])
- continue;
- count++;
- d = &values[table[i]];
- hash = (d->pname * prime_factor);
- j = 0;
- while (1) {
- if (values[table[hash & mask]].pname == d->pname)
- break;
- hash += prime_step;
- j++;
- }
-
- if (j < 10)
- collisions[j]++;
- else
- collisions[10]++;
- }
-
- printf("number of enums: %d (total %d)\n", count, Elements(values));
- for (i = 0; i < Elements(collisions) - 1; i++)
- if (collisions[i] > 0)
- printf(" %d enums with %d %scollisions\n",
- collisions[i], i, i == 10 ? "or more " : "");
-}
-#endif
-
-/**
- * Initialize the enum hash for a given API
- *
- * This is called from one_time_init() to insert the enum values that
- * are valid for the API in question into the enum hash table.
- *
- * \param the current context, for determining the API in question
- */
-void _mesa_init_get_hash(struct gl_context *ctx)
-{
- int i, hash, index, mask;
- int api_mask = 0, api_bit;
-
- mask = Elements(table) - 1;
- api_bit = 1 << ctx->API;
-
- for (i = 0; i < Elements(values); i++) {
- if (values[i].type == TYPE_API_MASK) {
- api_mask = values[i].offset;
- continue;
- }
- if (!(api_mask & api_bit))
- continue;
-
- hash = (values[i].pname * prime_factor) & mask;
- while (1) {
- index = hash & mask;
- if (!table[index]) {
- table[index] = i;
- break;
- }
- hash += prime_step;
- }
- }
-
-#ifdef GET_DEBUG
- print_table_stats();
-#endif
-}
-
-/**
- * Handle irregular enums
- *
- * Some values don't conform to the "well-known type at context
- * pointer + offset" pattern, so we have this function to catch all
- * the corner cases. Typically, it's a computed value or a one-off
- * pointer to a custom struct or something.
- *
- * In this case we can't return a pointer to the value, so we'll have
- * to use the temporary variable 'v' declared back in the calling
- * glGet*v() function to store the result.
- *
- * \param ctx the current context
- * \param d the struct value_desc that describes the enum
- * \param v pointer to the tmp declared in the calling glGet*v() function
- */
-static void
-find_custom_value(struct gl_context *ctx, const struct value_desc *d, union value *v)
-{
- struct gl_buffer_object *buffer_obj;
- struct gl_client_array *array;
- GLuint unit, *p;
-
- switch (d->pname) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_TEXTURE_CUBE_MAP_ARB:
- case GL_TEXTURE_RECTANGLE_NV:
- v->value_bool = _mesa_IsEnabled(d->pname);
- break;
-
- case GL_LINE_STIPPLE_PATTERN:
- /* This is the only GLushort, special case it here by promoting
- * to an int rather than introducing a new type. */
- v->value_int = ctx->Line.StipplePattern;
- break;
-
- case GL_CURRENT_RASTER_TEXTURE_COORDS:
- unit = ctx->Texture.CurrentUnit;
- v->value_float_4[0] = ctx->Current.RasterTexCoords[unit][0];
- v->value_float_4[1] = ctx->Current.RasterTexCoords[unit][1];
- v->value_float_4[2] = ctx->Current.RasterTexCoords[unit][2];
- v->value_float_4[3] = ctx->Current.RasterTexCoords[unit][3];
- break;
-
- case GL_CURRENT_TEXTURE_COORDS:
- unit = ctx->Texture.CurrentUnit;
- v->value_float_4[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][0];
- v->value_float_4[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][1];
- v->value_float_4[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][2];
- v->value_float_4[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][3];
- break;
-
- case GL_COLOR_WRITEMASK:
- v->value_int_4[0] = ctx->Color.ColorMask[0][RCOMP] ? 1 : 0;
- v->value_int_4[1] = ctx->Color.ColorMask[0][GCOMP] ? 1 : 0;
- v->value_int_4[2] = ctx->Color.ColorMask[0][BCOMP] ? 1 : 0;
- v->value_int_4[3] = ctx->Color.ColorMask[0][ACOMP] ? 1 : 0;
- break;
-
- case GL_EDGE_FLAG:
- v->value_bool = ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0;
- break;
-
- case GL_READ_BUFFER:
- v->value_enum = ctx->ReadBuffer->ColorReadBuffer;
- break;
-
- case GL_MAP2_GRID_DOMAIN:
- v->value_float_4[0] = ctx->Eval.MapGrid2u1;
- v->value_float_4[1] = ctx->Eval.MapGrid2u2;
- v->value_float_4[2] = ctx->Eval.MapGrid2v1;
- v->value_float_4[3] = ctx->Eval.MapGrid2v2;
- break;
-
- case GL_TEXTURE_STACK_DEPTH:
- unit = ctx->Texture.CurrentUnit;
- v->value_int = ctx->TextureMatrixStack[unit].Depth + 1;
- break;
- case GL_TEXTURE_MATRIX:
- unit = ctx->Texture.CurrentUnit;
- v->value_matrix = ctx->TextureMatrixStack[unit].Top;
- break;
-
- case GL_TEXTURE_COORD_ARRAY:
- case GL_TEXTURE_COORD_ARRAY_SIZE:
- case GL_TEXTURE_COORD_ARRAY_TYPE:
- case GL_TEXTURE_COORD_ARRAY_STRIDE:
- array = &ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture];
- v->value_int = *(GLuint *) ((char *) array + d->offset);
- break;
-
- case GL_ACTIVE_TEXTURE_ARB:
- v->value_int = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit;
- break;
- case GL_CLIENT_ACTIVE_TEXTURE_ARB:
- v->value_int = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture;
- break;
-
- case GL_MODELVIEW_STACK_DEPTH:
- case GL_PROJECTION_STACK_DEPTH:
- v->value_int = *(GLint *) ((char *) ctx + d->offset) + 1;
- break;
-
- case GL_MAX_TEXTURE_SIZE:
- case GL_MAX_3D_TEXTURE_SIZE:
- case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
- p = (GLuint *) ((char *) ctx + d->offset);
- v->value_int = 1 << (*p - 1);
- break;
-
- case GL_SCISSOR_BOX:
- v->value_int_4[0] = ctx->Scissor.X;
- v->value_int_4[1] = ctx->Scissor.Y;
- v->value_int_4[2] = ctx->Scissor.Width;
- v->value_int_4[3] = ctx->Scissor.Height;
- break;
-
- case GL_LIST_INDEX:
- v->value_int =
- ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0;
- break;
- case GL_LIST_MODE:
- if (!ctx->CompileFlag)
- v->value_enum = 0;
- else if (ctx->ExecuteFlag)
- v->value_enum = GL_COMPILE_AND_EXECUTE;
- else
- v->value_enum = GL_COMPILE;
- break;
-
- case GL_VIEWPORT:
- v->value_int_4[0] = ctx->Viewport.X;
- v->value_int_4[1] = ctx->Viewport.Y;
- v->value_int_4[2] = ctx->Viewport.Width;
- v->value_int_4[3] = ctx->Viewport.Height;
- break;
-
- case GL_ACTIVE_STENCIL_FACE_EXT:
- v->value_enum = ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT;
- break;
-
- case GL_STENCIL_FAIL:
- v->value_enum = ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace];
- break;
- case GL_STENCIL_FUNC:
- v->value_enum = ctx->Stencil.Function[ctx->Stencil.ActiveFace];
- break;
- case GL_STENCIL_PASS_DEPTH_FAIL:
- v->value_enum = ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace];
- break;
- case GL_STENCIL_PASS_DEPTH_PASS:
- v->value_enum = ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace];
- break;
- case GL_STENCIL_REF:
- v->value_int = ctx->Stencil.Ref[ctx->Stencil.ActiveFace];
- break;
- case GL_STENCIL_VALUE_MASK:
- v->value_int = ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace];
- break;
- case GL_STENCIL_WRITEMASK:
- v->value_int = ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace];
- break;
-
- case GL_NUM_EXTENSIONS:
- v->value_int = _mesa_get_extension_count(ctx);
- break;
-
- case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
- v->value_int = _mesa_get_color_read_type(ctx);
- break;
- case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
- v->value_int = _mesa_get_color_read_format(ctx);
- break;
-
- case GL_CURRENT_MATRIX_STACK_DEPTH_ARB:
- v->value_int = ctx->CurrentStack->Depth + 1;
- break;
- case GL_CURRENT_MATRIX_ARB:
- case GL_TRANSPOSE_CURRENT_MATRIX_ARB:
- v->value_matrix = ctx->CurrentStack->Top;
- break;
-
- case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
- v->value_int = _mesa_get_compressed_formats(ctx, NULL, GL_FALSE);
- break;
- case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
- v->value_int_n.n =
- _mesa_get_compressed_formats(ctx, v->value_int_n.ints, GL_FALSE);
- ASSERT(v->value_int_n.n <= 100);
- break;
-
- case GL_MAX_VARYING_FLOATS_ARB:
- v->value_int = ctx->Const.MaxVarying * 4;
- break;
-
- /* Various object names */
-
- case GL_TEXTURE_BINDING_1D:
- case GL_TEXTURE_BINDING_2D:
- case GL_TEXTURE_BINDING_3D:
- case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
- case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
- case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
- case GL_TEXTURE_BINDING_RECTANGLE_NV:
- unit = ctx->Texture.CurrentUnit;
- v->value_int =
- ctx->Texture.Unit[unit].CurrentTex[d->offset]->Name;
- break;
-
- /* GL_ARB_vertex_buffer_object */
- case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
- case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
- case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
- case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
- case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
- case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
- case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
- buffer_obj = (struct gl_buffer_object *)
- ((char *) ctx->Array.ArrayObj + d->offset);
- v->value_int = buffer_obj->Name;
- break;
- case GL_ARRAY_BUFFER_BINDING_ARB:
- v->value_int = ctx->Array.ArrayBufferObj->Name;
- break;
- case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
- v->value_int =
- ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name;
- break;
- case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
- v->value_int = ctx->Array.ElementArrayBufferObj->Name;
- break;
-
- /* ARB_copy_buffer */
- case GL_COPY_READ_BUFFER:
- v->value_int = ctx->CopyReadBuffer->Name;
- break;
- case GL_COPY_WRITE_BUFFER:
- v->value_int = ctx->CopyWriteBuffer->Name;
- break;
-
- case GL_FRAGMENT_PROGRAM_BINDING_NV:
- v->value_int =
- ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0;
- break;
- case GL_VERTEX_PROGRAM_BINDING_NV:
- v->value_int =
- ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0;
- break;
- case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
- v->value_int = ctx->Pack.BufferObj->Name;
- break;
- case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
- v->value_int = ctx->Unpack.BufferObj->Name;
- break;
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- v->value_int = ctx->TransformFeedback.CurrentBuffer->Name;
- break;
- case GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED:
- v->value_int = ctx->TransformFeedback.CurrentObject->Paused;
- break;
- case GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE:
- v->value_int = ctx->TransformFeedback.CurrentObject->Active;
- break;
- case GL_TRANSFORM_FEEDBACK_BINDING:
- v->value_int = ctx->TransformFeedback.CurrentObject->Name;
- break;
- case GL_CURRENT_PROGRAM:
- v->value_int =
- ctx->Shader.ActiveProgram ? ctx->Shader.ActiveProgram->Name : 0;
- break;
- case GL_READ_FRAMEBUFFER_BINDING_EXT:
- v->value_int = ctx->ReadBuffer->Name;
- break;
- case GL_RENDERBUFFER_BINDING_EXT:
- v->value_int =
- ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0;
- break;
- case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
- v->value_int = ctx->Array.ArrayObj->PointSize.BufferObj->Name;
- break;
-
- case GL_MAX_VERTEX_UNIFORM_VECTORS:
- v->value_int = ctx->Const.VertexProgram.MaxUniformComponents / 4;
- break;
-
- case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
- v->value_int = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
- break;
- }
-}
-
-/**
- * Check extra constraints on a struct value_desc descriptor
- *
- * If a struct value_desc has a non-NULL extra pointer, it means that
- * there are a number of extra constraints to check or actions to
- * perform. The extras is just an integer array where each integer
- * encode different constraints or actions.
- *
- * \param ctx current context
- * \param func name of calling glGet*v() function for error reporting
- * \param d the struct value_desc that has the extra constraints
- *
- * \return GL_FALSE if one of the constraints was not satisfied,
- * otherwise GL_TRUE.
- */
-static GLboolean
-check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d)
-{
- const GLuint version = ctx->VersionMajor * 10 + ctx->VersionMinor;
- int total, enabled;
- const int *e;
-
- total = 0;
- enabled = 0;
- for (e = d->extra; *e != EXTRA_END; e++)
- switch (*e) {
- case EXTRA_VERSION_30:
- if (version >= 30) {
- total++;
- enabled++;
- }
- break;
- case EXTRA_VERSION_31:
- if (version >= 31) {
- total++;
- enabled++;
- }
- break;
- case EXTRA_VERSION_32:
- if (version >= 32) {
- total++;
- enabled++;
- }
- break;
- case EXTRA_VERSION_ES2:
- if (ctx->API == API_OPENGLES2) {
- total++;
- enabled++;
- }
- break;
- case EXTRA_NEW_BUFFERS:
- if (ctx->NewState & _NEW_BUFFERS)
- _mesa_update_state(ctx);
- break;
- case EXTRA_FLUSH_CURRENT:
- FLUSH_CURRENT(ctx, 0);
- break;
- case EXTRA_VALID_DRAW_BUFFER:
- if (d->pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(draw buffer %u)",
- func, d->pname - GL_DRAW_BUFFER0_ARB);
- return GL_FALSE;
- }
- break;
- case EXTRA_VALID_TEXTURE_UNIT:
- if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture %u)",
- func, ctx->Texture.CurrentUnit);
- return GL_FALSE;
- }
- break;
- case EXTRA_END:
- break;
- default: /* *e is a offset into the extension struct */
- total++;
- if (*(GLboolean *) ((char *) &ctx->Extensions + *e))
- enabled++;
- break;
- }
-
- if (total > 0 && enabled == 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
- _mesa_lookup_enum_by_nr(d->pname));
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-static const struct value_desc error_value =
- { 0, 0, TYPE_INVALID, NO_OFFSET, NO_EXTRA };
-
-/**
- * Find the struct value_desc corresponding to the enum 'pname'.
- *
- * We hash the enum value to get an index into the 'table' array,
- * which holds the index in the 'values' array of struct value_desc.
- * Once we've found the entry, we do the extra checks, if any, then
- * look up the value and return a pointer to it.
- *
- * If the value has to be computed (for example, it's the result of a
- * function call or we need to add 1 to it), we use the tmp 'v' to
- * store the result.
- *
- * \param func name of glGet*v() func for error reporting
- * \param pname the enum value we're looking up
- * \param p is were we return the pointer to the value
- * \param v a tmp union value variable in the calling glGet*v() function
- *
- * \return the struct value_desc corresponding to the enum or a struct
- * value_desc of TYPE_INVALID if not found. This lets the calling
- * glGet*v() function jump right into a switch statement and
- * handle errors there instead of having to check for NULL.
- */
-static const struct value_desc *
-find_value(const char *func, GLenum pname, void **p, union value *v)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_unit *unit;
- int mask, hash;
- const struct value_desc *d;
-
- mask = Elements(table) - 1;
- hash = (pname * prime_factor);
- while (1) {
- d = &values[table[hash & mask]];
-
- /* If the enum isn't valid, the hash walk ends with index 0,
- * which is the API mask entry at the beginning of values[]. */
- if (unlikely(d->type == TYPE_API_MASK)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
- _mesa_lookup_enum_by_nr(pname));
- return &error_value;
- }
-
- if (likely(d->pname == pname))
- break;
-
- hash += prime_step;
- }
-
- if (unlikely(d->extra && !check_extra(ctx, func, d)))
- return &error_value;
-
- switch (d->location) {
- case LOC_BUFFER:
- *p = ((char *) ctx->DrawBuffer + d->offset);
- return d;
- case LOC_CONTEXT:
- *p = ((char *) ctx + d->offset);
- return d;
- case LOC_ARRAY:
- *p = ((char *) ctx->Array.ArrayObj + d->offset);
- return d;
- case LOC_TEXUNIT:
- unit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- *p = ((char *) unit + d->offset);
- return d;
- case LOC_CUSTOM:
- find_custom_value(ctx, d, v);
- *p = v;
- return d;
- default:
- assert(0);
- break;
- }
-
- /* silence warning */
- return &error_value;
-}
-
-static const int transpose[] = {
- 0, 4, 8, 12,
- 1, 5, 9, 13,
- 2, 6, 10, 14,
- 3, 7, 11, 15
-};
-
-void GLAPIENTRY
-_mesa_GetBooleanv(GLenum pname, GLboolean *params)
-{
- const struct value_desc *d;
- union value v;
- GLmatrix *m;
- int shift, i;
- void *p;
-
- d = find_value("glGetBooleanv", pname, &p, &v);
- switch (d->type) {
- case TYPE_INVALID:
- break;
- case TYPE_CONST:
- params[0] = INT_TO_BOOLEAN(d->offset);
- break;
-
- case TYPE_FLOAT_4:
- case TYPE_FLOATN_4:
- params[3] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[3]);
- case TYPE_FLOAT_3:
- case TYPE_FLOATN_3:
- params[2] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[2]);
- case TYPE_FLOAT_2:
- case TYPE_FLOATN_2:
- params[1] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[1]);
- case TYPE_FLOAT:
- case TYPE_FLOATN:
- params[0] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[0]);
- break;
-
- case TYPE_DOUBLEN:
- params[0] = FLOAT_TO_BOOLEAN(((GLdouble *) p)[0]);
- break;
-
- case TYPE_INT_4:
- params[3] = INT_TO_BOOLEAN(((GLint *) p)[3]);
- case TYPE_INT_3:
- params[2] = INT_TO_BOOLEAN(((GLint *) p)[2]);
- case TYPE_INT_2:
- case TYPE_ENUM_2:
- params[1] = INT_TO_BOOLEAN(((GLint *) p)[1]);
- case TYPE_INT:
- case TYPE_ENUM:
- params[0] = INT_TO_BOOLEAN(((GLint *) p)[0]);
- break;
-
- case TYPE_INT_N:
- for (i = 0; i < v.value_int_n.n; i++)
- params[i] = INT_TO_BOOLEAN(v.value_int_n.ints[i]);
- break;
-
- case TYPE_INT64:
- params[0] = INT64_TO_BOOLEAN(((GLint64 *) p)[0]);
- break;
-
- case TYPE_BOOLEAN:
- params[0] = ((GLboolean*) p)[0];
- break;
-
- case TYPE_MATRIX:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_BOOLEAN(m->m[i]);
- break;
-
- case TYPE_MATRIX_T:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_BOOLEAN(m->m[transpose[i]]);
- break;
-
- case TYPE_BIT_0:
- case TYPE_BIT_1:
- case TYPE_BIT_2:
- case TYPE_BIT_3:
- case TYPE_BIT_4:
- case TYPE_BIT_5:
- shift = d->type - TYPE_BIT_0;
- params[0] = (*(GLbitfield *) p >> shift) & 1;
- break;
- }
-}
-
-void GLAPIENTRY
-_mesa_GetFloatv(GLenum pname, GLfloat *params)
-{
- const struct value_desc *d;
- union value v;
- GLmatrix *m;
- int shift, i;
- void *p;
-
- d = find_value("glGetFloatv", pname, &p, &v);
- switch (d->type) {
- case TYPE_INVALID:
- break;
- case TYPE_CONST:
- params[0] = (GLfloat) d->offset;
- break;
-
- case TYPE_FLOAT_4:
- case TYPE_FLOATN_4:
- params[3] = ((GLfloat *) p)[3];
- case TYPE_FLOAT_3:
- case TYPE_FLOATN_3:
- params[2] = ((GLfloat *) p)[2];
- case TYPE_FLOAT_2:
- case TYPE_FLOATN_2:
- params[1] = ((GLfloat *) p)[1];
- case TYPE_FLOAT:
- case TYPE_FLOATN:
- params[0] = ((GLfloat *) p)[0];
- break;
-
- case TYPE_DOUBLEN:
- params[0] = ((GLdouble *) p)[0];
- break;
-
- case TYPE_INT_4:
- params[3] = (GLfloat) (((GLint *) p)[3]);
- case TYPE_INT_3:
- params[2] = (GLfloat) (((GLint *) p)[2]);
- case TYPE_INT_2:
- case TYPE_ENUM_2:
- params[1] = (GLfloat) (((GLint *) p)[1]);
- case TYPE_INT:
- case TYPE_ENUM:
- params[0] = (GLfloat) (((GLint *) p)[0]);
- break;
-
- case TYPE_INT_N:
- for (i = 0; i < v.value_int_n.n; i++)
- params[i] = INT_TO_FLOAT(v.value_int_n.ints[i]);
- break;
-
- case TYPE_INT64:
- params[0] = ((GLint64 *) p)[0];
- break;
-
- case TYPE_BOOLEAN:
- params[0] = BOOLEAN_TO_FLOAT(*(GLboolean*) p);
- break;
-
- case TYPE_MATRIX:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = m->m[i];
- break;
-
- case TYPE_MATRIX_T:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = m->m[transpose[i]];
- break;
-
- case TYPE_BIT_0:
- case TYPE_BIT_1:
- case TYPE_BIT_2:
- case TYPE_BIT_3:
- case TYPE_BIT_4:
- case TYPE_BIT_5:
- shift = d->type - TYPE_BIT_0;
- params[0] = BOOLEAN_TO_FLOAT((*(GLbitfield *) p >> shift) & 1);
- break;
- }
-}
-
-void GLAPIENTRY
-_mesa_GetIntegerv(GLenum pname, GLint *params)
-{
- const struct value_desc *d;
- union value v;
- GLmatrix *m;
- int shift, i;
- void *p;
-
- d = find_value("glGetIntegerv", pname, &p, &v);
- switch (d->type) {
- case TYPE_INVALID:
- break;
- case TYPE_CONST:
- params[0] = d->offset;
- break;
-
- case TYPE_FLOAT_4:
- params[3] = IROUND(((GLfloat *) p)[3]);
- case TYPE_FLOAT_3:
- params[2] = IROUND(((GLfloat *) p)[2]);
- case TYPE_FLOAT_2:
- params[1] = IROUND(((GLfloat *) p)[1]);
- case TYPE_FLOAT:
- params[0] = IROUND(((GLfloat *) p)[0]);
- break;
-
- case TYPE_FLOATN_4:
- params[3] = FLOAT_TO_INT(((GLfloat *) p)[3]);
- case TYPE_FLOATN_3:
- params[2] = FLOAT_TO_INT(((GLfloat *) p)[2]);
- case TYPE_FLOATN_2:
- params[1] = FLOAT_TO_INT(((GLfloat *) p)[1]);
- case TYPE_FLOATN:
- params[0] = FLOAT_TO_INT(((GLfloat *) p)[0]);
- break;
-
- case TYPE_DOUBLEN:
- params[0] = FLOAT_TO_INT(((GLdouble *) p)[0]);
- break;
-
- case TYPE_INT_4:
- params[3] = ((GLint *) p)[3];
- case TYPE_INT_3:
- params[2] = ((GLint *) p)[2];
- case TYPE_INT_2:
- case TYPE_ENUM_2:
- params[1] = ((GLint *) p)[1];
- case TYPE_INT:
- case TYPE_ENUM:
- params[0] = ((GLint *) p)[0];
- break;
-
- case TYPE_INT_N:
- for (i = 0; i < v.value_int_n.n; i++)
- params[i] = v.value_int_n.ints[i];
- break;
-
- case TYPE_INT64:
- params[0] = INT64_TO_INT(((GLint64 *) p)[0]);
- break;
-
- case TYPE_BOOLEAN:
- params[0] = BOOLEAN_TO_INT(*(GLboolean*) p);
- break;
-
- case TYPE_MATRIX:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_INT(m->m[i]);
- break;
-
- case TYPE_MATRIX_T:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_INT(m->m[transpose[i]]);
- break;
-
- case TYPE_BIT_0:
- case TYPE_BIT_1:
- case TYPE_BIT_2:
- case TYPE_BIT_3:
- case TYPE_BIT_4:
- case TYPE_BIT_5:
- shift = d->type - TYPE_BIT_0;
- params[0] = (*(GLbitfield *) p >> shift) & 1;
- break;
- }
-}
-
-#if FEATURE_ARB_sync
-void GLAPIENTRY
-_mesa_GetInteger64v(GLenum pname, GLint64 *params)
-{
- const struct value_desc *d;
- union value v;
- GLmatrix *m;
- int shift, i;
- void *p;
-
- d = find_value("glGetInteger64v", pname, &p, &v);
- switch (d->type) {
- case TYPE_INVALID:
- break;
- case TYPE_CONST:
- params[0] = d->offset;
- break;
-
- case TYPE_FLOAT_4:
- params[3] = IROUND64(((GLfloat *) p)[3]);
- case TYPE_FLOAT_3:
- params[2] = IROUND64(((GLfloat *) p)[2]);
- case TYPE_FLOAT_2:
- params[1] = IROUND64(((GLfloat *) p)[1]);
- case TYPE_FLOAT:
- params[0] = IROUND64(((GLfloat *) p)[0]);
- break;
-
- case TYPE_FLOATN_4:
- params[3] = FLOAT_TO_INT64(((GLfloat *) p)[3]);
- case TYPE_FLOATN_3:
- params[2] = FLOAT_TO_INT64(((GLfloat *) p)[2]);
- case TYPE_FLOATN_2:
- params[1] = FLOAT_TO_INT64(((GLfloat *) p)[1]);
- case TYPE_FLOATN:
- params[0] = FLOAT_TO_INT64(((GLfloat *) p)[0]);
- break;
-
- case TYPE_DOUBLEN:
- params[0] = FLOAT_TO_INT64(((GLdouble *) p)[0]);
- break;
-
- case TYPE_INT_4:
- params[3] = ((GLint *) p)[3];
- case TYPE_INT_3:
- params[2] = ((GLint *) p)[2];
- case TYPE_INT_2:
- case TYPE_ENUM_2:
- params[1] = ((GLint *) p)[1];
- case TYPE_INT:
- case TYPE_ENUM:
- params[0] = ((GLint *) p)[0];
- break;
-
- case TYPE_INT_N:
- for (i = 0; i < v.value_int_n.n; i++)
- params[i] = INT_TO_BOOLEAN(v.value_int_n.ints[i]);
- break;
-
- case TYPE_INT64:
- params[0] = ((GLint64 *) p)[0];
- break;
-
- case TYPE_BOOLEAN:
- params[0] = ((GLboolean*) p)[0];
- break;
-
- case TYPE_MATRIX:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_INT64(m->m[i]);
- break;
-
- case TYPE_MATRIX_T:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_INT64(m->m[transpose[i]]);
- break;
-
- case TYPE_BIT_0:
- case TYPE_BIT_1:
- case TYPE_BIT_2:
- case TYPE_BIT_3:
- case TYPE_BIT_4:
- case TYPE_BIT_5:
- shift = d->type - TYPE_BIT_0;
- params[0] = (*(GLbitfield *) p >> shift) & 1;
- break;
- }
-}
-#endif /* FEATURE_ARB_sync */
-
-void GLAPIENTRY
-_mesa_GetDoublev(GLenum pname, GLdouble *params)
-{
- const struct value_desc *d;
- union value v;
- GLmatrix *m;
- int shift, i;
- void *p;
-
- d = find_value("glGetDoublev", pname, &p, &v);
- switch (d->type) {
- case TYPE_INVALID:
- break;
- case TYPE_CONST:
- params[0] = d->offset;
- break;
-
- case TYPE_FLOAT_4:
- case TYPE_FLOATN_4:
- params[3] = ((GLfloat *) p)[3];
- case TYPE_FLOAT_3:
- case TYPE_FLOATN_3:
- params[2] = ((GLfloat *) p)[2];
- case TYPE_FLOAT_2:
- case TYPE_FLOATN_2:
- params[1] = ((GLfloat *) p)[1];
- case TYPE_FLOAT:
- case TYPE_FLOATN:
- params[0] = ((GLfloat *) p)[0];
- break;
-
- case TYPE_DOUBLEN:
- params[0] = ((GLdouble *) p)[0];
- break;
-
- case TYPE_INT_4:
- params[3] = ((GLint *) p)[3];
- case TYPE_INT_3:
- params[2] = ((GLint *) p)[2];
- case TYPE_INT_2:
- case TYPE_ENUM_2:
- params[1] = ((GLint *) p)[1];
- case TYPE_INT:
- case TYPE_ENUM:
- params[0] = ((GLint *) p)[0];
- break;
-
- case TYPE_INT_N:
- for (i = 0; i < v.value_int_n.n; i++)
- params[i] = v.value_int_n.ints[i];
- break;
-
- case TYPE_INT64:
- params[0] = ((GLint64 *) p)[0];
- break;
-
- case TYPE_BOOLEAN:
- params[0] = *(GLboolean*) p;
- break;
-
- case TYPE_MATRIX:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = m->m[i];
- break;
-
- case TYPE_MATRIX_T:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = m->m[transpose[i]];
- break;
-
- case TYPE_BIT_0:
- case TYPE_BIT_1:
- case TYPE_BIT_2:
- case TYPE_BIT_3:
- case TYPE_BIT_4:
- case TYPE_BIT_5:
- shift = d->type - TYPE_BIT_0;
- params[0] = (*(GLbitfield *) p >> shift) & 1;
- break;
- }
-}
-
-static enum value_type
-find_value_indexed(const char *func, GLenum pname, int index, union value *v)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- switch (pname) {
-
- case GL_BLEND:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.EXT_draw_buffers2)
- goto invalid_enum;
- v->value_int = (ctx->Color.BlendEnabled >> index) & 1;
- return TYPE_INT;
-
- case GL_BLEND_SRC:
- /* fall-through */
- case GL_BLEND_SRC_RGB:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.ARB_draw_buffers_blend)
- goto invalid_enum;
- v->value_int = ctx->Color.Blend[index].SrcRGB;
- return TYPE_INT;
- case GL_BLEND_SRC_ALPHA:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.ARB_draw_buffers_blend)
- goto invalid_enum;
- v->value_int = ctx->Color.Blend[index].SrcA;
- return TYPE_INT;
- case GL_BLEND_DST:
- /* fall-through */
- case GL_BLEND_DST_RGB:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.ARB_draw_buffers_blend)
- goto invalid_enum;
- v->value_int = ctx->Color.Blend[index].DstRGB;
- return TYPE_INT;
- case GL_BLEND_DST_ALPHA:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.ARB_draw_buffers_blend)
- goto invalid_enum;
- v->value_int = ctx->Color.Blend[index].DstA;
- return TYPE_INT;
- case GL_BLEND_EQUATION_RGB:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.ARB_draw_buffers_blend)
- goto invalid_enum;
- v->value_int = ctx->Color.Blend[index].EquationRGB;
- return TYPE_INT;
- case GL_BLEND_EQUATION_ALPHA:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.ARB_draw_buffers_blend)
- goto invalid_enum;
- v->value_int = ctx->Color.Blend[index].EquationA;
- return TYPE_INT;
-
- case GL_COLOR_WRITEMASK:
- if (index >= ctx->Const.MaxDrawBuffers)
- goto invalid_value;
- if (!ctx->Extensions.EXT_draw_buffers2)
- goto invalid_enum;
- v->value_int_4[0] = ctx->Color.ColorMask[index][RCOMP] ? 1 : 0;
- v->value_int_4[1] = ctx->Color.ColorMask[index][GCOMP] ? 1 : 0;
- v->value_int_4[2] = ctx->Color.ColorMask[index][BCOMP] ? 1 : 0;
- v->value_int_4[3] = ctx->Color.ColorMask[index][ACOMP] ? 1 : 0;
- return TYPE_INT_4;
-
- case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs)
- goto invalid_value;
- if (!ctx->Extensions.EXT_transform_feedback)
- goto invalid_enum;
- v->value_int64 = ctx->TransformFeedback.CurrentObject->Offset[index];
- return TYPE_INT64;
-
- case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs)
- goto invalid_value;
- if (!ctx->Extensions.EXT_transform_feedback)
- goto invalid_enum;
- v->value_int64 = ctx->TransformFeedback.CurrentObject->Size[index];
- return TYPE_INT64;
-
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs)
- goto invalid_value;
- if (!ctx->Extensions.EXT_transform_feedback)
- goto invalid_enum;
- v->value_int = ctx->TransformFeedback.CurrentObject->Buffers[index]->Name;
- return TYPE_INT;
- }
-
- invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
- _mesa_lookup_enum_by_nr(pname));
- return TYPE_INVALID;
- invalid_value:
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(pname=%s)", func,
- _mesa_lookup_enum_by_nr(pname));
- return TYPE_INVALID;
-}
-
-void GLAPIENTRY
-_mesa_GetBooleanIndexedv( GLenum pname, GLuint index, GLboolean *params )
-{
- union value v;
- enum value_type type =
- find_value_indexed("glGetBooleanIndexedv", pname, index, &v);
-
- switch (type) {
- case TYPE_INT:
- params[0] = INT_TO_BOOLEAN(v.value_int);
- break;
- case TYPE_INT_4:
- params[0] = INT_TO_BOOLEAN(v.value_int_4[0]);
- params[1] = INT_TO_BOOLEAN(v.value_int_4[1]);
- params[2] = INT_TO_BOOLEAN(v.value_int_4[2]);
- params[3] = INT_TO_BOOLEAN(v.value_int_4[3]);
- break;
- case TYPE_INT64:
- params[0] = INT64_TO_BOOLEAN(v.value_int);
- break;
- default:
- ; /* nothing - GL error was recorded */
- }
-}
-
-void GLAPIENTRY
-_mesa_GetIntegerIndexedv( GLenum pname, GLuint index, GLint *params )
-{
- union value v;
- enum value_type type =
- find_value_indexed("glGetIntegerIndexedv", pname, index, &v);
-
- switch (type) {
- case TYPE_INT:
- params[0] = v.value_int;
- break;
- case TYPE_INT_4:
- params[0] = v.value_int_4[0];
- params[1] = v.value_int_4[1];
- params[2] = v.value_int_4[2];
- params[3] = v.value_int_4[3];
- break;
- case TYPE_INT64:
- params[0] = INT64_TO_INT(v.value_int);
- break;
- default:
- ; /* nothing - GL error was recorded */
- }
-}
-
-#if FEATURE_ARB_sync
-void GLAPIENTRY
-_mesa_GetInteger64Indexedv( GLenum pname, GLuint index, GLint64 *params )
-{
- union value v;
- enum value_type type =
- find_value_indexed("glGetIntegerIndexedv", pname, index, &v);
-
- switch (type) {
- case TYPE_INT:
- params[0] = v.value_int;
- break;
- case TYPE_INT_4:
- params[0] = v.value_int_4[0];
- params[1] = v.value_int_4[1];
- params[2] = v.value_int_4[2];
- params[3] = v.value_int_4[3];
- break;
- case TYPE_INT64:
- params[0] = v.value_int;
- break;
- default:
- ; /* nothing - GL error was recorded */
- }
-}
-#endif /* FEATURE_ARB_sync */
-
-#if FEATURE_ES1
-void GLAPIENTRY
-_mesa_GetFixedv(GLenum pname, GLfixed *params)
-{
- const struct value_desc *d;
- union value v;
- GLmatrix *m;
- int shift, i;
- void *p;
-
- d = find_value("glGetDoublev", pname, &p, &v);
- switch (d->type) {
- case TYPE_INVALID:
- break;
- case TYPE_CONST:
- params[0] = INT_TO_FIXED(d->offset);
- break;
-
- case TYPE_FLOAT_4:
- case TYPE_FLOATN_4:
- params[3] = FLOAT_TO_FIXED(((GLfloat *) p)[3]);
- case TYPE_FLOAT_3:
- case TYPE_FLOATN_3:
- params[2] = FLOAT_TO_FIXED(((GLfloat *) p)[2]);
- case TYPE_FLOAT_2:
- case TYPE_FLOATN_2:
- params[1] = FLOAT_TO_FIXED(((GLfloat *) p)[1]);
- case TYPE_FLOAT:
- case TYPE_FLOATN:
- params[0] = FLOAT_TO_FIXED(((GLfloat *) p)[0]);
- break;
-
- case TYPE_DOUBLEN:
- params[0] = FLOAT_TO_FIXED(((GLdouble *) p)[0]);
- break;
-
- case TYPE_INT_4:
- params[3] = INT_TO_FIXED(((GLint *) p)[3]);
- case TYPE_INT_3:
- params[2] = INT_TO_FIXED(((GLint *) p)[2]);
- case TYPE_INT_2:
- case TYPE_ENUM_2:
- params[1] = INT_TO_FIXED(((GLint *) p)[1]);
- case TYPE_INT:
- case TYPE_ENUM:
- params[0] = INT_TO_FIXED(((GLint *) p)[0]);
- break;
-
- case TYPE_INT_N:
- for (i = 0; i < v.value_int_n.n; i++)
- params[i] = INT_TO_FIXED(v.value_int_n.ints[i]);
- break;
-
- case TYPE_INT64:
- params[0] = ((GLint64 *) p)[0];
- break;
-
- case TYPE_BOOLEAN:
- params[0] = BOOLEAN_TO_FIXED(((GLboolean*) p)[0]);
- break;
-
- case TYPE_MATRIX:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_FIXED(m->m[i]);
- break;
-
- case TYPE_MATRIX_T:
- m = *(GLmatrix **) p;
- for (i = 0; i < 16; i++)
- params[i] = FLOAT_TO_FIXED(m->m[transpose[i]]);
- break;
-
- case TYPE_BIT_0:
- case TYPE_BIT_1:
- case TYPE_BIT_2:
- case TYPE_BIT_3:
- case TYPE_BIT_4:
- case TYPE_BIT_5:
- shift = d->type - TYPE_BIT_0;
- params[0] = BOOLEAN_TO_FIXED((*(GLbitfield *) p >> shift) & 1);
- break;
- }
-}
-#endif
+/*
+ * Copyright (C) 2010 Brian Paul All Rights Reserved.
+ * Copyright (C) 2010 Intel Corporation
+ *
+ * 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.
+ *
+ * Author: Kristian Høgsberg <krh@bitplanet.net>
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "enable.h"
+#include "enums.h"
+#include "extensions.h"
+#include "get.h"
+#include "macros.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "state.h"
+#include "texcompress.h"
+#include "framebuffer.h"
+
+/* This is a table driven implemetation of the glGet*v() functions.
+ * The basic idea is that most getters just look up an int somewhere
+ * in struct gl_context and then convert it to a bool or float according to
+ * which of glGetIntegerv() glGetBooleanv() etc is being called.
+ * Instead of generating code to do this, we can just record the enum
+ * value and the offset into struct gl_context in an array of structs. Then
+ * in glGet*(), we lookup the struct for the enum in question, and use
+ * the offset to get the int we need.
+ *
+ * Sometimes we need to look up a float, a boolean, a bit in a
+ * bitfield, a matrix or other types instead, so we need to track the
+ * type of the value in struct gl_context. And sometimes the value isn't in
+ * struct gl_context but in the drawbuffer, the array object, current texture
+ * unit, or maybe it's a computed value. So we need to also track
+ * where or how to find the value. Finally, we sometimes need to
+ * check that one of a number of extensions are enabled, the GL
+ * version or flush or call _mesa_update_state(). This is done by
+ * attaching optional extra information to the value description
+ * struct, it's sort of like an array of opcodes that describe extra
+ * checks or actions.
+ *
+ * Putting all this together we end up with struct value_desc below,
+ * and with a couple of macros to help, the table of struct value_desc
+ * is about as concise as the specification in the old python script.
+ */
+
+#undef CONST
+
+#define FLOAT_TO_BOOLEAN(X) ( (X) ? GL_TRUE : GL_FALSE )
+#define FLOAT_TO_FIXED(F) ( ((F) * 65536.0f > INT_MAX) ? INT_MAX : \
+ ((F) * 65536.0f < INT_MIN) ? INT_MIN : \
+ (GLint) ((F) * 65536.0f) )
+
+#define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+#define INT_TO_FIXED(I) ( ((I) > SHRT_MAX) ? INT_MAX : \
+ ((I) < SHRT_MIN) ? INT_MIN : \
+ (GLint) ((I) * 65536) )
+
+#define INT64_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+#define INT64_TO_INT(I) ( (GLint)((I > INT_MAX) ? INT_MAX : ((I < INT_MIN) ? INT_MIN : (I))) )
+
+#define BOOLEAN_TO_INT(B) ( (GLint) (B) )
+#define BOOLEAN_TO_INT64(B) ( (GLint64) (B) )
+#define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F )
+#define BOOLEAN_TO_FIXED(B) ( (GLint) ((B) ? 1 : 0) << 16 )
+
+#define ENUM_TO_INT64(E) ( (GLint64) (E) )
+#define ENUM_TO_FIXED(E) (E)
+
+enum value_type {
+ TYPE_INVALID,
+ TYPE_API_MASK,
+ TYPE_INT,
+ TYPE_INT_2,
+ TYPE_INT_3,
+ TYPE_INT_4,
+ TYPE_INT_N,
+ TYPE_INT64,
+ TYPE_ENUM,
+ TYPE_ENUM_2,
+ TYPE_BOOLEAN,
+ TYPE_BIT_0,
+ TYPE_BIT_1,
+ TYPE_BIT_2,
+ TYPE_BIT_3,
+ TYPE_BIT_4,
+ TYPE_BIT_5,
+ TYPE_FLOAT,
+ TYPE_FLOAT_2,
+ TYPE_FLOAT_3,
+ TYPE_FLOAT_4,
+ TYPE_FLOATN,
+ TYPE_FLOATN_2,
+ TYPE_FLOATN_3,
+ TYPE_FLOATN_4,
+ TYPE_DOUBLEN,
+ TYPE_MATRIX,
+ TYPE_MATRIX_T,
+ TYPE_CONST
+};
+
+enum value_location {
+ LOC_BUFFER,
+ LOC_CONTEXT,
+ LOC_ARRAY,
+ LOC_TEXUNIT,
+ LOC_CUSTOM
+};
+
+enum value_extra {
+ EXTRA_END = 0x8000,
+ EXTRA_VERSION_30,
+ EXTRA_VERSION_31,
+ EXTRA_VERSION_32,
+ EXTRA_VERSION_ES2,
+ EXTRA_NEW_BUFFERS,
+ EXTRA_VALID_DRAW_BUFFER,
+ EXTRA_VALID_TEXTURE_UNIT,
+ EXTRA_FLUSH_CURRENT,
+};
+
+#define NO_EXTRA NULL
+#define NO_OFFSET 0
+
+struct value_desc {
+ GLenum pname;
+ GLubyte location; /**< enum value_location */
+ GLubyte type; /**< enum value_type */
+ int offset;
+ const int *extra;
+};
+
+union value {
+ GLfloat value_float;
+ GLfloat value_float_4[4];
+ GLmatrix *value_matrix;
+ GLint value_int;
+ GLint value_int_4[4];
+ GLint64 value_int64;
+ GLenum value_enum;
+
+ /* Sigh, see GL_COMPRESSED_TEXTURE_FORMATS_ARB handling */
+ struct {
+ GLint n, ints[100];
+ } value_int_n;
+ GLboolean value_bool;
+};
+
+#define BUFFER_FIELD(field, type) \
+ LOC_BUFFER, type, offsetof(struct gl_framebuffer, field)
+#define CONTEXT_FIELD(field, type) \
+ LOC_CONTEXT, type, offsetof(struct gl_context, field)
+#define ARRAY_FIELD(field, type) \
+ LOC_ARRAY, type, offsetof(struct gl_array_object, field)
+#define CONST(value) \
+ LOC_CONTEXT, TYPE_CONST, value
+
+#define BUFFER_INT(field) BUFFER_FIELD(field, TYPE_INT)
+#define BUFFER_ENUM(field) BUFFER_FIELD(field, TYPE_ENUM)
+#define BUFFER_BOOL(field) BUFFER_FIELD(field, TYPE_BOOLEAN)
+
+#define CONTEXT_INT(field) CONTEXT_FIELD(field, TYPE_INT)
+#define CONTEXT_INT2(field) CONTEXT_FIELD(field, TYPE_INT_2)
+#define CONTEXT_INT64(field) CONTEXT_FIELD(field, TYPE_INT64)
+#define CONTEXT_ENUM(field) CONTEXT_FIELD(field, TYPE_ENUM)
+#define CONTEXT_ENUM2(field) CONTEXT_FIELD(field, TYPE_ENUM_2)
+#define CONTEXT_BOOL(field) CONTEXT_FIELD(field, TYPE_BOOLEAN)
+#define CONTEXT_BIT0(field) CONTEXT_FIELD(field, TYPE_BIT_0)
+#define CONTEXT_BIT1(field) CONTEXT_FIELD(field, TYPE_BIT_1)
+#define CONTEXT_BIT2(field) CONTEXT_FIELD(field, TYPE_BIT_2)
+#define CONTEXT_BIT3(field) CONTEXT_FIELD(field, TYPE_BIT_3)
+#define CONTEXT_BIT4(field) CONTEXT_FIELD(field, TYPE_BIT_4)
+#define CONTEXT_BIT5(field) CONTEXT_FIELD(field, TYPE_BIT_5)
+#define CONTEXT_FLOAT(field) CONTEXT_FIELD(field, TYPE_FLOAT)
+#define CONTEXT_FLOAT2(field) CONTEXT_FIELD(field, TYPE_FLOAT_2)
+#define CONTEXT_FLOAT3(field) CONTEXT_FIELD(field, TYPE_FLOAT_3)
+#define CONTEXT_FLOAT4(field) CONTEXT_FIELD(field, TYPE_FLOAT_4)
+#define CONTEXT_MATRIX(field) CONTEXT_FIELD(field, TYPE_MATRIX)
+#define CONTEXT_MATRIX_T(field) CONTEXT_FIELD(field, TYPE_MATRIX_T)
+
+#define ARRAY_INT(field) ARRAY_FIELD(field, TYPE_INT)
+#define ARRAY_ENUM(field) ARRAY_FIELD(field, TYPE_ENUM)
+#define ARRAY_BOOL(field) ARRAY_FIELD(field, TYPE_BOOLEAN)
+
+#define EXT(f) \
+ offsetof(struct gl_extensions, f)
+
+#define EXTRA_EXT(e) \
+ static const int extra_##e[] = { \
+ EXT(e), EXTRA_END \
+ }
+
+#define EXTRA_EXT2(e1, e2) \
+ static const int extra_##e1##_##e2[] = { \
+ EXT(e1), EXT(e2), EXTRA_END \
+ }
+
+/* The 'extra' mechanism is a way to specify extra checks (such as
+ * extensions or specific gl versions) or actions (flush current, new
+ * buffers) that we need to do before looking up an enum. We need to
+ * declare them all up front so we can refer to them in the value_desc
+ * structs below. */
+
+static const int extra_new_buffers[] = {
+ EXTRA_NEW_BUFFERS,
+ EXTRA_END
+};
+
+static const int extra_valid_draw_buffer[] = {
+ EXTRA_VALID_DRAW_BUFFER,
+ EXTRA_END
+};
+
+static const int extra_valid_texture_unit[] = {
+ EXTRA_VALID_TEXTURE_UNIT,
+ EXTRA_END
+};
+
+static const int extra_flush_current_valid_texture_unit[] = {
+ EXTRA_FLUSH_CURRENT,
+ EXTRA_VALID_TEXTURE_UNIT,
+ EXTRA_END
+};
+
+static const int extra_flush_current[] = {
+ EXTRA_FLUSH_CURRENT,
+ EXTRA_END
+};
+
+static const int extra_new_buffers_OES_read_format[] = {
+ EXTRA_NEW_BUFFERS,
+ EXT(OES_read_format),
+ EXTRA_END
+};
+
+static const int extra_EXT_secondary_color_flush_current[] = {
+ EXT(EXT_secondary_color),
+ EXTRA_FLUSH_CURRENT,
+ EXTRA_END
+};
+
+static const int extra_EXT_fog_coord_flush_current[] = {
+ EXT(EXT_fog_coord),
+ EXTRA_FLUSH_CURRENT,
+ EXTRA_END
+};
+
+static const int extra_EXT_texture_integer[] = {
+ EXT(EXT_texture_integer),
+ EXTRA_END
+};
+
+static const int extra_EXT_gpu_shader4[] = {
+ EXT(EXT_gpu_shader4),
+ EXTRA_END
+};
+
+
+EXTRA_EXT(ARB_ES2_compatibility);
+EXTRA_EXT(ARB_multitexture);
+EXTRA_EXT(ARB_texture_cube_map);
+EXTRA_EXT(MESA_texture_array);
+EXTRA_EXT2(EXT_secondary_color, ARB_vertex_program);
+EXTRA_EXT(EXT_secondary_color);
+EXTRA_EXT(EXT_fog_coord);
+EXTRA_EXT(EXT_texture_lod_bias);
+EXTRA_EXT(EXT_texture_filter_anisotropic);
+EXTRA_EXT(IBM_rasterpos_clip);
+EXTRA_EXT(NV_point_sprite);
+EXTRA_EXT(SGIS_generate_mipmap);
+EXTRA_EXT(NV_vertex_program);
+EXTRA_EXT(NV_fragment_program);
+EXTRA_EXT(NV_texture_rectangle);
+EXTRA_EXT(EXT_stencil_two_side);
+EXTRA_EXT(NV_light_max_exponent);
+EXTRA_EXT(EXT_depth_bounds_test);
+EXTRA_EXT(ARB_depth_clamp);
+EXTRA_EXT(ATI_fragment_shader);
+EXTRA_EXT(EXT_framebuffer_blit);
+EXTRA_EXT(ARB_shader_objects);
+EXTRA_EXT(EXT_provoking_vertex);
+EXTRA_EXT(ARB_fragment_shader);
+EXTRA_EXT(ARB_fragment_program);
+EXTRA_EXT2(ARB_framebuffer_object, EXT_framebuffer_multisample);
+EXTRA_EXT(EXT_framebuffer_object);
+EXTRA_EXT(APPLE_vertex_array_object);
+EXTRA_EXT(ARB_seamless_cube_map);
+EXTRA_EXT(EXT_compiled_vertex_array);
+EXTRA_EXT(ARB_sync);
+EXTRA_EXT(ARB_vertex_shader);
+EXTRA_EXT(EXT_transform_feedback);
+EXTRA_EXT(ARB_transform_feedback2);
+EXTRA_EXT(EXT_pixel_buffer_object);
+EXTRA_EXT(ARB_vertex_program);
+EXTRA_EXT2(NV_point_sprite, ARB_point_sprite);
+EXTRA_EXT2(ARB_fragment_program, NV_fragment_program);
+EXTRA_EXT2(ARB_vertex_program, NV_vertex_program);
+EXTRA_EXT2(ARB_vertex_program, ARB_fragment_program);
+EXTRA_EXT(ARB_vertex_buffer_object);
+EXTRA_EXT(ARB_geometry_shader4);
+EXTRA_EXT(ARB_copy_buffer);
+EXTRA_EXT(EXT_framebuffer_sRGB);
+
+static const int
+extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program[] = {
+ EXT(ARB_vertex_program),
+ EXT(ARB_fragment_program),
+ EXT(NV_vertex_program),
+ EXTRA_END
+};
+
+static const int
+extra_NV_vertex_program_ARB_vertex_program_ARB_fragment_program_NV_vertex_program[] = {
+ EXT(NV_vertex_program),
+ EXT(ARB_vertex_program),
+ EXT(ARB_fragment_program),
+ EXT(NV_vertex_program),
+ EXTRA_END
+};
+
+static const int
+extra_NV_primitive_restart[] = {
+ EXT(NV_primitive_restart),
+ EXTRA_END
+};
+
+static const int extra_version_30[] = { EXTRA_VERSION_30, EXTRA_END };
+static const int extra_version_31[] = { EXTRA_VERSION_31, EXTRA_END };
+static const int extra_version_32[] = { EXTRA_VERSION_32, EXTRA_END };
+
+static const int
+extra_ARB_vertex_program_version_es2[] = {
+ EXT(ARB_vertex_program),
+ EXTRA_VERSION_ES2,
+ EXTRA_END
+};
+
+#define API_OPENGL_BIT (1 << API_OPENGL)
+#define API_OPENGLES_BIT (1 << API_OPENGLES)
+#define API_OPENGLES2_BIT (1 << API_OPENGLES2)
+
+/* This is the big table describing all the enums we accept in
+ * glGet*v(). The table is partitioned into six parts: enums
+ * understood by all GL APIs (OpenGL, GLES and GLES2), enums shared
+ * between OpenGL and GLES, enums exclusive to GLES, etc for the
+ * remaining combinations. When we add the enums to the hash table in
+ * _mesa_init_get_hash(), we only add the enums for the API we're
+ * instantiating and the different sections are guarded by #if
+ * FEATURE_GL etc to make sure we only compile in the enums we may
+ * need. */
+
+static const struct value_desc values[] = {
+ /* Enums shared between OpenGL, GLES1 and GLES2 */
+ { 0, 0, TYPE_API_MASK,
+ API_OPENGL_BIT | API_OPENGLES_BIT | API_OPENGLES2_BIT, NO_EXTRA},
+ { GL_ALPHA_BITS, BUFFER_INT(Visual.alphaBits), extra_new_buffers },
+ { GL_BLEND, CONTEXT_BIT0(Color.BlendEnabled), NO_EXTRA },
+ { GL_BLEND_SRC, CONTEXT_ENUM(Color.Blend[0].SrcRGB), NO_EXTRA },
+ { GL_BLUE_BITS, BUFFER_INT(Visual.blueBits), extra_new_buffers },
+ { GL_COLOR_CLEAR_VALUE, CONTEXT_FIELD(Color.ClearColor[0], TYPE_FLOATN_4), NO_EXTRA },
+ { GL_COLOR_WRITEMASK, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA },
+ { GL_CULL_FACE, CONTEXT_BOOL(Polygon.CullFlag), NO_EXTRA },
+ { GL_CULL_FACE_MODE, CONTEXT_ENUM(Polygon.CullFaceMode), NO_EXTRA },
+ { GL_DEPTH_BITS, BUFFER_INT(Visual.depthBits), NO_EXTRA },
+ { GL_DEPTH_CLEAR_VALUE, CONTEXT_FIELD(Depth.Clear, TYPE_DOUBLEN), NO_EXTRA },
+ { GL_DEPTH_FUNC, CONTEXT_ENUM(Depth.Func), NO_EXTRA },
+ { GL_DEPTH_RANGE, CONTEXT_FIELD(Viewport.Near, TYPE_FLOATN_2), NO_EXTRA },
+ { GL_DEPTH_TEST, CONTEXT_BOOL(Depth.Test), NO_EXTRA },
+ { GL_DEPTH_WRITEMASK, CONTEXT_BOOL(Depth.Mask), NO_EXTRA },
+ { GL_DITHER, CONTEXT_BOOL(Color.DitherFlag), NO_EXTRA },
+ { GL_FRONT_FACE, CONTEXT_ENUM(Polygon.FrontFace), NO_EXTRA },
+ { GL_GREEN_BITS, BUFFER_INT(Visual.greenBits), extra_new_buffers },
+ { GL_LINE_WIDTH, CONTEXT_FLOAT(Line.Width), NO_EXTRA },
+ { GL_ALIASED_LINE_WIDTH_RANGE, CONTEXT_FLOAT2(Const.MinLineWidth), NO_EXTRA },
+ { GL_MAX_ELEMENTS_VERTICES, CONTEXT_INT(Const.MaxArrayLockSize), NO_EXTRA },
+ { GL_MAX_ELEMENTS_INDICES, CONTEXT_INT(Const.MaxArrayLockSize), NO_EXTRA },
+ { GL_MAX_TEXTURE_SIZE, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_context, Const.MaxTextureLevels), NO_EXTRA },
+ { GL_MAX_VIEWPORT_DIMS, CONTEXT_INT2(Const.MaxViewportWidth), NO_EXTRA },
+ { GL_PACK_ALIGNMENT, CONTEXT_INT(Pack.Alignment), NO_EXTRA },
+ { GL_ALIASED_POINT_SIZE_RANGE, CONTEXT_FLOAT2(Const.MinPointSize), NO_EXTRA },
+ { GL_POLYGON_OFFSET_FACTOR, CONTEXT_FLOAT(Polygon.OffsetFactor ), NO_EXTRA },
+ { GL_POLYGON_OFFSET_UNITS, CONTEXT_FLOAT(Polygon.OffsetUnits ), NO_EXTRA },
+ { GL_POLYGON_OFFSET_FILL, CONTEXT_BOOL(Polygon.OffsetFill), NO_EXTRA },
+ { GL_RED_BITS, BUFFER_INT(Visual.redBits), extra_new_buffers },
+ { GL_SCISSOR_BOX, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA },
+ { GL_SCISSOR_TEST, CONTEXT_BOOL(Scissor.Enabled), NO_EXTRA },
+ { GL_STENCIL_BITS, BUFFER_INT(Visual.stencilBits), NO_EXTRA },
+ { GL_STENCIL_CLEAR_VALUE, CONTEXT_INT(Stencil.Clear), NO_EXTRA },
+ { GL_STENCIL_FAIL, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
+ { GL_STENCIL_FUNC, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
+ { GL_STENCIL_PASS_DEPTH_FAIL, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
+ { GL_STENCIL_PASS_DEPTH_PASS, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
+ { GL_STENCIL_REF, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
+ { GL_STENCIL_TEST, CONTEXT_BOOL(Stencil.Enabled), NO_EXTRA },
+ { GL_STENCIL_VALUE_MASK, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
+ { GL_STENCIL_WRITEMASK, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
+ { GL_SUBPIXEL_BITS, CONTEXT_INT(Const.SubPixelBits), NO_EXTRA },
+ { GL_TEXTURE_BINDING_2D, LOC_CUSTOM, TYPE_INT, TEXTURE_2D_INDEX, NO_EXTRA },
+ { GL_UNPACK_ALIGNMENT, CONTEXT_INT(Unpack.Alignment), NO_EXTRA },
+ { GL_VIEWPORT, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA },
+
+ /* GL_ARB_multitexture */
+ { GL_ACTIVE_TEXTURE_ARB,
+ LOC_CUSTOM, TYPE_INT, 0, extra_ARB_multitexture },
+
+ /* Note that all the OES_* extensions require that the Mesa "struct
+ * gl_extensions" include a member with the name of the extension.
+ * That structure does not yet include OES extensions (and we're
+ * not sure whether it will). If it does, all the OES_*
+ * extensions below should mark the dependency. */
+
+ /* GL_ARB_texture_cube_map */
+ { GL_TEXTURE_BINDING_CUBE_MAP_ARB, LOC_CUSTOM, TYPE_INT,
+ TEXTURE_CUBE_INDEX, extra_ARB_texture_cube_map },
+ { GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_context, Const.MaxCubeTextureLevels),
+ extra_ARB_texture_cube_map }, /* XXX: OES_texture_cube_map */
+
+ /* XXX: OES_blend_subtract */
+ { GL_BLEND_SRC_RGB_EXT, CONTEXT_ENUM(Color.Blend[0].SrcRGB), NO_EXTRA },
+ { GL_BLEND_DST_RGB_EXT, CONTEXT_ENUM(Color.Blend[0].DstRGB), NO_EXTRA },
+ { GL_BLEND_SRC_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].SrcA), NO_EXTRA },
+ { GL_BLEND_DST_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].DstA), NO_EXTRA },
+
+ /* GL_BLEND_EQUATION_RGB, which is what we're really after, is
+ * defined identically to GL_BLEND_EQUATION. */
+ { GL_BLEND_EQUATION, CONTEXT_ENUM(Color.Blend[0].EquationRGB), NO_EXTRA },
+ { GL_BLEND_EQUATION_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].EquationA), NO_EXTRA },
+
+ /* GL_ARB_texture_compression */
+ { GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
+ { GL_COMPRESSED_TEXTURE_FORMATS_ARB, LOC_CUSTOM, TYPE_INT_N, 0, NO_EXTRA },
+
+ /* GL_ARB_multisample */
+ { GL_SAMPLE_ALPHA_TO_COVERAGE_ARB,
+ CONTEXT_BOOL(Multisample.SampleAlphaToCoverage), NO_EXTRA },
+ { GL_SAMPLE_COVERAGE_ARB, CONTEXT_BOOL(Multisample.SampleCoverage), NO_EXTRA },
+ { GL_SAMPLE_COVERAGE_VALUE_ARB,
+ CONTEXT_FLOAT(Multisample.SampleCoverageValue), NO_EXTRA },
+ { GL_SAMPLE_COVERAGE_INVERT_ARB,
+ CONTEXT_BOOL(Multisample.SampleCoverageInvert), NO_EXTRA },
+ { GL_SAMPLE_BUFFERS_ARB, BUFFER_INT(Visual.sampleBuffers), NO_EXTRA },
+ { GL_SAMPLES_ARB, BUFFER_INT(Visual.samples), NO_EXTRA },
+
+ /* GL_SGIS_generate_mipmap */
+ { GL_GENERATE_MIPMAP_HINT_SGIS, CONTEXT_ENUM(Hint.GenerateMipmap),
+ extra_SGIS_generate_mipmap },
+
+ /* GL_ARB_vertex_buffer_object */
+ { GL_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
+
+ /* GL_ARB_vertex_buffer_object */
+ /* GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB - not supported */
+ { GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT, 0,
+ extra_ARB_vertex_buffer_object },
+
+ /* GL_ARB_copy_buffer */
+ { GL_COPY_READ_BUFFER, LOC_CUSTOM, TYPE_INT, 0, extra_ARB_copy_buffer },
+ { GL_COPY_WRITE_BUFFER, LOC_CUSTOM, TYPE_INT, 0, extra_ARB_copy_buffer },
+
+ /* GL_OES_read_format */
+ { GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, LOC_CUSTOM, TYPE_INT, 0,
+ extra_new_buffers_OES_read_format },
+ { GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, LOC_CUSTOM, TYPE_INT, 0,
+ extra_new_buffers_OES_read_format },
+
+ /* GL_EXT_framebuffer_object */
+ { GL_FRAMEBUFFER_BINDING_EXT, BUFFER_INT(Name),
+ extra_EXT_framebuffer_object },
+ { GL_RENDERBUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
+ extra_EXT_framebuffer_object },
+ { GL_MAX_RENDERBUFFER_SIZE_EXT, CONTEXT_INT(Const.MaxRenderbufferSize),
+ extra_EXT_framebuffer_object },
+
+ /* This entry isn't spec'ed for GLES 2, but is needed for Mesa's
+ * GLSL: */
+ { GL_MAX_CLIP_PLANES, CONTEXT_INT(Const.MaxClipPlanes), NO_EXTRA },
+
+#if FEATURE_GL || FEATURE_ES1
+ /* Enums in OpenGL and GLES1 */
+ { 0, 0, TYPE_API_MASK, API_OPENGL_BIT | API_OPENGLES_BIT, NO_EXTRA },
+ { GL_LIGHT0, CONTEXT_BOOL(Light.Light[0].Enabled), NO_EXTRA },
+ { GL_LIGHT1, CONTEXT_BOOL(Light.Light[1].Enabled), NO_EXTRA },
+ { GL_LIGHT2, CONTEXT_BOOL(Light.Light[2].Enabled), NO_EXTRA },
+ { GL_LIGHT3, CONTEXT_BOOL(Light.Light[3].Enabled), NO_EXTRA },
+ { GL_LIGHT4, CONTEXT_BOOL(Light.Light[4].Enabled), NO_EXTRA },
+ { GL_LIGHT5, CONTEXT_BOOL(Light.Light[5].Enabled), NO_EXTRA },
+ { GL_LIGHT6, CONTEXT_BOOL(Light.Light[6].Enabled), NO_EXTRA },
+ { GL_LIGHT7, CONTEXT_BOOL(Light.Light[7].Enabled), NO_EXTRA },
+ { GL_LIGHTING, CONTEXT_BOOL(Light.Enabled), NO_EXTRA },
+ { GL_LIGHT_MODEL_AMBIENT,
+ CONTEXT_FIELD(Light.Model.Ambient[0], TYPE_FLOATN_4), NO_EXTRA },
+ { GL_LIGHT_MODEL_TWO_SIDE, CONTEXT_BOOL(Light.Model.TwoSide), NO_EXTRA },
+ { GL_ALPHA_TEST, CONTEXT_BOOL(Color.AlphaEnabled), NO_EXTRA },
+ { GL_ALPHA_TEST_FUNC, CONTEXT_ENUM(Color.AlphaFunc), NO_EXTRA },
+ { GL_ALPHA_TEST_REF, CONTEXT_FIELD(Color.AlphaRef, TYPE_FLOATN), NO_EXTRA },
+ { GL_BLEND_DST, CONTEXT_ENUM(Color.Blend[0].DstRGB), NO_EXTRA },
+ { GL_CLIP_PLANE0, CONTEXT_BIT0(Transform.ClipPlanesEnabled), NO_EXTRA },
+ { GL_CLIP_PLANE1, CONTEXT_BIT1(Transform.ClipPlanesEnabled), NO_EXTRA },
+ { GL_CLIP_PLANE2, CONTEXT_BIT2(Transform.ClipPlanesEnabled), NO_EXTRA },
+ { GL_CLIP_PLANE3, CONTEXT_BIT3(Transform.ClipPlanesEnabled), NO_EXTRA },
+ { GL_CLIP_PLANE4, CONTEXT_BIT4(Transform.ClipPlanesEnabled), NO_EXTRA },
+ { GL_CLIP_PLANE5, CONTEXT_BIT5(Transform.ClipPlanesEnabled), NO_EXTRA },
+ { GL_COLOR_MATERIAL, CONTEXT_BOOL(Light.ColorMaterialEnabled), NO_EXTRA },
+ { GL_CURRENT_COLOR,
+ CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_COLOR0][0], TYPE_FLOATN_4),
+ extra_flush_current },
+ { GL_CURRENT_NORMAL,
+ CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_NORMAL][0], TYPE_FLOATN_3),
+ extra_flush_current },
+ { GL_CURRENT_TEXTURE_COORDS, LOC_CUSTOM, TYPE_FLOAT_4, 0,
+ extra_flush_current_valid_texture_unit },
+ { GL_DISTANCE_ATTENUATION_EXT, CONTEXT_FLOAT3(Point.Params[0]), NO_EXTRA },
+ { GL_FOG, CONTEXT_BOOL(Fog.Enabled), NO_EXTRA },
+ { GL_FOG_COLOR, CONTEXT_FIELD(Fog.Color[0], TYPE_FLOATN_4), NO_EXTRA },
+ { GL_FOG_DENSITY, CONTEXT_FLOAT(Fog.Density), NO_EXTRA },
+ { GL_FOG_END, CONTEXT_FLOAT(Fog.End), NO_EXTRA },
+ { GL_FOG_HINT, CONTEXT_ENUM(Hint.Fog), NO_EXTRA },
+ { GL_FOG_MODE, CONTEXT_ENUM(Fog.Mode), NO_EXTRA },
+ { GL_FOG_START, CONTEXT_FLOAT(Fog.Start), NO_EXTRA },
+ { GL_LINE_SMOOTH, CONTEXT_BOOL(Line.SmoothFlag), NO_EXTRA },
+ { GL_LINE_SMOOTH_HINT, CONTEXT_ENUM(Hint.LineSmooth), NO_EXTRA },
+ { GL_LINE_WIDTH_RANGE, CONTEXT_FLOAT2(Const.MinLineWidthAA), NO_EXTRA },
+ { GL_COLOR_LOGIC_OP, CONTEXT_BOOL(Color.ColorLogicOpEnabled), NO_EXTRA },
+ { GL_LOGIC_OP_MODE, CONTEXT_ENUM(Color.LogicOp), NO_EXTRA },
+ { GL_MATRIX_MODE, CONTEXT_ENUM(Transform.MatrixMode), NO_EXTRA },
+ { GL_MAX_MODELVIEW_STACK_DEPTH, CONST(MAX_MODELVIEW_STACK_DEPTH), NO_EXTRA },
+ { GL_MAX_PROJECTION_STACK_DEPTH, CONST(MAX_PROJECTION_STACK_DEPTH), NO_EXTRA },
+ { GL_MAX_TEXTURE_STACK_DEPTH, CONST(MAX_TEXTURE_STACK_DEPTH), NO_EXTRA },
+ { GL_MODELVIEW_MATRIX, CONTEXT_MATRIX(ModelviewMatrixStack.Top), NO_EXTRA },
+ { GL_MODELVIEW_STACK_DEPTH, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_context, ModelviewMatrixStack.Depth), NO_EXTRA },
+ { GL_NORMALIZE, CONTEXT_BOOL(Transform.Normalize), NO_EXTRA },
+ { GL_PACK_SKIP_IMAGES_EXT, CONTEXT_INT(Pack.SkipImages), NO_EXTRA },
+ { GL_PERSPECTIVE_CORRECTION_HINT, CONTEXT_ENUM(Hint.PerspectiveCorrection), NO_EXTRA },
+ { GL_POINT_SIZE, CONTEXT_FLOAT(Point.Size), NO_EXTRA },
+ { GL_POINT_SIZE_RANGE, CONTEXT_FLOAT2(Const.MinPointSizeAA), NO_EXTRA },
+ { GL_POINT_SMOOTH, CONTEXT_BOOL(Point.SmoothFlag), NO_EXTRA },
+ { GL_POINT_SMOOTH_HINT, CONTEXT_ENUM(Hint.PointSmooth), NO_EXTRA },
+ { GL_POINT_SIZE_MIN_EXT, CONTEXT_FLOAT(Point.MinSize), NO_EXTRA },
+ { GL_POINT_SIZE_MAX_EXT, CONTEXT_FLOAT(Point.MaxSize), NO_EXTRA },
+ { GL_POINT_FADE_THRESHOLD_SIZE_EXT, CONTEXT_FLOAT(Point.Threshold), NO_EXTRA },
+ { GL_PROJECTION_MATRIX, CONTEXT_MATRIX(ProjectionMatrixStack.Top), NO_EXTRA },
+ { GL_PROJECTION_STACK_DEPTH, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_context, ProjectionMatrixStack.Depth), NO_EXTRA },
+ { GL_RESCALE_NORMAL, CONTEXT_BOOL(Transform.RescaleNormals), NO_EXTRA },
+ { GL_SHADE_MODEL, CONTEXT_ENUM(Light.ShadeModel), NO_EXTRA },
+ { GL_TEXTURE_2D, LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA },
+ { GL_TEXTURE_MATRIX, LOC_CUSTOM, TYPE_MATRIX, 0, extra_valid_texture_unit },
+ { GL_TEXTURE_STACK_DEPTH, LOC_CUSTOM, TYPE_INT, 0,
+ extra_valid_texture_unit },
+
+ { GL_VERTEX_ARRAY, ARRAY_BOOL(Vertex.Enabled), NO_EXTRA },
+ { GL_VERTEX_ARRAY_SIZE, ARRAY_INT(Vertex.Size), NO_EXTRA },
+ { GL_VERTEX_ARRAY_TYPE, ARRAY_ENUM(Vertex.Type), NO_EXTRA },
+ { GL_VERTEX_ARRAY_STRIDE, ARRAY_INT(Vertex.Stride), NO_EXTRA },
+ { GL_NORMAL_ARRAY, ARRAY_ENUM(Normal.Enabled), NO_EXTRA },
+ { GL_NORMAL_ARRAY_TYPE, ARRAY_ENUM(Normal.Type), NO_EXTRA },
+ { GL_NORMAL_ARRAY_STRIDE, ARRAY_INT(Normal.Stride), NO_EXTRA },
+ { GL_COLOR_ARRAY, ARRAY_BOOL(Color.Enabled), NO_EXTRA },
+ { GL_COLOR_ARRAY_SIZE, ARRAY_INT(Color.Size), NO_EXTRA },
+ { GL_COLOR_ARRAY_TYPE, ARRAY_ENUM(Color.Type), NO_EXTRA },
+ { GL_COLOR_ARRAY_STRIDE, ARRAY_INT(Color.Stride), NO_EXTRA },
+ { GL_TEXTURE_COORD_ARRAY,
+ LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Enabled), NO_EXTRA },
+ { GL_TEXTURE_COORD_ARRAY_SIZE,
+ LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Size), NO_EXTRA },
+ { GL_TEXTURE_COORD_ARRAY_TYPE,
+ LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Type), NO_EXTRA },
+ { GL_TEXTURE_COORD_ARRAY_STRIDE,
+ LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Stride), NO_EXTRA },
+
+ /* GL_ARB_ES2_compatibility */
+ { GL_SHADER_COMPILER, CONST(1), extra_ARB_ES2_compatibility },
+ { GL_MAX_VARYING_VECTORS, CONTEXT_INT(Const.MaxVarying),
+ extra_ARB_ES2_compatibility },
+ { GL_MAX_VERTEX_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0,
+ extra_ARB_ES2_compatibility },
+ { GL_MAX_FRAGMENT_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0,
+ extra_ARB_ES2_compatibility },
+
+ /* GL_ARB_multitexture */
+ { GL_MAX_TEXTURE_UNITS_ARB,
+ CONTEXT_INT(Const.MaxTextureUnits), extra_ARB_multitexture },
+ { GL_CLIENT_ACTIVE_TEXTURE_ARB,
+ LOC_CUSTOM, TYPE_INT, 0, extra_ARB_multitexture },
+
+ /* GL_ARB_texture_cube_map */
+ { GL_TEXTURE_CUBE_MAP_ARB, LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA },
+ /* S, T, and R are always set at the same time */
+ { GL_TEXTURE_GEN_STR_OES, LOC_TEXUNIT, TYPE_BIT_0,
+ offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
+
+ /* GL_ARB_multisample */
+ { GL_MULTISAMPLE_ARB, CONTEXT_BOOL(Multisample.Enabled), NO_EXTRA },
+ { GL_SAMPLE_ALPHA_TO_ONE_ARB, CONTEXT_BOOL(Multisample.SampleAlphaToOne), NO_EXTRA },
+
+ /* GL_ARB_vertex_buffer_object */
+ { GL_VERTEX_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_array_object, Vertex.BufferObj), NO_EXTRA },
+ { GL_NORMAL_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_array_object, Normal.BufferObj), NO_EXTRA },
+ { GL_COLOR_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_array_object, Color.BufferObj), NO_EXTRA },
+ { GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA },
+
+ /* GL_OES_point_sprite */
+ { GL_POINT_SPRITE_NV,
+ CONTEXT_BOOL(Point.PointSprite),
+ extra_NV_point_sprite_ARB_point_sprite },
+
+ /* GL_ARB_fragment_shader */
+ { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB,
+ CONTEXT_INT(Const.FragmentProgram.MaxUniformComponents),
+ extra_ARB_fragment_shader },
+
+ /* GL_ARB_vertex_shader */
+ { GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB,
+ CONTEXT_INT(Const.VertexProgram.MaxUniformComponents),
+ extra_ARB_vertex_shader },
+ { GL_MAX_VARYING_FLOATS_ARB, LOC_CUSTOM, TYPE_INT, 0,
+ extra_ARB_vertex_shader },
+
+ /* GL_EXT_texture_lod_bias */
+ { GL_MAX_TEXTURE_LOD_BIAS_EXT, CONTEXT_FLOAT(Const.MaxTextureLodBias),
+ extra_EXT_texture_lod_bias },
+
+ /* GL_EXT_texture_filter_anisotropic */
+ { GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,
+ CONTEXT_FLOAT(Const.MaxTextureMaxAnisotropy),
+ extra_EXT_texture_filter_anisotropic },
+#endif /* FEATURE_GL || FEATURE_ES1 */
+
+#if FEATURE_ES1
+ { 0, 0, TYPE_API_MASK, API_OPENGLES_BIT },
+ /* XXX: OES_matrix_get */
+ { GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES },
+ { GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES },
+ { GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES },
+
+ /* OES_point_size_array */
+ { GL_POINT_SIZE_ARRAY_OES, ARRAY_FIELD(PointSize.Enabled, TYPE_BOOLEAN) },
+ { GL_POINT_SIZE_ARRAY_TYPE_OES, ARRAY_FIELD(PointSize.Type, TYPE_ENUM) },
+ { GL_POINT_SIZE_ARRAY_STRIDE_OES, ARRAY_FIELD(PointSize.Stride, TYPE_INT) },
+ { GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES, LOC_CUSTOM, TYPE_INT, 0 },
+#endif /* FEATURE_ES1 */
+
+#if FEATURE_GL || FEATURE_ES2
+ { 0, 0, TYPE_API_MASK, API_OPENGL_BIT | API_OPENGLES2_BIT, NO_EXTRA },
+ /* This entry isn't spec'ed for GLES 2, but is needed for Mesa's GLSL: */
+ { GL_MAX_LIGHTS, CONTEXT_INT(Const.MaxLights), NO_EXTRA },
+ { GL_MAX_TEXTURE_COORDS_ARB, /* == GL_MAX_TEXTURE_COORDS_NV */
+ CONTEXT_INT(Const.MaxTextureCoordUnits),
+ extra_ARB_fragment_program_NV_fragment_program },
+
+ /* GL_ARB_draw_buffers */
+ { GL_MAX_DRAW_BUFFERS_ARB, CONTEXT_INT(Const.MaxDrawBuffers), NO_EXTRA },
+
+ { GL_BLEND_COLOR_EXT, CONTEXT_FIELD(Color.BlendColor[0], TYPE_FLOATN_4), NO_EXTRA },
+ /* GL_ARB_fragment_program */
+ { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, /* == GL_MAX_TEXTURE_IMAGE_UNITS_NV */
+ CONTEXT_INT(Const.MaxTextureImageUnits),
+ extra_ARB_fragment_program_NV_fragment_program },
+ { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB,
+ CONTEXT_INT(Const.MaxVertexTextureImageUnits), extra_ARB_vertex_shader },
+ { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB,
+ CONTEXT_INT(Const.MaxCombinedTextureImageUnits),
+ extra_ARB_vertex_shader },
+
+ /* GL_ARB_shader_objects
+ * Actually, this token isn't part of GL_ARB_shader_objects, but is
+ * close enough for now. */
+ { GL_CURRENT_PROGRAM, LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_objects },
+
+ /* OpenGL 2.0 */
+ { GL_STENCIL_BACK_FUNC, CONTEXT_ENUM(Stencil.Function[1]), NO_EXTRA },
+ { GL_STENCIL_BACK_VALUE_MASK, CONTEXT_INT(Stencil.ValueMask[1]), NO_EXTRA },
+ { GL_STENCIL_BACK_WRITEMASK, CONTEXT_INT(Stencil.WriteMask[1]), NO_EXTRA },
+ { GL_STENCIL_BACK_REF, CONTEXT_INT(Stencil.Ref[1]), NO_EXTRA },
+ { GL_STENCIL_BACK_FAIL, CONTEXT_ENUM(Stencil.FailFunc[1]), NO_EXTRA },
+ { GL_STENCIL_BACK_PASS_DEPTH_FAIL, CONTEXT_ENUM(Stencil.ZFailFunc[1]), NO_EXTRA },
+ { GL_STENCIL_BACK_PASS_DEPTH_PASS, CONTEXT_ENUM(Stencil.ZPassFunc[1]), NO_EXTRA },
+
+ { GL_MAX_VERTEX_ATTRIBS_ARB,
+ CONTEXT_INT(Const.VertexProgram.MaxAttribs),
+ extra_ARB_vertex_program_version_es2 },
+
+ /* OES_texture_3D */
+ { GL_TEXTURE_BINDING_3D, LOC_CUSTOM, TYPE_INT, TEXTURE_3D_INDEX, NO_EXTRA },
+ { GL_MAX_3D_TEXTURE_SIZE, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_context, Const.Max3DTextureLevels), NO_EXTRA },
+
+ /* GL_ARB_fragment_program/OES_standard_derivatives */
+ { GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB,
+ CONTEXT_ENUM(Hint.FragmentShaderDerivative), extra_ARB_fragment_shader },
+#endif /* FEATURE_GL || FEATURE_ES2 */
+
+#if FEATURE_ES2
+ /* Enums unique to OpenGL ES 2.0 */
+ { 0, 0, TYPE_API_MASK, API_OPENGLES2_BIT, NO_EXTRA },
+ { GL_MAX_FRAGMENT_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
+ { GL_MAX_VARYING_VECTORS, CONTEXT_INT(Const.MaxVarying), NO_EXTRA },
+ { GL_MAX_VERTEX_UNIFORM_VECTORS, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
+ { GL_SHADER_COMPILER, CONST(1), NO_EXTRA },
+ /* OES_get_program_binary */
+ { GL_NUM_SHADER_BINARY_FORMATS, CONST(0), NO_EXTRA },
+ { GL_SHADER_BINARY_FORMATS, CONST(0), NO_EXTRA },
+#endif /* FEATURE_ES2 */
+
+#if FEATURE_GL
+ /* Remaining enums are only in OpenGL */
+ { 0, 0, TYPE_API_MASK, API_OPENGL_BIT, NO_EXTRA },
+ { GL_ACCUM_RED_BITS, BUFFER_INT(Visual.accumRedBits), NO_EXTRA },
+ { GL_ACCUM_GREEN_BITS, BUFFER_INT(Visual.accumGreenBits), NO_EXTRA },
+ { GL_ACCUM_BLUE_BITS, BUFFER_INT(Visual.accumBlueBits), NO_EXTRA },
+ { GL_ACCUM_ALPHA_BITS, BUFFER_INT(Visual.accumAlphaBits), NO_EXTRA },
+ { GL_ACCUM_CLEAR_VALUE, CONTEXT_FIELD(Accum.ClearColor[0], TYPE_FLOATN_4), NO_EXTRA },
+ { GL_ALPHA_BIAS, CONTEXT_FLOAT(Pixel.AlphaBias), NO_EXTRA },
+ { GL_ALPHA_SCALE, CONTEXT_FLOAT(Pixel.AlphaScale), NO_EXTRA },
+ { GL_ATTRIB_STACK_DEPTH, CONTEXT_INT(AttribStackDepth), NO_EXTRA },
+ { GL_AUTO_NORMAL, CONTEXT_BOOL(Eval.AutoNormal), NO_EXTRA },
+ { GL_AUX_BUFFERS, BUFFER_INT(Visual.numAuxBuffers), NO_EXTRA },
+ { GL_BLUE_BIAS, CONTEXT_FLOAT(Pixel.BlueBias), NO_EXTRA },
+ { GL_BLUE_SCALE, CONTEXT_FLOAT(Pixel.BlueScale), NO_EXTRA },
+ { GL_CLIENT_ATTRIB_STACK_DEPTH, CONTEXT_INT(ClientAttribStackDepth), NO_EXTRA },
+ { GL_COLOR_MATERIAL_FACE, CONTEXT_ENUM(Light.ColorMaterialFace), NO_EXTRA },
+ { GL_COLOR_MATERIAL_PARAMETER, CONTEXT_ENUM(Light.ColorMaterialMode), NO_EXTRA },
+ { GL_CURRENT_INDEX,
+ CONTEXT_FLOAT(Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0]),
+ extra_flush_current },
+ { GL_CURRENT_RASTER_COLOR,
+ CONTEXT_FIELD(Current.RasterColor[0], TYPE_FLOATN_4), NO_EXTRA },
+ { GL_CURRENT_RASTER_DISTANCE, CONTEXT_FLOAT(Current.RasterDistance), NO_EXTRA },
+ { GL_CURRENT_RASTER_INDEX, CONST(1), NO_EXTRA },
+ { GL_CURRENT_RASTER_POSITION, CONTEXT_FLOAT4(Current.RasterPos[0]), NO_EXTRA },
+ { GL_CURRENT_RASTER_SECONDARY_COLOR,
+ CONTEXT_FIELD(Current.RasterSecondaryColor[0], TYPE_FLOATN_4), NO_EXTRA },
+ { GL_CURRENT_RASTER_TEXTURE_COORDS, LOC_CUSTOM, TYPE_FLOAT_4, 0,
+ extra_valid_texture_unit },
+ { GL_CURRENT_RASTER_POSITION_VALID, CONTEXT_BOOL(Current.RasterPosValid), NO_EXTRA },
+ { GL_DEPTH_BIAS, CONTEXT_FLOAT(Pixel.DepthBias), NO_EXTRA },
+ { GL_DEPTH_SCALE, CONTEXT_FLOAT(Pixel.DepthScale), NO_EXTRA },
+ { GL_DOUBLEBUFFER, BUFFER_INT(Visual.doubleBufferMode), NO_EXTRA },
+ { GL_DRAW_BUFFER, BUFFER_ENUM(ColorDrawBuffer[0]), NO_EXTRA },
+ { GL_EDGE_FLAG, LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA },
+ { GL_FEEDBACK_BUFFER_SIZE, CONTEXT_INT(Feedback.BufferSize), NO_EXTRA },
+ { GL_FEEDBACK_BUFFER_TYPE, CONTEXT_ENUM(Feedback.Type), NO_EXTRA },
+ { GL_FOG_INDEX, CONTEXT_FLOAT(Fog.Index), NO_EXTRA },
+ { GL_GREEN_BIAS, CONTEXT_FLOAT(Pixel.GreenBias), NO_EXTRA },
+ { GL_GREEN_SCALE, CONTEXT_FLOAT(Pixel.GreenScale), NO_EXTRA },
+ { GL_INDEX_BITS, BUFFER_INT(Visual.indexBits), extra_new_buffers },
+ { GL_INDEX_CLEAR_VALUE, CONTEXT_INT(Color.ClearIndex), NO_EXTRA },
+ { GL_INDEX_MODE, CONST(0) , NO_EXTRA},
+ { GL_INDEX_OFFSET, CONTEXT_INT(Pixel.IndexOffset), NO_EXTRA },
+ { GL_INDEX_SHIFT, CONTEXT_INT(Pixel.IndexShift), NO_EXTRA },
+ { GL_INDEX_WRITEMASK, CONTEXT_INT(Color.IndexMask), NO_EXTRA },
+ { GL_LIGHT_MODEL_COLOR_CONTROL, CONTEXT_ENUM(Light.Model.ColorControl), NO_EXTRA },
+ { GL_LIGHT_MODEL_LOCAL_VIEWER, CONTEXT_BOOL(Light.Model.LocalViewer), NO_EXTRA },
+ { GL_LINE_STIPPLE, CONTEXT_BOOL(Line.StippleFlag), NO_EXTRA },
+ { GL_LINE_STIPPLE_PATTERN, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
+ { GL_LINE_STIPPLE_REPEAT, CONTEXT_INT(Line.StippleFactor), NO_EXTRA },
+ { GL_LINE_WIDTH_GRANULARITY, CONTEXT_FLOAT(Const.LineWidthGranularity), NO_EXTRA },
+ { GL_LIST_BASE, CONTEXT_INT(List.ListBase), NO_EXTRA },
+ { GL_LIST_INDEX, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA },
+ { GL_LIST_MODE, LOC_CUSTOM, TYPE_ENUM, 0, NO_EXTRA },
+ { GL_INDEX_LOGIC_OP, CONTEXT_BOOL(Color.IndexLogicOpEnabled), NO_EXTRA },
+ { GL_MAP1_COLOR_4, CONTEXT_BOOL(Eval.Map1Color4), NO_EXTRA },
+ { GL_MAP1_GRID_DOMAIN, CONTEXT_FLOAT2(Eval.MapGrid1u1), NO_EXTRA },
+ { GL_MAP1_GRID_SEGMENTS, CONTEXT_INT(Eval.MapGrid1un), NO_EXTRA },
+ { GL_MAP1_INDEX, CONTEXT_BOOL(Eval.Map1Index), NO_EXTRA },
+ { GL_MAP1_NORMAL, CONTEXT_BOOL(Eval.Map1Normal), NO_EXTRA },
+ { GL_MAP1_TEXTURE_COORD_1, CONTEXT_BOOL(Eval.Map1TextureCoord1), NO_EXTRA },
+ { GL_MAP1_TEXTURE_COORD_2, CONTEXT_BOOL(Eval.Map1TextureCoord2), NO_EXTRA },
+ { GL_MAP1_TEXTURE_COORD_3, CONTEXT_BOOL(Eval.Map1TextureCoord3), NO_EXTRA },
+ { GL_MAP1_TEXTURE_COORD_4, CONTEXT_BOOL(Eval.Map1TextureCoord4), NO_EXTRA },
+ { GL_MAP1_VERTEX_3, CONTEXT_BOOL(Eval.Map1Vertex3), NO_EXTRA },
+ { GL_MAP1_VERTEX_4, CONTEXT_BOOL(Eval.Map1Vertex4), NO_EXTRA },
+ { GL_MAP2_COLOR_4, CONTEXT_BOOL(Eval.Map2Color4), NO_EXTRA },
+ { GL_MAP2_GRID_DOMAIN, LOC_CUSTOM, TYPE_FLOAT_4, 0, NO_EXTRA },
+ { GL_MAP2_GRID_SEGMENTS, CONTEXT_INT2(Eval.MapGrid2un), NO_EXTRA },
+ { GL_MAP2_INDEX, CONTEXT_BOOL(Eval.Map2Index), NO_EXTRA },
+ { GL_MAP2_NORMAL, CONTEXT_BOOL(Eval.Map2Normal), NO_EXTRA },
+ { GL_MAP2_TEXTURE_COORD_1, CONTEXT_BOOL(Eval.Map2TextureCoord1), NO_EXTRA },
+ { GL_MAP2_TEXTURE_COORD_2, CONTEXT_BOOL(Eval.Map2TextureCoord2), NO_EXTRA },
+ { GL_MAP2_TEXTURE_COORD_3, CONTEXT_BOOL(Eval.Map2TextureCoord3), NO_EXTRA },
+ { GL_MAP2_TEXTURE_COORD_4, CONTEXT_BOOL(Eval.Map2TextureCoord4), NO_EXTRA },
+ { GL_MAP2_VERTEX_3, CONTEXT_BOOL(Eval.Map2Vertex3), NO_EXTRA },
+ { GL_MAP2_VERTEX_4, CONTEXT_BOOL(Eval.Map2Vertex4), NO_EXTRA },
+ { GL_MAP_COLOR, CONTEXT_BOOL(Pixel.MapColorFlag), NO_EXTRA },
+ { GL_MAP_STENCIL, CONTEXT_BOOL(Pixel.MapStencilFlag), NO_EXTRA },
+ { GL_MAX_ATTRIB_STACK_DEPTH, CONST(MAX_ATTRIB_STACK_DEPTH), NO_EXTRA },
+ { GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, CONST(MAX_CLIENT_ATTRIB_STACK_DEPTH), NO_EXTRA },
+
+ { GL_MAX_EVAL_ORDER, CONST(MAX_EVAL_ORDER), NO_EXTRA },
+ { GL_MAX_LIST_NESTING, CONST(MAX_LIST_NESTING), NO_EXTRA },
+ { GL_MAX_NAME_STACK_DEPTH, CONST(MAX_NAME_STACK_DEPTH), NO_EXTRA },
+ { GL_MAX_PIXEL_MAP_TABLE, CONST(MAX_PIXEL_MAP_TABLE), NO_EXTRA },
+ { GL_NAME_STACK_DEPTH, CONTEXT_INT(Select.NameStackDepth), NO_EXTRA },
+ { GL_PACK_LSB_FIRST, CONTEXT_BOOL(Pack.LsbFirst), NO_EXTRA },
+ { GL_PACK_ROW_LENGTH, CONTEXT_INT(Pack.RowLength), NO_EXTRA },
+ { GL_PACK_SKIP_PIXELS, CONTEXT_INT(Pack.SkipPixels), NO_EXTRA },
+ { GL_PACK_SKIP_ROWS, CONTEXT_INT(Pack.SkipRows), NO_EXTRA },
+ { GL_PACK_SWAP_BYTES, CONTEXT_BOOL(Pack.SwapBytes), NO_EXTRA },
+ { GL_PACK_IMAGE_HEIGHT_EXT, CONTEXT_INT(Pack.ImageHeight), NO_EXTRA },
+ { GL_PACK_INVERT_MESA, CONTEXT_BOOL(Pack.Invert), NO_EXTRA },
+ { GL_PIXEL_MAP_A_TO_A_SIZE, CONTEXT_INT(PixelMaps.AtoA.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_B_TO_B_SIZE, CONTEXT_INT(PixelMaps.BtoB.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_G_TO_G_SIZE, CONTEXT_INT(PixelMaps.GtoG.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_I_TO_A_SIZE, CONTEXT_INT(PixelMaps.ItoA.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_I_TO_B_SIZE, CONTEXT_INT(PixelMaps.ItoB.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_I_TO_G_SIZE, CONTEXT_INT(PixelMaps.ItoG.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_I_TO_I_SIZE, CONTEXT_INT(PixelMaps.ItoI.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_I_TO_R_SIZE, CONTEXT_INT(PixelMaps.ItoR.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_R_TO_R_SIZE, CONTEXT_INT(PixelMaps.RtoR.Size), NO_EXTRA },
+ { GL_PIXEL_MAP_S_TO_S_SIZE, CONTEXT_INT(PixelMaps.StoS.Size), NO_EXTRA },
+ { GL_POINT_SIZE_GRANULARITY, CONTEXT_FLOAT(Const.PointSizeGranularity), NO_EXTRA },
+ { GL_POLYGON_MODE, CONTEXT_ENUM2(Polygon.FrontMode), NO_EXTRA },
+ { GL_POLYGON_OFFSET_BIAS_EXT, CONTEXT_FLOAT(Polygon.OffsetUnits), NO_EXTRA },
+ { GL_POLYGON_OFFSET_POINT, CONTEXT_BOOL(Polygon.OffsetPoint), NO_EXTRA },
+ { GL_POLYGON_OFFSET_LINE, CONTEXT_BOOL(Polygon.OffsetLine), NO_EXTRA },
+ { GL_POLYGON_SMOOTH, CONTEXT_BOOL(Polygon.SmoothFlag), NO_EXTRA },
+ { GL_POLYGON_SMOOTH_HINT, CONTEXT_ENUM(Hint.PolygonSmooth), NO_EXTRA },
+ { GL_POLYGON_STIPPLE, CONTEXT_BOOL(Polygon.StippleFlag), NO_EXTRA },
+ { GL_READ_BUFFER, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
+ { GL_RED_BIAS, CONTEXT_FLOAT(Pixel.RedBias), NO_EXTRA },
+ { GL_RED_SCALE, CONTEXT_FLOAT(Pixel.RedScale), NO_EXTRA },
+ { GL_RENDER_MODE, CONTEXT_ENUM(RenderMode), NO_EXTRA },
+ { GL_RGBA_MODE, CONST(1), NO_EXTRA },
+ { GL_SELECTION_BUFFER_SIZE, CONTEXT_INT(Select.BufferSize), NO_EXTRA },
+ { GL_SHARED_TEXTURE_PALETTE_EXT, CONTEXT_BOOL(Texture.SharedPalette), NO_EXTRA },
+
+ { GL_STEREO, BUFFER_INT(Visual.stereoMode), NO_EXTRA },
+
+ { GL_TEXTURE_1D, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
+ { GL_TEXTURE_3D, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
+ { GL_TEXTURE_1D_ARRAY_EXT, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
+ { GL_TEXTURE_2D_ARRAY_EXT, LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA },
+
+ { GL_TEXTURE_BINDING_1D, LOC_CUSTOM, TYPE_INT, TEXTURE_1D_INDEX, NO_EXTRA },
+ { GL_TEXTURE_BINDING_1D_ARRAY, LOC_CUSTOM, TYPE_INT,
+ TEXTURE_1D_ARRAY_INDEX, extra_MESA_texture_array },
+ { GL_TEXTURE_BINDING_2D_ARRAY, LOC_CUSTOM, TYPE_INT,
+ TEXTURE_1D_ARRAY_INDEX, extra_MESA_texture_array },
+ { GL_MAX_ARRAY_TEXTURE_LAYERS_EXT,
+ CONTEXT_INT(Const.MaxArrayTextureLayers), extra_MESA_texture_array },
+
+ { GL_TEXTURE_GEN_S, LOC_TEXUNIT, TYPE_BIT_0,
+ offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
+ { GL_TEXTURE_GEN_T, LOC_TEXUNIT, TYPE_BIT_1,
+ offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
+ { GL_TEXTURE_GEN_R, LOC_TEXUNIT, TYPE_BIT_2,
+ offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
+ { GL_TEXTURE_GEN_Q, LOC_TEXUNIT, TYPE_BIT_3,
+ offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA },
+ { GL_UNPACK_LSB_FIRST, CONTEXT_BOOL(Unpack.LsbFirst), NO_EXTRA },
+ { GL_UNPACK_ROW_LENGTH, CONTEXT_INT(Unpack.RowLength), NO_EXTRA },
+ { GL_UNPACK_SKIP_PIXELS, CONTEXT_INT(Unpack.SkipPixels), NO_EXTRA },
+ { GL_UNPACK_SKIP_ROWS, CONTEXT_INT(Unpack.SkipRows), NO_EXTRA },
+ { GL_UNPACK_SWAP_BYTES, CONTEXT_BOOL(Unpack.SwapBytes), NO_EXTRA },
+ { GL_UNPACK_SKIP_IMAGES_EXT, CONTEXT_INT(Unpack.SkipImages), NO_EXTRA },
+ { GL_UNPACK_IMAGE_HEIGHT_EXT, CONTEXT_INT(Unpack.ImageHeight), NO_EXTRA },
+ { GL_UNPACK_CLIENT_STORAGE_APPLE, CONTEXT_BOOL(Unpack.ClientStorage), NO_EXTRA },
+ { GL_ZOOM_X, CONTEXT_FLOAT(Pixel.ZoomX), NO_EXTRA },
+ { GL_ZOOM_Y, CONTEXT_FLOAT(Pixel.ZoomY), NO_EXTRA },
+
+ /* Vertex arrays */
+ { GL_VERTEX_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
+ { GL_NORMAL_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
+ { GL_COLOR_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
+ { GL_INDEX_ARRAY, ARRAY_BOOL(Index.Enabled), NO_EXTRA },
+ { GL_INDEX_ARRAY_TYPE, ARRAY_ENUM(Index.Type), NO_EXTRA },
+ { GL_INDEX_ARRAY_STRIDE, ARRAY_INT(Index.Stride), NO_EXTRA },
+ { GL_INDEX_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
+ { GL_TEXTURE_COORD_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
+ { GL_EDGE_FLAG_ARRAY, ARRAY_BOOL(EdgeFlag.Enabled), NO_EXTRA },
+ { GL_EDGE_FLAG_ARRAY_STRIDE, ARRAY_INT(EdgeFlag.Stride), NO_EXTRA },
+ { GL_EDGE_FLAG_ARRAY_COUNT_EXT, CONST(0), NO_EXTRA },
+
+ /* GL_ARB_texture_compression */
+ { GL_TEXTURE_COMPRESSION_HINT_ARB, CONTEXT_INT(Hint.TextureCompression), NO_EXTRA },
+
+ /* GL_EXT_compiled_vertex_array */
+ { GL_ARRAY_ELEMENT_LOCK_FIRST_EXT, CONTEXT_INT(Array.LockFirst),
+ extra_EXT_compiled_vertex_array },
+ { GL_ARRAY_ELEMENT_LOCK_COUNT_EXT, CONTEXT_INT(Array.LockCount),
+ extra_EXT_compiled_vertex_array },
+
+ /* GL_ARB_transpose_matrix */
+ { GL_TRANSPOSE_MODELVIEW_MATRIX_ARB,
+ CONTEXT_MATRIX_T(ModelviewMatrixStack), NO_EXTRA },
+ { GL_TRANSPOSE_PROJECTION_MATRIX_ARB,
+ CONTEXT_MATRIX_T(ProjectionMatrixStack.Top), NO_EXTRA },
+ { GL_TRANSPOSE_TEXTURE_MATRIX_ARB, CONTEXT_MATRIX_T(TextureMatrixStack), NO_EXTRA },
+
+ /* GL_EXT_secondary_color */
+ { GL_COLOR_SUM_EXT, CONTEXT_BOOL(Fog.ColorSumEnabled),
+ extra_EXT_secondary_color_ARB_vertex_program },
+ { GL_CURRENT_SECONDARY_COLOR_EXT,
+ CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_COLOR1][0], TYPE_FLOATN_4),
+ extra_EXT_secondary_color_flush_current },
+ { GL_SECONDARY_COLOR_ARRAY_EXT, ARRAY_BOOL(SecondaryColor.Enabled),
+ extra_EXT_secondary_color },
+ { GL_SECONDARY_COLOR_ARRAY_TYPE_EXT, ARRAY_ENUM(SecondaryColor.Type),
+ extra_EXT_secondary_color },
+ { GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT, ARRAY_INT(SecondaryColor.Stride),
+ extra_EXT_secondary_color },
+ { GL_SECONDARY_COLOR_ARRAY_SIZE_EXT, ARRAY_INT(SecondaryColor.Size),
+ extra_EXT_secondary_color },
+
+ /* GL_EXT_fog_coord */
+ { GL_CURRENT_FOG_COORDINATE_EXT,
+ CONTEXT_FLOAT(Current.Attrib[VERT_ATTRIB_FOG][0]),
+ extra_EXT_fog_coord_flush_current },
+ { GL_FOG_COORDINATE_ARRAY_EXT, ARRAY_BOOL(FogCoord.Enabled),
+ extra_EXT_fog_coord },
+ { GL_FOG_COORDINATE_ARRAY_TYPE_EXT, ARRAY_ENUM(FogCoord.Type),
+ extra_EXT_fog_coord },
+ { GL_FOG_COORDINATE_ARRAY_STRIDE_EXT, ARRAY_INT(FogCoord.Stride),
+ extra_EXT_fog_coord },
+ { GL_FOG_COORDINATE_SOURCE_EXT, CONTEXT_ENUM(Fog.FogCoordinateSource),
+ extra_EXT_fog_coord },
+
+ /* GL_IBM_rasterpos_clip */
+ { GL_RASTER_POSITION_UNCLIPPED_IBM,
+ CONTEXT_BOOL(Transform.RasterPositionUnclipped),
+ extra_IBM_rasterpos_clip },
+
+ /* GL_NV_point_sprite */
+ { GL_POINT_SPRITE_R_MODE_NV,
+ CONTEXT_ENUM(Point.SpriteRMode), extra_NV_point_sprite },
+ { GL_POINT_SPRITE_COORD_ORIGIN, CONTEXT_ENUM(Point.SpriteOrigin),
+ extra_NV_point_sprite_ARB_point_sprite },
+
+ /* GL_NV_vertex_program */
+ { GL_VERTEX_PROGRAM_BINDING_NV, LOC_CUSTOM, TYPE_INT, 0,
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY0_NV, ARRAY_BOOL(VertexAttrib[0].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY1_NV, ARRAY_BOOL(VertexAttrib[1].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY2_NV, ARRAY_BOOL(VertexAttrib[2].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY3_NV, ARRAY_BOOL(VertexAttrib[3].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY4_NV, ARRAY_BOOL(VertexAttrib[4].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY5_NV, ARRAY_BOOL(VertexAttrib[5].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY6_NV, ARRAY_BOOL(VertexAttrib[6].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY7_NV, ARRAY_BOOL(VertexAttrib[7].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY8_NV, ARRAY_BOOL(VertexAttrib[8].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY9_NV, ARRAY_BOOL(VertexAttrib[9].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY10_NV, ARRAY_BOOL(VertexAttrib[10].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY11_NV, ARRAY_BOOL(VertexAttrib[11].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY12_NV, ARRAY_BOOL(VertexAttrib[12].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY13_NV, ARRAY_BOOL(VertexAttrib[13].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY14_NV, ARRAY_BOOL(VertexAttrib[14].Enabled),
+ extra_NV_vertex_program },
+ { GL_VERTEX_ATTRIB_ARRAY15_NV, ARRAY_BOOL(VertexAttrib[15].Enabled),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB0_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[0]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB1_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[1]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB2_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[2]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB3_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[3]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB4_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[4]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB5_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[5]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB6_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[6]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB7_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[7]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB8_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[8]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB9_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[9]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB10_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[10]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB11_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[11]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB12_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[12]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB13_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[13]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB14_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[14]),
+ extra_NV_vertex_program },
+ { GL_MAP1_VERTEX_ATTRIB15_4_NV, CONTEXT_BOOL(Eval.Map1Attrib[15]),
+ extra_NV_vertex_program },
+
+ /* GL_NV_fragment_program */
+ { GL_FRAGMENT_PROGRAM_NV, CONTEXT_BOOL(FragmentProgram.Enabled),
+ extra_NV_fragment_program },
+ { GL_FRAGMENT_PROGRAM_BINDING_NV, LOC_CUSTOM, TYPE_INT, 0,
+ extra_NV_fragment_program },
+ { GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV,
+ CONST(MAX_NV_FRAGMENT_PROGRAM_PARAMS),
+ extra_NV_fragment_program },
+
+ /* GL_NV_texture_rectangle */
+ { GL_TEXTURE_RECTANGLE_NV,
+ LOC_CUSTOM, TYPE_BOOLEAN, 0, extra_NV_texture_rectangle },
+ { GL_TEXTURE_BINDING_RECTANGLE_NV,
+ LOC_CUSTOM, TYPE_INT, TEXTURE_RECT_INDEX, extra_NV_texture_rectangle },
+ { GL_MAX_RECTANGLE_TEXTURE_SIZE_NV,
+ CONTEXT_INT(Const.MaxTextureRectSize), extra_NV_texture_rectangle },
+
+ /* GL_EXT_stencil_two_side */
+ { GL_STENCIL_TEST_TWO_SIDE_EXT, CONTEXT_BOOL(Stencil.TestTwoSide),
+ extra_EXT_stencil_two_side },
+ { GL_ACTIVE_STENCIL_FACE_EXT, LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA },
+
+ /* GL_NV_light_max_exponent */
+ { GL_MAX_SHININESS_NV, CONTEXT_FLOAT(Const.MaxShininess),
+ extra_NV_light_max_exponent },
+ { GL_MAX_SPOT_EXPONENT_NV, CONTEXT_FLOAT(Const.MaxSpotExponent),
+ extra_NV_light_max_exponent },
+
+ /* GL_NV_primitive_restart */
+ { GL_PRIMITIVE_RESTART_NV, CONTEXT_BOOL(Array.PrimitiveRestart),
+ extra_NV_primitive_restart },
+ { GL_PRIMITIVE_RESTART_INDEX_NV, CONTEXT_INT(Array.RestartIndex),
+ extra_NV_primitive_restart },
+
+ /* GL_ARB_vertex_buffer_object */
+ { GL_INDEX_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_array_object, Index.BufferObj), NO_EXTRA },
+ { GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_array_object, EdgeFlag.BufferObj), NO_EXTRA },
+ { GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_array_object, SecondaryColor.BufferObj), NO_EXTRA },
+ { GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB, LOC_CUSTOM, TYPE_INT,
+ offsetof(struct gl_array_object, FogCoord.BufferObj), NO_EXTRA },
+
+ /* GL_EXT_pixel_buffer_object */
+ { GL_PIXEL_PACK_BUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
+ extra_EXT_pixel_buffer_object },
+ { GL_PIXEL_UNPACK_BUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
+ extra_EXT_pixel_buffer_object },
+
+ /* GL_ARB_vertex_program */
+ { GL_VERTEX_PROGRAM_ARB, /* == GL_VERTEX_PROGRAM_NV */
+ CONTEXT_BOOL(VertexProgram.Enabled),
+ extra_ARB_vertex_program_NV_vertex_program },
+ { GL_VERTEX_PROGRAM_POINT_SIZE_ARB, /* == GL_VERTEX_PROGRAM_POINT_SIZE_NV*/
+ CONTEXT_BOOL(VertexProgram.PointSizeEnabled),
+ extra_ARB_vertex_program_NV_vertex_program },
+ { GL_VERTEX_PROGRAM_TWO_SIDE_ARB, /* == GL_VERTEX_PROGRAM_TWO_SIDE_NV */
+ CONTEXT_BOOL(VertexProgram.TwoSideEnabled),
+ extra_ARB_vertex_program_NV_vertex_program },
+ { GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB, /* == GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV */
+ CONTEXT_INT(Const.MaxProgramMatrixStackDepth),
+ extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
+ { GL_MAX_PROGRAM_MATRICES_ARB, /* == GL_MAX_TRACK_MATRICES_NV */
+ CONTEXT_INT(Const.MaxProgramMatrices),
+ extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
+ { GL_CURRENT_MATRIX_STACK_DEPTH_ARB, /* == GL_CURRENT_MATRIX_STACK_DEPTH_NV */
+ LOC_CUSTOM, TYPE_INT, 0,
+ extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
+
+ { GL_CURRENT_MATRIX_ARB, /* == GL_CURRENT_MATRIX_NV */
+ LOC_CUSTOM, TYPE_MATRIX, 0,
+ extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
+ { GL_TRANSPOSE_CURRENT_MATRIX_ARB, /* == GL_CURRENT_MATRIX_NV */
+ LOC_CUSTOM, TYPE_MATRIX, 0,
+ extra_ARB_vertex_program_ARB_fragment_program },
+
+ { GL_PROGRAM_ERROR_POSITION_ARB, /* == GL_PROGRAM_ERROR_POSITION_NV */
+ CONTEXT_INT(Program.ErrorPos),
+ extra_NV_vertex_program_ARB_vertex_program_ARB_fragment_program_NV_vertex_program },
+
+ /* GL_ARB_fragment_program */
+ { GL_FRAGMENT_PROGRAM_ARB, CONTEXT_BOOL(FragmentProgram.Enabled),
+ extra_ARB_fragment_program },
+
+ /* GL_EXT_depth_bounds_test */
+ { GL_DEPTH_BOUNDS_TEST_EXT, CONTEXT_BOOL(Depth.BoundsTest),
+ extra_EXT_depth_bounds_test },
+ { GL_DEPTH_BOUNDS_EXT, CONTEXT_FLOAT2(Depth.BoundsMin),
+ extra_EXT_depth_bounds_test },
+
+ /* GL_ARB_depth_clamp*/
+ { GL_DEPTH_CLAMP, CONTEXT_BOOL(Transform.DepthClamp),
+ extra_ARB_depth_clamp },
+
+ /* GL_ARB_draw_buffers */
+ { GL_DRAW_BUFFER0_ARB, BUFFER_ENUM(ColorDrawBuffer[0]), NO_EXTRA },
+ { GL_DRAW_BUFFER1_ARB, BUFFER_ENUM(ColorDrawBuffer[1]),
+ extra_valid_draw_buffer },
+ { GL_DRAW_BUFFER2_ARB, BUFFER_ENUM(ColorDrawBuffer[2]),
+ extra_valid_draw_buffer },
+ { GL_DRAW_BUFFER3_ARB, BUFFER_ENUM(ColorDrawBuffer[3]),
+ extra_valid_draw_buffer },
+ { GL_DRAW_BUFFER4_ARB, BUFFER_ENUM(ColorDrawBuffer[4]),
+ extra_valid_draw_buffer },
+ { GL_DRAW_BUFFER5_ARB, BUFFER_ENUM(ColorDrawBuffer[5]),
+ extra_valid_draw_buffer },
+ { GL_DRAW_BUFFER6_ARB, BUFFER_ENUM(ColorDrawBuffer[6]),
+ extra_valid_draw_buffer },
+ { GL_DRAW_BUFFER7_ARB, BUFFER_ENUM(ColorDrawBuffer[7]),
+ extra_valid_draw_buffer },
+
+ /* GL_ATI_fragment_shader */
+ { GL_NUM_FRAGMENT_REGISTERS_ATI, CONST(6), extra_ATI_fragment_shader },
+ { GL_NUM_FRAGMENT_CONSTANTS_ATI, CONST(8), extra_ATI_fragment_shader },
+ { GL_NUM_PASSES_ATI, CONST(2), extra_ATI_fragment_shader },
+ { GL_NUM_INSTRUCTIONS_PER_PASS_ATI, CONST(8), extra_ATI_fragment_shader },
+ { GL_NUM_INSTRUCTIONS_TOTAL_ATI, CONST(16), extra_ATI_fragment_shader },
+ { GL_COLOR_ALPHA_PAIRING_ATI, CONST(GL_TRUE), extra_ATI_fragment_shader },
+ { GL_NUM_LOOPBACK_COMPONENTS_ATI, CONST(3), extra_ATI_fragment_shader },
+ { GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI,
+ CONST(3), extra_ATI_fragment_shader },
+
+ /* GL_EXT_framebuffer_object */
+ { GL_MAX_COLOR_ATTACHMENTS_EXT, CONTEXT_INT(Const.MaxColorAttachments),
+ extra_EXT_framebuffer_object },
+
+ /* GL_EXT_framebuffer_blit
+ * NOTE: GL_DRAW_FRAMEBUFFER_BINDING_EXT == GL_FRAMEBUFFER_BINDING_EXT */
+ { GL_READ_FRAMEBUFFER_BINDING_EXT, LOC_CUSTOM, TYPE_INT, 0,
+ extra_EXT_framebuffer_blit },
+
+ /* GL_EXT_provoking_vertex */
+ { GL_PROVOKING_VERTEX_EXT,
+ CONTEXT_BOOL(Light.ProvokingVertex), extra_EXT_provoking_vertex },
+ { GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT,
+ CONTEXT_BOOL(Const.QuadsFollowProvokingVertexConvention),
+ extra_EXT_provoking_vertex },
+
+ /* GL_ARB_framebuffer_object */
+ { GL_MAX_SAMPLES, CONTEXT_INT(Const.MaxSamples),
+ extra_ARB_framebuffer_object_EXT_framebuffer_multisample },
+
+ /* GL_APPLE_vertex_array_object */
+ { GL_VERTEX_ARRAY_BINDING_APPLE, ARRAY_INT(Name),
+ extra_APPLE_vertex_array_object },
+
+ /* GL_ARB_seamless_cube_map */
+ { GL_TEXTURE_CUBE_MAP_SEAMLESS,
+ CONTEXT_BOOL(Texture.CubeMapSeamless), extra_ARB_seamless_cube_map },
+
+ /* GL_ARB_sync */
+ { GL_MAX_SERVER_WAIT_TIMEOUT,
+ CONTEXT_INT64(Const.MaxServerWaitTimeout), extra_ARB_sync },
+
+ /* GL_EXT_texture_integer */
+ { GL_RGBA_INTEGER_MODE_EXT, BUFFER_BOOL(_IntegerColor),
+ extra_EXT_texture_integer },
+
+ /* GL_EXT_transform_feedback */
+ { GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, LOC_CUSTOM, TYPE_INT, 0,
+ extra_EXT_transform_feedback },
+ { GL_RASTERIZER_DISCARD, CONTEXT_BOOL(TransformFeedback.RasterDiscard),
+ extra_EXT_transform_feedback },
+ { GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
+ CONTEXT_INT(Const.MaxTransformFeedbackInterleavedComponents),
+ extra_EXT_transform_feedback },
+ { GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
+ CONTEXT_INT(Const.MaxTransformFeedbackSeparateAttribs),
+ extra_EXT_transform_feedback },
+ { GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
+ CONTEXT_INT(Const.MaxTransformFeedbackSeparateComponents),
+ extra_EXT_transform_feedback },
+
+ /* GL_ARB_transform_feedback2 */
+ { GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED, LOC_CUSTOM, TYPE_BOOLEAN, 0,
+ extra_ARB_transform_feedback2 },
+ { GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE, LOC_CUSTOM, TYPE_BOOLEAN, 0,
+ extra_ARB_transform_feedback2 },
+ { GL_TRANSFORM_FEEDBACK_BINDING, LOC_CUSTOM, TYPE_INT, 0,
+ extra_ARB_transform_feedback2 },
+
+ /* GL_ARB_geometry_shader4 */
+ { GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB,
+ CONTEXT_INT(Const.GeometryProgram.MaxGeometryTextureImageUnits),
+ extra_ARB_geometry_shader4 },
+ { GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB,
+ CONTEXT_INT(Const.GeometryProgram.MaxGeometryOutputVertices),
+ extra_ARB_geometry_shader4 },
+ { GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB,
+ CONTEXT_INT(Const.GeometryProgram.MaxGeometryTotalOutputComponents),
+ extra_ARB_geometry_shader4 },
+ { GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB,
+ CONTEXT_INT(Const.GeometryProgram.MaxGeometryUniformComponents),
+ extra_ARB_geometry_shader4 },
+ { GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB,
+ CONTEXT_INT(Const.GeometryProgram.MaxGeometryVaryingComponents),
+ extra_ARB_geometry_shader4 },
+ { GL_MAX_VERTEX_VARYING_COMPONENTS_ARB,
+ CONTEXT_INT(Const.GeometryProgram.MaxVertexVaryingComponents),
+ extra_ARB_geometry_shader4 },
+
+ /* GL_EXT_gpu_shader4 / GL 3.0 */
+ { GL_MIN_PROGRAM_TEXEL_OFFSET,
+ CONTEXT_INT(Const.MinProgramTexelOffset),
+ extra_EXT_gpu_shader4 },
+ { GL_MAX_PROGRAM_TEXEL_OFFSET,
+ CONTEXT_INT(Const.MaxProgramTexelOffset),
+ extra_EXT_gpu_shader4 },
+
+ /* GL 3.0 */
+ { GL_NUM_EXTENSIONS, LOC_CUSTOM, TYPE_INT, 0, extra_version_30 },
+ { GL_MAJOR_VERSION, CONTEXT_INT(VersionMajor), extra_version_30 },
+ { GL_MINOR_VERSION, CONTEXT_INT(VersionMinor), extra_version_30 },
+ { GL_CONTEXT_FLAGS, CONTEXT_INT(Const.ContextFlags), extra_version_30 },
+
+ /* GL3.0 / GL_EXT_framebuffer_sRGB */
+ { GL_FRAMEBUFFER_SRGB_EXT, CONTEXT_BOOL(Color.sRGBEnabled), extra_EXT_framebuffer_sRGB },
+ { GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, BUFFER_INT(Visual.sRGBCapable), extra_EXT_framebuffer_sRGB },
+
+ /* GL 3.1 */
+ /* NOTE: different enum values for GL_PRIMITIVE_RESTART_NV
+ * vs. GL_PRIMITIVE_RESTART!
+ */
+ { GL_PRIMITIVE_RESTART, CONTEXT_BOOL(Array.PrimitiveRestart),
+ extra_version_31 },
+ { GL_PRIMITIVE_RESTART_INDEX, CONTEXT_INT(Array.RestartIndex),
+ extra_version_31 },
+
+
+ /* GL 3.2 */
+ { GL_CONTEXT_PROFILE_MASK, CONTEXT_INT(Const.ProfileMask),
+ extra_version_32 },
+#endif /* FEATURE_GL */
+};
+
+/* All we need now is a way to look up the value struct from the enum.
+ * The code generated by gcc for the old generated big switch
+ * statement is a big, balanced, open coded if/else tree, essentially
+ * an unrolled binary search. It would be natural to sort the new
+ * enum table and use bsearch(), but we will use a read-only hash
+ * table instead. bsearch() has a nice guaranteed worst case
+ * performance, but we're also guaranteed to hit that worst case
+ * (log2(n) iterations) for about half the enums. Instead, using an
+ * open addressing hash table, we can find the enum on the first try
+ * for 80% of the enums, 1 collision for 10% and never more than 5
+ * collisions for any enum (typical numbers). And the code is very
+ * simple, even though it feels a little magic. */
+
+static unsigned short table[1024];
+static const int prime_factor = 89, prime_step = 281;
+
+#ifdef GET_DEBUG
+static void
+print_table_stats(void)
+{
+ int i, j, collisions[11], count, hash, mask;
+ const struct value_desc *d;
+
+ count = 0;
+ mask = Elements(table) - 1;
+ memset(collisions, 0, sizeof collisions);
+
+ for (i = 0; i < Elements(table); i++) {
+ if (!table[i])
+ continue;
+ count++;
+ d = &values[table[i]];
+ hash = (d->pname * prime_factor);
+ j = 0;
+ while (1) {
+ if (values[table[hash & mask]].pname == d->pname)
+ break;
+ hash += prime_step;
+ j++;
+ }
+
+ if (j < 10)
+ collisions[j]++;
+ else
+ collisions[10]++;
+ }
+
+ printf("number of enums: %d (total %d)\n", count, Elements(values));
+ for (i = 0; i < Elements(collisions) - 1; i++)
+ if (collisions[i] > 0)
+ printf(" %d enums with %d %scollisions\n",
+ collisions[i], i, i == 10 ? "or more " : "");
+}
+#endif
+
+/**
+ * Initialize the enum hash for a given API
+ *
+ * This is called from one_time_init() to insert the enum values that
+ * are valid for the API in question into the enum hash table.
+ *
+ * \param the current context, for determining the API in question
+ */
+void _mesa_init_get_hash(struct gl_context *ctx)
+{
+ int i, hash, index, mask;
+ int api_mask = 0, api_bit;
+
+ mask = Elements(table) - 1;
+ api_bit = 1 << ctx->API;
+
+ for (i = 0; i < Elements(values); i++) {
+ if (values[i].type == TYPE_API_MASK) {
+ api_mask = values[i].offset;
+ continue;
+ }
+ if (!(api_mask & api_bit))
+ continue;
+
+ hash = (values[i].pname * prime_factor) & mask;
+ while (1) {
+ index = hash & mask;
+ if (!table[index]) {
+ table[index] = i;
+ break;
+ }
+ hash += prime_step;
+ }
+ }
+
+#ifdef GET_DEBUG
+ print_table_stats();
+#endif
+}
+
+/**
+ * Handle irregular enums
+ *
+ * Some values don't conform to the "well-known type at context
+ * pointer + offset" pattern, so we have this function to catch all
+ * the corner cases. Typically, it's a computed value or a one-off
+ * pointer to a custom struct or something.
+ *
+ * In this case we can't return a pointer to the value, so we'll have
+ * to use the temporary variable 'v' declared back in the calling
+ * glGet*v() function to store the result.
+ *
+ * \param ctx the current context
+ * \param d the struct value_desc that describes the enum
+ * \param v pointer to the tmp declared in the calling glGet*v() function
+ */
+static void
+find_custom_value(struct gl_context *ctx, const struct value_desc *d, union value *v)
+{
+ struct gl_buffer_object *buffer_obj;
+ struct gl_client_array *array;
+ GLuint unit, *p;
+
+ switch (d->pname) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_TEXTURE_RECTANGLE_NV:
+ v->value_bool = _mesa_IsEnabled(d->pname);
+ break;
+
+ case GL_LINE_STIPPLE_PATTERN:
+ /* This is the only GLushort, special case it here by promoting
+ * to an int rather than introducing a new type. */
+ v->value_int = ctx->Line.StipplePattern;
+ break;
+
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ unit = ctx->Texture.CurrentUnit;
+ v->value_float_4[0] = ctx->Current.RasterTexCoords[unit][0];
+ v->value_float_4[1] = ctx->Current.RasterTexCoords[unit][1];
+ v->value_float_4[2] = ctx->Current.RasterTexCoords[unit][2];
+ v->value_float_4[3] = ctx->Current.RasterTexCoords[unit][3];
+ break;
+
+ case GL_CURRENT_TEXTURE_COORDS:
+ unit = ctx->Texture.CurrentUnit;
+ v->value_float_4[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][0];
+ v->value_float_4[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][1];
+ v->value_float_4[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][2];
+ v->value_float_4[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][3];
+ break;
+
+ case GL_COLOR_WRITEMASK:
+ v->value_int_4[0] = ctx->Color.ColorMask[0][RCOMP] ? 1 : 0;
+ v->value_int_4[1] = ctx->Color.ColorMask[0][GCOMP] ? 1 : 0;
+ v->value_int_4[2] = ctx->Color.ColorMask[0][BCOMP] ? 1 : 0;
+ v->value_int_4[3] = ctx->Color.ColorMask[0][ACOMP] ? 1 : 0;
+ break;
+
+ case GL_EDGE_FLAG:
+ v->value_bool = ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0;
+ break;
+
+ case GL_READ_BUFFER:
+ v->value_enum = ctx->ReadBuffer->ColorReadBuffer;
+ break;
+
+ case GL_MAP2_GRID_DOMAIN:
+ v->value_float_4[0] = ctx->Eval.MapGrid2u1;
+ v->value_float_4[1] = ctx->Eval.MapGrid2u2;
+ v->value_float_4[2] = ctx->Eval.MapGrid2v1;
+ v->value_float_4[3] = ctx->Eval.MapGrid2v2;
+ break;
+
+ case GL_TEXTURE_STACK_DEPTH:
+ unit = ctx->Texture.CurrentUnit;
+ v->value_int = ctx->TextureMatrixStack[unit].Depth + 1;
+ break;
+ case GL_TEXTURE_MATRIX:
+ unit = ctx->Texture.CurrentUnit;
+ v->value_matrix = ctx->TextureMatrixStack[unit].Top;
+ break;
+
+ case GL_TEXTURE_COORD_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ array = &ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture];
+ v->value_int = *(GLuint *) ((char *) array + d->offset);
+ break;
+
+ case GL_ACTIVE_TEXTURE_ARB:
+ v->value_int = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit;
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ v->value_int = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture;
+ break;
+
+ case GL_MODELVIEW_STACK_DEPTH:
+ case GL_PROJECTION_STACK_DEPTH:
+ v->value_int = *(GLint *) ((char *) ctx + d->offset) + 1;
+ break;
+
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_3D_TEXTURE_SIZE:
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
+ p = (GLuint *) ((char *) ctx + d->offset);
+ v->value_int = 1 << (*p - 1);
+ break;
+
+ case GL_SCISSOR_BOX:
+ v->value_int_4[0] = ctx->Scissor.X;
+ v->value_int_4[1] = ctx->Scissor.Y;
+ v->value_int_4[2] = ctx->Scissor.Width;
+ v->value_int_4[3] = ctx->Scissor.Height;
+ break;
+
+ case GL_LIST_INDEX:
+ v->value_int =
+ ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0;
+ break;
+ case GL_LIST_MODE:
+ if (!ctx->CompileFlag)
+ v->value_enum = 0;
+ else if (ctx->ExecuteFlag)
+ v->value_enum = GL_COMPILE_AND_EXECUTE;
+ else
+ v->value_enum = GL_COMPILE;
+ break;
+
+ case GL_VIEWPORT:
+ v->value_int_4[0] = ctx->Viewport.X;
+ v->value_int_4[1] = ctx->Viewport.Y;
+ v->value_int_4[2] = ctx->Viewport.Width;
+ v->value_int_4[3] = ctx->Viewport.Height;
+ break;
+
+ case GL_ACTIVE_STENCIL_FACE_EXT:
+ v->value_enum = ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT;
+ break;
+
+ case GL_STENCIL_FAIL:
+ v->value_enum = ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_FUNC:
+ v->value_enum = ctx->Stencil.Function[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ v->value_enum = ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ v->value_enum = ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_REF:
+ v->value_int = ctx->Stencil.Ref[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ v->value_int = ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_WRITEMASK:
+ v->value_int = ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace];
+ break;
+
+ case GL_NUM_EXTENSIONS:
+ v->value_int = _mesa_get_extension_count(ctx);
+ break;
+
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ v->value_int = _mesa_get_color_read_type(ctx);
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ v->value_int = _mesa_get_color_read_format(ctx);
+ break;
+
+ case GL_CURRENT_MATRIX_STACK_DEPTH_ARB:
+ v->value_int = ctx->CurrentStack->Depth + 1;
+ break;
+ case GL_CURRENT_MATRIX_ARB:
+ case GL_TRANSPOSE_CURRENT_MATRIX_ARB:
+ v->value_matrix = ctx->CurrentStack->Top;
+ break;
+
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
+ v->value_int = _mesa_get_compressed_formats(ctx, NULL, GL_FALSE);
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
+ v->value_int_n.n =
+ _mesa_get_compressed_formats(ctx, v->value_int_n.ints, GL_FALSE);
+ ASSERT(v->value_int_n.n <= 100);
+ break;
+
+ case GL_MAX_VARYING_FLOATS_ARB:
+ v->value_int = ctx->Const.MaxVarying * 4;
+ break;
+
+ /* Various object names */
+
+ case GL_TEXTURE_BINDING_1D:
+ case GL_TEXTURE_BINDING_2D:
+ case GL_TEXTURE_BINDING_3D:
+ case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
+ case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
+ case GL_TEXTURE_BINDING_RECTANGLE_NV:
+ unit = ctx->Texture.CurrentUnit;
+ v->value_int =
+ ctx->Texture.Unit[unit].CurrentTex[d->offset]->Name;
+ break;
+
+ /* GL_ARB_vertex_buffer_object */
+ case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
+ case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
+ case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
+ case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
+ case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
+ buffer_obj = (struct gl_buffer_object *)
+ ((char *) ctx->Array.ArrayObj + d->offset);
+ v->value_int = buffer_obj->Name;
+ break;
+ case GL_ARRAY_BUFFER_BINDING_ARB:
+ v->value_int = ctx->Array.ArrayBufferObj->Name;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
+ v->value_int =
+ ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
+ v->value_int = ctx->Array.ElementArrayBufferObj->Name;
+ break;
+
+ /* ARB_copy_buffer */
+ case GL_COPY_READ_BUFFER:
+ v->value_int = ctx->CopyReadBuffer->Name;
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ v->value_int = ctx->CopyWriteBuffer->Name;
+ break;
+
+ case GL_FRAGMENT_PROGRAM_BINDING_NV:
+ v->value_int =
+ ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0;
+ break;
+ case GL_VERTEX_PROGRAM_BINDING_NV:
+ v->value_int =
+ ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0;
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
+ v->value_int = ctx->Pack.BufferObj->Name;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
+ v->value_int = ctx->Unpack.BufferObj->Name;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ v->value_int = ctx->TransformFeedback.CurrentBuffer->Name;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED:
+ v->value_int = ctx->TransformFeedback.CurrentObject->Paused;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE:
+ v->value_int = ctx->TransformFeedback.CurrentObject->Active;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BINDING:
+ v->value_int = ctx->TransformFeedback.CurrentObject->Name;
+ break;
+ case GL_CURRENT_PROGRAM:
+ v->value_int =
+ ctx->Shader.ActiveProgram ? ctx->Shader.ActiveProgram->Name : 0;
+ break;
+ case GL_READ_FRAMEBUFFER_BINDING_EXT:
+ v->value_int = ctx->ReadBuffer->Name;
+ break;
+ case GL_RENDERBUFFER_BINDING_EXT:
+ v->value_int =
+ ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0;
+ break;
+ case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+ v->value_int = ctx->Array.ArrayObj->PointSize.BufferObj->Name;
+ break;
+
+ case GL_MAX_VERTEX_UNIFORM_VECTORS:
+ v->value_int = ctx->Const.VertexProgram.MaxUniformComponents / 4;
+ break;
+
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+ v->value_int = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
+ break;
+ }
+}
+
+/**
+ * Check extra constraints on a struct value_desc descriptor
+ *
+ * If a struct value_desc has a non-NULL extra pointer, it means that
+ * there are a number of extra constraints to check or actions to
+ * perform. The extras is just an integer array where each integer
+ * encode different constraints or actions.
+ *
+ * \param ctx current context
+ * \param func name of calling glGet*v() function for error reporting
+ * \param d the struct value_desc that has the extra constraints
+ *
+ * \return GL_FALSE if one of the constraints was not satisfied,
+ * otherwise GL_TRUE.
+ */
+static GLboolean
+check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d)
+{
+ const GLuint version = ctx->VersionMajor * 10 + ctx->VersionMinor;
+ int total, enabled;
+ const int *e;
+
+ total = 0;
+ enabled = 0;
+ for (e = d->extra; *e != EXTRA_END; e++)
+ switch (*e) {
+ case EXTRA_VERSION_30:
+ if (version >= 30) {
+ total++;
+ enabled++;
+ }
+ break;
+ case EXTRA_VERSION_31:
+ if (version >= 31) {
+ total++;
+ enabled++;
+ }
+ break;
+ case EXTRA_VERSION_32:
+ if (version >= 32) {
+ total++;
+ enabled++;
+ }
+ break;
+ case EXTRA_VERSION_ES2:
+ if (ctx->API == API_OPENGLES2) {
+ total++;
+ enabled++;
+ }
+ break;
+ case EXTRA_NEW_BUFFERS:
+ if (ctx->NewState & _NEW_BUFFERS)
+ _mesa_update_state(ctx);
+ break;
+ case EXTRA_FLUSH_CURRENT:
+ FLUSH_CURRENT(ctx, 0);
+ break;
+ case EXTRA_VALID_DRAW_BUFFER:
+ if (d->pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(draw buffer %u)",
+ func, d->pname - GL_DRAW_BUFFER0_ARB);
+ return GL_FALSE;
+ }
+ break;
+ case EXTRA_VALID_TEXTURE_UNIT:
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture %u)",
+ func, ctx->Texture.CurrentUnit);
+ return GL_FALSE;
+ }
+ break;
+ case EXTRA_END:
+ break;
+ default: /* *e is a offset into the extension struct */
+ total++;
+ if (*(GLboolean *) ((char *) &ctx->Extensions + *e))
+ enabled++;
+ break;
+ }
+
+ if (total > 0 && enabled == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(d->pname));
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static const struct value_desc error_value =
+ { 0, 0, TYPE_INVALID, NO_OFFSET, NO_EXTRA };
+
+/**
+ * Find the struct value_desc corresponding to the enum 'pname'.
+ *
+ * We hash the enum value to get an index into the 'table' array,
+ * which holds the index in the 'values' array of struct value_desc.
+ * Once we've found the entry, we do the extra checks, if any, then
+ * look up the value and return a pointer to it.
+ *
+ * If the value has to be computed (for example, it's the result of a
+ * function call or we need to add 1 to it), we use the tmp 'v' to
+ * store the result.
+ *
+ * \param func name of glGet*v() func for error reporting
+ * \param pname the enum value we're looking up
+ * \param p is were we return the pointer to the value
+ * \param v a tmp union value variable in the calling glGet*v() function
+ *
+ * \return the struct value_desc corresponding to the enum or a struct
+ * value_desc of TYPE_INVALID if not found. This lets the calling
+ * glGet*v() function jump right into a switch statement and
+ * handle errors there instead of having to check for NULL.
+ */
+static const struct value_desc *
+find_value(const char *func, GLenum pname, void **p, union value *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *unit;
+ int mask, hash;
+ const struct value_desc *d;
+
+ mask = Elements(table) - 1;
+ hash = (pname * prime_factor);
+ while (1) {
+ d = &values[table[hash & mask]];
+
+ /* If the enum isn't valid, the hash walk ends with index 0,
+ * which is the API mask entry at the beginning of values[]. */
+ if (unlikely(d->type == TYPE_API_MASK)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
+ return &error_value;
+ }
+
+ if (likely(d->pname == pname))
+ break;
+
+ hash += prime_step;
+ }
+
+ if (unlikely(d->extra && !check_extra(ctx, func, d)))
+ return &error_value;
+
+ switch (d->location) {
+ case LOC_BUFFER:
+ *p = ((char *) ctx->DrawBuffer + d->offset);
+ return d;
+ case LOC_CONTEXT:
+ *p = ((char *) ctx + d->offset);
+ return d;
+ case LOC_ARRAY:
+ *p = ((char *) ctx->Array.ArrayObj + d->offset);
+ return d;
+ case LOC_TEXUNIT:
+ unit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ *p = ((char *) unit + d->offset);
+ return d;
+ case LOC_CUSTOM:
+ find_custom_value(ctx, d, v);
+ *p = v;
+ return d;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* silence warning */
+ return &error_value;
+}
+
+static const int transpose[] = {
+ 0, 4, 8, 12,
+ 1, 5, 9, 13,
+ 2, 6, 10, 14,
+ 3, 7, 11, 15
+};
+
+void GLAPIENTRY
+_mesa_GetBooleanv(GLenum pname, GLboolean *params)
+{
+ const struct value_desc *d;
+ union value v;
+ GLmatrix *m;
+ int shift, i;
+ void *p;
+
+ d = find_value("glGetBooleanv", pname, &p, &v);
+ switch (d->type) {
+ case TYPE_INVALID:
+ break;
+ case TYPE_CONST:
+ params[0] = INT_TO_BOOLEAN(d->offset);
+ break;
+
+ case TYPE_FLOAT_4:
+ case TYPE_FLOATN_4:
+ params[3] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[3]);
+ case TYPE_FLOAT_3:
+ case TYPE_FLOATN_3:
+ params[2] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[2]);
+ case TYPE_FLOAT_2:
+ case TYPE_FLOATN_2:
+ params[1] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[1]);
+ case TYPE_FLOAT:
+ case TYPE_FLOATN:
+ params[0] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[0]);
+ break;
+
+ case TYPE_DOUBLEN:
+ params[0] = FLOAT_TO_BOOLEAN(((GLdouble *) p)[0]);
+ break;
+
+ case TYPE_INT_4:
+ params[3] = INT_TO_BOOLEAN(((GLint *) p)[3]);
+ case TYPE_INT_3:
+ params[2] = INT_TO_BOOLEAN(((GLint *) p)[2]);
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = INT_TO_BOOLEAN(((GLint *) p)[1]);
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = INT_TO_BOOLEAN(((GLint *) p)[0]);
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = INT_TO_BOOLEAN(v.value_int_n.ints[i]);
+ break;
+
+ case TYPE_INT64:
+ params[0] = INT64_TO_BOOLEAN(((GLint64 *) p)[0]);
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = ((GLboolean*) p)[0];
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_BOOLEAN(m->m[i]);
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_BOOLEAN(m->m[transpose[i]]);
+ break;
+
+ case TYPE_BIT_0:
+ case TYPE_BIT_1:
+ case TYPE_BIT_2:
+ case TYPE_BIT_3:
+ case TYPE_BIT_4:
+ case TYPE_BIT_5:
+ shift = d->type - TYPE_BIT_0;
+ params[0] = (*(GLbitfield *) p >> shift) & 1;
+ break;
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetFloatv(GLenum pname, GLfloat *params)
+{
+ const struct value_desc *d;
+ union value v;
+ GLmatrix *m;
+ int shift, i;
+ void *p;
+
+ d = find_value("glGetFloatv", pname, &p, &v);
+ switch (d->type) {
+ case TYPE_INVALID:
+ break;
+ case TYPE_CONST:
+ params[0] = (GLfloat) d->offset;
+ break;
+
+ case TYPE_FLOAT_4:
+ case TYPE_FLOATN_4:
+ params[3] = ((GLfloat *) p)[3];
+ case TYPE_FLOAT_3:
+ case TYPE_FLOATN_3:
+ params[2] = ((GLfloat *) p)[2];
+ case TYPE_FLOAT_2:
+ case TYPE_FLOATN_2:
+ params[1] = ((GLfloat *) p)[1];
+ case TYPE_FLOAT:
+ case TYPE_FLOATN:
+ params[0] = ((GLfloat *) p)[0];
+ break;
+
+ case TYPE_DOUBLEN:
+ params[0] = ((GLdouble *) p)[0];
+ break;
+
+ case TYPE_INT_4:
+ params[3] = (GLfloat) (((GLint *) p)[3]);
+ case TYPE_INT_3:
+ params[2] = (GLfloat) (((GLint *) p)[2]);
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = (GLfloat) (((GLint *) p)[1]);
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = (GLfloat) (((GLint *) p)[0]);
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = INT_TO_FLOAT(v.value_int_n.ints[i]);
+ break;
+
+ case TYPE_INT64:
+ params[0] = ((GLint64 *) p)[0];
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = BOOLEAN_TO_FLOAT(*(GLboolean*) p);
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = m->m[i];
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = m->m[transpose[i]];
+ break;
+
+ case TYPE_BIT_0:
+ case TYPE_BIT_1:
+ case TYPE_BIT_2:
+ case TYPE_BIT_3:
+ case TYPE_BIT_4:
+ case TYPE_BIT_5:
+ shift = d->type - TYPE_BIT_0;
+ params[0] = BOOLEAN_TO_FLOAT((*(GLbitfield *) p >> shift) & 1);
+ break;
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetIntegerv(GLenum pname, GLint *params)
+{
+ const struct value_desc *d;
+ union value v;
+ GLmatrix *m;
+ int shift, i;
+ void *p;
+
+ d = find_value("glGetIntegerv", pname, &p, &v);
+ switch (d->type) {
+ case TYPE_INVALID:
+ break;
+ case TYPE_CONST:
+ params[0] = d->offset;
+ break;
+
+ case TYPE_FLOAT_4:
+ params[3] = IROUND(((GLfloat *) p)[3]);
+ case TYPE_FLOAT_3:
+ params[2] = IROUND(((GLfloat *) p)[2]);
+ case TYPE_FLOAT_2:
+ params[1] = IROUND(((GLfloat *) p)[1]);
+ case TYPE_FLOAT:
+ params[0] = IROUND(((GLfloat *) p)[0]);
+ break;
+
+ case TYPE_FLOATN_4:
+ params[3] = FLOAT_TO_INT(((GLfloat *) p)[3]);
+ case TYPE_FLOATN_3:
+ params[2] = FLOAT_TO_INT(((GLfloat *) p)[2]);
+ case TYPE_FLOATN_2:
+ params[1] = FLOAT_TO_INT(((GLfloat *) p)[1]);
+ case TYPE_FLOATN:
+ params[0] = FLOAT_TO_INT(((GLfloat *) p)[0]);
+ break;
+
+ case TYPE_DOUBLEN:
+ params[0] = FLOAT_TO_INT(((GLdouble *) p)[0]);
+ break;
+
+ case TYPE_INT_4:
+ params[3] = ((GLint *) p)[3];
+ case TYPE_INT_3:
+ params[2] = ((GLint *) p)[2];
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = ((GLint *) p)[1];
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = ((GLint *) p)[0];
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = v.value_int_n.ints[i];
+ break;
+
+ case TYPE_INT64:
+ params[0] = INT64_TO_INT(((GLint64 *) p)[0]);
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = BOOLEAN_TO_INT(*(GLboolean*) p);
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_INT(m->m[i]);
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_INT(m->m[transpose[i]]);
+ break;
+
+ case TYPE_BIT_0:
+ case TYPE_BIT_1:
+ case TYPE_BIT_2:
+ case TYPE_BIT_3:
+ case TYPE_BIT_4:
+ case TYPE_BIT_5:
+ shift = d->type - TYPE_BIT_0;
+ params[0] = (*(GLbitfield *) p >> shift) & 1;
+ break;
+ }
+}
+
+#if FEATURE_ARB_sync
+void GLAPIENTRY
+_mesa_GetInteger64v(GLenum pname, GLint64 *params)
+{
+ const struct value_desc *d;
+ union value v;
+ GLmatrix *m;
+ int shift, i;
+ void *p;
+
+ d = find_value("glGetInteger64v", pname, &p, &v);
+ switch (d->type) {
+ case TYPE_INVALID:
+ break;
+ case TYPE_CONST:
+ params[0] = d->offset;
+ break;
+
+ case TYPE_FLOAT_4:
+ params[3] = IROUND64(((GLfloat *) p)[3]);
+ case TYPE_FLOAT_3:
+ params[2] = IROUND64(((GLfloat *) p)[2]);
+ case TYPE_FLOAT_2:
+ params[1] = IROUND64(((GLfloat *) p)[1]);
+ case TYPE_FLOAT:
+ params[0] = IROUND64(((GLfloat *) p)[0]);
+ break;
+
+ case TYPE_FLOATN_4:
+ params[3] = FLOAT_TO_INT64(((GLfloat *) p)[3]);
+ case TYPE_FLOATN_3:
+ params[2] = FLOAT_TO_INT64(((GLfloat *) p)[2]);
+ case TYPE_FLOATN_2:
+ params[1] = FLOAT_TO_INT64(((GLfloat *) p)[1]);
+ case TYPE_FLOATN:
+ params[0] = FLOAT_TO_INT64(((GLfloat *) p)[0]);
+ break;
+
+ case TYPE_DOUBLEN:
+ params[0] = FLOAT_TO_INT64(((GLdouble *) p)[0]);
+ break;
+
+ case TYPE_INT_4:
+ params[3] = ((GLint *) p)[3];
+ case TYPE_INT_3:
+ params[2] = ((GLint *) p)[2];
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = ((GLint *) p)[1];
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = ((GLint *) p)[0];
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = INT_TO_BOOLEAN(v.value_int_n.ints[i]);
+ break;
+
+ case TYPE_INT64:
+ params[0] = ((GLint64 *) p)[0];
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = ((GLboolean*) p)[0];
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_INT64(m->m[i]);
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_INT64(m->m[transpose[i]]);
+ break;
+
+ case TYPE_BIT_0:
+ case TYPE_BIT_1:
+ case TYPE_BIT_2:
+ case TYPE_BIT_3:
+ case TYPE_BIT_4:
+ case TYPE_BIT_5:
+ shift = d->type - TYPE_BIT_0;
+ params[0] = (*(GLbitfield *) p >> shift) & 1;
+ break;
+ }
+}
+#endif /* FEATURE_ARB_sync */
+
+void GLAPIENTRY
+_mesa_GetDoublev(GLenum pname, GLdouble *params)
+{
+ const struct value_desc *d;
+ union value v;
+ GLmatrix *m;
+ int shift, i;
+ void *p;
+
+ d = find_value("glGetDoublev", pname, &p, &v);
+ switch (d->type) {
+ case TYPE_INVALID:
+ break;
+ case TYPE_CONST:
+ params[0] = d->offset;
+ break;
+
+ case TYPE_FLOAT_4:
+ case TYPE_FLOATN_4:
+ params[3] = ((GLfloat *) p)[3];
+ case TYPE_FLOAT_3:
+ case TYPE_FLOATN_3:
+ params[2] = ((GLfloat *) p)[2];
+ case TYPE_FLOAT_2:
+ case TYPE_FLOATN_2:
+ params[1] = ((GLfloat *) p)[1];
+ case TYPE_FLOAT:
+ case TYPE_FLOATN:
+ params[0] = ((GLfloat *) p)[0];
+ break;
+
+ case TYPE_DOUBLEN:
+ params[0] = ((GLdouble *) p)[0];
+ break;
+
+ case TYPE_INT_4:
+ params[3] = ((GLint *) p)[3];
+ case TYPE_INT_3:
+ params[2] = ((GLint *) p)[2];
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = ((GLint *) p)[1];
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = ((GLint *) p)[0];
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = v.value_int_n.ints[i];
+ break;
+
+ case TYPE_INT64:
+ params[0] = ((GLint64 *) p)[0];
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = *(GLboolean*) p;
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = m->m[i];
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = m->m[transpose[i]];
+ break;
+
+ case TYPE_BIT_0:
+ case TYPE_BIT_1:
+ case TYPE_BIT_2:
+ case TYPE_BIT_3:
+ case TYPE_BIT_4:
+ case TYPE_BIT_5:
+ shift = d->type - TYPE_BIT_0;
+ params[0] = (*(GLbitfield *) p >> shift) & 1;
+ break;
+ }
+}
+
+static enum value_type
+find_value_indexed(const char *func, GLenum pname, int index, union value *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ switch (pname) {
+
+ case GL_BLEND:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.EXT_draw_buffers2)
+ goto invalid_enum;
+ v->value_int = (ctx->Color.BlendEnabled >> index) & 1;
+ return TYPE_INT;
+
+ case GL_BLEND_SRC:
+ /* fall-through */
+ case GL_BLEND_SRC_RGB:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.ARB_draw_buffers_blend)
+ goto invalid_enum;
+ v->value_int = ctx->Color.Blend[index].SrcRGB;
+ return TYPE_INT;
+ case GL_BLEND_SRC_ALPHA:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.ARB_draw_buffers_blend)
+ goto invalid_enum;
+ v->value_int = ctx->Color.Blend[index].SrcA;
+ return TYPE_INT;
+ case GL_BLEND_DST:
+ /* fall-through */
+ case GL_BLEND_DST_RGB:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.ARB_draw_buffers_blend)
+ goto invalid_enum;
+ v->value_int = ctx->Color.Blend[index].DstRGB;
+ return TYPE_INT;
+ case GL_BLEND_DST_ALPHA:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.ARB_draw_buffers_blend)
+ goto invalid_enum;
+ v->value_int = ctx->Color.Blend[index].DstA;
+ return TYPE_INT;
+ case GL_BLEND_EQUATION_RGB:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.ARB_draw_buffers_blend)
+ goto invalid_enum;
+ v->value_int = ctx->Color.Blend[index].EquationRGB;
+ return TYPE_INT;
+ case GL_BLEND_EQUATION_ALPHA:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.ARB_draw_buffers_blend)
+ goto invalid_enum;
+ v->value_int = ctx->Color.Blend[index].EquationA;
+ return TYPE_INT;
+
+ case GL_COLOR_WRITEMASK:
+ if (index >= ctx->Const.MaxDrawBuffers)
+ goto invalid_value;
+ if (!ctx->Extensions.EXT_draw_buffers2)
+ goto invalid_enum;
+ v->value_int_4[0] = ctx->Color.ColorMask[index][RCOMP] ? 1 : 0;
+ v->value_int_4[1] = ctx->Color.ColorMask[index][GCOMP] ? 1 : 0;
+ v->value_int_4[2] = ctx->Color.ColorMask[index][BCOMP] ? 1 : 0;
+ v->value_int_4[3] = ctx->Color.ColorMask[index][ACOMP] ? 1 : 0;
+ return TYPE_INT_4;
+
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs)
+ goto invalid_value;
+ if (!ctx->Extensions.EXT_transform_feedback)
+ goto invalid_enum;
+ v->value_int64 = ctx->TransformFeedback.CurrentObject->Offset[index];
+ return TYPE_INT64;
+
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs)
+ goto invalid_value;
+ if (!ctx->Extensions.EXT_transform_feedback)
+ goto invalid_enum;
+ v->value_int64 = ctx->TransformFeedback.CurrentObject->Size[index];
+ return TYPE_INT64;
+
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs)
+ goto invalid_value;
+ if (!ctx->Extensions.EXT_transform_feedback)
+ goto invalid_enum;
+ v->value_int = ctx->TransformFeedback.CurrentObject->Buffers[index]->Name;
+ return TYPE_INT;
+ }
+
+ invalid_enum:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
+ return TYPE_INVALID;
+ invalid_value:
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
+ return TYPE_INVALID;
+}
+
+void GLAPIENTRY
+_mesa_GetBooleanIndexedv( GLenum pname, GLuint index, GLboolean *params )
+{
+ union value v;
+ enum value_type type =
+ find_value_indexed("glGetBooleanIndexedv", pname, index, &v);
+
+ switch (type) {
+ case TYPE_INT:
+ params[0] = INT_TO_BOOLEAN(v.value_int);
+ break;
+ case TYPE_INT_4:
+ params[0] = INT_TO_BOOLEAN(v.value_int_4[0]);
+ params[1] = INT_TO_BOOLEAN(v.value_int_4[1]);
+ params[2] = INT_TO_BOOLEAN(v.value_int_4[2]);
+ params[3] = INT_TO_BOOLEAN(v.value_int_4[3]);
+ break;
+ case TYPE_INT64:
+ params[0] = INT64_TO_BOOLEAN(v.value_int);
+ break;
+ default:
+ ; /* nothing - GL error was recorded */
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetIntegerIndexedv( GLenum pname, GLuint index, GLint *params )
+{
+ union value v;
+ enum value_type type =
+ find_value_indexed("glGetIntegerIndexedv", pname, index, &v);
+
+ switch (type) {
+ case TYPE_INT:
+ params[0] = v.value_int;
+ break;
+ case TYPE_INT_4:
+ params[0] = v.value_int_4[0];
+ params[1] = v.value_int_4[1];
+ params[2] = v.value_int_4[2];
+ params[3] = v.value_int_4[3];
+ break;
+ case TYPE_INT64:
+ params[0] = INT64_TO_INT(v.value_int);
+ break;
+ default:
+ ; /* nothing - GL error was recorded */
+ }
+}
+
+#if FEATURE_ARB_sync
+void GLAPIENTRY
+_mesa_GetInteger64Indexedv( GLenum pname, GLuint index, GLint64 *params )
+{
+ union value v;
+ enum value_type type =
+ find_value_indexed("glGetIntegerIndexedv", pname, index, &v);
+
+ switch (type) {
+ case TYPE_INT:
+ params[0] = v.value_int;
+ break;
+ case TYPE_INT_4:
+ params[0] = v.value_int_4[0];
+ params[1] = v.value_int_4[1];
+ params[2] = v.value_int_4[2];
+ params[3] = v.value_int_4[3];
+ break;
+ case TYPE_INT64:
+ params[0] = v.value_int;
+ break;
+ default:
+ ; /* nothing - GL error was recorded */
+ }
+}
+#endif /* FEATURE_ARB_sync */
+
+#if FEATURE_ES1
+void GLAPIENTRY
+_mesa_GetFixedv(GLenum pname, GLfixed *params)
+{
+ const struct value_desc *d;
+ union value v;
+ GLmatrix *m;
+ int shift, i;
+ void *p;
+
+ d = find_value("glGetDoublev", pname, &p, &v);
+ switch (d->type) {
+ case TYPE_INVALID:
+ break;
+ case TYPE_CONST:
+ params[0] = INT_TO_FIXED(d->offset);
+ break;
+
+ case TYPE_FLOAT_4:
+ case TYPE_FLOATN_4:
+ params[3] = FLOAT_TO_FIXED(((GLfloat *) p)[3]);
+ case TYPE_FLOAT_3:
+ case TYPE_FLOATN_3:
+ params[2] = FLOAT_TO_FIXED(((GLfloat *) p)[2]);
+ case TYPE_FLOAT_2:
+ case TYPE_FLOATN_2:
+ params[1] = FLOAT_TO_FIXED(((GLfloat *) p)[1]);
+ case TYPE_FLOAT:
+ case TYPE_FLOATN:
+ params[0] = FLOAT_TO_FIXED(((GLfloat *) p)[0]);
+ break;
+
+ case TYPE_DOUBLEN:
+ params[0] = FLOAT_TO_FIXED(((GLdouble *) p)[0]);
+ break;
+
+ case TYPE_INT_4:
+ params[3] = INT_TO_FIXED(((GLint *) p)[3]);
+ case TYPE_INT_3:
+ params[2] = INT_TO_FIXED(((GLint *) p)[2]);
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = INT_TO_FIXED(((GLint *) p)[1]);
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = INT_TO_FIXED(((GLint *) p)[0]);
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = INT_TO_FIXED(v.value_int_n.ints[i]);
+ break;
+
+ case TYPE_INT64:
+ params[0] = ((GLint64 *) p)[0];
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = BOOLEAN_TO_FIXED(((GLboolean*) p)[0]);
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_FIXED(m->m[i]);
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) p;
+ for (i = 0; i < 16; i++)
+ params[i] = FLOAT_TO_FIXED(m->m[transpose[i]]);
+ break;
+
+ case TYPE_BIT_0:
+ case TYPE_BIT_1:
+ case TYPE_BIT_2:
+ case TYPE_BIT_3:
+ case TYPE_BIT_4:
+ case TYPE_BIT_5:
+ shift = d->type - TYPE_BIT_0;
+ params[0] = BOOLEAN_TO_FIXED((*(GLbitfield *) p >> shift) & 1);
+ break;
+ }
+}
+#endif
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index d2888fa80..fcb06d49e 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -1,3367 +1,3355 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.7
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009 VMware, Inc. 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 mtypes.h
- * Main Mesa data structures.
- *
- * Please try to mark derived values with a leading underscore ('_').
- */
-
-#ifndef MTYPES_H
-#define MTYPES_H
-
-
-#include "main/glheader.h"
-#include "main/config.h"
-#include "main/mfeatures.h"
-#include "glapi/glapi.h"
-#include "math/m_matrix.h" /* GLmatrix */
-#include "main/simple_list.h" /* struct simple_node */
-#include "main/formats.h" /* MESA_FORMAT_COUNT */
-
-
-/**
- * Color channel data type.
- */
-#if CHAN_BITS == 8
- typedef GLubyte GLchan;
-#define CHAN_MAX 255
-#define CHAN_MAXF 255.0F
-#define CHAN_TYPE GL_UNSIGNED_BYTE
-#elif CHAN_BITS == 16
- typedef GLushort GLchan;
-#define CHAN_MAX 65535
-#define CHAN_MAXF 65535.0F
-#define CHAN_TYPE GL_UNSIGNED_SHORT
-#elif CHAN_BITS == 32
- typedef GLfloat GLchan;
-#define CHAN_MAX 1.0
-#define CHAN_MAXF 1.0F
-#define CHAN_TYPE GL_FLOAT
-#else
-#error "illegal number of color channel bits"
-#endif
-
-
-/**
- * Stencil buffer data type.
- */
-#if STENCIL_BITS==8
- typedef GLubyte GLstencil;
-#elif STENCIL_BITS==16
- typedef GLushort GLstencil;
-#else
-# error "illegal number of stencil bits"
-#endif
-
-
-/**
- * \name 64-bit extension of GLbitfield.
- */
-/*@{*/
-typedef GLuint64 GLbitfield64;
-
-/** Set a single bit */
-#define BITFIELD64_BIT(b) (1ULL << (b))
-
-
-/**
- * \name Some forward type declarations
- */
-/*@{*/
-struct _mesa_HashTable;
-struct gl_attrib_node;
-struct gl_list_extensions;
-struct gl_meta_state;
-struct gl_pixelstore_attrib;
-struct gl_program_cache;
-struct gl_texture_format;
-struct gl_texture_image;
-struct gl_texture_object;
-struct gl_context;
-struct st_context;
-/*@}*/
-
-
-/** Extra draw modes beyond GL_POINTS, GL_TRIANGLE_FAN, etc */
-#define PRIM_OUTSIDE_BEGIN_END (GL_POLYGON+1)
-#define PRIM_INSIDE_UNKNOWN_PRIM (GL_POLYGON+2)
-#define PRIM_UNKNOWN (GL_POLYGON+3)
-
-
-/**
- * Shader stages. Note that these will become 5 with tessellation.
- * These MUST have the same values as gallium's PIPE_SHADER_*
- */
-typedef enum
-{
- MESA_SHADER_VERTEX = 0,
- MESA_SHADER_FRAGMENT = 1,
- MESA_SHADER_GEOMETRY = 2,
- MESA_SHADER_TYPES = 3
-} gl_shader_type;
-
-
-
-/**
- * Indexes for vertex program attributes.
- * GL_NV_vertex_program aliases generic attributes over the conventional
- * attributes. In GL_ARB_vertex_program shader the aliasing is optional.
- * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
- * generic attributes are distinct/separate).
- */
-typedef enum
-{
- VERT_ATTRIB_POS = 0,
- VERT_ATTRIB_WEIGHT = 1,
- VERT_ATTRIB_NORMAL = 2,
- VERT_ATTRIB_COLOR0 = 3,
- VERT_ATTRIB_COLOR1 = 4,
- VERT_ATTRIB_FOG = 5,
- VERT_ATTRIB_COLOR_INDEX = 6,
- VERT_ATTRIB_POINT_SIZE = 6, /*alias*/
- VERT_ATTRIB_EDGEFLAG = 7,
- VERT_ATTRIB_TEX0 = 8,
- VERT_ATTRIB_TEX1 = 9,
- VERT_ATTRIB_TEX2 = 10,
- VERT_ATTRIB_TEX3 = 11,
- VERT_ATTRIB_TEX4 = 12,
- VERT_ATTRIB_TEX5 = 13,
- VERT_ATTRIB_TEX6 = 14,
- VERT_ATTRIB_TEX7 = 15,
- VERT_ATTRIB_GENERIC0 = 16,
- VERT_ATTRIB_GENERIC1 = 17,
- VERT_ATTRIB_GENERIC2 = 18,
- VERT_ATTRIB_GENERIC3 = 19,
- VERT_ATTRIB_GENERIC4 = 20,
- VERT_ATTRIB_GENERIC5 = 21,
- VERT_ATTRIB_GENERIC6 = 22,
- VERT_ATTRIB_GENERIC7 = 23,
- VERT_ATTRIB_GENERIC8 = 24,
- VERT_ATTRIB_GENERIC9 = 25,
- VERT_ATTRIB_GENERIC10 = 26,
- VERT_ATTRIB_GENERIC11 = 27,
- VERT_ATTRIB_GENERIC12 = 28,
- VERT_ATTRIB_GENERIC13 = 29,
- VERT_ATTRIB_GENERIC14 = 30,
- VERT_ATTRIB_GENERIC15 = 31,
- VERT_ATTRIB_MAX = 32
-} gl_vert_attrib;
-
-/**
- * Bitflags for vertex attributes.
- * These are used in bitfields in many places.
- */
-/*@{*/
-#define VERT_BIT_POS (1 << VERT_ATTRIB_POS)
-#define VERT_BIT_WEIGHT (1 << VERT_ATTRIB_WEIGHT)
-#define VERT_BIT_NORMAL (1 << VERT_ATTRIB_NORMAL)
-#define VERT_BIT_COLOR0 (1 << VERT_ATTRIB_COLOR0)
-#define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1)
-#define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG)
-#define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX)
-#define VERT_BIT_EDGEFLAG (1 << VERT_ATTRIB_EDGEFLAG)
-#define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0)
-#define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1)
-#define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2)
-#define VERT_BIT_TEX3 (1 << VERT_ATTRIB_TEX3)
-#define VERT_BIT_TEX4 (1 << VERT_ATTRIB_TEX4)
-#define VERT_BIT_TEX5 (1 << VERT_ATTRIB_TEX5)
-#define VERT_BIT_TEX6 (1 << VERT_ATTRIB_TEX6)
-#define VERT_BIT_TEX7 (1 << VERT_ATTRIB_TEX7)
-#define VERT_BIT_GENERIC0 (1 << VERT_ATTRIB_GENERIC0)
-#define VERT_BIT_GENERIC1 (1 << VERT_ATTRIB_GENERIC1)
-#define VERT_BIT_GENERIC2 (1 << VERT_ATTRIB_GENERIC2)
-#define VERT_BIT_GENERIC3 (1 << VERT_ATTRIB_GENERIC3)
-#define VERT_BIT_GENERIC4 (1 << VERT_ATTRIB_GENERIC4)
-#define VERT_BIT_GENERIC5 (1 << VERT_ATTRIB_GENERIC5)
-#define VERT_BIT_GENERIC6 (1 << VERT_ATTRIB_GENERIC6)
-#define VERT_BIT_GENERIC7 (1 << VERT_ATTRIB_GENERIC7)
-#define VERT_BIT_GENERIC8 (1 << VERT_ATTRIB_GENERIC8)
-#define VERT_BIT_GENERIC9 (1 << VERT_ATTRIB_GENERIC9)
-#define VERT_BIT_GENERIC10 (1 << VERT_ATTRIB_GENERIC10)
-#define VERT_BIT_GENERIC11 (1 << VERT_ATTRIB_GENERIC11)
-#define VERT_BIT_GENERIC12 (1 << VERT_ATTRIB_GENERIC12)
-#define VERT_BIT_GENERIC13 (1 << VERT_ATTRIB_GENERIC13)
-#define VERT_BIT_GENERIC14 (1 << VERT_ATTRIB_GENERIC14)
-#define VERT_BIT_GENERIC15 (1 << VERT_ATTRIB_GENERIC15)
-
-#define VERT_BIT_TEX(u) (1 << (VERT_ATTRIB_TEX0 + (u)))
-#define VERT_BIT_GENERIC(g) (1 << (VERT_ATTRIB_GENERIC0 + (g)))
-/*@}*/
-
-
-/**
- * Indexes for vertex program result attributes
- */
-typedef enum
-{
- VERT_RESULT_HPOS = 0,
- VERT_RESULT_COL0 = 1,
- VERT_RESULT_COL1 = 2,
- VERT_RESULT_FOGC = 3,
- VERT_RESULT_TEX0 = 4,
- VERT_RESULT_TEX1 = 5,
- VERT_RESULT_TEX2 = 6,
- VERT_RESULT_TEX3 = 7,
- VERT_RESULT_TEX4 = 8,
- VERT_RESULT_TEX5 = 9,
- VERT_RESULT_TEX6 = 10,
- VERT_RESULT_TEX7 = 11,
- VERT_RESULT_PSIZ = 12,
- VERT_RESULT_BFC0 = 13,
- VERT_RESULT_BFC1 = 14,
- VERT_RESULT_EDGE = 15,
- VERT_RESULT_VAR0 = 16, /**< shader varying */
- VERT_RESULT_MAX = (VERT_RESULT_VAR0 + MAX_VARYING)
-} gl_vert_result;
-
-
-/*********************************************/
-
-/**
- * Indexes for geometry program attributes.
- */
-typedef enum
-{
- GEOM_ATTRIB_POSITION = 0,
- GEOM_ATTRIB_COLOR0 = 1,
- GEOM_ATTRIB_COLOR1 = 2,
- GEOM_ATTRIB_SECONDARY_COLOR0 = 3,
- GEOM_ATTRIB_SECONDARY_COLOR1 = 4,
- GEOM_ATTRIB_FOG_FRAG_COORD = 5,
- GEOM_ATTRIB_POINT_SIZE = 6,
- GEOM_ATTRIB_CLIP_VERTEX = 7,
- GEOM_ATTRIB_PRIMITIVE_ID = 8,
- GEOM_ATTRIB_TEX_COORD = 9,
-
- GEOM_ATTRIB_VAR0 = 16,
- GEOM_ATTRIB_MAX = (GEOM_ATTRIB_VAR0 + MAX_VARYING)
-} gl_geom_attrib;
-
-/**
- * Bitflags for geometry attributes.
- * These are used in bitfields in many places.
- */
-/*@{*/
-#define GEOM_BIT_COLOR0 (1 << GEOM_ATTRIB_COLOR0)
-#define GEOM_BIT_COLOR1 (1 << GEOM_ATTRIB_COLOR1)
-#define GEOM_BIT_SCOLOR0 (1 << GEOM_ATTRIB_SECONDARY_COLOR0)
-#define GEOM_BIT_SCOLOR1 (1 << GEOM_ATTRIB_SECONDARY_COLOR1)
-#define GEOM_BIT_TEX_COORD (1 << GEOM_ATTRIB_TEX_COORD)
-#define GEOM_BIT_FOG_COORD (1 << GEOM_ATTRIB_FOG_FRAG_COORD)
-#define GEOM_BIT_POSITION (1 << GEOM_ATTRIB_POSITION)
-#define GEOM_BIT_POINT_SIDE (1 << GEOM_ATTRIB_POINT_SIZE)
-#define GEOM_BIT_CLIP_VERTEX (1 << GEOM_ATTRIB_CLIP_VERTEX)
-#define GEOM_BIT_PRIM_ID (1 << GEOM_ATTRIB_PRIMITIVE_ID)
-#define GEOM_BIT_VAR0 (1 << GEOM_ATTRIB_VAR0)
-
-#define GEOM_BIT_VAR(g) (1 << (GEOM_BIT_VAR0 + (g)))
-/*@}*/
-
-
-/**
- * Indexes for geometry program result attributes
- */
-typedef enum
-{
- GEOM_RESULT_POS = 0,
- GEOM_RESULT_COL0 = 1,
- GEOM_RESULT_COL1 = 2,
- GEOM_RESULT_SCOL0 = 3,
- GEOM_RESULT_SCOL1 = 4,
- GEOM_RESULT_FOGC = 5,
- GEOM_RESULT_TEX0 = 6,
- GEOM_RESULT_TEX1 = 7,
- GEOM_RESULT_TEX2 = 8,
- GEOM_RESULT_TEX3 = 9,
- GEOM_RESULT_TEX4 = 10,
- GEOM_RESULT_TEX5 = 11,
- GEOM_RESULT_TEX6 = 12,
- GEOM_RESULT_TEX7 = 13,
- GEOM_RESULT_PSIZ = 14,
- GEOM_RESULT_CLPV = 15,
- GEOM_RESULT_PRID = 16,
- GEOM_RESULT_LAYR = 17,
- GEOM_RESULT_VAR0 = 18, /**< shader varying, should really be 16 */
- /* ### we need to -2 because var0 is 18 instead 16 like in the others */
- GEOM_RESULT_MAX = (GEOM_RESULT_VAR0 + MAX_VARYING - 2)
-} gl_geom_result;
-
-
-/**
- * Indexes for fragment program input attributes.
- */
-typedef enum
-{
- FRAG_ATTRIB_WPOS = 0,
- FRAG_ATTRIB_COL0 = 1,
- FRAG_ATTRIB_COL1 = 2,
- FRAG_ATTRIB_FOGC = 3,
- FRAG_ATTRIB_TEX0 = 4,
- FRAG_ATTRIB_TEX1 = 5,
- FRAG_ATTRIB_TEX2 = 6,
- FRAG_ATTRIB_TEX3 = 7,
- FRAG_ATTRIB_TEX4 = 8,
- FRAG_ATTRIB_TEX5 = 9,
- FRAG_ATTRIB_TEX6 = 10,
- FRAG_ATTRIB_TEX7 = 11,
- FRAG_ATTRIB_FACE = 12, /**< front/back face */
- FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */
- FRAG_ATTRIB_VAR0 = 14, /**< shader varying */
- FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
-} gl_frag_attrib;
-
-/**
- * Bitflags for fragment program input attributes.
- */
-/*@{*/
-#define FRAG_BIT_WPOS (1 << FRAG_ATTRIB_WPOS)
-#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0)
-#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1)
-#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC)
-#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE)
-#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC)
-#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0)
-#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1)
-#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2)
-#define FRAG_BIT_TEX3 (1 << FRAG_ATTRIB_TEX3)
-#define FRAG_BIT_TEX4 (1 << FRAG_ATTRIB_TEX4)
-#define FRAG_BIT_TEX5 (1 << FRAG_ATTRIB_TEX5)
-#define FRAG_BIT_TEX6 (1 << FRAG_ATTRIB_TEX6)
-#define FRAG_BIT_TEX7 (1 << FRAG_ATTRIB_TEX7)
-#define FRAG_BIT_VAR0 (1 << FRAG_ATTRIB_VAR0)
-
-#define FRAG_BIT_TEX(U) (FRAG_BIT_TEX0 << (U))
-#define FRAG_BIT_VAR(V) (FRAG_BIT_VAR0 << (V))
-
-#define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0| \
- FRAG_BIT_TEX1| \
- FRAG_BIT_TEX2| \
- FRAG_BIT_TEX3| \
- FRAG_BIT_TEX4| \
- FRAG_BIT_TEX5| \
- FRAG_BIT_TEX6| \
- FRAG_BIT_TEX7)
-/*@}*/
-
-
-/**
- * Fragment program results
- */
-typedef enum
-{
- FRAG_RESULT_DEPTH = 0,
- FRAG_RESULT_STENCIL = 1,
- FRAG_RESULT_COLOR = 2,
- FRAG_RESULT_DATA0 = 3,
- FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
-} gl_frag_result;
-
-
-/**
- * Indexes for all renderbuffers
- */
-typedef enum
-{
- /* the four standard color buffers */
- BUFFER_FRONT_LEFT,
- BUFFER_BACK_LEFT,
- BUFFER_FRONT_RIGHT,
- BUFFER_BACK_RIGHT,
- BUFFER_DEPTH,
- BUFFER_STENCIL,
- BUFFER_ACCUM,
- /* optional aux buffer */
- BUFFER_AUX0,
- /* generic renderbuffers */
- BUFFER_COLOR0,
- BUFFER_COLOR1,
- BUFFER_COLOR2,
- BUFFER_COLOR3,
- BUFFER_COLOR4,
- BUFFER_COLOR5,
- BUFFER_COLOR6,
- BUFFER_COLOR7,
- BUFFER_COUNT
-} gl_buffer_index;
-
-/**
- * Bit flags for all renderbuffers
- */
-#define BUFFER_BIT_FRONT_LEFT (1 << BUFFER_FRONT_LEFT)
-#define BUFFER_BIT_BACK_LEFT (1 << BUFFER_BACK_LEFT)
-#define BUFFER_BIT_FRONT_RIGHT (1 << BUFFER_FRONT_RIGHT)
-#define BUFFER_BIT_BACK_RIGHT (1 << BUFFER_BACK_RIGHT)
-#define BUFFER_BIT_AUX0 (1 << BUFFER_AUX0)
-#define BUFFER_BIT_AUX1 (1 << BUFFER_AUX1)
-#define BUFFER_BIT_AUX2 (1 << BUFFER_AUX2)
-#define BUFFER_BIT_AUX3 (1 << BUFFER_AUX3)
-#define BUFFER_BIT_DEPTH (1 << BUFFER_DEPTH)
-#define BUFFER_BIT_STENCIL (1 << BUFFER_STENCIL)
-#define BUFFER_BIT_ACCUM (1 << BUFFER_ACCUM)
-#define BUFFER_BIT_COLOR0 (1 << BUFFER_COLOR0)
-#define BUFFER_BIT_COLOR1 (1 << BUFFER_COLOR1)
-#define BUFFER_BIT_COLOR2 (1 << BUFFER_COLOR2)
-#define BUFFER_BIT_COLOR3 (1 << BUFFER_COLOR3)
-#define BUFFER_BIT_COLOR4 (1 << BUFFER_COLOR4)
-#define BUFFER_BIT_COLOR5 (1 << BUFFER_COLOR5)
-#define BUFFER_BIT_COLOR6 (1 << BUFFER_COLOR6)
-#define BUFFER_BIT_COLOR7 (1 << BUFFER_COLOR7)
-
-/**
- * Mask of all the color buffer bits (but not accum).
- */
-#define BUFFER_BITS_COLOR (BUFFER_BIT_FRONT_LEFT | \
- BUFFER_BIT_BACK_LEFT | \
- BUFFER_BIT_FRONT_RIGHT | \
- BUFFER_BIT_BACK_RIGHT | \
- BUFFER_BIT_AUX0 | \
- BUFFER_BIT_COLOR0 | \
- BUFFER_BIT_COLOR1 | \
- BUFFER_BIT_COLOR2 | \
- BUFFER_BIT_COLOR3 | \
- BUFFER_BIT_COLOR4 | \
- BUFFER_BIT_COLOR5 | \
- BUFFER_BIT_COLOR6 | \
- BUFFER_BIT_COLOR7)
-
-
-/**
- * Framebuffer configuration (aka visual / pixelformat)
- * Note: some of these fields should be boolean, but it appears that
- * code in drivers/dri/common/util.c requires int-sized fields.
- */
-struct gl_config
-{
- GLboolean rgbMode;
- GLboolean floatMode;
- GLboolean colorIndexMode; /* XXX is this used anywhere? */
- GLuint doubleBufferMode;
- GLuint stereoMode;
-
- GLboolean haveAccumBuffer;
- GLboolean haveDepthBuffer;
- GLboolean haveStencilBuffer;
-
- GLint redBits, greenBits, blueBits, alphaBits; /* bits per comp */
- GLuint redMask, greenMask, blueMask, alphaMask;
- GLint rgbBits; /* total bits for rgb */
- GLint indexBits; /* total bits for colorindex */
-
- GLint accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits;
- GLint depthBits;
- GLint stencilBits;
-
- GLint numAuxBuffers;
-
- GLint level;
-
- /* EXT_visual_rating / GLX 1.2 */
- GLint visualRating;
-
- /* EXT_visual_info / GLX 1.2 */
- GLint transparentPixel;
- /* colors are floats scaled to ints */
- GLint transparentRed, transparentGreen, transparentBlue, transparentAlpha;
- GLint transparentIndex;
-
- /* ARB_multisample / SGIS_multisample */
- GLint sampleBuffers;
- GLint samples;
-
- /* SGIX_pbuffer / GLX 1.3 */
- GLint maxPbufferWidth;
- GLint maxPbufferHeight;
- GLint maxPbufferPixels;
- GLint optimalPbufferWidth; /* Only for SGIX_pbuffer. */
- GLint optimalPbufferHeight; /* Only for SGIX_pbuffer. */
-
- /* OML_swap_method */
- GLint swapMethod;
-
- /* EXT_texture_from_pixmap */
- GLint bindToTextureRgb;
- GLint bindToTextureRgba;
- GLint bindToMipmapTexture;
- GLint bindToTextureTargets;
- GLint yInverted;
-
- /* EXT_framebuffer_sRGB */
- GLint sRGBCapable;
-};
-
-
-/**
- * Data structure for color tables
- */
-struct gl_color_table
-{
- GLenum InternalFormat; /**< The user-specified format */
- GLenum _BaseFormat; /**< GL_ALPHA, GL_RGBA, GL_RGB, etc */
- GLuint Size; /**< number of entries in table */
- GLfloat *TableF; /**< Color table, floating point values */
- GLubyte *TableUB; /**< Color table, ubyte values */
- GLubyte RedSize;
- GLubyte GreenSize;
- GLubyte BlueSize;
- GLubyte AlphaSize;
- GLubyte LuminanceSize;
- GLubyte IntensitySize;
-};
-
-
-/**
- * \name Bit flags used for updating material values.
- */
-/*@{*/
-#define MAT_ATTRIB_FRONT_AMBIENT 0
-#define MAT_ATTRIB_BACK_AMBIENT 1
-#define MAT_ATTRIB_FRONT_DIFFUSE 2
-#define MAT_ATTRIB_BACK_DIFFUSE 3
-#define MAT_ATTRIB_FRONT_SPECULAR 4
-#define MAT_ATTRIB_BACK_SPECULAR 5
-#define MAT_ATTRIB_FRONT_EMISSION 6
-#define MAT_ATTRIB_BACK_EMISSION 7
-#define MAT_ATTRIB_FRONT_SHININESS 8
-#define MAT_ATTRIB_BACK_SHININESS 9
-#define MAT_ATTRIB_FRONT_INDEXES 10
-#define MAT_ATTRIB_BACK_INDEXES 11
-#define MAT_ATTRIB_MAX 12
-
-#define MAT_ATTRIB_AMBIENT(f) (MAT_ATTRIB_FRONT_AMBIENT+(f))
-#define MAT_ATTRIB_DIFFUSE(f) (MAT_ATTRIB_FRONT_DIFFUSE+(f))
-#define MAT_ATTRIB_SPECULAR(f) (MAT_ATTRIB_FRONT_SPECULAR+(f))
-#define MAT_ATTRIB_EMISSION(f) (MAT_ATTRIB_FRONT_EMISSION+(f))
-#define MAT_ATTRIB_SHININESS(f)(MAT_ATTRIB_FRONT_SHININESS+(f))
-#define MAT_ATTRIB_INDEXES(f) (MAT_ATTRIB_FRONT_INDEXES+(f))
-
-#define MAT_INDEX_AMBIENT 0
-#define MAT_INDEX_DIFFUSE 1
-#define MAT_INDEX_SPECULAR 2
-
-#define MAT_BIT_FRONT_AMBIENT (1<<MAT_ATTRIB_FRONT_AMBIENT)
-#define MAT_BIT_BACK_AMBIENT (1<<MAT_ATTRIB_BACK_AMBIENT)
-#define MAT_BIT_FRONT_DIFFUSE (1<<MAT_ATTRIB_FRONT_DIFFUSE)
-#define MAT_BIT_BACK_DIFFUSE (1<<MAT_ATTRIB_BACK_DIFFUSE)
-#define MAT_BIT_FRONT_SPECULAR (1<<MAT_ATTRIB_FRONT_SPECULAR)
-#define MAT_BIT_BACK_SPECULAR (1<<MAT_ATTRIB_BACK_SPECULAR)
-#define MAT_BIT_FRONT_EMISSION (1<<MAT_ATTRIB_FRONT_EMISSION)
-#define MAT_BIT_BACK_EMISSION (1<<MAT_ATTRIB_BACK_EMISSION)
-#define MAT_BIT_FRONT_SHININESS (1<<MAT_ATTRIB_FRONT_SHININESS)
-#define MAT_BIT_BACK_SHININESS (1<<MAT_ATTRIB_BACK_SHININESS)
-#define MAT_BIT_FRONT_INDEXES (1<<MAT_ATTRIB_FRONT_INDEXES)
-#define MAT_BIT_BACK_INDEXES (1<<MAT_ATTRIB_BACK_INDEXES)
-
-
-#define FRONT_MATERIAL_BITS (MAT_BIT_FRONT_EMISSION | \
- MAT_BIT_FRONT_AMBIENT | \
- MAT_BIT_FRONT_DIFFUSE | \
- MAT_BIT_FRONT_SPECULAR | \
- MAT_BIT_FRONT_SHININESS | \
- MAT_BIT_FRONT_INDEXES)
-
-#define BACK_MATERIAL_BITS (MAT_BIT_BACK_EMISSION | \
- MAT_BIT_BACK_AMBIENT | \
- MAT_BIT_BACK_DIFFUSE | \
- MAT_BIT_BACK_SPECULAR | \
- MAT_BIT_BACK_SHININESS | \
- MAT_BIT_BACK_INDEXES)
-
-#define ALL_MATERIAL_BITS (FRONT_MATERIAL_BITS | BACK_MATERIAL_BITS)
-/*@}*/
-
-
-#define EXP_TABLE_SIZE 512 /**< Specular exponent lookup table sizes */
-#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
-
-/**
- * Material shininess lookup table.
- */
-struct gl_shine_tab
-{
- struct gl_shine_tab *next, *prev;
- GLfloat tab[SHINE_TABLE_SIZE+1];
- GLfloat shininess;
- GLuint refcount;
-};
-
-
-/**
- * Light source state.
- */
-struct gl_light
-{
- struct gl_light *next; /**< double linked list with sentinel */
- struct gl_light *prev;
-
- GLfloat Ambient[4]; /**< ambient color */
- GLfloat Diffuse[4]; /**< diffuse color */
- GLfloat Specular[4]; /**< specular color */
- GLfloat EyePosition[4]; /**< position in eye coordinates */
- GLfloat SpotDirection[4]; /**< spotlight direction in eye coordinates */
- GLfloat SpotExponent;
- GLfloat SpotCutoff; /**< in degrees */
- GLfloat _CosCutoffNeg; /**< = cos(SpotCutoff) */
- GLfloat _CosCutoff; /**< = MAX(0, cos(SpotCutoff)) */
- GLfloat ConstantAttenuation;
- GLfloat LinearAttenuation;
- GLfloat QuadraticAttenuation;
- GLboolean Enabled; /**< On/off flag */
-
- /**
- * \name Derived fields
- */
- /*@{*/
- GLbitfield _Flags; /**< State */
-
- GLfloat _Position[4]; /**< position in eye/obj coordinates */
- GLfloat _VP_inf_norm[3]; /**< Norm direction to infinite light */
- GLfloat _h_inf_norm[3]; /**< Norm( _VP_inf_norm + <0,0,1> ) */
- GLfloat _NormSpotDirection[4]; /**< normalized spotlight direction */
- GLfloat _VP_inf_spot_attenuation;
-
- GLfloat _SpotExpTable[EXP_TABLE_SIZE][2]; /**< to replace a pow() call */
- GLfloat _MatAmbient[2][3]; /**< material ambient * light ambient */
- GLfloat _MatDiffuse[2][3]; /**< material diffuse * light diffuse */
- GLfloat _MatSpecular[2][3]; /**< material spec * light specular */
- GLfloat _dli; /**< CI diffuse light intensity */
- GLfloat _sli; /**< CI specular light intensity */
- /*@}*/
-};
-
-
-/**
- * Light model state.
- */
-struct gl_lightmodel
-{
- GLfloat Ambient[4]; /**< ambient color */
- GLboolean LocalViewer; /**< Local (or infinite) view point? */
- GLboolean TwoSide; /**< Two (or one) sided lighting? */
- GLenum ColorControl; /**< either GL_SINGLE_COLOR
- * or GL_SEPARATE_SPECULAR_COLOR */
-};
-
-
-/**
- * Material state.
- */
-struct gl_material
-{
- GLfloat Attrib[MAT_ATTRIB_MAX][4];
-};
-
-
-/**
- * Accumulation buffer attribute group (GL_ACCUM_BUFFER_BIT)
- */
-struct gl_accum_attrib
-{
- GLfloat ClearColor[4]; /**< Accumulation buffer clear color */
-};
-
-
-/**
- * Color buffer attribute group (GL_COLOR_BUFFER_BIT).
- */
-struct gl_colorbuffer_attrib
-{
- GLuint ClearIndex; /**< Index to use for glClear */
- GLclampf ClearColor[4]; /**< Color to use for glClear */
-
- GLuint IndexMask; /**< Color index write mask */
- GLubyte ColorMask[MAX_DRAW_BUFFERS][4];/**< Each flag is 0xff or 0x0 */
-
- GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */
-
- /**
- * \name alpha testing
- */
- /*@{*/
- GLboolean AlphaEnabled; /**< Alpha test enabled flag */
- GLenum AlphaFunc; /**< Alpha test function */
- GLclampf AlphaRef; /**< Alpha reference value */
- /*@}*/
-
- /**
- * \name Blending
- */
- /*@{*/
- GLbitfield BlendEnabled; /**< Per-buffer blend enable flags */
- GLfloat BlendColor[4]; /**< Blending color */
- struct
- {
- GLenum SrcRGB; /**< RGB blend source term */
- GLenum DstRGB; /**< RGB blend dest term */
- GLenum SrcA; /**< Alpha blend source term */
- GLenum DstA; /**< Alpha blend dest term */
- GLenum EquationRGB; /**< GL_ADD, GL_SUBTRACT, etc. */
- GLenum EquationA; /**< GL_ADD, GL_SUBTRACT, etc. */
- } Blend[MAX_DRAW_BUFFERS];
- /** Are the blend func terms currently different for each buffer/target? */
- GLboolean _BlendFuncPerBuffer;
- /** Are the blend equations currently different for each buffer/target? */
- GLboolean _BlendEquationPerBuffer;
- /*@}*/
-
- /**
- * \name Logic op
- */
- /*@{*/
- GLenum LogicOp; /**< Logic operator */
- GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */
- GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */
- GLboolean _LogicOpEnabled; /**< RGBA logic op + EXT_blend_logic_op enabled flag */
- /*@}*/
-
- GLboolean DitherFlag; /**< Dither enable flag */
-
- GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
- GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
-
- GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */
-};
-
-
-/**
- * Current attribute group (GL_CURRENT_BIT).
- */
-struct gl_current_attrib
-{
- /**
- * \name Current vertex attributes.
- * \note Values are valid only after FLUSH_VERTICES has been called.
- * \note Index and Edgeflag current values are stored as floats in the
- * SIX and SEVEN attribute slots.
- */
- GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
-
- /**
- * \name Current raster position attributes (always valid).
- * \note This set of attributes is very similar to the SWvertex struct.
- */
- /*@{*/
- GLfloat RasterPos[4];
- GLfloat RasterDistance;
- GLfloat RasterColor[4];
- GLfloat RasterSecondaryColor[4];
- GLfloat RasterTexCoords[MAX_TEXTURE_COORD_UNITS][4];
- GLboolean RasterPosValid;
- /*@}*/
-};
-
-
-/**
- * Depth buffer attribute group (GL_DEPTH_BUFFER_BIT).
- */
-struct gl_depthbuffer_attrib
-{
- GLenum Func; /**< Function for depth buffer compare */
- GLclampd Clear; /**< Value to clear depth buffer to */
- GLboolean Test; /**< Depth buffering enabled flag */
- GLboolean Mask; /**< Depth buffer writable? */
- GLboolean BoundsTest; /**< GL_EXT_depth_bounds_test */
- GLfloat BoundsMin, BoundsMax;/**< GL_EXT_depth_bounds_test */
-};
-
-
-/**
- * Evaluator attribute group (GL_EVAL_BIT).
- */
-struct gl_eval_attrib
-{
- /**
- * \name Enable bits
- */
- /*@{*/
- GLboolean Map1Color4;
- GLboolean Map1Index;
- GLboolean Map1Normal;
- GLboolean Map1TextureCoord1;
- GLboolean Map1TextureCoord2;
- GLboolean Map1TextureCoord3;
- GLboolean Map1TextureCoord4;
- GLboolean Map1Vertex3;
- GLboolean Map1Vertex4;
- GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
- GLboolean Map2Color4;
- GLboolean Map2Index;
- GLboolean Map2Normal;
- GLboolean Map2TextureCoord1;
- GLboolean Map2TextureCoord2;
- GLboolean Map2TextureCoord3;
- GLboolean Map2TextureCoord4;
- GLboolean Map2Vertex3;
- GLboolean Map2Vertex4;
- GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
- GLboolean AutoNormal;
- /*@}*/
-
- /**
- * \name Map Grid endpoints and divisions and calculated du values
- */
- /*@{*/
- GLint MapGrid1un;
- GLfloat MapGrid1u1, MapGrid1u2, MapGrid1du;
- GLint MapGrid2un, MapGrid2vn;
- GLfloat MapGrid2u1, MapGrid2u2, MapGrid2du;
- GLfloat MapGrid2v1, MapGrid2v2, MapGrid2dv;
- /*@}*/
-};
-
-
-/**
- * Fog attribute group (GL_FOG_BIT).
- */
-struct gl_fog_attrib
-{
- GLboolean Enabled; /**< Fog enabled flag */
- GLfloat Color[4]; /**< Fog color */
- GLfloat Density; /**< Density >= 0.0 */
- GLfloat Start; /**< Start distance in eye coords */
- GLfloat End; /**< End distance in eye coords */
- GLfloat Index; /**< Fog index */
- GLenum Mode; /**< Fog mode */
- GLboolean ColorSumEnabled;
- GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */
- GLfloat _Scale; /**< (End == Start) ? 1.0 : 1.0 / (End - Start) */
-};
-
-
-/**
- * \brief Layout qualifiers for gl_FragDepth.
- *
- * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with
- * a layout qualifier.
- *
- * \see enum ir_depth_layout
- */
-enum gl_frag_depth_layout {
- FRAG_DEPTH_LAYOUT_NONE, /**< No layout is specified. */
- FRAG_DEPTH_LAYOUT_ANY,
- FRAG_DEPTH_LAYOUT_GREATER,
- FRAG_DEPTH_LAYOUT_LESS,
- FRAG_DEPTH_LAYOUT_UNCHANGED
-};
-
-
-/**
- * Hint attribute group (GL_HINT_BIT).
- *
- * Values are always one of GL_FASTEST, GL_NICEST, or GL_DONT_CARE.
- */
-struct gl_hint_attrib
-{
- GLenum PerspectiveCorrection;
- GLenum PointSmooth;
- GLenum LineSmooth;
- GLenum PolygonSmooth;
- GLenum Fog;
- GLenum ClipVolumeClipping; /**< GL_EXT_clip_volume_hint */
- GLenum TextureCompression; /**< GL_ARB_texture_compression */
- GLenum GenerateMipmap; /**< GL_SGIS_generate_mipmap */
- GLenum FragmentShaderDerivative; /**< GL_ARB_fragment_shader */
-};
-
-/**
- * Light state flags.
- */
-/*@{*/
-#define LIGHT_SPOT 0x1
-#define LIGHT_LOCAL_VIEWER 0x2
-#define LIGHT_POSITIONAL 0x4
-#define LIGHT_NEED_VERTICES (LIGHT_POSITIONAL|LIGHT_LOCAL_VIEWER)
-/*@}*/
-
-
-/**
- * Lighting attribute group (GL_LIGHT_BIT).
- */
-struct gl_light_attrib
-{
- struct gl_light Light[MAX_LIGHTS]; /**< Array of light sources */
- struct gl_lightmodel Model; /**< Lighting model */
-
- /**
- * Must flush FLUSH_VERTICES before referencing:
- */
- /*@{*/
- struct gl_material Material; /**< Includes front & back values */
- /*@}*/
-
- GLboolean Enabled; /**< Lighting enabled flag */
- GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */
- GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */
- GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */
- GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */
- GLbitfield ColorMaterialBitmask; /**< bitmask formed from Face and Mode */
- GLboolean ColorMaterialEnabled;
- GLenum ClampVertexColor;
-
- struct gl_light EnabledList; /**< List sentinel */
-
- /**
- * Derived state for optimizations:
- */
- /*@{*/
- GLboolean _NeedEyeCoords;
- GLboolean _NeedVertices; /**< Use fast shader? */
- GLbitfield _Flags; /**< LIGHT_* flags, see above */
- GLfloat _BaseColor[2][3];
- /*@}*/
-};
-
-
-/**
- * Line attribute group (GL_LINE_BIT).
- */
-struct gl_line_attrib
-{
- GLboolean SmoothFlag; /**< GL_LINE_SMOOTH enabled? */
- GLboolean StippleFlag; /**< GL_LINE_STIPPLE enabled? */
- GLushort StipplePattern; /**< Stipple pattern */
- GLint StippleFactor; /**< Stipple repeat factor */
- GLfloat Width; /**< Line width */
-};
-
-
-/**
- * Display list attribute group (GL_LIST_BIT).
- */
-struct gl_list_attrib
-{
- GLuint ListBase;
-};
-
-
-/**
- * Multisample attribute group (GL_MULTISAMPLE_BIT).
- */
-struct gl_multisample_attrib
-{
- GLboolean Enabled;
- GLboolean _Enabled; /**< true if Enabled and multisample buffer */
- GLboolean SampleAlphaToCoverage;
- GLboolean SampleAlphaToOne;
- GLboolean SampleCoverage;
- GLfloat SampleCoverageValue;
- GLboolean SampleCoverageInvert;
-};
-
-
-/**
- * A pixelmap (see glPixelMap)
- */
-struct gl_pixelmap
-{
- GLint Size;
- GLfloat Map[MAX_PIXEL_MAP_TABLE];
- GLubyte Map8[MAX_PIXEL_MAP_TABLE]; /**< converted to 8-bit color */
-};
-
-
-/**
- * Collection of all pixelmaps
- */
-struct gl_pixelmaps
-{
- struct gl_pixelmap RtoR; /**< i.e. GL_PIXEL_MAP_R_TO_R */
- struct gl_pixelmap GtoG;
- struct gl_pixelmap BtoB;
- struct gl_pixelmap AtoA;
- struct gl_pixelmap ItoR;
- struct gl_pixelmap ItoG;
- struct gl_pixelmap ItoB;
- struct gl_pixelmap ItoA;
- struct gl_pixelmap ItoI;
- struct gl_pixelmap StoS;
-};
-
-
-/**
- * Pixel attribute group (GL_PIXEL_MODE_BIT).
- */
-struct gl_pixel_attrib
-{
- GLenum ReadBuffer; /**< source buffer for glRead/CopyPixels() */
-
- /*--- Begin Pixel Transfer State ---*/
- /* Fields are in the order in which they're applied... */
-
- /** Scale & Bias (index shift, offset) */
- /*@{*/
- GLfloat RedBias, RedScale;
- GLfloat GreenBias, GreenScale;
- GLfloat BlueBias, BlueScale;
- GLfloat AlphaBias, AlphaScale;
- GLfloat DepthBias, DepthScale;
- GLint IndexShift, IndexOffset;
- /*@}*/
-
- /* Pixel Maps */
- /* Note: actual pixel maps are not part of this attrib group */
- GLboolean MapColorFlag;
- GLboolean MapStencilFlag;
-
- /*--- End Pixel Transfer State ---*/
-
- /** glPixelZoom */
- GLfloat ZoomX, ZoomY;
-
- /** GL_SGI_texture_color_table */
- GLfloat TextureColorTableScale[4]; /**< RGBA */
- GLfloat TextureColorTableBias[4]; /**< RGBA */
-};
-
-
-/**
- * Point attribute group (GL_POINT_BIT).
- */
-struct gl_point_attrib
-{
- GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */
- GLfloat Size; /**< User-specified point size */
- GLfloat Params[3]; /**< GL_EXT_point_parameters */
- GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */
- GLfloat Threshold; /**< GL_EXT_point_parameters */
- GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */
- GLboolean PointSprite; /**< GL_NV/ARB_point_sprite */
- GLboolean CoordReplace[MAX_TEXTURE_COORD_UNITS]; /**< GL_ARB_point_sprite*/
- GLenum SpriteRMode; /**< GL_NV_point_sprite (only!) */
- GLenum SpriteOrigin; /**< GL_ARB_point_sprite */
-};
-
-
-/**
- * Polygon attribute group (GL_POLYGON_BIT).
- */
-struct gl_polygon_attrib
-{
- GLenum FrontFace; /**< Either GL_CW or GL_CCW */
- GLenum FrontMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
- GLenum BackMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
- GLboolean _FrontBit; /**< 0=GL_CCW, 1=GL_CW */
- GLboolean CullFlag; /**< Culling on/off flag */
- GLboolean SmoothFlag; /**< True if GL_POLYGON_SMOOTH is enabled */
- GLboolean StippleFlag; /**< True if GL_POLYGON_STIPPLE is enabled */
- GLenum CullFaceMode; /**< Culling mode GL_FRONT or GL_BACK */
- GLfloat OffsetFactor; /**< Polygon offset factor, from user */
- GLfloat OffsetUnits; /**< Polygon offset units, from user */
- GLboolean OffsetPoint; /**< Offset in GL_POINT mode */
- GLboolean OffsetLine; /**< Offset in GL_LINE mode */
- GLboolean OffsetFill; /**< Offset in GL_FILL mode */
-};
-
-
-/**
- * Scissor attributes (GL_SCISSOR_BIT).
- */
-struct gl_scissor_attrib
-{
- GLboolean Enabled; /**< Scissor test enabled? */
- GLint X, Y; /**< Lower left corner of box */
- GLsizei Width, Height; /**< Size of box */
-};
-
-
-/**
- * Stencil attribute group (GL_STENCIL_BUFFER_BIT).
- *
- * Three sets of stencil data are tracked so that OpenGL 2.0,
- * GL_EXT_stencil_two_side, and GL_ATI_separate_stencil can all be supported
- * simultaneously. In each of the stencil state arrays, element 0 corresponds
- * to GL_FRONT. Element 1 corresponds to the OpenGL 2.0 /
- * GL_ATI_separate_stencil GL_BACK state. Element 2 corresponds to the
- * GL_EXT_stencil_two_side GL_BACK state.
- *
- * The derived value \c _BackFace is either 1 or 2 depending on whether or
- * not GL_STENCIL_TEST_TWO_SIDE_EXT is enabled.
- *
- * The derived value \c _TestTwoSide is set when the front-face and back-face
- * stencil state are different.
- */
-struct gl_stencil_attrib
-{
- GLboolean Enabled; /**< Enabled flag */
- GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */
- GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */
- GLboolean _Enabled; /**< Enabled and stencil buffer present */
- GLboolean _TestTwoSide;
- GLubyte _BackFace; /**< Current back stencil state (1 or 2) */
- GLenum Function[3]; /**< Stencil function */
- GLenum FailFunc[3]; /**< Fail function */
- GLenum ZPassFunc[3]; /**< Depth buffer pass function */
- GLenum ZFailFunc[3]; /**< Depth buffer fail function */
- GLint Ref[3]; /**< Reference value */
- GLuint ValueMask[3]; /**< Value mask */
- GLuint WriteMask[3]; /**< Write mask */
- GLuint Clear; /**< Clear value */
-};
-
-
-/**
- * An index for each type of texture object. These correspond to the GL
- * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
- * Note: the order is from highest priority to lowest priority.
- */
-typedef enum
-{
- TEXTURE_2D_ARRAY_INDEX,
- TEXTURE_1D_ARRAY_INDEX,
- TEXTURE_CUBE_INDEX,
- TEXTURE_3D_INDEX,
- TEXTURE_RECT_INDEX,
- TEXTURE_2D_INDEX,
- TEXTURE_1D_INDEX,
- NUM_TEXTURE_TARGETS
-} gl_texture_index;
-
-
-/**
- * Bit flags for each type of texture object
- * Used for Texture.Unit[]._ReallyEnabled flags.
- */
-/*@{*/
-#define TEXTURE_2D_ARRAY_BIT (1 << TEXTURE_2D_ARRAY_INDEX)
-#define TEXTURE_1D_ARRAY_BIT (1 << TEXTURE_1D_ARRAY_INDEX)
-#define TEXTURE_CUBE_BIT (1 << TEXTURE_CUBE_INDEX)
-#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX)
-#define TEXTURE_RECT_BIT (1 << TEXTURE_RECT_INDEX)
-#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX)
-#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX)
-/*@}*/
-
-
-/**
- * TexGenEnabled flags.
- */
-/*@{*/
-#define S_BIT 1
-#define T_BIT 2
-#define R_BIT 4
-#define Q_BIT 8
-#define STR_BITS (S_BIT | T_BIT | R_BIT)
-/*@}*/
-
-
-/**
- * Bit flag versions of the corresponding GL_ constants.
- */
-/*@{*/
-#define TEXGEN_SPHERE_MAP 0x1
-#define TEXGEN_OBJ_LINEAR 0x2
-#define TEXGEN_EYE_LINEAR 0x4
-#define TEXGEN_REFLECTION_MAP_NV 0x8
-#define TEXGEN_NORMAL_MAP_NV 0x10
-
-#define TEXGEN_NEED_NORMALS (TEXGEN_SPHERE_MAP | \
- TEXGEN_REFLECTION_MAP_NV | \
- TEXGEN_NORMAL_MAP_NV)
-#define TEXGEN_NEED_EYE_COORD (TEXGEN_SPHERE_MAP | \
- TEXGEN_REFLECTION_MAP_NV | \
- TEXGEN_NORMAL_MAP_NV | \
- TEXGEN_EYE_LINEAR)
-/*@}*/
-
-
-
-/** Tex-gen enabled for texture unit? */
-#define ENABLE_TEXGEN(unit) (1 << (unit))
-
-/** Non-identity texture matrix for texture unit? */
-#define ENABLE_TEXMAT(unit) (1 << (unit))
-
-
-/**
- * Texel fetch function prototype. We use texel fetch functions to
- * extract RGBA, color indexes and depth components out of 1D, 2D and 3D
- * texture images. These functions help to isolate us from the gritty
- * details of all the various texture image encodings.
- *
- * \param texImage texture image.
- * \param col texel column.
- * \param row texel row.
- * \param img texel image level/layer.
- * \param texelOut output texel (up to 4 GLchans)
- */
-typedef void (*FetchTexelFuncC)( const struct gl_texture_image *texImage,
- GLint col, GLint row, GLint img,
- GLchan *texelOut );
-
-/**
- * As above, but returns floats.
- * Used for depth component images and for upcoming signed/float
- * texture images.
- */
-typedef void (*FetchTexelFuncF)( const struct gl_texture_image *texImage,
- GLint col, GLint row, GLint img,
- GLfloat *texelOut );
-
-
-typedef void (*StoreTexelFunc)(struct gl_texture_image *texImage,
- GLint col, GLint row, GLint img,
- const void *texel);
-
-
-/**
- * Texture image state. Describes the dimensions of a texture image,
- * the texel format and pointers to Texel Fetch functions.
- */
-struct gl_texture_image
-{
- GLint InternalFormat; /**< Internal format as given by the user */
- GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA,
- * GL_LUMINANCE, GL_LUMINANCE_ALPHA,
- * GL_INTENSITY, GL_COLOR_INDEX,
- * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT
- * only. Used for choosing TexEnv arithmetic.
- */
- gl_format TexFormat; /**< The actual texture memory format */
-
- GLuint Border; /**< 0 or 1 */
- GLuint Width; /**< = 2^WidthLog2 + 2*Border */
- GLuint Height; /**< = 2^HeightLog2 + 2*Border */
- GLuint Depth; /**< = 2^DepthLog2 + 2*Border */
- GLuint Width2; /**< = Width - 2*Border */
- GLuint Height2; /**< = Height - 2*Border */
- GLuint Depth2; /**< = Depth - 2*Border */
- GLuint WidthLog2; /**< = log2(Width2) */
- GLuint HeightLog2; /**< = log2(Height2) */
- GLuint DepthLog2; /**< = log2(Depth2) */
- GLuint MaxLog2; /**< = MAX(WidthLog2, HeightLog2) */
- GLfloat WidthScale; /**< used for mipmap LOD computation */
- GLfloat HeightScale; /**< used for mipmap LOD computation */
- GLfloat DepthScale; /**< used for mipmap LOD computation */
- GLboolean IsClientData; /**< Data owned by client? */
- GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */
-
- struct gl_texture_object *TexObject; /**< Pointer back to parent object */
-
- FetchTexelFuncC FetchTexelc; /**< GLchan texel fetch function pointer */
- FetchTexelFuncF FetchTexelf; /**< Float texel fetch function pointer */
-
- GLuint RowStride; /**< Padded width in units of texels */
- GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to
- each 2D slice in 'Data', in texels */
- GLvoid *Data; /**< Image data, accessed via FetchTexel() */
-
- /**
- * \name For device driver:
- */
- /*@{*/
- void *DriverData; /**< Arbitrary device driver data */
- /*@}*/
-};
-
-
-/**
- * Indexes for cube map faces.
- */
-typedef enum
-{
- FACE_POS_X = 0,
- FACE_NEG_X = 1,
- FACE_POS_Y = 2,
- FACE_NEG_Y = 3,
- FACE_POS_Z = 4,
- FACE_NEG_Z = 5,
- MAX_FACES = 6
-} gl_face_index;
-
-
-/**
- * Texture object state. Contains the array of mipmap images, border color,
- * wrap modes, filter modes, shadow/texcompare state, and the per-texture
- * color palette.
- */
-struct gl_texture_object
-{
- _glthread_Mutex Mutex; /**< for thread safety */
- GLint RefCount; /**< reference count */
- GLuint Name; /**< the user-visible texture object ID */
- GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
- GLfloat Priority; /**< in [0,1] */
- union {
- GLfloat f[4];
- GLuint ui[4];
- GLint i[4];
- } BorderColor; /**< Interpreted according to texture format */
- GLenum WrapS; /**< S-axis texture image wrap mode */
- GLenum WrapT; /**< T-axis texture image wrap mode */
- GLenum WrapR; /**< R-axis texture image wrap mode */
- GLenum MinFilter; /**< minification filter */
- GLenum MagFilter; /**< magnification filter */
- GLfloat MinLod; /**< min lambda, OpenGL 1.2 */
- GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */
- GLfloat LodBias; /**< OpenGL 1.4 */
- GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
- GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
- GLfloat MaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
- GLenum CompareMode; /**< GL_ARB_shadow */
- GLenum CompareFunc; /**< GL_ARB_shadow */
- GLfloat CompareFailValue; /**< GL_ARB_shadow_ambient */
- GLenum DepthMode; /**< GL_ARB_depth_texture */
- GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
- GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */
- GLint CropRect[4]; /**< GL_OES_draw_texture */
- GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
- GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
- GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
- GLboolean _Complete; /**< Is texture object complete? */
- GLboolean _RenderToTexture; /**< Any rendering to this texture? */
- GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
- GLenum sRGBDecode; /**< GL_DECODE_EXT or GL_SKIP_DECODE_EXT */
-
- /** Actual texture images, indexed by [cube face] and [mipmap level] */
- struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
-
- /** GL_EXT_paletted_texture */
- struct gl_color_table Palette;
-
- /**
- * \name For device driver.
- * Note: instead of attaching driver data to this pointer, it's preferable
- * to instead use this struct as a base class for your own texture object
- * class. Driver->NewTextureObject() can be used to implement the
- * allocation.
- */
- void *DriverData; /**< Arbitrary device driver data */
-};
-
-
-/** Up to four combiner sources are possible with GL_NV_texture_env_combine4 */
-#define MAX_COMBINER_TERMS 4
-
-
-/**
- * Texture combine environment state.
- */
-struct gl_tex_env_combine_state
-{
- GLenum ModeRGB; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
- GLenum ModeA; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
- /** Source terms: GL_PRIMARY_COLOR, GL_TEXTURE, etc */
- GLenum SourceRGB[MAX_COMBINER_TERMS];
- GLenum SourceA[MAX_COMBINER_TERMS];
- /** Source operands: GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, etc */
- GLenum OperandRGB[MAX_COMBINER_TERMS];
- GLenum OperandA[MAX_COMBINER_TERMS];
- GLuint ScaleShiftRGB; /**< 0, 1 or 2 */
- GLuint ScaleShiftA; /**< 0, 1 or 2 */
- GLuint _NumArgsRGB; /**< Number of inputs used for the RGB combiner */
- GLuint _NumArgsA; /**< Number of inputs used for the A combiner */
-};
-
-
-/**
- * Texture coord generation state.
- */
-struct gl_texgen
-{
- GLenum Mode; /**< GL_EYE_LINEAR, GL_SPHERE_MAP, etc */
- GLbitfield _ModeBit; /**< TEXGEN_x bit corresponding to Mode */
- GLfloat ObjectPlane[4];
- GLfloat EyePlane[4];
-};
-
-
-/**
- * Texture unit state. Contains enable flags, texture environment/function/
- * combiners, texgen state, pointers to current texture objects and
- * post-filter color tables.
- */
-struct gl_texture_unit
-{
- GLbitfield Enabled; /**< bitmask of TEXTURE_*_BIT flags */
- GLbitfield _ReallyEnabled; /**< 0 or exactly one of TEXTURE_*_BIT flags */
-
- GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
- GLfloat EnvColor[4];
-
- struct gl_texgen GenS;
- struct gl_texgen GenT;
- struct gl_texgen GenR;
- struct gl_texgen GenQ;
- GLbitfield TexGenEnabled; /**< Bitwise-OR of [STRQ]_BIT values */
- GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
-
- GLfloat LodBias; /**< for biasing mipmap levels */
- GLenum BumpTarget;
- GLfloat RotMatrix[4]; /* 2x2 matrix */
-
- /**
- * \name GL_EXT_texture_env_combine
- */
- struct gl_tex_env_combine_state Combine;
-
- /**
- * Derived state based on \c EnvMode and the \c BaseFormat of the
- * currently enabled texture.
- */
- struct gl_tex_env_combine_state _EnvMode;
-
- /**
- * Currently enabled combiner state. This will point to either
- * \c Combine or \c _EnvMode.
- */
- struct gl_tex_env_combine_state *_CurrentCombine;
-
- /** Current texture object pointers */
- struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
-
- /** Points to highest priority, complete and enabled texture object */
- struct gl_texture_object *_Current;
-
- /** GL_SGI_texture_color_table */
- /*@{*/
- struct gl_color_table ColorTable;
- struct gl_color_table ProxyColorTable;
- GLboolean ColorTableEnabled;
- /*@}*/
-};
-
-
-/**
- * Texture attribute group (GL_TEXTURE_BIT).
- */
-struct gl_texture_attrib
-{
- GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */
- struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-
- struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
-
- /** GL_ARB_seamless_cubemap */
- GLboolean CubeMapSeamless;
-
- /** GL_EXT_shared_texture_palette */
- GLboolean SharedPalette;
- struct gl_color_table Palette;
-
- /** Texture units/samplers used by vertex or fragment texturing */
- GLbitfield _EnabledUnits;
-
- /** Texture coord units/sets used for fragment texturing */
- GLbitfield _EnabledCoordUnits;
-
- /** Texture coord units that have texgen enabled */
- GLbitfield _TexGenEnabled;
-
- /** Texture coord units that have non-identity matrices */
- GLbitfield _TexMatEnabled;
-
- /** Bitwise-OR of all Texture.Unit[i]._GenFlags */
- GLbitfield _GenFlags;
-};
-
-
-/**
- * Transformation attribute group (GL_TRANSFORM_BIT).
- */
-struct gl_transform_attrib
-{
- GLenum MatrixMode; /**< Matrix mode */
- GLfloat EyeUserPlane[MAX_CLIP_PLANES][4]; /**< User clip planes */
- GLfloat _ClipUserPlane[MAX_CLIP_PLANES][4]; /**< derived */
- GLbitfield ClipPlanesEnabled; /**< on/off bitmask */
- GLboolean Normalize; /**< Normalize all normals? */
- GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */
- GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */
- GLboolean DepthClamp; /**< GL_ARB_depth_clamp */
-
- GLfloat CullEyePos[4];
- GLfloat CullObjPos[4];
-};
-
-
-/**
- * Viewport attribute group (GL_VIEWPORT_BIT).
- */
-struct gl_viewport_attrib
-{
- GLint X, Y; /**< position */
- GLsizei Width, Height; /**< size */
- GLfloat Near, Far; /**< Depth buffer range */
- GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
-};
-
-
-/**
- * GL_ARB_vertex/pixel_buffer_object buffer object
- */
-struct gl_buffer_object
-{
- _glthread_Mutex Mutex;
- GLint RefCount;
- GLuint Name;
- GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */
- GLsizeiptrARB Size; /**< Size of buffer storage in bytes */
- GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
- /** Fields describing a mapped buffer */
- /*@{*/
- GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */
- GLvoid *Pointer; /**< User-space address of mapping */
- GLintptr Offset; /**< Mapped offset */
- GLsizeiptr Length; /**< Mapped length */
- /*@}*/
- GLboolean Written; /**< Ever written to? (for debugging) */
- GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
-};
-
-
-/**
- * Client pixel packing/unpacking attributes
- */
-struct gl_pixelstore_attrib
-{
- GLint Alignment;
- GLint RowLength;
- GLint SkipPixels;
- GLint SkipRows;
- GLint ImageHeight;
- GLint SkipImages;
- GLboolean SwapBytes;
- GLboolean LsbFirst;
- GLboolean ClientStorage; /**< GL_APPLE_client_storage */
- GLboolean Invert; /**< GL_MESA_pack_invert */
- struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */
-};
-
-
-/**
- * Client vertex array attributes
- */
-struct gl_client_array
-{
- GLint Size; /**< components per element (1,2,3,4) */
- GLenum Type; /**< datatype: GL_FLOAT, GL_INT, etc */
- GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */
- GLsizei Stride; /**< user-specified stride */
- GLsizei StrideB; /**< actual stride in bytes */
- const GLubyte *Ptr; /**< Points to array data */
- GLboolean Enabled; /**< Enabled flag is a boolean */
- GLboolean Normalized; /**< GL_ARB_vertex_program */
- GLboolean Integer; /**< Integer-valued? */
- GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
- GLuint _ElementSize; /**< size of each element in bytes */
-
- struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
- GLuint _MaxElement; /**< max element index into array buffer + 1 */
-};
-
-
-/**
- * Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object
- * extension, but a nice encapsulation in any case.
- */
-struct gl_array_object
-{
- /** Name of the array object as received from glGenVertexArrayAPPLE. */
- GLuint Name;
-
- GLint RefCount;
- _glthread_Mutex Mutex;
- GLboolean VBOonly; /**< require all arrays to live in VBOs? */
-
- /** Conventional vertex arrays */
- /*@{*/
- struct gl_client_array Vertex;
- struct gl_client_array Weight;
- struct gl_client_array Normal;
- struct gl_client_array Color;
- struct gl_client_array SecondaryColor;
- struct gl_client_array FogCoord;
- struct gl_client_array Index;
- struct gl_client_array EdgeFlag;
- struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS];
- struct gl_client_array PointSize;
- /*@}*/
-
- /**
- * Generic arrays for vertex programs/shaders.
- * For NV vertex programs, these attributes alias and take priority
- * over the conventional attribs above. For ARB vertex programs and
- * GLSL vertex shaders, these attributes are separate.
- */
- struct gl_client_array VertexAttrib[MAX_VERTEX_GENERIC_ATTRIBS];
-
- /** Mask of _NEW_ARRAY_* values indicating which arrays are enabled */
- GLbitfield _Enabled;
-
- /**
- * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs
- * we can determine the max legal (in bounds) glDrawElements array index.
- */
- GLuint _MaxElement;
-};
-
-
-/**
- * Vertex array state
- */
-struct gl_array_attrib
-{
- /** Currently bound array object. See _mesa_BindVertexArrayAPPLE() */
- struct gl_array_object *ArrayObj;
-
- /** The default vertex array object */
- struct gl_array_object *DefaultArrayObj;
-
- /** Array objects (GL_ARB/APPLE_vertex_array_object) */
- struct _mesa_HashTable *Objects;
-
- GLint ActiveTexture; /**< Client Active Texture */
- GLuint LockFirst; /**< GL_EXT_compiled_vertex_array */
- GLuint LockCount; /**< GL_EXT_compiled_vertex_array */
-
- /** GL 3.1 (slightly different from GL_NV_primitive_restart) */
- GLboolean PrimitiveRestart;
- GLuint RestartIndex;
-
- GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */
- GLboolean RebindArrays; /**< whether the VBO module should rebind arrays */
-
- /* GL_ARB_vertex_buffer_object */
- struct gl_buffer_object *ArrayBufferObj;
- struct gl_buffer_object *ElementArrayBufferObj;
-};
-
-
-/**
- * Feedback buffer state
- */
-struct gl_feedback
-{
- GLenum Type;
- GLbitfield _Mask; /**< FB_* bits */
- GLfloat *Buffer;
- GLuint BufferSize;
- GLuint Count;
-};
-
-
-/**
- * Selection buffer state
- */
-struct gl_selection
-{
- GLuint *Buffer; /**< selection buffer */
- GLuint BufferSize; /**< size of the selection buffer */
- GLuint BufferCount; /**< number of values in the selection buffer */
- GLuint Hits; /**< number of records in the selection buffer */
- GLuint NameStackDepth; /**< name stack depth */
- GLuint NameStack[MAX_NAME_STACK_DEPTH]; /**< name stack */
- GLboolean HitFlag; /**< hit flag */
- GLfloat HitMinZ; /**< minimum hit depth */
- GLfloat HitMaxZ; /**< maximum hit depth */
-};
-
-
-/**
- * 1-D Evaluator control points
- */
-struct gl_1d_map
-{
- GLuint Order; /**< Number of control points */
- GLfloat u1, u2, du; /**< u1, u2, 1.0/(u2-u1) */
- GLfloat *Points; /**< Points to contiguous control points */
-};
-
-
-/**
- * 2-D Evaluator control points
- */
-struct gl_2d_map
-{
- GLuint Uorder; /**< Number of control points in U dimension */
- GLuint Vorder; /**< Number of control points in V dimension */
- GLfloat u1, u2, du;
- GLfloat v1, v2, dv;
- GLfloat *Points; /**< Points to contiguous control points */
-};
-
-
-/**
- * All evaluator control point state
- */
-struct gl_evaluators
-{
- /**
- * \name 1-D maps
- */
- /*@{*/
- struct gl_1d_map Map1Vertex3;
- struct gl_1d_map Map1Vertex4;
- struct gl_1d_map Map1Index;
- struct gl_1d_map Map1Color4;
- struct gl_1d_map Map1Normal;
- struct gl_1d_map Map1Texture1;
- struct gl_1d_map Map1Texture2;
- struct gl_1d_map Map1Texture3;
- struct gl_1d_map Map1Texture4;
- struct gl_1d_map Map1Attrib[16]; /**< GL_NV_vertex_program */
- /*@}*/
-
- /**
- * \name 2-D maps
- */
- /*@{*/
- struct gl_2d_map Map2Vertex3;
- struct gl_2d_map Map2Vertex4;
- struct gl_2d_map Map2Index;
- struct gl_2d_map Map2Color4;
- struct gl_2d_map Map2Normal;
- struct gl_2d_map Map2Texture1;
- struct gl_2d_map Map2Texture2;
- struct gl_2d_map Map2Texture3;
- struct gl_2d_map Map2Texture4;
- struct gl_2d_map Map2Attrib[16]; /**< GL_NV_vertex_program */
- /*@}*/
-};
-
-
-/**
- * Names of the various vertex/fragment program register files, etc.
- *
- * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
- * All values should fit in a 4-bit field.
- *
- * NOTE: PROGRAM_ENV_PARAM, PROGRAM_STATE_VAR, PROGRAM_NAMED_PARAM,
- * PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be considered to
- * be "uniform" variables since they can only be set outside glBegin/End.
- * They're also all stored in the same Parameters array.
- */
-typedef enum
-{
- PROGRAM_TEMPORARY, /**< machine->Temporary[] */
- PROGRAM_INPUT, /**< machine->Inputs[] */
- PROGRAM_OUTPUT, /**< machine->Outputs[] */
- PROGRAM_VARYING, /**< machine->Inputs[]/Outputs[] */
- PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */
- PROGRAM_ENV_PARAM, /**< gl_program->Parameters[] */
- PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
- PROGRAM_NAMED_PARAM, /**< gl_program->Parameters[] */
- PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
- PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
- PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
- PROGRAM_ADDRESS, /**< machine->AddressReg */
- PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
- PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */
- PROGRAM_UNDEFINED, /**< Invalid/TBD value */
- PROGRAM_FILE_MAX
-} gl_register_file;
-
-
-/**
- * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be
- * one of these values.
- */
-typedef enum
-{
- SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */
- SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */
- SYSTEM_VALUE_MAX /**< Number of values */
-} gl_system_value;
-
-
-/** Vertex and fragment instructions */
-struct prog_instruction;
-struct gl_program_parameter_list;
-struct gl_uniform_list;
-
-
-/**
- * Base class for any kind of program object
- */
-struct gl_program
-{
- GLuint Id;
- GLubyte *String; /**< Null-terminated program text */
- GLint RefCount;
- GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_FRAGMENT_PROGRAM_NV */
- GLenum Format; /**< String encoding format */
- GLboolean Resident;
-
- struct prog_instruction *Instructions;
-
- GLbitfield InputsRead; /**< Bitmask of which input regs are read */
- GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
- GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
- GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
- GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
- GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */
- GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */
- GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
-
-
- /** Named parameters, constants, etc. from program text */
- struct gl_program_parameter_list *Parameters;
- /** Numbered local parameters */
- GLfloat LocalParams[MAX_PROGRAM_LOCAL_PARAMS][4];
-
- /** Vertex/fragment shader varying vars */
- struct gl_program_parameter_list *Varying;
- /** Vertex program user-defined attributes */
- struct gl_program_parameter_list *Attributes;
-
- /** Map from sampler unit to texture unit (set by glUniform1i()) */
- GLubyte SamplerUnits[MAX_SAMPLERS];
- /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
- gl_texture_index SamplerTargets[MAX_SAMPLERS];
-
- /** Bitmask of which register files are read/written with indirect
- * addressing. Mask of (1 << PROGRAM_x) bits.
- */
- GLbitfield IndirectRegisterFiles;
-
- /** Logical counts */
- /*@{*/
- GLuint NumInstructions;
- GLuint NumTemporaries;
- GLuint NumParameters;
- GLuint NumAttributes;
- GLuint NumAddressRegs;
- GLuint NumAluInstructions;
- GLuint NumTexInstructions;
- GLuint NumTexIndirections;
- /*@}*/
- /** Native, actual h/w counts */
- /*@{*/
- GLuint NumNativeInstructions;
- GLuint NumNativeTemporaries;
- GLuint NumNativeParameters;
- GLuint NumNativeAttributes;
- GLuint NumNativeAddressRegs;
- GLuint NumNativeAluInstructions;
- GLuint NumNativeTexInstructions;
- GLuint NumNativeTexIndirections;
- /*@}*/
-};
-
-
-/** Vertex program object */
-struct gl_vertex_program
-{
- struct gl_program Base; /**< base class */
- GLboolean IsNVProgram; /**< is this a GL_NV_vertex_program program? */
- GLboolean IsPositionInvariant;
-};
-
-
-/** Geometry program object */
-struct gl_geometry_program
-{
- struct gl_program Base; /**< base class */
-
- GLint VerticesOut;
- GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
- GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
- GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
-};
-
-
-/** Fragment program object */
-struct gl_fragment_program
-{
- struct gl_program Base; /**< base class */
- GLenum FogOption;
- GLboolean UsesKill; /**< shader uses KIL instruction */
- GLboolean OriginUpperLeft;
- GLboolean PixelCenterInteger;
- enum gl_frag_depth_layout FragDepthLayout;
-};
-
-
-/**
- * State common to vertex and fragment programs.
- */
-struct gl_program_state
-{
- GLint ErrorPos; /* GL_PROGRAM_ERROR_POSITION_ARB/NV */
- const char *ErrorString; /* GL_PROGRAM_ERROR_STRING_ARB/NV */
-};
-
-
-/**
- * Context state for vertex programs.
- */
-struct gl_vertex_program_state
-{
- GLboolean Enabled; /**< User-set GL_VERTEX_PROGRAM_ARB/NV flag */
- GLboolean _Enabled; /**< Enabled and _valid_ user program? */
- GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
- GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
- struct gl_vertex_program *Current; /**< User-bound vertex program */
-
- /** Currently enabled and valid vertex program (including internal
- * programs, user-defined vertex programs and GLSL vertex shaders).
- * This is the program we must use when rendering.
- */
- struct gl_vertex_program *_Current;
-
- GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
-
- /* For GL_NV_vertex_program only: */
- GLenum TrackMatrix[MAX_PROGRAM_ENV_PARAMS / 4];
- GLenum TrackMatrixTransform[MAX_PROGRAM_ENV_PARAMS / 4];
-
- /** Should fixed-function T&L be implemented with a vertex prog? */
- GLboolean _MaintainTnlProgram;
-
- /** Program to emulate fixed-function T&L (see above) */
- struct gl_vertex_program *_TnlProgram;
-
- /** Cache of fixed-function programs */
- struct gl_program_cache *Cache;
-
- GLboolean _Overriden;
-};
-
-
-/**
- * Context state for geometry programs.
- */
-struct gl_geometry_program_state
-{
- GLboolean Enabled; /**< GL_ARB_GEOMETRY_SHADER4 */
- GLboolean _Enabled; /**< Enabled and valid program? */
- struct gl_geometry_program *Current; /**< user-bound geometry program */
-
- /** Currently enabled and valid program (including internal programs
- * and compiled shader programs).
- */
- struct gl_geometry_program *_Current;
-
- GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
-
- /** Cache of fixed-function programs */
- struct gl_program_cache *Cache;
-};
-
-/**
- * Context state for fragment programs.
- */
-struct gl_fragment_program_state
-{
- GLboolean Enabled; /**< User-set fragment program enable flag */
- GLboolean _Enabled; /**< Enabled and _valid_ user program? */
- struct gl_fragment_program *Current; /**< User-bound fragment program */
-
- /** Currently enabled and valid fragment program (including internal
- * programs, user-defined fragment programs and GLSL fragment shaders).
- * This is the program we must use when rendering.
- */
- struct gl_fragment_program *_Current;
-
- GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
-
- /** Should fixed-function texturing be implemented with a fragment prog? */
- GLboolean _MaintainTexEnvProgram;
-
- /** Program to emulate fixed-function texture env/combine (see above) */
- struct gl_fragment_program *_TexEnvProgram;
-
- /** Cache of fixed-function programs */
- struct gl_program_cache *Cache;
-};
-
-
-/**
- * ATI_fragment_shader runtime state
- */
-#define ATI_FS_INPUT_PRIMARY 0
-#define ATI_FS_INPUT_SECONDARY 1
-
-struct atifs_instruction;
-struct atifs_setupinst;
-
-/**
- * ATI fragment shader
- */
-struct ati_fragment_shader
-{
- GLuint Id;
- GLint RefCount;
- struct atifs_instruction *Instructions[2];
- struct atifs_setupinst *SetupInst[2];
- GLfloat Constants[8][4];
- GLbitfield LocalConstDef; /**< Indicates which constants have been set */
- GLubyte numArithInstr[2];
- GLubyte regsAssigned[2];
- GLubyte NumPasses; /**< 1 or 2 */
- GLubyte cur_pass;
- GLubyte last_optype;
- GLboolean interpinp1;
- GLboolean isValid;
- GLuint swizzlerq;
-};
-
-/**
- * Context state for GL_ATI_fragment_shader
- */
-struct gl_ati_fragment_shader_state
-{
- GLboolean Enabled;
- GLboolean _Enabled; /**< enabled and valid shader? */
- GLboolean Compiling;
- GLfloat GlobalConstants[8][4];
- struct ati_fragment_shader *Current;
-};
-
-
-/**
- * Occlusion/timer query object.
- */
-struct gl_query_object
-{
- GLenum Target; /**< The query target, when active */
- GLuint Id; /**< hash table ID/name */
- GLuint64EXT Result; /**< the counter */
- GLboolean Active; /**< inside Begin/EndQuery */
- GLboolean Ready; /**< result is ready? */
-};
-
-
-/**
- * Context state for query objects.
- */
-struct gl_query_state
-{
- struct _mesa_HashTable *QueryObjects;
- struct gl_query_object *CurrentOcclusionObject; /* GL_ARB_occlusion_query */
- struct gl_query_object *CurrentTimerObject; /* GL_EXT_timer_query */
-
- /** GL_NV_conditional_render */
- struct gl_query_object *CondRenderQuery;
-
- /** GL_EXT_transform_feedback */
- struct gl_query_object *PrimitivesGenerated;
- struct gl_query_object *PrimitivesWritten;
-
- /** GL_ARB_timer_query */
- struct gl_query_object *TimeElapsed;
-
- GLenum CondRenderMode;
-};
-
-
-/** Sync object state */
-struct gl_sync_object {
- struct simple_node link;
- GLenum Type; /**< GL_SYNC_FENCE */
- GLuint Name; /**< Fence name */
- GLint RefCount; /**< Reference count */
- GLboolean DeletePending; /**< Object was deleted while there were still
- * live references (e.g., sync not yet finished)
- */
- GLenum SyncCondition;
- GLbitfield Flags; /**< Flags passed to glFenceSync */
- GLuint StatusFlag:1; /**< Has the sync object been signaled? */
-};
-
-
-/** Set by #pragma directives */
-struct gl_sl_pragmas
-{
- GLboolean IgnoreOptimize; /**< ignore #pragma optimize(on/off) ? */
- GLboolean IgnoreDebug; /**< ignore #pragma debug(on/off) ? */
- GLboolean Optimize; /**< defaults on */
- GLboolean Debug; /**< defaults off */
-};
-
-
-/**
- * A GLSL vertex or fragment shader object.
- */
-struct gl_shader
-{
- GLenum Type; /**< GL_FRAGMENT_SHADER || GL_VERTEX_SHADER || GL_GEOMETRY_SHADER_ARB (first field!) */
- GLuint Name; /**< AKA the handle */
- GLint RefCount; /**< Reference count */
- GLboolean DeletePending;
- GLboolean CompileStatus;
- const GLchar *Source; /**< Source code string */
- GLuint SourceChecksum; /**< for debug/logging purposes */
- struct gl_program *Program; /**< Post-compile assembly code */
- GLchar *InfoLog;
- struct gl_sl_pragmas Pragmas;
-
- unsigned Version; /**< GLSL version used for linking */
-
- struct exec_list *ir;
- struct glsl_symbol_table *symbols;
-
- /** Shaders containing built-in functions that are used for linking. */
- struct gl_shader *builtins_to_link[16];
- unsigned num_builtins_to_link;
-};
-
-
-/**
- * A GLSL program object.
- * Basically a linked collection of vertex and fragment shaders.
- */
-struct gl_shader_program
-{
- GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */
- GLuint Name; /**< aka handle or ID */
- GLint RefCount; /**< Reference count */
- GLboolean DeletePending;
-
- GLuint NumShaders; /**< number of attached shaders */
- struct gl_shader **Shaders; /**< List of attached the shaders */
-
- /** User-defined attribute bindings (glBindAttribLocation) */
- struct gl_program_parameter_list *Attributes;
-
- /** Transform feedback varyings */
- struct {
- GLenum BufferMode;
- GLuint NumVarying;
- GLchar **VaryingNames; /**< Array [NumVarying] of char * */
- } TransformFeedback;
-
- /** Geometry shader state - copied into gl_geometry_program at link time */
- struct {
- GLint VerticesOut;
- GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
- GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
- GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
- } Geom;
-
- /* post-link info: */
- struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
- struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
- struct gl_geometry_program *GeometryProgram; /**< Linked geometry prog */
- struct gl_uniform_list *Uniforms;
- struct gl_program_parameter_list *Varying;
- GLboolean LinkStatus; /**< GL_LINK_STATUS */
- GLboolean Validated;
- GLboolean _Used; /**< Ever used for drawing? */
- GLchar *InfoLog;
-
- unsigned Version; /**< GLSL version used for linking */
-
- /**
- * Per-stage shaders resulting from the first stage of linking.
- *
- * Set of linked shaders for this program. The array is accessed using the
- * \c MESA_SHADER_* defines. Entries for non-existent stages will be
- * \c NULL.
- */
- struct gl_shader *_LinkedShaders[MESA_SHADER_TYPES];
-};
-
-
-#define GLSL_DUMP 0x1 /**< Dump shaders to stdout */
-#define GLSL_LOG 0x2 /**< Write shaders to files */
-#define GLSL_OPT 0x4 /**< Force optimizations (override pragmas) */
-#define GLSL_NO_OPT 0x8 /**< Force no optimizations (override pragmas) */
-#define GLSL_UNIFORMS 0x10 /**< Print glUniform calls */
-#define GLSL_NOP_VERT 0x20 /**< Force no-op vertex shaders */
-#define GLSL_NOP_FRAG 0x40 /**< Force no-op fragment shaders */
-#define GLSL_USE_PROG 0x80 /**< Log glUseProgram calls */
-
-
-/**
- * Context state for GLSL vertex/fragment shaders.
- */
-struct gl_shader_state
-{
- /**
- * Programs used for rendering
- *
- * There is a separate program set for each shader stage. If
- * GL_EXT_separate_shader_objects is not supported, each of these must point
- * to \c NULL or to the same program.
- */
- struct gl_shader_program *CurrentVertexProgram;
- struct gl_shader_program *CurrentGeometryProgram;
- struct gl_shader_program *CurrentFragmentProgram;
-
- /**
- * Program used by glUniform calls.
- *
- * Explicitly set by \c glUseProgram and \c glActiveProgramEXT.
- */
- struct gl_shader_program *ActiveProgram;
-
- void *MemPool;
-
- GLbitfield Flags; /**< Mask of GLSL_x flags */
-};
-
-/**
- * Compiler options for a single GLSL shaders type
- */
-struct gl_shader_compiler_options
-{
- /** Driver-selectable options: */
- GLboolean EmitCondCodes; /**< Use condition codes? */
- GLboolean EmitNVTempInitialization; /**< 0-fill NV temp registers */
- /**
- * Attempts to flatten all ir_if (OPCODE_IF) for GPUs that can't
- * support control flow.
- */
- GLboolean EmitNoIfs;
- GLboolean EmitNoLoops;
- GLboolean EmitNoFunctions;
- GLboolean EmitNoCont; /**< Emit CONT opcode? */
- GLboolean EmitNoMainReturn; /**< Emit CONT/RET opcodes? */
- GLboolean EmitNoNoise; /**< Emit NOISE opcodes? */
- GLboolean EmitNoPow; /**< Emit POW opcodes? */
-
- /**
- * \name Forms of indirect addressing the driver cannot do.
- */
- /*@{*/
- GLboolean EmitNoIndirectInput; /**< No indirect addressing of inputs */
- GLboolean EmitNoIndirectOutput; /**< No indirect addressing of outputs */
- GLboolean EmitNoIndirectTemp; /**< No indirect addressing of temps */
- GLboolean EmitNoIndirectUniform; /**< No indirect addressing of constants */
- /*@}*/
-
- GLuint MaxUnrollIterations;
-
- struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
-};
-
-/**
- * Transform feedback object state
- */
-struct gl_transform_feedback_object
-{
- GLuint Name; /**< AKA the object ID */
- GLint RefCount;
- GLboolean Active; /**< Is transform feedback enabled? */
- GLboolean Paused; /**< Is transform feedback paused? */
-
- /** The feedback buffers */
- GLuint BufferNames[MAX_FEEDBACK_ATTRIBS];
- struct gl_buffer_object *Buffers[MAX_FEEDBACK_ATTRIBS];
-
- /** Start of feedback data in dest buffer */
- GLintptr Offset[MAX_FEEDBACK_ATTRIBS];
- /** Max data to put into dest buffer (in bytes) */
- GLsizeiptr Size[MAX_FEEDBACK_ATTRIBS];
-};
-
-
-/**
- * Context state for transform feedback.
- */
-struct gl_transform_feedback
-{
- GLenum Mode; /**< GL_POINTS, GL_LINES or GL_TRIANGLES */
-
- GLboolean RasterDiscard; /**< GL_RASTERIZER_DISCARD */
-
- /** The general binding point (GL_TRANSFORM_FEEDBACK_BUFFER) */
- struct gl_buffer_object *CurrentBuffer;
-
- /** The table of all transform feedback objects */
- struct _mesa_HashTable *Objects;
-
- /** The current xform-fb object (GL_TRANSFORM_FEEDBACK_BINDING) */
- struct gl_transform_feedback_object *CurrentObject;
-
- /** The default xform-fb object (Name==0) */
- struct gl_transform_feedback_object *DefaultObject;
-};
-
-
-
-/**
- * State which can be shared by multiple contexts:
- */
-struct gl_shared_state
-{
- _glthread_Mutex Mutex; /**< for thread safety */
- GLint RefCount; /**< Reference count */
- struct _mesa_HashTable *DisplayList; /**< Display lists hash table */
- struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */
-
- /** Default texture objects (shared by all texture units) */
- struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
-
- /** Fallback texture used when a bound texture is incomplete */
- struct gl_texture_object *FallbackTex;
-
- /**
- * \name Thread safety and statechange notification for texture
- * objects.
- *
- * \todo Improve the granularity of locking.
- */
- /*@{*/
- _glthread_Mutex TexMutex; /**< texobj thread safety */
- GLuint TextureStateStamp; /**< state notification for shared tex */
- /*@}*/
-
- /** Default buffer object for vertex arrays that aren't in VBOs */
- struct gl_buffer_object *NullBufferObj;
-
- /**
- * \name Vertex/geometry/fragment programs
- */
- /*@{*/
- struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
- struct gl_vertex_program *DefaultVertexProgram;
- struct gl_fragment_program *DefaultFragmentProgram;
- struct gl_geometry_program *DefaultGeometryProgram;
- /*@}*/
-
- /* GL_ATI_fragment_shader */
- struct _mesa_HashTable *ATIShaders;
- struct ati_fragment_shader *DefaultFragmentShader;
-
- struct _mesa_HashTable *BufferObjects;
-
- /** Table of both gl_shader and gl_shader_program objects */
- struct _mesa_HashTable *ShaderObjects;
-
- /* GL_EXT_framebuffer_object */
- struct _mesa_HashTable *RenderBuffers;
- struct _mesa_HashTable *FrameBuffers;
-
- /* GL_ARB_sync */
- struct simple_node SyncObjects;
-
- void *DriverData; /**< Device driver shared state */
-};
-
-
-
-
-/**
- * A renderbuffer stores colors or depth values or stencil values.
- * A framebuffer object will have a collection of these.
- * Data are read/written to the buffer with a handful of Get/Put functions.
- *
- * Instances of this object are allocated with the Driver's NewRenderbuffer
- * hook. Drivers will likely wrap this class inside a driver-specific
- * class to simulate inheritance.
- */
-struct gl_renderbuffer
-{
-#define RB_MAGIC 0xaabbccdd
- int Magic; /** XXX TEMPORARY DEBUG INFO */
- _glthread_Mutex Mutex; /**< for thread safety */
- GLuint ClassID; /**< Useful for drivers */
- GLuint Name;
- GLint RefCount;
- GLuint Width, Height;
- GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
-
- GLenum InternalFormat; /**< The user-specified format */
- GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or
- GL_STENCIL_INDEX. */
- gl_format Format; /**< The actual renderbuffer memory format */
-
- GLubyte NumSamples;
-
- GLenum DataType; /**< Type of values passed to the Get/Put functions */
- GLvoid *Data; /**< This may not be used by some kinds of RBs */
-
- /* Used to wrap one renderbuffer around another: */
- struct gl_renderbuffer *Wrapped;
-
- /* Delete this renderbuffer */
- void (*Delete)(struct gl_renderbuffer *rb);
-
- /* Allocate new storage for this renderbuffer */
- GLboolean (*AllocStorage)(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLenum internalFormat,
- GLuint width, GLuint height);
-
- /* Lock/Unlock are called before/after calling the Get/Put functions.
- * Not sure this is the right place for these yet.
- void (*Lock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
- void (*Unlock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
- */
-
- /* Return a pointer to the element/pixel at (x,y).
- * Should return NULL if the buffer memory can't be directly addressed.
- */
- void *(*GetPointer)(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLint x, GLint y);
-
- /* Get/Read a row of values.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*GetRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, void *values);
-
- /* Get/Read values at arbitrary locations.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*GetValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- const GLint x[], const GLint y[], void *values);
-
- /* Put/Write a row of values.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, const void *values, const GLubyte *mask);
-
- /* Put/Write a row of RGB values. This is a special-case routine that's
- * only used for RGBA renderbuffers when the source data is GL_RGB. That's
- * a common case for glDrawPixels and some triangle routines.
- * The values will be of format GL_RGB and type DataType.
- */
- void (*PutRowRGB)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, const void *values, const GLubyte *mask);
-
-
- /* Put/Write a row of identical values.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutMonoRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, const void *value, const GLubyte *mask);
-
- /* Put/Write values at arbitrary locations.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- const GLint x[], const GLint y[], const void *values,
- const GLubyte *mask);
- /* Put/Write identical values at arbitrary locations.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutMonoValues)(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[],
- const void *value, const GLubyte *mask);
-};
-
-
-/**
- * A renderbuffer attachment points to either a texture object (and specifies
- * a mipmap level, cube face or 3D texture slice) or points to a renderbuffer.
- */
-struct gl_renderbuffer_attachment
-{
- GLenum Type; /**< \c GL_NONE or \c GL_TEXTURE or \c GL_RENDERBUFFER_EXT */
- GLboolean Complete;
-
- /**
- * If \c Type is \c GL_RENDERBUFFER_EXT, this stores a pointer to the
- * application supplied renderbuffer object.
- */
- struct gl_renderbuffer *Renderbuffer;
-
- /**
- * If \c Type is \c GL_TEXTURE, this stores a pointer to the application
- * supplied texture object.
- */
- struct gl_texture_object *Texture;
- GLuint TextureLevel; /**< Attached mipmap level. */
- GLuint CubeMapFace; /**< 0 .. 5, for cube map textures. */
- GLuint Zoffset; /**< Slice for 3D textures, or layer for both 1D
- * and 2D array textures */
-};
-
-
-/**
- * A framebuffer is a collection of renderbuffers (color, depth, stencil, etc).
- * In C++ terms, think of this as a base class from which device drivers
- * will make derived classes.
- */
-struct gl_framebuffer
-{
- _glthread_Mutex Mutex; /**< for thread safety */
- /**
- * If zero, this is a window system framebuffer. If non-zero, this
- * is a FBO framebuffer; note that for some devices (i.e. those with
- * a natural pixel coordinate system for FBOs that differs from the
- * OpenGL/Mesa coordinate system), this means that the viewport,
- * polygon face orientation, and polygon stipple will have to be inverted.
- */
- GLuint Name;
-
- GLint RefCount;
- GLboolean DeletePending;
-
- /**
- * The framebuffer's visual. Immutable if this is a window system buffer.
- * Computed from attachments if user-made FBO.
- */
- struct gl_config Visual;
-
- GLboolean Initialized;
-
- GLuint Width, Height; /**< size of frame buffer in pixels */
-
- /** \name Drawing bounds (Intersection of buffer size and scissor box) */
- /*@{*/
- GLint _Xmin, _Xmax; /**< inclusive */
- GLint _Ymin, _Ymax; /**< exclusive */
- /*@}*/
-
- /** \name Derived Z buffer stuff */
- /*@{*/
- GLuint _DepthMax; /**< Max depth buffer value */
- GLfloat _DepthMaxF; /**< Float max depth buffer value */
- GLfloat _MRD; /**< minimum resolvable difference in Z values */
- /*@}*/
-
- /** One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */
- GLenum _Status;
-
- /** Integer color values */
- GLboolean _IntegerColor;
-
- /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
- struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT];
-
- /* In unextended OpenGL these vars are part of the GL_COLOR_BUFFER
- * attribute group and GL_PIXEL attribute group, respectively.
- */
- GLenum ColorDrawBuffer[MAX_DRAW_BUFFERS];
- GLenum ColorReadBuffer;
-
- /** Computed from ColorDraw/ReadBuffer above */
- GLuint _NumColorDrawBuffers;
- GLint _ColorDrawBufferIndexes[MAX_DRAW_BUFFERS]; /**< BUFFER_x or -1 */
- GLint _ColorReadBufferIndex; /* -1 = None */
- struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS];
- struct gl_renderbuffer *_ColorReadBuffer;
-
- /** The Actual depth/stencil buffers to use. May be wrappers around the
- * depth/stencil buffers attached above. */
- struct gl_renderbuffer *_DepthBuffer;
- struct gl_renderbuffer *_StencilBuffer;
-
- /** Delete this framebuffer */
- void (*Delete)(struct gl_framebuffer *fb);
-};
-
-
-/**
- * Precision info for shader datatypes. See glGetShaderPrecisionFormat().
- */
-struct gl_precision
-{
- GLushort RangeMin; /**< min value exponent */
- GLushort RangeMax; /**< max value exponent */
- GLushort Precision; /**< number of mantissa bits */
-};
-
-
-/**
- * Limits for vertex and fragment programs/shaders.
- */
-struct gl_program_constants
-{
- /* logical limits */
- GLuint MaxInstructions;
- GLuint MaxAluInstructions;
- GLuint MaxTexInstructions;
- GLuint MaxTexIndirections;
- GLuint MaxAttribs;
- GLuint MaxTemps;
- GLuint MaxAddressRegs;
- GLuint MaxParameters;
- GLuint MaxLocalParams;
- GLuint MaxEnvParams;
- /* native/hardware limits */
- GLuint MaxNativeInstructions;
- GLuint MaxNativeAluInstructions;
- GLuint MaxNativeTexInstructions;
- GLuint MaxNativeTexIndirections;
- GLuint MaxNativeAttribs;
- GLuint MaxNativeTemps;
- GLuint MaxNativeAddressRegs;
- GLuint MaxNativeParameters;
- /* For shaders */
- GLuint MaxUniformComponents;
- /* GL_ARB_geometry_shader4 */
- GLuint MaxGeometryTextureImageUnits;
- GLuint MaxGeometryVaryingComponents;
- GLuint MaxVertexVaryingComponents;
- GLuint MaxGeometryUniformComponents;
- GLuint MaxGeometryOutputVertices;
- GLuint MaxGeometryTotalOutputComponents;
- /* ES 2.0 and GL_ARB_ES2_compatibility */
- struct gl_precision LowFloat, MediumFloat, HighFloat;
- struct gl_precision LowInt, MediumInt, HighInt;
-};
-
-
-/**
- * Constants which may be overridden by device driver during context creation
- * but are never changed after that.
- */
-struct gl_constants
-{
- GLint MaxTextureMbytes; /**< Max memory per image, in MB */
- GLint MaxTextureLevels; /**< Max mipmap levels. */
- GLint Max3DTextureLevels; /**< Max mipmap levels for 3D textures */
- GLint MaxCubeTextureLevels; /**< Max mipmap levels for cube textures */
- GLint MaxArrayTextureLayers; /**< Max layers in array textures */
- GLint MaxTextureRectSize; /**< Max rectangle texture size, in pixes */
- GLuint MaxTextureCoordUnits;
- GLuint MaxTextureImageUnits;
- GLuint MaxVertexTextureImageUnits;
- GLuint MaxCombinedTextureImageUnits;
- GLuint MaxTextureUnits; /**< = MIN(CoordUnits, ImageUnits) */
- GLfloat MaxTextureMaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
- GLfloat MaxTextureLodBias; /**< GL_EXT_texture_lod_bias */
-
- GLuint MaxArrayLockSize;
-
- GLint SubPixelBits;
-
- GLfloat MinPointSize, MaxPointSize; /**< aliased */
- GLfloat MinPointSizeAA, MaxPointSizeAA; /**< antialiased */
- GLfloat PointSizeGranularity;
- GLfloat MinLineWidth, MaxLineWidth; /**< aliased */
- GLfloat MinLineWidthAA, MaxLineWidthAA; /**< antialiased */
- GLfloat LineWidthGranularity;
-
- GLuint MaxColorTableSize;
-
- GLuint MaxClipPlanes;
- GLuint MaxLights;
- GLfloat MaxShininess; /**< GL_NV_light_max_exponent */
- GLfloat MaxSpotExponent; /**< GL_NV_light_max_exponent */
-
- GLuint MaxViewportWidth, MaxViewportHeight;
-
- struct gl_program_constants VertexProgram; /**< GL_ARB_vertex_program */
- struct gl_program_constants FragmentProgram; /**< GL_ARB_fragment_program */
- struct gl_program_constants GeometryProgram; /**< GL_ARB_geometry_shader4 */
- GLuint MaxProgramMatrices;
- GLuint MaxProgramMatrixStackDepth;
-
- /** vertex array / buffer object bounds checking */
- GLboolean CheckArrayBounds;
-
- GLuint MaxDrawBuffers; /**< GL_ARB_draw_buffers */
-
- GLuint MaxColorAttachments; /**< GL_EXT_framebuffer_object */
- GLuint MaxRenderbufferSize; /**< GL_EXT_framebuffer_object */
- GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
-
- GLuint MaxVarying; /**< Number of float[4] varying parameters */
-
- GLuint GLSLVersion; /**< GLSL version supported (ex: 120 = 1.20) */
-
- /** Which texture units support GL_ATI_envmap_bumpmap as targets */
- GLbitfield SupportedBumpUnits;
-
- /**
- * Maximum amount of time, measured in nanseconds, that the server can wait.
- */
- GLuint64 MaxServerWaitTimeout;
-
- /** GL_EXT_provoking_vertex */
- GLboolean QuadsFollowProvokingVertexConvention;
-
- /** OpenGL version 3.0 */
- GLbitfield ContextFlags; /**< Ex: GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT */
-
- /** OpenGL version 3.2 */
- GLbitfield ProfileMask; /**< Mask of CONTEXT_x_PROFILE_BIT */
-
- /** GL_EXT_transform_feedback */
- GLuint MaxTransformFeedbackSeparateAttribs;
- GLuint MaxTransformFeedbackSeparateComponents;
- GLuint MaxTransformFeedbackInterleavedComponents;
-
- /** GL_EXT_gpu_shader4 */
- GLint MinProgramTexelOffset, MaxProgramTexelOffset;
-
- /* GL_EXT_framebuffer_sRGB */
- GLboolean sRGBCapable; /* can enable sRGB blend/update on FBOs */
-};
-
-
-/**
- * Enable flag for each OpenGL extension. Different device drivers will
- * enable different extensions at runtime.
- */
-struct gl_extensions
-{
- GLboolean dummy; /* don't remove this! */
- GLboolean dummy_true; /* Set true by _mesa_init_extensions(). */
- GLboolean dummy_false; /* Set false by _mesa_init_extensions(). */
- GLboolean ARB_ES2_compatibility;
- GLboolean ARB_blend_func_extended;
- GLboolean ARB_copy_buffer;
- GLboolean ARB_depth_buffer_float;
- GLboolean ARB_depth_clamp;
- GLboolean ARB_depth_texture;
- GLboolean ARB_draw_buffers;
- GLboolean ARB_draw_buffers_blend;
- GLboolean ARB_draw_elements_base_vertex;
- GLboolean ARB_draw_instanced;
- GLboolean ARB_fragment_coord_conventions;
- GLboolean ARB_fragment_program;
- GLboolean ARB_fragment_program_shadow;
- GLboolean ARB_fragment_shader;
- GLboolean ARB_framebuffer_object;
- GLboolean ARB_explicit_attrib_location;
- GLboolean ARB_geometry_shader4;
- GLboolean ARB_half_float_pixel;
- GLboolean ARB_half_float_vertex;
- GLboolean ARB_instanced_arrays;
- GLboolean ARB_map_buffer_range;
- GLboolean ARB_multisample;
- GLboolean ARB_multitexture;
- GLboolean ARB_occlusion_query;
- GLboolean ARB_occlusion_query2;
- GLboolean ARB_point_sprite;
- GLboolean ARB_sampler_objects;
- GLboolean ARB_seamless_cube_map;
- GLboolean ARB_shader_objects;
- GLboolean ARB_shader_stencil_export;
- GLboolean ARB_shading_language_100;
- GLboolean ARB_shadow;
- GLboolean ARB_shadow_ambient;
- GLboolean ARB_sync;
- GLboolean ARB_texture_border_clamp;
- GLboolean ARB_texture_buffer_object;
- GLboolean ARB_texture_compression;
- GLboolean ARB_texture_compression_rgtc;
- GLboolean ARB_texture_cube_map;
- GLboolean ARB_texture_env_combine;
- GLboolean ARB_texture_env_crossbar;
- GLboolean ARB_texture_env_dot3;
- GLboolean ARB_texture_float;
- GLboolean ARB_texture_mirrored_repeat;
- GLboolean ARB_texture_multisample;
- GLboolean ARB_texture_non_power_of_two;
- GLboolean ARB_texture_rg;
- GLboolean ARB_texture_rgb10_a2ui;
- GLboolean ARB_timer_query;
- GLboolean ARB_transform_feedback2;
- GLboolean ARB_transpose_matrix;
- GLboolean ARB_uniform_buffer_object;
- GLboolean ARB_vertex_array_object;
- GLboolean ARB_vertex_buffer_object;
- GLboolean ARB_vertex_program;
- GLboolean ARB_vertex_shader;
- GLboolean ARB_vertex_type_2_10_10_10_rev;
- GLboolean ARB_window_pos;
- GLboolean EXT_abgr;
- GLboolean EXT_bgra;
- GLboolean EXT_blend_color;
- GLboolean EXT_blend_equation_separate;
- GLboolean EXT_blend_func_separate;
- GLboolean EXT_blend_logic_op;
- GLboolean EXT_blend_minmax;
- GLboolean EXT_blend_subtract;
- GLboolean EXT_clip_volume_hint;
- GLboolean EXT_compiled_vertex_array;
- GLboolean EXT_copy_texture;
- GLboolean EXT_depth_bounds_test;
- GLboolean EXT_draw_buffers2;
- GLboolean EXT_draw_range_elements;
- GLboolean EXT_fog_coord;
- GLboolean EXT_framebuffer_blit;
- GLboolean EXT_framebuffer_multisample;
- GLboolean EXT_framebuffer_object;
- GLboolean EXT_framebuffer_sRGB;
- GLboolean EXT_gpu_program_parameters;
- GLboolean EXT_gpu_shader4;
- GLboolean EXT_multi_draw_arrays;
- GLboolean EXT_paletted_texture;
- GLboolean EXT_packed_depth_stencil;
- GLboolean EXT_packed_float;
- GLboolean EXT_packed_pixels;
- GLboolean EXT_pixel_buffer_object;
- GLboolean EXT_point_parameters;
- GLboolean EXT_polygon_offset;
- GLboolean EXT_provoking_vertex;
- GLboolean EXT_rescale_normal;
- GLboolean EXT_shadow_funcs;
- GLboolean EXT_secondary_color;
- GLboolean EXT_separate_shader_objects;
- GLboolean EXT_separate_specular_color;
- GLboolean EXT_shared_texture_palette;
- GLboolean EXT_stencil_wrap;
- GLboolean EXT_stencil_two_side;
- GLboolean EXT_subtexture;
- GLboolean EXT_texture;
- GLboolean EXT_texture_object;
- GLboolean EXT_texture3D;
- GLboolean EXT_texture_array;
- GLboolean EXT_texture_compression_s3tc;
- GLboolean EXT_texture_env_add;
- GLboolean EXT_texture_env_combine;
- GLboolean EXT_texture_env_dot3;
- GLboolean EXT_texture_filter_anisotropic;
- GLboolean EXT_texture_integer;
- GLboolean EXT_texture_lod_bias;
- GLboolean EXT_texture_mirror_clamp;
- GLboolean EXT_texture_shared_exponent;
- GLboolean EXT_texture_sRGB;
- GLboolean EXT_texture_sRGB_decode;
- GLboolean EXT_texture_swizzle;
- GLboolean EXT_transform_feedback;
- GLboolean EXT_timer_query;
- GLboolean EXT_vertex_array;
- GLboolean EXT_vertex_array_bgra;
- GLboolean EXT_vertex_array_set;
- GLboolean OES_standard_derivatives;
- /* vendor extensions */
- GLboolean AMD_conservative_depth;
- GLboolean APPLE_client_storage;
- GLboolean APPLE_packed_pixels;
- GLboolean APPLE_vertex_array_object;
- GLboolean APPLE_object_purgeable;
- GLboolean ATI_envmap_bumpmap;
- GLboolean ATI_texture_mirror_once;
- GLboolean ATI_texture_env_combine3;
- GLboolean ATI_fragment_shader;
- GLboolean ATI_separate_stencil;
- GLboolean IBM_rasterpos_clip;
- GLboolean IBM_multimode_draw_arrays;
- GLboolean MESA_pack_invert;
- GLboolean MESA_resize_buffers;
- GLboolean MESA_ycbcr_texture;
- GLboolean MESA_texture_array;
- GLboolean MESA_texture_signed_rgba;
- GLboolean NV_blend_square;
- GLboolean NV_conditional_render;
- GLboolean NV_fragment_program;
- GLboolean NV_fragment_program_option;
- GLboolean NV_light_max_exponent;
- GLboolean NV_point_sprite;
- GLboolean NV_primitive_restart;
- GLboolean NV_texgen_reflection;
- GLboolean NV_texture_env_combine4;
- GLboolean NV_texture_rectangle;
- GLboolean NV_vertex_program;
- GLboolean NV_vertex_program1_1;
- GLboolean OES_read_format;
- GLboolean SGI_texture_color_table;
- GLboolean SGIS_generate_mipmap;
- GLboolean SGIS_texture_edge_clamp;
- GLboolean SGIS_texture_lod;
- GLboolean TDFX_texture_compression_FXT1;
- GLboolean S3_s3tc;
- GLboolean OES_EGL_image;
- GLboolean OES_draw_texture;
- GLboolean EXT_texture_format_BGRA8888;
- GLboolean extension_sentinel;
- /** The extension string */
- const GLubyte *String;
- /** Number of supported extensions */
- GLuint Count;
-};
-
-
-/**
- * A stack of matrices (projection, modelview, color, texture, etc).
- */
-struct gl_matrix_stack
-{
- GLmatrix *Top; /**< points into Stack */
- GLmatrix *Stack; /**< array [MaxDepth] of GLmatrix */
- GLuint Depth; /**< 0 <= Depth < MaxDepth */
- GLuint MaxDepth; /**< size of Stack[] array */
- GLuint DirtyFlag; /**< _NEW_MODELVIEW or _NEW_PROJECTION, for example */
-};
-
-
-/**
- * \name Bits for image transfer operations
- * \sa __struct gl_contextRec::ImageTransferState.
- */
-/*@{*/
-#define IMAGE_SCALE_BIAS_BIT 0x1
-#define IMAGE_SHIFT_OFFSET_BIT 0x2
-#define IMAGE_MAP_COLOR_BIT 0x4
-#define IMAGE_CLAMP_BIT 0x800
-
-
-/** Pixel Transfer ops */
-#define IMAGE_BITS (IMAGE_SCALE_BIAS_BIT | \
- IMAGE_SHIFT_OFFSET_BIT | \
- IMAGE_MAP_COLOR_BIT)
-
-/**
- * \name Bits to indicate what state has changed.
- */
-/*@{*/
-#define _NEW_MODELVIEW (1 << 0) /**< gl_context::ModelView */
-#define _NEW_PROJECTION (1 << 1) /**< gl_context::Projection */
-#define _NEW_TEXTURE_MATRIX (1 << 2) /**< gl_context::TextureMatrix */
-#define _NEW_COLOR (1 << 3) /**< gl_context::Color */
-#define _NEW_DEPTH (1 << 4) /**< gl_context::Depth */
-#define _NEW_EVAL (1 << 5) /**< gl_context::Eval, EvalMap */
-#define _NEW_FOG (1 << 6) /**< gl_context::Fog */
-#define _NEW_HINT (1 << 7) /**< gl_context::Hint */
-#define _NEW_LIGHT (1 << 8) /**< gl_context::Light */
-#define _NEW_LINE (1 << 9) /**< gl_context::Line */
-#define _NEW_PIXEL (1 << 10) /**< gl_context::Pixel */
-#define _NEW_POINT (1 << 11) /**< gl_context::Point */
-#define _NEW_POLYGON (1 << 12) /**< gl_context::Polygon */
-#define _NEW_POLYGONSTIPPLE (1 << 13) /**< gl_context::PolygonStipple */
-#define _NEW_SCISSOR (1 << 14) /**< gl_context::Scissor */
-#define _NEW_STENCIL (1 << 15) /**< gl_context::Stencil */
-#define _NEW_TEXTURE (1 << 16) /**< gl_context::Texture */
-#define _NEW_TRANSFORM (1 << 17) /**< gl_context::Transform */
-#define _NEW_VIEWPORT (1 << 18) /**< gl_context::Viewport */
-#define _NEW_PACKUNPACK (1 << 19) /**< gl_context::Pack, Unpack */
-#define _NEW_ARRAY (1 << 20) /**< gl_context::Array */
-#define _NEW_RENDERMODE (1 << 21) /**< gl_context::RenderMode, etc */
-#define _NEW_BUFFERS (1 << 22) /**< gl_context::Visual, DrawBuffer, */
-#define _NEW_CURRENT_ATTRIB (1 << 23) /**< gl_context::Current */
-#define _NEW_MULTISAMPLE (1 << 24) /**< gl_context::Multisample */
-#define _NEW_TRACK_MATRIX (1 << 25) /**< gl_context::VertexProgram */
-#define _NEW_PROGRAM (1 << 26) /**< New program/shader state */
-#define _NEW_PROGRAM_CONSTANTS (1 << 27)
-#define _NEW_BUFFER_OBJECT (1 << 28)
-#define _NEW_ALL ~0
-/*@}*/
-
-
-/**
- * \name Bits to track array state changes
- *
- * Also used to summarize array enabled.
- */
-/*@{*/
-#define _NEW_ARRAY_VERTEX VERT_BIT_POS
-#define _NEW_ARRAY_WEIGHT VERT_BIT_WEIGHT
-#define _NEW_ARRAY_NORMAL VERT_BIT_NORMAL
-#define _NEW_ARRAY_COLOR0 VERT_BIT_COLOR0
-#define _NEW_ARRAY_COLOR1 VERT_BIT_COLOR1
-#define _NEW_ARRAY_FOGCOORD VERT_BIT_FOG
-#define _NEW_ARRAY_INDEX VERT_BIT_COLOR_INDEX
-#define _NEW_ARRAY_EDGEFLAG VERT_BIT_EDGEFLAG
-#define _NEW_ARRAY_POINT_SIZE VERT_BIT_COLOR_INDEX /* aliased */
-#define _NEW_ARRAY_TEXCOORD_0 VERT_BIT_TEX0
-#define _NEW_ARRAY_TEXCOORD_1 VERT_BIT_TEX1
-#define _NEW_ARRAY_TEXCOORD_2 VERT_BIT_TEX2
-#define _NEW_ARRAY_TEXCOORD_3 VERT_BIT_TEX3
-#define _NEW_ARRAY_TEXCOORD_4 VERT_BIT_TEX4
-#define _NEW_ARRAY_TEXCOORD_5 VERT_BIT_TEX5
-#define _NEW_ARRAY_TEXCOORD_6 VERT_BIT_TEX6
-#define _NEW_ARRAY_TEXCOORD_7 VERT_BIT_TEX7
-#define _NEW_ARRAY_ATTRIB_0 VERT_BIT_GENERIC0 /* start at bit 16 */
-#define _NEW_ARRAY_ALL 0xffffffff
-
-
-#define _NEW_ARRAY_TEXCOORD(i) (_NEW_ARRAY_TEXCOORD_0 << (i))
-#define _NEW_ARRAY_ATTRIB(i) (_NEW_ARRAY_ATTRIB_0 << (i))
-/*@}*/
-
-
-
-/**
- * \name A bunch of flags that we think might be useful to drivers.
- *
- * Set in the __struct gl_contextRec::_TriangleCaps bitfield.
- */
-/*@{*/
-#define DD_FLATSHADE 0x1
-#define DD_SEPARATE_SPECULAR 0x2
-#define DD_TRI_CULL_FRONT_BACK 0x4 /* special case on some hw */
-#define DD_TRI_LIGHT_TWOSIDE 0x8
-#define DD_TRI_UNFILLED 0x10
-#define DD_TRI_SMOOTH 0x20
-#define DD_TRI_STIPPLE 0x40
-#define DD_TRI_OFFSET 0x80
-#define DD_LINE_SMOOTH 0x100
-#define DD_LINE_STIPPLE 0x200
-#define DD_POINT_SMOOTH 0x400
-#define DD_POINT_ATTEN 0x800
-#define DD_TRI_TWOSTENCIL 0x1000
-/*@}*/
-
-
-/**
- * \name Define the state changes under which each of these bits might change
- */
-/*@{*/
-#define _DD_NEW_FLATSHADE _NEW_LIGHT
-#define _DD_NEW_SEPARATE_SPECULAR (_NEW_LIGHT | _NEW_FOG | _NEW_PROGRAM)
-#define _DD_NEW_TRI_CULL_FRONT_BACK _NEW_POLYGON
-#define _DD_NEW_TRI_LIGHT_TWOSIDE _NEW_LIGHT
-#define _DD_NEW_TRI_UNFILLED _NEW_POLYGON
-#define _DD_NEW_TRI_SMOOTH _NEW_POLYGON
-#define _DD_NEW_TRI_STIPPLE _NEW_POLYGON
-#define _DD_NEW_TRI_OFFSET _NEW_POLYGON
-#define _DD_NEW_LINE_SMOOTH _NEW_LINE
-#define _DD_NEW_LINE_STIPPLE _NEW_LINE
-#define _DD_NEW_LINE_WIDTH _NEW_LINE
-#define _DD_NEW_POINT_SMOOTH _NEW_POINT
-#define _DD_NEW_POINT_SIZE _NEW_POINT
-#define _DD_NEW_POINT_ATTEN _NEW_POINT
-/*@}*/
-
-
-/**
- * Composite state flags
- */
-/*@{*/
-#define _MESA_NEW_NEED_EYE_COORDS (_NEW_LIGHT | \
- _NEW_TEXTURE | \
- _NEW_POINT | \
- _NEW_PROGRAM | \
- _NEW_MODELVIEW)
-
-#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \
- _NEW_TEXTURE)
-
-#define _MESA_NEW_TRANSFER_STATE (_NEW_PIXEL)
-/*@}*/
-
-
-
-
-/* This has to be included here. */
-#include "dd.h"
-
-
-/**
- * Display list flags.
- * Strictly this is a tnl-private concept, but it doesn't seem
- * worthwhile adding a tnl private structure just to hold this one bit
- * of information:
- */
-#define DLIST_DANGLING_REFS 0x1
-
-
-/** Opaque declaration of display list payload data type */
-union gl_dlist_node;
-
-
-/**
- * Provide a location where information about a display list can be
- * collected. Could be extended with driverPrivate structures,
- * etc. in the future.
- */
-struct gl_display_list
-{
- GLuint Name;
- GLbitfield Flags; /**< DLIST_x flags */
- /** The dlist commands are in a linked list of nodes */
- union gl_dlist_node *Head;
-};
-
-
-/**
- * State used during display list compilation and execution.
- */
-struct gl_dlist_state
-{
- GLuint CallDepth; /**< Current recursion calling depth */
-
- struct gl_display_list *CurrentList; /**< List currently being compiled */
- union gl_dlist_node *CurrentBlock; /**< Pointer to current block of nodes */
- GLuint CurrentPos; /**< Index into current block of nodes */
-
- GLvertexformat ListVtxfmt;
-
- GLubyte ActiveAttribSize[VERT_ATTRIB_MAX];
- GLfloat CurrentAttrib[VERT_ATTRIB_MAX][4];
-
- GLubyte ActiveMaterialSize[MAT_ATTRIB_MAX];
- GLfloat CurrentMaterial[MAT_ATTRIB_MAX][4];
-
- GLubyte ActiveIndex;
- GLfloat CurrentIndex;
-
- GLubyte ActiveEdgeFlag;
- GLboolean CurrentEdgeFlag;
-
- struct {
- /* State known to have been set by the currently-compiling display
- * list. Used to eliminate some redundant state changes.
- */
- GLenum ShadeModel;
- } Current;
-};
-
-
-/**
- * Enum for the OpenGL APIs we know about and may support.
- */
-typedef enum
-{
- API_OPENGL,
- API_OPENGLES,
- API_OPENGLES2
-} gl_api;
-
-
-/**
- * Mesa rendering context.
- *
- * This is the central context data structure for Mesa. Almost all
- * OpenGL state is contained in this structure.
- * Think of this as a base class from which device drivers will derive
- * sub classes.
- *
- * The struct gl_context typedef names this structure.
- */
-struct gl_context
-{
- /** State possibly shared with other contexts in the address space */
- struct gl_shared_state *Shared;
-
- /** \name API function pointer tables */
- /*@{*/
- gl_api API;
- struct _glapi_table *Save; /**< Display list save functions */
- struct _glapi_table *Exec; /**< Execute functions */
- struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! */
- /*@}*/
-
- struct gl_config Visual;
- struct gl_framebuffer *DrawBuffer; /**< buffer for writing */
- struct gl_framebuffer *ReadBuffer; /**< buffer for reading */
- struct gl_framebuffer *WinSysDrawBuffer; /**< set with MakeCurrent */
- struct gl_framebuffer *WinSysReadBuffer; /**< set with MakeCurrent */
-
- /**
- * Device driver function pointer table
- */
- struct dd_function_table Driver;
-
- void *DriverCtx; /**< Points to device driver context/state */
-
- /** Core/Driver constants */
- struct gl_constants Const;
-
- /** \name The various 4x4 matrix stacks */
- /*@{*/
- struct gl_matrix_stack ModelviewMatrixStack;
- struct gl_matrix_stack ProjectionMatrixStack;
- struct gl_matrix_stack TextureMatrixStack[MAX_TEXTURE_UNITS];
- struct gl_matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES];
- struct gl_matrix_stack *CurrentStack; /**< Points to one of the above stacks */
- /*@}*/
-
- /** Combined modelview and projection matrix */
- GLmatrix _ModelProjectMatrix;
-
- /** \name Display lists */
- struct gl_dlist_state ListState;
-
- GLboolean ExecuteFlag; /**< Execute GL commands? */
- GLboolean CompileFlag; /**< Compile GL commands into display list? */
-
- /** Extension information */
- struct gl_extensions Extensions;
-
- /** Version info */
- GLuint VersionMajor, VersionMinor;
- char *VersionString;
-
- /** \name State attribute stack (for glPush/PopAttrib) */
- /*@{*/
- GLuint AttribStackDepth;
- struct gl_attrib_node *AttribStack[MAX_ATTRIB_STACK_DEPTH];
- /*@}*/
-
- /** \name Renderer attribute groups
- *
- * We define a struct for each attribute group to make pushing and popping
- * attributes easy. Also it's a good organization.
- */
- /*@{*/
- struct gl_accum_attrib Accum; /**< Accum buffer attributes */
- struct gl_colorbuffer_attrib Color; /**< Color buffer attributes */
- struct gl_current_attrib Current; /**< Current attributes */
- struct gl_depthbuffer_attrib Depth; /**< Depth buffer attributes */
- struct gl_eval_attrib Eval; /**< Eval attributes */
- struct gl_fog_attrib Fog; /**< Fog attributes */
- struct gl_hint_attrib Hint; /**< Hint attributes */
- struct gl_light_attrib Light; /**< Light attributes */
- struct gl_line_attrib Line; /**< Line attributes */
- struct gl_list_attrib List; /**< List attributes */
- struct gl_multisample_attrib Multisample;
- struct gl_pixel_attrib Pixel; /**< Pixel attributes */
- struct gl_point_attrib Point; /**< Point attributes */
- struct gl_polygon_attrib Polygon; /**< Polygon attributes */
- GLuint PolygonStipple[32]; /**< Polygon stipple */
- struct gl_scissor_attrib Scissor; /**< Scissor attributes */
- struct gl_stencil_attrib Stencil; /**< Stencil buffer attributes */
- struct gl_texture_attrib Texture; /**< Texture attributes */
- struct gl_transform_attrib Transform; /**< Transformation attributes */
- struct gl_viewport_attrib Viewport; /**< Viewport attributes */
- /*@}*/
-
- /** \name Client attribute stack */
- /*@{*/
- GLuint ClientAttribStackDepth;
- struct gl_attrib_node *ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH];
- /*@}*/
-
- /** \name Client attribute groups */
- /*@{*/
- struct gl_array_attrib Array; /**< Vertex arrays */
- struct gl_pixelstore_attrib Pack; /**< Pixel packing */
- struct gl_pixelstore_attrib Unpack; /**< Pixel unpacking */
- struct gl_pixelstore_attrib DefaultPacking; /**< Default params */
- /*@}*/
-
- /** \name Other assorted state (not pushed/popped on attribute stack) */
- /*@{*/
- struct gl_pixelmaps PixelMaps;
-
- struct gl_evaluators EvalMap; /**< All evaluators */
- struct gl_feedback Feedback; /**< Feedback */
- struct gl_selection Select; /**< Selection */
-
- struct gl_program_state Program; /**< general program state */
- struct gl_vertex_program_state VertexProgram;
- struct gl_fragment_program_state FragmentProgram;
- struct gl_geometry_program_state GeometryProgram;
- struct gl_ati_fragment_shader_state ATIFragmentShader;
-
- struct gl_shader_state Shader; /**< GLSL shader object state */
- struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_TYPES];
-
- struct gl_query_state Query; /**< occlusion, timer queries */
-
- struct gl_transform_feedback TransformFeedback;
-
- struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
- struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */
- /*@}*/
-
- struct gl_meta_state *Meta; /**< for "meta" operations */
-
- /* GL_EXT_framebuffer_object */
- struct gl_renderbuffer *CurrentRenderbuffer;
-
- GLenum ErrorValue; /**< Last error code */
-
- /**
- * Recognize and silence repeated error debug messages in buggy apps.
- */
- const char *ErrorDebugFmtString;
- GLuint ErrorDebugCount;
-
- GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
- GLbitfield NewState; /**< bitwise-or of _NEW_* flags */
-
- GLboolean ViewportInitialized; /**< has viewport size been initialized? */
-
- GLbitfield varying_vp_inputs; /**< mask of VERT_BIT_* flags */
-
- /** \name Derived state */
- /*@{*/
- /** Bitwise-or of DD_* flags. Note that this bitfield may be used before
- * state validation so they need to always be current.
- */
- GLbitfield _TriangleCaps;
- GLbitfield _ImageTransferState;/**< bitwise-or of IMAGE_*_BIT flags */
- GLfloat _EyeZDir[3];
- GLfloat _ModelViewInvScale;
- GLboolean _NeedEyeCoords;
- GLboolean _ForceEyeCoords;
-
- GLuint TextureStateTimestamp; /**< detect changes to shared state */
-
- struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */
- struct gl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
- /**@}*/
-
- struct gl_list_extensions *ListExt; /**< driver dlist extensions */
-
- /** \name For debugging/development only */
- /*@{*/
- GLboolean FirstTimeCurrent;
- /*@}*/
-
- /** software compression/decompression supported or not */
- GLboolean Mesa_DXTn;
-
- GLboolean TextureFormatSupported[MESA_FORMAT_COUNT];
-
- /**
- * Use dp4 (rather than mul/mad) instructions for position
- * transformation?
- */
- GLboolean mvp_with_dp4;
-
- /**
- * \name Hooks for module contexts.
- *
- * These will eventually live in the driver or elsewhere.
- */
- /*@{*/
- void *swrast_context;
- void *swsetup_context;
- void *swtnl_context;
- void *swtnl_im;
- struct st_context *st;
- void *aelt_context;
- /*@}*/
-};
-
-
-#ifdef DEBUG
-extern int MESA_VERBOSE;
-extern int MESA_DEBUG_FLAGS;
-# define MESA_FUNCTION __FUNCTION__
-#else
-# define MESA_VERBOSE 0
-# define MESA_DEBUG_FLAGS 0
-# define MESA_FUNCTION "a function"
-# ifndef NDEBUG
-# define NDEBUG
-# endif
-#endif
-
-
-/** The MESA_VERBOSE var is a bitmask of these flags */
-enum _verbose
-{
- VERBOSE_VARRAY = 0x0001,
- VERBOSE_TEXTURE = 0x0002,
- VERBOSE_MATERIAL = 0x0004,
- VERBOSE_PIPELINE = 0x0008,
- VERBOSE_DRIVER = 0x0010,
- VERBOSE_STATE = 0x0020,
- VERBOSE_API = 0x0040,
- VERBOSE_DISPLAY_LIST = 0x0100,
- VERBOSE_LIGHTING = 0x0200,
- VERBOSE_PRIMS = 0x0400,
- VERBOSE_VERTS = 0x0800,
- VERBOSE_DISASSEM = 0x1000,
- VERBOSE_DRAW = 0x2000,
- VERBOSE_SWAPBUFFERS = 0x4000
-};
-
-
-/** The MESA_DEBUG_FLAGS var is a bitmask of these flags */
-enum _debug
-{
- DEBUG_ALWAYS_FLUSH = 0x1
-};
-
-
-
-#endif /* MTYPES_H */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.7
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. 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 mtypes.h
+ * Main Mesa data structures.
+ *
+ * Please try to mark derived values with a leading underscore ('_').
+ */
+
+#ifndef MTYPES_H
+#define MTYPES_H
+
+
+#include "main/glheader.h"
+#include "main/config.h"
+#include "main/mfeatures.h"
+#include "glapi/glapi.h"
+#include "math/m_matrix.h" /* GLmatrix */
+#include "main/simple_list.h" /* struct simple_node */
+#include "main/formats.h" /* MESA_FORMAT_COUNT */
+
+
+/**
+ * Color channel data type.
+ */
+#if CHAN_BITS == 8
+ typedef GLubyte GLchan;
+#define CHAN_MAX 255
+#define CHAN_MAXF 255.0F
+#define CHAN_TYPE GL_UNSIGNED_BYTE
+#elif CHAN_BITS == 16
+ typedef GLushort GLchan;
+#define CHAN_MAX 65535
+#define CHAN_MAXF 65535.0F
+#define CHAN_TYPE GL_UNSIGNED_SHORT
+#elif CHAN_BITS == 32
+ typedef GLfloat GLchan;
+#define CHAN_MAX 1.0
+#define CHAN_MAXF 1.0F
+#define CHAN_TYPE GL_FLOAT
+#else
+#error "illegal number of color channel bits"
+#endif
+
+
+/**
+ * Stencil buffer data type.
+ */
+#if STENCIL_BITS==8
+ typedef GLubyte GLstencil;
+#elif STENCIL_BITS==16
+ typedef GLushort GLstencil;
+#else
+# error "illegal number of stencil bits"
+#endif
+
+
+/**
+ * \name 64-bit extension of GLbitfield.
+ */
+/*@{*/
+typedef GLuint64 GLbitfield64;
+
+/** Set a single bit */
+#define BITFIELD64_BIT(b) (1ULL << (b))
+
+
+/**
+ * \name Some forward type declarations
+ */
+/*@{*/
+struct _mesa_HashTable;
+struct gl_attrib_node;
+struct gl_list_extensions;
+struct gl_meta_state;
+struct gl_pixelstore_attrib;
+struct gl_program_cache;
+struct gl_texture_format;
+struct gl_texture_image;
+struct gl_texture_object;
+struct gl_context;
+struct st_context;
+/*@}*/
+
+
+/** Extra draw modes beyond GL_POINTS, GL_TRIANGLE_FAN, etc */
+#define PRIM_OUTSIDE_BEGIN_END (GL_POLYGON+1)
+#define PRIM_INSIDE_UNKNOWN_PRIM (GL_POLYGON+2)
+#define PRIM_UNKNOWN (GL_POLYGON+3)
+
+
+/**
+ * Shader stages. Note that these will become 5 with tessellation.
+ * These MUST have the same values as gallium's PIPE_SHADER_*
+ */
+typedef enum
+{
+ MESA_SHADER_VERTEX = 0,
+ MESA_SHADER_FRAGMENT = 1,
+ MESA_SHADER_GEOMETRY = 2,
+ MESA_SHADER_TYPES = 3
+} gl_shader_type;
+
+
+
+/**
+ * Indexes for vertex program attributes.
+ * GL_NV_vertex_program aliases generic attributes over the conventional
+ * attributes. In GL_ARB_vertex_program shader the aliasing is optional.
+ * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
+ * generic attributes are distinct/separate).
+ */
+typedef enum
+{
+ VERT_ATTRIB_POS = 0,
+ VERT_ATTRIB_WEIGHT = 1,
+ VERT_ATTRIB_NORMAL = 2,
+ VERT_ATTRIB_COLOR0 = 3,
+ VERT_ATTRIB_COLOR1 = 4,
+ VERT_ATTRIB_FOG = 5,
+ VERT_ATTRIB_COLOR_INDEX = 6,
+ VERT_ATTRIB_POINT_SIZE = 6, /*alias*/
+ VERT_ATTRIB_EDGEFLAG = 7,
+ VERT_ATTRIB_TEX0 = 8,
+ VERT_ATTRIB_TEX1 = 9,
+ VERT_ATTRIB_TEX2 = 10,
+ VERT_ATTRIB_TEX3 = 11,
+ VERT_ATTRIB_TEX4 = 12,
+ VERT_ATTRIB_TEX5 = 13,
+ VERT_ATTRIB_TEX6 = 14,
+ VERT_ATTRIB_TEX7 = 15,
+ VERT_ATTRIB_GENERIC0 = 16,
+ VERT_ATTRIB_GENERIC1 = 17,
+ VERT_ATTRIB_GENERIC2 = 18,
+ VERT_ATTRIB_GENERIC3 = 19,
+ VERT_ATTRIB_GENERIC4 = 20,
+ VERT_ATTRIB_GENERIC5 = 21,
+ VERT_ATTRIB_GENERIC6 = 22,
+ VERT_ATTRIB_GENERIC7 = 23,
+ VERT_ATTRIB_GENERIC8 = 24,
+ VERT_ATTRIB_GENERIC9 = 25,
+ VERT_ATTRIB_GENERIC10 = 26,
+ VERT_ATTRIB_GENERIC11 = 27,
+ VERT_ATTRIB_GENERIC12 = 28,
+ VERT_ATTRIB_GENERIC13 = 29,
+ VERT_ATTRIB_GENERIC14 = 30,
+ VERT_ATTRIB_GENERIC15 = 31,
+ VERT_ATTRIB_MAX = 32
+} gl_vert_attrib;
+
+/**
+ * Bitflags for vertex attributes.
+ * These are used in bitfields in many places.
+ */
+/*@{*/
+#define VERT_BIT_POS (1 << VERT_ATTRIB_POS)
+#define VERT_BIT_WEIGHT (1 << VERT_ATTRIB_WEIGHT)
+#define VERT_BIT_NORMAL (1 << VERT_ATTRIB_NORMAL)
+#define VERT_BIT_COLOR0 (1 << VERT_ATTRIB_COLOR0)
+#define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1)
+#define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG)
+#define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX)
+#define VERT_BIT_EDGEFLAG (1 << VERT_ATTRIB_EDGEFLAG)
+#define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0)
+#define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1)
+#define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2)
+#define VERT_BIT_TEX3 (1 << VERT_ATTRIB_TEX3)
+#define VERT_BIT_TEX4 (1 << VERT_ATTRIB_TEX4)
+#define VERT_BIT_TEX5 (1 << VERT_ATTRIB_TEX5)
+#define VERT_BIT_TEX6 (1 << VERT_ATTRIB_TEX6)
+#define VERT_BIT_TEX7 (1 << VERT_ATTRIB_TEX7)
+#define VERT_BIT_GENERIC0 (1 << VERT_ATTRIB_GENERIC0)
+#define VERT_BIT_GENERIC1 (1 << VERT_ATTRIB_GENERIC1)
+#define VERT_BIT_GENERIC2 (1 << VERT_ATTRIB_GENERIC2)
+#define VERT_BIT_GENERIC3 (1 << VERT_ATTRIB_GENERIC3)
+#define VERT_BIT_GENERIC4 (1 << VERT_ATTRIB_GENERIC4)
+#define VERT_BIT_GENERIC5 (1 << VERT_ATTRIB_GENERIC5)
+#define VERT_BIT_GENERIC6 (1 << VERT_ATTRIB_GENERIC6)
+#define VERT_BIT_GENERIC7 (1 << VERT_ATTRIB_GENERIC7)
+#define VERT_BIT_GENERIC8 (1 << VERT_ATTRIB_GENERIC8)
+#define VERT_BIT_GENERIC9 (1 << VERT_ATTRIB_GENERIC9)
+#define VERT_BIT_GENERIC10 (1 << VERT_ATTRIB_GENERIC10)
+#define VERT_BIT_GENERIC11 (1 << VERT_ATTRIB_GENERIC11)
+#define VERT_BIT_GENERIC12 (1 << VERT_ATTRIB_GENERIC12)
+#define VERT_BIT_GENERIC13 (1 << VERT_ATTRIB_GENERIC13)
+#define VERT_BIT_GENERIC14 (1 << VERT_ATTRIB_GENERIC14)
+#define VERT_BIT_GENERIC15 (1 << VERT_ATTRIB_GENERIC15)
+
+#define VERT_BIT_TEX(u) (1 << (VERT_ATTRIB_TEX0 + (u)))
+#define VERT_BIT_GENERIC(g) (1 << (VERT_ATTRIB_GENERIC0 + (g)))
+/*@}*/
+
+
+/**
+ * Indexes for vertex program result attributes
+ */
+typedef enum
+{
+ VERT_RESULT_HPOS = 0,
+ VERT_RESULT_COL0 = 1,
+ VERT_RESULT_COL1 = 2,
+ VERT_RESULT_FOGC = 3,
+ VERT_RESULT_TEX0 = 4,
+ VERT_RESULT_TEX1 = 5,
+ VERT_RESULT_TEX2 = 6,
+ VERT_RESULT_TEX3 = 7,
+ VERT_RESULT_TEX4 = 8,
+ VERT_RESULT_TEX5 = 9,
+ VERT_RESULT_TEX6 = 10,
+ VERT_RESULT_TEX7 = 11,
+ VERT_RESULT_PSIZ = 12,
+ VERT_RESULT_BFC0 = 13,
+ VERT_RESULT_BFC1 = 14,
+ VERT_RESULT_EDGE = 15,
+ VERT_RESULT_VAR0 = 16, /**< shader varying */
+ VERT_RESULT_MAX = (VERT_RESULT_VAR0 + MAX_VARYING)
+} gl_vert_result;
+
+
+/*********************************************/
+
+/**
+ * Indexes for geometry program attributes.
+ */
+typedef enum
+{
+ GEOM_ATTRIB_POSITION = 0,
+ GEOM_ATTRIB_COLOR0 = 1,
+ GEOM_ATTRIB_COLOR1 = 2,
+ GEOM_ATTRIB_SECONDARY_COLOR0 = 3,
+ GEOM_ATTRIB_SECONDARY_COLOR1 = 4,
+ GEOM_ATTRIB_FOG_FRAG_COORD = 5,
+ GEOM_ATTRIB_POINT_SIZE = 6,
+ GEOM_ATTRIB_CLIP_VERTEX = 7,
+ GEOM_ATTRIB_PRIMITIVE_ID = 8,
+ GEOM_ATTRIB_TEX_COORD = 9,
+
+ GEOM_ATTRIB_VAR0 = 16,
+ GEOM_ATTRIB_MAX = (GEOM_ATTRIB_VAR0 + MAX_VARYING)
+} gl_geom_attrib;
+
+/**
+ * Bitflags for geometry attributes.
+ * These are used in bitfields in many places.
+ */
+/*@{*/
+#define GEOM_BIT_COLOR0 (1 << GEOM_ATTRIB_COLOR0)
+#define GEOM_BIT_COLOR1 (1 << GEOM_ATTRIB_COLOR1)
+#define GEOM_BIT_SCOLOR0 (1 << GEOM_ATTRIB_SECONDARY_COLOR0)
+#define GEOM_BIT_SCOLOR1 (1 << GEOM_ATTRIB_SECONDARY_COLOR1)
+#define GEOM_BIT_TEX_COORD (1 << GEOM_ATTRIB_TEX_COORD)
+#define GEOM_BIT_FOG_COORD (1 << GEOM_ATTRIB_FOG_FRAG_COORD)
+#define GEOM_BIT_POSITION (1 << GEOM_ATTRIB_POSITION)
+#define GEOM_BIT_POINT_SIDE (1 << GEOM_ATTRIB_POINT_SIZE)
+#define GEOM_BIT_CLIP_VERTEX (1 << GEOM_ATTRIB_CLIP_VERTEX)
+#define GEOM_BIT_PRIM_ID (1 << GEOM_ATTRIB_PRIMITIVE_ID)
+#define GEOM_BIT_VAR0 (1 << GEOM_ATTRIB_VAR0)
+
+#define GEOM_BIT_VAR(g) (1 << (GEOM_BIT_VAR0 + (g)))
+/*@}*/
+
+
+/**
+ * Indexes for geometry program result attributes
+ */
+typedef enum
+{
+ GEOM_RESULT_POS = 0,
+ GEOM_RESULT_COL0 = 1,
+ GEOM_RESULT_COL1 = 2,
+ GEOM_RESULT_SCOL0 = 3,
+ GEOM_RESULT_SCOL1 = 4,
+ GEOM_RESULT_FOGC = 5,
+ GEOM_RESULT_TEX0 = 6,
+ GEOM_RESULT_TEX1 = 7,
+ GEOM_RESULT_TEX2 = 8,
+ GEOM_RESULT_TEX3 = 9,
+ GEOM_RESULT_TEX4 = 10,
+ GEOM_RESULT_TEX5 = 11,
+ GEOM_RESULT_TEX6 = 12,
+ GEOM_RESULT_TEX7 = 13,
+ GEOM_RESULT_PSIZ = 14,
+ GEOM_RESULT_CLPV = 15,
+ GEOM_RESULT_PRID = 16,
+ GEOM_RESULT_LAYR = 17,
+ GEOM_RESULT_VAR0 = 18, /**< shader varying, should really be 16 */
+ /* ### we need to -2 because var0 is 18 instead 16 like in the others */
+ GEOM_RESULT_MAX = (GEOM_RESULT_VAR0 + MAX_VARYING - 2)
+} gl_geom_result;
+
+
+/**
+ * Indexes for fragment program input attributes.
+ */
+typedef enum
+{
+ FRAG_ATTRIB_WPOS = 0,
+ FRAG_ATTRIB_COL0 = 1,
+ FRAG_ATTRIB_COL1 = 2,
+ FRAG_ATTRIB_FOGC = 3,
+ FRAG_ATTRIB_TEX0 = 4,
+ FRAG_ATTRIB_TEX1 = 5,
+ FRAG_ATTRIB_TEX2 = 6,
+ FRAG_ATTRIB_TEX3 = 7,
+ FRAG_ATTRIB_TEX4 = 8,
+ FRAG_ATTRIB_TEX5 = 9,
+ FRAG_ATTRIB_TEX6 = 10,
+ FRAG_ATTRIB_TEX7 = 11,
+ FRAG_ATTRIB_FACE = 12, /**< front/back face */
+ FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */
+ FRAG_ATTRIB_VAR0 = 14, /**< shader varying */
+ FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
+} gl_frag_attrib;
+
+/**
+ * Bitflags for fragment program input attributes.
+ */
+/*@{*/
+#define FRAG_BIT_WPOS (1 << FRAG_ATTRIB_WPOS)
+#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0)
+#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1)
+#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC)
+#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE)
+#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC)
+#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0)
+#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1)
+#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2)
+#define FRAG_BIT_TEX3 (1 << FRAG_ATTRIB_TEX3)
+#define FRAG_BIT_TEX4 (1 << FRAG_ATTRIB_TEX4)
+#define FRAG_BIT_TEX5 (1 << FRAG_ATTRIB_TEX5)
+#define FRAG_BIT_TEX6 (1 << FRAG_ATTRIB_TEX6)
+#define FRAG_BIT_TEX7 (1 << FRAG_ATTRIB_TEX7)
+#define FRAG_BIT_VAR0 (1 << FRAG_ATTRIB_VAR0)
+
+#define FRAG_BIT_TEX(U) (FRAG_BIT_TEX0 << (U))
+#define FRAG_BIT_VAR(V) (FRAG_BIT_VAR0 << (V))
+
+#define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0| \
+ FRAG_BIT_TEX1| \
+ FRAG_BIT_TEX2| \
+ FRAG_BIT_TEX3| \
+ FRAG_BIT_TEX4| \
+ FRAG_BIT_TEX5| \
+ FRAG_BIT_TEX6| \
+ FRAG_BIT_TEX7)
+/*@}*/
+
+
+/**
+ * Fragment program results
+ */
+typedef enum
+{
+ FRAG_RESULT_DEPTH = 0,
+ FRAG_RESULT_STENCIL = 1,
+ FRAG_RESULT_COLOR = 2,
+ FRAG_RESULT_DATA0 = 3,
+ FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
+} gl_frag_result;
+
+
+/**
+ * Indexes for all renderbuffers
+ */
+typedef enum
+{
+ /* the four standard color buffers */
+ BUFFER_FRONT_LEFT,
+ BUFFER_BACK_LEFT,
+ BUFFER_FRONT_RIGHT,
+ BUFFER_BACK_RIGHT,
+ BUFFER_DEPTH,
+ BUFFER_STENCIL,
+ BUFFER_ACCUM,
+ /* optional aux buffer */
+ BUFFER_AUX0,
+ /* generic renderbuffers */
+ BUFFER_COLOR0,
+ BUFFER_COLOR1,
+ BUFFER_COLOR2,
+ BUFFER_COLOR3,
+ BUFFER_COLOR4,
+ BUFFER_COLOR5,
+ BUFFER_COLOR6,
+ BUFFER_COLOR7,
+ BUFFER_COUNT
+} gl_buffer_index;
+
+/**
+ * Bit flags for all renderbuffers
+ */
+#define BUFFER_BIT_FRONT_LEFT (1 << BUFFER_FRONT_LEFT)
+#define BUFFER_BIT_BACK_LEFT (1 << BUFFER_BACK_LEFT)
+#define BUFFER_BIT_FRONT_RIGHT (1 << BUFFER_FRONT_RIGHT)
+#define BUFFER_BIT_BACK_RIGHT (1 << BUFFER_BACK_RIGHT)
+#define BUFFER_BIT_AUX0 (1 << BUFFER_AUX0)
+#define BUFFER_BIT_AUX1 (1 << BUFFER_AUX1)
+#define BUFFER_BIT_AUX2 (1 << BUFFER_AUX2)
+#define BUFFER_BIT_AUX3 (1 << BUFFER_AUX3)
+#define BUFFER_BIT_DEPTH (1 << BUFFER_DEPTH)
+#define BUFFER_BIT_STENCIL (1 << BUFFER_STENCIL)
+#define BUFFER_BIT_ACCUM (1 << BUFFER_ACCUM)
+#define BUFFER_BIT_COLOR0 (1 << BUFFER_COLOR0)
+#define BUFFER_BIT_COLOR1 (1 << BUFFER_COLOR1)
+#define BUFFER_BIT_COLOR2 (1 << BUFFER_COLOR2)
+#define BUFFER_BIT_COLOR3 (1 << BUFFER_COLOR3)
+#define BUFFER_BIT_COLOR4 (1 << BUFFER_COLOR4)
+#define BUFFER_BIT_COLOR5 (1 << BUFFER_COLOR5)
+#define BUFFER_BIT_COLOR6 (1 << BUFFER_COLOR6)
+#define BUFFER_BIT_COLOR7 (1 << BUFFER_COLOR7)
+
+/**
+ * Mask of all the color buffer bits (but not accum).
+ */
+#define BUFFER_BITS_COLOR (BUFFER_BIT_FRONT_LEFT | \
+ BUFFER_BIT_BACK_LEFT | \
+ BUFFER_BIT_FRONT_RIGHT | \
+ BUFFER_BIT_BACK_RIGHT | \
+ BUFFER_BIT_AUX0 | \
+ BUFFER_BIT_COLOR0 | \
+ BUFFER_BIT_COLOR1 | \
+ BUFFER_BIT_COLOR2 | \
+ BUFFER_BIT_COLOR3 | \
+ BUFFER_BIT_COLOR4 | \
+ BUFFER_BIT_COLOR5 | \
+ BUFFER_BIT_COLOR6 | \
+ BUFFER_BIT_COLOR7)
+
+
+/**
+ * Framebuffer configuration (aka visual / pixelformat)
+ * Note: some of these fields should be boolean, but it appears that
+ * code in drivers/dri/common/util.c requires int-sized fields.
+ */
+struct gl_config
+{
+ GLboolean rgbMode;
+ GLboolean floatMode;
+ GLboolean colorIndexMode; /* XXX is this used anywhere? */
+ GLuint doubleBufferMode;
+ GLuint stereoMode;
+
+ GLboolean haveAccumBuffer;
+ GLboolean haveDepthBuffer;
+ GLboolean haveStencilBuffer;
+
+ GLint redBits, greenBits, blueBits, alphaBits; /* bits per comp */
+ GLuint redMask, greenMask, blueMask, alphaMask;
+ GLint rgbBits; /* total bits for rgb */
+ GLint indexBits; /* total bits for colorindex */
+
+ GLint accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits;
+ GLint depthBits;
+ GLint stencilBits;
+
+ GLint numAuxBuffers;
+
+ GLint level;
+
+ /* EXT_visual_rating / GLX 1.2 */
+ GLint visualRating;
+
+ /* EXT_visual_info / GLX 1.2 */
+ GLint transparentPixel;
+ /* colors are floats scaled to ints */
+ GLint transparentRed, transparentGreen, transparentBlue, transparentAlpha;
+ GLint transparentIndex;
+
+ /* ARB_multisample / SGIS_multisample */
+ GLint sampleBuffers;
+ GLint samples;
+
+ /* SGIX_pbuffer / GLX 1.3 */
+ GLint maxPbufferWidth;
+ GLint maxPbufferHeight;
+ GLint maxPbufferPixels;
+ GLint optimalPbufferWidth; /* Only for SGIX_pbuffer. */
+ GLint optimalPbufferHeight; /* Only for SGIX_pbuffer. */
+
+ /* OML_swap_method */
+ GLint swapMethod;
+
+ /* EXT_texture_from_pixmap */
+ GLint bindToTextureRgb;
+ GLint bindToTextureRgba;
+ GLint bindToMipmapTexture;
+ GLint bindToTextureTargets;
+ GLint yInverted;
+
+ /* EXT_framebuffer_sRGB */
+ GLint sRGBCapable;
+};
+
+
+/**
+ * Data structure for color tables
+ */
+struct gl_color_table
+{
+ GLenum InternalFormat; /**< The user-specified format */
+ GLenum _BaseFormat; /**< GL_ALPHA, GL_RGBA, GL_RGB, etc */
+ GLuint Size; /**< number of entries in table */
+ GLfloat *TableF; /**< Color table, floating point values */
+ GLubyte *TableUB; /**< Color table, ubyte values */
+ GLubyte RedSize;
+ GLubyte GreenSize;
+ GLubyte BlueSize;
+ GLubyte AlphaSize;
+ GLubyte LuminanceSize;
+ GLubyte IntensitySize;
+};
+
+
+/**
+ * \name Bit flags used for updating material values.
+ */
+/*@{*/
+#define MAT_ATTRIB_FRONT_AMBIENT 0
+#define MAT_ATTRIB_BACK_AMBIENT 1
+#define MAT_ATTRIB_FRONT_DIFFUSE 2
+#define MAT_ATTRIB_BACK_DIFFUSE 3
+#define MAT_ATTRIB_FRONT_SPECULAR 4
+#define MAT_ATTRIB_BACK_SPECULAR 5
+#define MAT_ATTRIB_FRONT_EMISSION 6
+#define MAT_ATTRIB_BACK_EMISSION 7
+#define MAT_ATTRIB_FRONT_SHININESS 8
+#define MAT_ATTRIB_BACK_SHININESS 9
+#define MAT_ATTRIB_FRONT_INDEXES 10
+#define MAT_ATTRIB_BACK_INDEXES 11
+#define MAT_ATTRIB_MAX 12
+
+#define MAT_ATTRIB_AMBIENT(f) (MAT_ATTRIB_FRONT_AMBIENT+(f))
+#define MAT_ATTRIB_DIFFUSE(f) (MAT_ATTRIB_FRONT_DIFFUSE+(f))
+#define MAT_ATTRIB_SPECULAR(f) (MAT_ATTRIB_FRONT_SPECULAR+(f))
+#define MAT_ATTRIB_EMISSION(f) (MAT_ATTRIB_FRONT_EMISSION+(f))
+#define MAT_ATTRIB_SHININESS(f)(MAT_ATTRIB_FRONT_SHININESS+(f))
+#define MAT_ATTRIB_INDEXES(f) (MAT_ATTRIB_FRONT_INDEXES+(f))
+
+#define MAT_INDEX_AMBIENT 0
+#define MAT_INDEX_DIFFUSE 1
+#define MAT_INDEX_SPECULAR 2
+
+#define MAT_BIT_FRONT_AMBIENT (1<<MAT_ATTRIB_FRONT_AMBIENT)
+#define MAT_BIT_BACK_AMBIENT (1<<MAT_ATTRIB_BACK_AMBIENT)
+#define MAT_BIT_FRONT_DIFFUSE (1<<MAT_ATTRIB_FRONT_DIFFUSE)
+#define MAT_BIT_BACK_DIFFUSE (1<<MAT_ATTRIB_BACK_DIFFUSE)
+#define MAT_BIT_FRONT_SPECULAR (1<<MAT_ATTRIB_FRONT_SPECULAR)
+#define MAT_BIT_BACK_SPECULAR (1<<MAT_ATTRIB_BACK_SPECULAR)
+#define MAT_BIT_FRONT_EMISSION (1<<MAT_ATTRIB_FRONT_EMISSION)
+#define MAT_BIT_BACK_EMISSION (1<<MAT_ATTRIB_BACK_EMISSION)
+#define MAT_BIT_FRONT_SHININESS (1<<MAT_ATTRIB_FRONT_SHININESS)
+#define MAT_BIT_BACK_SHININESS (1<<MAT_ATTRIB_BACK_SHININESS)
+#define MAT_BIT_FRONT_INDEXES (1<<MAT_ATTRIB_FRONT_INDEXES)
+#define MAT_BIT_BACK_INDEXES (1<<MAT_ATTRIB_BACK_INDEXES)
+
+
+#define FRONT_MATERIAL_BITS (MAT_BIT_FRONT_EMISSION | \
+ MAT_BIT_FRONT_AMBIENT | \
+ MAT_BIT_FRONT_DIFFUSE | \
+ MAT_BIT_FRONT_SPECULAR | \
+ MAT_BIT_FRONT_SHININESS | \
+ MAT_BIT_FRONT_INDEXES)
+
+#define BACK_MATERIAL_BITS (MAT_BIT_BACK_EMISSION | \
+ MAT_BIT_BACK_AMBIENT | \
+ MAT_BIT_BACK_DIFFUSE | \
+ MAT_BIT_BACK_SPECULAR | \
+ MAT_BIT_BACK_SHININESS | \
+ MAT_BIT_BACK_INDEXES)
+
+#define ALL_MATERIAL_BITS (FRONT_MATERIAL_BITS | BACK_MATERIAL_BITS)
+/*@}*/
+
+
+#define EXP_TABLE_SIZE 512 /**< Specular exponent lookup table sizes */
+#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
+
+/**
+ * Material shininess lookup table.
+ */
+struct gl_shine_tab
+{
+ struct gl_shine_tab *next, *prev;
+ GLfloat tab[SHINE_TABLE_SIZE+1];
+ GLfloat shininess;
+ GLuint refcount;
+};
+
+
+/**
+ * Light source state.
+ */
+struct gl_light
+{
+ struct gl_light *next; /**< double linked list with sentinel */
+ struct gl_light *prev;
+
+ GLfloat Ambient[4]; /**< ambient color */
+ GLfloat Diffuse[4]; /**< diffuse color */
+ GLfloat Specular[4]; /**< specular color */
+ GLfloat EyePosition[4]; /**< position in eye coordinates */
+ GLfloat SpotDirection[4]; /**< spotlight direction in eye coordinates */
+ GLfloat SpotExponent;
+ GLfloat SpotCutoff; /**< in degrees */
+ GLfloat _CosCutoffNeg; /**< = cos(SpotCutoff) */
+ GLfloat _CosCutoff; /**< = MAX(0, cos(SpotCutoff)) */
+ GLfloat ConstantAttenuation;
+ GLfloat LinearAttenuation;
+ GLfloat QuadraticAttenuation;
+ GLboolean Enabled; /**< On/off flag */
+
+ /**
+ * \name Derived fields
+ */
+ /*@{*/
+ GLbitfield _Flags; /**< State */
+
+ GLfloat _Position[4]; /**< position in eye/obj coordinates */
+ GLfloat _VP_inf_norm[3]; /**< Norm direction to infinite light */
+ GLfloat _h_inf_norm[3]; /**< Norm( _VP_inf_norm + <0,0,1> ) */
+ GLfloat _NormSpotDirection[4]; /**< normalized spotlight direction */
+ GLfloat _VP_inf_spot_attenuation;
+
+ GLfloat _SpotExpTable[EXP_TABLE_SIZE][2]; /**< to replace a pow() call */
+ GLfloat _MatAmbient[2][3]; /**< material ambient * light ambient */
+ GLfloat _MatDiffuse[2][3]; /**< material diffuse * light diffuse */
+ GLfloat _MatSpecular[2][3]; /**< material spec * light specular */
+ GLfloat _dli; /**< CI diffuse light intensity */
+ GLfloat _sli; /**< CI specular light intensity */
+ /*@}*/
+};
+
+
+/**
+ * Light model state.
+ */
+struct gl_lightmodel
+{
+ GLfloat Ambient[4]; /**< ambient color */
+ GLboolean LocalViewer; /**< Local (or infinite) view point? */
+ GLboolean TwoSide; /**< Two (or one) sided lighting? */
+ GLenum ColorControl; /**< either GL_SINGLE_COLOR
+ * or GL_SEPARATE_SPECULAR_COLOR */
+};
+
+
+/**
+ * Material state.
+ */
+struct gl_material
+{
+ GLfloat Attrib[MAT_ATTRIB_MAX][4];
+};
+
+
+/**
+ * Accumulation buffer attribute group (GL_ACCUM_BUFFER_BIT)
+ */
+struct gl_accum_attrib
+{
+ GLfloat ClearColor[4]; /**< Accumulation buffer clear color */
+};
+
+
+/**
+ * Color buffer attribute group (GL_COLOR_BUFFER_BIT).
+ */
+struct gl_colorbuffer_attrib
+{
+ GLuint ClearIndex; /**< Index to use for glClear */
+ GLclampf ClearColor[4]; /**< Color to use for glClear */
+
+ GLuint IndexMask; /**< Color index write mask */
+ GLubyte ColorMask[MAX_DRAW_BUFFERS][4];/**< Each flag is 0xff or 0x0 */
+
+ GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */
+
+ /**
+ * \name alpha testing
+ */
+ /*@{*/
+ GLboolean AlphaEnabled; /**< Alpha test enabled flag */
+ GLenum AlphaFunc; /**< Alpha test function */
+ GLclampf AlphaRef; /**< Alpha reference value */
+ /*@}*/
+
+ /**
+ * \name Blending
+ */
+ /*@{*/
+ GLbitfield BlendEnabled; /**< Per-buffer blend enable flags */
+ GLfloat BlendColor[4]; /**< Blending color */
+ struct
+ {
+ GLenum SrcRGB; /**< RGB blend source term */
+ GLenum DstRGB; /**< RGB blend dest term */
+ GLenum SrcA; /**< Alpha blend source term */
+ GLenum DstA; /**< Alpha blend dest term */
+ GLenum EquationRGB; /**< GL_ADD, GL_SUBTRACT, etc. */
+ GLenum EquationA; /**< GL_ADD, GL_SUBTRACT, etc. */
+ } Blend[MAX_DRAW_BUFFERS];
+ /** Are the blend func terms currently different for each buffer/target? */
+ GLboolean _BlendFuncPerBuffer;
+ /** Are the blend equations currently different for each buffer/target? */
+ GLboolean _BlendEquationPerBuffer;
+ /*@}*/
+
+ /**
+ * \name Logic op
+ */
+ /*@{*/
+ GLenum LogicOp; /**< Logic operator */
+ GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */
+ GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */
+ GLboolean _LogicOpEnabled; /**< RGBA logic op + EXT_blend_logic_op enabled flag */
+ /*@}*/
+
+ GLboolean DitherFlag; /**< Dither enable flag */
+
+ GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+ GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+
+ GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */
+};
+
+
+/**
+ * Current attribute group (GL_CURRENT_BIT).
+ */
+struct gl_current_attrib
+{
+ /**
+ * \name Current vertex attributes.
+ * \note Values are valid only after FLUSH_VERTICES has been called.
+ * \note Index and Edgeflag current values are stored as floats in the
+ * SIX and SEVEN attribute slots.
+ */
+ GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
+
+ /**
+ * \name Current raster position attributes (always valid).
+ * \note This set of attributes is very similar to the SWvertex struct.
+ */
+ /*@{*/
+ GLfloat RasterPos[4];
+ GLfloat RasterDistance;
+ GLfloat RasterColor[4];
+ GLfloat RasterSecondaryColor[4];
+ GLfloat RasterTexCoords[MAX_TEXTURE_COORD_UNITS][4];
+ GLboolean RasterPosValid;
+ /*@}*/
+};
+
+
+/**
+ * Depth buffer attribute group (GL_DEPTH_BUFFER_BIT).
+ */
+struct gl_depthbuffer_attrib
+{
+ GLenum Func; /**< Function for depth buffer compare */
+ GLclampd Clear; /**< Value to clear depth buffer to */
+ GLboolean Test; /**< Depth buffering enabled flag */
+ GLboolean Mask; /**< Depth buffer writable? */
+ GLboolean BoundsTest; /**< GL_EXT_depth_bounds_test */
+ GLfloat BoundsMin, BoundsMax;/**< GL_EXT_depth_bounds_test */
+};
+
+
+/**
+ * Evaluator attribute group (GL_EVAL_BIT).
+ */
+struct gl_eval_attrib
+{
+ /**
+ * \name Enable bits
+ */
+ /*@{*/
+ GLboolean Map1Color4;
+ GLboolean Map1Index;
+ GLboolean Map1Normal;
+ GLboolean Map1TextureCoord1;
+ GLboolean Map1TextureCoord2;
+ GLboolean Map1TextureCoord3;
+ GLboolean Map1TextureCoord4;
+ GLboolean Map1Vertex3;
+ GLboolean Map1Vertex4;
+ GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean Map2Color4;
+ GLboolean Map2Index;
+ GLboolean Map2Normal;
+ GLboolean Map2TextureCoord1;
+ GLboolean Map2TextureCoord2;
+ GLboolean Map2TextureCoord3;
+ GLboolean Map2TextureCoord4;
+ GLboolean Map2Vertex3;
+ GLboolean Map2Vertex4;
+ GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean AutoNormal;
+ /*@}*/
+
+ /**
+ * \name Map Grid endpoints and divisions and calculated du values
+ */
+ /*@{*/
+ GLint MapGrid1un;
+ GLfloat MapGrid1u1, MapGrid1u2, MapGrid1du;
+ GLint MapGrid2un, MapGrid2vn;
+ GLfloat MapGrid2u1, MapGrid2u2, MapGrid2du;
+ GLfloat MapGrid2v1, MapGrid2v2, MapGrid2dv;
+ /*@}*/
+};
+
+
+/**
+ * Fog attribute group (GL_FOG_BIT).
+ */
+struct gl_fog_attrib
+{
+ GLboolean Enabled; /**< Fog enabled flag */
+ GLfloat Color[4]; /**< Fog color */
+ GLfloat Density; /**< Density >= 0.0 */
+ GLfloat Start; /**< Start distance in eye coords */
+ GLfloat End; /**< End distance in eye coords */
+ GLfloat Index; /**< Fog index */
+ GLenum Mode; /**< Fog mode */
+ GLboolean ColorSumEnabled;
+ GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */
+ GLfloat _Scale; /**< (End == Start) ? 1.0 : 1.0 / (End - Start) */
+};
+
+
+/**
+ * \brief Layout qualifiers for gl_FragDepth.
+ *
+ * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with
+ * a layout qualifier.
+ *
+ * \see enum ir_depth_layout
+ */
+enum gl_frag_depth_layout {
+ FRAG_DEPTH_LAYOUT_NONE, /**< No layout is specified. */
+ FRAG_DEPTH_LAYOUT_ANY,
+ FRAG_DEPTH_LAYOUT_GREATER,
+ FRAG_DEPTH_LAYOUT_LESS,
+ FRAG_DEPTH_LAYOUT_UNCHANGED
+};
+
+
+/**
+ * Hint attribute group (GL_HINT_BIT).
+ *
+ * Values are always one of GL_FASTEST, GL_NICEST, or GL_DONT_CARE.
+ */
+struct gl_hint_attrib
+{
+ GLenum PerspectiveCorrection;
+ GLenum PointSmooth;
+ GLenum LineSmooth;
+ GLenum PolygonSmooth;
+ GLenum Fog;
+ GLenum ClipVolumeClipping; /**< GL_EXT_clip_volume_hint */
+ GLenum TextureCompression; /**< GL_ARB_texture_compression */
+ GLenum GenerateMipmap; /**< GL_SGIS_generate_mipmap */
+ GLenum FragmentShaderDerivative; /**< GL_ARB_fragment_shader */
+};
+
+/**
+ * Light state flags.
+ */
+/*@{*/
+#define LIGHT_SPOT 0x1
+#define LIGHT_LOCAL_VIEWER 0x2
+#define LIGHT_POSITIONAL 0x4
+#define LIGHT_NEED_VERTICES (LIGHT_POSITIONAL|LIGHT_LOCAL_VIEWER)
+/*@}*/
+
+
+/**
+ * Lighting attribute group (GL_LIGHT_BIT).
+ */
+struct gl_light_attrib
+{
+ struct gl_light Light[MAX_LIGHTS]; /**< Array of light sources */
+ struct gl_lightmodel Model; /**< Lighting model */
+
+ /**
+ * Must flush FLUSH_VERTICES before referencing:
+ */
+ /*@{*/
+ struct gl_material Material; /**< Includes front & back values */
+ /*@}*/
+
+ GLboolean Enabled; /**< Lighting enabled flag */
+ GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */
+ GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */
+ GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */
+ GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */
+ GLbitfield ColorMaterialBitmask; /**< bitmask formed from Face and Mode */
+ GLboolean ColorMaterialEnabled;
+ GLenum ClampVertexColor;
+
+ struct gl_light EnabledList; /**< List sentinel */
+
+ /**
+ * Derived state for optimizations:
+ */
+ /*@{*/
+ GLboolean _NeedEyeCoords;
+ GLboolean _NeedVertices; /**< Use fast shader? */
+ GLbitfield _Flags; /**< LIGHT_* flags, see above */
+ GLfloat _BaseColor[2][3];
+ /*@}*/
+};
+
+
+/**
+ * Line attribute group (GL_LINE_BIT).
+ */
+struct gl_line_attrib
+{
+ GLboolean SmoothFlag; /**< GL_LINE_SMOOTH enabled? */
+ GLboolean StippleFlag; /**< GL_LINE_STIPPLE enabled? */
+ GLushort StipplePattern; /**< Stipple pattern */
+ GLint StippleFactor; /**< Stipple repeat factor */
+ GLfloat Width; /**< Line width */
+};
+
+
+/**
+ * Display list attribute group (GL_LIST_BIT).
+ */
+struct gl_list_attrib
+{
+ GLuint ListBase;
+};
+
+
+/**
+ * Multisample attribute group (GL_MULTISAMPLE_BIT).
+ */
+struct gl_multisample_attrib
+{
+ GLboolean Enabled;
+ GLboolean _Enabled; /**< true if Enabled and multisample buffer */
+ GLboolean SampleAlphaToCoverage;
+ GLboolean SampleAlphaToOne;
+ GLboolean SampleCoverage;
+ GLfloat SampleCoverageValue;
+ GLboolean SampleCoverageInvert;
+};
+
+
+/**
+ * A pixelmap (see glPixelMap)
+ */
+struct gl_pixelmap
+{
+ GLint Size;
+ GLfloat Map[MAX_PIXEL_MAP_TABLE];
+ GLubyte Map8[MAX_PIXEL_MAP_TABLE]; /**< converted to 8-bit color */
+};
+
+
+/**
+ * Collection of all pixelmaps
+ */
+struct gl_pixelmaps
+{
+ struct gl_pixelmap RtoR; /**< i.e. GL_PIXEL_MAP_R_TO_R */
+ struct gl_pixelmap GtoG;
+ struct gl_pixelmap BtoB;
+ struct gl_pixelmap AtoA;
+ struct gl_pixelmap ItoR;
+ struct gl_pixelmap ItoG;
+ struct gl_pixelmap ItoB;
+ struct gl_pixelmap ItoA;
+ struct gl_pixelmap ItoI;
+ struct gl_pixelmap StoS;
+};
+
+
+/**
+ * Pixel attribute group (GL_PIXEL_MODE_BIT).
+ */
+struct gl_pixel_attrib
+{
+ GLenum ReadBuffer; /**< source buffer for glRead/CopyPixels() */
+
+ /*--- Begin Pixel Transfer State ---*/
+ /* Fields are in the order in which they're applied... */
+
+ /** Scale & Bias (index shift, offset) */
+ /*@{*/
+ GLfloat RedBias, RedScale;
+ GLfloat GreenBias, GreenScale;
+ GLfloat BlueBias, BlueScale;
+ GLfloat AlphaBias, AlphaScale;
+ GLfloat DepthBias, DepthScale;
+ GLint IndexShift, IndexOffset;
+ /*@}*/
+
+ /* Pixel Maps */
+ /* Note: actual pixel maps are not part of this attrib group */
+ GLboolean MapColorFlag;
+ GLboolean MapStencilFlag;
+
+ /*--- End Pixel Transfer State ---*/
+
+ /** glPixelZoom */
+ GLfloat ZoomX, ZoomY;
+};
+
+
+/**
+ * Point attribute group (GL_POINT_BIT).
+ */
+struct gl_point_attrib
+{
+ GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */
+ GLfloat Size; /**< User-specified point size */
+ GLfloat Params[3]; /**< GL_EXT_point_parameters */
+ GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */
+ GLfloat Threshold; /**< GL_EXT_point_parameters */
+ GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */
+ GLboolean PointSprite; /**< GL_NV/ARB_point_sprite */
+ GLboolean CoordReplace[MAX_TEXTURE_COORD_UNITS]; /**< GL_ARB_point_sprite*/
+ GLenum SpriteRMode; /**< GL_NV_point_sprite (only!) */
+ GLenum SpriteOrigin; /**< GL_ARB_point_sprite */
+};
+
+
+/**
+ * Polygon attribute group (GL_POLYGON_BIT).
+ */
+struct gl_polygon_attrib
+{
+ GLenum FrontFace; /**< Either GL_CW or GL_CCW */
+ GLenum FrontMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
+ GLenum BackMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
+ GLboolean _FrontBit; /**< 0=GL_CCW, 1=GL_CW */
+ GLboolean CullFlag; /**< Culling on/off flag */
+ GLboolean SmoothFlag; /**< True if GL_POLYGON_SMOOTH is enabled */
+ GLboolean StippleFlag; /**< True if GL_POLYGON_STIPPLE is enabled */
+ GLenum CullFaceMode; /**< Culling mode GL_FRONT or GL_BACK */
+ GLfloat OffsetFactor; /**< Polygon offset factor, from user */
+ GLfloat OffsetUnits; /**< Polygon offset units, from user */
+ GLboolean OffsetPoint; /**< Offset in GL_POINT mode */
+ GLboolean OffsetLine; /**< Offset in GL_LINE mode */
+ GLboolean OffsetFill; /**< Offset in GL_FILL mode */
+};
+
+
+/**
+ * Scissor attributes (GL_SCISSOR_BIT).
+ */
+struct gl_scissor_attrib
+{
+ GLboolean Enabled; /**< Scissor test enabled? */
+ GLint X, Y; /**< Lower left corner of box */
+ GLsizei Width, Height; /**< Size of box */
+};
+
+
+/**
+ * Stencil attribute group (GL_STENCIL_BUFFER_BIT).
+ *
+ * Three sets of stencil data are tracked so that OpenGL 2.0,
+ * GL_EXT_stencil_two_side, and GL_ATI_separate_stencil can all be supported
+ * simultaneously. In each of the stencil state arrays, element 0 corresponds
+ * to GL_FRONT. Element 1 corresponds to the OpenGL 2.0 /
+ * GL_ATI_separate_stencil GL_BACK state. Element 2 corresponds to the
+ * GL_EXT_stencil_two_side GL_BACK state.
+ *
+ * The derived value \c _BackFace is either 1 or 2 depending on whether or
+ * not GL_STENCIL_TEST_TWO_SIDE_EXT is enabled.
+ *
+ * The derived value \c _TestTwoSide is set when the front-face and back-face
+ * stencil state are different.
+ */
+struct gl_stencil_attrib
+{
+ GLboolean Enabled; /**< Enabled flag */
+ GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */
+ GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */
+ GLboolean _Enabled; /**< Enabled and stencil buffer present */
+ GLboolean _TestTwoSide;
+ GLubyte _BackFace; /**< Current back stencil state (1 or 2) */
+ GLenum Function[3]; /**< Stencil function */
+ GLenum FailFunc[3]; /**< Fail function */
+ GLenum ZPassFunc[3]; /**< Depth buffer pass function */
+ GLenum ZFailFunc[3]; /**< Depth buffer fail function */
+ GLint Ref[3]; /**< Reference value */
+ GLuint ValueMask[3]; /**< Value mask */
+ GLuint WriteMask[3]; /**< Write mask */
+ GLuint Clear; /**< Clear value */
+};
+
+
+/**
+ * An index for each type of texture object. These correspond to the GL
+ * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
+ * Note: the order is from highest priority to lowest priority.
+ */
+typedef enum
+{
+ TEXTURE_2D_ARRAY_INDEX,
+ TEXTURE_1D_ARRAY_INDEX,
+ TEXTURE_CUBE_INDEX,
+ TEXTURE_3D_INDEX,
+ TEXTURE_RECT_INDEX,
+ TEXTURE_2D_INDEX,
+ TEXTURE_1D_INDEX,
+ NUM_TEXTURE_TARGETS
+} gl_texture_index;
+
+
+/**
+ * Bit flags for each type of texture object
+ * Used for Texture.Unit[]._ReallyEnabled flags.
+ */
+/*@{*/
+#define TEXTURE_2D_ARRAY_BIT (1 << TEXTURE_2D_ARRAY_INDEX)
+#define TEXTURE_1D_ARRAY_BIT (1 << TEXTURE_1D_ARRAY_INDEX)
+#define TEXTURE_CUBE_BIT (1 << TEXTURE_CUBE_INDEX)
+#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX)
+#define TEXTURE_RECT_BIT (1 << TEXTURE_RECT_INDEX)
+#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX)
+#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX)
+/*@}*/
+
+
+/**
+ * TexGenEnabled flags.
+ */
+/*@{*/
+#define S_BIT 1
+#define T_BIT 2
+#define R_BIT 4
+#define Q_BIT 8
+#define STR_BITS (S_BIT | T_BIT | R_BIT)
+/*@}*/
+
+
+/**
+ * Bit flag versions of the corresponding GL_ constants.
+ */
+/*@{*/
+#define TEXGEN_SPHERE_MAP 0x1
+#define TEXGEN_OBJ_LINEAR 0x2
+#define TEXGEN_EYE_LINEAR 0x4
+#define TEXGEN_REFLECTION_MAP_NV 0x8
+#define TEXGEN_NORMAL_MAP_NV 0x10
+
+#define TEXGEN_NEED_NORMALS (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV | \
+ TEXGEN_NORMAL_MAP_NV)
+#define TEXGEN_NEED_EYE_COORD (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV | \
+ TEXGEN_NORMAL_MAP_NV | \
+ TEXGEN_EYE_LINEAR)
+/*@}*/
+
+
+
+/** Tex-gen enabled for texture unit? */
+#define ENABLE_TEXGEN(unit) (1 << (unit))
+
+/** Non-identity texture matrix for texture unit? */
+#define ENABLE_TEXMAT(unit) (1 << (unit))
+
+
+/**
+ * Texel fetch function prototype. We use texel fetch functions to
+ * extract RGBA, color indexes and depth components out of 1D, 2D and 3D
+ * texture images. These functions help to isolate us from the gritty
+ * details of all the various texture image encodings.
+ *
+ * \param texImage texture image.
+ * \param col texel column.
+ * \param row texel row.
+ * \param img texel image level/layer.
+ * \param texelOut output texel (up to 4 GLchans)
+ */
+typedef void (*FetchTexelFuncC)( const struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ GLchan *texelOut );
+
+/**
+ * As above, but returns floats.
+ * Used for depth component images and for upcoming signed/float
+ * texture images.
+ */
+typedef void (*FetchTexelFuncF)( const struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ GLfloat *texelOut );
+
+
+typedef void (*StoreTexelFunc)(struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ const void *texel);
+
+
+/**
+ * Texture image state. Describes the dimensions of a texture image,
+ * the texel format and pointers to Texel Fetch functions.
+ */
+struct gl_texture_image
+{
+ GLint InternalFormat; /**< Internal format as given by the user */
+ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA,
+ * GL_LUMINANCE, GL_LUMINANCE_ALPHA,
+ * GL_INTENSITY, GL_COLOR_INDEX,
+ * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT
+ * only. Used for choosing TexEnv arithmetic.
+ */
+ gl_format TexFormat; /**< The actual texture memory format */
+
+ GLuint Border; /**< 0 or 1 */
+ GLuint Width; /**< = 2^WidthLog2 + 2*Border */
+ GLuint Height; /**< = 2^HeightLog2 + 2*Border */
+ GLuint Depth; /**< = 2^DepthLog2 + 2*Border */
+ GLuint Width2; /**< = Width - 2*Border */
+ GLuint Height2; /**< = Height - 2*Border */
+ GLuint Depth2; /**< = Depth - 2*Border */
+ GLuint WidthLog2; /**< = log2(Width2) */
+ GLuint HeightLog2; /**< = log2(Height2) */
+ GLuint DepthLog2; /**< = log2(Depth2) */
+ GLuint MaxLog2; /**< = MAX(WidthLog2, HeightLog2) */
+ GLfloat WidthScale; /**< used for mipmap LOD computation */
+ GLfloat HeightScale; /**< used for mipmap LOD computation */
+ GLfloat DepthScale; /**< used for mipmap LOD computation */
+ GLboolean IsClientData; /**< Data owned by client? */
+ GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */
+
+ struct gl_texture_object *TexObject; /**< Pointer back to parent object */
+
+ FetchTexelFuncC FetchTexelc; /**< GLchan texel fetch function pointer */
+ FetchTexelFuncF FetchTexelf; /**< Float texel fetch function pointer */
+
+ GLuint RowStride; /**< Padded width in units of texels */
+ GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to
+ each 2D slice in 'Data', in texels */
+ GLvoid *Data; /**< Image data, accessed via FetchTexel() */
+
+ /**
+ * \name For device driver:
+ */
+ /*@{*/
+ void *DriverData; /**< Arbitrary device driver data */
+ /*@}*/
+};
+
+
+/**
+ * Indexes for cube map faces.
+ */
+typedef enum
+{
+ FACE_POS_X = 0,
+ FACE_NEG_X = 1,
+ FACE_POS_Y = 2,
+ FACE_NEG_Y = 3,
+ FACE_POS_Z = 4,
+ FACE_NEG_Z = 5,
+ MAX_FACES = 6
+} gl_face_index;
+
+
+/**
+ * Texture object state. Contains the array of mipmap images, border color,
+ * wrap modes, filter modes, shadow/texcompare state, and the per-texture
+ * color palette.
+ */
+struct gl_texture_object
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLint RefCount; /**< reference count */
+ GLuint Name; /**< the user-visible texture object ID */
+ GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
+ GLfloat Priority; /**< in [0,1] */
+ union {
+ GLfloat f[4];
+ GLuint ui[4];
+ GLint i[4];
+ } BorderColor; /**< Interpreted according to texture format */
+ GLenum WrapS; /**< S-axis texture image wrap mode */
+ GLenum WrapT; /**< T-axis texture image wrap mode */
+ GLenum WrapR; /**< R-axis texture image wrap mode */
+ GLenum MinFilter; /**< minification filter */
+ GLenum MagFilter; /**< magnification filter */
+ GLfloat MinLod; /**< min lambda, OpenGL 1.2 */
+ GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */
+ GLfloat LodBias; /**< OpenGL 1.4 */
+ GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
+ GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
+ GLfloat MaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
+ GLenum CompareMode; /**< GL_ARB_shadow */
+ GLenum CompareFunc; /**< GL_ARB_shadow */
+ GLfloat CompareFailValue; /**< GL_ARB_shadow_ambient */
+ GLenum DepthMode; /**< GL_ARB_depth_texture */
+ GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
+ GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */
+ GLint CropRect[4]; /**< GL_OES_draw_texture */
+ GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
+ GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
+ GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
+ GLboolean _Complete; /**< Is texture object complete? */
+ GLboolean _RenderToTexture; /**< Any rendering to this texture? */
+ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
+ GLenum sRGBDecode; /**< GL_DECODE_EXT or GL_SKIP_DECODE_EXT */
+
+ /** Actual texture images, indexed by [cube face] and [mipmap level] */
+ struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
+
+ /** GL_EXT_paletted_texture */
+ struct gl_color_table Palette;
+
+ /**
+ * \name For device driver.
+ * Note: instead of attaching driver data to this pointer, it's preferable
+ * to instead use this struct as a base class for your own texture object
+ * class. Driver->NewTextureObject() can be used to implement the
+ * allocation.
+ */
+ void *DriverData; /**< Arbitrary device driver data */
+};
+
+
+/** Up to four combiner sources are possible with GL_NV_texture_env_combine4 */
+#define MAX_COMBINER_TERMS 4
+
+
+/**
+ * Texture combine environment state.
+ */
+struct gl_tex_env_combine_state
+{
+ GLenum ModeRGB; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
+ GLenum ModeA; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
+ /** Source terms: GL_PRIMARY_COLOR, GL_TEXTURE, etc */
+ GLenum SourceRGB[MAX_COMBINER_TERMS];
+ GLenum SourceA[MAX_COMBINER_TERMS];
+ /** Source operands: GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, etc */
+ GLenum OperandRGB[MAX_COMBINER_TERMS];
+ GLenum OperandA[MAX_COMBINER_TERMS];
+ GLuint ScaleShiftRGB; /**< 0, 1 or 2 */
+ GLuint ScaleShiftA; /**< 0, 1 or 2 */
+ GLuint _NumArgsRGB; /**< Number of inputs used for the RGB combiner */
+ GLuint _NumArgsA; /**< Number of inputs used for the A combiner */
+};
+
+
+/**
+ * Texture coord generation state.
+ */
+struct gl_texgen
+{
+ GLenum Mode; /**< GL_EYE_LINEAR, GL_SPHERE_MAP, etc */
+ GLbitfield _ModeBit; /**< TEXGEN_x bit corresponding to Mode */
+ GLfloat ObjectPlane[4];
+ GLfloat EyePlane[4];
+};
+
+
+/**
+ * Texture unit state. Contains enable flags, texture environment/function/
+ * combiners, texgen state, pointers to current texture objects and
+ * post-filter color tables.
+ */
+struct gl_texture_unit
+{
+ GLbitfield Enabled; /**< bitmask of TEXTURE_*_BIT flags */
+ GLbitfield _ReallyEnabled; /**< 0 or exactly one of TEXTURE_*_BIT flags */
+
+ GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
+ GLfloat EnvColor[4];
+
+ struct gl_texgen GenS;
+ struct gl_texgen GenT;
+ struct gl_texgen GenR;
+ struct gl_texgen GenQ;
+ GLbitfield TexGenEnabled; /**< Bitwise-OR of [STRQ]_BIT values */
+ GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
+
+ GLfloat LodBias; /**< for biasing mipmap levels */
+ GLenum BumpTarget;
+ GLfloat RotMatrix[4]; /* 2x2 matrix */
+
+ /**
+ * \name GL_EXT_texture_env_combine
+ */
+ struct gl_tex_env_combine_state Combine;
+
+ /**
+ * Derived state based on \c EnvMode and the \c BaseFormat of the
+ * currently enabled texture.
+ */
+ struct gl_tex_env_combine_state _EnvMode;
+
+ /**
+ * Currently enabled combiner state. This will point to either
+ * \c Combine or \c _EnvMode.
+ */
+ struct gl_tex_env_combine_state *_CurrentCombine;
+
+ /** Current texture object pointers */
+ struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
+
+ /** Points to highest priority, complete and enabled texture object */
+ struct gl_texture_object *_Current;
+};
+
+
+/**
+ * Texture attribute group (GL_TEXTURE_BIT).
+ */
+struct gl_texture_attrib
+{
+ GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */
+ struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
+
+ struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
+
+ /** GL_ARB_seamless_cubemap */
+ GLboolean CubeMapSeamless;
+
+ /** GL_EXT_shared_texture_palette */
+ GLboolean SharedPalette;
+ struct gl_color_table Palette;
+
+ /** Texture units/samplers used by vertex or fragment texturing */
+ GLbitfield _EnabledUnits;
+
+ /** Texture coord units/sets used for fragment texturing */
+ GLbitfield _EnabledCoordUnits;
+
+ /** Texture coord units that have texgen enabled */
+ GLbitfield _TexGenEnabled;
+
+ /** Texture coord units that have non-identity matrices */
+ GLbitfield _TexMatEnabled;
+
+ /** Bitwise-OR of all Texture.Unit[i]._GenFlags */
+ GLbitfield _GenFlags;
+};
+
+
+/**
+ * Transformation attribute group (GL_TRANSFORM_BIT).
+ */
+struct gl_transform_attrib
+{
+ GLenum MatrixMode; /**< Matrix mode */
+ GLfloat EyeUserPlane[MAX_CLIP_PLANES][4]; /**< User clip planes */
+ GLfloat _ClipUserPlane[MAX_CLIP_PLANES][4]; /**< derived */
+ GLbitfield ClipPlanesEnabled; /**< on/off bitmask */
+ GLboolean Normalize; /**< Normalize all normals? */
+ GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */
+ GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */
+ GLboolean DepthClamp; /**< GL_ARB_depth_clamp */
+
+ GLfloat CullEyePos[4];
+ GLfloat CullObjPos[4];
+};
+
+
+/**
+ * Viewport attribute group (GL_VIEWPORT_BIT).
+ */
+struct gl_viewport_attrib
+{
+ GLint X, Y; /**< position */
+ GLsizei Width, Height; /**< size */
+ GLfloat Near, Far; /**< Depth buffer range */
+ GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
+};
+
+
+/**
+ * GL_ARB_vertex/pixel_buffer_object buffer object
+ */
+struct gl_buffer_object
+{
+ _glthread_Mutex Mutex;
+ GLint RefCount;
+ GLuint Name;
+ GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */
+ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */
+ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
+ /** Fields describing a mapped buffer */
+ /*@{*/
+ GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */
+ GLvoid *Pointer; /**< User-space address of mapping */
+ GLintptr Offset; /**< Mapped offset */
+ GLsizeiptr Length; /**< Mapped length */
+ /*@}*/
+ GLboolean Written; /**< Ever written to? (for debugging) */
+ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
+};
+
+
+/**
+ * Client pixel packing/unpacking attributes
+ */
+struct gl_pixelstore_attrib
+{
+ GLint Alignment;
+ GLint RowLength;
+ GLint SkipPixels;
+ GLint SkipRows;
+ GLint ImageHeight;
+ GLint SkipImages;
+ GLboolean SwapBytes;
+ GLboolean LsbFirst;
+ GLboolean ClientStorage; /**< GL_APPLE_client_storage */
+ GLboolean Invert; /**< GL_MESA_pack_invert */
+ struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */
+};
+
+
+/**
+ * Client vertex array attributes
+ */
+struct gl_client_array
+{
+ GLint Size; /**< components per element (1,2,3,4) */
+ GLenum Type; /**< datatype: GL_FLOAT, GL_INT, etc */
+ GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */
+ GLsizei Stride; /**< user-specified stride */
+ GLsizei StrideB; /**< actual stride in bytes */
+ const GLubyte *Ptr; /**< Points to array data */
+ GLboolean Enabled; /**< Enabled flag is a boolean */
+ GLboolean Normalized; /**< GL_ARB_vertex_program */
+ GLboolean Integer; /**< Integer-valued? */
+ GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
+ GLuint _ElementSize; /**< size of each element in bytes */
+
+ struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
+ GLuint _MaxElement; /**< max element index into array buffer + 1 */
+};
+
+
+/**
+ * Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object
+ * extension, but a nice encapsulation in any case.
+ */
+struct gl_array_object
+{
+ /** Name of the array object as received from glGenVertexArrayAPPLE. */
+ GLuint Name;
+
+ GLint RefCount;
+ _glthread_Mutex Mutex;
+ GLboolean VBOonly; /**< require all arrays to live in VBOs? */
+
+ /** Conventional vertex arrays */
+ /*@{*/
+ struct gl_client_array Vertex;
+ struct gl_client_array Weight;
+ struct gl_client_array Normal;
+ struct gl_client_array Color;
+ struct gl_client_array SecondaryColor;
+ struct gl_client_array FogCoord;
+ struct gl_client_array Index;
+ struct gl_client_array EdgeFlag;
+ struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS];
+ struct gl_client_array PointSize;
+ /*@}*/
+
+ /**
+ * Generic arrays for vertex programs/shaders.
+ * For NV vertex programs, these attributes alias and take priority
+ * over the conventional attribs above. For ARB vertex programs and
+ * GLSL vertex shaders, these attributes are separate.
+ */
+ struct gl_client_array VertexAttrib[MAX_VERTEX_GENERIC_ATTRIBS];
+
+ /** Mask of _NEW_ARRAY_* values indicating which arrays are enabled */
+ GLbitfield _Enabled;
+
+ /**
+ * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs
+ * we can determine the max legal (in bounds) glDrawElements array index.
+ */
+ GLuint _MaxElement;
+};
+
+
+/**
+ * Vertex array state
+ */
+struct gl_array_attrib
+{
+ /** Currently bound array object. See _mesa_BindVertexArrayAPPLE() */
+ struct gl_array_object *ArrayObj;
+
+ /** The default vertex array object */
+ struct gl_array_object *DefaultArrayObj;
+
+ /** Array objects (GL_ARB/APPLE_vertex_array_object) */
+ struct _mesa_HashTable *Objects;
+
+ GLint ActiveTexture; /**< Client Active Texture */
+ GLuint LockFirst; /**< GL_EXT_compiled_vertex_array */
+ GLuint LockCount; /**< GL_EXT_compiled_vertex_array */
+
+ /** GL 3.1 (slightly different from GL_NV_primitive_restart) */
+ GLboolean PrimitiveRestart;
+ GLuint RestartIndex;
+
+ GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */
+ GLboolean RebindArrays; /**< whether the VBO module should rebind arrays */
+
+ /* GL_ARB_vertex_buffer_object */
+ struct gl_buffer_object *ArrayBufferObj;
+ struct gl_buffer_object *ElementArrayBufferObj;
+};
+
+
+/**
+ * Feedback buffer state
+ */
+struct gl_feedback
+{
+ GLenum Type;
+ GLbitfield _Mask; /**< FB_* bits */
+ GLfloat *Buffer;
+ GLuint BufferSize;
+ GLuint Count;
+};
+
+
+/**
+ * Selection buffer state
+ */
+struct gl_selection
+{
+ GLuint *Buffer; /**< selection buffer */
+ GLuint BufferSize; /**< size of the selection buffer */
+ GLuint BufferCount; /**< number of values in the selection buffer */
+ GLuint Hits; /**< number of records in the selection buffer */
+ GLuint NameStackDepth; /**< name stack depth */
+ GLuint NameStack[MAX_NAME_STACK_DEPTH]; /**< name stack */
+ GLboolean HitFlag; /**< hit flag */
+ GLfloat HitMinZ; /**< minimum hit depth */
+ GLfloat HitMaxZ; /**< maximum hit depth */
+};
+
+
+/**
+ * 1-D Evaluator control points
+ */
+struct gl_1d_map
+{
+ GLuint Order; /**< Number of control points */
+ GLfloat u1, u2, du; /**< u1, u2, 1.0/(u2-u1) */
+ GLfloat *Points; /**< Points to contiguous control points */
+};
+
+
+/**
+ * 2-D Evaluator control points
+ */
+struct gl_2d_map
+{
+ GLuint Uorder; /**< Number of control points in U dimension */
+ GLuint Vorder; /**< Number of control points in V dimension */
+ GLfloat u1, u2, du;
+ GLfloat v1, v2, dv;
+ GLfloat *Points; /**< Points to contiguous control points */
+};
+
+
+/**
+ * All evaluator control point state
+ */
+struct gl_evaluators
+{
+ /**
+ * \name 1-D maps
+ */
+ /*@{*/
+ struct gl_1d_map Map1Vertex3;
+ struct gl_1d_map Map1Vertex4;
+ struct gl_1d_map Map1Index;
+ struct gl_1d_map Map1Color4;
+ struct gl_1d_map Map1Normal;
+ struct gl_1d_map Map1Texture1;
+ struct gl_1d_map Map1Texture2;
+ struct gl_1d_map Map1Texture3;
+ struct gl_1d_map Map1Texture4;
+ struct gl_1d_map Map1Attrib[16]; /**< GL_NV_vertex_program */
+ /*@}*/
+
+ /**
+ * \name 2-D maps
+ */
+ /*@{*/
+ struct gl_2d_map Map2Vertex3;
+ struct gl_2d_map Map2Vertex4;
+ struct gl_2d_map Map2Index;
+ struct gl_2d_map Map2Color4;
+ struct gl_2d_map Map2Normal;
+ struct gl_2d_map Map2Texture1;
+ struct gl_2d_map Map2Texture2;
+ struct gl_2d_map Map2Texture3;
+ struct gl_2d_map Map2Texture4;
+ struct gl_2d_map Map2Attrib[16]; /**< GL_NV_vertex_program */
+ /*@}*/
+};
+
+
+/**
+ * Names of the various vertex/fragment program register files, etc.
+ *
+ * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
+ * All values should fit in a 4-bit field.
+ *
+ * NOTE: PROGRAM_ENV_PARAM, PROGRAM_STATE_VAR, PROGRAM_NAMED_PARAM,
+ * PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be considered to
+ * be "uniform" variables since they can only be set outside glBegin/End.
+ * They're also all stored in the same Parameters array.
+ */
+typedef enum
+{
+ PROGRAM_TEMPORARY, /**< machine->Temporary[] */
+ PROGRAM_INPUT, /**< machine->Inputs[] */
+ PROGRAM_OUTPUT, /**< machine->Outputs[] */
+ PROGRAM_VARYING, /**< machine->Inputs[]/Outputs[] */
+ PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */
+ PROGRAM_ENV_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
+ PROGRAM_NAMED_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
+ PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
+ PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
+ PROGRAM_ADDRESS, /**< machine->AddressReg */
+ PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
+ PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */
+ PROGRAM_UNDEFINED, /**< Invalid/TBD value */
+ PROGRAM_FILE_MAX
+} gl_register_file;
+
+
+/**
+ * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be
+ * one of these values.
+ */
+typedef enum
+{
+ SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */
+ SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */
+ SYSTEM_VALUE_MAX /**< Number of values */
+} gl_system_value;
+
+
+/** Vertex and fragment instructions */
+struct prog_instruction;
+struct gl_program_parameter_list;
+struct gl_uniform_list;
+
+
+/**
+ * Base class for any kind of program object
+ */
+struct gl_program
+{
+ GLuint Id;
+ GLubyte *String; /**< Null-terminated program text */
+ GLint RefCount;
+ GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_FRAGMENT_PROGRAM_NV */
+ GLenum Format; /**< String encoding format */
+ GLboolean Resident;
+
+ struct prog_instruction *Instructions;
+
+ GLbitfield InputsRead; /**< Bitmask of which input regs are read */
+ GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
+ GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
+ GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
+ GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
+ GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */
+ GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */
+ GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
+
+
+ /** Named parameters, constants, etc. from program text */
+ struct gl_program_parameter_list *Parameters;
+ /** Numbered local parameters */
+ GLfloat LocalParams[MAX_PROGRAM_LOCAL_PARAMS][4];
+
+ /** Vertex/fragment shader varying vars */
+ struct gl_program_parameter_list *Varying;
+ /** Vertex program user-defined attributes */
+ struct gl_program_parameter_list *Attributes;
+
+ /** Map from sampler unit to texture unit (set by glUniform1i()) */
+ GLubyte SamplerUnits[MAX_SAMPLERS];
+ /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
+ gl_texture_index SamplerTargets[MAX_SAMPLERS];
+
+ /** Bitmask of which register files are read/written with indirect
+ * addressing. Mask of (1 << PROGRAM_x) bits.
+ */
+ GLbitfield IndirectRegisterFiles;
+
+ /** Logical counts */
+ /*@{*/
+ GLuint NumInstructions;
+ GLuint NumTemporaries;
+ GLuint NumParameters;
+ GLuint NumAttributes;
+ GLuint NumAddressRegs;
+ GLuint NumAluInstructions;
+ GLuint NumTexInstructions;
+ GLuint NumTexIndirections;
+ /*@}*/
+ /** Native, actual h/w counts */
+ /*@{*/
+ GLuint NumNativeInstructions;
+ GLuint NumNativeTemporaries;
+ GLuint NumNativeParameters;
+ GLuint NumNativeAttributes;
+ GLuint NumNativeAddressRegs;
+ GLuint NumNativeAluInstructions;
+ GLuint NumNativeTexInstructions;
+ GLuint NumNativeTexIndirections;
+ /*@}*/
+};
+
+
+/** Vertex program object */
+struct gl_vertex_program
+{
+ struct gl_program Base; /**< base class */
+ GLboolean IsNVProgram; /**< is this a GL_NV_vertex_program program? */
+ GLboolean IsPositionInvariant;
+};
+
+
+/** Geometry program object */
+struct gl_geometry_program
+{
+ struct gl_program Base; /**< base class */
+
+ GLint VerticesOut;
+ GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
+ GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
+ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
+};
+
+
+/** Fragment program object */
+struct gl_fragment_program
+{
+ struct gl_program Base; /**< base class */
+ GLenum FogOption;
+ GLboolean UsesKill; /**< shader uses KIL instruction */
+ GLboolean OriginUpperLeft;
+ GLboolean PixelCenterInteger;
+ enum gl_frag_depth_layout FragDepthLayout;
+};
+
+
+/**
+ * State common to vertex and fragment programs.
+ */
+struct gl_program_state
+{
+ GLint ErrorPos; /* GL_PROGRAM_ERROR_POSITION_ARB/NV */
+ const char *ErrorString; /* GL_PROGRAM_ERROR_STRING_ARB/NV */
+};
+
+
+/**
+ * Context state for vertex programs.
+ */
+struct gl_vertex_program_state
+{
+ GLboolean Enabled; /**< User-set GL_VERTEX_PROGRAM_ARB/NV flag */
+ GLboolean _Enabled; /**< Enabled and _valid_ user program? */
+ GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
+ GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
+ struct gl_vertex_program *Current; /**< User-bound vertex program */
+
+ /** Currently enabled and valid vertex program (including internal
+ * programs, user-defined vertex programs and GLSL vertex shaders).
+ * This is the program we must use when rendering.
+ */
+ struct gl_vertex_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /* For GL_NV_vertex_program only: */
+ GLenum TrackMatrix[MAX_PROGRAM_ENV_PARAMS / 4];
+ GLenum TrackMatrixTransform[MAX_PROGRAM_ENV_PARAMS / 4];
+
+ /** Should fixed-function T&L be implemented with a vertex prog? */
+ GLboolean _MaintainTnlProgram;
+
+ /** Program to emulate fixed-function T&L (see above) */
+ struct gl_vertex_program *_TnlProgram;
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+
+ GLboolean _Overriden;
+};
+
+
+/**
+ * Context state for geometry programs.
+ */
+struct gl_geometry_program_state
+{
+ GLboolean Enabled; /**< GL_ARB_GEOMETRY_SHADER4 */
+ GLboolean _Enabled; /**< Enabled and valid program? */
+ struct gl_geometry_program *Current; /**< user-bound geometry program */
+
+ /** Currently enabled and valid program (including internal programs
+ * and compiled shader programs).
+ */
+ struct gl_geometry_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+};
+
+/**
+ * Context state for fragment programs.
+ */
+struct gl_fragment_program_state
+{
+ GLboolean Enabled; /**< User-set fragment program enable flag */
+ GLboolean _Enabled; /**< Enabled and _valid_ user program? */
+ struct gl_fragment_program *Current; /**< User-bound fragment program */
+
+ /** Currently enabled and valid fragment program (including internal
+ * programs, user-defined fragment programs and GLSL fragment shaders).
+ * This is the program we must use when rendering.
+ */
+ struct gl_fragment_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /** Should fixed-function texturing be implemented with a fragment prog? */
+ GLboolean _MaintainTexEnvProgram;
+
+ /** Program to emulate fixed-function texture env/combine (see above) */
+ struct gl_fragment_program *_TexEnvProgram;
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+};
+
+
+/**
+ * ATI_fragment_shader runtime state
+ */
+#define ATI_FS_INPUT_PRIMARY 0
+#define ATI_FS_INPUT_SECONDARY 1
+
+struct atifs_instruction;
+struct atifs_setupinst;
+
+/**
+ * ATI fragment shader
+ */
+struct ati_fragment_shader
+{
+ GLuint Id;
+ GLint RefCount;
+ struct atifs_instruction *Instructions[2];
+ struct atifs_setupinst *SetupInst[2];
+ GLfloat Constants[8][4];
+ GLbitfield LocalConstDef; /**< Indicates which constants have been set */
+ GLubyte numArithInstr[2];
+ GLubyte regsAssigned[2];
+ GLubyte NumPasses; /**< 1 or 2 */
+ GLubyte cur_pass;
+ GLubyte last_optype;
+ GLboolean interpinp1;
+ GLboolean isValid;
+ GLuint swizzlerq;
+};
+
+/**
+ * Context state for GL_ATI_fragment_shader
+ */
+struct gl_ati_fragment_shader_state
+{
+ GLboolean Enabled;
+ GLboolean _Enabled; /**< enabled and valid shader? */
+ GLboolean Compiling;
+ GLfloat GlobalConstants[8][4];
+ struct ati_fragment_shader *Current;
+};
+
+
+/**
+ * Occlusion/timer query object.
+ */
+struct gl_query_object
+{
+ GLenum Target; /**< The query target, when active */
+ GLuint Id; /**< hash table ID/name */
+ GLuint64EXT Result; /**< the counter */
+ GLboolean Active; /**< inside Begin/EndQuery */
+ GLboolean Ready; /**< result is ready? */
+};
+
+
+/**
+ * Context state for query objects.
+ */
+struct gl_query_state
+{
+ struct _mesa_HashTable *QueryObjects;
+ struct gl_query_object *CurrentOcclusionObject; /* GL_ARB_occlusion_query */
+ struct gl_query_object *CurrentTimerObject; /* GL_EXT_timer_query */
+
+ /** GL_NV_conditional_render */
+ struct gl_query_object *CondRenderQuery;
+
+ /** GL_EXT_transform_feedback */
+ struct gl_query_object *PrimitivesGenerated;
+ struct gl_query_object *PrimitivesWritten;
+
+ /** GL_ARB_timer_query */
+ struct gl_query_object *TimeElapsed;
+
+ GLenum CondRenderMode;
+};
+
+
+/** Sync object state */
+struct gl_sync_object {
+ struct simple_node link;
+ GLenum Type; /**< GL_SYNC_FENCE */
+ GLuint Name; /**< Fence name */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending; /**< Object was deleted while there were still
+ * live references (e.g., sync not yet finished)
+ */
+ GLenum SyncCondition;
+ GLbitfield Flags; /**< Flags passed to glFenceSync */
+ GLuint StatusFlag:1; /**< Has the sync object been signaled? */
+};
+
+
+/** Set by #pragma directives */
+struct gl_sl_pragmas
+{
+ GLboolean IgnoreOptimize; /**< ignore #pragma optimize(on/off) ? */
+ GLboolean IgnoreDebug; /**< ignore #pragma debug(on/off) ? */
+ GLboolean Optimize; /**< defaults on */
+ GLboolean Debug; /**< defaults off */
+};
+
+
+/**
+ * A GLSL vertex or fragment shader object.
+ */
+struct gl_shader
+{
+ GLenum Type; /**< GL_FRAGMENT_SHADER || GL_VERTEX_SHADER || GL_GEOMETRY_SHADER_ARB (first field!) */
+ GLuint Name; /**< AKA the handle */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending;
+ GLboolean CompileStatus;
+ const GLchar *Source; /**< Source code string */
+ GLuint SourceChecksum; /**< for debug/logging purposes */
+ struct gl_program *Program; /**< Post-compile assembly code */
+ GLchar *InfoLog;
+ struct gl_sl_pragmas Pragmas;
+
+ unsigned Version; /**< GLSL version used for linking */
+
+ struct exec_list *ir;
+ struct glsl_symbol_table *symbols;
+
+ /** Shaders containing built-in functions that are used for linking. */
+ struct gl_shader *builtins_to_link[16];
+ unsigned num_builtins_to_link;
+};
+
+
+/**
+ * A GLSL program object.
+ * Basically a linked collection of vertex and fragment shaders.
+ */
+struct gl_shader_program
+{
+ GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */
+ GLuint Name; /**< aka handle or ID */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending;
+
+ GLuint NumShaders; /**< number of attached shaders */
+ struct gl_shader **Shaders; /**< List of attached the shaders */
+
+ /** User-defined attribute bindings (glBindAttribLocation) */
+ struct gl_program_parameter_list *Attributes;
+
+ /** Transform feedback varyings */
+ struct {
+ GLenum BufferMode;
+ GLuint NumVarying;
+ GLchar **VaryingNames; /**< Array [NumVarying] of char * */
+ } TransformFeedback;
+
+ /** Geometry shader state - copied into gl_geometry_program at link time */
+ struct {
+ GLint VerticesOut;
+ GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
+ GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
+ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
+ } Geom;
+
+ /* post-link info: */
+ struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
+ struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
+ struct gl_geometry_program *GeometryProgram; /**< Linked geometry prog */
+ struct gl_uniform_list *Uniforms;
+ struct gl_program_parameter_list *Varying;
+ GLboolean LinkStatus; /**< GL_LINK_STATUS */
+ GLboolean Validated;
+ GLboolean _Used; /**< Ever used for drawing? */
+ GLchar *InfoLog;
+
+ unsigned Version; /**< GLSL version used for linking */
+
+ /**
+ * Per-stage shaders resulting from the first stage of linking.
+ *
+ * Set of linked shaders for this program. The array is accessed using the
+ * \c MESA_SHADER_* defines. Entries for non-existent stages will be
+ * \c NULL.
+ */
+ struct gl_shader *_LinkedShaders[MESA_SHADER_TYPES];
+};
+
+
+#define GLSL_DUMP 0x1 /**< Dump shaders to stdout */
+#define GLSL_LOG 0x2 /**< Write shaders to files */
+#define GLSL_OPT 0x4 /**< Force optimizations (override pragmas) */
+#define GLSL_NO_OPT 0x8 /**< Force no optimizations (override pragmas) */
+#define GLSL_UNIFORMS 0x10 /**< Print glUniform calls */
+#define GLSL_NOP_VERT 0x20 /**< Force no-op vertex shaders */
+#define GLSL_NOP_FRAG 0x40 /**< Force no-op fragment shaders */
+#define GLSL_USE_PROG 0x80 /**< Log glUseProgram calls */
+
+
+/**
+ * Context state for GLSL vertex/fragment shaders.
+ */
+struct gl_shader_state
+{
+ /**
+ * Programs used for rendering
+ *
+ * There is a separate program set for each shader stage. If
+ * GL_EXT_separate_shader_objects is not supported, each of these must point
+ * to \c NULL or to the same program.
+ */
+ struct gl_shader_program *CurrentVertexProgram;
+ struct gl_shader_program *CurrentGeometryProgram;
+ struct gl_shader_program *CurrentFragmentProgram;
+
+ /**
+ * Program used by glUniform calls.
+ *
+ * Explicitly set by \c glUseProgram and \c glActiveProgramEXT.
+ */
+ struct gl_shader_program *ActiveProgram;
+
+ void *MemPool;
+
+ GLbitfield Flags; /**< Mask of GLSL_x flags */
+};
+
+/**
+ * Compiler options for a single GLSL shaders type
+ */
+struct gl_shader_compiler_options
+{
+ /** Driver-selectable options: */
+ GLboolean EmitCondCodes; /**< Use condition codes? */
+ GLboolean EmitNVTempInitialization; /**< 0-fill NV temp registers */
+ /**
+ * Attempts to flatten all ir_if (OPCODE_IF) for GPUs that can't
+ * support control flow.
+ */
+ GLboolean EmitNoIfs;
+ GLboolean EmitNoLoops;
+ GLboolean EmitNoFunctions;
+ GLboolean EmitNoCont; /**< Emit CONT opcode? */
+ GLboolean EmitNoMainReturn; /**< Emit CONT/RET opcodes? */
+ GLboolean EmitNoNoise; /**< Emit NOISE opcodes? */
+ GLboolean EmitNoPow; /**< Emit POW opcodes? */
+
+ /**
+ * \name Forms of indirect addressing the driver cannot do.
+ */
+ /*@{*/
+ GLboolean EmitNoIndirectInput; /**< No indirect addressing of inputs */
+ GLboolean EmitNoIndirectOutput; /**< No indirect addressing of outputs */
+ GLboolean EmitNoIndirectTemp; /**< No indirect addressing of temps */
+ GLboolean EmitNoIndirectUniform; /**< No indirect addressing of constants */
+ /*@}*/
+
+ GLuint MaxUnrollIterations;
+
+ struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
+};
+
+/**
+ * Transform feedback object state
+ */
+struct gl_transform_feedback_object
+{
+ GLuint Name; /**< AKA the object ID */
+ GLint RefCount;
+ GLboolean Active; /**< Is transform feedback enabled? */
+ GLboolean Paused; /**< Is transform feedback paused? */
+
+ /** The feedback buffers */
+ GLuint BufferNames[MAX_FEEDBACK_ATTRIBS];
+ struct gl_buffer_object *Buffers[MAX_FEEDBACK_ATTRIBS];
+
+ /** Start of feedback data in dest buffer */
+ GLintptr Offset[MAX_FEEDBACK_ATTRIBS];
+ /** Max data to put into dest buffer (in bytes) */
+ GLsizeiptr Size[MAX_FEEDBACK_ATTRIBS];
+};
+
+
+/**
+ * Context state for transform feedback.
+ */
+struct gl_transform_feedback
+{
+ GLenum Mode; /**< GL_POINTS, GL_LINES or GL_TRIANGLES */
+
+ GLboolean RasterDiscard; /**< GL_RASTERIZER_DISCARD */
+
+ /** The general binding point (GL_TRANSFORM_FEEDBACK_BUFFER) */
+ struct gl_buffer_object *CurrentBuffer;
+
+ /** The table of all transform feedback objects */
+ struct _mesa_HashTable *Objects;
+
+ /** The current xform-fb object (GL_TRANSFORM_FEEDBACK_BINDING) */
+ struct gl_transform_feedback_object *CurrentObject;
+
+ /** The default xform-fb object (Name==0) */
+ struct gl_transform_feedback_object *DefaultObject;
+};
+
+
+
+/**
+ * State which can be shared by multiple contexts:
+ */
+struct gl_shared_state
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLint RefCount; /**< Reference count */
+ struct _mesa_HashTable *DisplayList; /**< Display lists hash table */
+ struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */
+
+ /** Default texture objects (shared by all texture units) */
+ struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
+
+ /** Fallback texture used when a bound texture is incomplete */
+ struct gl_texture_object *FallbackTex;
+
+ /**
+ * \name Thread safety and statechange notification for texture
+ * objects.
+ *
+ * \todo Improve the granularity of locking.
+ */
+ /*@{*/
+ _glthread_Mutex TexMutex; /**< texobj thread safety */
+ GLuint TextureStateStamp; /**< state notification for shared tex */
+ /*@}*/
+
+ /** Default buffer object for vertex arrays that aren't in VBOs */
+ struct gl_buffer_object *NullBufferObj;
+
+ /**
+ * \name Vertex/geometry/fragment programs
+ */
+ /*@{*/
+ struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
+ struct gl_vertex_program *DefaultVertexProgram;
+ struct gl_fragment_program *DefaultFragmentProgram;
+ struct gl_geometry_program *DefaultGeometryProgram;
+ /*@}*/
+
+ /* GL_ATI_fragment_shader */
+ struct _mesa_HashTable *ATIShaders;
+ struct ati_fragment_shader *DefaultFragmentShader;
+
+ struct _mesa_HashTable *BufferObjects;
+
+ /** Table of both gl_shader and gl_shader_program objects */
+ struct _mesa_HashTable *ShaderObjects;
+
+ /* GL_EXT_framebuffer_object */
+ struct _mesa_HashTable *RenderBuffers;
+ struct _mesa_HashTable *FrameBuffers;
+
+ /* GL_ARB_sync */
+ struct simple_node SyncObjects;
+
+ void *DriverData; /**< Device driver shared state */
+};
+
+
+
+
+/**
+ * A renderbuffer stores colors or depth values or stencil values.
+ * A framebuffer object will have a collection of these.
+ * Data are read/written to the buffer with a handful of Get/Put functions.
+ *
+ * Instances of this object are allocated with the Driver's NewRenderbuffer
+ * hook. Drivers will likely wrap this class inside a driver-specific
+ * class to simulate inheritance.
+ */
+struct gl_renderbuffer
+{
+#define RB_MAGIC 0xaabbccdd
+ int Magic; /** XXX TEMPORARY DEBUG INFO */
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLuint ClassID; /**< Useful for drivers */
+ GLuint Name;
+ GLint RefCount;
+ GLuint Width, Height;
+ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
+
+ GLenum InternalFormat; /**< The user-specified format */
+ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or
+ GL_STENCIL_INDEX. */
+ gl_format Format; /**< The actual renderbuffer memory format */
+
+ GLubyte NumSamples;
+
+ GLenum DataType; /**< Type of values passed to the Get/Put functions */
+ GLvoid *Data; /**< This may not be used by some kinds of RBs */
+
+ /* Used to wrap one renderbuffer around another: */
+ struct gl_renderbuffer *Wrapped;
+
+ /* Delete this renderbuffer */
+ void (*Delete)(struct gl_renderbuffer *rb);
+
+ /* Allocate new storage for this renderbuffer */
+ GLboolean (*AllocStorage)(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height);
+
+ /* Lock/Unlock are called before/after calling the Get/Put functions.
+ * Not sure this is the right place for these yet.
+ void (*Lock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
+ void (*Unlock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
+ */
+
+ /* Return a pointer to the element/pixel at (x,y).
+ * Should return NULL if the buffer memory can't be directly addressed.
+ */
+ void *(*GetPointer)(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y);
+
+ /* Get/Read a row of values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*GetRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values);
+
+ /* Get/Read values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*GetValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values);
+
+ /* Put/Write a row of values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask);
+
+ /* Put/Write a row of RGB values. This is a special-case routine that's
+ * only used for RGBA renderbuffers when the source data is GL_RGB. That's
+ * a common case for glDrawPixels and some triangle routines.
+ * The values will be of format GL_RGB and type DataType.
+ */
+ void (*PutRowRGB)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask);
+
+
+ /* Put/Write a row of identical values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutMonoRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask);
+
+ /* Put/Write values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask);
+ /* Put/Write identical values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutMonoValues)(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask);
+};
+
+
+/**
+ * A renderbuffer attachment points to either a texture object (and specifies
+ * a mipmap level, cube face or 3D texture slice) or points to a renderbuffer.
+ */
+struct gl_renderbuffer_attachment
+{
+ GLenum Type; /**< \c GL_NONE or \c GL_TEXTURE or \c GL_RENDERBUFFER_EXT */
+ GLboolean Complete;
+
+ /**
+ * If \c Type is \c GL_RENDERBUFFER_EXT, this stores a pointer to the
+ * application supplied renderbuffer object.
+ */
+ struct gl_renderbuffer *Renderbuffer;
+
+ /**
+ * If \c Type is \c GL_TEXTURE, this stores a pointer to the application
+ * supplied texture object.
+ */
+ struct gl_texture_object *Texture;
+ GLuint TextureLevel; /**< Attached mipmap level. */
+ GLuint CubeMapFace; /**< 0 .. 5, for cube map textures. */
+ GLuint Zoffset; /**< Slice for 3D textures, or layer for both 1D
+ * and 2D array textures */
+};
+
+
+/**
+ * A framebuffer is a collection of renderbuffers (color, depth, stencil, etc).
+ * In C++ terms, think of this as a base class from which device drivers
+ * will make derived classes.
+ */
+struct gl_framebuffer
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ /**
+ * If zero, this is a window system framebuffer. If non-zero, this
+ * is a FBO framebuffer; note that for some devices (i.e. those with
+ * a natural pixel coordinate system for FBOs that differs from the
+ * OpenGL/Mesa coordinate system), this means that the viewport,
+ * polygon face orientation, and polygon stipple will have to be inverted.
+ */
+ GLuint Name;
+
+ GLint RefCount;
+ GLboolean DeletePending;
+
+ /**
+ * The framebuffer's visual. Immutable if this is a window system buffer.
+ * Computed from attachments if user-made FBO.
+ */
+ struct gl_config Visual;
+
+ GLboolean Initialized;
+
+ GLuint Width, Height; /**< size of frame buffer in pixels */
+
+ /** \name Drawing bounds (Intersection of buffer size and scissor box) */
+ /*@{*/
+ GLint _Xmin, _Xmax; /**< inclusive */
+ GLint _Ymin, _Ymax; /**< exclusive */
+ /*@}*/
+
+ /** \name Derived Z buffer stuff */
+ /*@{*/
+ GLuint _DepthMax; /**< Max depth buffer value */
+ GLfloat _DepthMaxF; /**< Float max depth buffer value */
+ GLfloat _MRD; /**< minimum resolvable difference in Z values */
+ /*@}*/
+
+ /** One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */
+ GLenum _Status;
+
+ /** Integer color values */
+ GLboolean _IntegerColor;
+
+ /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
+ struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT];
+
+ /* In unextended OpenGL these vars are part of the GL_COLOR_BUFFER
+ * attribute group and GL_PIXEL attribute group, respectively.
+ */
+ GLenum ColorDrawBuffer[MAX_DRAW_BUFFERS];
+ GLenum ColorReadBuffer;
+
+ /** Computed from ColorDraw/ReadBuffer above */
+ GLuint _NumColorDrawBuffers;
+ GLint _ColorDrawBufferIndexes[MAX_DRAW_BUFFERS]; /**< BUFFER_x or -1 */
+ GLint _ColorReadBufferIndex; /* -1 = None */
+ struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS];
+ struct gl_renderbuffer *_ColorReadBuffer;
+
+ /** The Actual depth/stencil buffers to use. May be wrappers around the
+ * depth/stencil buffers attached above. */
+ struct gl_renderbuffer *_DepthBuffer;
+ struct gl_renderbuffer *_StencilBuffer;
+
+ /** Delete this framebuffer */
+ void (*Delete)(struct gl_framebuffer *fb);
+};
+
+
+/**
+ * Precision info for shader datatypes. See glGetShaderPrecisionFormat().
+ */
+struct gl_precision
+{
+ GLushort RangeMin; /**< min value exponent */
+ GLushort RangeMax; /**< max value exponent */
+ GLushort Precision; /**< number of mantissa bits */
+};
+
+
+/**
+ * Limits for vertex and fragment programs/shaders.
+ */
+struct gl_program_constants
+{
+ /* logical limits */
+ GLuint MaxInstructions;
+ GLuint MaxAluInstructions;
+ GLuint MaxTexInstructions;
+ GLuint MaxTexIndirections;
+ GLuint MaxAttribs;
+ GLuint MaxTemps;
+ GLuint MaxAddressRegs;
+ GLuint MaxParameters;
+ GLuint MaxLocalParams;
+ GLuint MaxEnvParams;
+ /* native/hardware limits */
+ GLuint MaxNativeInstructions;
+ GLuint MaxNativeAluInstructions;
+ GLuint MaxNativeTexInstructions;
+ GLuint MaxNativeTexIndirections;
+ GLuint MaxNativeAttribs;
+ GLuint MaxNativeTemps;
+ GLuint MaxNativeAddressRegs;
+ GLuint MaxNativeParameters;
+ /* For shaders */
+ GLuint MaxUniformComponents;
+ /* GL_ARB_geometry_shader4 */
+ GLuint MaxGeometryTextureImageUnits;
+ GLuint MaxGeometryVaryingComponents;
+ GLuint MaxVertexVaryingComponents;
+ GLuint MaxGeometryUniformComponents;
+ GLuint MaxGeometryOutputVertices;
+ GLuint MaxGeometryTotalOutputComponents;
+ /* ES 2.0 and GL_ARB_ES2_compatibility */
+ struct gl_precision LowFloat, MediumFloat, HighFloat;
+ struct gl_precision LowInt, MediumInt, HighInt;
+};
+
+
+/**
+ * Constants which may be overridden by device driver during context creation
+ * but are never changed after that.
+ */
+struct gl_constants
+{
+ GLint MaxTextureMbytes; /**< Max memory per image, in MB */
+ GLint MaxTextureLevels; /**< Max mipmap levels. */
+ GLint Max3DTextureLevels; /**< Max mipmap levels for 3D textures */
+ GLint MaxCubeTextureLevels; /**< Max mipmap levels for cube textures */
+ GLint MaxArrayTextureLayers; /**< Max layers in array textures */
+ GLint MaxTextureRectSize; /**< Max rectangle texture size, in pixes */
+ GLuint MaxTextureCoordUnits;
+ GLuint MaxTextureImageUnits;
+ GLuint MaxVertexTextureImageUnits;
+ GLuint MaxCombinedTextureImageUnits;
+ GLuint MaxTextureUnits; /**< = MIN(CoordUnits, ImageUnits) */
+ GLfloat MaxTextureMaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
+ GLfloat MaxTextureLodBias; /**< GL_EXT_texture_lod_bias */
+
+ GLuint MaxArrayLockSize;
+
+ GLint SubPixelBits;
+
+ GLfloat MinPointSize, MaxPointSize; /**< aliased */
+ GLfloat MinPointSizeAA, MaxPointSizeAA; /**< antialiased */
+ GLfloat PointSizeGranularity;
+ GLfloat MinLineWidth, MaxLineWidth; /**< aliased */
+ GLfloat MinLineWidthAA, MaxLineWidthAA; /**< antialiased */
+ GLfloat LineWidthGranularity;
+
+ GLuint MaxColorTableSize;
+
+ GLuint MaxClipPlanes;
+ GLuint MaxLights;
+ GLfloat MaxShininess; /**< GL_NV_light_max_exponent */
+ GLfloat MaxSpotExponent; /**< GL_NV_light_max_exponent */
+
+ GLuint MaxViewportWidth, MaxViewportHeight;
+
+ struct gl_program_constants VertexProgram; /**< GL_ARB_vertex_program */
+ struct gl_program_constants FragmentProgram; /**< GL_ARB_fragment_program */
+ struct gl_program_constants GeometryProgram; /**< GL_ARB_geometry_shader4 */
+ GLuint MaxProgramMatrices;
+ GLuint MaxProgramMatrixStackDepth;
+
+ /** vertex array / buffer object bounds checking */
+ GLboolean CheckArrayBounds;
+
+ GLuint MaxDrawBuffers; /**< GL_ARB_draw_buffers */
+
+ GLuint MaxColorAttachments; /**< GL_EXT_framebuffer_object */
+ GLuint MaxRenderbufferSize; /**< GL_EXT_framebuffer_object */
+ GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
+
+ GLuint MaxVarying; /**< Number of float[4] varying parameters */
+
+ GLuint GLSLVersion; /**< GLSL version supported (ex: 120 = 1.20) */
+
+ /** Which texture units support GL_ATI_envmap_bumpmap as targets */
+ GLbitfield SupportedBumpUnits;
+
+ /**
+ * Maximum amount of time, measured in nanseconds, that the server can wait.
+ */
+ GLuint64 MaxServerWaitTimeout;
+
+ /** GL_EXT_provoking_vertex */
+ GLboolean QuadsFollowProvokingVertexConvention;
+
+ /** OpenGL version 3.0 */
+ GLbitfield ContextFlags; /**< Ex: GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT */
+
+ /** OpenGL version 3.2 */
+ GLbitfield ProfileMask; /**< Mask of CONTEXT_x_PROFILE_BIT */
+
+ /** GL_EXT_transform_feedback */
+ GLuint MaxTransformFeedbackSeparateAttribs;
+ GLuint MaxTransformFeedbackSeparateComponents;
+ GLuint MaxTransformFeedbackInterleavedComponents;
+
+ /** GL_EXT_gpu_shader4 */
+ GLint MinProgramTexelOffset, MaxProgramTexelOffset;
+
+ /* GL_EXT_framebuffer_sRGB */
+ GLboolean sRGBCapable; /* can enable sRGB blend/update on FBOs */
+};
+
+
+/**
+ * Enable flag for each OpenGL extension. Different device drivers will
+ * enable different extensions at runtime.
+ */
+struct gl_extensions
+{
+ GLboolean dummy; /* don't remove this! */
+ GLboolean dummy_true; /* Set true by _mesa_init_extensions(). */
+ GLboolean dummy_false; /* Set false by _mesa_init_extensions(). */
+ GLboolean ARB_ES2_compatibility;
+ GLboolean ARB_blend_func_extended;
+ GLboolean ARB_copy_buffer;
+ GLboolean ARB_depth_buffer_float;
+ GLboolean ARB_depth_clamp;
+ GLboolean ARB_depth_texture;
+ GLboolean ARB_draw_buffers;
+ GLboolean ARB_draw_buffers_blend;
+ GLboolean ARB_draw_elements_base_vertex;
+ GLboolean ARB_draw_instanced;
+ GLboolean ARB_fragment_coord_conventions;
+ GLboolean ARB_fragment_program;
+ GLboolean ARB_fragment_program_shadow;
+ GLboolean ARB_fragment_shader;
+ GLboolean ARB_framebuffer_object;
+ GLboolean ARB_explicit_attrib_location;
+ GLboolean ARB_geometry_shader4;
+ GLboolean ARB_half_float_pixel;
+ GLboolean ARB_half_float_vertex;
+ GLboolean ARB_instanced_arrays;
+ GLboolean ARB_map_buffer_range;
+ GLboolean ARB_multisample;
+ GLboolean ARB_multitexture;
+ GLboolean ARB_occlusion_query;
+ GLboolean ARB_occlusion_query2;
+ GLboolean ARB_point_sprite;
+ GLboolean ARB_sampler_objects;
+ GLboolean ARB_seamless_cube_map;
+ GLboolean ARB_shader_objects;
+ GLboolean ARB_shader_stencil_export;
+ GLboolean ARB_shading_language_100;
+ GLboolean ARB_shadow;
+ GLboolean ARB_shadow_ambient;
+ GLboolean ARB_sync;
+ GLboolean ARB_texture_border_clamp;
+ GLboolean ARB_texture_buffer_object;
+ GLboolean ARB_texture_compression;
+ GLboolean ARB_texture_compression_rgtc;
+ GLboolean ARB_texture_cube_map;
+ GLboolean ARB_texture_env_combine;
+ GLboolean ARB_texture_env_crossbar;
+ GLboolean ARB_texture_env_dot3;
+ GLboolean ARB_texture_float;
+ GLboolean ARB_texture_mirrored_repeat;
+ GLboolean ARB_texture_multisample;
+ GLboolean ARB_texture_non_power_of_two;
+ GLboolean ARB_texture_rg;
+ GLboolean ARB_texture_rgb10_a2ui;
+ GLboolean ARB_timer_query;
+ GLboolean ARB_transform_feedback2;
+ GLboolean ARB_transpose_matrix;
+ GLboolean ARB_uniform_buffer_object;
+ GLboolean ARB_vertex_array_object;
+ GLboolean ARB_vertex_buffer_object;
+ GLboolean ARB_vertex_program;
+ GLboolean ARB_vertex_shader;
+ GLboolean ARB_vertex_type_2_10_10_10_rev;
+ GLboolean ARB_window_pos;
+ GLboolean EXT_abgr;
+ GLboolean EXT_bgra;
+ GLboolean EXT_blend_color;
+ GLboolean EXT_blend_equation_separate;
+ GLboolean EXT_blend_func_separate;
+ GLboolean EXT_blend_logic_op;
+ GLboolean EXT_blend_minmax;
+ GLboolean EXT_blend_subtract;
+ GLboolean EXT_clip_volume_hint;
+ GLboolean EXT_compiled_vertex_array;
+ GLboolean EXT_copy_texture;
+ GLboolean EXT_depth_bounds_test;
+ GLboolean EXT_draw_buffers2;
+ GLboolean EXT_draw_range_elements;
+ GLboolean EXT_fog_coord;
+ GLboolean EXT_framebuffer_blit;
+ GLboolean EXT_framebuffer_multisample;
+ GLboolean EXT_framebuffer_object;
+ GLboolean EXT_framebuffer_sRGB;
+ GLboolean EXT_gpu_program_parameters;
+ GLboolean EXT_gpu_shader4;
+ GLboolean EXT_multi_draw_arrays;
+ GLboolean EXT_paletted_texture;
+ GLboolean EXT_packed_depth_stencil;
+ GLboolean EXT_packed_float;
+ GLboolean EXT_packed_pixels;
+ GLboolean EXT_pixel_buffer_object;
+ GLboolean EXT_point_parameters;
+ GLboolean EXT_polygon_offset;
+ GLboolean EXT_provoking_vertex;
+ GLboolean EXT_rescale_normal;
+ GLboolean EXT_shadow_funcs;
+ GLboolean EXT_secondary_color;
+ GLboolean EXT_separate_shader_objects;
+ GLboolean EXT_separate_specular_color;
+ GLboolean EXT_shared_texture_palette;
+ GLboolean EXT_stencil_wrap;
+ GLboolean EXT_stencil_two_side;
+ GLboolean EXT_subtexture;
+ GLboolean EXT_texture;
+ GLboolean EXT_texture_object;
+ GLboolean EXT_texture3D;
+ GLboolean EXT_texture_array;
+ GLboolean EXT_texture_compression_s3tc;
+ GLboolean EXT_texture_env_add;
+ GLboolean EXT_texture_env_combine;
+ GLboolean EXT_texture_env_dot3;
+ GLboolean EXT_texture_filter_anisotropic;
+ GLboolean EXT_texture_integer;
+ GLboolean EXT_texture_lod_bias;
+ GLboolean EXT_texture_mirror_clamp;
+ GLboolean EXT_texture_shared_exponent;
+ GLboolean EXT_texture_sRGB;
+ GLboolean EXT_texture_sRGB_decode;
+ GLboolean EXT_texture_swizzle;
+ GLboolean EXT_transform_feedback;
+ GLboolean EXT_timer_query;
+ GLboolean EXT_vertex_array;
+ GLboolean EXT_vertex_array_bgra;
+ GLboolean EXT_vertex_array_set;
+ GLboolean OES_standard_derivatives;
+ /* vendor extensions */
+ GLboolean AMD_conservative_depth;
+ GLboolean APPLE_client_storage;
+ GLboolean APPLE_packed_pixels;
+ GLboolean APPLE_vertex_array_object;
+ GLboolean APPLE_object_purgeable;
+ GLboolean ATI_envmap_bumpmap;
+ GLboolean ATI_texture_mirror_once;
+ GLboolean ATI_texture_env_combine3;
+ GLboolean ATI_fragment_shader;
+ GLboolean ATI_separate_stencil;
+ GLboolean IBM_rasterpos_clip;
+ GLboolean IBM_multimode_draw_arrays;
+ GLboolean MESA_pack_invert;
+ GLboolean MESA_resize_buffers;
+ GLboolean MESA_ycbcr_texture;
+ GLboolean MESA_texture_array;
+ GLboolean MESA_texture_signed_rgba;
+ GLboolean NV_blend_square;
+ GLboolean NV_conditional_render;
+ GLboolean NV_fragment_program;
+ GLboolean NV_fragment_program_option;
+ GLboolean NV_light_max_exponent;
+ GLboolean NV_point_sprite;
+ GLboolean NV_primitive_restart;
+ GLboolean NV_texgen_reflection;
+ GLboolean NV_texture_env_combine4;
+ GLboolean NV_texture_rectangle;
+ GLboolean NV_vertex_program;
+ GLboolean NV_vertex_program1_1;
+ GLboolean OES_read_format;
+ GLboolean SGIS_generate_mipmap;
+ GLboolean SGIS_texture_edge_clamp;
+ GLboolean SGIS_texture_lod;
+ GLboolean TDFX_texture_compression_FXT1;
+ GLboolean S3_s3tc;
+ GLboolean OES_EGL_image;
+ GLboolean OES_draw_texture;
+ GLboolean EXT_texture_format_BGRA8888;
+ GLboolean extension_sentinel;
+ /** The extension string */
+ const GLubyte *String;
+ /** Number of supported extensions */
+ GLuint Count;
+};
+
+
+/**
+ * A stack of matrices (projection, modelview, color, texture, etc).
+ */
+struct gl_matrix_stack
+{
+ GLmatrix *Top; /**< points into Stack */
+ GLmatrix *Stack; /**< array [MaxDepth] of GLmatrix */
+ GLuint Depth; /**< 0 <= Depth < MaxDepth */
+ GLuint MaxDepth; /**< size of Stack[] array */
+ GLuint DirtyFlag; /**< _NEW_MODELVIEW or _NEW_PROJECTION, for example */
+};
+
+
+/**
+ * \name Bits for image transfer operations
+ * \sa __struct gl_contextRec::ImageTransferState.
+ */
+/*@{*/
+#define IMAGE_SCALE_BIAS_BIT 0x1
+#define IMAGE_SHIFT_OFFSET_BIT 0x2
+#define IMAGE_MAP_COLOR_BIT 0x4
+#define IMAGE_CLAMP_BIT 0x800
+
+
+/** Pixel Transfer ops */
+#define IMAGE_BITS (IMAGE_SCALE_BIAS_BIT | \
+ IMAGE_SHIFT_OFFSET_BIT | \
+ IMAGE_MAP_COLOR_BIT)
+
+/**
+ * \name Bits to indicate what state has changed.
+ */
+/*@{*/
+#define _NEW_MODELVIEW (1 << 0) /**< gl_context::ModelView */
+#define _NEW_PROJECTION (1 << 1) /**< gl_context::Projection */
+#define _NEW_TEXTURE_MATRIX (1 << 2) /**< gl_context::TextureMatrix */
+#define _NEW_COLOR (1 << 3) /**< gl_context::Color */
+#define _NEW_DEPTH (1 << 4) /**< gl_context::Depth */
+#define _NEW_EVAL (1 << 5) /**< gl_context::Eval, EvalMap */
+#define _NEW_FOG (1 << 6) /**< gl_context::Fog */
+#define _NEW_HINT (1 << 7) /**< gl_context::Hint */
+#define _NEW_LIGHT (1 << 8) /**< gl_context::Light */
+#define _NEW_LINE (1 << 9) /**< gl_context::Line */
+#define _NEW_PIXEL (1 << 10) /**< gl_context::Pixel */
+#define _NEW_POINT (1 << 11) /**< gl_context::Point */
+#define _NEW_POLYGON (1 << 12) /**< gl_context::Polygon */
+#define _NEW_POLYGONSTIPPLE (1 << 13) /**< gl_context::PolygonStipple */
+#define _NEW_SCISSOR (1 << 14) /**< gl_context::Scissor */
+#define _NEW_STENCIL (1 << 15) /**< gl_context::Stencil */
+#define _NEW_TEXTURE (1 << 16) /**< gl_context::Texture */
+#define _NEW_TRANSFORM (1 << 17) /**< gl_context::Transform */
+#define _NEW_VIEWPORT (1 << 18) /**< gl_context::Viewport */
+#define _NEW_PACKUNPACK (1 << 19) /**< gl_context::Pack, Unpack */
+#define _NEW_ARRAY (1 << 20) /**< gl_context::Array */
+#define _NEW_RENDERMODE (1 << 21) /**< gl_context::RenderMode, etc */
+#define _NEW_BUFFERS (1 << 22) /**< gl_context::Visual, DrawBuffer, */
+#define _NEW_CURRENT_ATTRIB (1 << 23) /**< gl_context::Current */
+#define _NEW_MULTISAMPLE (1 << 24) /**< gl_context::Multisample */
+#define _NEW_TRACK_MATRIX (1 << 25) /**< gl_context::VertexProgram */
+#define _NEW_PROGRAM (1 << 26) /**< New program/shader state */
+#define _NEW_PROGRAM_CONSTANTS (1 << 27)
+#define _NEW_BUFFER_OBJECT (1 << 28)
+#define _NEW_ALL ~0
+/*@}*/
+
+
+/**
+ * \name Bits to track array state changes
+ *
+ * Also used to summarize array enabled.
+ */
+/*@{*/
+#define _NEW_ARRAY_VERTEX VERT_BIT_POS
+#define _NEW_ARRAY_WEIGHT VERT_BIT_WEIGHT
+#define _NEW_ARRAY_NORMAL VERT_BIT_NORMAL
+#define _NEW_ARRAY_COLOR0 VERT_BIT_COLOR0
+#define _NEW_ARRAY_COLOR1 VERT_BIT_COLOR1
+#define _NEW_ARRAY_FOGCOORD VERT_BIT_FOG
+#define _NEW_ARRAY_INDEX VERT_BIT_COLOR_INDEX
+#define _NEW_ARRAY_EDGEFLAG VERT_BIT_EDGEFLAG
+#define _NEW_ARRAY_POINT_SIZE VERT_BIT_COLOR_INDEX /* aliased */
+#define _NEW_ARRAY_TEXCOORD_0 VERT_BIT_TEX0
+#define _NEW_ARRAY_TEXCOORD_1 VERT_BIT_TEX1
+#define _NEW_ARRAY_TEXCOORD_2 VERT_BIT_TEX2
+#define _NEW_ARRAY_TEXCOORD_3 VERT_BIT_TEX3
+#define _NEW_ARRAY_TEXCOORD_4 VERT_BIT_TEX4
+#define _NEW_ARRAY_TEXCOORD_5 VERT_BIT_TEX5
+#define _NEW_ARRAY_TEXCOORD_6 VERT_BIT_TEX6
+#define _NEW_ARRAY_TEXCOORD_7 VERT_BIT_TEX7
+#define _NEW_ARRAY_ATTRIB_0 VERT_BIT_GENERIC0 /* start at bit 16 */
+#define _NEW_ARRAY_ALL 0xffffffff
+
+
+#define _NEW_ARRAY_TEXCOORD(i) (_NEW_ARRAY_TEXCOORD_0 << (i))
+#define _NEW_ARRAY_ATTRIB(i) (_NEW_ARRAY_ATTRIB_0 << (i))
+/*@}*/
+
+
+
+/**
+ * \name A bunch of flags that we think might be useful to drivers.
+ *
+ * Set in the __struct gl_contextRec::_TriangleCaps bitfield.
+ */
+/*@{*/
+#define DD_FLATSHADE 0x1
+#define DD_SEPARATE_SPECULAR 0x2
+#define DD_TRI_CULL_FRONT_BACK 0x4 /* special case on some hw */
+#define DD_TRI_LIGHT_TWOSIDE 0x8
+#define DD_TRI_UNFILLED 0x10
+#define DD_TRI_SMOOTH 0x20
+#define DD_TRI_STIPPLE 0x40
+#define DD_TRI_OFFSET 0x80
+#define DD_LINE_SMOOTH 0x100
+#define DD_LINE_STIPPLE 0x200
+#define DD_POINT_SMOOTH 0x400
+#define DD_POINT_ATTEN 0x800
+#define DD_TRI_TWOSTENCIL 0x1000
+/*@}*/
+
+
+/**
+ * \name Define the state changes under which each of these bits might change
+ */
+/*@{*/
+#define _DD_NEW_FLATSHADE _NEW_LIGHT
+#define _DD_NEW_SEPARATE_SPECULAR (_NEW_LIGHT | _NEW_FOG | _NEW_PROGRAM)
+#define _DD_NEW_TRI_CULL_FRONT_BACK _NEW_POLYGON
+#define _DD_NEW_TRI_LIGHT_TWOSIDE _NEW_LIGHT
+#define _DD_NEW_TRI_UNFILLED _NEW_POLYGON
+#define _DD_NEW_TRI_SMOOTH _NEW_POLYGON
+#define _DD_NEW_TRI_STIPPLE _NEW_POLYGON
+#define _DD_NEW_TRI_OFFSET _NEW_POLYGON
+#define _DD_NEW_LINE_SMOOTH _NEW_LINE
+#define _DD_NEW_LINE_STIPPLE _NEW_LINE
+#define _DD_NEW_LINE_WIDTH _NEW_LINE
+#define _DD_NEW_POINT_SMOOTH _NEW_POINT
+#define _DD_NEW_POINT_SIZE _NEW_POINT
+#define _DD_NEW_POINT_ATTEN _NEW_POINT
+/*@}*/
+
+
+/**
+ * Composite state flags
+ */
+/*@{*/
+#define _MESA_NEW_NEED_EYE_COORDS (_NEW_LIGHT | \
+ _NEW_TEXTURE | \
+ _NEW_POINT | \
+ _NEW_PROGRAM | \
+ _NEW_MODELVIEW)
+
+#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \
+ _NEW_TEXTURE)
+
+#define _MESA_NEW_TRANSFER_STATE (_NEW_PIXEL)
+/*@}*/
+
+
+
+
+/* This has to be included here. */
+#include "dd.h"
+
+
+/**
+ * Display list flags.
+ * Strictly this is a tnl-private concept, but it doesn't seem
+ * worthwhile adding a tnl private structure just to hold this one bit
+ * of information:
+ */
+#define DLIST_DANGLING_REFS 0x1
+
+
+/** Opaque declaration of display list payload data type */
+union gl_dlist_node;
+
+
+/**
+ * Provide a location where information about a display list can be
+ * collected. Could be extended with driverPrivate structures,
+ * etc. in the future.
+ */
+struct gl_display_list
+{
+ GLuint Name;
+ GLbitfield Flags; /**< DLIST_x flags */
+ /** The dlist commands are in a linked list of nodes */
+ union gl_dlist_node *Head;
+};
+
+
+/**
+ * State used during display list compilation and execution.
+ */
+struct gl_dlist_state
+{
+ GLuint CallDepth; /**< Current recursion calling depth */
+
+ struct gl_display_list *CurrentList; /**< List currently being compiled */
+ union gl_dlist_node *CurrentBlock; /**< Pointer to current block of nodes */
+ GLuint CurrentPos; /**< Index into current block of nodes */
+
+ GLvertexformat ListVtxfmt;
+
+ GLubyte ActiveAttribSize[VERT_ATTRIB_MAX];
+ GLfloat CurrentAttrib[VERT_ATTRIB_MAX][4];
+
+ GLubyte ActiveMaterialSize[MAT_ATTRIB_MAX];
+ GLfloat CurrentMaterial[MAT_ATTRIB_MAX][4];
+
+ GLubyte ActiveIndex;
+ GLfloat CurrentIndex;
+
+ GLubyte ActiveEdgeFlag;
+ GLboolean CurrentEdgeFlag;
+
+ struct {
+ /* State known to have been set by the currently-compiling display
+ * list. Used to eliminate some redundant state changes.
+ */
+ GLenum ShadeModel;
+ } Current;
+};
+
+
+/**
+ * Enum for the OpenGL APIs we know about and may support.
+ */
+typedef enum
+{
+ API_OPENGL,
+ API_OPENGLES,
+ API_OPENGLES2
+} gl_api;
+
+
+/**
+ * Mesa rendering context.
+ *
+ * This is the central context data structure for Mesa. Almost all
+ * OpenGL state is contained in this structure.
+ * Think of this as a base class from which device drivers will derive
+ * sub classes.
+ *
+ * The struct gl_context typedef names this structure.
+ */
+struct gl_context
+{
+ /** State possibly shared with other contexts in the address space */
+ struct gl_shared_state *Shared;
+
+ /** \name API function pointer tables */
+ /*@{*/
+ gl_api API;
+ struct _glapi_table *Save; /**< Display list save functions */
+ struct _glapi_table *Exec; /**< Execute functions */
+ struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! */
+ /*@}*/
+
+ struct gl_config Visual;
+ struct gl_framebuffer *DrawBuffer; /**< buffer for writing */
+ struct gl_framebuffer *ReadBuffer; /**< buffer for reading */
+ struct gl_framebuffer *WinSysDrawBuffer; /**< set with MakeCurrent */
+ struct gl_framebuffer *WinSysReadBuffer; /**< set with MakeCurrent */
+
+ /**
+ * Device driver function pointer table
+ */
+ struct dd_function_table Driver;
+
+ void *DriverCtx; /**< Points to device driver context/state */
+
+ /** Core/Driver constants */
+ struct gl_constants Const;
+
+ /** \name The various 4x4 matrix stacks */
+ /*@{*/
+ struct gl_matrix_stack ModelviewMatrixStack;
+ struct gl_matrix_stack ProjectionMatrixStack;
+ struct gl_matrix_stack TextureMatrixStack[MAX_TEXTURE_UNITS];
+ struct gl_matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES];
+ struct gl_matrix_stack *CurrentStack; /**< Points to one of the above stacks */
+ /*@}*/
+
+ /** Combined modelview and projection matrix */
+ GLmatrix _ModelProjectMatrix;
+
+ /** \name Display lists */
+ struct gl_dlist_state ListState;
+
+ GLboolean ExecuteFlag; /**< Execute GL commands? */
+ GLboolean CompileFlag; /**< Compile GL commands into display list? */
+
+ /** Extension information */
+ struct gl_extensions Extensions;
+
+ /** Version info */
+ GLuint VersionMajor, VersionMinor;
+ char *VersionString;
+
+ /** \name State attribute stack (for glPush/PopAttrib) */
+ /*@{*/
+ GLuint AttribStackDepth;
+ struct gl_attrib_node *AttribStack[MAX_ATTRIB_STACK_DEPTH];
+ /*@}*/
+
+ /** \name Renderer attribute groups
+ *
+ * We define a struct for each attribute group to make pushing and popping
+ * attributes easy. Also it's a good organization.
+ */
+ /*@{*/
+ struct gl_accum_attrib Accum; /**< Accum buffer attributes */
+ struct gl_colorbuffer_attrib Color; /**< Color buffer attributes */
+ struct gl_current_attrib Current; /**< Current attributes */
+ struct gl_depthbuffer_attrib Depth; /**< Depth buffer attributes */
+ struct gl_eval_attrib Eval; /**< Eval attributes */
+ struct gl_fog_attrib Fog; /**< Fog attributes */
+ struct gl_hint_attrib Hint; /**< Hint attributes */
+ struct gl_light_attrib Light; /**< Light attributes */
+ struct gl_line_attrib Line; /**< Line attributes */
+ struct gl_list_attrib List; /**< List attributes */
+ struct gl_multisample_attrib Multisample;
+ struct gl_pixel_attrib Pixel; /**< Pixel attributes */
+ struct gl_point_attrib Point; /**< Point attributes */
+ struct gl_polygon_attrib Polygon; /**< Polygon attributes */
+ GLuint PolygonStipple[32]; /**< Polygon stipple */
+ struct gl_scissor_attrib Scissor; /**< Scissor attributes */
+ struct gl_stencil_attrib Stencil; /**< Stencil buffer attributes */
+ struct gl_texture_attrib Texture; /**< Texture attributes */
+ struct gl_transform_attrib Transform; /**< Transformation attributes */
+ struct gl_viewport_attrib Viewport; /**< Viewport attributes */
+ /*@}*/
+
+ /** \name Client attribute stack */
+ /*@{*/
+ GLuint ClientAttribStackDepth;
+ struct gl_attrib_node *ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH];
+ /*@}*/
+
+ /** \name Client attribute groups */
+ /*@{*/
+ struct gl_array_attrib Array; /**< Vertex arrays */
+ struct gl_pixelstore_attrib Pack; /**< Pixel packing */
+ struct gl_pixelstore_attrib Unpack; /**< Pixel unpacking */
+ struct gl_pixelstore_attrib DefaultPacking; /**< Default params */
+ /*@}*/
+
+ /** \name Other assorted state (not pushed/popped on attribute stack) */
+ /*@{*/
+ struct gl_pixelmaps PixelMaps;
+
+ struct gl_evaluators EvalMap; /**< All evaluators */
+ struct gl_feedback Feedback; /**< Feedback */
+ struct gl_selection Select; /**< Selection */
+
+ struct gl_program_state Program; /**< general program state */
+ struct gl_vertex_program_state VertexProgram;
+ struct gl_fragment_program_state FragmentProgram;
+ struct gl_geometry_program_state GeometryProgram;
+ struct gl_ati_fragment_shader_state ATIFragmentShader;
+
+ struct gl_shader_state Shader; /**< GLSL shader object state */
+ struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_TYPES];
+
+ struct gl_query_state Query; /**< occlusion, timer queries */
+
+ struct gl_transform_feedback TransformFeedback;
+
+ struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
+ struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */
+ /*@}*/
+
+ struct gl_meta_state *Meta; /**< for "meta" operations */
+
+ /* GL_EXT_framebuffer_object */
+ struct gl_renderbuffer *CurrentRenderbuffer;
+
+ GLenum ErrorValue; /**< Last error code */
+
+ /**
+ * Recognize and silence repeated error debug messages in buggy apps.
+ */
+ const char *ErrorDebugFmtString;
+ GLuint ErrorDebugCount;
+
+ GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
+ GLbitfield NewState; /**< bitwise-or of _NEW_* flags */
+
+ GLboolean ViewportInitialized; /**< has viewport size been initialized? */
+
+ GLbitfield varying_vp_inputs; /**< mask of VERT_BIT_* flags */
+
+ /** \name Derived state */
+ /*@{*/
+ /** Bitwise-or of DD_* flags. Note that this bitfield may be used before
+ * state validation so they need to always be current.
+ */
+ GLbitfield _TriangleCaps;
+ GLbitfield _ImageTransferState;/**< bitwise-or of IMAGE_*_BIT flags */
+ GLfloat _EyeZDir[3];
+ GLfloat _ModelViewInvScale;
+ GLboolean _NeedEyeCoords;
+ GLboolean _ForceEyeCoords;
+
+ GLuint TextureStateTimestamp; /**< detect changes to shared state */
+
+ struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */
+ struct gl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
+ /**@}*/
+
+ struct gl_list_extensions *ListExt; /**< driver dlist extensions */
+
+ /** \name For debugging/development only */
+ /*@{*/
+ GLboolean FirstTimeCurrent;
+ /*@}*/
+
+ /** software compression/decompression supported or not */
+ GLboolean Mesa_DXTn;
+
+ GLboolean TextureFormatSupported[MESA_FORMAT_COUNT];
+
+ /**
+ * Use dp4 (rather than mul/mad) instructions for position
+ * transformation?
+ */
+ GLboolean mvp_with_dp4;
+
+ /**
+ * \name Hooks for module contexts.
+ *
+ * These will eventually live in the driver or elsewhere.
+ */
+ /*@{*/
+ void *swrast_context;
+ void *swsetup_context;
+ void *swtnl_context;
+ void *swtnl_im;
+ struct st_context *st;
+ void *aelt_context;
+ /*@}*/
+};
+
+
+#ifdef DEBUG
+extern int MESA_VERBOSE;
+extern int MESA_DEBUG_FLAGS;
+# define MESA_FUNCTION __FUNCTION__
+#else
+# define MESA_VERBOSE 0
+# define MESA_DEBUG_FLAGS 0
+# define MESA_FUNCTION "a function"
+# ifndef NDEBUG
+# define NDEBUG
+# endif
+#endif
+
+
+/** The MESA_VERBOSE var is a bitmask of these flags */
+enum _verbose
+{
+ VERBOSE_VARRAY = 0x0001,
+ VERBOSE_TEXTURE = 0x0002,
+ VERBOSE_MATERIAL = 0x0004,
+ VERBOSE_PIPELINE = 0x0008,
+ VERBOSE_DRIVER = 0x0010,
+ VERBOSE_STATE = 0x0020,
+ VERBOSE_API = 0x0040,
+ VERBOSE_DISPLAY_LIST = 0x0100,
+ VERBOSE_LIGHTING = 0x0200,
+ VERBOSE_PRIMS = 0x0400,
+ VERBOSE_VERTS = 0x0800,
+ VERBOSE_DISASSEM = 0x1000,
+ VERBOSE_DRAW = 0x2000,
+ VERBOSE_SWAPBUFFERS = 0x4000
+};
+
+
+/** The MESA_DEBUG_FLAGS var is a bitmask of these flags */
+enum _debug
+{
+ DEBUG_ALWAYS_FLUSH = 0x1
+};
+
+
+
+#endif /* MTYPES_H */
diff --git a/mesalib/src/mesa/main/pbo.c b/mesalib/src/mesa/main/pbo.c
new file mode 100644
index 000000000..dc00d423b
--- /dev/null
+++ b/mesalib/src/mesa/main/pbo.c
@@ -0,0 +1,372 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009-2011 VMware, Inc. 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
+ * THE AUTHORS 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 pbo.c
+ * \brief Functions related to Pixel Buffer Objects.
+ */
+
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "image.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "pbo.h"
+
+
+
+/**
+ * When we're about to read pixel data out of a PBO (via glDrawPixels,
+ * glTexImage, etc) or write data into a PBO (via glReadPixels,
+ * glGetTexImage, etc) we call this function to check that we're not
+ * going to read out of bounds.
+ *
+ * XXX This would also be a convenient time to check that the PBO isn't
+ * currently mapped. Whoever calls this function should check for that.
+ * Remember, we can't use a PBO when it's mapped!
+ *
+ * If we're not using a PBO, this is a no-op.
+ *
+ * \param width width of image to read/write
+ * \param height height of image to read/write
+ * \param depth depth of image to read/write
+ * \param format format of image to read/write
+ * \param type datatype of image to read/write
+ * \param ptr the user-provided pointer/offset
+ * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
+ * go out of bounds.
+ */
+GLboolean
+_mesa_validate_pbo_access(GLuint dimensions,
+ const struct gl_pixelstore_attrib *pack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr)
+{
+ GLvoid *start, *end;
+ const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
+
+ if (!_mesa_is_bufferobj(pack->BufferObj))
+ return GL_TRUE; /* no PBO, OK */
+
+ if (pack->BufferObj->Size == 0)
+ /* no buffer! */
+ return GL_FALSE;
+
+ /* get address of first pixel we'll read */
+ start = _mesa_image_address(dimensions, pack, ptr, width, height,
+ format, type, 0, 0, 0);
+
+ /* get address just past the last pixel we'll read */
+ end = _mesa_image_address(dimensions, pack, ptr, width, height,
+ format, type, depth-1, height-1, width);
+
+
+ sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
+
+ if ((const GLubyte *) start > sizeAddr) {
+ /* This will catch negative values / wrap-around */
+ return GL_FALSE;
+ }
+ if ((const GLubyte *) end > sizeAddr) {
+ /* Image read goes beyond end of buffer */
+ return GL_FALSE;
+ }
+
+ /* OK! */
+ return GL_TRUE;
+}
+
+
+/**
+ * For commands that read from a PBO (glDrawPixels, glTexImage,
+ * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
+ * and return the pointer into the PBO. If we're not reading from a
+ * PBO, return \p src as-is.
+ * If non-null return, must call _mesa_unmap_pbo_source() when done.
+ *
+ * \return NULL if error, else pointer to start of data
+ */
+const GLvoid *
+_mesa_map_pbo_source(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *src)
+{
+ const GLubyte *buf;
+
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* unpack from PBO */
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB,
+ unpack->BufferObj);
+ if (!buf)
+ return NULL;
+
+ buf = ADD_POINTERS(buf, src);
+ }
+ else {
+ /* unpack from normal memory */
+ buf = src;
+ }
+
+ return buf;
+}
+
+
+/**
+ * Combine PBO-read validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_source
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_source().
+ */
+const GLvoid *
+_mesa_map_validate_pbo_source(struct gl_context *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr,
+ const char *where)
+{
+ ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* non-PBO access: no validation to be done */
+ return ptr;
+ }
+
+ if (!_mesa_validate_pbo_access(dimensions, unpack,
+ width, height, depth, format, type, ptr)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(out of bounds PBO access)", where);
+ return NULL;
+ }
+
+ if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+ return NULL;
+ }
+
+ ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
+ return ptr;
+}
+
+
+/**
+ * Counterpart to _mesa_map_pbo_source()
+ */
+void
+_mesa_unmap_pbo_source(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *unpack)
+{
+ ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ unpack->BufferObj);
+ }
+}
+
+
+/**
+ * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
+ * if we're writing to a PBO, map it write-only and return the pointer
+ * into the PBO. If we're not writing to a PBO, return \p dst as-is.
+ * If non-null return, must call _mesa_unmap_pbo_dest() when done.
+ *
+ * \return NULL if error, else pointer to start of data
+ */
+void *
+_mesa_map_pbo_dest(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+ void *buf;
+
+ if (_mesa_is_bufferobj(pack->BufferObj)) {
+ /* pack into PBO */
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ pack->BufferObj);
+ if (!buf)
+ return NULL;
+
+ buf = ADD_POINTERS(buf, dest);
+ }
+ else {
+ /* pack to normal memory */
+ buf = dest;
+ }
+
+ return buf;
+}
+
+
+/**
+ * Combine PBO-write validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_dest
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_dest().
+ */
+GLvoid *
+_mesa_map_validate_pbo_dest(struct gl_context *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, GLvoid *ptr,
+ const char *where)
+{
+ ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* non-PBO access: no validation to be done */
+ return ptr;
+ }
+
+ if (!_mesa_validate_pbo_access(dimensions, unpack,
+ width, height, depth, format, type, ptr)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(out of bounds PBO access)", where);
+ return NULL;
+ }
+
+ if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+ return NULL;
+ }
+
+ ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
+ return ptr;
+}
+
+
+/**
+ * Counterpart to _mesa_map_pbo_dest()
+ */
+void
+_mesa_unmap_pbo_dest(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *pack)
+{
+ ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
+ if (_mesa_is_bufferobj(pack->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
+ }
+}
+
+
+
+/**
+ * Check if an unpack PBO is active prior to fetching a texture image.
+ * If so, do bounds checking and map the buffer into main memory.
+ * Any errors detected will be recorded.
+ * The caller _must_ call _mesa_unmap_teximage_pbo() too!
+ */
+const GLvoid *
+_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ const char *funcName)
+{
+ GLubyte *buf;
+
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* no PBO */
+ return pixels;
+ }
+ if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)");
+ return NULL;
+ }
+
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, unpack->BufferObj);
+ if (!buf) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped)");
+ return NULL;
+ }
+
+ return ADD_POINTERS(buf, pixels);
+}
+
+
+/**
+ * Check if an unpack PBO is active prior to fetching a compressed texture
+ * image.
+ * If so, do bounds checking and map the buffer into main memory.
+ * Any errors detected will be recorded.
+ * The caller _must_ call _mesa_unmap_teximage_pbo() too!
+ */
+const GLvoid *
+_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
+ GLsizei imageSize, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ const char *funcName)
+{
+ GLubyte *buf;
+
+ if (!_mesa_is_bufferobj(packing->BufferObj)) {
+ /* not using a PBO - return pointer unchanged */
+ return pixels;
+ }
+ if ((const GLubyte *) pixels + imageSize >
+ ((const GLubyte *) 0) + packing->BufferObj->Size) {
+ /* out of bounds read! */
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)");
+ return NULL;
+ }
+
+ buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, packing->BufferObj);
+ if (!buf) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
+ return NULL;
+ }
+
+ return ADD_POINTERS(buf, pixels);
+}
+
+
+/**
+ * This function must be called after either of the validate_pbo_*_teximage()
+ * functions. It unmaps the PBO buffer if it was mapped earlier.
+ */
+void
+_mesa_unmap_teximage_pbo(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *unpack)
+{
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ unpack->BufferObj);
+ }
+}
+
+
diff --git a/mesalib/src/mesa/main/pbo.h b/mesalib/src/mesa/main/pbo.h
new file mode 100644
index 000000000..0cddd72ba
--- /dev/null
+++ b/mesalib/src/mesa/main/pbo.h
@@ -0,0 +1,92 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009-2011 VMware, Inc. 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
+ * THE AUTHORS 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 PBO_H
+#define PBO_H
+
+
+#include "mtypes.h"
+
+
+extern GLboolean
+_mesa_validate_pbo_access(GLuint dimensions,
+ const struct gl_pixelstore_attrib *pack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr);
+
+extern const GLvoid *
+_mesa_map_pbo_source(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *src);
+
+extern const GLvoid *
+_mesa_map_validate_pbo_source(struct gl_context *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr,
+ const char *where);
+
+extern void
+_mesa_unmap_pbo_source(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *unpack);
+
+extern void *
+_mesa_map_pbo_dest(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest);
+
+extern GLvoid *
+_mesa_map_validate_pbo_dest(struct gl_context *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, GLvoid *ptr,
+ const char *where);
+
+extern void
+_mesa_unmap_pbo_dest(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *pack);
+
+
+extern const GLvoid *
+_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ const char *funcName);
+
+extern const GLvoid *
+_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
+ GLsizei imageSize, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ const char *funcName);
+
+extern void
+_mesa_unmap_teximage_pbo(struct gl_context *ctx,
+ const struct gl_pixelstore_attrib *unpack);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/pixel.c b/mesalib/src/mesa/main/pixel.c
index 2b4934fd3..195fa234b 100644
--- a/mesalib/src/mesa/main/pixel.c
+++ b/mesalib/src/mesa/main/pixel.c
@@ -1,701 +1,699 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2008 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 pixel.c
- * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
- */
-
-#include "glheader.h"
-#include "bufferobj.h"
-#include "colormac.h"
-#include "context.h"
-#include "macros.h"
-#include "mfeatures.h"
-#include "pixel.h"
-#include "mtypes.h"
-#include "main/dispatch.h"
-
-
-#if FEATURE_pixel_transfer
-
-
-/**********************************************************************/
-/***** glPixelZoom *****/
-/**********************************************************************/
-
-static void GLAPIENTRY
-_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if (ctx->Pixel.ZoomX == xfactor &&
- ctx->Pixel.ZoomY == yfactor)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.ZoomX = xfactor;
- ctx->Pixel.ZoomY = yfactor;
-}
-
-
-
-/**********************************************************************/
-/***** glPixelMap *****/
-/**********************************************************************/
-
-/**
- * Return pointer to a pixelmap by name.
- */
-static struct gl_pixelmap *
-get_pixelmap(struct gl_context *ctx, GLenum map)
-{
- switch (map) {
- case GL_PIXEL_MAP_I_TO_I:
- return &ctx->PixelMaps.ItoI;
- case GL_PIXEL_MAP_S_TO_S:
- return &ctx->PixelMaps.StoS;
- case GL_PIXEL_MAP_I_TO_R:
- return &ctx->PixelMaps.ItoR;
- case GL_PIXEL_MAP_I_TO_G:
- return &ctx->PixelMaps.ItoG;
- case GL_PIXEL_MAP_I_TO_B:
- return &ctx->PixelMaps.ItoB;
- case GL_PIXEL_MAP_I_TO_A:
- return &ctx->PixelMaps.ItoA;
- case GL_PIXEL_MAP_R_TO_R:
- return &ctx->PixelMaps.RtoR;
- case GL_PIXEL_MAP_G_TO_G:
- return &ctx->PixelMaps.GtoG;
- case GL_PIXEL_MAP_B_TO_B:
- return &ctx->PixelMaps.BtoB;
- case GL_PIXEL_MAP_A_TO_A:
- return &ctx->PixelMaps.AtoA;
- default:
- return NULL;
- }
-}
-
-
-/**
- * Helper routine used by the other _mesa_PixelMap() functions.
- */
-static void
-store_pixelmap(struct gl_context *ctx, GLenum map, GLsizei mapsize,
- const GLfloat *values)
-{
- GLint i;
- struct gl_pixelmap *pm = get_pixelmap(ctx, map);
- if (!pm) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
- return;
- }
-
- switch (map) {
- case GL_PIXEL_MAP_S_TO_S:
- /* special case */
- ctx->PixelMaps.StoS.Size = mapsize;
- for (i = 0; i < mapsize; i++) {
- ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
- }
- break;
- case GL_PIXEL_MAP_I_TO_I:
- /* special case */
- ctx->PixelMaps.ItoI.Size = mapsize;
- for (i = 0; i < mapsize; i++) {
- ctx->PixelMaps.ItoI.Map[i] = values[i];
- }
- break;
- default:
- /* general case */
- pm->Size = mapsize;
- for (i = 0; i < mapsize; i++) {
- GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
- pm->Map[i] = val;
- pm->Map8[i] = (GLint) (val * 255.0F);
- }
- }
-}
-
-
-/**
- * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
- */
-static GLboolean
-validate_pbo_access(struct gl_context *ctx, struct gl_pixelstore_attrib *pack,
- GLsizei mapsize, GLenum format, GLenum type,
- const GLvoid *ptr)
-{
- GLboolean ok;
-
- /* Note, need to use DefaultPacking and Unpack's buffer object */
- _mesa_reference_buffer_object(ctx,
- &ctx->DefaultPacking.BufferObj,
- pack->BufferObj);
-
- ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
- format, type, ptr);
-
- /* restore */
- _mesa_reference_buffer_object(ctx,
- &ctx->DefaultPacking.BufferObj,
- ctx->Shared->NullBufferObj);
-
- if (!ok) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPixelMap(invalid PBO access)");
- }
- return ok;
-}
-
-
-static void GLAPIENTRY
-_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
- if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
- return;
- }
-
- if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
- /* test that mapsize is a power of two */
- if (!_mesa_is_pow_two(mapsize)) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
- return;
- }
- }
-
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
-
- if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
- GL_INTENSITY, GL_FLOAT, values)) {
- return;
- }
-
- values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
- if (!values) {
- if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPixelMapfv(PBO is mapped)");
- }
- return;
- }
-
- store_pixelmap(ctx, map, mapsize, values);
-
- _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
-}
-
-
-static void GLAPIENTRY
-_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
-{
- GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
- return;
- }
-
- if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
- /* test that mapsize is a power of two */
- if (!_mesa_is_pow_two(mapsize)) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
- return;
- }
- }
-
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
-
- if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
- GL_INTENSITY, GL_UNSIGNED_INT, values)) {
- return;
- }
-
- values = (const GLuint *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
- if (!values) {
- if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPixelMapuiv(PBO is mapped)");
- }
- return;
- }
-
- /* convert to floats */
- if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
- GLint i;
- for (i = 0; i < mapsize; i++) {
- fvalues[i] = (GLfloat) values[i];
- }
- }
- else {
- GLint i;
- for (i = 0; i < mapsize; i++) {
- fvalues[i] = UINT_TO_FLOAT( values[i] );
- }
- }
-
- _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
-
- store_pixelmap(ctx, map, mapsize, fvalues);
-}
-
-
-static void GLAPIENTRY
-_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
-{
- GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
- return;
- }
-
- if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
- /* test that mapsize is a power of two */
- if (!_mesa_is_pow_two(mapsize)) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
- return;
- }
- }
-
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
-
- if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
- GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
- return;
- }
-
- values = (const GLushort *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
- if (!values) {
- if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPixelMapusv(PBO is mapped)");
- }
- return;
- }
-
- /* convert to floats */
- if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
- GLint i;
- for (i = 0; i < mapsize; i++) {
- fvalues[i] = (GLfloat) values[i];
- }
- }
- else {
- GLint i;
- for (i = 0; i < mapsize; i++) {
- fvalues[i] = USHORT_TO_FLOAT( values[i] );
- }
- }
-
- _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
-
- store_pixelmap(ctx, map, mapsize, fvalues);
-}
-
-
-static void GLAPIENTRY
-_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
-{
- GET_CURRENT_CONTEXT(ctx);
- GLuint mapsize, i;
- const struct gl_pixelmap *pm;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- pm = get_pixelmap(ctx, map);
- if (!pm) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
- return;
- }
-
- mapsize = pm->Size;
-
- if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
- GL_INTENSITY, GL_FLOAT, values)) {
- return;
- }
-
- values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
- if (!values) {
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPixelMapfv(PBO is mapped)");
- }
- return;
- }
-
- if (map == GL_PIXEL_MAP_S_TO_S) {
- /* special case */
- for (i = 0; i < mapsize; i++) {
- values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
- }
- }
- else {
- memcpy(values, pm->Map, mapsize * sizeof(GLfloat));
- }
-
- _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
-}
-
-
-static void GLAPIENTRY
-_mesa_GetPixelMapuiv( GLenum map, GLuint *values )
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint mapsize, i;
- const struct gl_pixelmap *pm;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- pm = get_pixelmap(ctx, map);
- if (!pm) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
- return;
- }
- mapsize = pm->Size;
-
- if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
- GL_INTENSITY, GL_UNSIGNED_INT, values)) {
- return;
- }
-
- values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
- if (!values) {
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPixelMapuiv(PBO is mapped)");
- }
- return;
- }
-
- if (map == GL_PIXEL_MAP_S_TO_S) {
- /* special case */
- memcpy(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
- }
- else {
- for (i = 0; i < mapsize; i++) {
- values[i] = FLOAT_TO_UINT( pm->Map[i] );
- }
- }
-
- _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
-}
-
-
-static void GLAPIENTRY
-_mesa_GetPixelMapusv( GLenum map, GLushort *values )
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint mapsize, i;
- const struct gl_pixelmap *pm;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- pm = get_pixelmap(ctx, map);
- if (!pm) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
- return;
- }
- mapsize = pm->Size;
-
- if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
- GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
- return;
- }
-
- values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
- if (!values) {
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPixelMapusv(PBO is mapped)");
- }
- return;
- }
-
- switch (map) {
- /* special cases */
- case GL_PIXEL_MAP_I_TO_I:
- for (i = 0; i < mapsize; i++) {
- values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
- }
- break;
- case GL_PIXEL_MAP_S_TO_S:
- for (i = 0; i < mapsize; i++) {
- values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
- }
- break;
- default:
- for (i = 0; i < mapsize; i++) {
- CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
- }
- }
-
- _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
-}
-
-
-
-/**********************************************************************/
-/***** glPixelTransfer *****/
-/**********************************************************************/
-
-
-/*
- * Implements glPixelTransfer[fi] whether called immediately or from a
- * display list.
- */
-static void GLAPIENTRY
-_mesa_PixelTransferf( GLenum pname, GLfloat param )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- switch (pname) {
- case GL_MAP_COLOR:
- if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
- break;
- case GL_MAP_STENCIL:
- if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
- break;
- case GL_INDEX_SHIFT:
- if (ctx->Pixel.IndexShift == (GLint) param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.IndexShift = (GLint) param;
- break;
- case GL_INDEX_OFFSET:
- if (ctx->Pixel.IndexOffset == (GLint) param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.IndexOffset = (GLint) param;
- break;
- case GL_RED_SCALE:
- if (ctx->Pixel.RedScale == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.RedScale = param;
- break;
- case GL_RED_BIAS:
- if (ctx->Pixel.RedBias == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.RedBias = param;
- break;
- case GL_GREEN_SCALE:
- if (ctx->Pixel.GreenScale == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.GreenScale = param;
- break;
- case GL_GREEN_BIAS:
- if (ctx->Pixel.GreenBias == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.GreenBias = param;
- break;
- case GL_BLUE_SCALE:
- if (ctx->Pixel.BlueScale == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.BlueScale = param;
- break;
- case GL_BLUE_BIAS:
- if (ctx->Pixel.BlueBias == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.BlueBias = param;
- break;
- case GL_ALPHA_SCALE:
- if (ctx->Pixel.AlphaScale == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.AlphaScale = param;
- break;
- case GL_ALPHA_BIAS:
- if (ctx->Pixel.AlphaBias == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.AlphaBias = param;
- break;
- case GL_DEPTH_SCALE:
- if (ctx->Pixel.DepthScale == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.DepthScale = param;
- break;
- case GL_DEPTH_BIAS:
- if (ctx->Pixel.DepthBias == param)
- return;
- FLUSH_VERTICES(ctx, _NEW_PIXEL);
- ctx->Pixel.DepthBias = param;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
- return;
- }
-}
-
-
-static void GLAPIENTRY
-_mesa_PixelTransferi( GLenum pname, GLint param )
-{
- _mesa_PixelTransferf( pname, (GLfloat) param );
-}
-
-
-
-/**********************************************************************/
-/***** State Management *****/
-/**********************************************************************/
-
-/*
- * Return a bitmask of IMAGE_*_BIT flags which to indicate which
- * pixel transfer operations are enabled.
- */
-static void
-update_image_transfer_state(struct gl_context *ctx)
-{
- GLuint mask = 0;
-
- if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F ||
- ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
- ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F ||
- ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
- mask |= IMAGE_SCALE_BIAS_BIT;
-
- if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
- mask |= IMAGE_SHIFT_OFFSET_BIT;
-
- if (ctx->Pixel.MapColorFlag)
- mask |= IMAGE_MAP_COLOR_BIT;
-
- ctx->_ImageTransferState = mask;
-}
-
-
-/**
- * Update mesa pixel transfer derived state.
- */
-void _mesa_update_pixel( struct gl_context *ctx, GLuint new_state )
-{
- if (new_state & _MESA_NEW_TRANSFER_STATE)
- update_image_transfer_state(ctx);
-}
-
-
-void
-_mesa_init_pixel_dispatch(struct _glapi_table *disp)
-{
- SET_GetPixelMapfv(disp, _mesa_GetPixelMapfv);
- SET_GetPixelMapuiv(disp, _mesa_GetPixelMapuiv);
- SET_GetPixelMapusv(disp, _mesa_GetPixelMapusv);
- SET_PixelMapfv(disp, _mesa_PixelMapfv);
- SET_PixelMapuiv(disp, _mesa_PixelMapuiv);
- SET_PixelMapusv(disp, _mesa_PixelMapusv);
- SET_PixelTransferf(disp, _mesa_PixelTransferf);
- SET_PixelTransferi(disp, _mesa_PixelTransferi);
- SET_PixelZoom(disp, _mesa_PixelZoom);
-}
-
-
-#endif /* FEATURE_pixel_transfer */
-
-
-/**********************************************************************/
-/***** Initialization *****/
-/**********************************************************************/
-
-static void
-init_pixelmap(struct gl_pixelmap *map)
-{
- map->Size = 1;
- map->Map[0] = 0.0;
- map->Map8[0] = 0;
-}
-
-
-/**
- * Initialize the context's PIXEL attribute group.
- */
-void
-_mesa_init_pixel( struct gl_context *ctx )
-{
- /* Pixel group */
- ctx->Pixel.RedBias = 0.0;
- ctx->Pixel.RedScale = 1.0;
- ctx->Pixel.GreenBias = 0.0;
- ctx->Pixel.GreenScale = 1.0;
- ctx->Pixel.BlueBias = 0.0;
- ctx->Pixel.BlueScale = 1.0;
- ctx->Pixel.AlphaBias = 0.0;
- ctx->Pixel.AlphaScale = 1.0;
- ctx->Pixel.DepthBias = 0.0;
- ctx->Pixel.DepthScale = 1.0;
- ctx->Pixel.IndexOffset = 0;
- ctx->Pixel.IndexShift = 0;
- ctx->Pixel.ZoomX = 1.0;
- ctx->Pixel.ZoomY = 1.0;
- ctx->Pixel.MapColorFlag = GL_FALSE;
- ctx->Pixel.MapStencilFlag = GL_FALSE;
- init_pixelmap(&ctx->PixelMaps.StoS);
- init_pixelmap(&ctx->PixelMaps.ItoI);
- init_pixelmap(&ctx->PixelMaps.ItoR);
- init_pixelmap(&ctx->PixelMaps.ItoG);
- init_pixelmap(&ctx->PixelMaps.ItoB);
- init_pixelmap(&ctx->PixelMaps.ItoA);
- init_pixelmap(&ctx->PixelMaps.RtoR);
- init_pixelmap(&ctx->PixelMaps.GtoG);
- init_pixelmap(&ctx->PixelMaps.BtoB);
- init_pixelmap(&ctx->PixelMaps.AtoA);
- /* GL_SGI_texture_color_table */
- ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
- ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
-
- if (ctx->Visual.doubleBufferMode) {
- ctx->Pixel.ReadBuffer = GL_BACK;
- }
- else {
- ctx->Pixel.ReadBuffer = GL_FRONT;
- }
-
- /* Miscellaneous */
- ctx->_ImageTransferState = 0;
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 pixel.c
+ * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
+ */
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "colormac.h"
+#include "context.h"
+#include "macros.h"
+#include "mfeatures.h"
+#include "pixel.h"
+#include "pbo.h"
+#include "mtypes.h"
+#include "main/dispatch.h"
+
+
+#if FEATURE_pixel_transfer
+
+
+/**********************************************************************/
+/***** glPixelZoom *****/
+/**********************************************************************/
+
+static void GLAPIENTRY
+_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx->Pixel.ZoomX == xfactor &&
+ ctx->Pixel.ZoomY == yfactor)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.ZoomX = xfactor;
+ ctx->Pixel.ZoomY = yfactor;
+}
+
+
+
+/**********************************************************************/
+/***** glPixelMap *****/
+/**********************************************************************/
+
+/**
+ * Return pointer to a pixelmap by name.
+ */
+static struct gl_pixelmap *
+get_pixelmap(struct gl_context *ctx, GLenum map)
+{
+ switch (map) {
+ case GL_PIXEL_MAP_I_TO_I:
+ return &ctx->PixelMaps.ItoI;
+ case GL_PIXEL_MAP_S_TO_S:
+ return &ctx->PixelMaps.StoS;
+ case GL_PIXEL_MAP_I_TO_R:
+ return &ctx->PixelMaps.ItoR;
+ case GL_PIXEL_MAP_I_TO_G:
+ return &ctx->PixelMaps.ItoG;
+ case GL_PIXEL_MAP_I_TO_B:
+ return &ctx->PixelMaps.ItoB;
+ case GL_PIXEL_MAP_I_TO_A:
+ return &ctx->PixelMaps.ItoA;
+ case GL_PIXEL_MAP_R_TO_R:
+ return &ctx->PixelMaps.RtoR;
+ case GL_PIXEL_MAP_G_TO_G:
+ return &ctx->PixelMaps.GtoG;
+ case GL_PIXEL_MAP_B_TO_B:
+ return &ctx->PixelMaps.BtoB;
+ case GL_PIXEL_MAP_A_TO_A:
+ return &ctx->PixelMaps.AtoA;
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Helper routine used by the other _mesa_PixelMap() functions.
+ */
+static void
+store_pixelmap(struct gl_context *ctx, GLenum map, GLsizei mapsize,
+ const GLfloat *values)
+{
+ GLint i;
+ struct gl_pixelmap *pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
+ return;
+ }
+
+ switch (map) {
+ case GL_PIXEL_MAP_S_TO_S:
+ /* special case */
+ ctx->PixelMaps.StoS.Size = mapsize;
+ for (i = 0; i < mapsize; i++) {
+ ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_I:
+ /* special case */
+ ctx->PixelMaps.ItoI.Size = mapsize;
+ for (i = 0; i < mapsize; i++) {
+ ctx->PixelMaps.ItoI.Map[i] = values[i];
+ }
+ break;
+ default:
+ /* general case */
+ pm->Size = mapsize;
+ for (i = 0; i < mapsize; i++) {
+ GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
+ pm->Map[i] = val;
+ pm->Map8[i] = (GLint) (val * 255.0F);
+ }
+ }
+}
+
+
+/**
+ * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
+ */
+static GLboolean
+validate_pbo_access(struct gl_context *ctx, struct gl_pixelstore_attrib *pack,
+ GLsizei mapsize, GLenum format, GLenum type,
+ const GLvoid *ptr)
+{
+ GLboolean ok;
+
+ /* Note, need to use DefaultPacking and Unpack's buffer object */
+ _mesa_reference_buffer_object(ctx,
+ &ctx->DefaultPacking.BufferObj,
+ pack->BufferObj);
+
+ ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
+ format, type, ptr);
+
+ /* restore */
+ _mesa_reference_buffer_object(ctx,
+ &ctx->DefaultPacking.BufferObj,
+ ctx->Shared->NullBufferObj);
+
+ if (!ok) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMap(invalid PBO access)");
+ }
+ return ok;
+}
+
+
+static void GLAPIENTRY
+_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
+ if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
+ return;
+ }
+
+ if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
+ /* test that mapsize is a power of two */
+ if (!_mesa_is_pow_two(mapsize)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
+ return;
+ }
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_FLOAT, values)) {
+ return;
+ }
+
+ values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMapfv(PBO is mapped)");
+ }
+ return;
+ }
+
+ store_pixelmap(ctx, map, mapsize, values);
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+}
+
+
+static void GLAPIENTRY
+_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
+{
+ GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
+ return;
+ }
+
+ if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
+ /* test that mapsize is a power of two */
+ if (!_mesa_is_pow_two(mapsize)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
+ return;
+ }
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_INT, values)) {
+ return;
+ }
+
+ values = (const GLuint *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMapuiv(PBO is mapped)");
+ }
+ return;
+ }
+
+ /* convert to floats */
+ if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = UINT_TO_FLOAT( values[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+
+ store_pixelmap(ctx, map, mapsize, fvalues);
+}
+
+
+static void GLAPIENTRY
+_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
+{
+ GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
+ return;
+ }
+
+ if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
+ /* test that mapsize is a power of two */
+ if (!_mesa_is_pow_two(mapsize)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
+ return;
+ }
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
+ return;
+ }
+
+ values = (const GLushort *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMapusv(PBO is mapped)");
+ }
+ return;
+ }
+
+ /* convert to floats */
+ if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = USHORT_TO_FLOAT( values[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+
+ store_pixelmap(ctx, map, mapsize, fvalues);
+}
+
+
+static void GLAPIENTRY
+_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint mapsize, i;
+ const struct gl_pixelmap *pm;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
+ return;
+ }
+
+ mapsize = pm->Size;
+
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_FLOAT, values)) {
+ return;
+ }
+
+ values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetPixelMapfv(PBO is mapped)");
+ }
+ return;
+ }
+
+ if (map == GL_PIXEL_MAP_S_TO_S) {
+ /* special case */
+ for (i = 0; i < mapsize; i++) {
+ values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
+ }
+ }
+ else {
+ memcpy(values, pm->Map, mapsize * sizeof(GLfloat));
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+static void GLAPIENTRY
+_mesa_GetPixelMapuiv( GLenum map, GLuint *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint mapsize, i;
+ const struct gl_pixelmap *pm;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
+ return;
+ }
+ mapsize = pm->Size;
+
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_INT, values)) {
+ return;
+ }
+
+ values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetPixelMapuiv(PBO is mapped)");
+ }
+ return;
+ }
+
+ if (map == GL_PIXEL_MAP_S_TO_S) {
+ /* special case */
+ memcpy(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
+ }
+ else {
+ for (i = 0; i < mapsize; i++) {
+ values[i] = FLOAT_TO_UINT( pm->Map[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+static void GLAPIENTRY
+_mesa_GetPixelMapusv( GLenum map, GLushort *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint mapsize, i;
+ const struct gl_pixelmap *pm;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
+ return;
+ }
+ mapsize = pm->Size;
+
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
+ return;
+ }
+
+ values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetPixelMapusv(PBO is mapped)");
+ }
+ return;
+ }
+
+ switch (map) {
+ /* special cases */
+ case GL_PIXEL_MAP_I_TO_I:
+ for (i = 0; i < mapsize; i++) {
+ values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
+ }
+ break;
+ case GL_PIXEL_MAP_S_TO_S:
+ for (i = 0; i < mapsize; i++) {
+ values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
+ }
+ break;
+ default:
+ for (i = 0; i < mapsize; i++) {
+ CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+
+/**********************************************************************/
+/***** glPixelTransfer *****/
+/**********************************************************************/
+
+
+/*
+ * Implements glPixelTransfer[fi] whether called immediately or from a
+ * display list.
+ */
+static void GLAPIENTRY
+_mesa_PixelTransferf( GLenum pname, GLfloat param )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (pname) {
+ case GL_MAP_COLOR:
+ if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_MAP_STENCIL:
+ if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_INDEX_SHIFT:
+ if (ctx->Pixel.IndexShift == (GLint) param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.IndexShift = (GLint) param;
+ break;
+ case GL_INDEX_OFFSET:
+ if (ctx->Pixel.IndexOffset == (GLint) param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.IndexOffset = (GLint) param;
+ break;
+ case GL_RED_SCALE:
+ if (ctx->Pixel.RedScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.RedScale = param;
+ break;
+ case GL_RED_BIAS:
+ if (ctx->Pixel.RedBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.RedBias = param;
+ break;
+ case GL_GREEN_SCALE:
+ if (ctx->Pixel.GreenScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.GreenScale = param;
+ break;
+ case GL_GREEN_BIAS:
+ if (ctx->Pixel.GreenBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.GreenBias = param;
+ break;
+ case GL_BLUE_SCALE:
+ if (ctx->Pixel.BlueScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.BlueScale = param;
+ break;
+ case GL_BLUE_BIAS:
+ if (ctx->Pixel.BlueBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.BlueBias = param;
+ break;
+ case GL_ALPHA_SCALE:
+ if (ctx->Pixel.AlphaScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.AlphaScale = param;
+ break;
+ case GL_ALPHA_BIAS:
+ if (ctx->Pixel.AlphaBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.AlphaBias = param;
+ break;
+ case GL_DEPTH_SCALE:
+ if (ctx->Pixel.DepthScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.DepthScale = param;
+ break;
+ case GL_DEPTH_BIAS:
+ if (ctx->Pixel.DepthBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.DepthBias = param;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
+ return;
+ }
+}
+
+
+static void GLAPIENTRY
+_mesa_PixelTransferi( GLenum pname, GLint param )
+{
+ _mesa_PixelTransferf( pname, (GLfloat) param );
+}
+
+
+
+/**********************************************************************/
+/***** State Management *****/
+/**********************************************************************/
+
+/*
+ * Return a bitmask of IMAGE_*_BIT flags which to indicate which
+ * pixel transfer operations are enabled.
+ */
+static void
+update_image_transfer_state(struct gl_context *ctx)
+{
+ GLuint mask = 0;
+
+ if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F ||
+ ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
+ ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F ||
+ ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
+ mask |= IMAGE_SCALE_BIAS_BIT;
+
+ if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
+ mask |= IMAGE_SHIFT_OFFSET_BIT;
+
+ if (ctx->Pixel.MapColorFlag)
+ mask |= IMAGE_MAP_COLOR_BIT;
+
+ ctx->_ImageTransferState = mask;
+}
+
+
+/**
+ * Update mesa pixel transfer derived state.
+ */
+void _mesa_update_pixel( struct gl_context *ctx, GLuint new_state )
+{
+ if (new_state & _MESA_NEW_TRANSFER_STATE)
+ update_image_transfer_state(ctx);
+}
+
+
+void
+_mesa_init_pixel_dispatch(struct _glapi_table *disp)
+{
+ SET_GetPixelMapfv(disp, _mesa_GetPixelMapfv);
+ SET_GetPixelMapuiv(disp, _mesa_GetPixelMapuiv);
+ SET_GetPixelMapusv(disp, _mesa_GetPixelMapusv);
+ SET_PixelMapfv(disp, _mesa_PixelMapfv);
+ SET_PixelMapuiv(disp, _mesa_PixelMapuiv);
+ SET_PixelMapusv(disp, _mesa_PixelMapusv);
+ SET_PixelTransferf(disp, _mesa_PixelTransferf);
+ SET_PixelTransferi(disp, _mesa_PixelTransferi);
+ SET_PixelZoom(disp, _mesa_PixelZoom);
+}
+
+
+#endif /* FEATURE_pixel_transfer */
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+static void
+init_pixelmap(struct gl_pixelmap *map)
+{
+ map->Size = 1;
+ map->Map[0] = 0.0;
+ map->Map8[0] = 0;
+}
+
+
+/**
+ * Initialize the context's PIXEL attribute group.
+ */
+void
+_mesa_init_pixel( struct gl_context *ctx )
+{
+ /* Pixel group */
+ ctx->Pixel.RedBias = 0.0;
+ ctx->Pixel.RedScale = 1.0;
+ ctx->Pixel.GreenBias = 0.0;
+ ctx->Pixel.GreenScale = 1.0;
+ ctx->Pixel.BlueBias = 0.0;
+ ctx->Pixel.BlueScale = 1.0;
+ ctx->Pixel.AlphaBias = 0.0;
+ ctx->Pixel.AlphaScale = 1.0;
+ ctx->Pixel.DepthBias = 0.0;
+ ctx->Pixel.DepthScale = 1.0;
+ ctx->Pixel.IndexOffset = 0;
+ ctx->Pixel.IndexShift = 0;
+ ctx->Pixel.ZoomX = 1.0;
+ ctx->Pixel.ZoomY = 1.0;
+ ctx->Pixel.MapColorFlag = GL_FALSE;
+ ctx->Pixel.MapStencilFlag = GL_FALSE;
+ init_pixelmap(&ctx->PixelMaps.StoS);
+ init_pixelmap(&ctx->PixelMaps.ItoI);
+ init_pixelmap(&ctx->PixelMaps.ItoR);
+ init_pixelmap(&ctx->PixelMaps.ItoG);
+ init_pixelmap(&ctx->PixelMaps.ItoB);
+ init_pixelmap(&ctx->PixelMaps.ItoA);
+ init_pixelmap(&ctx->PixelMaps.RtoR);
+ init_pixelmap(&ctx->PixelMaps.GtoG);
+ init_pixelmap(&ctx->PixelMaps.BtoB);
+ init_pixelmap(&ctx->PixelMaps.AtoA);
+
+ if (ctx->Visual.doubleBufferMode) {
+ ctx->Pixel.ReadBuffer = GL_BACK;
+ }
+ else {
+ ctx->Pixel.ReadBuffer = GL_FRONT;
+ }
+
+ /* Miscellaneous */
+ ctx->_ImageTransferState = 0;
+}
diff --git a/mesalib/src/mesa/main/polygon.c b/mesalib/src/mesa/main/polygon.c
index 71ef929fc..ff4232ecc 100644
--- a/mesalib/src/mesa/main/polygon.c
+++ b/mesalib/src/mesa/main/polygon.c
@@ -1,322 +1,322 @@
-/**
- * \file polygon.c
- * Polygon operations.
- */
-
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.1
- *
- * Copyright (C) 1999-2006 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 "imports.h"
-#include "bufferobj.h"
-#include "context.h"
-#include "image.h"
-#include "enums.h"
-#include "pack.h"
-#include "polygon.h"
-#include "mtypes.h"
-
-
-/**
- * Specify whether to cull front- or back-facing facets.
- *
- * \param mode culling mode.
- *
- * \sa glCullFace().
- *
- * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On
- * change, flushes the vertices and notifies the driver via
- * the dd_function_table::CullFace callback.
- */
-void GLAPIENTRY
-_mesa_CullFace( GLenum mode )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE&VERBOSE_API)
- _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode));
-
- if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" );
- return;
- }
-
- if (ctx->Polygon.CullFaceMode == mode)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.CullFaceMode = mode;
-
- if (ctx->Driver.CullFace)
- ctx->Driver.CullFace( ctx, mode );
-}
-
-
-/**
- * Define front- and back-facing
- *
- * \param mode orientation of front-facing polygons.
- *
- * \sa glFrontFace().
- *
- * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change
- * flushes the vertices and notifies the driver via
- * the dd_function_table::FrontFace callback.
- */
-void GLAPIENTRY
-_mesa_FrontFace( GLenum mode )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE&VERBOSE_API)
- _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode));
-
- if (mode!=GL_CW && mode!=GL_CCW) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" );
- return;
- }
-
- if (ctx->Polygon.FrontFace == mode)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.FrontFace = mode;
-
- ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW);
-
- if (ctx->Driver.FrontFace)
- ctx->Driver.FrontFace( ctx, mode );
-}
-
-
-/**
- * Set the polygon rasterization mode.
- *
- * \param face the polygons which \p mode applies to.
- * \param mode how polygons should be rasterized.
- *
- * \sa glPolygonMode().
- *
- * Verifies the parameters and updates gl_polygon_attrib::FrontMode and
- * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the
- * driver via the dd_function_table::PolygonMode callback.
- */
-void GLAPIENTRY
-_mesa_PolygonMode( GLenum face, GLenum mode )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE&VERBOSE_API)
- _mesa_debug(ctx, "glPolygonMode %s %s\n",
- _mesa_lookup_enum_by_nr(face),
- _mesa_lookup_enum_by_nr(mode));
-
- if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" );
- return;
- }
-
- switch (face) {
- case GL_FRONT:
- if (ctx->Polygon.FrontMode == mode)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.FrontMode = mode;
- break;
- case GL_FRONT_AND_BACK:
- if (ctx->Polygon.FrontMode == mode &&
- ctx->Polygon.BackMode == mode)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.FrontMode = mode;
- ctx->Polygon.BackMode = mode;
- break;
- case GL_BACK:
- if (ctx->Polygon.BackMode == mode)
- return;
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.BackMode = mode;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
- return;
- }
-
- if (ctx->Polygon.FrontMode == GL_FILL && ctx->Polygon.BackMode == GL_FILL)
- ctx->_TriangleCaps &= ~DD_TRI_UNFILLED;
- else
- ctx->_TriangleCaps |= DD_TRI_UNFILLED;
-
- if (ctx->Driver.PolygonMode)
- ctx->Driver.PolygonMode(ctx, face, mode);
-}
-
-#if _HAVE_FULL_GL
-
-
-/**
- * This routine updates the ctx->Polygon.Stipple state.
- * If we're getting the stipple data from a PBO, we map the buffer
- * in order to access the data.
- * In any case, we obey the current pixel unpacking parameters when fetching
- * the stipple data.
- *
- * In the future, this routine should be used as a fallback, called via
- * ctx->Driver.PolygonStipple(). We'll have to update all the DRI drivers
- * too.
- */
-void
-_mesa_polygon_stipple(struct gl_context *ctx, const GLubyte *pattern)
-{
- pattern = _mesa_map_validate_pbo_source(ctx, 2,
- &ctx->Unpack, 32, 32, 1,
- GL_COLOR_INDEX, GL_BITMAP, pattern,
- "glPolygonStipple");
- if (!pattern)
- return;
-
- _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack);
-
- _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
-}
-
-
-/**
- * Called by glPolygonStipple.
- */
-void GLAPIENTRY
-_mesa_PolygonStipple( const GLubyte *pattern )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE&VERBOSE_API)
- _mesa_debug(ctx, "glPolygonStipple\n");
-
- FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE);
-
- _mesa_polygon_stipple(ctx, pattern);
-
- if (ctx->Driver.PolygonStipple)
- ctx->Driver.PolygonStipple(ctx, pattern);
-}
-
-
-/**
- * Called by glPolygonStipple.
- */
-void GLAPIENTRY
-_mesa_GetPolygonStipple( GLubyte *dest )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE&VERBOSE_API)
- _mesa_debug(ctx, "glGetPolygonStipple\n");
-
- dest = _mesa_map_validate_pbo_dest(ctx, 2,
- &ctx->Pack, 32, 32, 1,
- GL_COLOR_INDEX, GL_BITMAP, dest,
- "glGetPolygonStipple");
- if (!dest)
- return;
-
- _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
-
- _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
-}
-
-
-void GLAPIENTRY
-_mesa_PolygonOffset( GLfloat factor, GLfloat units )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE&VERBOSE_API)
- _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units);
-
- if (ctx->Polygon.OffsetFactor == factor &&
- ctx->Polygon.OffsetUnits == units)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_POLYGON);
- ctx->Polygon.OffsetFactor = factor;
- ctx->Polygon.OffsetUnits = units;
-
- if (ctx->Driver.PolygonOffset)
- ctx->Driver.PolygonOffset( ctx, factor, units );
-}
-
-
-void GLAPIENTRY
-_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias )
-{
- GET_CURRENT_CONTEXT(ctx);
- /* XXX mult by DepthMaxF here??? */
- _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF );
-}
-
-#endif
-
-
-/**********************************************************************/
-/** \name Initialization */
-/*@{*/
-
-/**
- * Initialize the context polygon state.
- *
- * \param ctx GL context.
- *
- * Initializes __struct gl_contextRec::Polygon and __struct gl_contextRec::PolygonStipple
- * attribute groups.
- */
-void _mesa_init_polygon( struct gl_context * ctx )
-{
- /* Polygon group */
- ctx->Polygon.CullFlag = GL_FALSE;
- ctx->Polygon.CullFaceMode = GL_BACK;
- ctx->Polygon.FrontFace = GL_CCW;
- ctx->Polygon._FrontBit = 0;
- ctx->Polygon.FrontMode = GL_FILL;
- ctx->Polygon.BackMode = GL_FILL;
- ctx->Polygon.SmoothFlag = GL_FALSE;
- ctx->Polygon.StippleFlag = GL_FALSE;
- ctx->Polygon.OffsetFactor = 0.0F;
- ctx->Polygon.OffsetUnits = 0.0F;
- ctx->Polygon.OffsetPoint = GL_FALSE;
- ctx->Polygon.OffsetLine = GL_FALSE;
- ctx->Polygon.OffsetFill = GL_FALSE;
-
-
- /* Polygon Stipple group */
- memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) );
-}
-
-/*@}*/
+/**
+ * \file polygon.c
+ * Polygon operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "imports.h"
+#include "context.h"
+#include "image.h"
+#include "enums.h"
+#include "pack.h"
+#include "pbo.h"
+#include "polygon.h"
+#include "mtypes.h"
+
+
+/**
+ * Specify whether to cull front- or back-facing facets.
+ *
+ * \param mode culling mode.
+ *
+ * \sa glCullFace().
+ *
+ * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On
+ * change, flushes the vertices and notifies the driver via
+ * the dd_function_table::CullFace callback.
+ */
+void GLAPIENTRY
+_mesa_CullFace( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" );
+ return;
+ }
+
+ if (ctx->Polygon.CullFaceMode == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.CullFaceMode = mode;
+
+ if (ctx->Driver.CullFace)
+ ctx->Driver.CullFace( ctx, mode );
+}
+
+
+/**
+ * Define front- and back-facing
+ *
+ * \param mode orientation of front-facing polygons.
+ *
+ * \sa glFrontFace().
+ *
+ * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change
+ * flushes the vertices and notifies the driver via
+ * the dd_function_table::FrontFace callback.
+ */
+void GLAPIENTRY
+_mesa_FrontFace( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_CW && mode!=GL_CCW) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" );
+ return;
+ }
+
+ if (ctx->Polygon.FrontFace == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.FrontFace = mode;
+
+ ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW);
+
+ if (ctx->Driver.FrontFace)
+ ctx->Driver.FrontFace( ctx, mode );
+}
+
+
+/**
+ * Set the polygon rasterization mode.
+ *
+ * \param face the polygons which \p mode applies to.
+ * \param mode how polygons should be rasterized.
+ *
+ * \sa glPolygonMode().
+ *
+ * Verifies the parameters and updates gl_polygon_attrib::FrontMode and
+ * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::PolygonMode callback.
+ */
+void GLAPIENTRY
+_mesa_PolygonMode( GLenum face, GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPolygonMode %s %s\n",
+ _mesa_lookup_enum_by_nr(face),
+ _mesa_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" );
+ return;
+ }
+
+ switch (face) {
+ case GL_FRONT:
+ if (ctx->Polygon.FrontMode == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.FrontMode = mode;
+ break;
+ case GL_FRONT_AND_BACK:
+ if (ctx->Polygon.FrontMode == mode &&
+ ctx->Polygon.BackMode == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.FrontMode = mode;
+ ctx->Polygon.BackMode = mode;
+ break;
+ case GL_BACK:
+ if (ctx->Polygon.BackMode == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.BackMode = mode;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
+ return;
+ }
+
+ if (ctx->Polygon.FrontMode == GL_FILL && ctx->Polygon.BackMode == GL_FILL)
+ ctx->_TriangleCaps &= ~DD_TRI_UNFILLED;
+ else
+ ctx->_TriangleCaps |= DD_TRI_UNFILLED;
+
+ if (ctx->Driver.PolygonMode)
+ ctx->Driver.PolygonMode(ctx, face, mode);
+}
+
+#if _HAVE_FULL_GL
+
+
+/**
+ * This routine updates the ctx->Polygon.Stipple state.
+ * If we're getting the stipple data from a PBO, we map the buffer
+ * in order to access the data.
+ * In any case, we obey the current pixel unpacking parameters when fetching
+ * the stipple data.
+ *
+ * In the future, this routine should be used as a fallback, called via
+ * ctx->Driver.PolygonStipple(). We'll have to update all the DRI drivers
+ * too.
+ */
+void
+_mesa_polygon_stipple(struct gl_context *ctx, const GLubyte *pattern)
+{
+ pattern = _mesa_map_validate_pbo_source(ctx, 2,
+ &ctx->Unpack, 32, 32, 1,
+ GL_COLOR_INDEX, GL_BITMAP, pattern,
+ "glPolygonStipple");
+ if (!pattern)
+ return;
+
+ _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack);
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+}
+
+
+/**
+ * Called by glPolygonStipple.
+ */
+void GLAPIENTRY
+_mesa_PolygonStipple( const GLubyte *pattern )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPolygonStipple\n");
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE);
+
+ _mesa_polygon_stipple(ctx, pattern);
+
+ if (ctx->Driver.PolygonStipple)
+ ctx->Driver.PolygonStipple(ctx, pattern);
+}
+
+
+/**
+ * Called by glPolygonStipple.
+ */
+void GLAPIENTRY
+_mesa_GetPolygonStipple( GLubyte *dest )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glGetPolygonStipple\n");
+
+ dest = _mesa_map_validate_pbo_dest(ctx, 2,
+ &ctx->Pack, 32, 32, 1,
+ GL_COLOR_INDEX, GL_BITMAP, dest,
+ "glGetPolygonStipple");
+ if (!dest)
+ return;
+
+ _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+void GLAPIENTRY
+_mesa_PolygonOffset( GLfloat factor, GLfloat units )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units);
+
+ if (ctx->Polygon.OffsetFactor == factor &&
+ ctx->Polygon.OffsetUnits == units)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetFactor = factor;
+ ctx->Polygon.OffsetUnits = units;
+
+ if (ctx->Driver.PolygonOffset)
+ ctx->Driver.PolygonOffset( ctx, factor, units );
+}
+
+
+void GLAPIENTRY
+_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ /* XXX mult by DepthMaxF here??? */
+ _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF );
+}
+
+#endif
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+/**
+ * Initialize the context polygon state.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes __struct gl_contextRec::Polygon and __struct gl_contextRec::PolygonStipple
+ * attribute groups.
+ */
+void _mesa_init_polygon( struct gl_context * ctx )
+{
+ /* Polygon group */
+ ctx->Polygon.CullFlag = GL_FALSE;
+ ctx->Polygon.CullFaceMode = GL_BACK;
+ ctx->Polygon.FrontFace = GL_CCW;
+ ctx->Polygon._FrontBit = 0;
+ ctx->Polygon.FrontMode = GL_FILL;
+ ctx->Polygon.BackMode = GL_FILL;
+ ctx->Polygon.SmoothFlag = GL_FALSE;
+ ctx->Polygon.StippleFlag = GL_FALSE;
+ ctx->Polygon.OffsetFactor = 0.0F;
+ ctx->Polygon.OffsetUnits = 0.0F;
+ ctx->Polygon.OffsetPoint = GL_FALSE;
+ ctx->Polygon.OffsetLine = GL_FALSE;
+ ctx->Polygon.OffsetFill = GL_FALSE;
+
+
+ /* Polygon Stipple group */
+ memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) );
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c
index 3f424600c..6e09a52c8 100644
--- a/mesalib/src/mesa/main/readpix.c
+++ b/mesalib/src/mesa/main/readpix.c
@@ -1,243 +1,244 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2008 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 "imports.h"
-#include "bufferobj.h"
-#include "context.h"
-#include "enums.h"
-#include "readpix.h"
-#include "framebuffer.h"
-#include "formats.h"
-#include "image.h"
-#include "mtypes.h"
-#include "state.h"
-
-
-/**
- * Do error checking of the format/type parameters to glReadPixels and
- * glDrawPixels.
- * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
- * for ReadPixels.
- * \return GL_TRUE if error detected, GL_FALSE if no errors
- */
-GLboolean
-_mesa_error_check_format_type(struct gl_context *ctx, GLenum format, GLenum type,
- GLboolean drawing)
-{
- const char *readDraw = drawing ? "Draw" : "Read";
- const GLboolean reading = !drawing;
-
- /* state validation should have already been done */
- ASSERT(ctx->NewState == 0x0);
-
- if (ctx->Extensions.EXT_packed_depth_stencil
- && type == GL_UNSIGNED_INT_24_8_EXT
- && format != GL_DEPTH_STENCIL_EXT) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
- return GL_TRUE;
- }
-
- /* basic combinations test */
- if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "gl%sPixels(format or type)", readDraw);
- return GL_TRUE;
- }
-
- /* additional checks */
- switch (format) {
- case GL_RG:
- case GL_RED:
- case GL_GREEN:
- case GL_BLUE:
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_RGB:
- case GL_BGR:
- case GL_RGBA:
- case GL_BGRA:
- case GL_ABGR_EXT:
- case GL_RED_INTEGER_EXT:
- case GL_GREEN_INTEGER_EXT:
- case GL_BLUE_INTEGER_EXT:
- case GL_ALPHA_INTEGER_EXT:
- case GL_RGB_INTEGER_EXT:
- case GL_RGBA_INTEGER_EXT:
- case GL_BGR_INTEGER_EXT:
- case GL_BGRA_INTEGER_EXT:
- case GL_LUMINANCE_INTEGER_EXT:
- case GL_LUMINANCE_ALPHA_INTEGER_EXT:
- if (!drawing) {
- /* reading */
- if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(no color buffer)");
- return GL_TRUE;
- }
- }
- break;
- case GL_COLOR_INDEX:
- if (drawing) {
- if (ctx->PixelMaps.ItoR.Size == 0 ||
- ctx->PixelMaps.ItoG.Size == 0 ||
- ctx->PixelMaps.ItoB.Size == 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawPixels(drawing color index pixels into RGB buffer)");
- return GL_TRUE;
- }
- }
- else {
- /* reading */
- if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(no color buffer)");
- return GL_TRUE;
- }
- /* We no longer support CI-mode color buffers so trying to read
- * GL_COLOR_INDEX pixels is always an error.
- */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(color buffer is RGB)");
- return GL_TRUE;
- }
- break;
- case GL_STENCIL_INDEX:
- if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
- (reading && !_mesa_source_buffer_exists(ctx, format))) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "gl%sPixels(no stencil buffer)", readDraw);
- return GL_TRUE;
- }
- break;
- case GL_DEPTH_COMPONENT:
- if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "gl%sPixels(no depth buffer)", readDraw);
- return GL_TRUE;
- }
- break;
- case GL_DEPTH_STENCIL_EXT:
- if (!ctx->Extensions.EXT_packed_depth_stencil ||
- type != GL_UNSIGNED_INT_24_8_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
- return GL_TRUE;
- }
- if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
- (reading && !_mesa_source_buffer_exists(ctx, format))) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "gl%sPixels(no depth or stencil buffer)", readDraw);
- return GL_TRUE;
- }
- break;
- default:
- /* this should have been caught in _mesa_is_legal_format_type() */
- _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
- return GL_TRUE;
- }
-
- /* no errors */
- return GL_FALSE;
-}
-
-
-
-void GLAPIENTRY
-_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- FLUSH_CURRENT(ctx, 0);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
- width, height,
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type),
- pixels);
-
- if (width < 0 || height < 0) {
- _mesa_error( ctx, GL_INVALID_VALUE,
- "glReadPixels(width=%d height=%d)", width, height );
- return;
- }
-
- if (ctx->NewState)
- _mesa_update_state(ctx);
-
- if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
- /* found an error */
- return;
- }
-
- /* Check that the destination format and source buffer are both
- * integer-valued or both non-integer-valued.
- */
- if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
- const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
- const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
- const GLboolean dstInteger = _mesa_is_integer_format(format);
- if (dstInteger != srcInteger) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(integer / non-integer format mismatch");
- return;
- }
- }
-
- if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glReadPixels(incomplete framebuffer)" );
- return;
- }
-
- if (!_mesa_source_buffer_exists(ctx, format)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
- return;
- }
-
- if (width == 0 || height == 0)
- return; /* nothing to do */
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(invalid PBO access)");
- return;
- }
-
- if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
- /* buffer is mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
- return;
- }
- }
-
- ctx->Driver.ReadPixels(ctx, x, y, width, height,
- format, type, &ctx->Pack, pixels);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "imports.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "enums.h"
+#include "readpix.h"
+#include "framebuffer.h"
+#include "formats.h"
+#include "image.h"
+#include "mtypes.h"
+#include "pbo.h"
+#include "state.h"
+
+
+/**
+ * Do error checking of the format/type parameters to glReadPixels and
+ * glDrawPixels.
+ * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
+ * for ReadPixels.
+ * \return GL_TRUE if error detected, GL_FALSE if no errors
+ */
+GLboolean
+_mesa_error_check_format_type(struct gl_context *ctx, GLenum format, GLenum type,
+ GLboolean drawing)
+{
+ const char *readDraw = drawing ? "Draw" : "Read";
+ const GLboolean reading = !drawing;
+
+ /* state validation should have already been done */
+ ASSERT(ctx->NewState == 0x0);
+
+ if (ctx->Extensions.EXT_packed_depth_stencil
+ && type == GL_UNSIGNED_INT_24_8_EXT
+ && format != GL_DEPTH_STENCIL_EXT) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* basic combinations test */
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "gl%sPixels(format or type)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* additional checks */
+ switch (format) {
+ case GL_RG:
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ case GL_RED_INTEGER_EXT:
+ case GL_GREEN_INTEGER_EXT:
+ case GL_BLUE_INTEGER_EXT:
+ case GL_ALPHA_INTEGER_EXT:
+ case GL_RGB_INTEGER_EXT:
+ case GL_RGBA_INTEGER_EXT:
+ case GL_BGR_INTEGER_EXT:
+ case GL_BGRA_INTEGER_EXT:
+ case GL_LUMINANCE_INTEGER_EXT:
+ case GL_LUMINANCE_ALPHA_INTEGER_EXT:
+ if (!drawing) {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
+ }
+ break;
+ case GL_COLOR_INDEX:
+ if (drawing) {
+ if (ctx->PixelMaps.ItoR.Size == 0 ||
+ ctx->PixelMaps.ItoG.Size == 0 ||
+ ctx->PixelMaps.ItoB.Size == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(drawing color index pixels into RGB buffer)");
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
+ /* We no longer support CI-mode color buffers so trying to read
+ * GL_COLOR_INDEX pixels is always an error.
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(color buffer is RGB)");
+ return GL_TRUE;
+ }
+ break;
+ case GL_STENCIL_INDEX:
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no stencil buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no depth buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ if (!ctx->Extensions.EXT_packed_depth_stencil ||
+ type != GL_UNSIGNED_INT_24_8_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
+ return GL_TRUE;
+ }
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no depth or stencil buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ default:
+ /* this should have been caught in _mesa_is_legal_format_type() */
+ _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
+ return GL_TRUE;
+ }
+
+ /* no errors */
+ return GL_FALSE;
+}
+
+
+
+void GLAPIENTRY
+_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ FLUSH_CURRENT(ctx, 0);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
+ width, height,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type),
+ pixels);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glReadPixels(width=%d height=%d)", width, height );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
+ /* found an error */
+ return;
+ }
+
+ /* Check that the destination format and source buffer are both
+ * integer-valued or both non-integer-valued.
+ */
+ if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
+ const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+ const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
+ const GLboolean dstInteger = _mesa_is_integer_format(format);
+ if (dstInteger != srcInteger) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(integer / non-integer format mismatch");
+ return;
+ }
+ }
+
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glReadPixels(incomplete framebuffer)" );
+ return;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
+ return;
+ }
+
+ if (width == 0 || height == 0)
+ return; /* nothing to do */
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(invalid PBO access)");
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
+ return;
+ }
+ }
+
+ ctx->Driver.ReadPixels(ctx, x, y, width, height,
+ format, type, &ctx->Pack, pixels);
+}
diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c
index b7725f4a9..2f3a0f214 100644
--- a/mesalib/src/mesa/main/texcompress_rgtc.c
+++ b/mesalib/src/mesa/main/texcompress_rgtc.c
@@ -46,9 +46,9 @@
#define RGTC_DEBUG 0
-static void encode_rgtc_chan_u(GLubyte *blkaddr, GLubyte srccolors[4][4],
- GLint numxpixels, GLint numypixels);
-static void encode_rgtc_chan_s(GLbyte *blkaddr, GLbyte srccolors[4][4],
+static void unsigned_encode_rgtc_chan(GLubyte *blkaddr, GLubyte srccolors[4][4],
+ GLint numxpixels, GLint numypixels);
+static void signed_encode_rgtc_chan(GLbyte *blkaddr, GLbyte srccolors[4][4],
GLint numxpixels, GLint numypixels);
static void extractsrc_u( GLubyte srcpixels[4][4], const GLchan *srcaddr,
@@ -88,7 +88,7 @@ _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
const GLchan *tempImage = NULL;
int i, j;
int numxpixels, numypixels;
- const void *srcaddr;
+ const GLchan *srcaddr;
GLubyte srcpixels[4][4];
GLubyte *blkaddr;
GLint dstRowDiff;
@@ -123,7 +123,7 @@ _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
if (srcWidth > i + 3) numxpixels = 4;
else numxpixels = srcWidth - i;
extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
- encode_rgtc_chan_u(blkaddr, srcpixels, numxpixels, numypixels);
+ unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
srcaddr += numxpixels;
blkaddr += 8;
}
@@ -177,7 +177,7 @@ _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
if (srcWidth > i + 3) numxpixels = 4;
else numxpixels = srcWidth - i;
extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
- encode_rgtc_chan_s(blkaddr, srcpixels, numxpixels, numypixels);
+ signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
srcaddr += numxpixels;
blkaddr += 8;
}
@@ -197,7 +197,7 @@ _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
const GLchan *tempImage = NULL;
int i, j;
int numxpixels, numypixels;
- const void *srcaddr;
+ const GLchan *srcaddr;
GLubyte srcpixels[4][4];
GLubyte *blkaddr;
GLint dstRowDiff;
@@ -232,11 +232,11 @@ _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
if (srcWidth > i + 3) numxpixels = 4;
else numxpixels = srcWidth - i;
extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
- encode_rgtc_chan_u(blkaddr, srcpixels, numxpixels, numypixels);
+ unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
blkaddr += 8;
extractsrc_u(srcpixels, (GLchan *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
- encode_rgtc_chan_u(blkaddr, srcpixels, numxpixels, numypixels);
+ unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
blkaddr += 8;
@@ -294,11 +294,11 @@ _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
else numxpixels = srcWidth - i;
extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
- encode_rgtc_chan_s(blkaddr, srcpixels, numxpixels, numypixels);
+ signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
blkaddr += 8;
extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
- encode_rgtc_chan_s(blkaddr, srcpixels, numxpixels, numypixels);
+ signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
blkaddr += 8;
srcaddr += numxpixels * 2;
@@ -427,696 +427,27 @@ _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage,
texel[ACOMP] = 1.0;
}
-static void write_rgtc_encoded_channel(GLubyte *blkaddr,
- GLubyte alphabase1,
- GLubyte alphabase2,
- GLubyte alphaenc[16])
-{
- *blkaddr++ = alphabase1;
- *blkaddr++ = alphabase2;
- *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
- *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
- *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
- *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
- *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
- *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
-}
-
-static void encode_rgtc_chan_u(GLubyte *blkaddr, GLubyte srccolors[4][4],
- GLint numxpixels, GLint numypixels)
-{
- GLubyte alphabase[2], alphause[2];
- GLshort alphatest[2] = { 0 };
- GLuint alphablockerror1, alphablockerror2, alphablockerror3;
- GLubyte i, j, aindex, acutValues[7];
- GLubyte alphaenc1[16], alphaenc2[16], alphaenc3[16];
- GLboolean alphaabsmin = GL_FALSE;
- GLboolean alphaabsmax = GL_FALSE;
- GLshort alphadist;
-
- /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
- alphabase[0] = 0xff; alphabase[1] = 0x0;
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- if (srccolors[j][i] == 0)
- alphaabsmin = GL_TRUE;
- else if (srccolors[j][i] == 255)
- alphaabsmax = GL_TRUE;
- else {
- if (srccolors[j][i] > alphabase[1])
- alphabase[1] = srccolors[j][i];
- if (srccolors[j][i] < alphabase[0])
- alphabase[0] = srccolors[j][i];
- }
- }
- }
-
-
- if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */
- /* shortcut here since it is a very common case (and also avoids later problems) */
- /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */
- /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
-
- *blkaddr++ = srccolors[0][0];
- blkaddr++;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
-#if RGTC_DEBUG
- fprintf(stderr, "enc0 used\n");
-#endif
- return;
- }
-
- /* find best encoding for alpha0 > alpha1 */
- /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
- alphablockerror1 = 0x0;
- alphablockerror2 = 0xffffffff;
- alphablockerror3 = 0xffffffff;
- if (alphaabsmin) alphause[0] = 0;
- else alphause[0] = alphabase[0];
- if (alphaabsmax) alphause[1] = 255;
- else alphause[1] = alphabase[1];
- /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
- for (aindex = 0; aindex < 7; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
- }
-
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- /* maybe it's overkill to have the most complicated calculation just for the error
- calculation which we only need to figure out if encoding1 or encoding2 is better... */
- if (srccolors[j][i] > acutValues[0]) {
- alphaenc1[4*j + i] = 0;
- alphadist = srccolors[j][i] - alphause[1];
- }
- else if (srccolors[j][i] > acutValues[1]) {
- alphaenc1[4*j + i] = 2;
- alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
- }
- else if (srccolors[j][i] > acutValues[2]) {
- alphaenc1[4*j + i] = 3;
- alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
- }
- else if (srccolors[j][i] > acutValues[3]) {
- alphaenc1[4*j + i] = 4;
- alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
- }
- else if (srccolors[j][i] > acutValues[4]) {
- alphaenc1[4*j + i] = 5;
- alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
- }
- else if (srccolors[j][i] > acutValues[5]) {
- alphaenc1[4*j + i] = 6;
- alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
- }
- else if (srccolors[j][i] > acutValues[6]) {
- alphaenc1[4*j + i] = 7;
- alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
- }
- else {
- alphaenc1[4*j + i] = 1;
- alphadist = srccolors[j][i] - alphause[0];
- }
- alphablockerror1 += alphadist * alphadist;
- }
- }
-
-#if RGTC_DEBUG
- for (i = 0; i < 16; i++) {
- fprintf(stderr, "%d ", alphaenc1[i]);
- }
- fprintf(stderr, "cutVals ");
- for (i = 0; i < 8; i++) {
- fprintf(stderr, "%d ", acutValues[i]);
- }
- fprintf(stderr, "srcVals ");
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- fprintf(stderr, "%d ", srccolors[j][i]);
- }
- }
- fprintf(stderr, "\n");
-#endif
-
- /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
- are false but try it anyway */
- if (alphablockerror1 >= 32) {
-
- /* don't bother if encoding is already very good, this condition should also imply
- we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
- alphablockerror2 = 0;
- for (aindex = 0; aindex < 5; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
- }
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- /* maybe it's overkill to have the most complicated calculation just for the error
- calculation which we only need to figure out if encoding1 or encoding2 is better... */
- if (srccolors[j][i] == 0) {
- alphaenc2[4*j + i] = 6;
- alphadist = 0;
- }
- else if (srccolors[j][i] == 255) {
- alphaenc2[4*j + i] = 7;
- alphadist = 0;
- }
- else if (srccolors[j][i] <= acutValues[0]) {
- alphaenc2[4*j + i] = 0;
- alphadist = srccolors[j][i] - alphabase[0];
- }
- else if (srccolors[j][i] <= acutValues[1]) {
- alphaenc2[4*j + i] = 2;
- alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
- }
- else if (srccolors[j][i] <= acutValues[2]) {
- alphaenc2[4*j + i] = 3;
- alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
- }
- else if (srccolors[j][i] <= acutValues[3]) {
- alphaenc2[4*j + i] = 4;
- alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
- }
- else if (srccolors[j][i] <= acutValues[4]) {
- alphaenc2[4*j + i] = 5;
- alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
- }
- else {
- alphaenc2[4*j + i] = 1;
- alphadist = srccolors[j][i] - alphabase[1];
- }
- alphablockerror2 += alphadist * alphadist;
- }
- }
-
-
- /* skip this if the error is already very small
- this encoding is MUCH better on average than #2 though, but expensive! */
- if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
- GLshort blockerrlin1 = 0;
- GLshort blockerrlin2 = 0;
- GLubyte nralphainrangelow = 0;
- GLubyte nralphainrangehigh = 0;
- alphatest[0] = 0xff;
- alphatest[1] = 0x0;
- /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (255 -(alphabase[1] - alphabase[0]) / 28)))
- alphatest[1] = srccolors[j][i];
- if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
- alphatest[0] = srccolors[j][i];
- }
- }
- /* shouldn't happen too often, don't really care about those degenerated cases */
- if (alphatest[1] <= alphatest[0]) {
- alphatest[0] = 1;
- alphatest[1] = 254;
- }
- for (aindex = 0; aindex < 5; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
- }
-
- /* find the "average" difference between the alpha values and the next encoded value.
- This is then used to calculate new base values.
- Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
- since they will see more improvement, and also because the values in the middle are somewhat
- likely to get no improvement at all (because the base values might move in different directions)?
- OTOH it would mean the values in the middle are even less likely to get an improvement
- */
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- if (srccolors[j][i] <= alphatest[0] / 2) {
- }
- else if (srccolors[j][i] > ((255 + alphatest[1]) / 2)) {
- }
- else if (srccolors[j][i] <= acutValues[0]) {
- blockerrlin1 += (srccolors[j][i] - alphatest[0]);
- nralphainrangelow += 1;
- }
- else if (srccolors[j][i] <= acutValues[1]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else if (srccolors[j][i] <= acutValues[2]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else if (srccolors[j][i] <= acutValues[3]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else if (srccolors[j][i] <= acutValues[4]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else {
- blockerrlin2 += (srccolors[j][i] - alphatest[1]);
- nralphainrangehigh += 1;
- }
- }
- }
- /* shouldn't happen often, needed to avoid div by zero */
- if (nralphainrangelow == 0) nralphainrangelow = 1;
- if (nralphainrangehigh == 0) nralphainrangehigh = 1;
- alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
-#if RGTC_DEBUG
- fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
- fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
-#endif
- /* again shouldn't really happen often... */
- if (alphatest[0] < 0) {
- alphatest[0] = 0;
- }
- alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
- if (alphatest[1] > 255) {
- alphatest[1] = 255;
- }
-
- alphablockerror3 = 0;
- for (aindex = 0; aindex < 5; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
- }
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- /* maybe it's overkill to have the most complicated calculation just for the error
- calculation which we only need to figure out if encoding1 or encoding2 is better... */
- if (srccolors[j][i] <= alphatest[0] / 2) {
- alphaenc3[4*j + i] = 6;
- alphadist = srccolors[j][i];
- }
- else if (srccolors[j][i] > ((255 + alphatest[1]) / 2)) {
- alphaenc3[4*j + i] = 7;
- alphadist = 255 - srccolors[j][i];
- }
- else if (srccolors[j][i] <= acutValues[0]) {
- alphaenc3[4*j + i] = 0;
- alphadist = srccolors[j][i] - alphatest[0];
- }
- else if (srccolors[j][i] <= acutValues[1]) {
- alphaenc3[4*j + i] = 2;
- alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
- }
- else if (srccolors[j][i] <= acutValues[2]) {
- alphaenc3[4*j + i] = 3;
- alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
- }
- else if (srccolors[j][i] <= acutValues[3]) {
- alphaenc3[4*j + i] = 4;
- alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
- }
- else if (srccolors[j][i] <= acutValues[4]) {
- alphaenc3[4*j + i] = 5;
- alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
- }
- else {
- alphaenc3[4*j + i] = 1;
- alphadist = srccolors[j][i] - alphatest[1];
- }
- alphablockerror3 += alphadist * alphadist;
- }
- }
- }
- }
- /* write the alpha values and encoding back. */
- if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
-#if RGTC_DEBUG
- if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
-#endif
- write_rgtc_encoded_channel( blkaddr, alphause[1], alphause[0], alphaenc1 );
- }
- else if (alphablockerror2 <= alphablockerror3) {
-#if RGTC_DEBUG
- if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
-#endif
- write_rgtc_encoded_channel( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
- }
- else {
-#if RGTC_DEBUG
- fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
-#endif
- write_rgtc_encoded_channel( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3 );
- }
-}
-
-
-static void write_rgtc_encoded_channel_s(GLbyte *blkaddr,
- GLbyte alphabase1,
- GLbyte alphabase2,
- GLbyte alphaenc[16])
-{
- *blkaddr++ = alphabase1;
- *blkaddr++ = alphabase2;
- *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
- *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
- *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
- *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
- *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
- *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
-}
-
-static void encode_rgtc_chan_s(GLbyte *blkaddr, GLbyte srccolors[4][4],
- GLint numxpixels, GLint numypixels)
-{
- GLbyte alphabase[2], alphause[2];
- GLshort alphatest[2] = { 0 };
- GLuint alphablockerror1, alphablockerror2, alphablockerror3;
- GLbyte i, j, aindex, acutValues[7];
- GLbyte alphaenc1[16], alphaenc2[16], alphaenc3[16];
- GLboolean alphaabsmin = GL_FALSE;
- GLboolean alphaabsmax = GL_FALSE;
- GLshort alphadist;
-
- /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
- alphabase[0] = 0xff; alphabase[1] = 0x0;
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- if (srccolors[j][i] == 0)
- alphaabsmin = GL_TRUE;
- else if (srccolors[j][i] == 255)
- alphaabsmax = GL_TRUE;
- else {
- if (srccolors[j][i] > alphabase[1])
- alphabase[1] = srccolors[j][i];
- if (srccolors[j][i] < alphabase[0])
- alphabase[0] = srccolors[j][i];
- }
- }
- }
-
-
- if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */
- /* shortcut here since it is a very common case (and also avoids later problems) */
- /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */
- /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
-
- *blkaddr++ = srccolors[0][0];
- blkaddr++;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
- *blkaddr++ = 0;
-#if RGTC_DEBUG
- fprintf(stderr, "enc0 used\n");
-#endif
- return;
- }
-
- /* find best encoding for alpha0 > alpha1 */
- /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
- alphablockerror1 = 0x0;
- alphablockerror2 = 0xffffffff;
- alphablockerror3 = 0xffffffff;
- if (alphaabsmin) alphause[0] = 0;
- else alphause[0] = alphabase[0];
- if (alphaabsmax) alphause[1] = 255;
- else alphause[1] = alphabase[1];
- /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
- for (aindex = 0; aindex < 7; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
- }
+#define TAG(x) unsigned_##x
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- /* maybe it's overkill to have the most complicated calculation just for the error
- calculation which we only need to figure out if encoding1 or encoding2 is better... */
- if (srccolors[j][i] > acutValues[0]) {
- alphaenc1[4*j + i] = 0;
- alphadist = srccolors[j][i] - alphause[1];
- }
- else if (srccolors[j][i] > acutValues[1]) {
- alphaenc1[4*j + i] = 2;
- alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
- }
- else if (srccolors[j][i] > acutValues[2]) {
- alphaenc1[4*j + i] = 3;
- alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
- }
- else if (srccolors[j][i] > acutValues[3]) {
- alphaenc1[4*j + i] = 4;
- alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
- }
- else if (srccolors[j][i] > acutValues[4]) {
- alphaenc1[4*j + i] = 5;
- alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
- }
- else if (srccolors[j][i] > acutValues[5]) {
- alphaenc1[4*j + i] = 6;
- alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
- }
- else if (srccolors[j][i] > acutValues[6]) {
- alphaenc1[4*j + i] = 7;
- alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
- }
- else {
- alphaenc1[4*j + i] = 1;
- alphadist = srccolors[j][i] - alphause[0];
- }
- alphablockerror1 += alphadist * alphadist;
- }
- }
-#if RGTC_DEBUG
- for (i = 0; i < 16; i++) {
- fprintf(stderr, "%d ", alphaenc1[i]);
- }
- fprintf(stderr, "cutVals ");
- for (i = 0; i < 8; i++) {
- fprintf(stderr, "%d ", acutValues[i]);
- }
- fprintf(stderr, "srcVals ");
- for (j = 0; j < numypixels; j++)
- for (i = 0; i < numxpixels; i++) {
- fprintf(stderr, "%d ", srccolors[j][i]);
- }
-
- fprintf(stderr, "\n");
-#endif
+#define TYPE GLubyte
+#define T_MIN 0
+#define T_MAX 0xff
- /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
- are false but try it anyway */
- if (alphablockerror1 >= 32) {
-
- /* don't bother if encoding is already very good, this condition should also imply
- we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
- alphablockerror2 = 0;
- for (aindex = 0; aindex < 5; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
- }
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- /* maybe it's overkill to have the most complicated calculation just for the error
- calculation which we only need to figure out if encoding1 or encoding2 is better... */
- if (srccolors[j][i] == 0) {
- alphaenc2[4*j + i] = 6;
- alphadist = 0;
- }
- else if (srccolors[j][i] == 255) {
- alphaenc2[4*j + i] = 7;
- alphadist = 0;
- }
- else if (srccolors[j][i] <= acutValues[0]) {
- alphaenc2[4*j + i] = 0;
- alphadist = srccolors[j][i] - alphabase[0];
- }
- else if (srccolors[j][i] <= acutValues[1]) {
- alphaenc2[4*j + i] = 2;
- alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
- }
- else if (srccolors[j][i] <= acutValues[2]) {
- alphaenc2[4*j + i] = 3;
- alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
- }
- else if (srccolors[j][i] <= acutValues[3]) {
- alphaenc2[4*j + i] = 4;
- alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
- }
- else if (srccolors[j][i] <= acutValues[4]) {
- alphaenc2[4*j + i] = 5;
- alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
- }
- else {
- alphaenc2[4*j + i] = 1;
- alphadist = srccolors[j][i] - alphabase[1];
- }
- alphablockerror2 += alphadist * alphadist;
- }
- }
+#include "texcompress_rgtc_tmp.h"
+#undef TAG
+#undef TYPE
+#undef T_MIN
+#undef T_MAX
- /* skip this if the error is already very small
- this encoding is MUCH better on average than #2 though, but expensive! */
- if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
- GLshort blockerrlin1 = 0;
- GLshort blockerrlin2 = 0;
- GLubyte nralphainrangelow = 0;
- GLubyte nralphainrangehigh = 0;
- alphatest[0] = 0xff;
- alphatest[1] = 0x0;
- /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (255 -(alphabase[1] - alphabase[0]) / 28)))
- alphatest[1] = srccolors[j][i];
- if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
- alphatest[0] = srccolors[j][i];
- }
- }
- /* shouldn't happen too often, don't really care about those degenerated cases */
- if (alphatest[1] <= alphatest[0]) {
- alphatest[0] = 1;
- alphatest[1] = 254;
- }
- for (aindex = 0; aindex < 5; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
- }
+#define TAG(x) signed_##x
+#define TYPE GLbyte
+#define T_MIN (GLbyte)-127
+#define T_MAX (GLbyte)127
- /* find the "average" difference between the alpha values and the next encoded value.
- This is then used to calculate new base values.
- Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
- since they will see more improvement, and also because the values in the middle are somewhat
- likely to get no improvement at all (because the base values might move in different directions)?
- OTOH it would mean the values in the middle are even less likely to get an improvement
- */
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- if (srccolors[j][i] <= alphatest[0] / 2) {
- }
- else if (srccolors[j][i] > ((255 + alphatest[1]) / 2)) {
- }
- else if (srccolors[j][i] <= acutValues[0]) {
- blockerrlin1 += (srccolors[j][i] - alphatest[0]);
- nralphainrangelow += 1;
- }
- else if (srccolors[j][i] <= acutValues[1]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else if (srccolors[j][i] <= acutValues[2]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else if (srccolors[j][i] <= acutValues[3]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else if (srccolors[j][i] <= acutValues[4]) {
- blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
- blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
- nralphainrangelow += 1;
- nralphainrangehigh += 1;
- }
- else {
- blockerrlin2 += (srccolors[j][i] - alphatest[1]);
- nralphainrangehigh += 1;
- }
- }
- }
- /* shouldn't happen often, needed to avoid div by zero */
- if (nralphainrangelow == 0) nralphainrangelow = 1;
- if (nralphainrangehigh == 0) nralphainrangehigh = 1;
- alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
-#if RGTC_DEBUG
- fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
- fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
-#endif
- /* again shouldn't really happen often... */
- if (alphatest[0] < 0) {
- alphatest[0] = 0;
- }
- alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
- if (alphatest[1] > 255) {
- alphatest[1] = 255;
- }
+#include "texcompress_rgtc_tmp.h"
- alphablockerror3 = 0;
- for (aindex = 0; aindex < 5; aindex++) {
- /* don't forget here is always rounded down */
- acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
- }
- for (j = 0; j < numypixels; j++) {
- for (i = 0; i < numxpixels; i++) {
- /* maybe it's overkill to have the most complicated calculation just for the error
- calculation which we only need to figure out if encoding1 or encoding2 is better... */
- if (srccolors[j][i] <= alphatest[0] / 2) {
- alphaenc3[4*j + i] = 6;
- alphadist = srccolors[j][i];
- }
- else if (srccolors[j][i] > ((255 + alphatest[1]) / 2)) {
- alphaenc3[4*j + i] = 7;
- alphadist = 255 - srccolors[j][i];
- }
- else if (srccolors[j][i] <= acutValues[0]) {
- alphaenc3[4*j + i] = 0;
- alphadist = srccolors[j][i] - alphatest[0];
- }
- else if (srccolors[j][i] <= acutValues[1]) {
- alphaenc3[4*j + i] = 2;
- alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
- }
- else if (srccolors[j][i] <= acutValues[2]) {
- alphaenc3[4*j + i] = 3;
- alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
- }
- else if (srccolors[j][i] <= acutValues[3]) {
- alphaenc3[4*j + i] = 4;
- alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
- }
- else if (srccolors[j][i] <= acutValues[4]) {
- alphaenc3[4*j + i] = 5;
- alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
- }
- else {
- alphaenc3[4*j + i] = 1;
- alphadist = srccolors[j][i] - alphatest[1];
- }
- alphablockerror3 += alphadist * alphadist;
- }
- }
- }
- }
- /* write the alpha values and encoding back. */
- if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
-#if RGTC_DEBUG
- if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
-#endif
- write_rgtc_encoded_channel_s( blkaddr, alphause[1], alphause[0], alphaenc1 );
- }
- else if (alphablockerror2 <= alphablockerror3) {
-#if RGTC_DEBUG
- if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
-#endif
- write_rgtc_encoded_channel_s( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
- }
- else {
-#if RGTC_DEBUG
- fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
-#endif
- write_rgtc_encoded_channel_s( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3 );
- }
-}
+#undef TAG
+#undef TYPE
+#undef T_MIN
+#undef T_MAX
diff --git a/mesalib/src/mesa/main/texcompress_rgtc_tmp.h b/mesalib/src/mesa/main/texcompress_rgtc_tmp.h
new file mode 100644
index 000000000..0f830a5d9
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress_rgtc_tmp.h
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * block compression parts are:
+ * Copyright (C) 2004 Roland Scheidegger 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author:
+ * Dave Airlie
+ */
+
+/* included by texcompress_rgtc to define byte/ubyte compressors */
+
+static void TAG(write_rgtc_encoded_channel)(TYPE *blkaddr,
+ TYPE alphabase1,
+ TYPE alphabase2,
+ TYPE alphaenc[16])
+{
+ *blkaddr++ = alphabase1;
+ *blkaddr++ = alphabase2;
+ *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
+ *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
+ *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
+ *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
+ *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
+ *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
+}
+static void TAG(encode_rgtc_chan)(TYPE *blkaddr, TYPE srccolors[4][4],
+ GLint numxpixels, GLint numypixels)
+{
+ TYPE alphabase[2], alphause[2];
+ GLshort alphatest[2] = { 0 };
+ GLuint alphablockerror1, alphablockerror2, alphablockerror3;
+ TYPE i, j, aindex, acutValues[7];
+ TYPE alphaenc1[16], alphaenc2[16], alphaenc3[16];
+ GLboolean alphaabsmin = GL_FALSE;
+ GLboolean alphaabsmax = GL_FALSE;
+ GLshort alphadist;
+
+ /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
+ alphabase[0] = T_MAX; alphabase[1] = T_MIN;
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ if (srccolors[j][i] == T_MIN)
+ alphaabsmin = GL_TRUE;
+ else if (srccolors[j][i] == T_MAX)
+ alphaabsmax = GL_TRUE;
+ else {
+ if (srccolors[j][i] > alphabase[1])
+ alphabase[1] = srccolors[j][i];
+ if (srccolors[j][i] < alphabase[0])
+ alphabase[0] = srccolors[j][i];
+ }
+ }
+ }
+
+
+ if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */
+ /* shortcut here since it is a very common case (and also avoids later problems) */
+ /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */
+ /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
+
+ *blkaddr++ = srccolors[0][0];
+ blkaddr++;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+#if RGTC_DEBUG
+ fprintf(stderr, "enc0 used\n");
+#endif
+ return;
+ }
+
+ /* find best encoding for alpha0 > alpha1 */
+ /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
+ alphablockerror1 = 0x0;
+ alphablockerror2 = 0xffffffff;
+ alphablockerror3 = 0xffffffff;
+ if (alphaabsmin) alphause[0] = T_MIN;
+ else alphause[0] = alphabase[0];
+ if (alphaabsmax) alphause[1] = T_MAX;
+ else alphause[1] = alphabase[1];
+ /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
+ for (aindex = 0; aindex < 7; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
+ }
+
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ /* maybe it's overkill to have the most complicated calculation just for the error
+ calculation which we only need to figure out if encoding1 or encoding2 is better... */
+ if (srccolors[j][i] > acutValues[0]) {
+ alphaenc1[4*j + i] = 0;
+ alphadist = srccolors[j][i] - alphause[1];
+ }
+ else if (srccolors[j][i] > acutValues[1]) {
+ alphaenc1[4*j + i] = 2;
+ alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
+ }
+ else if (srccolors[j][i] > acutValues[2]) {
+ alphaenc1[4*j + i] = 3;
+ alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
+ }
+ else if (srccolors[j][i] > acutValues[3]) {
+ alphaenc1[4*j + i] = 4;
+ alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
+ }
+ else if (srccolors[j][i] > acutValues[4]) {
+ alphaenc1[4*j + i] = 5;
+ alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
+ }
+ else if (srccolors[j][i] > acutValues[5]) {
+ alphaenc1[4*j + i] = 6;
+ alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
+ }
+ else if (srccolors[j][i] > acutValues[6]) {
+ alphaenc1[4*j + i] = 7;
+ alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
+ }
+ else {
+ alphaenc1[4*j + i] = 1;
+ alphadist = srccolors[j][i] - alphause[0];
+ }
+ alphablockerror1 += alphadist * alphadist;
+ }
+ }
+
+#if RGTC_DEBUG
+ for (i = 0; i < 16; i++) {
+ fprintf(stderr, "%d ", alphaenc1[i]);
+ }
+ fprintf(stderr, "cutVals ");
+ for (i = 0; i < 8; i++) {
+ fprintf(stderr, "%d ", acutValues[i]);
+ }
+ fprintf(stderr, "srcVals ");
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ fprintf(stderr, "%d ", srccolors[j][i]);
+ }
+ }
+ fprintf(stderr, "\n");
+#endif
+
+ /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
+ are false but try it anyway */
+ if (alphablockerror1 >= 32) {
+
+ /* don't bother if encoding is already very good, this condition should also imply
+ we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
+ alphablockerror2 = 0;
+ for (aindex = 0; aindex < 5; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
+ }
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ /* maybe it's overkill to have the most complicated calculation just for the error
+ calculation which we only need to figure out if encoding1 or encoding2 is better... */
+ if (srccolors[j][i] == T_MIN) {
+ alphaenc2[4*j + i] = 6;
+ alphadist = 0;
+ }
+ else if (srccolors[j][i] == T_MAX) {
+ alphaenc2[4*j + i] = 7;
+ alphadist = 0;
+ }
+ else if (srccolors[j][i] <= acutValues[0]) {
+ alphaenc2[4*j + i] = 0;
+ alphadist = srccolors[j][i] - alphabase[0];
+ }
+ else if (srccolors[j][i] <= acutValues[1]) {
+ alphaenc2[4*j + i] = 2;
+ alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
+ }
+ else if (srccolors[j][i] <= acutValues[2]) {
+ alphaenc2[4*j + i] = 3;
+ alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
+ }
+ else if (srccolors[j][i] <= acutValues[3]) {
+ alphaenc2[4*j + i] = 4;
+ alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
+ }
+ else if (srccolors[j][i] <= acutValues[4]) {
+ alphaenc2[4*j + i] = 5;
+ alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
+ }
+ else {
+ alphaenc2[4*j + i] = 1;
+ alphadist = srccolors[j][i] - alphabase[1];
+ }
+ alphablockerror2 += alphadist * alphadist;
+ }
+ }
+
+
+ /* skip this if the error is already very small
+ this encoding is MUCH better on average than #2 though, but expensive! */
+ if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
+ GLshort blockerrlin1 = 0;
+ GLshort blockerrlin2 = 0;
+ TYPE nralphainrangelow = 0;
+ TYPE nralphainrangehigh = 0;
+ alphatest[0] = 0xff;
+ alphatest[1] = 0x0;
+ /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (T_MAX -(alphabase[1] - alphabase[0]) / 28)))
+ alphatest[1] = srccolors[j][i];
+ if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
+ alphatest[0] = srccolors[j][i];
+ }
+ }
+ /* shouldn't happen too often, don't really care about those degenerated cases */
+ if (alphatest[1] <= alphatest[0]) {
+ alphatest[0] = 1;
+ alphatest[1] = 254;
+ }
+ for (aindex = 0; aindex < 5; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
+ }
+
+ /* find the "average" difference between the alpha values and the next encoded value.
+ This is then used to calculate new base values.
+ Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
+ since they will see more improvement, and also because the values in the middle are somewhat
+ likely to get no improvement at all (because the base values might move in different directions)?
+ OTOH it would mean the values in the middle are even less likely to get an improvement
+ */
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ if (srccolors[j][i] <= alphatest[0] / 2) {
+ }
+ else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
+ }
+ else if (srccolors[j][i] <= acutValues[0]) {
+ blockerrlin1 += (srccolors[j][i] - alphatest[0]);
+ nralphainrangelow += 1;
+ }
+ else if (srccolors[j][i] <= acutValues[1]) {
+ blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
+ blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else if (srccolors[j][i] <= acutValues[2]) {
+ blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
+ blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else if (srccolors[j][i] <= acutValues[3]) {
+ blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
+ blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else if (srccolors[j][i] <= acutValues[4]) {
+ blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
+ blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else {
+ blockerrlin2 += (srccolors[j][i] - alphatest[1]);
+ nralphainrangehigh += 1;
+ }
+ }
+ }
+ /* shouldn't happen often, needed to avoid div by zero */
+ if (nralphainrangelow == 0) nralphainrangelow = 1;
+ if (nralphainrangehigh == 0) nralphainrangehigh = 1;
+ alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
+#if RGTC_DEBUG
+ fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
+ fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
+#endif
+ /* again shouldn't really happen often... */
+ if (alphatest[0] < T_MIN) {
+ alphatest[0] = T_MIN;
+ }
+ alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
+ if (alphatest[1] > T_MAX) {
+ alphatest[1] = T_MIN;
+ }
+
+ alphablockerror3 = 0;
+ for (aindex = 0; aindex < 5; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
+ }
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ /* maybe it's overkill to have the most complicated calculation just for the error
+ calculation which we only need to figure out if encoding1 or encoding2 is better... */
+ if (srccolors[j][i] <= alphatest[0] / 2) {
+ alphaenc3[4*j + i] = 6;
+ alphadist = srccolors[j][i];
+ }
+ else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
+ alphaenc3[4*j + i] = 7;
+ alphadist = T_MAX - srccolors[j][i];
+ }
+ else if (srccolors[j][i] <= acutValues[0]) {
+ alphaenc3[4*j + i] = 0;
+ alphadist = srccolors[j][i] - alphatest[0];
+ }
+ else if (srccolors[j][i] <= acutValues[1]) {
+ alphaenc3[4*j + i] = 2;
+ alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
+ }
+ else if (srccolors[j][i] <= acutValues[2]) {
+ alphaenc3[4*j + i] = 3;
+ alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
+ }
+ else if (srccolors[j][i] <= acutValues[3]) {
+ alphaenc3[4*j + i] = 4;
+ alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
+ }
+ else if (srccolors[j][i] <= acutValues[4]) {
+ alphaenc3[4*j + i] = 5;
+ alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
+ }
+ else {
+ alphaenc3[4*j + i] = 1;
+ alphadist = srccolors[j][i] - alphatest[1];
+ }
+ alphablockerror3 += alphadist * alphadist;
+ }
+ }
+ }
+ }
+ /* write the alpha values and encoding back. */
+ if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
+#if RGTC_DEBUG
+ if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
+#endif
+ TAG(write_rgtc_encoded_channel)( blkaddr, alphause[1], alphause[0], alphaenc1 );
+ }
+ else if (alphablockerror2 <= alphablockerror3) {
+#if RGTC_DEBUG
+ if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
+#endif
+ TAG(write_rgtc_encoded_channel)( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
+ }
+ else {
+#if RGTC_DEBUG
+ fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
+#endif
+ TAG(write_rgtc_encoded_channel)( blkaddr, (TYPE)alphatest[0], (TYPE)alphatest[1], alphaenc3 );
+ }
+}
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
index c3f7d3c32..21d9140c5 100644
--- a/mesalib/src/mesa/main/texgetimage.c
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -1,917 +1,918 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.7
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (c) 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.
- */
-
-
-/**
- * Code for glGetTexImage() and glGetCompressedTexImage().
- */
-
-
-#include "glheader.h"
-#include "bufferobj.h"
-#include "enums.h"
-#include "context.h"
-#include "formats.h"
-#include "image.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "pack.h"
-#include "texgetimage.h"
-#include "teximage.h"
-
-
-
-/**
- * Can the given type represent negative values?
- */
-static INLINE GLboolean
-type_with_negative_values(GLenum type)
-{
- switch (type) {
- case GL_BYTE:
- case GL_SHORT:
- case GL_INT:
- case GL_FLOAT:
- case GL_HALF_FLOAT_ARB:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * glGetTexImage for color index pixels.
- */
-static void
-get_tex_color_index(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- const GLuint indexBits =
- _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT);
- const GLbitfield transferOps = 0x0;
- GLint img, row, col;
-
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- GLuint indexRow[MAX_WIDTH] = { 0 };
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- assert(dest);
-
- if (indexBits == 8) {
- const GLubyte *src = (const GLubyte *) texImage->Data;
- src += width * (img * texImage->Height + row);
- for (col = 0; col < width; col++) {
- indexRow[col] = src[col];
- }
- }
- else if (indexBits == 16) {
- const GLushort *src = (const GLushort *) texImage->Data;
- src += width * (img * texImage->Height + row);
- for (col = 0; col < width; col++) {
- indexRow[col] = src[col];
- }
- }
- else {
- _mesa_problem(ctx, "Color index problem in _mesa_GetTexImage");
- }
- _mesa_pack_index_span(ctx, width, type, dest,
- indexRow, &ctx->Pack, transferOps);
- }
- }
-}
-
-
-/**
- * glGetTexImage for depth/Z pixels.
- */
-static void
-get_tex_depth(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- GLint img, row, col;
- GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));
-
- if (!depthRow) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
- return;
- }
-
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- assert(dest);
-
- for (col = 0; col < width; col++) {
- texImage->FetchTexelf(texImage, col, row, img, depthRow + col);
- }
- _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
- }
- }
-
- free(depthRow);
-}
-
-
-/**
- * glGetTexImage for depth/stencil pixels.
- */
-static void
-get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- const GLuint *src = (const GLuint *) texImage->Data;
- GLint img, row;
-
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- memcpy(dest, src, width * sizeof(GLuint));
- if (ctx->Pack.SwapBytes) {
- _mesa_swap4((GLuint *) dest, width);
- }
-
- src += width * row + width * height * img;
- }
- }
-}
-
-
-/**
- * glGetTexImage for YCbCr pixels.
- */
-static void
-get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- const GLint rowstride = texImage->RowStride;
- const GLushort *src = (const GLushort *) texImage->Data;
- GLint img, row;
-
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- memcpy(dest, src, width * sizeof(GLushort));
-
- /* check for byte swapping */
- if ((texImage->TexFormat == MESA_FORMAT_YCBCR
- && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
- (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
- && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
- if (!ctx->Pack.SwapBytes)
- _mesa_swap2((GLushort *) dest, width);
- }
- else if (ctx->Pack.SwapBytes) {
- _mesa_swap2((GLushort *) dest, width);
- }
-
- src += rowstride;
- }
- }
-}
-
-
-#if FEATURE_EXT_texture_sRGB
-
-
-/**
- * Convert a float value from linear space to a
- * non-linear sRGB value in [0, 255].
- * Not terribly efficient.
- */
-static INLINE GLfloat
-linear_to_nonlinear(GLfloat cl)
-{
- /* can't have values outside [0, 1] */
- GLfloat cs;
- if (cl < 0.0031308f) {
- cs = 12.92f * cl;
- }
- else {
- cs = (GLfloat)(1.055 * pow(cl, 0.41666) - 0.055);
- }
- return cs;
-}
-
-
-/**
- * glGetTexImagefor sRGB pixels;
- */
-static void
-get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- const GLbitfield transferOps = 0x0;
- GLint img, row;
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
-
- if (!rgba) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
- return;
- }
-
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
-
- GLint col;
-
- /* convert row to RGBA format */
- for (col = 0; col < width; col++) {
- texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
- if (texImage->_BaseFormat == GL_LUMINANCE) {
- rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- }
- else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
- rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- }
- else if (texImage->_BaseFormat == GL_RGB ||
- texImage->_BaseFormat == GL_RGBA) {
- rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
- rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
- rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
- }
- }
- _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
- format, type, dest,
- &ctx->Pack, transferOps);
- }
- }
-
- free(rgba);
-}
-
-
-#else /* FEATURE_EXT_texture_sRGB */
-
-
-static INLINE void
-get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- ASSERT_NO_FEATURE();
-}
-
-
-#endif /* FEATURE_EXT_texture_sRGB */
-
-
-/**
- * glGetTexImagefor RGBA, Luminance, etc. pixels.
- * This is the slow way since we use texture sampling.
- */
-static void
-get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_image *texImage)
-{
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- /* Normally, no pixel transfer ops are performed during glGetTexImage.
- * The only possible exception is component clamping to [0,1].
- */
- GLbitfield transferOps = 0x0;
- GLint img, row;
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
-
- if (!rgba) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
- return;
- }
-
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- GLint col;
- GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
-
- /* clamp does not apply to GetTexImage (final conversion)?
- * Looks like we need clamp though when going from format
- * containing negative values to unsigned format.
- */
- if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
- transferOps |= IMAGE_CLAMP_BIT;
- }
- else if (!type_with_negative_values(type) &&
- (dataType == GL_FLOAT ||
- dataType == GL_SIGNED_NORMALIZED)) {
- transferOps |= IMAGE_CLAMP_BIT;
- }
-
- for (col = 0; col < width; col++) {
- texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
- if (texImage->_BaseFormat == GL_ALPHA) {
- rgba[col][RCOMP] = 0.0F;
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- }
- else if (texImage->_BaseFormat == GL_LUMINANCE) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- rgba[col][ACOMP] = 1.0F;
- }
- else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- }
- else if (texImage->_BaseFormat == GL_INTENSITY) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- rgba[col][ACOMP] = 1.0F;
- }
- }
- _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
- format, type, dest,
- &ctx->Pack, transferOps);
- }
- }
-
- free(rgba);
-}
-
-
-/**
- * Try to do glGetTexImage() with simple memcpy().
- * \return GL_TRUE if done, GL_FALSE otherwise
- */
-static GLboolean
-get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels,
- const struct gl_texture_object *texObj,
- const struct gl_texture_image *texImage)
-{
- GLboolean memCopy = GL_FALSE;
-
- /* Texture image should have been mapped already */
- assert(texImage->Data);
-
- /*
- * Check if the src/dst formats are compatible.
- * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
- * so we don't have to worry about those.
- * XXX more format combinations could be supported here.
- */
- if ((texObj->Target == GL_TEXTURE_1D ||
- texObj->Target == GL_TEXTURE_2D ||
- texObj->Target == GL_TEXTURE_RECTANGLE ||
- (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
- texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
- if (texImage->TexFormat == MESA_FORMAT_ARGB8888 &&
- format == GL_BGRA &&
- type == GL_UNSIGNED_BYTE &&
- !ctx->Pack.SwapBytes &&
- _mesa_little_endian()) {
- memCopy = GL_TRUE;
- }
- else if (texImage->TexFormat == MESA_FORMAT_AL88 &&
- format == GL_LUMINANCE_ALPHA &&
- type == GL_UNSIGNED_BYTE &&
- !ctx->Pack.SwapBytes &&
- _mesa_little_endian()) {
- memCopy = GL_TRUE;
- }
- else if (texImage->TexFormat == MESA_FORMAT_L8 &&
- format == GL_LUMINANCE &&
- type == GL_UNSIGNED_BYTE) {
- memCopy = GL_TRUE;
- }
- else if (texImage->TexFormat == MESA_FORMAT_L16 &&
- format == GL_LUMINANCE &&
- type == GL_UNSIGNED_SHORT) {
- memCopy = GL_TRUE;
- }
- else if (texImage->TexFormat == MESA_FORMAT_A8 &&
- format == GL_ALPHA &&
- type == GL_UNSIGNED_BYTE) {
- memCopy = GL_TRUE;
- }
- else if (texImage->TexFormat == MESA_FORMAT_A16 &&
- format == GL_ALPHA &&
- type == GL_UNSIGNED_SHORT) {
- memCopy = GL_TRUE;
- }
- }
-
- if (memCopy) {
- const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
- const GLuint bytesPerRow = texImage->Width * bpp;
- GLubyte *dst =
- _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
- texImage->Height, format, type, 0, 0);
- const GLint dstRowStride =
- _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
- const GLubyte *src = texImage->Data;
- const GLint srcRowStride = texImage->RowStride * bpp;
- GLuint row;
-
- if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
- memcpy(dst, src, bytesPerRow * texImage->Height);
- }
- else {
- for (row = 0; row < texImage->Height; row++) {
- memcpy(dst, src, bytesPerRow);
- dst += dstRowStride;
- src += srcRowStride;
- }
- }
- }
-
- return memCopy;
-}
-
-
-/**
- * This is the software fallback for Driver.GetTexImage().
- * All error checking will have been done before this routine is called.
- * The texture image must be mapped.
- */
-void
-_mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
- GLenum format, GLenum type, GLvoid *pixels,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- GLuint dimensions;
-
- /* If we get here, the texture image should be mapped */
- assert(texImage->Data);
-
- switch (target) {
- case GL_TEXTURE_1D:
- dimensions = 1;
- break;
- case GL_TEXTURE_3D:
- dimensions = 3;
- break;
- default:
- dimensions = 2;
- }
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- /* Packing texture image into a PBO.
- * Map the (potentially) VRAM-based buffer into our process space so
- * we can write into it with the code below.
- * A hardware driver might use a sophisticated blit to move the
- * texture data to the PBO if the PBO is in VRAM along with the texture.
- */
- GLubyte *buf = (GLubyte *)
- ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
- if (!buf) {
- /* out of memory or other unexpected error */
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
- return;
- }
- /* <pixels> was an offset into the PBO.
- * Now make it a real, client-side pointer inside the mapped region.
- */
- pixels = ADD_POINTERS(buf, pixels);
- }
-
- if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) {
- /* all done */
- }
- else if (format == GL_COLOR_INDEX) {
- get_tex_color_index(ctx, dimensions, format, type, pixels, texImage);
- }
- else if (format == GL_DEPTH_COMPONENT) {
- get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
- }
- else if (format == GL_DEPTH_STENCIL_EXT) {
- get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage);
- }
- else if (format == GL_YCBCR_MESA) {
- get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
- }
- else if (_mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB) {
- get_tex_srgb(ctx, dimensions, format, type, pixels, texImage);
- }
- else {
- get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
- }
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
-}
-
-
-
-/**
- * This is the software fallback for Driver.GetCompressedTexImage().
- * All error checking will have been done before this routine is called.
- */
-void
-_mesa_get_compressed_teximage(struct gl_context *ctx, GLenum target, GLint level,
- GLvoid *img,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- const GLuint row_stride = _mesa_format_row_stride(texImage->TexFormat,
- texImage->Width);
- const GLuint row_stride_stored = _mesa_format_row_stride(texImage->TexFormat,
- texImage->RowStride);
- GLuint i;
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- /* pack texture image into a PBO */
- GLubyte *buf = (GLubyte *)
- ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
- if (!buf) {
- /* out of memory or other unexpected error */
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glGetCompresssedTexImage(map PBO failed)");
- return;
- }
- img = ADD_POINTERS(buf, img);
- }
-
- /* no pixelstore or pixel transfer, but respect stride */
-
- if (row_stride == row_stride_stored) {
- const GLuint size = _mesa_format_image_size(texImage->TexFormat,
- texImage->Width,
- texImage->Height,
- texImage->Depth);
- memcpy(img, texImage->Data, size);
- }
- else {
- GLuint bw, bh;
- _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
- for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) {
- memcpy((GLubyte *)img + i * row_stride,
- (GLubyte *)texImage->Data + i * row_stride_stored,
- row_stride);
- }
- }
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
-}
-
-
-
-/**
- * Do error checking for a glGetTexImage() call.
- * \return GL_TRUE if any error, GL_FALSE if no errors.
- */
-static GLboolean
-getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
- GLenum format, GLenum type, GLvoid *pixels )
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
- GLenum baseFormat;
-
- if (maxLevels == 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
- return GL_TRUE;
- }
-
- if (level < 0 || level >= maxLevels) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
- return GL_TRUE;
- }
-
- if (_mesa_sizeof_packed_type(type) <= 0) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
- return GL_TRUE;
- }
-
- if (_mesa_components_in_format(format) <= 0 ||
- format == GL_STENCIL_INDEX) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
- return GL_TRUE;
- }
-
- if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return GL_TRUE;
- }
-
- if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return GL_TRUE;
- }
-
- if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return GL_TRUE;
- }
-
- if (!ctx->Extensions.EXT_packed_depth_stencil
- && _mesa_is_depthstencil_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return GL_TRUE;
- }
-
- if (!ctx->Extensions.ATI_envmap_bumpmap
- && _mesa_is_dudv_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return GL_TRUE;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- if (!texObj || _mesa_is_proxy_texture(target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
- return GL_TRUE;
- }
-
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- /* out of memory */
- return GL_TRUE;
- }
-
- baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
-
- /* Make sure the requested image format is compatible with the
- * texture's format. Note that a color index texture can be converted
- * to RGBA so that combo is allowed.
- */
- if (_mesa_is_color_format(format)
- && !_mesa_is_color_format(baseFormat)
- && !_mesa_is_index_format(baseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- return GL_TRUE;
- }
- else if (_mesa_is_index_format(format)
- && !_mesa_is_index_format(baseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- return GL_TRUE;
- }
- else if (_mesa_is_depth_format(format)
- && !_mesa_is_depth_format(baseFormat)
- && !_mesa_is_depthstencil_format(baseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- return GL_TRUE;
- }
- else if (_mesa_is_ycbcr_format(format)
- && !_mesa_is_ycbcr_format(baseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- return GL_TRUE;
- }
- else if (_mesa_is_depthstencil_format(format)
- && !_mesa_is_depthstencil_format(baseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- return GL_TRUE;
- }
- else if (_mesa_is_dudv_format(format)
- && !_mesa_is_dudv_format(baseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- return GL_TRUE;
- }
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- /* packing texture image into a PBO */
- const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
- if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
- texImage->Height, texImage->Depth,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetTexImage(out of bounds PBO write)");
- return GL_TRUE;
- }
-
- /* PBO should not be mapped */
- if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetTexImage(PBO is mapped)");
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-
-
-/**
- * Get texture image. Called by glGetTexImage.
- *
- * \param target texture target.
- * \param level image level.
- * \param format pixel data format for returned image.
- * \param type pixel data type for returned image.
- * \param pixels returned pixel data.
- */
-void GLAPIENTRY
-_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
- GLenum type, GLvoid *pixels )
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
- return;
- }
-
- if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
- /* not an error, do nothing */
- return;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
- _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
- " dstFmt=0x%x, dstType=0x%x\n",
- texObj->Name,
- _mesa_get_format_name(texImage->TexFormat),
- texImage->Width, texImage->Height,
- format, type);
- }
-
- _mesa_lock_texture(ctx, texObj);
- {
- ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
- texObj, texImage);
- }
- _mesa_unlock_texture(ctx, texObj);
-}
-
-
-
-/**
- * Do error checking for a glGetCompressedTexImage() call.
- * \return GL_TRUE if any error, GL_FALSE if no errors.
- */
-static GLboolean
-getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,
- GLint level, GLvoid *img)
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
-
- if (maxLevels == 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",
- target);
- return GL_TRUE;
- }
-
- if (level < 0 || level >= maxLevels) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetCompressedTexImageARB(bad level = %d)", level);
- return GL_TRUE;
- }
-
- if (_mesa_is_proxy_texture(target)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetCompressedTexImageARB(bad target = %s)",
- _mesa_lookup_enum_by_nr(target));
- return GL_TRUE;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- if (!texObj) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
- return GL_TRUE;
- }
-
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (!texImage) {
- /* probably invalid mipmap level */
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetCompressedTexImageARB(level)");
- return GL_TRUE;
- }
-
- if (!_mesa_is_format_compressed(texImage->TexFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImageARB(texture is not compressed)");
- return GL_TRUE;
- }
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
- GLuint compressedSize;
-
- /* make sure PBO is not mapped */
- if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(PBO is mapped)");
- return GL_TRUE;
- }
-
- compressedSize = _mesa_format_image_size(texImage->TexFormat,
- texImage->Width,
- texImage->Height,
- texImage->Depth);
-
- /* do bounds checking on PBO write */
- if ((const GLubyte *) img + compressedSize >
- (const GLubyte *) ctx->Pack.BufferObj->Size) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(out of bounds PBO write)");
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-
-void GLAPIENTRY
-_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (getcompressedteximage_error_check(ctx, target, level, img)) {
- return;
- }
-
- if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {
- /* not an error, do nothing */
- return;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
- _mesa_debug(ctx,
- "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",
- texObj->Name,
- _mesa_get_format_name(texImage->TexFormat),
- texImage->Width, texImage->Height);
- }
-
- _mesa_lock_texture(ctx, texObj);
- {
- ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
- texObj, texImage);
- }
- _mesa_unlock_texture(ctx, texObj);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.7
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 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.
+ */
+
+
+/**
+ * Code for glGetTexImage() and glGetCompressedTexImage().
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "enums.h"
+#include "context.h"
+#include "formats.h"
+#include "image.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "pack.h"
+#include "pbo.h"
+#include "texgetimage.h"
+#include "teximage.h"
+
+
+
+/**
+ * Can the given type represent negative values?
+ */
+static INLINE GLboolean
+type_with_negative_values(GLenum type)
+{
+ switch (type) {
+ case GL_BYTE:
+ case GL_SHORT:
+ case GL_INT:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_ARB:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * glGetTexImage for color index pixels.
+ */
+static void
+get_tex_color_index(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_image *texImage)
+{
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ const GLuint indexBits =
+ _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT);
+ const GLbitfield transferOps = 0x0;
+ GLint img, row, col;
+
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ GLuint indexRow[MAX_WIDTH] = { 0 };
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ assert(dest);
+
+ if (indexBits == 8) {
+ const GLubyte *src = (const GLubyte *) texImage->Data;
+ src += width * (img * texImage->Height + row);
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[col];
+ }
+ }
+ else if (indexBits == 16) {
+ const GLushort *src = (const GLushort *) texImage->Data;
+ src += width * (img * texImage->Height + row);
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[col];
+ }
+ }
+ else {
+ _mesa_problem(ctx, "Color index problem in _mesa_GetTexImage");
+ }
+ _mesa_pack_index_span(ctx, width, type, dest,
+ indexRow, &ctx->Pack, transferOps);
+ }
+ }
+}
+
+
+/**
+ * glGetTexImage for depth/Z pixels.
+ */
+static void
+get_tex_depth(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_image *texImage)
+{
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ GLint img, row, col;
+ GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));
+
+ if (!depthRow) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
+ return;
+ }
+
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ assert(dest);
+
+ for (col = 0; col < width; col++) {
+ texImage->FetchTexelf(texImage, col, row, img, depthRow + col);
+ }
+ _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
+ }
+ }
+
+ free(depthRow);
+}
+
+
+/**
+ * glGetTexImage for depth/stencil pixels.
+ */
+static void
+get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_image *texImage)
+{
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ const GLuint *src = (const GLuint *) texImage->Data;
+ GLint img, row;
+
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ memcpy(dest, src, width * sizeof(GLuint));
+ if (ctx->Pack.SwapBytes) {
+ _mesa_swap4((GLuint *) dest, width);
+ }
+
+ src += width * row + width * height * img;
+ }
+ }
+}
+
+
+/**
+ * glGetTexImage for YCbCr pixels.
+ */
+static void
+get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_image *texImage)
+{
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ const GLint rowstride = texImage->RowStride;
+ const GLushort *src = (const GLushort *) texImage->Data;
+ GLint img, row;
+
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ memcpy(dest, src, width * sizeof(GLushort));
+
+ /* check for byte swapping */
+ if ((texImage->TexFormat == MESA_FORMAT_YCBCR
+ && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
+ (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
+ && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
+ if (!ctx->Pack.SwapBytes)
+ _mesa_swap2((GLushort *) dest, width);
+ }
+ else if (ctx->Pack.SwapBytes) {
+ _mesa_swap2((GLushort *) dest, width);
+ }
+
+ src += rowstride;
+ }
+ }
+}
+
+
+#if FEATURE_EXT_texture_sRGB
+
+
+/**
+ * Convert a float value from linear space to a
+ * non-linear sRGB value in [0, 255].
+ * Not terribly efficient.
+ */
+static INLINE GLfloat
+linear_to_nonlinear(GLfloat cl)
+{
+ /* can't have values outside [0, 1] */
+ GLfloat cs;
+ if (cl < 0.0031308f) {
+ cs = 12.92f * cl;
+ }
+ else {
+ cs = (GLfloat)(1.055 * pow(cl, 0.41666) - 0.055);
+ }
+ return cs;
+}
+
+
+/**
+ * glGetTexImagefor sRGB pixels;
+ */
+static void
+get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_image *texImage)
+{
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ const GLbitfield transferOps = 0x0;
+ GLint img, row;
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
+
+ if (!rgba) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
+ return;
+ }
+
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+
+ GLint col;
+
+ /* convert row to RGBA format */
+ for (col = 0; col < width; col++) {
+ texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
+ if (texImage->_BaseFormat == GL_LUMINANCE) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_RGB ||
+ texImage->_BaseFormat == GL_RGBA) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
+ rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
+ }
+ }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
+ format, type, dest,
+ &ctx->Pack, transferOps);
+ }
+ }
+
+ free(rgba);
+}
+
+
+#else /* FEATURE_EXT_texture_sRGB */
+
+
+static INLINE void
+get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_image *texImage)
+{
+ ASSERT_NO_FEATURE();
+}
+
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+/**
+ * glGetTexImagefor RGBA, Luminance, etc. pixels.
+ * This is the slow way since we use texture sampling.
+ */
+static void
+get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_image *texImage)
+{
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ /* Normally, no pixel transfer ops are performed during glGetTexImage.
+ * The only possible exception is component clamping to [0,1].
+ */
+ GLbitfield transferOps = 0x0;
+ GLint img, row;
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
+
+ if (!rgba) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
+ return;
+ }
+
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ GLint col;
+ GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
+
+ /* clamp does not apply to GetTexImage (final conversion)?
+ * Looks like we need clamp though when going from format
+ * containing negative values to unsigned format.
+ */
+ if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
+ transferOps |= IMAGE_CLAMP_BIT;
+ }
+ else if (!type_with_negative_values(type) &&
+ (dataType == GL_FLOAT ||
+ dataType == GL_SIGNED_NORMALIZED)) {
+ transferOps |= IMAGE_CLAMP_BIT;
+ }
+
+ for (col = 0; col < width; col++) {
+ texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
+ if (texImage->_BaseFormat == GL_ALPHA) {
+ rgba[col][RCOMP] = 0.0F;
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ rgba[col][ACOMP] = 1.0F;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ }
+ else if (texImage->_BaseFormat == GL_INTENSITY) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ rgba[col][ACOMP] = 1.0F;
+ }
+ }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
+ format, type, dest,
+ &ctx->Pack, transferOps);
+ }
+ }
+
+ free(rgba);
+}
+
+
+/**
+ * Try to do glGetTexImage() with simple memcpy().
+ * \return GL_TRUE if done, GL_FALSE otherwise
+ */
+static GLboolean
+get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_object *texObj,
+ const struct gl_texture_image *texImage)
+{
+ GLboolean memCopy = GL_FALSE;
+
+ /* Texture image should have been mapped already */
+ assert(texImage->Data);
+
+ /*
+ * Check if the src/dst formats are compatible.
+ * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
+ * so we don't have to worry about those.
+ * XXX more format combinations could be supported here.
+ */
+ if ((texObj->Target == GL_TEXTURE_1D ||
+ texObj->Target == GL_TEXTURE_2D ||
+ texObj->Target == GL_TEXTURE_RECTANGLE ||
+ (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+ texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
+ if (texImage->TexFormat == MESA_FORMAT_ARGB8888 &&
+ format == GL_BGRA &&
+ type == GL_UNSIGNED_BYTE &&
+ !ctx->Pack.SwapBytes &&
+ _mesa_little_endian()) {
+ memCopy = GL_TRUE;
+ }
+ else if (texImage->TexFormat == MESA_FORMAT_AL88 &&
+ format == GL_LUMINANCE_ALPHA &&
+ type == GL_UNSIGNED_BYTE &&
+ !ctx->Pack.SwapBytes &&
+ _mesa_little_endian()) {
+ memCopy = GL_TRUE;
+ }
+ else if (texImage->TexFormat == MESA_FORMAT_L8 &&
+ format == GL_LUMINANCE &&
+ type == GL_UNSIGNED_BYTE) {
+ memCopy = GL_TRUE;
+ }
+ else if (texImage->TexFormat == MESA_FORMAT_L16 &&
+ format == GL_LUMINANCE &&
+ type == GL_UNSIGNED_SHORT) {
+ memCopy = GL_TRUE;
+ }
+ else if (texImage->TexFormat == MESA_FORMAT_A8 &&
+ format == GL_ALPHA &&
+ type == GL_UNSIGNED_BYTE) {
+ memCopy = GL_TRUE;
+ }
+ else if (texImage->TexFormat == MESA_FORMAT_A16 &&
+ format == GL_ALPHA &&
+ type == GL_UNSIGNED_SHORT) {
+ memCopy = GL_TRUE;
+ }
+ }
+
+ if (memCopy) {
+ const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
+ const GLuint bytesPerRow = texImage->Width * bpp;
+ GLubyte *dst =
+ _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
+ texImage->Height, format, type, 0, 0);
+ const GLint dstRowStride =
+ _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
+ const GLubyte *src = texImage->Data;
+ const GLint srcRowStride = texImage->RowStride * bpp;
+ GLuint row;
+
+ if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
+ memcpy(dst, src, bytesPerRow * texImage->Height);
+ }
+ else {
+ for (row = 0; row < texImage->Height; row++) {
+ memcpy(dst, src, bytesPerRow);
+ dst += dstRowStride;
+ src += srcRowStride;
+ }
+ }
+ }
+
+ return memCopy;
+}
+
+
+/**
+ * This is the software fallback for Driver.GetTexImage().
+ * All error checking will have been done before this routine is called.
+ * The texture image must be mapped.
+ */
+void
+_mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ GLuint dimensions;
+
+ /* If we get here, the texture image should be mapped */
+ assert(texImage->Data);
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ dimensions = 1;
+ break;
+ case GL_TEXTURE_3D:
+ dimensions = 3;
+ break;
+ default:
+ dimensions = 2;
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* Packing texture image into a PBO.
+ * Map the (potentially) VRAM-based buffer into our process space so
+ * we can write into it with the code below.
+ * A hardware driver might use a sophisticated blit to move the
+ * texture data to the PBO if the PBO is in VRAM along with the texture.
+ */
+ GLubyte *buf = (GLubyte *)
+ ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
+ if (!buf) {
+ /* out of memory or other unexpected error */
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
+ return;
+ }
+ /* <pixels> was an offset into the PBO.
+ * Now make it a real, client-side pointer inside the mapped region.
+ */
+ pixels = ADD_POINTERS(buf, pixels);
+ }
+
+ if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) {
+ /* all done */
+ }
+ else if (format == GL_COLOR_INDEX) {
+ get_tex_color_index(ctx, dimensions, format, type, pixels, texImage);
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
+ }
+ else if (format == GL_DEPTH_STENCIL_EXT) {
+ get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage);
+ }
+ else if (format == GL_YCBCR_MESA) {
+ get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
+ }
+ else if (_mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB) {
+ get_tex_srgb(ctx, dimensions, format, type, pixels, texImage);
+ }
+ else {
+ get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}
+
+
+
+/**
+ * This is the software fallback for Driver.GetCompressedTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_compressed_teximage(struct gl_context *ctx, GLenum target, GLint level,
+ GLvoid *img,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ const GLuint row_stride = _mesa_format_row_stride(texImage->TexFormat,
+ texImage->Width);
+ const GLuint row_stride_stored = _mesa_format_row_stride(texImage->TexFormat,
+ texImage->RowStride);
+ GLuint i;
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* pack texture image into a PBO */
+ GLubyte *buf = (GLubyte *)
+ ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
+ if (!buf) {
+ /* out of memory or other unexpected error */
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glGetCompresssedTexImage(map PBO failed)");
+ return;
+ }
+ img = ADD_POINTERS(buf, img);
+ }
+
+ /* no pixelstore or pixel transfer, but respect stride */
+
+ if (row_stride == row_stride_stored) {
+ const GLuint size = _mesa_format_image_size(texImage->TexFormat,
+ texImage->Width,
+ texImage->Height,
+ texImage->Depth);
+ memcpy(img, texImage->Data, size);
+ }
+ else {
+ GLuint bw, bh;
+ _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
+ for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) {
+ memcpy((GLubyte *)img + i * row_stride,
+ (GLubyte *)texImage->Data + i * row_stride_stored,
+ row_stride);
+ }
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}
+
+
+
+/**
+ * Do error checking for a glGetTexImage() call.
+ * \return GL_TRUE if any error, GL_FALSE if no errors.
+ */
+static GLboolean
+getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
+ GLenum baseFormat;
+
+ if (maxLevels == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
+ return GL_TRUE;
+ }
+
+ if (level < 0 || level >= maxLevels) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
+ return GL_TRUE;
+ }
+
+ if (_mesa_sizeof_packed_type(type) <= 0) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
+ return GL_TRUE;
+ }
+
+ if (_mesa_components_in_format(format) <= 0 ||
+ format == GL_STENCIL_INDEX) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.EXT_packed_depth_stencil
+ && _mesa_is_depthstencil_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap
+ && _mesa_is_dudv_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ if (!texObj || _mesa_is_proxy_texture(target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
+ return GL_TRUE;
+ }
+
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ /* out of memory */
+ return GL_TRUE;
+ }
+
+ baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
+
+ /* Make sure the requested image format is compatible with the
+ * texture's format. Note that a color index texture can be converted
+ * to RGBA so that combo is allowed.
+ */
+ if (_mesa_is_color_format(format)
+ && !_mesa_is_color_format(baseFormat)
+ && !_mesa_is_index_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_index_format(format)
+ && !_mesa_is_index_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_depth_format(format)
+ && !_mesa_is_depth_format(baseFormat)
+ && !_mesa_is_depthstencil_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_ycbcr_format(format)
+ && !_mesa_is_ycbcr_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_depthstencil_format(format)
+ && !_mesa_is_depthstencil_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_dudv_format(format)
+ && !_mesa_is_dudv_format(baseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* packing texture image into a PBO */
+ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+ if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
+ texImage->Height, texImage->Depth,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexImage(out of bounds PBO write)");
+ return GL_TRUE;
+ }
+
+ /* PBO should not be mapped */
+ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexImage(PBO is mapped)");
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+
+/**
+ * Get texture image. Called by glGetTexImage.
+ *
+ * \param target texture target.
+ * \param level image level.
+ * \param format pixel data format for returned image.
+ * \param type pixel data type for returned image.
+ * \param pixels returned pixel data.
+ */
+void GLAPIENTRY
+_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
+ GLenum type, GLvoid *pixels )
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
+ return;
+ }
+
+ if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
+ /* not an error, do nothing */
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
+ _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
+ " dstFmt=0x%x, dstType=0x%x\n",
+ texObj->Name,
+ _mesa_get_format_name(texImage->TexFormat),
+ texImage->Width, texImage->Height,
+ format, type);
+ }
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
+ texObj, texImage);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+/**
+ * Do error checking for a glGetCompressedTexImage() call.
+ * \return GL_TRUE if any error, GL_FALSE if no errors.
+ */
+static GLboolean
+getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,
+ GLint level, GLvoid *img)
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
+
+ if (maxLevels == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",
+ target);
+ return GL_TRUE;
+ }
+
+ if (level < 0 || level >= maxLevels) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetCompressedTexImageARB(bad level = %d)", level);
+ return GL_TRUE;
+ }
+
+ if (_mesa_is_proxy_texture(target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetCompressedTexImageARB(bad target = %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return GL_TRUE;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
+ return GL_TRUE;
+ }
+
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (!texImage) {
+ /* probably invalid mipmap level */
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetCompressedTexImageARB(level)");
+ return GL_TRUE;
+ }
+
+ if (!_mesa_is_format_compressed(texImage->TexFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImageARB(texture is not compressed)");
+ return GL_TRUE;
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ GLuint compressedSize;
+
+ /* make sure PBO is not mapped */
+ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(PBO is mapped)");
+ return GL_TRUE;
+ }
+
+ compressedSize = _mesa_format_image_size(texImage->TexFormat,
+ texImage->Width,
+ texImage->Height,
+ texImage->Depth);
+
+ /* do bounds checking on PBO write */
+ if ((const GLubyte *) img + compressedSize >
+ (const GLubyte *) ctx->Pack.BufferObj->Size) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(out of bounds PBO write)");
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (getcompressedteximage_error_check(ctx, target, level, img)) {
+ return;
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {
+ /* not an error, do nothing */
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
+ _mesa_debug(ctx,
+ "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",
+ texObj->Name,
+ _mesa_get_format_name(texImage->TexFormat),
+ texImage->Width, texImage->Height);
+ }
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
+ texObj, texImage);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index ddad16a8e..d4ae6dd69 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -1,3500 +1,3504 @@
-/*
- * mesa 3-D graphics library
- * Version: 7.6
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009 VMware, Inc. 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 teximage.c
- * Texture image-related functions.
- */
-
-
-#include "glheader.h"
-#include "bufferobj.h"
-#include "context.h"
-#include "enums.h"
-#include "fbobject.h"
-#include "framebuffer.h"
-#include "hash.h"
-#include "image.h"
-#include "imports.h"
-#include "macros.h"
-#include "mfeatures.h"
-#include "state.h"
-#include "texcompress.h"
-#include "texfetch.h"
-#include "teximage.h"
-#include "texstate.h"
-#include "texpal.h"
-#include "mtypes.h"
-
-
-/**
- * State changes which we care about for glCopyTex[Sub]Image() calls.
- * In particular, we care about pixel transfer state and buffer state
- * (such as glReadBuffer to make sure we read from the right renderbuffer).
- */
-#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
- _NEW_BUFFERS | \
- _NEW_PIXEL)
-
-
-
-/**
- * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
- * elsewhere.
- */
-void *
-_mesa_alloc_texmemory(GLsizei bytes)
-{
- return _mesa_align_malloc(bytes, 512);
-}
-
-
-/**
- * Free texture memory allocated with _mesa_alloc_texmemory()
- */
-void
-_mesa_free_texmemory(void *m)
-{
- _mesa_align_free(m);
-}
-
-
-/*
- * Compute floor(log_base_2(n)).
- * If n < 0 return -1.
- */
-static int
-logbase2( int n )
-{
- GLint i = 1;
- GLint log2 = 0;
-
- if (n < 0)
- return -1;
-
- if (n == 0)
- return 0;
-
- while ( n > i ) {
- i *= 2;
- log2++;
- }
- if (i != n) {
- return log2 - 1;
- }
- else {
- return log2;
- }
-}
-
-
-
-/**
- * Return the simple base format for a given internal texture format.
- * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
- *
- * \param ctx GL context.
- * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
- *
- * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
- * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
- *
- * This is the format which is used during texture application (i.e. the
- * texture format and env mode determine the arithmetic used.
- *
- * XXX this could be static
- */
-GLint
-_mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
-{
- switch (internalFormat) {
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- return GL_ALPHA;
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- return GL_LUMINANCE;
- case 2:
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE4_ALPHA4:
- case GL_LUMINANCE6_ALPHA2:
- case GL_LUMINANCE8_ALPHA8:
- case GL_LUMINANCE12_ALPHA4:
- case GL_LUMINANCE12_ALPHA12:
- case GL_LUMINANCE16_ALPHA16:
- return GL_LUMINANCE_ALPHA;
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- return GL_INTENSITY;
- case 3:
- case GL_RGB:
- case GL_R3_G3_B2:
- case GL_RGB4:
- case GL_RGB5:
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- return GL_RGB;
- case 4:
- case GL_RGBA:
- case GL_RGBA2:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
-
- if (ctx->Extensions.EXT_texture_format_BGRA8888) {
- switch (internalFormat) {
- case GL_BGRA_EXT:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.EXT_paletted_texture) {
- switch (internalFormat) {
- case GL_COLOR_INDEX:
- case GL_COLOR_INDEX1_EXT:
- case GL_COLOR_INDEX2_EXT:
- case GL_COLOR_INDEX4_EXT:
- case GL_COLOR_INDEX8_EXT:
- case GL_COLOR_INDEX12_EXT:
- case GL_COLOR_INDEX16_EXT:
- return GL_COLOR_INDEX;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.ARB_depth_texture) {
- switch (internalFormat) {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- return GL_DEPTH_COMPONENT;
- default:
- ; /* fallthrough */
- }
- }
-
- switch (internalFormat) {
- case GL_COMPRESSED_ALPHA:
- return GL_ALPHA;
- case GL_COMPRESSED_LUMINANCE:
- return GL_LUMINANCE;
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- return GL_LUMINANCE_ALPHA;
- case GL_COMPRESSED_INTENSITY:
- return GL_INTENSITY;
- case GL_COMPRESSED_RGB:
- return GL_RGB;
- case GL_COMPRESSED_RGBA:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
-
- if (ctx->Extensions.TDFX_texture_compression_FXT1) {
- switch (internalFormat) {
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- return GL_RGB;
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.EXT_texture_compression_s3tc) {
- switch (internalFormat) {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- return GL_RGB;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.S3_s3tc) {
- switch (internalFormat) {
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- return GL_RGB;
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.MESA_ycbcr_texture) {
- if (internalFormat == GL_YCBCR_MESA)
- return GL_YCBCR_MESA;
- }
-
- if (ctx->Extensions.ARB_texture_float) {
- switch (internalFormat) {
- case GL_ALPHA16F_ARB:
- case GL_ALPHA32F_ARB:
- return GL_ALPHA;
- case GL_RGBA16F_ARB:
- case GL_RGBA32F_ARB:
- return GL_RGBA;
- case GL_RGB16F_ARB:
- case GL_RGB32F_ARB:
- return GL_RGB;
- case GL_INTENSITY16F_ARB:
- case GL_INTENSITY32F_ARB:
- return GL_INTENSITY;
- case GL_LUMINANCE16F_ARB:
- case GL_LUMINANCE32F_ARB:
- return GL_LUMINANCE;
- case GL_LUMINANCE_ALPHA16F_ARB:
- case GL_LUMINANCE_ALPHA32F_ARB:
- return GL_LUMINANCE_ALPHA;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.ATI_envmap_bumpmap) {
- switch (internalFormat) {
- case GL_DUDV_ATI:
- case GL_DU8DV8_ATI:
- return GL_DUDV_ATI;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.MESA_texture_signed_rgba) {
- switch (internalFormat) {
- case GL_RGBA_SNORM:
- case GL_RGBA8_SNORM:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.EXT_packed_depth_stencil) {
- switch (internalFormat) {
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- return GL_DEPTH_STENCIL_EXT;
- default:
- ; /* fallthrough */
- }
- }
-
-#if FEATURE_EXT_texture_sRGB
- if (ctx->Extensions.EXT_texture_sRGB) {
- switch (internalFormat) {
- case GL_SRGB_EXT:
- case GL_SRGB8_EXT:
- case GL_COMPRESSED_SRGB_EXT:
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
- return GL_RGB;
- case GL_SRGB_ALPHA_EXT:
- case GL_SRGB8_ALPHA8_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- return GL_RGBA;
- case GL_SLUMINANCE_ALPHA_EXT:
- case GL_SLUMINANCE8_ALPHA8_EXT:
- case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
- return GL_LUMINANCE_ALPHA;
- case GL_SLUMINANCE_EXT:
- case GL_SLUMINANCE8_EXT:
- case GL_COMPRESSED_SLUMINANCE_EXT:
- return GL_LUMINANCE;
- default:
- ; /* fallthrough */
- }
- }
-#endif /* FEATURE_EXT_texture_sRGB */
-
- if (ctx->Extensions.EXT_texture_integer) {
- switch (internalFormat) {
- case GL_RGBA8UI_EXT:
- case GL_RGBA16UI_EXT:
- case GL_RGBA32UI_EXT:
- case GL_RGBA8I_EXT:
- case GL_RGBA16I_EXT:
- case GL_RGBA32I_EXT:
- return GL_RGBA;
- case GL_RGB8UI_EXT:
- case GL_RGB16UI_EXT:
- case GL_RGB32UI_EXT:
- case GL_RGB8I_EXT:
- case GL_RGB16I_EXT:
- case GL_RGB32I_EXT:
- return GL_RGB;
- case GL_ALPHA8UI_EXT:
- case GL_ALPHA16UI_EXT:
- case GL_ALPHA32UI_EXT:
- case GL_ALPHA8I_EXT:
- case GL_ALPHA16I_EXT:
- case GL_ALPHA32I_EXT:
- return GL_ALPHA;
- case GL_INTENSITY8UI_EXT:
- case GL_INTENSITY16UI_EXT:
- case GL_INTENSITY32UI_EXT:
- case GL_INTENSITY8I_EXT:
- case GL_INTENSITY16I_EXT:
- case GL_INTENSITY32I_EXT:
- return GL_INTENSITY;
- case GL_LUMINANCE8UI_EXT:
- case GL_LUMINANCE16UI_EXT:
- case GL_LUMINANCE32UI_EXT:
- case GL_LUMINANCE8I_EXT:
- case GL_LUMINANCE16I_EXT:
- case GL_LUMINANCE32I_EXT:
- return GL_LUMINANCE;
- case GL_LUMINANCE_ALPHA8UI_EXT:
- case GL_LUMINANCE_ALPHA16UI_EXT:
- case GL_LUMINANCE_ALPHA32UI_EXT:
- case GL_LUMINANCE_ALPHA8I_EXT:
- case GL_LUMINANCE_ALPHA16I_EXT:
- case GL_LUMINANCE_ALPHA32I_EXT:
- return GL_LUMINANCE_ALPHA;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.ARB_texture_rg) {
- switch (internalFormat) {
- case GL_R16F:
- /* R16F depends on both ARB_half_float_pixel and ARB_texture_float.
- */
- if (!ctx->Extensions.ARB_half_float_pixel)
- break;
- /* FALLTHROUGH */
- case GL_R32F:
- if (!ctx->Extensions.ARB_texture_float)
- break;
- return GL_RED;
- case GL_R8I:
- case GL_R8UI:
- case GL_R16I:
- case GL_R16UI:
- case GL_R32I:
- case GL_R32UI:
- if (!ctx->Extensions.EXT_texture_integer)
- break;
- /* FALLTHROUGH */
- case GL_R8:
- case GL_R16:
- case GL_RED:
- case GL_COMPRESSED_RED:
- return GL_RED;
-
- case GL_RG16F:
- /* RG16F depends on both ARB_half_float_pixel and ARB_texture_float.
- */
- if (!ctx->Extensions.ARB_half_float_pixel)
- break;
- /* FALLTHROUGH */
- case GL_RG32F:
- if (!ctx->Extensions.ARB_texture_float)
- break;
- return GL_RG;
- case GL_RG8I:
- case GL_RG8UI:
- case GL_RG16I:
- case GL_RG16UI:
- case GL_RG32I:
- case GL_RG32UI:
- if (!ctx->Extensions.EXT_texture_integer)
- break;
- /* FALLTHROUGH */
- case GL_RG:
- case GL_RG8:
- case GL_RG16:
- case GL_COMPRESSED_RG:
- return GL_RG;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.EXT_texture_shared_exponent) {
- switch (internalFormat) {
- case GL_RGB9_E5_EXT:
- return GL_RGB;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.EXT_packed_float) {
- switch (internalFormat) {
- case GL_R11F_G11F_B10F_EXT:
- return GL_RGB;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.ARB_depth_buffer_float) {
- switch (internalFormat) {
- case GL_DEPTH_COMPONENT32F:
- return GL_DEPTH_COMPONENT;
- case GL_DEPTH32F_STENCIL8:
- return GL_DEPTH_STENCIL;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.ARB_texture_compression_rgtc) {
- switch (internalFormat) {
- case GL_COMPRESSED_RED_RGTC1:
- case GL_COMPRESSED_SIGNED_RED_RGTC1:
- return GL_RED;
- case GL_COMPRESSED_RG_RGTC2:
- case GL_COMPRESSED_SIGNED_RG_RGTC2:
- return GL_RG;
- default:
- ; /* fallthrough */
- }
- }
-
- return -1; /* error */
-}
-
-
-/**
- * For cube map faces, return a face index in [0,5].
- * For other targets return 0;
- */
-GLuint
-_mesa_tex_target_to_face(GLenum target)
-{
- if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
- return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- else
- return 0;
-}
-
-
-
-/**
- * Store a gl_texture_image pointer in a gl_texture_object structure
- * according to the target and level parameters.
- *
- * \param tObj texture object.
- * \param target texture target.
- * \param level image level.
- * \param texImage texture image.
- *
- * This was basically prompted by the introduction of cube maps.
- */
-void
-_mesa_set_tex_image(struct gl_texture_object *tObj,
- GLenum target, GLint level,
- struct gl_texture_image *texImage)
-{
- const GLuint face = _mesa_tex_target_to_face(target);
-
- ASSERT(tObj);
- ASSERT(texImage);
- ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0);
-
- tObj->Image[face][level] = texImage;
-
- /* Set the 'back' pointer */
- texImage->TexObject = tObj;
-}
-
-
-/**
- * Allocate a texture image structure.
- *
- * Called via ctx->Driver.NewTextureImage() unless overriden by a device
- * driver.
- *
- * \return a pointer to gl_texture_image struct with all fields initialized to
- * zero.
- */
-struct gl_texture_image *
-_mesa_new_texture_image( struct gl_context *ctx )
-{
- (void) ctx;
- return CALLOC_STRUCT(gl_texture_image);
-}
-
-
-/**
- * Free texture image data.
- * This function is a fallback called via ctx->Driver.FreeTexImageData().
- *
- * \param texImage texture image.
- *
- * Free the texture image data if it's not marked as client data.
- */
-void
-_mesa_free_texture_image_data(struct gl_context *ctx,
- struct gl_texture_image *texImage)
-{
- (void) ctx;
-
- if (texImage->Data && !texImage->IsClientData) {
- /* free the old texture data */
- _mesa_free_texmemory(texImage->Data);
- }
-
- texImage->Data = NULL;
-}
-
-
-/**
- * Free texture image.
- *
- * \param texImage texture image.
- *
- * Free the texture image structure and the associated image data.
- */
-void
-_mesa_delete_texture_image(struct gl_context *ctx,
- struct gl_texture_image *texImage)
-{
- /* Free texImage->Data and/or any other driver-specific texture
- * image storage.
- */
- ASSERT(ctx->Driver.FreeTexImageData);
- ctx->Driver.FreeTexImageData( ctx, texImage );
-
- ASSERT(texImage->Data == NULL);
- if (texImage->ImageOffsets)
- free(texImage->ImageOffsets);
- free(texImage);
-}
-
-
-/**
- * Test if a target is a proxy target.
- *
- * \param target texture target.
- *
- * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
- */
-GLboolean
-_mesa_is_proxy_texture(GLenum target)
-{
- /* NUM_TEXTURE_TARGETS should match number of terms below */
- assert(NUM_TEXTURE_TARGETS == 7);
-
- return (target == GL_PROXY_TEXTURE_1D ||
- target == GL_PROXY_TEXTURE_2D ||
- target == GL_PROXY_TEXTURE_3D ||
- target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
- target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
- target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
- target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
-}
-
-
-/**
- * Return the proxy target which corresponds to the given texture target
- */
-static GLenum
-get_proxy_target(GLenum target)
-{
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_PROXY_TEXTURE_1D:
- return GL_PROXY_TEXTURE_1D;
- case GL_TEXTURE_2D:
- case GL_PROXY_TEXTURE_2D:
- return GL_PROXY_TEXTURE_2D;
- case GL_TEXTURE_3D:
- case GL_PROXY_TEXTURE_3D:
- return GL_PROXY_TEXTURE_3D;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_ARB:
- case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
- return GL_PROXY_TEXTURE_CUBE_MAP_ARB;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- return GL_PROXY_TEXTURE_RECTANGLE_NV;
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- return GL_PROXY_TEXTURE_1D_ARRAY_EXT;
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- return GL_PROXY_TEXTURE_2D_ARRAY_EXT;
- default:
- _mesa_problem(NULL, "unexpected target in get_proxy_target()");
- return 0;
- }
-}
-
-
-/**
- * Get the texture object that corresponds to the target of the given
- * texture unit.
- *
- * \param ctx GL context.
- * \param texUnit texture unit.
- * \param target texture target.
- *
- * \return pointer to the texture object on success, or NULL on failure.
- *
- * \sa gl_texture_unit.
- */
-struct gl_texture_object *
-_mesa_select_tex_object(struct gl_context *ctx,
- const struct gl_texture_unit *texUnit,
- GLenum target)
-{
- const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
-
- switch (target) {
- case GL_TEXTURE_1D:
- return texUnit->CurrentTex[TEXTURE_1D_INDEX];
- case GL_PROXY_TEXTURE_1D:
- return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
- case GL_TEXTURE_2D:
- return texUnit->CurrentTex[TEXTURE_2D_INDEX];
- case GL_PROXY_TEXTURE_2D:
- return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
- case GL_TEXTURE_3D:
- return texUnit->CurrentTex[TEXTURE_3D_INDEX];
- case GL_PROXY_TEXTURE_3D:
- return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_ARB:
- return ctx->Extensions.ARB_texture_cube_map
- ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
- case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
- return ctx->Extensions.ARB_texture_cube_map
- ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
- case GL_TEXTURE_RECTANGLE_NV:
- return ctx->Extensions.NV_texture_rectangle
- ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- return ctx->Extensions.NV_texture_rectangle
- ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
- case GL_TEXTURE_1D_ARRAY_EXT:
- return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
- case GL_TEXTURE_2D_ARRAY_EXT:
- return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
- default:
- _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
- return NULL;
- }
-}
-
-
-/**
- * Return pointer to texture object for given target on current texture unit.
- */
-struct gl_texture_object *
-_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
-{
- struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
- return _mesa_select_tex_object(ctx, texUnit, target);
-}
-
-
-/**
- * Get a texture image pointer from a texture object, given a texture
- * target and mipmap level. The target and level parameters should
- * have already been error-checked.
- *
- * \param ctx GL context.
- * \param texObj texture unit.
- * \param target texture target.
- * \param level image level.
- *
- * \return pointer to the texture image structure, or NULL on failure.
- */
-struct gl_texture_image *
-_mesa_select_tex_image(struct gl_context *ctx,
- const struct gl_texture_object *texObj,
- GLenum target, GLint level)
-{
- const GLuint face = _mesa_tex_target_to_face(target);
-
- ASSERT(texObj);
- ASSERT(level >= 0);
- ASSERT(level < MAX_TEXTURE_LEVELS);
-
- return texObj->Image[face][level];
-}
-
-
-/**
- * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
- * it and install it. Only return NULL if passed a bad parameter or run
- * out of memory.
- */
-struct gl_texture_image *
-_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj,
- GLenum target, GLint level)
-{
- struct gl_texture_image *texImage;
-
- if (!texObj)
- return NULL;
-
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
- return NULL;
- }
-
- _mesa_set_tex_image(texObj, target, level, texImage);
- }
-
- return texImage;
-}
-
-
-/**
- * Return pointer to the specified proxy texture image.
- * Note that proxy textures are per-context, not per-texture unit.
- * \return pointer to texture image or NULL if invalid target, invalid
- * level, or out of memory.
- */
-struct gl_texture_image *
-_mesa_get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
-{
- struct gl_texture_image *texImage;
- GLuint texIndex;
-
- if (level < 0 )
- return NULL;
-
- switch (target) {
- case GL_PROXY_TEXTURE_1D:
- if (level >= ctx->Const.MaxTextureLevels)
- return NULL;
- texIndex = TEXTURE_1D_INDEX;
- break;
- case GL_PROXY_TEXTURE_2D:
- if (level >= ctx->Const.MaxTextureLevels)
- return NULL;
- texIndex = TEXTURE_2D_INDEX;
- break;
- case GL_PROXY_TEXTURE_3D:
- if (level >= ctx->Const.Max3DTextureLevels)
- return NULL;
- texIndex = TEXTURE_3D_INDEX;
- break;
- case GL_PROXY_TEXTURE_CUBE_MAP:
- if (level >= ctx->Const.MaxCubeTextureLevels)
- return NULL;
- texIndex = TEXTURE_CUBE_INDEX;
- break;
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- if (level > 0)
- return NULL;
- texIndex = TEXTURE_RECT_INDEX;
- break;
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- if (level >= ctx->Const.MaxTextureLevels)
- return NULL;
- texIndex = TEXTURE_1D_ARRAY_INDEX;
- break;
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- if (level >= ctx->Const.MaxTextureLevels)
- return NULL;
- texIndex = TEXTURE_2D_ARRAY_INDEX;
- break;
- default:
- return NULL;
- }
-
- texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
- }
- return texImage;
-}
-
-
-/**
- * Get the maximum number of allowed mipmap levels.
- *
- * \param ctx GL context.
- * \param target texture target.
- *
- * \return the maximum number of allowed mipmap levels for the given
- * texture target, or zero if passed a bad target.
- *
- * \sa gl_constants.
- */
-GLint
-_mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
-{
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_PROXY_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_PROXY_TEXTURE_2D:
- return ctx->Const.MaxTextureLevels;
- case GL_TEXTURE_3D:
- case GL_PROXY_TEXTURE_3D:
- return ctx->Const.Max3DTextureLevels;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_ARB:
- case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
- return ctx->Extensions.ARB_texture_cube_map
- ? ctx->Const.MaxCubeTextureLevels : 0;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array)
- ? ctx->Const.MaxTextureLevels : 0;
- default:
- return 0; /* bad target */
- }
-}
-
-
-/**
- * Return number of dimensions per mipmap level for the given texture target.
- */
-GLint
-_mesa_get_texture_dimensions(GLenum target)
-{
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_PROXY_TEXTURE_1D:
- return 1;
- case GL_TEXTURE_2D:
- case GL_TEXTURE_RECTANGLE:
- case GL_TEXTURE_CUBE_MAP:
- case GL_PROXY_TEXTURE_2D:
- case GL_PROXY_TEXTURE_RECTANGLE:
- case GL_PROXY_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- case GL_TEXTURE_1D_ARRAY:
- case GL_PROXY_TEXTURE_1D_ARRAY:
- return 2;
- case GL_TEXTURE_3D:
- case GL_PROXY_TEXTURE_3D:
- case GL_TEXTURE_2D_ARRAY:
- case GL_PROXY_TEXTURE_2D_ARRAY:
- return 3;
- default:
- _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()",
- target);
- return 2;
- }
-}
-
-
-
-
-#if 000 /* not used anymore */
-/*
- * glTexImage[123]D can accept a NULL image pointer. In this case we
- * create a texture image with unspecified image contents per the OpenGL
- * spec.
- */
-static GLubyte *
-make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
-{
- const GLint components = _mesa_components_in_format(format);
- const GLint numPixels = width * height * depth;
- GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
-
-#ifdef DEBUG
- /*
- * Let's see if anyone finds this. If glTexImage2D() is called with
- * a NULL image pointer then load the texture image with something
- * interesting instead of leaving it indeterminate.
- */
- if (data) {
- static const char message[8][32] = {
- " X X XXXXX XXX X ",
- " XX XX X X X X X ",
- " X X X X X X X ",
- " X X XXXX XXX XXXXX ",
- " X X X X X X ",
- " X X X X X X X ",
- " X X XXXXX XXX X X ",
- " "
- };
-
- GLubyte *imgPtr = data;
- GLint h, i, j, k;
- for (h = 0; h < depth; h++) {
- for (i = 0; i < height; i++) {
- GLint srcRow = 7 - (i % 8);
- for (j = 0; j < width; j++) {
- GLint srcCol = j % 32;
- GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
- for (k = 0; k < components; k++) {
- *imgPtr++ = texel;
- }
- }
- }
- }
- }
-#endif
-
- return data;
-}
-#endif
-
-
-
-/**
- * Reset the fields of a gl_texture_image struct to zero.
- *
- * \param img texture image structure.
- *
- * This is called when a proxy texture test fails, we set all the
- * image members (except DriverData) to zero.
- * It's also used in glTexImage[123]D as a safeguard to be sure all
- * required fields get initialized properly by the Driver.TexImage[123]D
- * functions.
- */
-static void
-clear_teximage_fields(struct gl_texture_image *img)
-{
- ASSERT(img);
- img->_BaseFormat = 0;
- img->InternalFormat = 0;
- img->Border = 0;
- img->Width = 0;
- img->Height = 0;
- img->Depth = 0;
- img->RowStride = 0;
- if (img->ImageOffsets) {
- free(img->ImageOffsets);
- img->ImageOffsets = NULL;
- }
- img->Width2 = 0;
- img->Height2 = 0;
- img->Depth2 = 0;
- img->WidthLog2 = 0;
- img->HeightLog2 = 0;
- img->DepthLog2 = 0;
- img->Data = NULL;
- img->TexFormat = MESA_FORMAT_NONE;
- img->FetchTexelc = NULL;
- img->FetchTexelf = NULL;
-}
-
-
-/**
- * Initialize basic fields of the gl_texture_image struct.
- *
- * \param ctx GL context.
- * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
- * \param img texture image structure to be initialized.
- * \param width image width.
- * \param height image height.
- * \param depth image depth.
- * \param border image border.
- * \param internalFormat internal format.
- * \param format the actual hardware format (one of MESA_FORMAT_*)
- *
- * Fills in the fields of \p img with the given information.
- * Note: width, height and depth include the border.
- */
-void
-_mesa_init_teximage_fields(struct gl_context *ctx, GLenum target,
- struct gl_texture_image *img,
- GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLenum internalFormat,
- gl_format format)
-{
- GLint i, dims;
-
- ASSERT(img);
- ASSERT(width >= 0);
- ASSERT(height >= 0);
- ASSERT(depth >= 0);
-
- img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
- ASSERT(img->_BaseFormat > 0);
- img->InternalFormat = internalFormat;
- img->Border = border;
- img->Width = width;
- img->Height = height;
- img->Depth = depth;
-
- img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
- img->WidthLog2 = logbase2(img->Width2);
-
- if (height == 1) { /* 1-D texture */
- img->Height2 = 1;
- img->HeightLog2 = 0;
- }
- else {
- img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
- img->HeightLog2 = logbase2(img->Height2);
- }
-
- if (depth == 1) { /* 2-D texture */
- img->Depth2 = 1;
- img->DepthLog2 = 0;
- }
- else {
- img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
- img->DepthLog2 = logbase2(img->Depth2);
- }
-
- img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
-
- if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
- (height == 1 || _mesa_is_pow_two(img->Height2)) &&
- (depth == 1 || _mesa_is_pow_two(img->Depth2)))
- img->_IsPowerOfTwo = GL_TRUE;
- else
- img->_IsPowerOfTwo = GL_FALSE;
-
- /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
- img->RowStride = width;
- /* Allocate the ImageOffsets array and initialize to typical values.
- * We allocate the array for 1D/2D textures too in order to avoid special-
- * case code in the texstore routines.
- */
- if (img->ImageOffsets)
- free(img->ImageOffsets);
- img->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint));
- for (i = 0; i < depth; i++) {
- img->ImageOffsets[i] = i * width * height;
- }
-
- /* Compute Width/Height/DepthScale for mipmap lod computation */
- if (target == GL_TEXTURE_RECTANGLE_NV) {
- /* scale = 1.0 since texture coords directly map to texels */
- img->WidthScale = 1.0;
- img->HeightScale = 1.0;
- img->DepthScale = 1.0;
- }
- else {
- img->WidthScale = (GLfloat) img->Width;
- img->HeightScale = (GLfloat) img->Height;
- img->DepthScale = (GLfloat) img->Depth;
- }
-
- img->TexFormat = format;
-
- dims = _mesa_get_texture_dimensions(target);
-
- _mesa_set_fetch_functions(img, dims);
-}
-
-
-/**
- * Free and clear fields of the gl_texture_image struct.
- *
- * \param ctx GL context.
- * \param texImage texture image structure to be cleared.
- *
- * After the call, \p texImage will have no data associated with it. Its
- * fields are cleared so that its parent object will test incomplete.
- */
-void
-_mesa_clear_texture_image(struct gl_context *ctx,
- struct gl_texture_image *texImage)
-{
- ctx->Driver.FreeTexImageData(ctx, texImage);
- clear_teximage_fields(texImage);
-}
-
-
-/**
- * This is the fallback for Driver.TestProxyTexImage(). Test the texture
- * level, width, height and depth against the ctx->Const limits for textures.
- *
- * A hardware driver might override this function if, for example, the
- * max 3D texture size is 512x512x64 (i.e. not a cube).
- *
- * Note that width, height, depth == 0 is not an error. However, a
- * texture with zero width/height/depth will be considered "incomplete"
- * and texturing will effectively be disabled.
- *
- * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
- * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
- * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
- * \param level as passed to glTexImage
- * \param internalFormat as passed to glTexImage
- * \param format as passed to glTexImage
- * \param type as passed to glTexImage
- * \param width as passed to glTexImage
- * \param height as passed to glTexImage
- * \param depth as passed to glTexImage
- * \param border as passed to glTexImage
- * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
- */
-GLboolean
-_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
- GLint internalFormat, GLenum format, GLenum type,
- GLint width, GLint height, GLint depth, GLint border)
-{
- GLint maxSize;
-
- (void) internalFormat;
- (void) format;
- (void) type;
-
- switch (target) {
- case GL_PROXY_TEXTURE_1D:
- maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize)
- return GL_FALSE;
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
- if (!ctx->Extensions.ARB_texture_non_power_of_two) {
- if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
- return GL_FALSE;
- }
- return GL_TRUE;
-
- case GL_PROXY_TEXTURE_2D:
- maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize)
- return GL_FALSE;
- if (height < 2 * border || height > 2 + maxSize)
- return GL_FALSE;
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
- if (!ctx->Extensions.ARB_texture_non_power_of_two) {
- if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
- return GL_FALSE;
- if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
- return GL_FALSE;
- }
- return GL_TRUE;
-
- case GL_PROXY_TEXTURE_3D:
- maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize)
- return GL_FALSE;
- if (height < 2 * border || height > 2 + maxSize)
- return GL_FALSE;
- if (depth < 2 * border || depth > 2 + maxSize)
- return GL_FALSE;
- if (level >= ctx->Const.Max3DTextureLevels)
- return GL_FALSE;
- if (!ctx->Extensions.ARB_texture_non_power_of_two) {
- if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
- return GL_FALSE;
- if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
- return GL_FALSE;
- if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border))
- return GL_FALSE;
- }
- return GL_TRUE;
-
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- maxSize = ctx->Const.MaxTextureRectSize;
- if (width < 0 || width > maxSize)
- return GL_FALSE;
- if (height < 0 || height > maxSize)
- return GL_FALSE;
- if (level != 0)
- return GL_FALSE;
- return GL_TRUE;
-
- case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
- maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize)
- return GL_FALSE;
- if (height < 2 * border || height > 2 + maxSize)
- return GL_FALSE;
- if (level >= ctx->Const.MaxCubeTextureLevels)
- return GL_FALSE;
- if (!ctx->Extensions.ARB_texture_non_power_of_two) {
- if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
- return GL_FALSE;
- if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
- return GL_FALSE;
- }
- return GL_TRUE;
-
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize)
- return GL_FALSE;
- if (height < 1 || height > ctx->Const.MaxArrayTextureLayers)
- return GL_FALSE;
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
- if (!ctx->Extensions.ARB_texture_non_power_of_two) {
- if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
- return GL_FALSE;
- }
- return GL_TRUE;
-
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize)
- return GL_FALSE;
- if (height < 2 * border || height > 2 + maxSize)
- return GL_FALSE;
- if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers)
- return GL_FALSE;
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
- if (!ctx->Extensions.ARB_texture_non_power_of_two) {
- if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
- return GL_FALSE;
- if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
- return GL_FALSE;
- }
- return GL_TRUE;
-
- default:
- _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if the memory used by the texture would exceed the driver's limit.
- * This lets us support a max 3D texture size of 8K (for example) but
- * prevents allocating a full 8K x 8K x 8K texture.
- * XXX this could be rolled into the proxy texture size test (above) but
- * we don't have the actual texture internal format at that point.
- */
-static GLboolean
-legal_texture_size(struct gl_context *ctx, gl_format format,
- GLint width, GLint height, GLint depth)
-{
- uint64_t bytes = _mesa_format_image_size64(format, width, height, depth);
- uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */
- return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes;
-}
-
-
-
-/**
- * Helper function to determine whether a target and specific compression
- * format are supported.
- */
-static GLboolean
-target_can_be_compressed(const struct gl_context *ctx, GLenum target,
- GLenum intFormat)
-{
- (void) intFormat; /* not used yet */
-
- switch (target) {
- case GL_TEXTURE_2D:
- case GL_PROXY_TEXTURE_2D:
- return GL_TRUE; /* true for any compressed format so far */
- case GL_PROXY_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- return ctx->Extensions.ARB_texture_cube_map;
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- case GL_TEXTURE_2D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if the given texture target value is legal for a
- * glTexImage1/2/3D call.
- */
-static GLboolean
-legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
-{
- switch (dims) {
- case 1:
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_PROXY_TEXTURE_1D:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
- case 2:
- switch (target) {
- case GL_TEXTURE_2D:
- case GL_PROXY_TEXTURE_2D:
- return GL_TRUE;
- case GL_PROXY_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- return ctx->Extensions.ARB_texture_cube_map;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- return ctx->Extensions.NV_texture_rectangle;
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
- default:
- return GL_FALSE;
- }
- case 3:
- switch (target) {
- case GL_TEXTURE_3D:
- case GL_PROXY_TEXTURE_3D:
- return GL_TRUE;
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
- default:
- return GL_FALSE;
- }
- default:
- _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims);
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if the given texture target value is legal for a
- * glTexSubImage, glCopyTexSubImage or glCopyTexImage call.
- * The difference compared to legal_teximage_target() above is that
- * proxy targets are not supported.
- */
-static GLboolean
-legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
-{
- switch (dims) {
- case 1:
- return target == GL_TEXTURE_1D;
- case 2:
- switch (target) {
- case GL_TEXTURE_2D:
- return GL_TRUE;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- return ctx->Extensions.ARB_texture_cube_map;
- case GL_TEXTURE_RECTANGLE_NV:
- return ctx->Extensions.NV_texture_rectangle;
- case GL_TEXTURE_1D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
- default:
- return GL_FALSE;
- }
- case 3:
- switch (target) {
- case GL_TEXTURE_3D:
- return GL_TRUE;
- case GL_TEXTURE_2D_ARRAY_EXT:
- return (ctx->Extensions.MESA_texture_array ||
- ctx->Extensions.EXT_texture_array);
- default:
- return GL_FALSE;
- }
- default:
- _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()",
- dims);
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test the glTexImage[123]D() parameters for errors.
- *
- * \param ctx GL context.
- * \param dimensions texture image dimensions (must be 1, 2 or 3).
- * \param target texture target given by the user.
- * \param level image level given by the user.
- * \param internalFormat internal format given by the user.
- * \param format pixel data format given by the user.
- * \param type pixel data type given by the user.
- * \param width image width given by the user.
- * \param height image height given by the user.
- * \param depth image depth given by the user.
- * \param border image border given by the user.
- *
- * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- *
- * Verifies each of the parameters against the constants specified in
- * __struct gl_contextRec::Const and the supported extensions, and according
- * to the OpenGL specification.
- */
-static GLboolean
-texture_error_check( struct gl_context *ctx,
- GLuint dimensions, GLenum target,
- GLint level, GLint internalFormat,
- GLenum format, GLenum type,
- GLint width, GLint height,
- GLint depth, GLint border )
-{
- const GLenum proxyTarget = get_proxy_target(target);
- const GLboolean isProxy = target == proxyTarget;
- GLboolean sizeOK = GL_TRUE;
- GLboolean colorFormat, indexFormat;
-
- /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage%dD(level=%d)", dimensions, level);
- }
- return GL_TRUE;
- }
-
- /* Check border */
- if (border < 0 || border > 1 ||
- ((target == GL_TEXTURE_RECTANGLE_NV ||
- target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage%dD(border=%d)", dimensions, border);
- }
- return GL_TRUE;
- }
-
- if (width < 0 || height < 0 || depth < 0) {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage%dD(width, height or depth < 0)", dimensions);
- }
- return GL_TRUE;
- }
-
- /* Do this simple check before calling the TestProxyTexImage() function */
- if (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
- sizeOK = (width == height);
- }
-
- /*
- * Use the proxy texture driver hook to see if the size/level/etc are
- * legal.
- */
- sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
- internalFormat, format,
- type, width, height,
- depth, border);
- if (!sizeOK) {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
- dimensions, level, width, height, depth);
- }
- return GL_TRUE;
- }
-
- /* Check internalFormat */
- if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage%dD(internalFormat=%s)",
- dimensions, _mesa_lookup_enum_by_nr(internalFormat));
- }
- return GL_TRUE;
- }
-
- /* Check incoming image format and type */
- if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
- /* Normally, GL_INVALID_OPERATION is generated by a format/type
- * mismatch (see the 1.2 spec page 94, sec 3.6.4.). But with the
- * GL_EXT_texture_integer extension, some combinations should generate
- * GL_INVALID_ENUM instead (grr!).
- */
- if (!isProxy) {
- GLenum error = _mesa_is_integer_format(format)
- ? GL_INVALID_ENUM : GL_INVALID_OPERATION;
- _mesa_error(ctx, error,
- "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
- dimensions, format, type);
- }
- return GL_TRUE;
- }
-
- /* make sure internal format and format basically agree */
- colorFormat = _mesa_is_color_format(format);
- indexFormat = _mesa_is_index_format(format);
- if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
- (_mesa_is_index_format(internalFormat) && !indexFormat) ||
- (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
- (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
- (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
- (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
- if (!isProxy)
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
- dimensions, internalFormat, format);
- return GL_TRUE;
- }
-
- /* additional checks for ycbcr textures */
- if (internalFormat == GL_YCBCR_MESA) {
- ASSERT(ctx->Extensions.MESA_ycbcr_texture);
- if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
- type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
- char message[100];
- _mesa_snprintf(message, sizeof(message),
- "glTexImage%dD(format/type YCBCR mismatch", dimensions);
- _mesa_error(ctx, GL_INVALID_ENUM, "%s", message);
- return GL_TRUE; /* error */
- }
- if (target != GL_TEXTURE_2D &&
- target != GL_PROXY_TEXTURE_2D &&
- target != GL_TEXTURE_RECTANGLE_NV &&
- target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
- if (!isProxy)
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
- return GL_TRUE;
- }
- if (border != 0) {
- if (!isProxy) {
- char message[100];
- _mesa_snprintf(message, sizeof(message),
- "glTexImage%dD(format=GL_YCBCR_MESA and border=%d)",
- dimensions, border);
- _mesa_error(ctx, GL_INVALID_VALUE, "%s", message);
- }
- return GL_TRUE;
- }
- }
-
- /* additional checks for depth textures */
- if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
- /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
- if (target != GL_TEXTURE_1D &&
- target != GL_PROXY_TEXTURE_1D &&
- target != GL_TEXTURE_2D &&
- target != GL_PROXY_TEXTURE_2D &&
- target != GL_TEXTURE_RECTANGLE_ARB &&
- target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
- if (!isProxy)
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexImage(target/internalFormat)");
- return GL_TRUE;
- }
- }
-
- /* additional checks for compressed textures */
- if (_mesa_is_compressed_format(ctx, internalFormat)) {
- if (!target_can_be_compressed(ctx, target, internalFormat)) {
- if (!isProxy)
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexImage%dD(target)", dimensions);
- return GL_TRUE;
- }
- if (border != 0) {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexImage%dD(border!=0)", dimensions);
- }
- return GL_TRUE;
- }
- }
-
- /* additional checks for integer textures */
- if (ctx->Extensions.EXT_texture_integer &&
- (_mesa_is_integer_format(format) !=
- _mesa_is_integer_format(internalFormat))) {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexImage%dD(integer/non-integer format mismatch)",
- dimensions);
- }
- return GL_TRUE;
- }
-
- /* if we get here, the parameters are OK */
- return GL_FALSE;
-}
-
-
-/**
- * Test glTexSubImage[123]D() parameters for errors.
- *
- * \param ctx GL context.
- * \param dimensions texture image dimensions (must be 1, 2 or 3).
- * \param target texture target given by the user.
- * \param level image level given by the user.
- * \param xoffset sub-image x offset given by the user.
- * \param yoffset sub-image y offset given by the user.
- * \param zoffset sub-image z offset given by the user.
- * \param format pixel data format given by the user.
- * \param type pixel data type given by the user.
- * \param width image width given by the user.
- * \param height image height given by the user.
- * \param depth image depth given by the user.
- *
- * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- *
- * Verifies each of the parameters against the constants specified in
- * __struct gl_contextRec::Const and the supported extensions, and according
- * to the OpenGL specification.
- */
-static GLboolean
-subtexture_error_check( struct gl_context *ctx, GLuint dimensions,
- GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLint width, GLint height, GLint depth,
- GLenum format, GLenum type )
-{
- /* Basic level check */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
- return GL_TRUE;
- }
-
- /* Check for negative sizes */
- if (width < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexSubImage%dD(width=%d)", dimensions, width);
- return GL_TRUE;
- }
- if (height < 0 && dimensions > 1) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexSubImage%dD(height=%d)", dimensions, height);
- return GL_TRUE;
- }
- if (depth < 0 && dimensions > 2) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexSubImage%dD(depth=%d)", dimensions, depth);
- return GL_TRUE;
- }
-
- if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
- /* As with the glTexImage2D check above, the error code here
- * depends on texture integer.
- */
- GLenum error = _mesa_is_integer_format(format)
- ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
- _mesa_error(ctx, error,
- "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
- dimensions, format, type);
- return GL_TRUE;
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Do second part of glTexSubImage which depends on the destination texture.
- * \return GL_TRUE if error recorded, GL_FALSE otherwise
- */
-static GLboolean
-subtexture_error_check2( struct gl_context *ctx, GLuint dimensions,
- GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLint width, GLint height, GLint depth,
- GLenum format, GLenum type,
- const struct gl_texture_image *destTex )
-{
- if (!destTex) {
- /* undefined image level */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
- return GL_TRUE;
- }
-
- if (xoffset < -((GLint)destTex->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
- dimensions);
- return GL_TRUE;
- }
- if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
- dimensions);
- return GL_TRUE;
- }
- if (dimensions > 1) {
- if (yoffset < -((GLint)destTex->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
- dimensions);
- return GL_TRUE;
- }
- if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
- dimensions);
- return GL_TRUE;
- }
- }
- if (dimensions > 2) {
- if (zoffset < -((GLint)destTex->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
- return GL_TRUE;
- }
- if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
- return GL_TRUE;
- }
- }
-
- if (_mesa_is_format_compressed(destTex->TexFormat)) {
- GLuint bw, bh;
-
- /* do tests which depend on compression block size */
- _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh);
-
- /* offset must be multiple of block size */
- if ((xoffset % bw != 0) || (yoffset % bh != 0)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexSubImage%dD(xoffset = %d, yoffset = %d)",
- dimensions, xoffset, yoffset);
- return GL_TRUE;
- }
- /* size must be multiple of bw by bh or equal to whole texture size */
- if ((width % bw != 0) && (GLuint) width != destTex->Width) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexSubImage%dD(width = %d)", dimensions, width);
- return GL_TRUE;
- }
- if ((height % bh != 0) && (GLuint) height != destTex->Height) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexSubImage%dD(height = %d)", dimensions, height);
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Test glCopyTexImage[12]D() parameters for errors.
- *
- * \param ctx GL context.
- * \param dimensions texture image dimensions (must be 1, 2 or 3).
- * \param target texture target given by the user.
- * \param level image level given by the user.
- * \param internalFormat internal format given by the user.
- * \param width image width given by the user.
- * \param height image height given by the user.
- * \param border texture border.
- *
- * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- *
- * Verifies each of the parameters against the constants specified in
- * __struct gl_contextRec::Const and the supported extensions, and according
- * to the OpenGL specification.
- */
-static GLboolean
-copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
- GLenum target, GLint level, GLint internalFormat,
- GLint width, GLint height, GLint border )
-{
- const GLenum proxyTarget = get_proxy_target(target);
- const GLenum type = GL_FLOAT;
- GLboolean sizeOK;
- GLint format;
-
- /* check target */
- if (!legal_texsubimage_target(ctx, dimensions, target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)",
- dimensions, _mesa_lookup_enum_by_nr(target));
- return GL_TRUE;
- }
-
- /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage%dD(level=%d)", dimensions, level);
- return GL_TRUE;
- }
-
- /* Check that the source buffer is complete */
- if (ctx->ReadBuffer->Name) {
- _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
- if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glCopyTexImage%dD(invalid readbuffer)", dimensions);
- return GL_TRUE;
- }
- }
-
- /* Check border */
- if (border < 0 || border > 1 ||
- ((target == GL_TEXTURE_RECTANGLE_NV ||
- target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
- return GL_TRUE;
- }
-
- format = _mesa_base_tex_format(ctx, internalFormat);
- if (format < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage%dD(internalFormat)", dimensions);
- return GL_TRUE;
- }
-
- if (!_mesa_source_buffer_exists(ctx, format)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexImage%dD(missing readbuffer)", dimensions);
- return GL_TRUE;
- }
-
- /* Do size, level checking */
- sizeOK = (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB)
- ? (width == height) : 1;
-
- sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
- internalFormat, format,
- type, width, height,
- 1, border);
-
- if (!sizeOK) {
- if (dimensions == 1) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage1D(width=%d)", width);
- }
- else {
- ASSERT(dimensions == 2);
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage2D(width=%d, height=%d)", width, height);
- }
- return GL_TRUE;
- }
-
- if (_mesa_is_compressed_format(ctx, internalFormat)) {
- if (!target_can_be_compressed(ctx, target, internalFormat)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTexImage%dD(target)", dimensions);
- return GL_TRUE;
- }
- if (border != 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexImage%dD(border!=0)", dimensions);
- return GL_TRUE;
- }
- }
- else if (_mesa_is_depth_format(internalFormat)) {
- /* make sure we have depth/stencil buffers */
- if (!ctx->ReadBuffer->_DepthBuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexImage%dD(no depth)", dimensions);
- return GL_TRUE;
- }
- }
- else if (_mesa_is_depthstencil_format(internalFormat)) {
- /* make sure we have depth/stencil buffers */
- if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexImage%dD(no depth/stencil buffer)", dimensions);
- return GL_TRUE;
- }
- }
-
- /* if we get here, the parameters are OK */
- return GL_FALSE;
-}
-
-
-/**
- * Test glCopyTexSubImage[12]D() parameters for errors.
- * Note that this is the first part of error checking.
- * See also copytexsubimage_error_check2() below for the second part.
- *
- * \param ctx GL context.
- * \param dimensions texture image dimensions (must be 1, 2 or 3).
- * \param target texture target given by the user.
- * \param level image level given by the user.
- *
- * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- */
-static GLboolean
-copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions,
- GLenum target, GLint level)
-{
- /* Check that the source buffer is complete */
- if (ctx->ReadBuffer->Name) {
- _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
- if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glCopyTexImage%dD(invalid readbuffer)", dimensions);
- return GL_TRUE;
- }
- }
-
- /* check target (proxies not allowed) */
- if (!legal_texsubimage_target(ctx, dimensions, target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexSubImage%uD(target=%s)",
- dimensions, _mesa_lookup_enum_by_nr(target));
- return GL_TRUE;
- }
-
- /* Check level */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(level=%d)", dimensions, level);
- return GL_TRUE;
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Second part of error checking for glCopyTexSubImage[12]D().
- * \param xoffset sub-image x offset given by the user.
- * \param yoffset sub-image y offset given by the user.
- * \param zoffset sub-image z offset given by the user.
- * \param width image width given by the user.
- * \param height image height given by the user.
- */
-static GLboolean
-copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions,
- GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height,
- const struct gl_texture_image *teximage )
-{
- /* check that dest tex image exists */
- if (!teximage) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexSubImage%dD(undefined texture level: %d)",
- dimensions, level);
- return GL_TRUE;
- }
-
- /* Check size */
- if (width < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(width=%d)", dimensions, width);
- return GL_TRUE;
- }
- if (dimensions > 1 && height < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(height=%d)", dimensions, height);
- return GL_TRUE;
- }
-
- /* check x/y offsets */
- if (xoffset < -((GLint)teximage->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
- return GL_TRUE;
- }
- if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(xoffset+width)", dimensions);
- return GL_TRUE;
- }
- if (dimensions > 1) {
- if (yoffset < -((GLint)teximage->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
- return GL_TRUE;
- }
- /* NOTE: we're adding the border here, not subtracting! */
- if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(yoffset+height)", dimensions);
- return GL_TRUE;
- }
- }
-
- /* check z offset */
- if (dimensions > 2) {
- if (zoffset < -((GLint)teximage->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(zoffset)", dimensions);
- return GL_TRUE;
- }
- if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
- return GL_TRUE;
- }
- }
-
- if (_mesa_is_format_compressed(teximage->TexFormat)) {
- /* offset must be multiple of 4 */
- if ((xoffset & 3) || (yoffset & 3)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions);
- return GL_TRUE;
- }
- /* size must be multiple of 4 */
- if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(width)", dimensions);
- return GL_TRUE;
- }
- if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexSubImage%dD(height)", dimensions);
- return GL_TRUE;
- }
- }
-
- if (teximage->InternalFormat == GL_YCBCR_MESA) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
- return GL_TRUE;
- }
-
- if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
- dimensions, teximage->_BaseFormat);
- return GL_TRUE;
- }
-
- if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
- if (!ctx->ReadBuffer->_DepthBuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexSubImage%dD(no depth buffer)",
- dimensions);
- return GL_TRUE;
- }
- }
- else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
- if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexSubImage%dD(no depth/stencil buffer)",
- dimensions);
- return GL_TRUE;
- }
- }
-
- /* If copying into an integer texture, the source buffer must also be
- * integer-valued.
- */
- if (_mesa_is_format_integer_color(teximage->TexFormat)) {
- struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
- if (!_mesa_is_format_integer_color(rb->Format)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexSubImage%dD(source buffer is not integer format)",
- dimensions);
- return GL_TRUE;
- }
- }
-
- /* if we get here, the parameters are OK */
- return GL_FALSE;
-}
-
-
-/** Callback info for walking over FBO hash table */
-struct cb_info
-{
- struct gl_context *ctx;
- struct gl_texture_object *texObj;
- GLuint level, face;
-};
-
-
-/**
- * Check render to texture callback. Called from _mesa_HashWalk().
- */
-static void
-check_rtt_cb(GLuint key, void *data, void *userData)
-{
- struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
- const struct cb_info *info = (struct cb_info *) userData;
- struct gl_context *ctx = info->ctx;
- const struct gl_texture_object *texObj = info->texObj;
- const GLuint level = info->level, face = info->face;
-
- /* If this is a user-created FBO */
- if (fb->Name) {
- GLuint i;
- /* check if any of the FBO's attachments point to 'texObj' */
- for (i = 0; i < BUFFER_COUNT; i++) {
- struct gl_renderbuffer_attachment *att = fb->Attachment + i;
- if (att->Type == GL_TEXTURE &&
- att->Texture == texObj &&
- att->TextureLevel == level &&
- att->CubeMapFace == face) {
- ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
- /* Tell driver about the new renderbuffer texture */
- ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
- /* Mark fb status as indeterminate to force re-validation */
- fb->_Status = 0;
- }
- }
- }
-}
-
-
-/**
- * When a texture image is specified we have to check if it's bound to
- * any framebuffer objects (render to texture) in order to detect changes
- * in size or format since that effects FBO completeness.
- * Any FBOs rendering into the texture must be re-validated.
- */
-static void
-update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj,
- GLuint face, GLuint level)
-{
- /* Only check this texture if it's been marked as RenderToTexture */
- if (texObj->_RenderToTexture) {
- struct cb_info info;
- info.ctx = ctx;
- info.texObj = texObj;
- info.level = level;
- info.face = face;
- _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
- }
-}
-
-
-/**
- * If the texture object's GenerateMipmap flag is set and we've
- * changed the texture base level image, regenerate the rest of the
- * mipmap levels now.
- */
-static INLINE void
-check_gen_mipmap(struct gl_context *ctx, GLenum target,
- struct gl_texture_object *texObj, GLint level)
-{
- ASSERT(target != GL_TEXTURE_CUBE_MAP);
- if (texObj->GenerateMipmap &&
- level == texObj->BaseLevel &&
- level < texObj->MaxLevel) {
- ASSERT(ctx->Driver.GenerateMipmap);
- ctx->Driver.GenerateMipmap(ctx, target, texObj);
- }
-}
-
-
-/** Debug helper: override the user-requested internal format */
-static GLenum
-override_internal_format(GLenum internalFormat, GLint width, GLint height)
-{
-#if 0
- if (internalFormat == GL_RGBA16F_ARB ||
- internalFormat == GL_RGBA32F_ARB) {
- printf("Convert rgba float tex to int %d x %d\n", width, height);
- return GL_RGBA;
- }
- else if (internalFormat == GL_RGB16F_ARB ||
- internalFormat == GL_RGB32F_ARB) {
- printf("Convert rgb float tex to int %d x %d\n", width, height);
- return GL_RGB;
- }
- else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
- internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
- printf("Convert luminance float tex to int %d x %d\n", width, height);
- return GL_LUMINANCE_ALPHA;
- }
- else if (internalFormat == GL_LUMINANCE16F_ARB ||
- internalFormat == GL_LUMINANCE32F_ARB) {
- printf("Convert luminance float tex to int %d x %d\n", width, height);
- return GL_LUMINANCE;
- }
- else if (internalFormat == GL_ALPHA16F_ARB ||
- internalFormat == GL_ALPHA32F_ARB) {
- printf("Convert luminance float tex to int %d x %d\n", width, height);
- return GL_ALPHA;
- }
- /*
- else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
- internalFormat = GL_RGBA;
- }
- */
- else {
- return internalFormat;
- }
-#else
- return internalFormat;
-#endif
-}
-
-
-/**
- * Choose the actual hardware format for a texture image.
- * Try to use the same format as the previous image level when possible.
- * Otherwise, ask the driver for the best format.
- * It's important to try to choose a consistant format for all levels
- * for efficient texture memory layout/allocation. In particular, this
- * comes up during automatic mipmap generation.
- */
-gl_format
-_mesa_choose_texture_format(struct gl_context *ctx,
- struct gl_texture_object *texObj,
- GLenum target, GLint level,
- GLenum internalFormat, GLenum format, GLenum type)
-{
- gl_format f;
-
- /* see if we've already chosen a format for the previous level */
- if (level > 0) {
- struct gl_texture_image *prevImage =
- _mesa_select_tex_image(ctx, texObj, target, level - 1);
- /* See if the prev level is defined and has an internal format which
- * matches the new internal format.
- */
- if (prevImage &&
- prevImage->Width > 0 &&
- prevImage->InternalFormat == internalFormat) {
- /* use the same format */
- ASSERT(prevImage->TexFormat != MESA_FORMAT_NONE);
- return prevImage->TexFormat;
- }
- }
-
- /* choose format from scratch */
- f = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
- ASSERT(f != MESA_FORMAT_NONE);
- return f;
-}
-
-
-/**
- * Common code to implement all the glTexImage1D/2D/3D functions.
- */
-static void
-teximage(struct gl_context *ctx, GLuint dims,
- GLenum target, GLint level, GLint internalFormat,
- GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLenum format, GLenum type,
- const GLvoid *pixels)
-{
- GLboolean error;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n",
- dims,
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height, depth, border,
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type), pixels);
-
- internalFormat = override_internal_format(internalFormat, width, height);
-
- /* target error checking */
- if (!legal_teximage_target(ctx, dims, target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)",
- dims, _mesa_lookup_enum_by_nr(target));
- return;
- }
-
- /* general error checking */
- error = texture_error_check(ctx, dims, target, level, internalFormat,
- format, type, width, height, depth, border);
-
- if (_mesa_is_proxy_texture(target)) {
- /* Proxy texture: just clear or set state depending on error checking */
- struct gl_texture_image *texImage =
- _mesa_get_proxy_tex_image(ctx, target, level);
-
- if (error) {
- /* when error, clear all proxy texture image parameters */
- if (texImage)
- clear_teximage_fields(texImage);
- }
- else {
- /* no error, set the tex image parameters */
- struct gl_texture_object *texObj =
- _mesa_get_current_tex_object(ctx, target);
- gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
- target, level,
- internalFormat,
- format, type);
-
- if (legal_texture_size(ctx, texFormat, width, height, depth)) {
- _mesa_init_teximage_fields(ctx, target, texImage, width, height,
- depth, border, internalFormat,
- texFormat);
- }
- else if (texImage) {
- clear_teximage_fields(texImage);
- }
- }
- }
- else {
- /* non-proxy target */
- const GLuint face = _mesa_tex_target_to_face(target);
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
-
- if (error) {
- return; /* error was recorded */
- }
-
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
- _mesa_update_state(ctx);
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
-
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
-
- ASSERT(texImage->Data == NULL);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, format,
- type);
-
- if (legal_texture_size(ctx, texFormat, width, height, depth)) {
- _mesa_init_teximage_fields(ctx, target, texImage,
- width, height, depth,
- border, internalFormat, texFormat);
-
- /* Give the texture to the driver. <pixels> may be null. */
- ASSERT(ctx->Driver.TexImage3D);
- switch (dims) {
- case 1:
- ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
- width, border, format,
- type, pixels, &ctx->Unpack, texObj,
- texImage);
- break;
- case 2:
- ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
- width, height, border, format,
- type, pixels, &ctx->Unpack, texObj,
- texImage);
- break;
- case 3:
- ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
- width, height, depth, border, format,
- type, pixels, &ctx->Unpack, texObj,
- texImage);
- break;
- default:
- _mesa_problem(ctx, "invalid dims=%u in teximage()", dims);
- }
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- update_fbo_texture(ctx, texObj, face, level);
-
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
- }
- }
- }
- _mesa_unlock_texture(ctx, texObj);
- }
-}
-
-
-/*
- * Called from the API. Note that width includes the border.
- */
-void GLAPIENTRY
-_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
- GLsizei width, GLint border, GLenum format,
- GLenum type, const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- teximage(ctx, 1, target, level, internalFormat, width, 1, 1,
- border, format, type, pixels);
-}
-
-
-void GLAPIENTRY
-_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
- GLsizei width, GLsizei height, GLint border,
- GLenum format, GLenum type,
- const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- teximage(ctx, 2, target, level, internalFormat, width, height, 1,
- border, format, type, pixels);
-}
-
-
-/*
- * Called by the API or display list executor.
- * Note that width and height include the border.
- */
-void GLAPIENTRY
-_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
- GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLenum format, GLenum type,
- const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- teximage(ctx, 3, target, level, internalFormat, width, height, depth,
- border, format, type, pixels);
-}
-
-
-void GLAPIENTRY
-_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
- GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLenum format, GLenum type,
- const GLvoid *pixels )
-{
- _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
- depth, border, format, type, pixels);
-}
-
-
-#if FEATURE_OES_EGL_image
-void GLAPIENTRY
-_mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (!ctx->Extensions.OES_EGL_image) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glEGLImageTargetTexture2DOES(unsupported)");
- return;
- }
-
- if (target != GL_TEXTURE_2D) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glEGLImageTargetTexture2D(target=%d)", target);
- return;
- }
-
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
- _mesa_update_state(ctx);
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- _mesa_lock_texture(ctx, texObj);
-
- texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D");
- } else {
- if (texImage->Data)
- ctx->Driver.FreeTexImageData( ctx, texImage );
-
- ASSERT(texImage->Data == NULL);
- ctx->Driver.EGLImageTargetTexture2D(ctx, target,
- texObj, texImage, image);
-
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- _mesa_unlock_texture(ctx, texObj);
-
-}
-#endif
-
-
-
-/**
- * Implement all the glTexSubImage1/2/3D() functions.
- */
-static void
-texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *pixels )
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n",
- dims,
- _mesa_lookup_enum_by_nr(target), level,
- xoffset, yoffset, zoffset, width, height, depth,
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type), pixels);
-
- /* check target (proxies not allowed) */
- if (!legal_texsubimage_target(ctx, dims, target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
- dims, _mesa_lookup_enum_by_nr(target));
- return;
- }
-
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
- _mesa_update_state(ctx);
-
- if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset,
- width, height, depth, format, type)) {
- return; /* error was detected */
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (subtexture_error_check2(ctx, dims, target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, texImage)) {
- /* error was recorded */
- }
- else if (width > 0 && height > 0 && height > 0) {
- /* If we have a border, offset=-1 is legal. Bias by border width. */
- switch (dims) {
- case 3:
- zoffset += texImage->Border;
- /* fall-through */
- case 2:
- yoffset += texImage->Border;
- /* fall-through */
- case 1:
- xoffset += texImage->Border;
- }
-
- switch (dims) {
- case 1:
- ctx->Driver.TexSubImage1D(ctx, target, level,
- xoffset, width,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage );
- break;
- case 2:
- ctx->Driver.TexSubImage2D(ctx, target, level,
- xoffset, yoffset, width, height,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage );
- break;
- case 3:
- ctx->Driver.TexSubImage3D(ctx, target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage );
- break;
- default:
- _mesa_problem(ctx, "unexpected dims in subteximage()");
- }
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
-}
-
-
-void GLAPIENTRY
-_mesa_TexSubImage1D( GLenum target, GLint level,
- GLint xoffset, GLsizei width,
- GLenum format, GLenum type,
- const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- texsubimage(ctx, 1, target, level,
- xoffset, 0, 0,
- width, 1, 1,
- format, type, pixels);
-}
-
-
-void GLAPIENTRY
-_mesa_TexSubImage2D( GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- texsubimage(ctx, 2, target, level,
- xoffset, yoffset, 0,
- width, height, 1,
- format, type, pixels);
-}
-
-
-
-void GLAPIENTRY
-_mesa_TexSubImage3D( GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- texsubimage(ctx, 3, target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, pixels);
-}
-
-
-
-/**
- * Implement the glCopyTexImage1/2D() functions.
- */
-static void
-copyteximage(struct gl_context *ctx, GLuint dims,
- GLenum target, GLint level, GLenum internalFormat,
- GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- const GLuint face = _mesa_tex_target_to_face(target);
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n",
- dims,
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat),
- x, y, width, height, border);
-
- if (ctx->NewState & NEW_COPY_TEX_STATE)
- _mesa_update_state(ctx);
-
- if (copytexture_error_check(ctx, dims, target, level, internalFormat,
- width, height, border))
- return;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
-
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
-
- ASSERT(texImage->Data == NULL);
-
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
-
- if (legal_texture_size(ctx, texFormat, width, height, 1)) {
- _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
- border, internalFormat, texFormat);
-
- ASSERT(ctx->Driver.CopyTexImage2D);
- if (dims == 1)
- ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
- x, y, width, border);
- else
- ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
- x, y, width, height, border);
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- update_fbo_texture(ctx, texObj, face, level);
-
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
- }
- }
- }
- _mesa_unlock_texture(ctx, texObj);
-}
-
-
-
-void GLAPIENTRY
-_mesa_CopyTexImage1D( GLenum target, GLint level,
- GLenum internalFormat,
- GLint x, GLint y,
- GLsizei width, GLint border )
-{
- GET_CURRENT_CONTEXT(ctx);
- copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border);
-}
-
-
-
-void GLAPIENTRY
-_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLint border )
-{
- GET_CURRENT_CONTEXT(ctx);
- copyteximage(ctx, 2, target, level, internalFormat,
- x, y, width, height, border);
-}
-
-
-
-/**
- * Implementation for glCopyTexSubImage1/2/3D() functions.
- */
-static void
-copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y, GLsizei width, GLsizei height)
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTexSubImage%uD %s %d %d %d %d %d %d %d %d\n",
- dims,
- _mesa_lookup_enum_by_nr(target),
- level, xoffset, yoffset, zoffset, x, y, width, height);
-
- if (ctx->NewState & NEW_COPY_TEX_STATE)
- _mesa_update_state(ctx);
-
- if (copytexsubimage_error_check1(ctx, dims, target, level))
- return;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset,
- zoffset, width, height, texImage)) {
- /* error was recored */
- }
- else {
- /* If we have a border, offset=-1 is legal. Bias by border width. */
- switch (dims) {
- case 3:
- zoffset += texImage->Border;
- /* fall-through */
- case 2:
- yoffset += texImage->Border;
- /* fall-through */
- case 1:
- xoffset += texImage->Border;
- }
-
- if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
- &width, &height)) {
- switch (dims) {
- case 1:
- ctx->Driver.CopyTexSubImage1D(ctx, target, level,
- xoffset, x, y, width);
- break;
- case 2:
- ctx->Driver.CopyTexSubImage2D(ctx, target, level,
- xoffset, yoffset,
- x, y, width, height);
- break;
- case 3:
- ctx->Driver.CopyTexSubImage3D(ctx, target, level,
- xoffset, yoffset, zoffset,
- x, y, width, height);
- break;
- default:
- _mesa_problem(ctx, "bad dims in copytexsubimage()");
- }
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- }
- _mesa_unlock_texture(ctx, texObj);
-}
-
-
-void GLAPIENTRY
-_mesa_CopyTexSubImage1D( GLenum target, GLint level,
- GLint xoffset, GLint x, GLint y, GLsizei width )
-{
- GET_CURRENT_CONTEXT(ctx);
- copytexsubimage(ctx, 1, target, level, xoffset, 0, 0, x, y, width, 1);
-}
-
-
-
-void GLAPIENTRY
-_mesa_CopyTexSubImage2D( GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLint x, GLint y, GLsizei width, GLsizei height )
-{
- GET_CURRENT_CONTEXT(ctx);
- copytexsubimage(ctx, 2, target, level, xoffset, yoffset, 0, x, y,
- width, height);
-}
-
-
-
-void GLAPIENTRY
-_mesa_CopyTexSubImage3D( GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y, GLsizei width, GLsizei height )
-{
- GET_CURRENT_CONTEXT(ctx);
- copytexsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
- x, y, width, height);
-}
-
-
-
-
-/**********************************************************************/
-/****** Compressed Textures ******/
-/**********************************************************************/
-
-
-/**
- * Return expected size of a compressed texture.
- */
-static GLuint
-compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
- GLenum glformat)
-{
- gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
- return _mesa_format_image_size(mesaFormat, width, height, depth);
-}
-
-
-/*
- * Return compressed texture block size, in pixels.
- */
-static void
-get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
-{
- gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
- _mesa_get_format_block_size(mesaFormat, bw, bh);
-}
-
-
-/**
- * Error checking for glCompressedTexImage[123]D().
- * \return error code or GL_NO_ERROR.
- */
-static GLenum
-compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
- GLenum target, GLint level,
- GLenum internalFormat, GLsizei width,
- GLsizei height, GLsizei depth, GLint border,
- GLsizei imageSize)
-{
- const GLenum proxyTarget = get_proxy_target(target);
- const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
- GLint expectedSize;
-
- /* check level */
- if (level < 0 || level >= maxLevels)
- return GL_INVALID_VALUE;
-
- if (!target_can_be_compressed(ctx, target, internalFormat)) {
- return GL_INVALID_ENUM;
- }
-
- /* This will detect any invalid internalFormat value */
- if (!_mesa_is_compressed_format(ctx, internalFormat))
- return GL_INVALID_ENUM;
-
- /* This should really never fail */
- if (_mesa_base_tex_format(ctx, internalFormat) < 0)
- return GL_INVALID_ENUM;
-
- /* No compressed formats support borders at this time */
- if (border != 0)
- return GL_INVALID_VALUE;
-
- /* For cube map, width must equal height */
- if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
- return GL_INVALID_VALUE;
-
- /* check image size against compression block size */
- {
- gl_format texFormat =
- ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
- GL_NONE, GL_NONE);
- GLuint bw, bh;
-
- _mesa_get_format_block_size(texFormat, &bw, &bh);
- if ((width > bw && width % bw > 0) ||
- (height > bh && height % bh > 0)) {
- /*
- * Per GL_ARB_texture_compression: GL_INVALID_OPERATION is
- * generated [...] if any parameter combinations are not
- * supported by the specific compressed internal format.
- */
- return GL_INVALID_OPERATION;
- }
- }
-
- /* check image sizes */
- if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
- internalFormat, GL_NONE, GL_NONE,
- width, height, depth, border)) {
- /* See error comment above */
- return GL_INVALID_OPERATION;
- }
-
- /* check image size in bytes */
- expectedSize = compressed_tex_size(width, height, depth, internalFormat);
- if (expectedSize != imageSize) {
- /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...]
- * if <imageSize> is not consistent with the format, dimensions, and
- * contents of the specified image.
- */
- return GL_INVALID_VALUE;
- }
-
- return GL_NO_ERROR;
-}
-
-
-/**
- * Error checking for glCompressedTexSubImage[123]D().
- * \warning There are some bad assumptions here about the size of compressed
- * texture tiles (multiple of 4) used to test the validity of the
- * offset and size parameters.
- * \return error code or GL_NO_ERROR.
- */
-static GLenum
-compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions,
- GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLsizei imageSize)
-{
- GLint expectedSize, maxLevels = 0, maxTextureSize;
- GLuint bw, bh;
- (void) zoffset;
-
- if (dimensions == 1) {
- /* 1D compressed textures not allowed */
- return GL_INVALID_ENUM;
- }
- else if (dimensions == 2) {
- if (target == GL_PROXY_TEXTURE_2D) {
- maxLevels = ctx->Const.MaxTextureLevels;
- }
- else if (target == GL_TEXTURE_2D) {
- maxLevels = ctx->Const.MaxTextureLevels;
- }
- else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
- if (!ctx->Extensions.ARB_texture_cube_map)
- return GL_INVALID_ENUM; /*target*/
- maxLevels = ctx->Const.MaxCubeTextureLevels;
- }
- else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
- if (!ctx->Extensions.ARB_texture_cube_map)
- return GL_INVALID_ENUM; /*target*/
- maxLevels = ctx->Const.MaxCubeTextureLevels;
- }
- else {
- return GL_INVALID_ENUM; /*target*/
- }
- }
- else if (dimensions == 3) {
- /* 3D compressed textures not allowed */
- return GL_INVALID_ENUM;
- }
-
- maxTextureSize = 1 << (maxLevels - 1);
-
- /* this will catch any invalid compressed format token */
- if (!_mesa_is_compressed_format(ctx, format))
- return GL_INVALID_ENUM;
-
- if (width < 1 || width > maxTextureSize)
- return GL_INVALID_VALUE;
-
- if ((height < 1 || height > maxTextureSize)
- && dimensions > 1)
- return GL_INVALID_VALUE;
-
- if (level < 0 || level >= maxLevels)
- return GL_INVALID_VALUE;
-
- /*
- * do checks which depend on compression block size
- */
- get_compressed_block_size(format, &bw, &bh);
-
- if ((xoffset % bw != 0) || (yoffset % bh != 0))
- return GL_INVALID_VALUE;
-
- if ((width % bw != 0) && width != 2 && width != 1)
- return GL_INVALID_VALUE;
-
- if ((height % bh != 0) && height != 2 && height != 1)
- return GL_INVALID_VALUE;
-
- expectedSize = compressed_tex_size(width, height, depth, format);
- if (expectedSize != imageSize)
- return GL_INVALID_VALUE;
-
- return GL_NO_ERROR;
-}
-
-
-/**
- * Do second part of glCompressedTexSubImage error checking.
- * \return GL_TRUE if error found, GL_FALSE otherwise.
- */
-static GLboolean
-compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims,
- GLsizei width, GLsizei height,
- GLsizei depth, GLenum format,
- struct gl_texture_image *texImage)
-{
-
- if ((GLint) format != texImage->InternalFormat) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glCompressedTexSubImage%uD(format=0x%x)", dims, format);
- return GL_TRUE;
- }
-
- if (((width == 1 || width == 2) &&
- width != (GLsizei) texImage->Width) ||
- (width > (GLsizei) texImage->Width)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCompressedTexSubImage%uD(width=%d)", dims, width);
- return GL_TRUE;
- }
-
- if (dims >= 2) {
- if (((height == 1 || height == 2) &&
- height != (GLsizei) texImage->Height) ||
- (height > (GLsizei) texImage->Height)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCompressedTexSubImage%uD(height=%d)", dims, height);
- return GL_TRUE;
- }
- }
-
- if (dims >= 3) {
- if (((depth == 1 || depth == 2) &&
- depth != (GLsizei) texImage->Depth) ||
- (depth > (GLsizei) texImage->Depth)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCompressedTexSubImage%uD(depth=%d)", dims, depth);
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Implementation of the glCompressedTexImage1/2/3D() functions.
- */
-static void
-compressedteximage(struct gl_context *ctx, GLuint dims,
- GLenum target, GLint level,
- GLenum internalFormat, GLsizei width,
- GLsizei height, GLsizei depth, GLint border,
- GLsizei imageSize, const GLvoid *data)
-{
- GLenum error;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx,
- "glCompressedTexImage%uDARB %s %d %s %d %d %d %d %d %p\n",
- dims,
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height, depth, border, imageSize, data);
-
- /* check target */
- if (!legal_teximage_target(ctx, dims, target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target=%s)",
- dims, _mesa_lookup_enum_by_nr(target));
- return;
- }
-
- error = compressed_texture_error_check(ctx, dims, target, level,
- internalFormat, width, height, depth,
- border, imageSize);
-
-#if FEATURE_ES
- /* XXX this is kind of a hack */
- if (error) {
- _mesa_error(ctx, error, "glTexImage2D");
- return;
- }
-
- if (dims == 2) {
- switch (internalFormat) {
- case GL_PALETTE4_RGB8_OES:
- case GL_PALETTE4_RGBA8_OES:
- case GL_PALETTE4_R5_G6_B5_OES:
- case GL_PALETTE4_RGBA4_OES:
- case GL_PALETTE4_RGB5_A1_OES:
- case GL_PALETTE8_RGB8_OES:
- case GL_PALETTE8_RGBA8_OES:
- case GL_PALETTE8_R5_G6_B5_OES:
- case GL_PALETTE8_RGBA4_OES:
- case GL_PALETTE8_RGB5_A1_OES:
- _mesa_cpal_compressed_teximage2d(target, level, internalFormat,
- width, height, imageSize, data);
- return;
- }
- }
-#endif
-
- if (_mesa_is_proxy_texture(target)) {
- /* Proxy texture: just check for errors and update proxy state */
- struct gl_texture_image *texImage;
-
- if (!error) {
- struct gl_texture_object *texObj =
- _mesa_get_current_tex_object(ctx, target);
- gl_format texFormat =
- _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE, GL_NONE);
- if (!legal_texture_size(ctx, texFormat, width, height, depth)) {
- error = GL_OUT_OF_MEMORY;
- }
- }
-
- texImage = _mesa_get_proxy_tex_image(ctx, target, level);
- if (texImage) {
- if (error) {
- /* if error, clear all proxy texture image parameters */
- clear_teximage_fields(texImage);
- }
- else {
- /* no error: store the teximage parameters */
- _mesa_init_teximage_fields(ctx, target, texImage, width, height,
- depth, border, internalFormat,
- MESA_FORMAT_NONE);
- }
- }
- }
- else {
- /* non-proxy target */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
-
- if (error) {
- _mesa_error(ctx, error, "glCompressedTexImage%uD", dims);
- return;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glCompressedTexImage%uD", dims);
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
- ASSERT(texImage->Data == NULL);
-
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
-
- if (legal_texture_size(ctx, texFormat, width, height, depth)) {
- _mesa_init_teximage_fields(ctx, target, texImage,
- width, height, depth,
- border, internalFormat, texFormat);
-
- switch (dims) {
- case 1:
- ASSERT(ctx->Driver.CompressedTexImage1D);
- ctx->Driver.CompressedTexImage1D(ctx, target, level,
- internalFormat,
- width,
- border, imageSize, data,
- texObj, texImage);
- break;
- case 2:
- ASSERT(ctx->Driver.CompressedTexImage2D);
- ctx->Driver.CompressedTexImage2D(ctx, target, level,
- internalFormat,
- width, height,
- border, imageSize, data,
- texObj, texImage);
- break;
- case 3:
- ASSERT(ctx->Driver.CompressedTexImage3D);
- ctx->Driver.CompressedTexImage3D(ctx, target, level,
- internalFormat,
- width, height, depth,
- border, imageSize, data,
- texObj, texImage);
- break;
- default:
- _mesa_problem(ctx, "bad dims in compressedteximage");
- }
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glCompressedTexImage%uD", dims);
- }
- }
- }
- _mesa_unlock_texture(ctx, texObj);
- }
-}
-
-
-void GLAPIENTRY
-_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
- GLenum internalFormat, GLsizei width,
- GLint border, GLsizei imageSize,
- const GLvoid *data)
-{
- GET_CURRENT_CONTEXT(ctx);
- compressedteximage(ctx, 1, target, level, internalFormat,
- width, 1, 1, border, imageSize, data);
-}
-
-
-void GLAPIENTRY
-_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
- GLenum internalFormat, GLsizei width,
- GLsizei height, GLint border, GLsizei imageSize,
- const GLvoid *data)
-{
- GET_CURRENT_CONTEXT(ctx);
- compressedteximage(ctx, 2, target, level, internalFormat,
- width, height, 1, border, imageSize, data);
-}
-
-
-void GLAPIENTRY
-_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
- GLenum internalFormat, GLsizei width,
- GLsizei height, GLsizei depth, GLint border,
- GLsizei imageSize, const GLvoid *data)
-{
- GET_CURRENT_CONTEXT(ctx);
- compressedteximage(ctx, 3, target, level, internalFormat,
- width, height, depth, border, imageSize, data);
-}
-
-
-/**
- * Common helper for glCompressedTexSubImage1/2/3D().
- */
-static void
-compressed_tex_sub_image(GLuint dims, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLsizei imageSize, const GLvoid *data)
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GLenum error;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- error = compressed_subtexture_error_check(ctx, dims, target, level,
- xoffset, 0, 0, /* pos */
- width, height, depth, /* size */
- format, imageSize);
- if (error) {
- _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims);
- return;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- assert(texImage);
-
- if (compressed_subtexture_error_check2(ctx, dims, width, height, depth,
- format, texImage)) {
- /* error was recorded */
- }
- else if (width > 0 && height > 0 && depth > 0) {
- switch (dims) {
- case 1:
- if (ctx->Driver.CompressedTexSubImage1D) {
- ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
- xoffset, width,
- format, imageSize, data,
- texObj, texImage);
- }
- break;
- case 2:
- if (ctx->Driver.CompressedTexSubImage2D) {
- ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
- xoffset, yoffset,
- width, height,
- format, imageSize, data,
- texObj, texImage);
- }
- break;
- case 3:
- if (ctx->Driver.CompressedTexSubImage3D) {
- ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, imageSize, data,
- texObj, texImage);
- }
- break;
- default:
- ;
- }
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
-}
-
-
-void GLAPIENTRY
-_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
- GLsizei width, GLenum format,
- GLsizei imageSize, const GLvoid *data)
-{
- compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1,
- format, imageSize, data);
-}
-
-
-void GLAPIENTRY
-_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
- GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLsizei imageSize,
- const GLvoid *data)
-{
- compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0,
- width, height, 1, format, imageSize, data);
-}
-
-
-void GLAPIENTRY
-_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
- GLint yoffset, GLint zoffset, GLsizei width,
- GLsizei height, GLsizei depth, GLenum format,
- GLsizei imageSize, const GLvoid *data)
-{
- compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset,
- width, height, depth, format, imageSize, data);
-}
+/*
+ * mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. 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 teximage.c
+ * Texture image-related functions.
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "enums.h"
+#include "fbobject.h"
+#include "framebuffer.h"
+#include "hash.h"
+#include "image.h"
+#include "imports.h"
+#include "macros.h"
+#include "mfeatures.h"
+#include "state.h"
+#include "texcompress.h"
+#include "texfetch.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "texpal.h"
+#include "mtypes.h"
+
+
+/**
+ * State changes which we care about for glCopyTex[Sub]Image() calls.
+ * In particular, we care about pixel transfer state and buffer state
+ * (such as glReadBuffer to make sure we read from the right renderbuffer).
+ */
+#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
+ _NEW_BUFFERS | \
+ _NEW_PIXEL)
+
+
+
+/**
+ * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
+ * elsewhere.
+ */
+void *
+_mesa_alloc_texmemory(GLsizei bytes)
+{
+ return _mesa_align_malloc(bytes, 512);
+}
+
+
+/**
+ * Free texture memory allocated with _mesa_alloc_texmemory()
+ */
+void
+_mesa_free_texmemory(void *m)
+{
+ _mesa_align_free(m);
+}
+
+
+/*
+ * Compute floor(log_base_2(n)).
+ * If n < 0 return -1.
+ */
+static int
+logbase2( int n )
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ if (n < 0)
+ return -1;
+
+ if (n == 0)
+ return 0;
+
+ while ( n > i ) {
+ i *= 2;
+ log2++;
+ }
+ if (i != n) {
+ return log2 - 1;
+ }
+ else {
+ return log2;
+ }
+}
+
+
+
+/**
+ * Return the simple base format for a given internal texture format.
+ * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
+ *
+ * \param ctx GL context.
+ * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
+ *
+ * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
+ * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
+ *
+ * This is the format which is used during texture application (i.e. the
+ * texture format and env mode determine the arithmetic used.
+ *
+ * XXX this could be static
+ */
+GLint
+_mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
+{
+ switch (internalFormat) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return GL_ALPHA;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return GL_LUMINANCE;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return GL_LUMINANCE_ALPHA;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return GL_INTENSITY;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return GL_RGB;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.EXT_texture_format_BGRA8888) {
+ switch (internalFormat) {
+ case GL_BGRA_EXT:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_paletted_texture) {
+ switch (internalFormat) {
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return GL_COLOR_INDEX;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ARB_depth_texture) {
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return GL_DEPTH_COMPONENT;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ switch (internalFormat) {
+ case GL_COMPRESSED_ALPHA:
+ return GL_ALPHA;
+ case GL_COMPRESSED_LUMINANCE:
+ return GL_LUMINANCE;
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ return GL_LUMINANCE_ALPHA;
+ case GL_COMPRESSED_INTENSITY:
+ return GL_INTENSITY;
+ case GL_COMPRESSED_RGB:
+ return GL_RGB;
+ case GL_COMPRESSED_RGBA:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ return GL_RGB;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_texture_compression_s3tc) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return GL_RGB;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.S3_s3tc) {
+ switch (internalFormat) {
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ return GL_RGB;
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_ycbcr_texture) {
+ if (internalFormat == GL_YCBCR_MESA)
+ return GL_YCBCR_MESA;
+ }
+
+ if (ctx->Extensions.ARB_texture_float) {
+ switch (internalFormat) {
+ case GL_ALPHA16F_ARB:
+ case GL_ALPHA32F_ARB:
+ return GL_ALPHA;
+ case GL_RGBA16F_ARB:
+ case GL_RGBA32F_ARB:
+ return GL_RGBA;
+ case GL_RGB16F_ARB:
+ case GL_RGB32F_ARB:
+ return GL_RGB;
+ case GL_INTENSITY16F_ARB:
+ case GL_INTENSITY32F_ARB:
+ return GL_INTENSITY;
+ case GL_LUMINANCE16F_ARB:
+ case GL_LUMINANCE32F_ARB:
+ return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ return GL_LUMINANCE_ALPHA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ switch (internalFormat) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return GL_DUDV_ATI;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_texture_signed_rgba) {
+ switch (internalFormat) {
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_packed_depth_stencil) {
+ switch (internalFormat) {
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return GL_DEPTH_STENCIL_EXT;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+#if FEATURE_EXT_texture_sRGB
+ if (ctx->Extensions.EXT_texture_sRGB) {
+ switch (internalFormat) {
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return GL_RGB;
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return GL_RGBA;
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+ return GL_LUMINANCE_ALPHA;
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ return GL_LUMINANCE;
+ default:
+ ; /* fallthrough */
+ }
+ }
+#endif /* FEATURE_EXT_texture_sRGB */
+
+ if (ctx->Extensions.EXT_texture_integer) {
+ switch (internalFormat) {
+ case GL_RGBA8UI_EXT:
+ case GL_RGBA16UI_EXT:
+ case GL_RGBA32UI_EXT:
+ case GL_RGBA8I_EXT:
+ case GL_RGBA16I_EXT:
+ case GL_RGBA32I_EXT:
+ return GL_RGBA;
+ case GL_RGB8UI_EXT:
+ case GL_RGB16UI_EXT:
+ case GL_RGB32UI_EXT:
+ case GL_RGB8I_EXT:
+ case GL_RGB16I_EXT:
+ case GL_RGB32I_EXT:
+ return GL_RGB;
+ case GL_ALPHA8UI_EXT:
+ case GL_ALPHA16UI_EXT:
+ case GL_ALPHA32UI_EXT:
+ case GL_ALPHA8I_EXT:
+ case GL_ALPHA16I_EXT:
+ case GL_ALPHA32I_EXT:
+ return GL_ALPHA;
+ case GL_INTENSITY8UI_EXT:
+ case GL_INTENSITY16UI_EXT:
+ case GL_INTENSITY32UI_EXT:
+ case GL_INTENSITY8I_EXT:
+ case GL_INTENSITY16I_EXT:
+ case GL_INTENSITY32I_EXT:
+ return GL_INTENSITY;
+ case GL_LUMINANCE8UI_EXT:
+ case GL_LUMINANCE16UI_EXT:
+ case GL_LUMINANCE32UI_EXT:
+ case GL_LUMINANCE8I_EXT:
+ case GL_LUMINANCE16I_EXT:
+ case GL_LUMINANCE32I_EXT:
+ return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA8UI_EXT:
+ case GL_LUMINANCE_ALPHA16UI_EXT:
+ case GL_LUMINANCE_ALPHA32UI_EXT:
+ case GL_LUMINANCE_ALPHA8I_EXT:
+ case GL_LUMINANCE_ALPHA16I_EXT:
+ case GL_LUMINANCE_ALPHA32I_EXT:
+ return GL_LUMINANCE_ALPHA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ARB_texture_rg) {
+ switch (internalFormat) {
+ case GL_R16F:
+ /* R16F depends on both ARB_half_float_pixel and ARB_texture_float.
+ */
+ if (!ctx->Extensions.ARB_half_float_pixel)
+ break;
+ /* FALLTHROUGH */
+ case GL_R32F:
+ if (!ctx->Extensions.ARB_texture_float)
+ break;
+ return GL_RED;
+ case GL_R8I:
+ case GL_R8UI:
+ case GL_R16I:
+ case GL_R16UI:
+ case GL_R32I:
+ case GL_R32UI:
+ if (!ctx->Extensions.EXT_texture_integer)
+ break;
+ /* FALLTHROUGH */
+ case GL_R8:
+ case GL_R16:
+ case GL_RED:
+ case GL_COMPRESSED_RED:
+ return GL_RED;
+
+ case GL_RG16F:
+ /* RG16F depends on both ARB_half_float_pixel and ARB_texture_float.
+ */
+ if (!ctx->Extensions.ARB_half_float_pixel)
+ break;
+ /* FALLTHROUGH */
+ case GL_RG32F:
+ if (!ctx->Extensions.ARB_texture_float)
+ break;
+ return GL_RG;
+ case GL_RG8I:
+ case GL_RG8UI:
+ case GL_RG16I:
+ case GL_RG16UI:
+ case GL_RG32I:
+ case GL_RG32UI:
+ if (!ctx->Extensions.EXT_texture_integer)
+ break;
+ /* FALLTHROUGH */
+ case GL_RG:
+ case GL_RG8:
+ case GL_RG16:
+ case GL_COMPRESSED_RG:
+ return GL_RG;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_texture_shared_exponent) {
+ switch (internalFormat) {
+ case GL_RGB9_E5_EXT:
+ return GL_RGB;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_packed_float) {
+ switch (internalFormat) {
+ case GL_R11F_G11F_B10F_EXT:
+ return GL_RGB;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ARB_depth_buffer_float) {
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT32F:
+ return GL_DEPTH_COMPONENT;
+ case GL_DEPTH32F_STENCIL8:
+ return GL_DEPTH_STENCIL;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ARB_texture_compression_rgtc) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RED_RGTC1:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1:
+ return GL_RED;
+ case GL_COMPRESSED_RG_RGTC2:
+ case GL_COMPRESSED_SIGNED_RG_RGTC2:
+ return GL_RG;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ return -1; /* error */
+}
+
+
+/**
+ * For cube map faces, return a face index in [0,5].
+ * For other targets return 0;
+ */
+GLuint
+_mesa_tex_target_to_face(GLenum target)
+{
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
+ return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ else
+ return 0;
+}
+
+
+
+/**
+ * Store a gl_texture_image pointer in a gl_texture_object structure
+ * according to the target and level parameters.
+ *
+ * \param tObj texture object.
+ * \param target texture target.
+ * \param level image level.
+ * \param texImage texture image.
+ *
+ * This was basically prompted by the introduction of cube maps.
+ */
+void
+_mesa_set_tex_image(struct gl_texture_object *tObj,
+ GLenum target, GLint level,
+ struct gl_texture_image *texImage)
+{
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ ASSERT(tObj);
+ ASSERT(texImage);
+ ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0);
+
+ tObj->Image[face][level] = texImage;
+
+ /* Set the 'back' pointer */
+ texImage->TexObject = tObj;
+}
+
+
+/**
+ * Allocate a texture image structure.
+ *
+ * Called via ctx->Driver.NewTextureImage() unless overriden by a device
+ * driver.
+ *
+ * \return a pointer to gl_texture_image struct with all fields initialized to
+ * zero.
+ */
+struct gl_texture_image *
+_mesa_new_texture_image( struct gl_context *ctx )
+{
+ (void) ctx;
+ return CALLOC_STRUCT(gl_texture_image);
+}
+
+
+/**
+ * Free texture image data.
+ * This function is a fallback called via ctx->Driver.FreeTexImageData().
+ *
+ * \param texImage texture image.
+ *
+ * Free the texture image data if it's not marked as client data.
+ */
+void
+_mesa_free_texture_image_data(struct gl_context *ctx,
+ struct gl_texture_image *texImage)
+{
+ (void) ctx;
+
+ if (texImage->Data && !texImage->IsClientData) {
+ /* free the old texture data */
+ _mesa_free_texmemory(texImage->Data);
+ }
+
+ texImage->Data = NULL;
+}
+
+
+/**
+ * Free texture image.
+ *
+ * \param texImage texture image.
+ *
+ * Free the texture image structure and the associated image data.
+ */
+void
+_mesa_delete_texture_image(struct gl_context *ctx,
+ struct gl_texture_image *texImage)
+{
+ /* Free texImage->Data and/or any other driver-specific texture
+ * image storage.
+ */
+ ASSERT(ctx->Driver.FreeTexImageData);
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+
+ ASSERT(texImage->Data == NULL);
+ if (texImage->ImageOffsets)
+ free(texImage->ImageOffsets);
+ free(texImage);
+}
+
+
+/**
+ * Test if a target is a proxy target.
+ *
+ * \param target texture target.
+ *
+ * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
+ */
+GLboolean
+_mesa_is_proxy_texture(GLenum target)
+{
+ /* NUM_TEXTURE_TARGETS should match number of terms below */
+ assert(NUM_TEXTURE_TARGETS == 7);
+
+ return (target == GL_PROXY_TEXTURE_1D ||
+ target == GL_PROXY_TEXTURE_2D ||
+ target == GL_PROXY_TEXTURE_3D ||
+ target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
+ target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
+}
+
+
+/**
+ * Return the proxy target which corresponds to the given texture target
+ */
+static GLenum
+get_proxy_target(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ return GL_PROXY_TEXTURE_1D;
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return GL_PROXY_TEXTURE_2D;
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ return GL_PROXY_TEXTURE_3D;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ return GL_PROXY_TEXTURE_CUBE_MAP_ARB;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return GL_PROXY_TEXTURE_RECTANGLE_NV;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ return GL_PROXY_TEXTURE_1D_ARRAY_EXT;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return GL_PROXY_TEXTURE_2D_ARRAY_EXT;
+ default:
+ _mesa_problem(NULL, "unexpected target in get_proxy_target()");
+ return 0;
+ }
+}
+
+
+/**
+ * Get the texture object that corresponds to the target of the given
+ * texture unit.
+ *
+ * \param ctx GL context.
+ * \param texUnit texture unit.
+ * \param target texture target.
+ *
+ * \return pointer to the texture object on success, or NULL on failure.
+ *
+ * \sa gl_texture_unit.
+ */
+struct gl_texture_object *
+_mesa_select_tex_object(struct gl_context *ctx,
+ const struct gl_texture_unit *texUnit,
+ GLenum target)
+{
+ const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array);
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return texUnit->CurrentTex[TEXTURE_1D_INDEX];
+ case GL_PROXY_TEXTURE_1D:
+ return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
+ case GL_TEXTURE_2D:
+ return texUnit->CurrentTex[TEXTURE_2D_INDEX];
+ case GL_PROXY_TEXTURE_2D:
+ return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
+ case GL_TEXTURE_3D:
+ return texUnit->CurrentTex[TEXTURE_3D_INDEX];
+ case GL_PROXY_TEXTURE_3D:
+ return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ return ctx->Extensions.ARB_texture_cube_map
+ ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ return ctx->Extensions.ARB_texture_cube_map
+ ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
+ case GL_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle
+ ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle
+ ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
+ default:
+ _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
+ return NULL;
+ }
+}
+
+
+/**
+ * Return pointer to texture object for given target on current texture unit.
+ */
+struct gl_texture_object *
+_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
+{
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ return _mesa_select_tex_object(ctx, texUnit, target);
+}
+
+
+/**
+ * Get a texture image pointer from a texture object, given a texture
+ * target and mipmap level. The target and level parameters should
+ * have already been error-checked.
+ *
+ * \param ctx GL context.
+ * \param texObj texture unit.
+ * \param target texture target.
+ * \param level image level.
+ *
+ * \return pointer to the texture image structure, or NULL on failure.
+ */
+struct gl_texture_image *
+_mesa_select_tex_image(struct gl_context *ctx,
+ const struct gl_texture_object *texObj,
+ GLenum target, GLint level)
+{
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ ASSERT(texObj);
+ ASSERT(level >= 0);
+ ASSERT(level < MAX_TEXTURE_LEVELS);
+
+ return texObj->Image[face][level];
+}
+
+
+/**
+ * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
+ * it and install it. Only return NULL if passed a bad parameter or run
+ * out of memory.
+ */
+struct gl_texture_image *
+_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj,
+ GLenum target, GLint level)
+{
+ struct gl_texture_image *texImage;
+
+ if (!texObj)
+ return NULL;
+
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ texImage = ctx->Driver.NewTextureImage(ctx);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
+ return NULL;
+ }
+
+ _mesa_set_tex_image(texObj, target, level, texImage);
+ }
+
+ return texImage;
+}
+
+
+/**
+ * Return pointer to the specified proxy texture image.
+ * Note that proxy textures are per-context, not per-texture unit.
+ * \return pointer to texture image or NULL if invalid target, invalid
+ * level, or out of memory.
+ */
+struct gl_texture_image *
+_mesa_get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
+{
+ struct gl_texture_image *texImage;
+ GLuint texIndex;
+
+ if (level < 0 )
+ return NULL;
+
+ switch (target) {
+ case GL_PROXY_TEXTURE_1D:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_1D_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_2D:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_2D_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_3D:
+ if (level >= ctx->Const.Max3DTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_3D_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ if (level >= ctx->Const.MaxCubeTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_CUBE_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ if (level > 0)
+ return NULL;
+ texIndex = TEXTURE_RECT_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_1D_ARRAY_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_2D_ARRAY_INDEX;
+ break;
+ default:
+ return NULL;
+ }
+
+ texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
+ if (!texImage) {
+ texImage = ctx->Driver.NewTextureImage(ctx);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
+ return NULL;
+ }
+ ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
+ /* Set the 'back' pointer */
+ texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
+ }
+ return texImage;
+}
+
+
+/**
+ * Get the maximum number of allowed mipmap levels.
+ *
+ * \param ctx GL context.
+ * \param target texture target.
+ *
+ * \return the maximum number of allowed mipmap levels for the given
+ * texture target, or zero if passed a bad target.
+ *
+ * \sa gl_constants.
+ */
+GLint
+_mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return ctx->Const.MaxTextureLevels;
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ return ctx->Const.Max3DTextureLevels;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ return ctx->Extensions.ARB_texture_cube_map
+ ? ctx->Const.MaxCubeTextureLevels : 0;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array)
+ ? ctx->Const.MaxTextureLevels : 0;
+ default:
+ return 0; /* bad target */
+ }
+}
+
+
+/**
+ * Return number of dimensions per mipmap level for the given texture target.
+ */
+GLint
+_mesa_get_texture_dimensions(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ return 1;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_PROXY_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_RECTANGLE:
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_PROXY_TEXTURE_1D_ARRAY:
+ return 2;
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_PROXY_TEXTURE_2D_ARRAY:
+ return 3;
+ default:
+ _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()",
+ target);
+ return 2;
+ }
+}
+
+
+
+
+#if 000 /* not used anymore */
+/*
+ * glTexImage[123]D can accept a NULL image pointer. In this case we
+ * create a texture image with unspecified image contents per the OpenGL
+ * spec.
+ */
+static GLubyte *
+make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
+{
+ const GLint components = _mesa_components_in_format(format);
+ const GLint numPixels = width * height * depth;
+ GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
+
+#ifdef DEBUG
+ /*
+ * Let's see if anyone finds this. If glTexImage2D() is called with
+ * a NULL image pointer then load the texture image with something
+ * interesting instead of leaving it indeterminate.
+ */
+ if (data) {
+ static const char message[8][32] = {
+ " X X XXXXX XXX X ",
+ " XX XX X X X X X ",
+ " X X X X X X X ",
+ " X X XXXX XXX XXXXX ",
+ " X X X X X X ",
+ " X X X X X X X ",
+ " X X XXXXX XXX X X ",
+ " "
+ };
+
+ GLubyte *imgPtr = data;
+ GLint h, i, j, k;
+ for (h = 0; h < depth; h++) {
+ for (i = 0; i < height; i++) {
+ GLint srcRow = 7 - (i % 8);
+ for (j = 0; j < width; j++) {
+ GLint srcCol = j % 32;
+ GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
+ for (k = 0; k < components; k++) {
+ *imgPtr++ = texel;
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ return data;
+}
+#endif
+
+
+
+/**
+ * Reset the fields of a gl_texture_image struct to zero.
+ *
+ * \param img texture image structure.
+ *
+ * This is called when a proxy texture test fails, we set all the
+ * image members (except DriverData) to zero.
+ * It's also used in glTexImage[123]D as a safeguard to be sure all
+ * required fields get initialized properly by the Driver.TexImage[123]D
+ * functions.
+ */
+static void
+clear_teximage_fields(struct gl_texture_image *img)
+{
+ ASSERT(img);
+ img->_BaseFormat = 0;
+ img->InternalFormat = 0;
+ img->Border = 0;
+ img->Width = 0;
+ img->Height = 0;
+ img->Depth = 0;
+ img->RowStride = 0;
+ if (img->ImageOffsets) {
+ free(img->ImageOffsets);
+ img->ImageOffsets = NULL;
+ }
+ img->Width2 = 0;
+ img->Height2 = 0;
+ img->Depth2 = 0;
+ img->WidthLog2 = 0;
+ img->HeightLog2 = 0;
+ img->DepthLog2 = 0;
+ img->Data = NULL;
+ img->TexFormat = MESA_FORMAT_NONE;
+ img->FetchTexelc = NULL;
+ img->FetchTexelf = NULL;
+}
+
+
+/**
+ * Initialize basic fields of the gl_texture_image struct.
+ *
+ * \param ctx GL context.
+ * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
+ * \param img texture image structure to be initialized.
+ * \param width image width.
+ * \param height image height.
+ * \param depth image depth.
+ * \param border image border.
+ * \param internalFormat internal format.
+ * \param format the actual hardware format (one of MESA_FORMAT_*)
+ *
+ * Fills in the fields of \p img with the given information.
+ * Note: width, height and depth include the border.
+ */
+void
+_mesa_init_teximage_fields(struct gl_context *ctx, GLenum target,
+ struct gl_texture_image *img,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum internalFormat,
+ gl_format format)
+{
+ GLint i, dims;
+
+ ASSERT(img);
+ ASSERT(width >= 0);
+ ASSERT(height >= 0);
+ ASSERT(depth >= 0);
+
+ img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
+ ASSERT(img->_BaseFormat > 0);
+ img->InternalFormat = internalFormat;
+ img->Border = border;
+ img->Width = width;
+ img->Height = height;
+ img->Depth = depth;
+
+ img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
+ img->WidthLog2 = logbase2(img->Width2);
+
+ if (height == 1) { /* 1-D texture */
+ img->Height2 = 1;
+ img->HeightLog2 = 0;
+ }
+ else {
+ img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
+ img->HeightLog2 = logbase2(img->Height2);
+ }
+
+ if (depth == 1) { /* 2-D texture */
+ img->Depth2 = 1;
+ img->DepthLog2 = 0;
+ }
+ else {
+ img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
+ img->DepthLog2 = logbase2(img->Depth2);
+ }
+
+ img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
+
+ if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
+ (height == 1 || _mesa_is_pow_two(img->Height2)) &&
+ (depth == 1 || _mesa_is_pow_two(img->Depth2)))
+ img->_IsPowerOfTwo = GL_TRUE;
+ else
+ img->_IsPowerOfTwo = GL_FALSE;
+
+ /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
+ img->RowStride = width;
+ /* Allocate the ImageOffsets array and initialize to typical values.
+ * We allocate the array for 1D/2D textures too in order to avoid special-
+ * case code in the texstore routines.
+ */
+ if (img->ImageOffsets)
+ free(img->ImageOffsets);
+ img->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint));
+ for (i = 0; i < depth; i++) {
+ img->ImageOffsets[i] = i * width * height;
+ }
+
+ /* Compute Width/Height/DepthScale for mipmap lod computation */
+ if (target == GL_TEXTURE_RECTANGLE_NV) {
+ /* scale = 1.0 since texture coords directly map to texels */
+ img->WidthScale = 1.0;
+ img->HeightScale = 1.0;
+ img->DepthScale = 1.0;
+ }
+ else {
+ img->WidthScale = (GLfloat) img->Width;
+ img->HeightScale = (GLfloat) img->Height;
+ img->DepthScale = (GLfloat) img->Depth;
+ }
+
+ img->TexFormat = format;
+
+ dims = _mesa_get_texture_dimensions(target);
+
+ _mesa_set_fetch_functions(img, dims);
+}
+
+
+/**
+ * Free and clear fields of the gl_texture_image struct.
+ *
+ * \param ctx GL context.
+ * \param texImage texture image structure to be cleared.
+ *
+ * After the call, \p texImage will have no data associated with it. Its
+ * fields are cleared so that its parent object will test incomplete.
+ */
+void
+_mesa_clear_texture_image(struct gl_context *ctx,
+ struct gl_texture_image *texImage)
+{
+ ctx->Driver.FreeTexImageData(ctx, texImage);
+ clear_teximage_fields(texImage);
+}
+
+
+/**
+ * This is the fallback for Driver.TestProxyTexImage(). Test the texture
+ * level, width, height and depth against the ctx->Const limits for textures.
+ *
+ * A hardware driver might override this function if, for example, the
+ * max 3D texture size is 512x512x64 (i.e. not a cube).
+ *
+ * Note that width, height, depth == 0 is not an error. However, a
+ * texture with zero width/height/depth will be considered "incomplete"
+ * and texturing will effectively be disabled.
+ *
+ * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
+ * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
+ * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
+ * \param level as passed to glTexImage
+ * \param internalFormat as passed to glTexImage
+ * \param format as passed to glTexImage
+ * \param type as passed to glTexImage
+ * \param width as passed to glTexImage
+ * \param height as passed to glTexImage
+ * \param depth as passed to glTexImage
+ * \param border as passed to glTexImage
+ * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
+ */
+GLboolean
+_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
+ GLint internalFormat, GLenum format, GLenum type,
+ GLint width, GLint height, GLint depth, GLint border)
+{
+ GLint maxSize;
+
+ (void) internalFormat;
+ (void) format;
+ (void) type;
+
+ switch (target) {
+ case GL_PROXY_TEXTURE_1D:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+
+ case GL_PROXY_TEXTURE_2D:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 2 * border || height > 2 + maxSize)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+
+ case GL_PROXY_TEXTURE_3D:
+ maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 2 * border || height > 2 + maxSize)
+ return GL_FALSE;
+ if (depth < 2 * border || depth > 2 + maxSize)
+ return GL_FALSE;
+ if (level >= ctx->Const.Max3DTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
+ if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border))
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ maxSize = ctx->Const.MaxTextureRectSize;
+ if (width < 0 || width > maxSize)
+ return GL_FALSE;
+ if (height < 0 || height > maxSize)
+ return GL_FALSE;
+ if (level != 0)
+ return GL_FALSE;
+ return GL_TRUE;
+
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 2 * border || height > 2 + maxSize)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxCubeTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 1 || height > ctx->Const.MaxArrayTextureLayers)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 2 * border || height > 2 + maxSize)
+ return GL_FALSE;
+ if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+
+ default:
+ _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if the memory used by the texture would exceed the driver's limit.
+ * This lets us support a max 3D texture size of 8K (for example) but
+ * prevents allocating a full 8K x 8K x 8K texture.
+ * XXX this could be rolled into the proxy texture size test (above) but
+ * we don't have the actual texture internal format at that point.
+ */
+static GLboolean
+legal_texture_size(struct gl_context *ctx, gl_format format,
+ GLint width, GLint height, GLint depth)
+{
+ uint64_t bytes = _mesa_format_image_size64(format, width, height, depth);
+ uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */
+ return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes;
+}
+
+
+
+/**
+ * Helper function to determine whether a target and specific compression
+ * format are supported.
+ */
+static GLboolean
+target_can_be_compressed(const struct gl_context *ctx, GLenum target,
+ GLenum intFormat)
+{
+ (void) intFormat; /* not used yet */
+
+ switch (target) {
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return GL_TRUE; /* true for any compressed format so far */
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ return ctx->Extensions.ARB_texture_cube_map;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array);
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if the given texture target value is legal for a
+ * glTexImage1/2/3D call.
+ */
+static GLboolean
+legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
+{
+ switch (dims) {
+ case 1:
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+ case 2:
+ switch (target) {
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ return ctx->Extensions.ARB_texture_cube_map;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array);
+ default:
+ return GL_FALSE;
+ }
+ case 3:
+ switch (target) {
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ return GL_TRUE;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array);
+ default:
+ return GL_FALSE;
+ }
+ default:
+ _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims);
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if the given texture target value is legal for a
+ * glTexSubImage, glCopyTexSubImage or glCopyTexImage call.
+ * The difference compared to legal_teximage_target() above is that
+ * proxy targets are not supported.
+ */
+static GLboolean
+legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
+{
+ switch (dims) {
+ case 1:
+ return target == GL_TEXTURE_1D;
+ case 2:
+ switch (target) {
+ case GL_TEXTURE_2D:
+ return GL_TRUE;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ return ctx->Extensions.ARB_texture_cube_map;
+ case GL_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array);
+ default:
+ return GL_FALSE;
+ }
+ case 3:
+ switch (target) {
+ case GL_TEXTURE_3D:
+ return GL_TRUE;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array);
+ default:
+ return GL_FALSE;
+ }
+ default:
+ _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()",
+ dims);
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test the glTexImage[123]D() parameters for errors.
+ *
+ * \param ctx GL context.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ * \param internalFormat internal format given by the user.
+ * \param format pixel data format given by the user.
+ * \param type pixel data type given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ * \param depth image depth given by the user.
+ * \param border image border given by the user.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ *
+ * Verifies each of the parameters against the constants specified in
+ * __struct gl_contextRec::Const and the supported extensions, and according
+ * to the OpenGL specification.
+ */
+static GLboolean
+texture_error_check( struct gl_context *ctx,
+ GLuint dimensions, GLenum target,
+ GLint level, GLint internalFormat,
+ GLenum format, GLenum type,
+ GLint width, GLint height,
+ GLint depth, GLint border )
+{
+ const GLenum proxyTarget = get_proxy_target(target);
+ const GLboolean isProxy = target == proxyTarget;
+ GLboolean sizeOK = GL_TRUE;
+ GLboolean colorFormat, indexFormat;
+
+ /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(level=%d)", dimensions, level);
+ }
+ return GL_TRUE;
+ }
+
+ /* Check border */
+ if (border < 0 || border > 1 ||
+ ((target == GL_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(border=%d)", dimensions, border);
+ }
+ return GL_TRUE;
+ }
+
+ if (width < 0 || height < 0 || depth < 0) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(width, height or depth < 0)", dimensions);
+ }
+ return GL_TRUE;
+ }
+
+ /* Do this simple check before calling the TestProxyTexImage() function */
+ if (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
+ sizeOK = (width == height);
+ }
+
+ /*
+ * Use the proxy texture driver hook to see if the size/level/etc are
+ * legal.
+ */
+ sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
+ internalFormat, format,
+ type, width, height,
+ depth, border);
+ if (!sizeOK) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
+ dimensions, level, width, height, depth);
+ }
+ return GL_TRUE;
+ }
+
+ /* Check internalFormat */
+ if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(internalFormat=%s)",
+ dimensions, _mesa_lookup_enum_by_nr(internalFormat));
+ }
+ return GL_TRUE;
+ }
+
+ /* Check incoming image format and type */
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ /* Normally, GL_INVALID_OPERATION is generated by a format/type
+ * mismatch (see the 1.2 spec page 94, sec 3.6.4.). But with the
+ * GL_EXT_texture_integer extension, some combinations should generate
+ * GL_INVALID_ENUM instead (grr!).
+ */
+ if (!isProxy) {
+ GLenum error = _mesa_is_integer_format(format)
+ ? GL_INVALID_ENUM : GL_INVALID_OPERATION;
+ _mesa_error(ctx, error,
+ "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
+ dimensions, format, type);
+ }
+ return GL_TRUE;
+ }
+
+ /* make sure internal format and format basically agree */
+ colorFormat = _mesa_is_color_format(format);
+ indexFormat = _mesa_is_index_format(format);
+ if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
+ (_mesa_is_index_format(internalFormat) && !indexFormat) ||
+ (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
+ (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
+ (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
+ (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
+ dimensions, internalFormat, format);
+ return GL_TRUE;
+ }
+
+ /* additional checks for ycbcr textures */
+ if (internalFormat == GL_YCBCR_MESA) {
+ ASSERT(ctx->Extensions.MESA_ycbcr_texture);
+ if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
+ type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
+ char message[100];
+ _mesa_snprintf(message, sizeof(message),
+ "glTexImage%dD(format/type YCBCR mismatch", dimensions);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s", message);
+ return GL_TRUE; /* error */
+ }
+ if (target != GL_TEXTURE_2D &&
+ target != GL_PROXY_TEXTURE_2D &&
+ target != GL_TEXTURE_RECTANGLE_NV &&
+ target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
+ return GL_TRUE;
+ }
+ if (border != 0) {
+ if (!isProxy) {
+ char message[100];
+ _mesa_snprintf(message, sizeof(message),
+ "glTexImage%dD(format=GL_YCBCR_MESA and border=%d)",
+ dimensions, border);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s", message);
+ }
+ return GL_TRUE;
+ }
+ }
+
+ /* additional checks for depth textures */
+ if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
+ /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
+ if (target != GL_TEXTURE_1D &&
+ target != GL_PROXY_TEXTURE_1D &&
+ target != GL_TEXTURE_2D &&
+ target != GL_PROXY_TEXTURE_2D &&
+ target != GL_TEXTURE_RECTANGLE_ARB &&
+ target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexImage(target/internalFormat)");
+ return GL_TRUE;
+ }
+ }
+
+ /* additional checks for compressed textures */
+ if (_mesa_is_compressed_format(ctx, internalFormat)) {
+ if (!target_can_be_compressed(ctx, target, internalFormat)) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexImage%dD(target)", dimensions);
+ return GL_TRUE;
+ }
+ if (border != 0) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%dD(border!=0)", dimensions);
+ }
+ return GL_TRUE;
+ }
+ }
+
+ /* additional checks for integer textures */
+ if (ctx->Extensions.EXT_texture_integer &&
+ (_mesa_is_integer_format(format) !=
+ _mesa_is_integer_format(internalFormat))) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%dD(integer/non-integer format mismatch)",
+ dimensions);
+ }
+ return GL_TRUE;
+ }
+
+ /* if we get here, the parameters are OK */
+ return GL_FALSE;
+}
+
+
+/**
+ * Test glTexSubImage[123]D() parameters for errors.
+ *
+ * \param ctx GL context.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ * \param xoffset sub-image x offset given by the user.
+ * \param yoffset sub-image y offset given by the user.
+ * \param zoffset sub-image z offset given by the user.
+ * \param format pixel data format given by the user.
+ * \param type pixel data type given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ * \param depth image depth given by the user.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ *
+ * Verifies each of the parameters against the constants specified in
+ * __struct gl_contextRec::Const and the supported extensions, and according
+ * to the OpenGL specification.
+ */
+static GLboolean
+subtexture_error_check( struct gl_context *ctx, GLuint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type )
+{
+ /* Basic level check */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
+ return GL_TRUE;
+ }
+
+ /* Check for negative sizes */
+ if (width < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexSubImage%dD(width=%d)", dimensions, width);
+ return GL_TRUE;
+ }
+ if (height < 0 && dimensions > 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexSubImage%dD(height=%d)", dimensions, height);
+ return GL_TRUE;
+ }
+ if (depth < 0 && dimensions > 2) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexSubImage%dD(depth=%d)", dimensions, depth);
+ return GL_TRUE;
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ /* As with the glTexImage2D check above, the error code here
+ * depends on texture integer.
+ */
+ GLenum error = _mesa_is_integer_format(format)
+ ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
+ _mesa_error(ctx, error,
+ "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
+ dimensions, format, type);
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Do second part of glTexSubImage which depends on the destination texture.
+ * \return GL_TRUE if error recorded, GL_FALSE otherwise
+ */
+static GLboolean
+subtexture_error_check2( struct gl_context *ctx, GLuint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type,
+ const struct gl_texture_image *destTex )
+{
+ if (!destTex) {
+ /* undefined image level */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
+ return GL_TRUE;
+ }
+
+ if (xoffset < -((GLint)destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
+ dimensions);
+ return GL_TRUE;
+ }
+ if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
+ dimensions);
+ return GL_TRUE;
+ }
+ if (dimensions > 1) {
+ if (yoffset < -((GLint)destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
+ dimensions);
+ return GL_TRUE;
+ }
+ if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+ if (dimensions > 2) {
+ if (zoffset < -((GLint)destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
+ return GL_TRUE;
+ }
+ if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
+ return GL_TRUE;
+ }
+ }
+
+ if (_mesa_is_format_compressed(destTex->TexFormat)) {
+ GLuint bw, bh;
+
+ /* do tests which depend on compression block size */
+ _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh);
+
+ /* offset must be multiple of block size */
+ if ((xoffset % bw != 0) || (yoffset % bh != 0)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%dD(xoffset = %d, yoffset = %d)",
+ dimensions, xoffset, yoffset);
+ return GL_TRUE;
+ }
+ /* size must be multiple of bw by bh or equal to whole texture size */
+ if ((width % bw != 0) && (GLuint) width != destTex->Width) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%dD(width = %d)", dimensions, width);
+ return GL_TRUE;
+ }
+ if ((height % bh != 0) && (GLuint) height != destTex->Height) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%dD(height = %d)", dimensions, height);
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Test glCopyTexImage[12]D() parameters for errors.
+ *
+ * \param ctx GL context.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ * \param internalFormat internal format given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ * \param border texture border.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ *
+ * Verifies each of the parameters against the constants specified in
+ * __struct gl_contextRec::Const and the supported extensions, and according
+ * to the OpenGL specification.
+ */
+static GLboolean
+copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
+ GLenum target, GLint level, GLint internalFormat,
+ GLint width, GLint height, GLint border )
+{
+ const GLenum proxyTarget = get_proxy_target(target);
+ const GLenum type = GL_FLOAT;
+ GLboolean sizeOK;
+ GLint format;
+
+ /* check target */
+ if (!legal_texsubimage_target(ctx, dimensions, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)",
+ dimensions, _mesa_lookup_enum_by_nr(target));
+ return GL_TRUE;
+ }
+
+ /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage%dD(level=%d)", dimensions, level);
+ return GL_TRUE;
+ }
+
+ /* Check that the source buffer is complete */
+ if (ctx->ReadBuffer->Name) {
+ if (ctx->ReadBuffer->_Status == 0) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ }
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyTexImage%dD(invalid readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* Check border */
+ if (border < 0 || border > 1 ||
+ ((target == GL_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
+ return GL_TRUE;
+ }
+
+ format = _mesa_base_tex_format(ctx, internalFormat);
+ if (format < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage%dD(internalFormat)", dimensions);
+ return GL_TRUE;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%dD(missing readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+
+ /* Do size, level checking */
+ sizeOK = (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB)
+ ? (width == height) : 1;
+
+ sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
+ internalFormat, format,
+ type, width, height,
+ 1, border);
+
+ if (!sizeOK) {
+ if (dimensions == 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage1D(width=%d)", width);
+ }
+ else {
+ ASSERT(dimensions == 2);
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage2D(width=%d, height=%d)", width, height);
+ }
+ return GL_TRUE;
+ }
+
+ if (_mesa_is_compressed_format(ctx, internalFormat)) {
+ if (!target_can_be_compressed(ctx, target, internalFormat)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyTexImage%dD(target)", dimensions);
+ return GL_TRUE;
+ }
+ if (border != 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%dD(border!=0)", dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (_mesa_is_depth_format(internalFormat)) {
+ /* make sure we have depth/stencil buffers */
+ if (!ctx->ReadBuffer->_DepthBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%dD(no depth)", dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (_mesa_is_depthstencil_format(internalFormat)) {
+ /* make sure we have depth/stencil buffers */
+ if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%dD(no depth/stencil buffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* if we get here, the parameters are OK */
+ return GL_FALSE;
+}
+
+
+/**
+ * Test glCopyTexSubImage[12]D() parameters for errors.
+ * Note that this is the first part of error checking.
+ * See also copytexsubimage_error_check2() below for the second part.
+ *
+ * \param ctx GL context.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ */
+static GLboolean
+copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions,
+ GLenum target, GLint level)
+{
+ /* Check that the source buffer is complete */
+ if (ctx->ReadBuffer->Name) {
+ if (ctx->ReadBuffer->_Status == 0) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ }
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyTexImage%dD(invalid readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* check target (proxies not allowed) */
+ if (!legal_texsubimage_target(ctx, dimensions, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexSubImage%uD(target=%s)",
+ dimensions, _mesa_lookup_enum_by_nr(target));
+ return GL_TRUE;
+ }
+
+ /* Check level */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(level=%d)", dimensions, level);
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Second part of error checking for glCopyTexSubImage[12]D().
+ * \param xoffset sub-image x offset given by the user.
+ * \param yoffset sub-image y offset given by the user.
+ * \param zoffset sub-image z offset given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ */
+static GLboolean
+copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height,
+ const struct gl_texture_image *teximage )
+{
+ /* check that dest tex image exists */
+ if (!teximage) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(undefined texture level: %d)",
+ dimensions, level);
+ return GL_TRUE;
+ }
+
+ /* Check size */
+ if (width < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(width=%d)", dimensions, width);
+ return GL_TRUE;
+ }
+ if (dimensions > 1 && height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(height=%d)", dimensions, height);
+ return GL_TRUE;
+ }
+
+ /* check x/y offsets */
+ if (xoffset < -((GLint)teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
+ return GL_TRUE;
+ }
+ if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(xoffset+width)", dimensions);
+ return GL_TRUE;
+ }
+ if (dimensions > 1) {
+ if (yoffset < -((GLint)teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
+ return GL_TRUE;
+ }
+ /* NOTE: we're adding the border here, not subtracting! */
+ if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(yoffset+height)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* check z offset */
+ if (dimensions > 2) {
+ if (zoffset < -((GLint)teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(zoffset)", dimensions);
+ return GL_TRUE;
+ }
+ if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ if (_mesa_is_format_compressed(teximage->TexFormat)) {
+ /* offset must be multiple of 4 */
+ if ((xoffset & 3) || (yoffset & 3)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions);
+ return GL_TRUE;
+ }
+ /* size must be multiple of 4 */
+ if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(width)", dimensions);
+ return GL_TRUE;
+ }
+ if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(height)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ if (teximage->InternalFormat == GL_YCBCR_MESA) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
+ return GL_TRUE;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
+ dimensions, teximage->_BaseFormat);
+ return GL_TRUE;
+ }
+
+ if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
+ if (!ctx->ReadBuffer->_DepthBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(no depth buffer)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(no depth/stencil buffer)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* If copying into an integer texture, the source buffer must also be
+ * integer-valued.
+ */
+ if (_mesa_is_format_integer_color(teximage->TexFormat)) {
+ struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+ if (!_mesa_is_format_integer_color(rb->Format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(source buffer is not integer format)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* if we get here, the parameters are OK */
+ return GL_FALSE;
+}
+
+
+/** Callback info for walking over FBO hash table */
+struct cb_info
+{
+ struct gl_context *ctx;
+ struct gl_texture_object *texObj;
+ GLuint level, face;
+};
+
+
+/**
+ * Check render to texture callback. Called from _mesa_HashWalk().
+ */
+static void
+check_rtt_cb(GLuint key, void *data, void *userData)
+{
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
+ const struct cb_info *info = (struct cb_info *) userData;
+ struct gl_context *ctx = info->ctx;
+ const struct gl_texture_object *texObj = info->texObj;
+ const GLuint level = info->level, face = info->face;
+
+ /* If this is a user-created FBO */
+ if (fb->Name) {
+ GLuint i;
+ /* check if any of the FBO's attachments point to 'texObj' */
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ if (att->Type == GL_TEXTURE &&
+ att->Texture == texObj &&
+ att->TextureLevel == level &&
+ att->CubeMapFace == face) {
+ ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
+ /* Tell driver about the new renderbuffer texture */
+ ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
+ /* Mark fb status as indeterminate to force re-validation */
+ fb->_Status = 0;
+ }
+ }
+ }
+}
+
+
+/**
+ * When a texture image is specified we have to check if it's bound to
+ * any framebuffer objects (render to texture) in order to detect changes
+ * in size or format since that effects FBO completeness.
+ * Any FBOs rendering into the texture must be re-validated.
+ */
+static void
+update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj,
+ GLuint face, GLuint level)
+{
+ /* Only check this texture if it's been marked as RenderToTexture */
+ if (texObj->_RenderToTexture) {
+ struct cb_info info;
+ info.ctx = ctx;
+ info.texObj = texObj;
+ info.level = level;
+ info.face = face;
+ _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
+ }
+}
+
+
+/**
+ * If the texture object's GenerateMipmap flag is set and we've
+ * changed the texture base level image, regenerate the rest of the
+ * mipmap levels now.
+ */
+static INLINE void
+check_gen_mipmap(struct gl_context *ctx, GLenum target,
+ struct gl_texture_object *texObj, GLint level)
+{
+ ASSERT(target != GL_TEXTURE_CUBE_MAP);
+ if (texObj->GenerateMipmap &&
+ level == texObj->BaseLevel &&
+ level < texObj->MaxLevel) {
+ ASSERT(ctx->Driver.GenerateMipmap);
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+/** Debug helper: override the user-requested internal format */
+static GLenum
+override_internal_format(GLenum internalFormat, GLint width, GLint height)
+{
+#if 0
+ if (internalFormat == GL_RGBA16F_ARB ||
+ internalFormat == GL_RGBA32F_ARB) {
+ printf("Convert rgba float tex to int %d x %d\n", width, height);
+ return GL_RGBA;
+ }
+ else if (internalFormat == GL_RGB16F_ARB ||
+ internalFormat == GL_RGB32F_ARB) {
+ printf("Convert rgb float tex to int %d x %d\n", width, height);
+ return GL_RGB;
+ }
+ else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
+ internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_LUMINANCE_ALPHA;
+ }
+ else if (internalFormat == GL_LUMINANCE16F_ARB ||
+ internalFormat == GL_LUMINANCE32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_LUMINANCE;
+ }
+ else if (internalFormat == GL_ALPHA16F_ARB ||
+ internalFormat == GL_ALPHA32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_ALPHA;
+ }
+ /*
+ else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
+ internalFormat = GL_RGBA;
+ }
+ */
+ else {
+ return internalFormat;
+ }
+#else
+ return internalFormat;
+#endif
+}
+
+
+/**
+ * Choose the actual hardware format for a texture image.
+ * Try to use the same format as the previous image level when possible.
+ * Otherwise, ask the driver for the best format.
+ * It's important to try to choose a consistant format for all levels
+ * for efficient texture memory layout/allocation. In particular, this
+ * comes up during automatic mipmap generation.
+ */
+gl_format
+_mesa_choose_texture_format(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ GLenum target, GLint level,
+ GLenum internalFormat, GLenum format, GLenum type)
+{
+ gl_format f;
+
+ /* see if we've already chosen a format for the previous level */
+ if (level > 0) {
+ struct gl_texture_image *prevImage =
+ _mesa_select_tex_image(ctx, texObj, target, level - 1);
+ /* See if the prev level is defined and has an internal format which
+ * matches the new internal format.
+ */
+ if (prevImage &&
+ prevImage->Width > 0 &&
+ prevImage->InternalFormat == internalFormat) {
+ /* use the same format */
+ ASSERT(prevImage->TexFormat != MESA_FORMAT_NONE);
+ return prevImage->TexFormat;
+ }
+ }
+
+ /* choose format from scratch */
+ f = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
+ ASSERT(f != MESA_FORMAT_NONE);
+ return f;
+}
+
+
+/**
+ * Common code to implement all the glTexImage1D/2D/3D functions.
+ */
+static void
+teximage(struct gl_context *ctx, GLuint dims,
+ GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels)
+{
+ GLboolean error;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n",
+ dims,
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, depth, border,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ internalFormat = override_internal_format(internalFormat, width, height);
+
+ /* target error checking */
+ if (!legal_teximage_target(ctx, dims, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)",
+ dims, _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ /* general error checking */
+ error = texture_error_check(ctx, dims, target, level, internalFormat,
+ format, type, width, height, depth, border);
+
+ if (_mesa_is_proxy_texture(target)) {
+ /* Proxy texture: just clear or set state depending on error checking */
+ struct gl_texture_image *texImage =
+ _mesa_get_proxy_tex_image(ctx, target, level);
+
+ if (error) {
+ /* when error, clear all proxy texture image parameters */
+ if (texImage)
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* no error, set the tex image parameters */
+ struct gl_texture_object *texObj =
+ _mesa_get_current_tex_object(ctx, target);
+ gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
+ target, level,
+ internalFormat,
+ format, type);
+
+ if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ depth, border, internalFormat,
+ texFormat);
+ }
+ else if (texImage) {
+ clear_teximage_fields(texImage);
+ }
+ }
+ }
+ else {
+ /* non-proxy target */
+ const GLuint face = _mesa_tex_target_to_face(target);
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ if (error) {
+ return; /* error was recorded */
+ }
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
+ }
+ else {
+ gl_format texFormat;
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+
+ ASSERT(texImage->Data == NULL);
+ texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, format,
+ type);
+
+ if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ width, height, depth,
+ border, internalFormat, texFormat);
+
+ /* Give the texture to the driver. <pixels> may be null. */
+ ASSERT(ctx->Driver.TexImage3D);
+ switch (dims) {
+ case 1:
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border, format,
+ type, pixels, &ctx->Unpack, texObj,
+ texImage);
+ break;
+ case 2:
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border, format,
+ type, pixels, &ctx->Unpack, texObj,
+ texImage);
+ break;
+ case 3:
+ ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
+ width, height, depth, border, format,
+ type, pixels, &ctx->Unpack, texObj,
+ texImage);
+ break;
+ default:
+ _mesa_problem(ctx, "invalid dims=%u in teximage()", dims);
+ }
+
+ check_gen_mipmap(ctx, target, texObj, level);
+
+ update_fbo_texture(ctx, texObj, face, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
+ }
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+ }
+}
+
+
+/*
+ * Called from the API. Note that width includes the border.
+ */
+void GLAPIENTRY
+_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLint border, GLenum format,
+ GLenum type, const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ teximage(ctx, 1, target, level, internalFormat, width, 1, 1,
+ border, format, type, pixels);
+}
+
+
+void GLAPIENTRY
+_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ teximage(ctx, 2, target, level, internalFormat, width, height, 1,
+ border, format, type, pixels);
+}
+
+
+/*
+ * Called by the API or display list executor.
+ * Note that width and height include the border.
+ */
+void GLAPIENTRY
+_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ teximage(ctx, 3, target, level, internalFormat, width, height, depth,
+ border, format, type, pixels);
+}
+
+
+void GLAPIENTRY
+_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
+ depth, border, format, type, pixels);
+}
+
+
+#if FEATURE_OES_EGL_image
+void GLAPIENTRY
+_mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (!ctx->Extensions.OES_EGL_image) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEGLImageTargetTexture2DOES(unsupported)");
+ return;
+ }
+
+ if (target != GL_TEXTURE_2D) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glEGLImageTargetTexture2D(target=%d)", target);
+ return;
+ }
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ _mesa_lock_texture(ctx, texObj);
+
+ texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D");
+ } else {
+ if (texImage->Data)
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+
+ ASSERT(texImage->Data == NULL);
+ ctx->Driver.EGLImageTargetTexture2D(ctx, target,
+ texObj, texImage, image);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ _mesa_unlock_texture(ctx, texObj);
+
+}
+#endif
+
+
+
+/**
+ * Implement all the glTexSubImage1/2/3D() functions.
+ */
+static void
+texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels )
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n",
+ dims,
+ _mesa_lookup_enum_by_nr(target), level,
+ xoffset, yoffset, zoffset, width, height, depth,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ /* check target (proxies not allowed) */
+ if (!legal_texsubimage_target(ctx, dims, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
+ dims, _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+ if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type)) {
+ return; /* error was detected */
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (subtexture_error_check2(ctx, dims, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, texImage)) {
+ /* error was recorded */
+ }
+ else if (width > 0 && height > 0 && height > 0) {
+ /* If we have a border, offset=-1 is legal. Bias by border width. */
+ switch (dims) {
+ case 3:
+ zoffset += texImage->Border;
+ /* fall-through */
+ case 2:
+ yoffset += texImage->Border;
+ /* fall-through */
+ case 1:
+ xoffset += texImage->Border;
+ }
+
+ switch (dims) {
+ case 1:
+ ctx->Driver.TexSubImage1D(ctx, target, level,
+ xoffset, width,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage );
+ break;
+ case 2:
+ ctx->Driver.TexSubImage2D(ctx, target, level,
+ xoffset, yoffset, width, height,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage );
+ break;
+ case 3:
+ ctx->Driver.TexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage );
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected dims in subteximage()");
+ }
+
+ check_gen_mipmap(ctx, target, texObj, level);
+
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_TexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ texsubimage(ctx, 1, target, level,
+ xoffset, 0, 0,
+ width, 1, 1,
+ format, type, pixels);
+}
+
+
+void GLAPIENTRY
+_mesa_TexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ texsubimage(ctx, 2, target, level,
+ xoffset, yoffset, 0,
+ width, height, 1,
+ format, type, pixels);
+}
+
+
+
+void GLAPIENTRY
+_mesa_TexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ texsubimage(ctx, 3, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels);
+}
+
+
+
+/**
+ * Implement the glCopyTexImage1/2D() functions.
+ */
+static void
+copyteximage(struct gl_context *ctx, GLuint dims,
+ GLenum target, GLint level, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n",
+ dims,
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ x, y, width, height, border);
+
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
+ _mesa_update_state(ctx);
+
+ if (copytexture_error_check(ctx, dims, target, level, internalFormat,
+ width, height, border))
+ return;
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
+ }
+ else {
+ gl_format texFormat;
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+
+ ASSERT(texImage->Data == NULL);
+
+ texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, GL_NONE,
+ GL_NONE);
+
+ if (legal_texture_size(ctx, texFormat, width, height, 1)) {
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+ border, internalFormat, texFormat);
+
+ ASSERT(ctx->Driver.CopyTexImage2D);
+ if (dims == 1)
+ ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
+ x, y, width, border);
+ else
+ ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
+ x, y, width, height, border);
+
+ check_gen_mipmap(ctx, target, texObj, level);
+
+ update_fbo_texture(ctx, texObj, face, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
+ }
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexImage1D( GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ copyteximage(ctx, 2, target, level, internalFormat,
+ x, y, width, height, border);
+}
+
+
+
+/**
+ * Implementation for glCopyTexSubImage1/2/3D() functions.
+ */
+static void
+copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCopyTexSubImage%uD %s %d %d %d %d %d %d %d %d\n",
+ dims,
+ _mesa_lookup_enum_by_nr(target),
+ level, xoffset, yoffset, zoffset, x, y, width, height);
+
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
+ _mesa_update_state(ctx);
+
+ if (copytexsubimage_error_check1(ctx, dims, target, level))
+ return;
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset,
+ zoffset, width, height, texImage)) {
+ /* error was recored */
+ }
+ else {
+ /* If we have a border, offset=-1 is legal. Bias by border width. */
+ switch (dims) {
+ case 3:
+ zoffset += texImage->Border;
+ /* fall-through */
+ case 2:
+ yoffset += texImage->Border;
+ /* fall-through */
+ case 1:
+ xoffset += texImage->Border;
+ }
+
+ if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
+ &width, &height)) {
+ switch (dims) {
+ case 1:
+ ctx->Driver.CopyTexSubImage1D(ctx, target, level,
+ xoffset, x, y, width);
+ break;
+ case 2:
+ ctx->Driver.CopyTexSubImage2D(ctx, target, level,
+ xoffset, yoffset,
+ x, y, width, height);
+ break;
+ case 3:
+ ctx->Driver.CopyTexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ x, y, width, height);
+ break;
+ default:
+ _mesa_problem(ctx, "bad dims in copytexsubimage()");
+ }
+
+ check_gen_mipmap(ctx, target, texObj, level);
+
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyTexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ copytexsubimage(ctx, 1, target, level, xoffset, 0, 0, x, y, width, 1);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ copytexsubimage(ctx, 2, target, level, xoffset, yoffset, 0, x, y,
+ width, height);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ copytexsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
+ x, y, width, height);
+}
+
+
+
+
+/**********************************************************************/
+/****** Compressed Textures ******/
+/**********************************************************************/
+
+
+/**
+ * Return expected size of a compressed texture.
+ */
+static GLuint
+compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
+ GLenum glformat)
+{
+ gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
+ return _mesa_format_image_size(mesaFormat, width, height, depth);
+}
+
+
+/*
+ * Return compressed texture block size, in pixels.
+ */
+static void
+get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
+{
+ gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
+ _mesa_get_format_block_size(mesaFormat, bw, bh);
+}
+
+
+/**
+ * Error checking for glCompressedTexImage[123]D().
+ * \return error code or GL_NO_ERROR.
+ */
+static GLenum
+compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
+ GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize)
+{
+ const GLenum proxyTarget = get_proxy_target(target);
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
+ GLint expectedSize;
+
+ /* check level */
+ if (level < 0 || level >= maxLevels)
+ return GL_INVALID_VALUE;
+
+ if (!target_can_be_compressed(ctx, target, internalFormat)) {
+ return GL_INVALID_ENUM;
+ }
+
+ /* This will detect any invalid internalFormat value */
+ if (!_mesa_is_compressed_format(ctx, internalFormat))
+ return GL_INVALID_ENUM;
+
+ /* This should really never fail */
+ if (_mesa_base_tex_format(ctx, internalFormat) < 0)
+ return GL_INVALID_ENUM;
+
+ /* No compressed formats support borders at this time */
+ if (border != 0)
+ return GL_INVALID_VALUE;
+
+ /* For cube map, width must equal height */
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
+ return GL_INVALID_VALUE;
+
+ /* check image size against compression block size */
+ {
+ gl_format texFormat =
+ ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
+ GL_NONE, GL_NONE);
+ GLuint bw, bh;
+
+ _mesa_get_format_block_size(texFormat, &bw, &bh);
+ if ((width > bw && width % bw > 0) ||
+ (height > bh && height % bh > 0)) {
+ /*
+ * Per GL_ARB_texture_compression: GL_INVALID_OPERATION is
+ * generated [...] if any parameter combinations are not
+ * supported by the specific compressed internal format.
+ */
+ return GL_INVALID_OPERATION;
+ }
+ }
+
+ /* check image sizes */
+ if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
+ internalFormat, GL_NONE, GL_NONE,
+ width, height, depth, border)) {
+ /* See error comment above */
+ return GL_INVALID_OPERATION;
+ }
+
+ /* check image size in bytes */
+ expectedSize = compressed_tex_size(width, height, depth, internalFormat);
+ if (expectedSize != imageSize) {
+ /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...]
+ * if <imageSize> is not consistent with the format, dimensions, and
+ * contents of the specified image.
+ */
+ return GL_INVALID_VALUE;
+ }
+
+ return GL_NO_ERROR;
+}
+
+
+/**
+ * Error checking for glCompressedTexSubImage[123]D().
+ * \warning There are some bad assumptions here about the size of compressed
+ * texture tiles (multiple of 4) used to test the validity of the
+ * offset and size parameters.
+ * \return error code or GL_NO_ERROR.
+ */
+static GLenum
+compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize)
+{
+ GLint expectedSize, maxLevels = 0, maxTextureSize;
+ GLuint bw, bh;
+ (void) zoffset;
+
+ if (dimensions == 1) {
+ /* 1D compressed textures not allowed */
+ return GL_INVALID_ENUM;
+ }
+ else if (dimensions == 2) {
+ if (target == GL_PROXY_TEXTURE_2D) {
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if (target == GL_TEXTURE_2D) {
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map)
+ return GL_INVALID_ENUM; /*target*/
+ maxLevels = ctx->Const.MaxCubeTextureLevels;
+ }
+ else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map)
+ return GL_INVALID_ENUM; /*target*/
+ maxLevels = ctx->Const.MaxCubeTextureLevels;
+ }
+ else {
+ return GL_INVALID_ENUM; /*target*/
+ }
+ }
+ else if (dimensions == 3) {
+ /* 3D compressed textures not allowed */
+ return GL_INVALID_ENUM;
+ }
+
+ maxTextureSize = 1 << (maxLevels - 1);
+
+ /* this will catch any invalid compressed format token */
+ if (!_mesa_is_compressed_format(ctx, format))
+ return GL_INVALID_ENUM;
+
+ if (width < 1 || width > maxTextureSize)
+ return GL_INVALID_VALUE;
+
+ if ((height < 1 || height > maxTextureSize)
+ && dimensions > 1)
+ return GL_INVALID_VALUE;
+
+ if (level < 0 || level >= maxLevels)
+ return GL_INVALID_VALUE;
+
+ /*
+ * do checks which depend on compression block size
+ */
+ get_compressed_block_size(format, &bw, &bh);
+
+ if ((xoffset % bw != 0) || (yoffset % bh != 0))
+ return GL_INVALID_VALUE;
+
+ if ((width % bw != 0) && width != 2 && width != 1)
+ return GL_INVALID_VALUE;
+
+ if ((height % bh != 0) && height != 2 && height != 1)
+ return GL_INVALID_VALUE;
+
+ expectedSize = compressed_tex_size(width, height, depth, format);
+ if (expectedSize != imageSize)
+ return GL_INVALID_VALUE;
+
+ return GL_NO_ERROR;
+}
+
+
+/**
+ * Do second part of glCompressedTexSubImage error checking.
+ * \return GL_TRUE if error found, GL_FALSE otherwise.
+ */
+static GLboolean
+compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLenum format,
+ struct gl_texture_image *texImage)
+{
+
+ if ((GLint) format != texImage->InternalFormat) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTexSubImage%uD(format=0x%x)", dims, format);
+ return GL_TRUE;
+ }
+
+ if (((width == 1 || width == 2) &&
+ width != (GLsizei) texImage->Width) ||
+ (width > (GLsizei) texImage->Width)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCompressedTexSubImage%uD(width=%d)", dims, width);
+ return GL_TRUE;
+ }
+
+ if (dims >= 2) {
+ if (((height == 1 || height == 2) &&
+ height != (GLsizei) texImage->Height) ||
+ (height > (GLsizei) texImage->Height)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCompressedTexSubImage%uD(height=%d)", dims, height);
+ return GL_TRUE;
+ }
+ }
+
+ if (dims >= 3) {
+ if (((depth == 1 || depth == 2) &&
+ depth != (GLsizei) texImage->Depth) ||
+ (depth > (GLsizei) texImage->Depth)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCompressedTexSubImage%uD(depth=%d)", dims, depth);
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Implementation of the glCompressedTexImage1/2/3D() functions.
+ */
+static void
+compressedteximage(struct gl_context *ctx, GLuint dims,
+ GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid *data)
+{
+ GLenum error;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx,
+ "glCompressedTexImage%uDARB %s %d %s %d %d %d %d %d %p\n",
+ dims,
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, depth, border, imageSize, data);
+
+ /* check target */
+ if (!legal_teximage_target(ctx, dims, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target=%s)",
+ dims, _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ error = compressed_texture_error_check(ctx, dims, target, level,
+ internalFormat, width, height, depth,
+ border, imageSize);
+
+#if FEATURE_ES
+ /* XXX this is kind of a hack */
+ if (error) {
+ _mesa_error(ctx, error, "glTexImage2D");
+ return;
+ }
+
+ if (dims == 2) {
+ switch (internalFormat) {
+ case GL_PALETTE4_RGB8_OES:
+ case GL_PALETTE4_RGBA8_OES:
+ case GL_PALETTE4_R5_G6_B5_OES:
+ case GL_PALETTE4_RGBA4_OES:
+ case GL_PALETTE4_RGB5_A1_OES:
+ case GL_PALETTE8_RGB8_OES:
+ case GL_PALETTE8_RGBA8_OES:
+ case GL_PALETTE8_R5_G6_B5_OES:
+ case GL_PALETTE8_RGBA4_OES:
+ case GL_PALETTE8_RGB5_A1_OES:
+ _mesa_cpal_compressed_teximage2d(target, level, internalFormat,
+ width, height, imageSize, data);
+ return;
+ }
+ }
+#endif
+
+ if (_mesa_is_proxy_texture(target)) {
+ /* Proxy texture: just check for errors and update proxy state */
+ struct gl_texture_image *texImage;
+
+ if (!error) {
+ struct gl_texture_object *texObj =
+ _mesa_get_current_tex_object(ctx, target);
+ gl_format texFormat =
+ _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, GL_NONE, GL_NONE);
+ if (!legal_texture_size(ctx, texFormat, width, height, depth)) {
+ error = GL_OUT_OF_MEMORY;
+ }
+ }
+
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage) {
+ if (error) {
+ /* if error, clear all proxy texture image parameters */
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* no error: store the teximage parameters */
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ depth, border, internalFormat,
+ MESA_FORMAT_NONE);
+ }
+ }
+ }
+ else {
+ /* non-proxy target */
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ if (error) {
+ _mesa_error(ctx, error, "glCompressedTexImage%uD", dims);
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glCompressedTexImage%uD", dims);
+ }
+ else {
+ gl_format texFormat;
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+ ASSERT(texImage->Data == NULL);
+
+ texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, GL_NONE,
+ GL_NONE);
+
+ if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ width, height, depth,
+ border, internalFormat, texFormat);
+
+ switch (dims) {
+ case 1:
+ ASSERT(ctx->Driver.CompressedTexImage1D);
+ ctx->Driver.CompressedTexImage1D(ctx, target, level,
+ internalFormat,
+ width,
+ border, imageSize, data,
+ texObj, texImage);
+ break;
+ case 2:
+ ASSERT(ctx->Driver.CompressedTexImage2D);
+ ctx->Driver.CompressedTexImage2D(ctx, target, level,
+ internalFormat,
+ width, height,
+ border, imageSize, data,
+ texObj, texImage);
+ break;
+ case 3:
+ ASSERT(ctx->Driver.CompressedTexImage3D);
+ ctx->Driver.CompressedTexImage3D(ctx, target, level,
+ internalFormat,
+ width, height, depth,
+ border, imageSize, data,
+ texObj, texImage);
+ break;
+ default:
+ _mesa_problem(ctx, "bad dims in compressedteximage");
+ }
+
+ check_gen_mipmap(ctx, target, texObj, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glCompressedTexImage%uD", dims);
+ }
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ compressedteximage(ctx, 1, target, level, internalFormat,
+ width, 1, 1, border, imageSize, data);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLint border, GLsizei imageSize,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ compressedteximage(ctx, 2, target, level, internalFormat,
+ width, height, 1, border, imageSize, data);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ compressedteximage(ctx, 3, target, level, internalFormat,
+ width, height, depth, border, imageSize, data);
+}
+
+
+/**
+ * Common helper for glCompressedTexSubImage1/2/3D().
+ */
+static void
+compressed_tex_sub_image(GLuint dims, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize, const GLvoid *data)
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum error;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ error = compressed_subtexture_error_check(ctx, dims, target, level,
+ xoffset, 0, 0, /* pos */
+ width, height, depth, /* size */
+ format, imageSize);
+ if (error) {
+ _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims);
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ assert(texImage);
+
+ if (compressed_subtexture_error_check2(ctx, dims, width, height, depth,
+ format, texImage)) {
+ /* error was recorded */
+ }
+ else if (width > 0 && height > 0 && depth > 0) {
+ switch (dims) {
+ case 1:
+ if (ctx->Driver.CompressedTexSubImage1D) {
+ ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
+ xoffset, width,
+ format, imageSize, data,
+ texObj, texImage);
+ }
+ break;
+ case 2:
+ if (ctx->Driver.CompressedTexSubImage2D) {
+ ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
+ xoffset, yoffset,
+ width, height,
+ format, imageSize, data,
+ texObj, texImage);
+ }
+ break;
+ case 3:
+ if (ctx->Driver.CompressedTexSubImage3D) {
+ ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, imageSize, data,
+ texObj, texImage);
+ }
+ break;
+ default:
+ ;
+ }
+
+ check_gen_mipmap(ctx, target, texObj, level);
+
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format,
+ GLsizei imageSize, const GLvoid *data)
+{
+ compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1,
+ format, imageSize, data);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize,
+ const GLvoid *data)
+{
+ compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0,
+ width, height, 1, format, imageSize, data);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth, GLenum format,
+ GLsizei imageSize, const GLvoid *data)
+{
+ compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, imageSize, data);
+}
diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c
index d86a5a5ec..41d531f59 100644
--- a/mesalib/src/mesa/main/texstate.c
+++ b/mesalib/src/mesa/main/texstate.c
@@ -1,844 +1,841 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.5
- *
- * 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 texstate.c
- *
- * Texture state handling.
- */
-
-#include "glheader.h"
-#include "mfeatures.h"
-#include "colormac.h"
-#include "colortab.h"
-#include "context.h"
-#include "enums.h"
-#include "macros.h"
-#include "texobj.h"
-#include "teximage.h"
-#include "texstate.h"
-#include "mtypes.h"
-
-
-
-/**
- * Default texture combine environment state. This is used to initialize
- * a context's texture units and as the basis for converting "classic"
- * texture environmnets to ARB_texture_env_combine style values.
- */
-static const struct gl_tex_env_combine_state default_combine_state = {
- GL_MODULATE, GL_MODULATE,
- { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
- { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
- { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
- { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
- 0, 0,
- 2, 2
-};
-
-
-
-/**
- * Used by glXCopyContext to copy texture state from one context to another.
- */
-void
-_mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst )
-{
- GLuint u, tex;
-
- ASSERT(src);
- ASSERT(dst);
-
- dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
- dst->Texture._GenFlags = src->Texture._GenFlags;
- dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
- dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
- dst->Texture.SharedPalette = src->Texture.SharedPalette;
-
- /* per-unit state */
- for (u = 0; u < src->Const.MaxCombinedTextureImageUnits; u++) {
- dst->Texture.Unit[u].Enabled = src->Texture.Unit[u].Enabled;
- dst->Texture.Unit[u].EnvMode = src->Texture.Unit[u].EnvMode;
- COPY_4V(dst->Texture.Unit[u].EnvColor, src->Texture.Unit[u].EnvColor);
- dst->Texture.Unit[u].TexGenEnabled = src->Texture.Unit[u].TexGenEnabled;
- dst->Texture.Unit[u].GenS = src->Texture.Unit[u].GenS;
- dst->Texture.Unit[u].GenT = src->Texture.Unit[u].GenT;
- dst->Texture.Unit[u].GenR = src->Texture.Unit[u].GenR;
- dst->Texture.Unit[u].GenQ = src->Texture.Unit[u].GenQ;
- dst->Texture.Unit[u].LodBias = src->Texture.Unit[u].LodBias;
-
- /* GL_EXT_texture_env_combine */
- dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
-
- /* GL_ATI_envmap_bumpmap - need this? */
- dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
- COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
-
- /*
- * XXX strictly speaking, we should compare texture names/ids and
- * bind textures in the dest context according to id. For now, only
- * copy bindings if the contexts share the same pool of textures to
- * avoid refcounting bugs.
- */
- if (dst->Shared == src->Shared) {
- /* copy texture object bindings, not contents of texture objects */
- _mesa_lock_context_textures(dst);
-
- for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
- _mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
- src->Texture.Unit[u].CurrentTex[tex]);
- }
- _mesa_unlock_context_textures(dst);
- }
- }
-}
-
-
-/*
- * For debugging
- */
-void
-_mesa_print_texunit_state( struct gl_context *ctx, GLuint unit )
-{
- const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
- printf("Texture Unit %d\n", unit);
- printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
- printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
- printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
- printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
- printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
- printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
- printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
- printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
- printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
- printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
- printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
- printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
- printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
- printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
- printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
- printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
- printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
- printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
-}
-
-
-
-/**********************************************************************/
-/* Texture Environment */
-/**********************************************************************/
-
-/**
- * Convert "classic" texture environment to ARB_texture_env_combine style
- * environments.
- *
- * \param state texture_env_combine state vector to be filled-in.
- * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
- * \c GL_BLEND, \c GL_DECAL, etc.).
- * \param texBaseFormat Base format of the texture associated with the
- * texture unit.
- */
-static void
-calculate_derived_texenv( struct gl_tex_env_combine_state *state,
- GLenum mode, GLenum texBaseFormat )
-{
- GLenum mode_rgb;
- GLenum mode_a;
-
- *state = default_combine_state;
-
- switch (texBaseFormat) {
- case GL_ALPHA:
- state->SourceRGB[0] = GL_PREVIOUS;
- break;
-
- case GL_LUMINANCE_ALPHA:
- case GL_INTENSITY:
- case GL_RGBA:
- break;
-
- case GL_LUMINANCE:
- case GL_RED:
- case GL_RG:
- case GL_RGB:
- case GL_YCBCR_MESA:
- case GL_DUDV_ATI:
- state->SourceA[0] = GL_PREVIOUS;
- break;
-
- default:
- _mesa_problem(NULL,
- "Invalid texBaseFormat 0x%x in calculate_derived_texenv",
- texBaseFormat);
- return;
- }
-
- if (mode == GL_REPLACE_EXT)
- mode = GL_REPLACE;
-
- switch (mode) {
- case GL_REPLACE:
- case GL_MODULATE:
- mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
- mode_a = mode;
- break;
-
- case GL_DECAL:
- mode_rgb = GL_INTERPOLATE;
- mode_a = GL_REPLACE;
-
- state->SourceA[0] = GL_PREVIOUS;
-
- /* Having alpha / luminance / intensity textures replace using the
- * incoming fragment color matches the definition in NV_texture_shader.
- * The 1.5 spec simply marks these as "undefined".
- */
- switch (texBaseFormat) {
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_INTENSITY:
- state->SourceRGB[0] = GL_PREVIOUS;
- break;
- case GL_RED:
- case GL_RG:
- case GL_RGB:
- case GL_YCBCR_MESA:
- case GL_DUDV_ATI:
- mode_rgb = GL_REPLACE;
- break;
- case GL_RGBA:
- state->SourceRGB[2] = GL_TEXTURE;
- break;
- }
- break;
-
- case GL_BLEND:
- mode_rgb = GL_INTERPOLATE;
- mode_a = GL_MODULATE;
-
- switch (texBaseFormat) {
- case GL_ALPHA:
- mode_rgb = GL_REPLACE;
- break;
- case GL_INTENSITY:
- mode_a = GL_INTERPOLATE;
- state->SourceA[0] = GL_CONSTANT;
- state->OperandA[2] = GL_SRC_ALPHA;
- /* FALLTHROUGH */
- case GL_LUMINANCE:
- case GL_RED:
- case GL_RG:
- case GL_RGB:
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- case GL_YCBCR_MESA:
- case GL_DUDV_ATI:
- state->SourceRGB[2] = GL_TEXTURE;
- state->SourceA[2] = GL_TEXTURE;
- state->SourceRGB[0] = GL_CONSTANT;
- state->OperandRGB[2] = GL_SRC_COLOR;
- break;
- }
- break;
-
- case GL_ADD:
- mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
- mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
- break;
-
- default:
- _mesa_problem(NULL,
- "Invalid texture env mode 0x%x in calculate_derived_texenv",
- mode);
- return;
- }
-
- state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
- ? mode_rgb : GL_REPLACE;
- state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
- ? mode_a : GL_REPLACE;
-}
-
-
-
-
-/* GL_ARB_multitexture */
-void GLAPIENTRY
-_mesa_ActiveTextureARB(GLenum texture)
-{
- const GLuint texUnit = texture - GL_TEXTURE0;
- GLuint k;
- GET_CURRENT_CONTEXT(ctx);
-
- /* See OpenGL spec for glActiveTexture: */
- k = MAX2(ctx->Const.MaxCombinedTextureImageUnits,
- ctx->Const.MaxTextureCoordUnits);
-
- ASSERT(k <= Elements(ctx->Texture.Unit));
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glActiveTexture %s\n",
- _mesa_lookup_enum_by_nr(texture));
-
- if (texUnit >= k) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture=%s)",
- _mesa_lookup_enum_by_nr(texture));
- return;
- }
-
- if (ctx->Texture.CurrentUnit == texUnit)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-
- ctx->Texture.CurrentUnit = texUnit;
- if (ctx->Transform.MatrixMode == GL_TEXTURE) {
- /* update current stack pointer */
- ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
- }
-}
-
-
-/* GL_ARB_multitexture */
-void GLAPIENTRY
-_mesa_ClientActiveTextureARB(GLenum texture)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLuint texUnit = texture - GL_TEXTURE0;
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glClientActiveTexture %s\n",
- _mesa_lookup_enum_by_nr(texture));
-
- if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
- return;
- }
-
- if (ctx->Array.ActiveTexture == texUnit)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_ARRAY);
- ctx->Array.ActiveTexture = texUnit;
-}
-
-
-
-/**********************************************************************/
-/***** State management *****/
-/**********************************************************************/
-
-
-/**
- * \note This routine refers to derived texture attribute values to
- * compute the ENABLE_TEXMAT flags, but is only called on
- * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
- * flags are updated by _mesa_update_textures(), below.
- *
- * \param ctx GL context.
- */
-static void
-update_texture_matrices( struct gl_context *ctx )
-{
- GLuint u;
-
- ctx->Texture._TexMatEnabled = 0x0;
-
- for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
- ASSERT(u < Elements(ctx->TextureMatrixStack));
- if (_math_matrix_is_dirty(ctx->TextureMatrixStack[u].Top)) {
- _math_matrix_analyse( ctx->TextureMatrixStack[u].Top );
-
- if (ctx->Texture.Unit[u]._ReallyEnabled &&
- ctx->TextureMatrixStack[u].Top->type != MATRIX_IDENTITY)
- ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(u);
- }
- }
-}
-
-
-/**
- * Examine texture unit's combine/env state to update derived state.
- */
-static void
-update_tex_combine(struct gl_context *ctx, struct gl_texture_unit *texUnit)
-{
- struct gl_tex_env_combine_state *combine;
-
- /* Set the texUnit->_CurrentCombine field to point to the user's combiner
- * state, or the combiner state which is derived from traditional texenv
- * mode.
- */
- if (texUnit->EnvMode == GL_COMBINE ||
- texUnit->EnvMode == GL_COMBINE4_NV) {
- texUnit->_CurrentCombine = & texUnit->Combine;
- }
- else {
- const struct gl_texture_object *texObj = texUnit->_Current;
- GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
- if (format == GL_COLOR_INDEX) {
- format = GL_RGBA; /* a bit of a hack */
- }
- else if (format == GL_DEPTH_COMPONENT ||
- format == GL_DEPTH_STENCIL_EXT) {
- format = texObj->DepthMode;
- }
- calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
- texUnit->_CurrentCombine = & texUnit->_EnvMode;
- }
-
- combine = texUnit->_CurrentCombine;
-
- /* Determine number of source RGB terms in the combiner function */
- switch (combine->ModeRGB) {
- case GL_REPLACE:
- combine->_NumArgsRGB = 1;
- break;
- case GL_ADD:
- case GL_ADD_SIGNED:
- if (texUnit->EnvMode == GL_COMBINE4_NV)
- combine->_NumArgsRGB = 4;
- else
- combine->_NumArgsRGB = 2;
- break;
- case GL_MODULATE:
- case GL_SUBTRACT:
- case GL_DOT3_RGB:
- case GL_DOT3_RGBA:
- case GL_DOT3_RGB_EXT:
- case GL_DOT3_RGBA_EXT:
- combine->_NumArgsRGB = 2;
- break;
- case GL_INTERPOLATE:
- case GL_MODULATE_ADD_ATI:
- case GL_MODULATE_SIGNED_ADD_ATI:
- case GL_MODULATE_SUBTRACT_ATI:
- combine->_NumArgsRGB = 3;
- break;
- case GL_BUMP_ENVMAP_ATI:
- /* no real arguments for this case */
- combine->_NumArgsRGB = 0;
- break;
- default:
- combine->_NumArgsRGB = 0;
- _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
- return;
- }
-
- /* Determine number of source Alpha terms in the combiner function */
- switch (combine->ModeA) {
- case GL_REPLACE:
- combine->_NumArgsA = 1;
- break;
- case GL_ADD:
- case GL_ADD_SIGNED:
- if (texUnit->EnvMode == GL_COMBINE4_NV)
- combine->_NumArgsA = 4;
- else
- combine->_NumArgsA = 2;
- break;
- case GL_MODULATE:
- case GL_SUBTRACT:
- combine->_NumArgsA = 2;
- break;
- case GL_INTERPOLATE:
- case GL_MODULATE_ADD_ATI:
- case GL_MODULATE_SIGNED_ADD_ATI:
- case GL_MODULATE_SUBTRACT_ATI:
- combine->_NumArgsA = 3;
- break;
- default:
- combine->_NumArgsA = 0;
- _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
- break;
- }
-}
-
-
-/**
- * \note This routine refers to derived texture matrix values to
- * compute the ENABLE_TEXMAT flags, but is only called on
- * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
- * flags are updated by _mesa_update_texture_matrices, above.
- *
- * \param ctx GL context.
- */
-static void
-update_texture_state( struct gl_context *ctx )
-{
- GLuint unit;
- struct gl_fragment_program *fprog = NULL;
- struct gl_vertex_program *vprog = NULL;
- GLbitfield enabledFragUnits = 0x0;
-
- if (ctx->Shader.CurrentVertexProgram &&
- ctx->Shader.CurrentVertexProgram->LinkStatus) {
- vprog = ctx->Shader.CurrentVertexProgram->VertexProgram;
- } else if (ctx->VertexProgram._Enabled) {
- /* XXX enable this if/when non-shader vertex programs get
- * texture fetches:
- vprog = ctx->VertexProgram.Current;
- */
- }
-
- if (ctx->Shader.CurrentFragmentProgram &&
- ctx->Shader.CurrentFragmentProgram->LinkStatus) {
- fprog = ctx->Shader.CurrentFragmentProgram->FragmentProgram;
- }
- else if (ctx->FragmentProgram._Enabled) {
- fprog = ctx->FragmentProgram.Current;
- }
-
- /* FINISHME: Geometry shader texture accesses should also be considered
- * FINISHME: here.
- */
-
- /* TODO: only set this if there are actual changes */
- ctx->NewState |= _NEW_TEXTURE;
-
- ctx->Texture._EnabledUnits = 0x0;
- ctx->Texture._GenFlags = 0x0;
- ctx->Texture._TexMatEnabled = 0x0;
- ctx->Texture._TexGenEnabled = 0x0;
-
- /*
- * Update texture unit state.
- */
- for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) {
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- GLbitfield enabledVertTargets = 0x0;
- GLbitfield enabledFragTargets = 0x0;
- GLbitfield enabledTargets = 0x0;
- GLuint texIndex;
-
- /* Get the bitmask of texture target enables.
- * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
- * which texture targets are enabled (fixed function) or referenced
- * by a fragment program/program. When multiple flags are set, we'll
- * settle on the one with highest priority (see below).
- */
- if (vprog) {
- enabledVertTargets |= vprog->Base.TexturesUsed[unit];
- }
-
- if (fprog) {
- enabledFragTargets |= fprog->Base.TexturesUsed[unit];
- }
- else {
- /* fixed-function fragment program */
- enabledFragTargets |= texUnit->Enabled;
- }
-
- enabledTargets = enabledVertTargets | enabledFragTargets;
-
- texUnit->_ReallyEnabled = 0x0;
-
- if (enabledTargets == 0x0) {
- /* neither vertex nor fragment processing uses this unit */
- continue;
- }
-
- /* Look for the highest priority texture target that's enabled (or used
- * by the vert/frag shaders) and "complete". That's the one we'll use
- * for texturing. If we're using vert/frag program we're guaranteed
- * that bitcount(enabledBits) <= 1.
- * Note that the TEXTURE_x_INDEX values are in high to low priority.
- */
- for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
- if (enabledTargets & (1 << texIndex)) {
- struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
- if (!texObj->_Complete) {
- _mesa_test_texobj_completeness(ctx, texObj);
- }
- if (texObj->_Complete) {
- texUnit->_ReallyEnabled = 1 << texIndex;
- _mesa_reference_texobj(&texUnit->_Current, texObj);
- break;
- }
- }
- }
-
- if (!texUnit->_ReallyEnabled) {
- if (fprog) {
- /* If we get here it means the shader is expecting a texture
- * object, but there isn't one (or it's incomplete). Use the
- * fallback texture.
- */
- struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
- texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
- _mesa_reference_texobj(&texUnit->_Current, texObj);
- }
- else {
- /* fixed-function: texture unit is really disabled */
- continue;
- }
- }
-
- /* if we get here, we know this texture unit is enabled */
-
- ctx->Texture._EnabledUnits |= (1 << unit);
-
- if (enabledFragTargets)
- enabledFragUnits |= (1 << unit);
-
- update_tex_combine(ctx, texUnit);
- }
-
-
- /* Determine which texture coordinate sets are actually needed */
- if (fprog) {
- const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
- ctx->Texture._EnabledCoordUnits
- = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
- }
- else {
- ctx->Texture._EnabledCoordUnits = enabledFragUnits;
- }
-
- /* Setup texgen for those texture coordinate sets that are in use */
- for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-
- texUnit->_GenFlags = 0x0;
-
- if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
- continue;
-
- if (texUnit->TexGenEnabled) {
- if (texUnit->TexGenEnabled & S_BIT) {
- texUnit->_GenFlags |= texUnit->GenS._ModeBit;
- }
- if (texUnit->TexGenEnabled & T_BIT) {
- texUnit->_GenFlags |= texUnit->GenT._ModeBit;
- }
- if (texUnit->TexGenEnabled & R_BIT) {
- texUnit->_GenFlags |= texUnit->GenR._ModeBit;
- }
- if (texUnit->TexGenEnabled & Q_BIT) {
- texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
- }
-
- ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
- ctx->Texture._GenFlags |= texUnit->_GenFlags;
- }
-
- ASSERT(unit < Elements(ctx->TextureMatrixStack));
- if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
- ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
- }
-}
-
-
-/**
- * Update texture-related derived state.
- */
-void
-_mesa_update_texture( struct gl_context *ctx, GLuint new_state )
-{
- if (new_state & _NEW_TEXTURE_MATRIX)
- update_texture_matrices( ctx );
-
- if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
- update_texture_state( ctx );
-}
-
-
-/**********************************************************************/
-/***** Initialization *****/
-/**********************************************************************/
-
-/**
- * Allocate the proxy textures for the given context.
- *
- * \param ctx the context to allocate proxies for.
- *
- * \return GL_TRUE on success, or GL_FALSE on failure
- *
- * If run out of memory part way through the allocations, clean up and return
- * GL_FALSE.
- */
-static GLboolean
-alloc_proxy_textures( struct gl_context *ctx )
-{
- static const GLenum targets[] = {
- GL_TEXTURE_1D,
- GL_TEXTURE_2D,
- GL_TEXTURE_3D,
- GL_TEXTURE_CUBE_MAP_ARB,
- GL_TEXTURE_RECTANGLE_NV,
- GL_TEXTURE_1D_ARRAY_EXT,
- GL_TEXTURE_2D_ARRAY_EXT
- };
- GLint tgt;
-
- ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
-
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
- if (!(ctx->Texture.ProxyTex[tgt]
- = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
- /* out of memory, free what we did allocate */
- while (--tgt >= 0) {
- ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
- }
- return GL_FALSE;
- }
- }
-
- assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
- return GL_TRUE;
-}
-
-
-/**
- * Initialize a texture unit.
- *
- * \param ctx GL context.
- * \param unit texture unit number to be initialized.
- */
-static void
-init_texture_unit( struct gl_context *ctx, GLuint unit )
-{
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- GLuint tex;
-
- texUnit->EnvMode = GL_MODULATE;
- ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
-
- texUnit->Combine = default_combine_state;
- texUnit->_EnvMode = default_combine_state;
- texUnit->_CurrentCombine = & texUnit->_EnvMode;
- texUnit->BumpTarget = GL_TEXTURE0;
-
- texUnit->TexGenEnabled = 0x0;
- texUnit->GenS.Mode = GL_EYE_LINEAR;
- texUnit->GenT.Mode = GL_EYE_LINEAR;
- texUnit->GenR.Mode = GL_EYE_LINEAR;
- texUnit->GenQ.Mode = GL_EYE_LINEAR;
- texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
- texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
- texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
- texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR;
-
- /* Yes, these plane coefficients are correct! */
- ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
-
- /* no mention of this in spec, but maybe id matrix expected? */
- ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
-
- /* initialize current texture object ptrs to the shared default objects */
- for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
- _mesa_reference_texobj(&texUnit->CurrentTex[tex],
- ctx->Shared->DefaultTex[tex]);
- }
-}
-
-
-/**
- * Initialize texture state for the given context.
- */
-GLboolean
-_mesa_init_texture(struct gl_context *ctx)
-{
- GLuint u;
-
- /* Texture group */
- ctx->Texture.CurrentUnit = 0; /* multitexture */
- ctx->Texture._EnabledUnits = 0x0;
- ctx->Texture.SharedPalette = GL_FALSE;
- _mesa_init_colortable(&ctx->Texture.Palette);
-
- for (u = 0; u < Elements(ctx->Texture.Unit); u++)
- init_texture_unit(ctx, u);
-
- /* After we're done initializing the context's texture state the default
- * texture objects' refcounts should be at least
- * MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1.
- */
- assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
- >= MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1);
-
- /* Allocate proxy textures */
- if (!alloc_proxy_textures( ctx ))
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-
-/**
- * Free dynamically-allocted texture data attached to the given context.
- */
-void
-_mesa_free_texture_data(struct gl_context *ctx)
-{
- GLuint u, tgt;
-
- /* unreference current textures */
- for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
- /* The _Current texture could account for another reference */
- _mesa_reference_texobj(&ctx->Texture.Unit[u]._Current, NULL);
-
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
- _mesa_reference_texobj(&ctx->Texture.Unit[u].CurrentTex[tgt], NULL);
- }
- }
-
- /* Free proxy texture objects */
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
- ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
-
- for (u = 0; u < Elements(ctx->Texture.Unit); u++)
- _mesa_free_colortable_data(&ctx->Texture.Unit[u].ColorTable);
-}
-
-
-/**
- * Update the default texture objects in the given context to reference those
- * specified in the shared state and release those referencing the old
- * shared state.
- */
-void
-_mesa_update_default_objects_texture(struct gl_context *ctx)
-{
- GLuint u, tex;
-
- for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
- for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
- _mesa_reference_texobj(&texUnit->CurrentTex[tex],
- ctx->Shared->DefaultTex[tex]);
- }
- }
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * 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 texstate.c
+ *
+ * Texture state handling.
+ */
+
+#include "glheader.h"
+#include "mfeatures.h"
+#include "colormac.h"
+#include "colortab.h"
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "mtypes.h"
+
+
+
+/**
+ * Default texture combine environment state. This is used to initialize
+ * a context's texture units and as the basis for converting "classic"
+ * texture environmnets to ARB_texture_env_combine style values.
+ */
+static const struct gl_tex_env_combine_state default_combine_state = {
+ GL_MODULATE, GL_MODULATE,
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+ { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
+ { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
+ 0, 0,
+ 2, 2
+};
+
+
+
+/**
+ * Used by glXCopyContext to copy texture state from one context to another.
+ */
+void
+_mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst )
+{
+ GLuint u, tex;
+
+ ASSERT(src);
+ ASSERT(dst);
+
+ dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
+ dst->Texture._GenFlags = src->Texture._GenFlags;
+ dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
+ dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
+ dst->Texture.SharedPalette = src->Texture.SharedPalette;
+
+ /* per-unit state */
+ for (u = 0; u < src->Const.MaxCombinedTextureImageUnits; u++) {
+ dst->Texture.Unit[u].Enabled = src->Texture.Unit[u].Enabled;
+ dst->Texture.Unit[u].EnvMode = src->Texture.Unit[u].EnvMode;
+ COPY_4V(dst->Texture.Unit[u].EnvColor, src->Texture.Unit[u].EnvColor);
+ dst->Texture.Unit[u].TexGenEnabled = src->Texture.Unit[u].TexGenEnabled;
+ dst->Texture.Unit[u].GenS = src->Texture.Unit[u].GenS;
+ dst->Texture.Unit[u].GenT = src->Texture.Unit[u].GenT;
+ dst->Texture.Unit[u].GenR = src->Texture.Unit[u].GenR;
+ dst->Texture.Unit[u].GenQ = src->Texture.Unit[u].GenQ;
+ dst->Texture.Unit[u].LodBias = src->Texture.Unit[u].LodBias;
+
+ /* GL_EXT_texture_env_combine */
+ dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
+
+ /* GL_ATI_envmap_bumpmap - need this? */
+ dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
+ COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
+
+ /*
+ * XXX strictly speaking, we should compare texture names/ids and
+ * bind textures in the dest context according to id. For now, only
+ * copy bindings if the contexts share the same pool of textures to
+ * avoid refcounting bugs.
+ */
+ if (dst->Shared == src->Shared) {
+ /* copy texture object bindings, not contents of texture objects */
+ _mesa_lock_context_textures(dst);
+
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
+ src->Texture.Unit[u].CurrentTex[tex]);
+ }
+ _mesa_unlock_context_textures(dst);
+ }
+ }
+}
+
+
+/*
+ * For debugging
+ */
+void
+_mesa_print_texunit_state( struct gl_context *ctx, GLuint unit )
+{
+ const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
+ printf("Texture Unit %d\n", unit);
+ printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
+ printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
+ printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
+ printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
+ printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
+ printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
+ printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
+ printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
+ printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
+ printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
+ printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
+ printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
+ printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
+ printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
+ printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
+ printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
+ printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
+ printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
+}
+
+
+
+/**********************************************************************/
+/* Texture Environment */
+/**********************************************************************/
+
+/**
+ * Convert "classic" texture environment to ARB_texture_env_combine style
+ * environments.
+ *
+ * \param state texture_env_combine state vector to be filled-in.
+ * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
+ * \c GL_BLEND, \c GL_DECAL, etc.).
+ * \param texBaseFormat Base format of the texture associated with the
+ * texture unit.
+ */
+static void
+calculate_derived_texenv( struct gl_tex_env_combine_state *state,
+ GLenum mode, GLenum texBaseFormat )
+{
+ GLenum mode_rgb;
+ GLenum mode_a;
+
+ *state = default_combine_state;
+
+ switch (texBaseFormat) {
+ case GL_ALPHA:
+ state->SourceRGB[0] = GL_PREVIOUS;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_RGBA:
+ break;
+
+ case GL_LUMINANCE:
+ case GL_RED:
+ case GL_RG:
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
+ state->SourceA[0] = GL_PREVIOUS;
+ break;
+
+ default:
+ _mesa_problem(NULL,
+ "Invalid texBaseFormat 0x%x in calculate_derived_texenv",
+ texBaseFormat);
+ return;
+ }
+
+ if (mode == GL_REPLACE_EXT)
+ mode = GL_REPLACE;
+
+ switch (mode) {
+ case GL_REPLACE:
+ case GL_MODULATE:
+ mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
+ mode_a = mode;
+ break;
+
+ case GL_DECAL:
+ mode_rgb = GL_INTERPOLATE;
+ mode_a = GL_REPLACE;
+
+ state->SourceA[0] = GL_PREVIOUS;
+
+ /* Having alpha / luminance / intensity textures replace using the
+ * incoming fragment color matches the definition in NV_texture_shader.
+ * The 1.5 spec simply marks these as "undefined".
+ */
+ switch (texBaseFormat) {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ state->SourceRGB[0] = GL_PREVIOUS;
+ break;
+ case GL_RED:
+ case GL_RG:
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
+ mode_rgb = GL_REPLACE;
+ break;
+ case GL_RGBA:
+ state->SourceRGB[2] = GL_TEXTURE;
+ break;
+ }
+ break;
+
+ case GL_BLEND:
+ mode_rgb = GL_INTERPOLATE;
+ mode_a = GL_MODULATE;
+
+ switch (texBaseFormat) {
+ case GL_ALPHA:
+ mode_rgb = GL_REPLACE;
+ break;
+ case GL_INTENSITY:
+ mode_a = GL_INTERPOLATE;
+ state->SourceA[0] = GL_CONSTANT;
+ state->OperandA[2] = GL_SRC_ALPHA;
+ /* FALLTHROUGH */
+ case GL_LUMINANCE:
+ case GL_RED:
+ case GL_RG:
+ case GL_RGB:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
+ state->SourceRGB[2] = GL_TEXTURE;
+ state->SourceA[2] = GL_TEXTURE;
+ state->SourceRGB[0] = GL_CONSTANT;
+ state->OperandRGB[2] = GL_SRC_COLOR;
+ break;
+ }
+ break;
+
+ case GL_ADD:
+ mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
+ mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
+ break;
+
+ default:
+ _mesa_problem(NULL,
+ "Invalid texture env mode 0x%x in calculate_derived_texenv",
+ mode);
+ return;
+ }
+
+ state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
+ ? mode_rgb : GL_REPLACE;
+ state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
+ ? mode_a : GL_REPLACE;
+}
+
+
+
+
+/* GL_ARB_multitexture */
+void GLAPIENTRY
+_mesa_ActiveTextureARB(GLenum texture)
+{
+ const GLuint texUnit = texture - GL_TEXTURE0;
+ GLuint k;
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* See OpenGL spec for glActiveTexture: */
+ k = MAX2(ctx->Const.MaxCombinedTextureImageUnits,
+ ctx->Const.MaxTextureCoordUnits);
+
+ ASSERT(k <= Elements(ctx->Texture.Unit));
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glActiveTexture %s\n",
+ _mesa_lookup_enum_by_nr(texture));
+
+ if (texUnit >= k) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture=%s)",
+ _mesa_lookup_enum_by_nr(texture));
+ return;
+ }
+
+ if (ctx->Texture.CurrentUnit == texUnit)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ ctx->Texture.CurrentUnit = texUnit;
+ if (ctx->Transform.MatrixMode == GL_TEXTURE) {
+ /* update current stack pointer */
+ ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
+ }
+}
+
+
+/* GL_ARB_multitexture */
+void GLAPIENTRY
+_mesa_ClientActiveTextureARB(GLenum texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint texUnit = texture - GL_TEXTURE0;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glClientActiveTexture %s\n",
+ _mesa_lookup_enum_by_nr(texture));
+
+ if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
+ return;
+ }
+
+ if (ctx->Array.ActiveTexture == texUnit)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ ctx->Array.ActiveTexture = texUnit;
+}
+
+
+
+/**********************************************************************/
+/***** State management *****/
+/**********************************************************************/
+
+
+/**
+ * \note This routine refers to derived texture attribute values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_textures(), below.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_matrices( struct gl_context *ctx )
+{
+ GLuint u;
+
+ ctx->Texture._TexMatEnabled = 0x0;
+
+ for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
+ ASSERT(u < Elements(ctx->TextureMatrixStack));
+ if (_math_matrix_is_dirty(ctx->TextureMatrixStack[u].Top)) {
+ _math_matrix_analyse( ctx->TextureMatrixStack[u].Top );
+
+ if (ctx->Texture.Unit[u]._ReallyEnabled &&
+ ctx->TextureMatrixStack[u].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(u);
+ }
+ }
+}
+
+
+/**
+ * Examine texture unit's combine/env state to update derived state.
+ */
+static void
+update_tex_combine(struct gl_context *ctx, struct gl_texture_unit *texUnit)
+{
+ struct gl_tex_env_combine_state *combine;
+
+ /* Set the texUnit->_CurrentCombine field to point to the user's combiner
+ * state, or the combiner state which is derived from traditional texenv
+ * mode.
+ */
+ if (texUnit->EnvMode == GL_COMBINE ||
+ texUnit->EnvMode == GL_COMBINE4_NV) {
+ texUnit->_CurrentCombine = & texUnit->Combine;
+ }
+ else {
+ const struct gl_texture_object *texObj = texUnit->_Current;
+ GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
+ if (format == GL_COLOR_INDEX) {
+ format = GL_RGBA; /* a bit of a hack */
+ }
+ else if (format == GL_DEPTH_COMPONENT ||
+ format == GL_DEPTH_STENCIL_EXT) {
+ format = texObj->DepthMode;
+ }
+ calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
+ }
+
+ combine = texUnit->_CurrentCombine;
+
+ /* Determine number of source RGB terms in the combiner function */
+ switch (combine->ModeRGB) {
+ case GL_REPLACE:
+ combine->_NumArgsRGB = 1;
+ break;
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ if (texUnit->EnvMode == GL_COMBINE4_NV)
+ combine->_NumArgsRGB = 4;
+ else
+ combine->_NumArgsRGB = 2;
+ break;
+ case GL_MODULATE:
+ case GL_SUBTRACT:
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ combine->_NumArgsRGB = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ combine->_NumArgsRGB = 3;
+ break;
+ case GL_BUMP_ENVMAP_ATI:
+ /* no real arguments for this case */
+ combine->_NumArgsRGB = 0;
+ break;
+ default:
+ combine->_NumArgsRGB = 0;
+ _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
+ return;
+ }
+
+ /* Determine number of source Alpha terms in the combiner function */
+ switch (combine->ModeA) {
+ case GL_REPLACE:
+ combine->_NumArgsA = 1;
+ break;
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ if (texUnit->EnvMode == GL_COMBINE4_NV)
+ combine->_NumArgsA = 4;
+ else
+ combine->_NumArgsA = 2;
+ break;
+ case GL_MODULATE:
+ case GL_SUBTRACT:
+ combine->_NumArgsA = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ combine->_NumArgsA = 3;
+ break;
+ default:
+ combine->_NumArgsA = 0;
+ _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
+ break;
+ }
+}
+
+
+/**
+ * \note This routine refers to derived texture matrix values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_texture_matrices, above.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_state( struct gl_context *ctx )
+{
+ GLuint unit;
+ struct gl_fragment_program *fprog = NULL;
+ struct gl_vertex_program *vprog = NULL;
+ GLbitfield enabledFragUnits = 0x0;
+
+ if (ctx->Shader.CurrentVertexProgram &&
+ ctx->Shader.CurrentVertexProgram->LinkStatus) {
+ vprog = ctx->Shader.CurrentVertexProgram->VertexProgram;
+ } else if (ctx->VertexProgram._Enabled) {
+ /* XXX enable this if/when non-shader vertex programs get
+ * texture fetches:
+ vprog = ctx->VertexProgram.Current;
+ */
+ }
+
+ if (ctx->Shader.CurrentFragmentProgram &&
+ ctx->Shader.CurrentFragmentProgram->LinkStatus) {
+ fprog = ctx->Shader.CurrentFragmentProgram->FragmentProgram;
+ }
+ else if (ctx->FragmentProgram._Enabled) {
+ fprog = ctx->FragmentProgram.Current;
+ }
+
+ /* FINISHME: Geometry shader texture accesses should also be considered
+ * FINISHME: here.
+ */
+
+ /* TODO: only set this if there are actual changes */
+ ctx->NewState |= _NEW_TEXTURE;
+
+ ctx->Texture._EnabledUnits = 0x0;
+ ctx->Texture._GenFlags = 0x0;
+ ctx->Texture._TexMatEnabled = 0x0;
+ ctx->Texture._TexGenEnabled = 0x0;
+
+ /*
+ * Update texture unit state.
+ */
+ for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLbitfield enabledVertTargets = 0x0;
+ GLbitfield enabledFragTargets = 0x0;
+ GLbitfield enabledTargets = 0x0;
+ GLuint texIndex;
+
+ /* Get the bitmask of texture target enables.
+ * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
+ * which texture targets are enabled (fixed function) or referenced
+ * by a fragment program/program. When multiple flags are set, we'll
+ * settle on the one with highest priority (see below).
+ */
+ if (vprog) {
+ enabledVertTargets |= vprog->Base.TexturesUsed[unit];
+ }
+
+ if (fprog) {
+ enabledFragTargets |= fprog->Base.TexturesUsed[unit];
+ }
+ else {
+ /* fixed-function fragment program */
+ enabledFragTargets |= texUnit->Enabled;
+ }
+
+ enabledTargets = enabledVertTargets | enabledFragTargets;
+
+ texUnit->_ReallyEnabled = 0x0;
+
+ if (enabledTargets == 0x0) {
+ /* neither vertex nor fragment processing uses this unit */
+ continue;
+ }
+
+ /* Look for the highest priority texture target that's enabled (or used
+ * by the vert/frag shaders) and "complete". That's the one we'll use
+ * for texturing. If we're using vert/frag program we're guaranteed
+ * that bitcount(enabledBits) <= 1.
+ * Note that the TEXTURE_x_INDEX values are in high to low priority.
+ */
+ for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
+ if (enabledTargets & (1 << texIndex)) {
+ struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
+ if (!texObj->_Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->_Complete) {
+ texUnit->_ReallyEnabled = 1 << texIndex;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
+ break;
+ }
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled) {
+ if (fprog) {
+ /* If we get here it means the shader is expecting a texture
+ * object, but there isn't one (or it's incomplete). Use the
+ * fallback texture.
+ */
+ struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
+ texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
+ }
+ else {
+ /* fixed-function: texture unit is really disabled */
+ continue;
+ }
+ }
+
+ /* if we get here, we know this texture unit is enabled */
+
+ ctx->Texture._EnabledUnits |= (1 << unit);
+
+ if (enabledFragTargets)
+ enabledFragUnits |= (1 << unit);
+
+ update_tex_combine(ctx, texUnit);
+ }
+
+
+ /* Determine which texture coordinate sets are actually needed */
+ if (fprog) {
+ const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
+ ctx->Texture._EnabledCoordUnits
+ = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
+ }
+ else {
+ ctx->Texture._EnabledCoordUnits = enabledFragUnits;
+ }
+
+ /* Setup texgen for those texture coordinate sets that are in use */
+ for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ texUnit->_GenFlags = 0x0;
+
+ if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
+ continue;
+
+ if (texUnit->TexGenEnabled) {
+ if (texUnit->TexGenEnabled & S_BIT) {
+ texUnit->_GenFlags |= texUnit->GenS._ModeBit;
+ }
+ if (texUnit->TexGenEnabled & T_BIT) {
+ texUnit->_GenFlags |= texUnit->GenT._ModeBit;
+ }
+ if (texUnit->TexGenEnabled & R_BIT) {
+ texUnit->_GenFlags |= texUnit->GenR._ModeBit;
+ }
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
+ }
+
+ ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
+ ctx->Texture._GenFlags |= texUnit->_GenFlags;
+ }
+
+ ASSERT(unit < Elements(ctx->TextureMatrixStack));
+ if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
+ }
+}
+
+
+/**
+ * Update texture-related derived state.
+ */
+void
+_mesa_update_texture( struct gl_context *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_TEXTURE_MATRIX)
+ update_texture_matrices( ctx );
+
+ if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
+ update_texture_state( ctx );
+}
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+/**
+ * Allocate the proxy textures for the given context.
+ *
+ * \param ctx the context to allocate proxies for.
+ *
+ * \return GL_TRUE on success, or GL_FALSE on failure
+ *
+ * If run out of memory part way through the allocations, clean up and return
+ * GL_FALSE.
+ */
+static GLboolean
+alloc_proxy_textures( struct gl_context *ctx )
+{
+ static const GLenum targets[] = {
+ GL_TEXTURE_1D,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_3D,
+ GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_RECTANGLE_NV,
+ GL_TEXTURE_1D_ARRAY_EXT,
+ GL_TEXTURE_2D_ARRAY_EXT
+ };
+ GLint tgt;
+
+ ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
+
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ if (!(ctx->Texture.ProxyTex[tgt]
+ = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
+ /* out of memory, free what we did allocate */
+ while (--tgt >= 0) {
+ ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
+ }
+ return GL_FALSE;
+ }
+ }
+
+ assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
+ return GL_TRUE;
+}
+
+
+/**
+ * Initialize a texture unit.
+ *
+ * \param ctx GL context.
+ * \param unit texture unit number to be initialized.
+ */
+static void
+init_texture_unit( struct gl_context *ctx, GLuint unit )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLuint tex;
+
+ texUnit->EnvMode = GL_MODULATE;
+ ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
+
+ texUnit->Combine = default_combine_state;
+ texUnit->_EnvMode = default_combine_state;
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
+ texUnit->BumpTarget = GL_TEXTURE0;
+
+ texUnit->TexGenEnabled = 0x0;
+ texUnit->GenS.Mode = GL_EYE_LINEAR;
+ texUnit->GenT.Mode = GL_EYE_LINEAR;
+ texUnit->GenR.Mode = GL_EYE_LINEAR;
+ texUnit->GenQ.Mode = GL_EYE_LINEAR;
+ texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR;
+
+ /* Yes, these plane coefficients are correct! */
+ ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+
+ /* no mention of this in spec, but maybe id matrix expected? */
+ ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
+
+ /* initialize current texture object ptrs to the shared default objects */
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[tex]);
+ }
+}
+
+
+/**
+ * Initialize texture state for the given context.
+ */
+GLboolean
+_mesa_init_texture(struct gl_context *ctx)
+{
+ GLuint u;
+
+ /* Texture group */
+ ctx->Texture.CurrentUnit = 0; /* multitexture */
+ ctx->Texture._EnabledUnits = 0x0;
+ ctx->Texture.SharedPalette = GL_FALSE;
+ _mesa_init_colortable(&ctx->Texture.Palette);
+
+ for (u = 0; u < Elements(ctx->Texture.Unit); u++)
+ init_texture_unit(ctx, u);
+
+ /* After we're done initializing the context's texture state the default
+ * texture objects' refcounts should be at least
+ * MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1.
+ */
+ assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
+ >= MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1);
+
+ /* Allocate proxy textures */
+ if (!alloc_proxy_textures( ctx ))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Free dynamically-allocted texture data attached to the given context.
+ */
+void
+_mesa_free_texture_data(struct gl_context *ctx)
+{
+ GLuint u, tgt;
+
+ /* unreference current textures */
+ for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
+ /* The _Current texture could account for another reference */
+ _mesa_reference_texobj(&ctx->Texture.Unit[u]._Current, NULL);
+
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&ctx->Texture.Unit[u].CurrentTex[tgt], NULL);
+ }
+ }
+
+ /* Free proxy texture objects */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
+ ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
+}
+
+
+/**
+ * Update the default texture objects in the given context to reference those
+ * specified in the shared state and release those referencing the old
+ * shared state.
+ */
+void
+_mesa_update_default_objects_texture(struct gl_context *ctx)
+{
+ GLuint u, tex;
+
+ for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[tex]);
+ }
+ }
+}
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c
index 8a3e5f779..cd30fa021 100644
--- a/mesalib/src/mesa/main/texstore.c
+++ b/mesalib/src/mesa/main/texstore.c
@@ -61,6 +61,7 @@
#include "mfeatures.h"
#include "mtypes.h"
#include "pack.h"
+#include "pbo.h"
#include "imports.h"
#include "pack.h"
#include "texcompress.h"
@@ -4200,94 +4201,6 @@ _mesa_texstore(TEXSTORE_PARAMS)
}
-/**
- * Check if an unpack PBO is active prior to fetching a texture image.
- * If so, do bounds checking and map the buffer into main memory.
- * Any errors detected will be recorded.
- * The caller _must_ call _mesa_unmap_teximage_pbo() too!
- */
-const GLvoid *
-_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *unpack,
- const char *funcName)
-{
- GLubyte *buf;
-
- if (!_mesa_is_bufferobj(unpack->BufferObj)) {
- /* no PBO */
- return pixels;
- }
- if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)");
- return NULL;
- }
-
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB, unpack->BufferObj);
- if (!buf) {
- _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped)");
- return NULL;
- }
-
- return ADD_POINTERS(buf, pixels);
-}
-
-
-/**
- * Check if an unpack PBO is active prior to fetching a compressed texture
- * image.
- * If so, do bounds checking and map the buffer into main memory.
- * Any errors detected will be recorded.
- * The caller _must_ call _mesa_unmap_teximage_pbo() too!
- */
-const GLvoid *
-_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
- GLsizei imageSize, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- const char *funcName)
-{
- GLubyte *buf;
-
- if (!_mesa_is_bufferobj(packing->BufferObj)) {
- /* not using a PBO - return pointer unchanged */
- return pixels;
- }
- if ((const GLubyte *) pixels + imageSize >
- ((const GLubyte *) 0) + packing->BufferObj->Size) {
- /* out of bounds read! */
- _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)");
- return NULL;
- }
-
- buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB, packing->BufferObj);
- if (!buf) {
- _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
- return NULL;
- }
-
- return ADD_POINTERS(buf, pixels);
-}
-
-
-/**
- * This function must be called after either of the validate_pbo_*_teximage()
- * functions. It unmaps the PBO buffer if it was mapped earlier.
- */
-void
-_mesa_unmap_teximage_pbo(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *unpack)
-{
- if (_mesa_is_bufferobj(unpack->BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- unpack->BufferObj);
- }
-}
-
-
/** Return texture size in bytes */
static GLuint
texture_size(const struct gl_texture_image *texImage)
diff --git a/mesalib/src/mesa/main/texstore.h b/mesalib/src/mesa/main/texstore.h
index 2f3c4e821..d56318709 100644
--- a/mesalib/src/mesa/main/texstore.h
+++ b/mesalib/src/mesa/main/texstore.h
@@ -206,22 +206,4 @@ _mesa_store_compressed_texsubimage3d(struct gl_context *ctx, GLenum target,
struct gl_texture_image *texImage);
-extern const GLvoid *
-_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *unpack,
- const char *funcName);
-
-extern const GLvoid *
-_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
- GLsizei imageSize, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- const char *funcName);
-
-extern void
-_mesa_unmap_teximage_pbo(struct gl_context *ctx,
- const struct gl_pixelstore_attrib *unpack);
-
-
#endif