mirror of
https://github.com/reactos/reactos.git
synced 2024-11-09 08:08:38 +00:00
756 lines
23 KiB
C
756 lines
23 KiB
C
/*
|
|
* Mesa 3-D graphics library
|
|
* Version: 7.6
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/**
|
|
* Meta operations. Some GL operations can be expressed in terms of
|
|
* other GL operations. For example, glBlitFramebuffer() can be done
|
|
* with texture mapping and glClear() can be done with polygon rendering.
|
|
*
|
|
* \author Brian Paul
|
|
*/
|
|
|
|
|
|
#include "main/glheader.h"
|
|
#include "main/mtypes.h"
|
|
#include "main/imports.h"
|
|
#include "main/blend.h"
|
|
#include "main/bufferobj.h"
|
|
#include "main/buffers.h"
|
|
#include "main/context.h"
|
|
#include "main/depth.h"
|
|
#include "main/enable.h"
|
|
#include "main/feedback.h"
|
|
#include "main/formats.h"
|
|
#include "main/image.h"
|
|
#include "main/macros.h"
|
|
#include "main/matrix.h"
|
|
#include "main/pixel.h"
|
|
#include "main/polygon.h"
|
|
#include "main/readpix.h"
|
|
#include "main/scissor.h"
|
|
#include "main/state.h"
|
|
#include "main/stencil.h"
|
|
#include "main/texobj.h"
|
|
#include "main/texenv.h"
|
|
#include "main/texgetimage.h"
|
|
#include "main/teximage.h"
|
|
#include "main/texparam.h"
|
|
#include "main/texstate.h"
|
|
#include "main/varray.h"
|
|
#include "main/viewport.h"
|
|
#include "swrast/swrast.h"
|
|
#include "drivers/common/meta.h"
|
|
|
|
|
|
/** Return offset in bytes of the field within a vertex struct */
|
|
#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
|
|
|
|
/**
|
|
* State which we may save/restore across meta ops.
|
|
* XXX this may be incomplete...
|
|
*/
|
|
struct save_state
|
|
{
|
|
GLbitfield SavedState; /**< bitmask of MESA_META_* flags */
|
|
|
|
/** MESA_META_ALPHA_TEST */
|
|
GLboolean AlphaEnabled;
|
|
GLenum AlphaFunc;
|
|
GLclampf AlphaRef;
|
|
|
|
/** MESA_META_BLEND */
|
|
GLbitfield BlendEnabled;
|
|
GLboolean ColorLogicOpEnabled;
|
|
|
|
/** MESA_META_COLOR_MASK */
|
|
GLubyte ColorMask[4];
|
|
|
|
/** MESA_META_DEPTH_TEST */
|
|
struct gl_depthbuffer_attrib Depth;
|
|
|
|
/** MESA_META_FOG */
|
|
GLboolean Fog;
|
|
|
|
/** MESA_META_PIXEL_STORE */
|
|
struct gl_pixelstore_attrib Pack, Unpack;
|
|
|
|
/** MESA_META_PIXEL_TRANSFER */
|
|
GLfloat RedBias, RedScale;
|
|
GLfloat GreenBias, GreenScale;
|
|
GLfloat BlueBias, BlueScale;
|
|
GLfloat AlphaBias, AlphaScale;
|
|
GLfloat DepthBias, DepthScale;
|
|
GLboolean MapColorFlag;
|
|
|
|
/** MESA_META_RASTERIZATION */
|
|
GLenum FrontPolygonMode, BackPolygonMode;
|
|
GLboolean PolygonOffset;
|
|
GLboolean PolygonSmooth;
|
|
GLboolean PolygonStipple;
|
|
GLboolean PolygonCull;
|
|
|
|
/** MESA_META_SCISSOR */
|
|
struct gl_scissor_attrib Scissor;
|
|
|
|
/** MESA_META_STENCIL_TEST */
|
|
struct gl_stencil_attrib Stencil;
|
|
|
|
/** MESA_META_TRANSFORM */
|
|
GLenum MatrixMode;
|
|
GLfloat ModelviewMatrix[16];
|
|
GLfloat ProjectionMatrix[16];
|
|
GLfloat TextureMatrix[16];
|
|
|
|
/** MESA_META_CLIP */
|
|
GLbitfield ClipPlanesEnabled;
|
|
|
|
/** MESA_META_TEXTURE */
|
|
struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
|
|
/** mask of TEXTURE_2D_BIT, etc */
|
|
GLbitfield TexEnabled;
|
|
GLbitfield TexGenEnabled;
|
|
GLuint EnvMode; /* unit[0] only */
|
|
|
|
/** MESA_META_VIEWPORT */
|
|
GLint ViewportX, ViewportY, ViewportW, ViewportH;
|
|
GLclampd DepthNear, DepthFar;
|
|
|
|
/** MESA_META_SELECT_FEEDBACK */
|
|
GLenum RenderMode;
|
|
struct gl_selection Select;
|
|
struct gl_feedback Feedback;
|
|
|
|
/** Miscellaneous (always disabled) */
|
|
GLboolean Lighting;
|
|
GLboolean RasterDiscard;
|
|
};
|
|
|
|
|
|
/**
|
|
* State for glBlitFramebufer()
|
|
*/
|
|
struct blit_state
|
|
{
|
|
GLuint ArrayObj;
|
|
GLuint VBO;
|
|
GLuint DepthFP;
|
|
};
|
|
|
|
|
|
/**
|
|
* State for glClear()
|
|
*/
|
|
struct clear_state
|
|
{
|
|
GLuint ArrayObj;
|
|
GLuint VBO;
|
|
GLint ColorLocation;
|
|
|
|
GLint IntegerColorLocation;
|
|
};
|
|
|
|
|
|
/**
|
|
* State for glCopyPixels()
|
|
*/
|
|
struct copypix_state
|
|
{
|
|
GLuint ArrayObj;
|
|
GLuint VBO;
|
|
};
|
|
|
|
#define MAX_META_OPS_DEPTH 8
|
|
/**
|
|
* All per-context meta state.
|
|
*/
|
|
struct gl_meta_state
|
|
{
|
|
/** Stack of state saved during meta-ops */
|
|
struct save_state Save[MAX_META_OPS_DEPTH];
|
|
/** Save stack depth */
|
|
GLuint SaveStackDepth;
|
|
|
|
struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */
|
|
};
|
|
|
|
/**
|
|
* Initialize meta-ops for a context.
|
|
* To be called once during context creation.
|
|
*/
|
|
void
|
|
_mesa_meta_init(struct gl_context *ctx)
|
|
{
|
|
ASSERT(!ctx->Meta);
|
|
|
|
ctx->Meta = CALLOC_STRUCT(gl_meta_state);
|
|
}
|
|
|
|
|
|
/**
|
|
* Free context meta-op state.
|
|
* To be called once during context destruction.
|
|
*/
|
|
void
|
|
_mesa_meta_free(struct gl_context *ctx)
|
|
{
|
|
GET_CURRENT_CONTEXT(old_context);
|
|
_mesa_make_current(ctx, NULL, NULL);
|
|
if (old_context)
|
|
_mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer);
|
|
else
|
|
_mesa_make_current(NULL, NULL, NULL);
|
|
free(ctx->Meta);
|
|
ctx->Meta = NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Enter meta state. This is like a light-weight version of glPushAttrib
|
|
* but it also resets most GL state back to default values.
|
|
*
|
|
* \param state bitmask of MESA_META_* flags indicating which attribute groups
|
|
* to save and reset to their defaults
|
|
*/
|
|
void
|
|
_mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
|
|
{
|
|
struct save_state *save;
|
|
|
|
/* hope MAX_META_OPS_DEPTH is large enough */
|
|
assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH);
|
|
|
|
save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++];
|
|
memset(save, 0, sizeof(*save));
|
|
save->SavedState = state;
|
|
|
|
if (state & MESA_META_ALPHA_TEST) {
|
|
save->AlphaEnabled = ctx->Color.AlphaEnabled;
|
|
save->AlphaFunc = ctx->Color.AlphaFunc;
|
|
save->AlphaRef = ctx->Color.AlphaRef;
|
|
if (ctx->Color.AlphaEnabled)
|
|
_mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE);
|
|
}
|
|
|
|
if (state & MESA_META_BLEND) {
|
|
save->BlendEnabled = ctx->Color.BlendEnabled;
|
|
if (ctx->Color.BlendEnabled) {
|
|
_mesa_set_enable(ctx, GL_BLEND, GL_FALSE);
|
|
}
|
|
save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
|
|
if (ctx->Color.ColorLogicOpEnabled)
|
|
_mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
|
|
}
|
|
|
|
if (state & MESA_META_COLOR_MASK) {
|
|
memcpy(save->ColorMask, ctx->Color.ColorMask,
|
|
sizeof(ctx->Color.ColorMask));
|
|
if (!ctx->Color.ColorMask[0] ||
|
|
!ctx->Color.ColorMask[1] ||
|
|
!ctx->Color.ColorMask[2] ||
|
|
!ctx->Color.ColorMask[3])
|
|
_mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
}
|
|
|
|
if (state & MESA_META_DEPTH_TEST) {
|
|
save->Depth = ctx->Depth; /* struct copy */
|
|
if (ctx->Depth.Test)
|
|
_mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
|
|
}
|
|
|
|
if (state & MESA_META_FOG) {
|
|
save->Fog = ctx->Fog.Enabled;
|
|
if (ctx->Fog.Enabled)
|
|
_mesa_set_enable(ctx, GL_FOG, GL_FALSE);
|
|
}
|
|
|
|
if (state & MESA_META_PIXEL_STORE) {
|
|
save->Pack = ctx->Pack;
|
|
save->Unpack = ctx->Unpack;
|
|
ctx->Pack = ctx->DefaultPacking;
|
|
ctx->Unpack = ctx->DefaultPacking;
|
|
}
|
|
|
|
if (state & MESA_META_PIXEL_TRANSFER) {
|
|
save->RedScale = ctx->Pixel.RedScale;
|
|
save->RedBias = ctx->Pixel.RedBias;
|
|
save->GreenScale = ctx->Pixel.GreenScale;
|
|
save->GreenBias = ctx->Pixel.GreenBias;
|
|
save->BlueScale = ctx->Pixel.BlueScale;
|
|
save->BlueBias = ctx->Pixel.BlueBias;
|
|
save->AlphaScale = ctx->Pixel.AlphaScale;
|
|
save->AlphaBias = ctx->Pixel.AlphaBias;
|
|
save->MapColorFlag = ctx->Pixel.MapColorFlag;
|
|
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;
|
|
ctx->Pixel.MapColorFlag = GL_FALSE;
|
|
/* XXX more state */
|
|
ctx->NewState |=_NEW_PIXEL;
|
|
}
|
|
|
|
if (state & MESA_META_RASTERIZATION) {
|
|
save->FrontPolygonMode = ctx->Polygon.FrontMode;
|
|
save->BackPolygonMode = ctx->Polygon.BackMode;
|
|
save->PolygonOffset = ctx->Polygon.OffsetFill;
|
|
save->PolygonSmooth = ctx->Polygon.SmoothFlag;
|
|
save->PolygonStipple = ctx->Polygon.StippleFlag;
|
|
save->PolygonCull = ctx->Polygon.CullFlag;
|
|
_mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
_mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
|
|
}
|
|
|
|
if (state & MESA_META_SCISSOR) {
|
|
save->Scissor = ctx->Scissor; /* struct copy */
|
|
_mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE);
|
|
}
|
|
|
|
if (state & MESA_META_STENCIL_TEST) {
|
|
save->Stencil = ctx->Stencil; /* struct copy */
|
|
if (ctx->Stencil.Enabled)
|
|
_mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);
|
|
/* NOTE: other stencil state not reset */
|
|
}
|
|
|
|
if (state & MESA_META_TEXTURE) {
|
|
GLuint tgt;
|
|
|
|
save->EnvMode = ctx->Texture.Unit.EnvMode;
|
|
|
|
/* Disable all texture units */
|
|
save->TexEnabled = ctx->Texture.Unit.Enabled;
|
|
save->TexGenEnabled = ctx->Texture.Unit.TexGenEnabled;
|
|
if (ctx->Texture.Unit.Enabled ||
|
|
ctx->Texture.Unit.TexGenEnabled) {
|
|
_mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
|
|
if (ctx->Extensions.ARB_texture_cube_map)
|
|
_mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
|
|
_mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
|
|
}
|
|
|
|
/* save current texture objects for unit[0] only */
|
|
for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
|
|
_mesa_reference_texobj(&save->CurrentTexture[tgt],
|
|
ctx->Texture.Unit.CurrentTex[tgt]);
|
|
}
|
|
_mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
}
|
|
|
|
if (state & MESA_META_TRANSFORM) {
|
|
memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
|
|
16 * sizeof(GLfloat));
|
|
memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
|
|
16 * sizeof(GLfloat));
|
|
memcpy(save->TextureMatrix, ctx->TextureMatrixStack.Top->m,
|
|
16 * sizeof(GLfloat));
|
|
save->MatrixMode = ctx->Transform.MatrixMode;
|
|
/* set 1:1 vertex:pixel coordinate transform */
|
|
_mesa_MatrixMode(GL_TEXTURE);
|
|
_mesa_LoadIdentity();
|
|
_mesa_MatrixMode(GL_MODELVIEW);
|
|
_mesa_LoadIdentity();
|
|
_mesa_MatrixMode(GL_PROJECTION);
|
|
_mesa_LoadIdentity();
|
|
_mesa_Ortho(0.0, ctx->DrawBuffer->Width,
|
|
0.0, ctx->DrawBuffer->Height,
|
|
-1.0, 1.0);
|
|
}
|
|
|
|
if (state & MESA_META_CLIP) {
|
|
save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
|
|
if (ctx->Transform.ClipPlanesEnabled) {
|
|
GLuint i;
|
|
for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
|
|
_mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (state & MESA_META_VIEWPORT) {
|
|
/* save viewport state */
|
|
save->ViewportX = ctx->Viewport.X;
|
|
save->ViewportY = ctx->Viewport.Y;
|
|
save->ViewportW = ctx->Viewport.Width;
|
|
save->ViewportH = ctx->Viewport.Height;
|
|
/* set viewport to match window size */
|
|
if (ctx->Viewport.X != 0 ||
|
|
ctx->Viewport.Y != 0 ||
|
|
ctx->Viewport.Width != ctx->DrawBuffer->Width ||
|
|
ctx->Viewport.Height != ctx->DrawBuffer->Height) {
|
|
_mesa_set_viewport(ctx, 0, 0,
|
|
ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
|
|
}
|
|
/* save depth range state */
|
|
save->DepthNear = ctx->Viewport.Near;
|
|
save->DepthFar = ctx->Viewport.Far;
|
|
/* set depth range to default */
|
|
_mesa_DepthRange(0.0, 1.0);
|
|
}
|
|
|
|
if (state & MESA_META_SELECT_FEEDBACK) {
|
|
save->RenderMode = ctx->RenderMode;
|
|
if (ctx->RenderMode == GL_SELECT) {
|
|
save->Select = ctx->Select; /* struct copy */
|
|
_mesa_RenderMode(GL_RENDER);
|
|
} else if (ctx->RenderMode == GL_FEEDBACK) {
|
|
save->Feedback = ctx->Feedback; /* struct copy */
|
|
_mesa_RenderMode(GL_RENDER);
|
|
}
|
|
}
|
|
|
|
/* misc */
|
|
{
|
|
save->Lighting = ctx->Light.Enabled;
|
|
if (ctx->Light.Enabled)
|
|
_mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
|
|
save->RasterDiscard = ctx->RasterDiscard;
|
|
if (ctx->RasterDiscard)
|
|
_mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Leave meta state. This is like a light-weight version of glPopAttrib().
|
|
*/
|
|
void
|
|
_mesa_meta_end(struct gl_context *ctx)
|
|
{
|
|
struct save_state *save = &ctx->Meta->Save[--ctx->Meta->SaveStackDepth];
|
|
const GLbitfield state = save->SavedState;
|
|
|
|
if (state & MESA_META_ALPHA_TEST) {
|
|
if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
|
|
_mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
|
|
_mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef);
|
|
}
|
|
|
|
if (state & MESA_META_BLEND) {
|
|
if (ctx->Color.BlendEnabled != save->BlendEnabled) {
|
|
_mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1));
|
|
}
|
|
if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
|
|
_mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
|
|
}
|
|
|
|
if (state & MESA_META_COLOR_MASK) {
|
|
if (!TEST_EQ_4V(ctx->Color.ColorMask, save->ColorMask)) {
|
|
_mesa_ColorMask(save->ColorMask[0], save->ColorMask[1],
|
|
save->ColorMask[2], save->ColorMask[3]);
|
|
}
|
|
}
|
|
|
|
if (state & MESA_META_DEPTH_TEST) {
|
|
if (ctx->Depth.Test != save->Depth.Test)
|
|
_mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
|
|
_mesa_DepthFunc(save->Depth.Func);
|
|
_mesa_DepthMask(save->Depth.Mask);
|
|
}
|
|
|
|
if (state & MESA_META_FOG) {
|
|
_mesa_set_enable(ctx, GL_FOG, save->Fog);
|
|
}
|
|
|
|
if (state & MESA_META_PIXEL_STORE) {
|
|
ctx->Pack = save->Pack;
|
|
ctx->Unpack = save->Unpack;
|
|
}
|
|
|
|
if (state & MESA_META_PIXEL_TRANSFER) {
|
|
ctx->Pixel.RedScale = save->RedScale;
|
|
ctx->Pixel.RedBias = save->RedBias;
|
|
ctx->Pixel.GreenScale = save->GreenScale;
|
|
ctx->Pixel.GreenBias = save->GreenBias;
|
|
ctx->Pixel.BlueScale = save->BlueScale;
|
|
ctx->Pixel.BlueBias = save->BlueBias;
|
|
ctx->Pixel.AlphaScale = save->AlphaScale;
|
|
ctx->Pixel.AlphaBias = save->AlphaBias;
|
|
ctx->Pixel.MapColorFlag = save->MapColorFlag;
|
|
/* XXX more state */
|
|
ctx->NewState |=_NEW_PIXEL;
|
|
}
|
|
|
|
if (state & MESA_META_RASTERIZATION) {
|
|
_mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
|
|
_mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
|
|
_mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
|
|
_mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
|
|
_mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
|
|
_mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
|
|
}
|
|
|
|
if (state & MESA_META_SCISSOR) {
|
|
_mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
|
|
_mesa_Scissor(save->Scissor.X, save->Scissor.Y,
|
|
save->Scissor.Width, save->Scissor.Height);
|
|
}
|
|
|
|
if (state & MESA_META_STENCIL_TEST) {
|
|
const struct gl_stencil_attrib *stencil = &save->Stencil;
|
|
|
|
_mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
|
|
_mesa_ClearStencil(stencil->Clear);
|
|
_mesa_StencilFunc(stencil->Function,
|
|
stencil->Ref,
|
|
stencil->ValueMask);
|
|
_mesa_StencilMask(stencil->WriteMask);
|
|
_mesa_StencilOp(stencil->FailFunc, stencil->ZFailFunc, stencil->ZPassFunc);
|
|
}
|
|
|
|
if (state & MESA_META_TEXTURE) {
|
|
GLuint tgt;
|
|
|
|
/* restore texenv for unit[0] */
|
|
_mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
|
|
|
|
/* restore texture objects for unit[0] only */
|
|
for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
|
|
if (ctx->Texture.Unit.CurrentTex[tgt] != save->CurrentTexture[tgt]) {
|
|
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
|
|
_mesa_reference_texobj(&ctx->Texture.Unit.CurrentTex[tgt],
|
|
save->CurrentTexture[tgt]);
|
|
}
|
|
_mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
|
|
}
|
|
|
|
/* Restore fixed function texture enables, texgen */
|
|
if (ctx->Texture.Unit.Enabled != save->TexEnabled) {
|
|
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
|
|
ctx->Texture.Unit.Enabled = save->TexEnabled;
|
|
}
|
|
|
|
if (ctx->Texture.Unit.TexGenEnabled != save->TexGenEnabled) {
|
|
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
|
|
ctx->Texture.Unit.TexGenEnabled = save->TexGenEnabled;
|
|
}
|
|
}
|
|
|
|
if (state & MESA_META_TRANSFORM) {
|
|
_mesa_MatrixMode(GL_TEXTURE);
|
|
_mesa_LoadMatrixf(save->TextureMatrix);
|
|
|
|
_mesa_MatrixMode(GL_MODELVIEW);
|
|
_mesa_LoadMatrixf(save->ModelviewMatrix);
|
|
|
|
_mesa_MatrixMode(GL_PROJECTION);
|
|
_mesa_LoadMatrixf(save->ProjectionMatrix);
|
|
|
|
_mesa_MatrixMode(save->MatrixMode);
|
|
}
|
|
|
|
if (state & MESA_META_CLIP) {
|
|
if (save->ClipPlanesEnabled) {
|
|
GLuint i;
|
|
for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
|
|
if (save->ClipPlanesEnabled & (1 << i)) {
|
|
_mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (state & MESA_META_VIEWPORT) {
|
|
if (save->ViewportX != ctx->Viewport.X ||
|
|
save->ViewportY != ctx->Viewport.Y ||
|
|
save->ViewportW != ctx->Viewport.Width ||
|
|
save->ViewportH != ctx->Viewport.Height) {
|
|
_mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
|
|
save->ViewportW, save->ViewportH);
|
|
}
|
|
_mesa_DepthRange(save->DepthNear, save->DepthFar);
|
|
}
|
|
|
|
/* misc */
|
|
if (save->Lighting) {
|
|
_mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
|
|
}
|
|
if (save->RasterDiscard) {
|
|
_mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Determine whether Mesa is currently in a meta state.
|
|
*/
|
|
GLboolean
|
|
_mesa_meta_in_progress(struct gl_context *ctx)
|
|
{
|
|
return ctx->Meta->SaveStackDepth != 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Determine the GL data type to use for the temporary image read with
|
|
* ReadPixels() and passed to Tex[Sub]Image().
|
|
*/
|
|
static GLenum
|
|
get_temp_image_type(struct gl_context *ctx, GLenum baseFormat)
|
|
{
|
|
switch (baseFormat) {
|
|
case GL_RGBA:
|
|
case GL_RGB:
|
|
case GL_RG:
|
|
case GL_RED:
|
|
case GL_ALPHA:
|
|
case GL_LUMINANCE:
|
|
case GL_LUMINANCE_ALPHA:
|
|
case GL_INTENSITY:
|
|
if (ctx->DrawBuffer->Visual.redBits <= 8)
|
|
return GL_UNSIGNED_BYTE;
|
|
else if (ctx->DrawBuffer->Visual.redBits <= 16)
|
|
return GL_UNSIGNED_SHORT;
|
|
else
|
|
return GL_FLOAT;
|
|
case GL_DEPTH_COMPONENT:
|
|
return GL_UNSIGNED_INT;
|
|
default:
|
|
_mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()",
|
|
baseFormat);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
|
|
* Have to be careful with locking and meta state for pixel transfer.
|
|
*/
|
|
static void
|
|
copy_tex_sub_image(struct gl_context *ctx,
|
|
GLuint dims,
|
|
struct gl_texture_image *texImage,
|
|
GLint xoffset, GLint yoffset, GLint zoffset,
|
|
struct gl_renderbuffer *rb,
|
|
GLint x, GLint y,
|
|
GLsizei width, GLsizei height)
|
|
{
|
|
struct gl_texture_object *texObj = texImage->TexObject;
|
|
const GLenum target = texObj->Target;
|
|
GLenum format, type;
|
|
GLint bpp;
|
|
void *buf;
|
|
|
|
/* Choose format/type for temporary image buffer */
|
|
format = _mesa_get_format_base_format(texImage->TexFormat);
|
|
if (format == GL_LUMINANCE ||
|
|
format == GL_LUMINANCE_ALPHA ||
|
|
format == GL_INTENSITY) {
|
|
/* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the
|
|
* temp image buffer because glReadPixels will do L=R+G+B which is
|
|
* not what we want (should be L=R).
|
|
*/
|
|
format = GL_RGBA;
|
|
}
|
|
|
|
if (_mesa_is_format_integer_color(texImage->TexFormat)) {
|
|
_mesa_problem(ctx, "unsupported integer color copyteximage");
|
|
return;
|
|
}
|
|
|
|
type = get_temp_image_type(ctx, format);
|
|
bpp = _mesa_bytes_per_pixel(format, type);
|
|
if (bpp <= 0) {
|
|
_mesa_problem(ctx, "Bad bpp in meta copy_tex_sub_image()");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Alloc image buffer (XXX could use a PBO)
|
|
*/
|
|
buf = malloc(width * height * bpp);
|
|
if (!buf) {
|
|
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims);
|
|
return;
|
|
}
|
|
|
|
_mesa_unlock_texture(ctx, texObj); /* need to unlock first */
|
|
|
|
/*
|
|
* Read image from framebuffer (disable pixel transfer ops)
|
|
*/
|
|
_mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER);
|
|
ctx->Driver.ReadPixels(ctx, x, y, width, height,
|
|
format, type, &ctx->Pack, buf);
|
|
_mesa_meta_end(ctx);
|
|
|
|
_mesa_update_state(ctx); /* to update pixel transfer state */
|
|
|
|
/*
|
|
* Store texture data (with pixel transfer ops)
|
|
*/
|
|
_mesa_meta_begin(ctx, MESA_META_PIXEL_STORE);
|
|
if (target == GL_TEXTURE_1D) {
|
|
ctx->Driver.TexSubImage1D(ctx, texImage,
|
|
xoffset, width,
|
|
format, type, buf, &ctx->Unpack);
|
|
}
|
|
else {
|
|
ctx->Driver.TexSubImage2D(ctx, texImage,
|
|
xoffset, yoffset, width, height,
|
|
format, type, buf, &ctx->Unpack);
|
|
}
|
|
_mesa_meta_end(ctx);
|
|
|
|
_mesa_lock_texture(ctx, texObj); /* re-lock */
|
|
|
|
free(buf);
|
|
}
|
|
|
|
|
|
void
|
|
_mesa_meta_CopyTexSubImage1D(struct gl_context *ctx,
|
|
struct gl_texture_image *texImage,
|
|
GLint xoffset,
|
|
struct gl_renderbuffer *rb,
|
|
GLint x, GLint y, GLsizei width)
|
|
{
|
|
copy_tex_sub_image(ctx, 1, texImage, xoffset, 0, 0,
|
|
rb, x, y, width, 1);
|
|
}
|
|
|
|
|
|
void
|
|
_mesa_meta_CopyTexSubImage2D(struct gl_context *ctx,
|
|
struct gl_texture_image *texImage,
|
|
GLint xoffset, GLint yoffset,
|
|
struct gl_renderbuffer *rb,
|
|
GLint x, GLint y,
|
|
GLsizei width, GLsizei height)
|
|
{
|
|
copy_tex_sub_image(ctx, 2, texImage, xoffset, yoffset, 0,
|
|
rb, x, y, width, height);
|
|
}
|
|
|