meta.c revision 0fc11a24c85413a335b87bc34659d2381fd6670c
1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/*
2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Mesa 3-D graphics library
3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Version:  7.6
4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Permission is hereby granted, free of charge, to any person obtaining a
8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * copy of this software and associated documentation files (the "Software"),
9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * to deal in the Software without restriction, including without limitation
10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * and/or sell copies of the Software, and to permit persons to whom the
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Software is furnished to do so, subject to the following conditions:
13ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * The above copyright notice and this permission notice shall be included
15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * in all copies or substantial portions of the Software.
16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
17ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
215ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Meta operations.  Some GL operations can be expressed in terms of
275ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * other GL operations.  For example, glBlitFramebuffer() can be done
28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * with texture mapping and glClear() can be done with polygon rendering.
29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * \author Brian Paul
315ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */
325ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
335ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
345ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "main/glheader.h"
35ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/mtypes.h"
36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/imports.h"
37ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/arbprogram.h"
38ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/arrayobj.h"
39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/blend.h"
40ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/bufferobj.h"
41ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/buffers.h"
42ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/colortab.h"
43ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/condrender.h"
44ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/depth.h"
45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/enable.h"
46ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/fbobject.h"
47ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/feedback.h"
48ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/formats.h"
49ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/glformats.h"
50ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/image.h"
51ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/macros.h"
52ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/matrix.h"
53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/mipmap.h"
54ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/pixel.h"
55ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/pbo.h"
56ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/polygon.h"
57ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/readpix.h"
58ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/scissor.h"
59ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/shaderapi.h"
60ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/shaderobj.h"
61ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/state.h"
62ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/stencil.h"
635ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "main/texobj.h"
645ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "main/texenv.h"
655ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "main/texgetimage.h"
665ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "main/teximage.h"
67ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/texparam.h"
68ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/texstate.h"
69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/transformfeedback.h"
70ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/uniforms.h"
71ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/varray.h"
72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/viewport.h"
735ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "main/samplerobj.h"
74ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "program/program.h"
75ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "swrast/swrast.h"
76ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "drivers/common/meta.h"
775ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "main/enums.h"
78ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "main/glformats.h"
79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
805ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
81ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/** Return offset in bytes of the field within a vertex struct */
82ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
83ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
84ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
85ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State which we may save/restore across meta ops.
86ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * XXX this may be incomplete...
87ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
88ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct save_state
89ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
90ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLbitfield SavedState;  /**< bitmask of MESA_META_* flags */
91ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
92ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_ALPHA_TEST */
93ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean AlphaEnabled;
94ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum AlphaFunc;
95ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLclampf AlphaRef;
96ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
97ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_BLEND */
98ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLbitfield BlendEnabled;
99b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   GLboolean ColorLogicOpEnabled;
100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_COLOR_MASK */
102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLubyte ColorMask[MAX_DRAW_BUFFERS][4];
103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_DEPTH_TEST */
105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_depthbuffer_attrib Depth;
106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_FOG */
108ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean Fog;
109ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
110ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_PIXEL_STORE */
111ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_pixelstore_attrib Pack, Unpack;
112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_PIXEL_TRANSFER */
114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat RedBias, RedScale;
115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat GreenBias, GreenScale;
116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat BlueBias, BlueScale;
117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat AlphaBias, AlphaScale;
118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat DepthBias, DepthScale;
1195ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   GLboolean MapColorFlag;
120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_RASTERIZATION */
122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum FrontPolygonMode, BackPolygonMode;
123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean PolygonOffset;
124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean PolygonSmooth;
125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean PolygonStipple;
126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean PolygonCull;
127b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_SCISSOR */
129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_scissor_attrib Scissor;
130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_SHADER */
132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean VertexProgramEnabled;
133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_vertex_program *VertexProgram;
134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean FragmentProgramEnabled;
135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_fragment_program *FragmentProgram;
136b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   struct gl_shader_program *VertexShader;
137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_shader_program *GeometryShader;
1385ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   struct gl_shader_program *FragmentShader;
1395ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   struct gl_shader_program *ActiveShader;
140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_STENCIL_TEST */
142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_stencil_attrib Stencil;
1435ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_TRANSFORM */
145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum MatrixMode;
146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat ModelviewMatrix[16];
147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat ProjectionMatrix[16];
148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat TextureMatrix[16];
149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_CLIP */
151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLbitfield ClipPlanesEnabled;
152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_TEXTURE */
154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ActiveUnit;
155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ClientActiveUnit;
156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** for unit[0] only */
157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** mask of TEXTURE_2D_BIT, etc */
159b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint EnvMode;  /* unit[0] only */
162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_VERTEX */
164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_array_object *ArrayObj;
165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_buffer_object *ArrayBufferObj;
166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_VIEWPORT */
168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLint ViewportX, ViewportY, ViewportW, ViewportH;
169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLclampd DepthNear, DepthFar;
170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_CLAMP_FRAGMENT_COLOR */
172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum ClampFragmentColor;
173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_CLAMP_VERTEX_COLOR */
175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum ClampVertexColor;
176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
177b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   /** MESA_META_CONDITIONAL_RENDER */
178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_query_object *CondRenderQuery;
179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum CondRenderMode;
180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if FEATURE_feedback
182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_SELECT_FEEDBACK */
183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum RenderMode;
184ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_selection Select;
185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gl_feedback Feedback;
186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** MESA_META_MULTISAMPLE */
189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean MultisampleEnabled;
190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** Miscellaneous (always disabled) */
192ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean Lighting;
193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean RasterDiscard;
194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if FEATURE_EXT_transform_feedback
195ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean TransformFeedbackNeedsResume;
196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
197ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
199ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
201ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * This is currently shared by all the meta ops.  But we could create a
202ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
203ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
2045ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstruct temp_texture
205ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
206ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint TexObj;
207ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLenum Target;         /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */
208ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLsizei MinSize;       /**< Min texture size to allocate */
209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLsizei MaxSize;       /**< Max possible texture size */
210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean NPOT;        /**< Non-power of two size OK? */
211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLsizei Width, Height; /**< Current texture size */
212b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   GLenum IntFormat;
213ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat Sright, Ttop;  /**< right, top texcoords */
214ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
215ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
216ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
217ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
218ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State for glBlitFramebufer()
219ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
220ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct blit_state
221b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
222ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ArrayObj;
2235ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   GLuint VBO;
2245ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   GLuint DepthFP;
225ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
226ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
227ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2285ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/**
229f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang * State for glClear()
230f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang */
231f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangstruct clear_state
232f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang{
233f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang   GLuint ArrayObj;
234f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang   GLuint VBO;
235f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang   GLuint ShaderProg;
236f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang   GLint ColorLocation;
2375ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
238f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang   GLuint IntegerShaderProg;
239f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang   GLint IntegerColorLocation;
240f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang};
241b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
242ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
243ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
244ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State for glCopyPixels()
245ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
246ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct copypix_state
247ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
248ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ArrayObj;
249ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint VBO;
250ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
251ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
252ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
253ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
254ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State for glDrawPixels()
255ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
256ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct drawpix_state
257ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
258ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ArrayObj;
259ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
260ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint StencilFP;  /**< Fragment program for drawing stencil images */
261ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint DepthFP;  /**< Fragment program for drawing depth images */
262ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
263ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
264ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
265ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
266ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State for glBitmap()
267ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
268ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct bitmap_state
269ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
270ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ArrayObj;
271ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint VBO;
272ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct temp_texture Tex;  /**< separate texture from other meta ops */
273ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
274ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
275ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
276ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
277ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State for _mesa_meta_generate_mipmap()
278ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
279ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct gen_mipmap_state
280ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
281ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ArrayObj;
282ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint VBO;
2835ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   GLuint FBO;
2845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   GLuint Sampler;
285ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ShaderProg;
286b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   GLuint IntegerShaderProg;
287b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian};
288b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
289b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
290ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
291ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State for texture decompression
292ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
293ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct decompress_state
294ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
295ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ArrayObj;
296ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint VBO, FBO, RBO, Sampler;
297ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLint Width, Height;
298ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
299ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
300ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
301ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * State for glDrawTex()
302ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
303ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct drawtex_state
304ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
305ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint ArrayObj;
306ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint VBO;
307ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
308ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
309ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#define MAX_META_OPS_DEPTH      8
3105ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/**
3115ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * All per-context meta state.
312ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
313ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstruct gl_meta_state
314b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
315ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** Stack of state saved during meta-ops */
316ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct save_state Save[MAX_META_OPS_DEPTH];
317ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /** Save stack depth */
318ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint SaveStackDepth;
319ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
320ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct temp_texture TempTex;
321ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
322ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct blit_state Blit;    /**< For _mesa_meta_BlitFramebuffer() */
323ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct clear_state Clear;  /**< For _mesa_meta_Clear() */
324ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct copypix_state CopyPix;  /**< For _mesa_meta_CopyPixels() */
325ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct drawpix_state DrawPix;  /**< For _mesa_meta_DrawPixels() */
326ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct bitmap_state Bitmap;    /**< For _mesa_meta_Bitmap() */
327ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct gen_mipmap_state Mipmap;    /**< For _mesa_meta_GenerateMipmap() */
328ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct decompress_state Decompress;  /**< For texture decompression */
329ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct drawtex_state DrawTex;  /**< For _mesa_meta_DrawTex() */
330ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
331ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
332ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit);
333ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void cleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex);
334ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear);
335ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
336ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                              struct gen_mipmap_state *mipmap);
337ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
338ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic GLuint
339ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangcompile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB *source)
340ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
341ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLuint shader;
342ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLint ok, size;
343ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLchar *info;
344ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
345ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   shader = _mesa_CreateShaderObjectARB(target);
346ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_ShaderSourceARB(shader, 1, &source, NULL);
347ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_CompileShaderARB(shader);
348ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
349ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &ok);
350ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (ok)
351ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return shader;
352ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
353ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
354ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (size == 0) {
355ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_DeleteObjectARB(shader);
356ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return 0;
357ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
358ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
359ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   info = malloc(size);
360ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (!info) {
361ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_DeleteObjectARB(shader);
362ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return 0;
363ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
364ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
365ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_GetProgramInfoLog(shader, size, NULL, info);
366ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_problem(ctx,
367ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang		 "meta program compile failed:\n%s\n"
368ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang		 "source:\n%s\n",
369ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang		 info, source);
370ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
371ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   free(info);
372ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_DeleteObjectARB(shader);
373ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
374ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   return 0;
375ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
376ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
377ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic GLuint
378ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuanglink_program_with_debug(struct gl_context *ctx, GLuint program)
379ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
380ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLint ok, size;
381ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLchar *info;
382ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
383ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_LinkProgramARB(program);
384ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
385ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_GetProgramiv(program, GL_LINK_STATUS, &ok);
386ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (ok)
387ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return program;
388ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
389ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_GetProgramiv(program, GL_INFO_LOG_LENGTH, &size);
390ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (size == 0)
391ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return 0;
392b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
393b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   info = malloc(size);
394b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   if (!info)
395b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return 0;
396ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
397ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_GetProgramInfoLog(program, size, NULL, info);
3985ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_problem(ctx, "meta program link failed:\n%s", info);
3995ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
400ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   free(info);
401ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
402ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   return 0;
403ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
404ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
405ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Initialize meta-ops for a context.
407ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * To be called once during context creation.
408ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
409ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangvoid
410ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_mesa_meta_init(struct gl_context *ctx)
411ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
412ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   ASSERT(!ctx->Meta);
413ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
414ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   ctx->Meta = CALLOC_STRUCT(gl_meta_state);
415ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
416ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
417ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
418ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
4195ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * Free context meta-op state.
4205ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * To be called once during context destruction.
4215ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */
422ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangvoid
423ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_mesa_meta_free(struct gl_context *ctx)
4245ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang{
42591037db265ecdd914a26e056cf69207b4f50924ehkuang   GET_CURRENT_CONTEXT(old_context);
426ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_make_current(ctx, NULL, NULL);
427ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   meta_glsl_blit_cleanup(ctx, &ctx->Meta->Blit);
428ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   meta_glsl_clear_cleanup(ctx, &ctx->Meta->Clear);
429ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   meta_glsl_generate_mipmap_cleanup(ctx, &ctx->Meta->Mipmap);
430ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   cleanup_temp_texture(ctx, &ctx->Meta->TempTex);
431ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (old_context)
432ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer);
433b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   else
434ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_make_current(NULL, NULL, NULL);
435ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   free(ctx->Meta);
436ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   ctx->Meta = NULL;
437ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
438ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
439ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
440ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
441ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Enter meta state.  This is like a light-weight version of glPushAttrib
442b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian * but it also resets most GL state back to default values.
443ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
4445ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * \param state  bitmask of MESA_META_* flags indicating which attribute groups
4455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang *               to save and reset to their defaults
446ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
447ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangvoid
448ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
449b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
450ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct save_state *save;
451ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
452ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /* hope MAX_META_OPS_DEPTH is large enough */
453ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH);
454ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
455ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++];
456ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   memset(save, 0, sizeof(*save));
457ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   save->SavedState = state;
458ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
459ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if FEATURE_EXT_transform_feedback
460ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /* Pausing transform feedback needs to be done early, or else we won't be
461ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    * able to change other state.
462ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    */
463ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   save->TransformFeedbackNeedsResume =
464ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->TransformFeedback.CurrentObject->Active &&
465ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      !ctx->TransformFeedback.CurrentObject->Paused;
466ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (save->TransformFeedbackNeedsResume)
467ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_PauseTransformFeedback();
468ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
469ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
470ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_ALPHA_TEST) {
471ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->AlphaEnabled = ctx->Color.AlphaEnabled;
472ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->AlphaFunc = ctx->Color.AlphaFunc;
473ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->AlphaRef = ctx->Color.AlphaRef;
474ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Color.AlphaEnabled)
475ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE);
476ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
477ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
478ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_BLEND) {
479ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->BlendEnabled = ctx->Color.BlendEnabled;
480ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Color.BlendEnabled) {
481ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         if (ctx->Extensions.EXT_draw_buffers2) {
482ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            GLuint i;
483ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
484ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_set_enablei(ctx, GL_BLEND, i, GL_FALSE);
485ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            }
486ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         }
487ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         else {
488ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_BLEND, GL_FALSE);
489ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         }
490ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
491ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
492ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Color.ColorLogicOpEnabled)
493ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
494ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
495ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
496ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_COLOR_MASK) {
497ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      memcpy(save->ColorMask, ctx->Color.ColorMask,
498ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             sizeof(ctx->Color.ColorMask));
499ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (!ctx->Color.ColorMask[0][0] ||
500ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          !ctx->Color.ColorMask[0][1] ||
501ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          !ctx->Color.ColorMask[0][2] ||
502ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          !ctx->Color.ColorMask[0][3])
503ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
504ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
505ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
506ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_DEPTH_TEST) {
507ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->Depth = ctx->Depth; /* struct copy */
508ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Depth.Test)
509ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
510ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
511ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
512ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_FOG) {
513ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->Fog = ctx->Fog.Enabled;
514ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Fog.Enabled)
515ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_FOG, GL_FALSE);
516ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
517ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
518ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_PIXEL_STORE) {
519ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->Pack = ctx->Pack;
520ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->Unpack = ctx->Unpack;
521ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pack = ctx->DefaultPacking;
522ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Unpack = ctx->DefaultPacking;
523ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
524ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
52591037db265ecdd914a26e056cf69207b4f50924ehkuang   if (state & MESA_META_PIXEL_TRANSFER) {
526ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->RedScale = ctx->Pixel.RedScale;
527ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->RedBias = ctx->Pixel.RedBias;
528ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->GreenScale = ctx->Pixel.GreenScale;
529ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->GreenBias = ctx->Pixel.GreenBias;
530ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->BlueScale = ctx->Pixel.BlueScale;
531ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->BlueBias = ctx->Pixel.BlueBias;
532ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->AlphaScale = ctx->Pixel.AlphaScale;
533ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->AlphaBias = ctx->Pixel.AlphaBias;
534ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->MapColorFlag = ctx->Pixel.MapColorFlag;
535ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.RedScale = 1.0F;
536ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.RedBias = 0.0F;
537ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.GreenScale = 1.0F;
538ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.GreenBias = 0.0F;
539ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.BlueScale = 1.0F;
540ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.BlueBias = 0.0F;
541ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.AlphaScale = 1.0F;
542ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.AlphaBias = 0.0F;
543ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.MapColorFlag = GL_FALSE;
544ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* XXX more state */
545ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->NewState |=_NEW_PIXEL;
546ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
547ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
548ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_RASTERIZATION) {
549ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->FrontPolygonMode = ctx->Polygon.FrontMode;
550ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->BackPolygonMode = ctx->Polygon.BackMode;
551ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->PolygonOffset = ctx->Polygon.OffsetFill;
552ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->PolygonSmooth = ctx->Polygon.SmoothFlag;
553ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->PolygonStipple = ctx->Polygon.StippleFlag;
554ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->PolygonCull = ctx->Polygon.CullFlag;
555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
556ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
557ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
558ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
559ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
560ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
561ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
562ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_SCISSOR) {
563ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->Scissor = ctx->Scissor; /* struct copy */
564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE);
565ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
566ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
567ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_SHADER) {
568ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.ARB_vertex_program) {
569ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
570ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_reference_vertprog(ctx, &save->VertexProgram,
571ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				  ctx->VertexProgram.Current);
572ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
573ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
574ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
575ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.ARB_fragment_program) {
576ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
577ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_reference_fragprog(ctx, &save->FragmentProgram,
578ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				  ctx->FragmentProgram.Current);
579ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
580ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
581ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
582ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.ARB_shader_objects) {
583ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_reference_shader_program(ctx, &save->VertexShader,
584ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang					ctx->Shader.CurrentVertexProgram);
585ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_reference_shader_program(ctx, &save->GeometryShader,
586ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang					ctx->Shader.CurrentGeometryProgram);
587ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_reference_shader_program(ctx, &save->FragmentShader,
588ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang					ctx->Shader.CurrentFragmentProgram);
589ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_reference_shader_program(ctx, &save->ActiveShader,
590ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang					ctx->Shader.ActiveProgram);
591ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
592ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_UseProgramObjectARB(0);
593ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
594ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
595ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
596ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_STENCIL_TEST) {
597ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->Stencil = ctx->Stencil; /* struct copy */
598ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Stencil.Enabled)
599ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);
600ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* NOTE: other stencil state not reset */
601ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
602ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
603ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_TEXTURE) {
604ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      GLuint u, tgt;
605ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
606ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ActiveUnit = ctx->Texture.CurrentUnit;
607ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ClientActiveUnit = ctx->Array.ActiveTexture;
608ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->EnvMode = ctx->Texture.Unit[0].EnvMode;
609ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
610ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* Disable all texture units */
611ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
612ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
613ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
6145ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         if (ctx->Texture.Unit[u].Enabled ||
615ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             ctx->Texture.Unit[u].TexGenEnabled) {
616ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
617ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
618ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
619ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
620ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            if (ctx->Extensions.ARB_texture_cube_map)
621ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
622b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            if (ctx->Extensions.NV_texture_rectangle)
623ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
624ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            if (ctx->Extensions.OES_EGL_image_external)
625ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_set_enable(ctx, GL_TEXTURE_EXTERNAL_OES, GL_FALSE);
626ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
627ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
628ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
629ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
630ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         }
631b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      }
632ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
6335ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      /* save current texture objects for unit[0] only */
6345ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
635ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_reference_texobj(&save->CurrentTexture[tgt],
636ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                ctx->Texture.Unit[0].CurrentTex[tgt]);
637ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
638b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
639ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* set defaults for unit[0] */
640ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ActiveTextureARB(GL_TEXTURE0);
641ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ClientActiveTextureARB(GL_TEXTURE0);
642ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
643ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
644ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
645ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_TRANSFORM) {
646ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      GLuint activeTexture = ctx->Texture.CurrentUnit;
647ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
648ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             16 * sizeof(GLfloat));
649ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
650ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             16 * sizeof(GLfloat));
651ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m,
652ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             16 * sizeof(GLfloat));
653ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->MatrixMode = ctx->Transform.MatrixMode;
654ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* set 1:1 vertex:pixel coordinate transform */
655ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ActiveTextureARB(GL_TEXTURE0);
656ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_MatrixMode(GL_TEXTURE);
657ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_LoadIdentity();
658ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
659ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_MatrixMode(GL_MODELVIEW);
660ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_LoadIdentity();
661ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_MatrixMode(GL_PROJECTION);
662ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_LoadIdentity();
663ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_Ortho(0.0, ctx->DrawBuffer->Width,
664ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  0.0, ctx->DrawBuffer->Height,
665ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  -1.0, 1.0);
666ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
667ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
668ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CLIP) {
669ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
670ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Transform.ClipPlanesEnabled) {
671ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         GLuint i;
672ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
673ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
674ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         }
675ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
676ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
677ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
678ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_VERTEX) {
679ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* save vertex array object state */
680ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_array_object(ctx, &save->ArrayObj,
681ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                   ctx->Array.ArrayObj);
682ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
683ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                    ctx->Array.ArrayBufferObj);
684ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* set some default state? */
685ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
686ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
687ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_VIEWPORT) {
688ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* save viewport state */
689ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ViewportX = ctx->Viewport.X;
690ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ViewportY = ctx->Viewport.Y;
691ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ViewportW = ctx->Viewport.Width;
692ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ViewportH = ctx->Viewport.Height;
693ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* set viewport to match window size */
694ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Viewport.X != 0 ||
695ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          ctx->Viewport.Y != 0 ||
696ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          ctx->Viewport.Width != ctx->DrawBuffer->Width ||
697ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          ctx->Viewport.Height != ctx->DrawBuffer->Height) {
698ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_viewport(ctx, 0, 0,
699ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                            ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
700ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
701ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* save depth range state */
702ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->DepthNear = ctx->Viewport.Near;
703ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->DepthFar = ctx->Viewport.Far;
704ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* set depth range to default */
705ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_DepthRange(0.0, 1.0);
706ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
707ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
708ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CLAMP_FRAGMENT_COLOR) {
709ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ClampFragmentColor = ctx->Color.ClampFragmentColor;
710ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
711ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* Generally in here we want to do clamping according to whether
712ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       * it's for the pixel path (ClampFragmentColor is GL_TRUE),
713ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       * regardless of the internal implementation of the metaops.
714ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       */
715ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Color.ClampFragmentColor != GL_TRUE)
716ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
717ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
718ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
719ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CLAMP_VERTEX_COLOR) {
720ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->ClampVertexColor = ctx->Light.ClampVertexColor;
721ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
722ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* Generally in here we never want vertex color clamping --
723ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       * result clamping is only dependent on fragment clamping.
724ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       */
725ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR, GL_FALSE);
726ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
727ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
728ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CONDITIONAL_RENDER) {
729ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->CondRenderQuery = ctx->Query.CondRenderQuery;
730ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->CondRenderMode = ctx->Query.CondRenderMode;
731ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
732ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Query.CondRenderQuery)
733ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_EndConditionalRender();
734ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
735ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
736ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if FEATURE_feedback
737ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_SELECT_FEEDBACK) {
738ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->RenderMode = ctx->RenderMode;
739ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->RenderMode == GL_SELECT) {
740ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 save->Select = ctx->Select; /* struct copy */
741ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_RenderMode(GL_RENDER);
742ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      } else if (ctx->RenderMode == GL_FEEDBACK) {
743ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 save->Feedback = ctx->Feedback; /* struct copy */
744ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_RenderMode(GL_RENDER);
745ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
746ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
747ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
748ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
749ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_MULTISAMPLE) {
750ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->MultisampleEnabled = ctx->Multisample.Enabled;
751ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Multisample.Enabled)
752ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_MULTISAMPLE, GL_FALSE);
753ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
754ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
755ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /* misc */
756ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   {
757ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->Lighting = ctx->Light.Enabled;
758ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Light.Enabled)
759ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
760ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      save->RasterDiscard = ctx->RasterDiscard;
761ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->RasterDiscard)
762ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE);
763ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
764ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
765ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
766ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
767ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
768ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Leave meta state.  This is like a light-weight version of glPopAttrib().
769ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
770ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangvoid
771ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_mesa_meta_end(struct gl_context *ctx)
772ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
773ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct save_state *save = &ctx->Meta->Save[--ctx->Meta->SaveStackDepth];
774ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   const GLbitfield state = save->SavedState;
775ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
776ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_ALPHA_TEST) {
777ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
778ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
779ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef);
780ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
781ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
782ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_BLEND) {
783ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Color.BlendEnabled != save->BlendEnabled) {
784ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         if (ctx->Extensions.EXT_draw_buffers2) {
785ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            GLuint i;
786ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
787ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_set_enablei(ctx, GL_BLEND, i, (save->BlendEnabled >> i) & 1);
788ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            }
789ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         }
790ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         else {
791ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1));
792ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         }
793ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
794ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
795ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
796ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
797ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
798ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_COLOR_MASK) {
799ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      GLuint i;
800ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
801ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         if (!TEST_EQ_4V(ctx->Color.ColorMask[i], save->ColorMask[i])) {
802ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            if (i == 0) {
803ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_ColorMask(save->ColorMask[i][0], save->ColorMask[i][1],
804ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                               save->ColorMask[i][2], save->ColorMask[i][3]);
805ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            }
806ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            else {
807ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_ColorMaskIndexed(i,
808ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                      save->ColorMask[i][0],
809ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                      save->ColorMask[i][1],
810b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                      save->ColorMask[i][2],
811b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                      save->ColorMask[i][3]);
812b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            }
813b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         }
814ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
815ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
8165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
8175ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   if (state & MESA_META_DEPTH_TEST) {
818ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Depth.Test != save->Depth.Test)
819ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
820ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_DepthFunc(save->Depth.Func);
821ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_DepthMask(save->Depth.Mask);
822ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
823ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
824ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_FOG) {
825ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_FOG, save->Fog);
826ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
827ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
828ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_PIXEL_STORE) {
829ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pack = save->Pack;
830ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Unpack = save->Unpack;
831ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
832ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
833ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_PIXEL_TRANSFER) {
834ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.RedScale = save->RedScale;
835ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.RedBias = save->RedBias;
836ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.GreenScale = save->GreenScale;
8375ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      ctx->Pixel.GreenBias = save->GreenBias;
838b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      ctx->Pixel.BlueScale = save->BlueScale;
839b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      ctx->Pixel.BlueBias = save->BlueBias;
840ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.AlphaScale = save->AlphaScale;
841ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->Pixel.AlphaBias = save->AlphaBias;
8425ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      ctx->Pixel.MapColorFlag = save->MapColorFlag;
84391037db265ecdd914a26e056cf69207b4f50924ehkuang      /* XXX more state */
844ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ctx->NewState |=_NEW_PIXEL;
845ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
846ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
847ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_RASTERIZATION) {
84891037db265ecdd914a26e056cf69207b4f50924ehkuang      _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
84991037db265ecdd914a26e056cf69207b4f50924ehkuang      _mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
850ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
851b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
852ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
853ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
854ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
855ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
856ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_SCISSOR) {
857ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
858ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
859ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    save->Scissor.Width, save->Scissor.Height);
860b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   }
861ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
8625ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   if (state & MESA_META_SHADER) {
8635ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      if (ctx->Extensions.ARB_vertex_program) {
864ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
865ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                          save->VertexProgramEnabled);
866ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
8675ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                                  save->VertexProgram);
868f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang	 _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL);
869f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang      }
870ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
871ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.ARB_fragment_program) {
872f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang         _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
873f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                          save->FragmentProgramEnabled);
874f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang         _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
875f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                                  save->FragmentProgram);
8765ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang	 _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL);
877f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang      }
878ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
879ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.ARB_vertex_shader)
880b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian	 _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader);
881ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
882ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.ARB_geometry_shader4)
883ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
884ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				  save->GeometryShader);
885ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
886ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.ARB_fragment_shader)
887ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER,
888ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				  save->FragmentShader);
889ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
890ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
891ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				     save->ActiveShader);
892ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
893ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_shader_program(ctx, &save->VertexShader, NULL);
894ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_shader_program(ctx, &save->GeometryShader, NULL);
895ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_shader_program(ctx, &save->FragmentShader, NULL);
896ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_shader_program(ctx, &save->ActiveShader, NULL);
897ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
898ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
899ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_STENCIL_TEST) {
900ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      const struct gl_stencil_attrib *stencil = &save->Stencil;
901ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
902ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
903ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ClearStencil(stencil->Clear);
904ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Extensions.EXT_stencil_two_side) {
905ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
906ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                          stencil->TestTwoSide);
907ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
908ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                    ? GL_BACK : GL_FRONT);
909ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
910ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* front state */
911ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_StencilFuncSeparate(GL_FRONT,
912ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                stencil->Function[0],
913ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                stencil->Ref[0],
914ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                stencil->ValueMask[0]);
915ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
916ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
917ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                              stencil->ZFailFunc[0],
918ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                              stencil->ZPassFunc[0]);
919ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* back state */
920ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_StencilFuncSeparate(GL_BACK,
921ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                stencil->Function[1],
922ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                stencil->Ref[1],
923ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                stencil->ValueMask[1]);
924ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
925ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
926ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                              stencil->ZFailFunc[1],
927ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                              stencil->ZPassFunc[1]);
928ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
929ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
930ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_TEXTURE) {
931ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      GLuint u, tgt;
932ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
933ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ASSERT(ctx->Texture.CurrentUnit == 0);
934ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
935ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* restore texenv for unit[0] */
936ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
937ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
938ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* restore texture objects for unit[0] only */
939ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
940ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 if (ctx->Texture.Unit[0].CurrentTex[tgt] != save->CurrentTexture[tgt]) {
941ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
942ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	    _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
943ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				   save->CurrentTexture[tgt]);
944ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 }
945ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
946ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
947ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
948ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* Restore fixed function texture enables, texgen */
949ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
950ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) {
951ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
952ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	    ctx->Texture.Unit[u].Enabled = save->TexEnabled[u];
953ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 }
954ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
955ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) {
956ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
957ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	    ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u];
958ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 }
959ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
960ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
961ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* restore current unit state */
962ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit);
963ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit);
964ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
965ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
966ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_TRANSFORM) {
967ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      GLuint activeTexture = ctx->Texture.CurrentUnit;
968ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ActiveTextureARB(GL_TEXTURE0);
969ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_MatrixMode(GL_TEXTURE);
970ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_LoadMatrixf(save->TextureMatrix);
971ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
972ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
973ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_MatrixMode(GL_MODELVIEW);
974ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_LoadMatrixf(save->ModelviewMatrix);
975ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
976ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_MatrixMode(GL_PROJECTION);
977ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_LoadMatrixf(save->ProjectionMatrix);
978ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
979ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_MatrixMode(save->MatrixMode);
980ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
981ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
982ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CLIP) {
983ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (save->ClipPlanesEnabled) {
984ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         GLuint i;
985ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
986ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            if (save->ClipPlanesEnabled & (1 << i)) {
987ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
988ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            }
989ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         }
990ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
991ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
992ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
993ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_VERTEX) {
994ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* restore vertex buffer object */
995ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
996ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
997ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
998ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* restore vertex array object */
999ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_BindVertexArray(save->ArrayObj->Name);
1000ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
1001ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1002ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1003ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_VIEWPORT) {
1004ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (save->ViewportX != ctx->Viewport.X ||
1005ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          save->ViewportY != ctx->Viewport.Y ||
1006ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          save->ViewportW != ctx->Viewport.Width ||
1007ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          save->ViewportH != ctx->Viewport.Height) {
1008ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
1009ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                            save->ViewportW, save->ViewportH);
1010ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1011ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_DepthRange(save->DepthNear, save->DepthFar);
1012ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1013ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1014ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CLAMP_FRAGMENT_COLOR) {
1015ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, save->ClampFragmentColor);
1016ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1017ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1018ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CLAMP_VERTEX_COLOR) {
1019ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR, save->ClampVertexColor);
1020ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1021ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1022ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_CONDITIONAL_RENDER) {
1023ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (save->CondRenderQuery)
1024ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_BeginConditionalRender(save->CondRenderQuery->Id,
1025ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				      save->CondRenderMode);
1026ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1027ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1028ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if FEATURE_feedback
1029ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_SELECT_FEEDBACK) {
1030ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (save->RenderMode == GL_SELECT) {
1031ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_RenderMode(GL_SELECT);
1032ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 ctx->Select = save->Select;
1033ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      } else if (save->RenderMode == GL_FEEDBACK) {
1034ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 _mesa_RenderMode(GL_FEEDBACK);
1035ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang	 ctx->Feedback = save->Feedback;
1036ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1037ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1038ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
1039ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1040ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (state & MESA_META_MULTISAMPLE) {
1041ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (ctx->Multisample.Enabled != save->MultisampleEnabled)
1042ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_set_enable(ctx, GL_MULTISAMPLE, save->MultisampleEnabled);
1043ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1044ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1045ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /* misc */
1046ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (save->Lighting) {
1047ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
1048ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1049ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (save->RasterDiscard) {
1050ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE);
1051ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1052ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if FEATURE_EXT_transform_feedback
1053ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (save->TransformFeedbackNeedsResume)
1054ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_ResumeTransformFeedback();
1055ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
1056ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1057ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1058ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1059ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
1060ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Determine whether Mesa is currently in a meta state.
1061ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1062ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangGLboolean
1063ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_mesa_meta_in_progress(struct gl_context *ctx)
1064ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1065ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   return ctx->Meta->SaveStackDepth != 0;
1066ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1067ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1068ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1069ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
1070ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Convert Z from a normalized value in the range [0, 1] to an object-space
1071ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Z coordinate in [-1, +1] so that drawing at the new Z position with the
1072ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * default/identity ortho projection results in the original Z value.
1073ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z
1074ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * value comes from the clear value or raster position.
1075ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1076ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic INLINE GLfloat
1077ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuanginvert_z(GLfloat normZ)
1078ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1079ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLfloat objZ = 1.0f - 2.0f * normZ;
1080ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   return objZ;
1081ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1082ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1083ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1084ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
1085ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * One-time init for a temp_texture object.
1086ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Choose tex target, compute max tex size, etc.
1087ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1088ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void
1089ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuanginit_temp_texture(struct gl_context *ctx, struct temp_texture *tex)
1090ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1091ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /* prefer texture rectangle */
1092ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (ctx->Extensions.NV_texture_rectangle) {
1093ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->Target = GL_TEXTURE_RECTANGLE;
1094ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->MaxSize = ctx->Const.MaxTextureRectSize;
1095ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->NPOT = GL_TRUE;
1096ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1097ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   else {
1098ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* use 2D texture, NPOT if possible */
1099ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->Target = GL_TEXTURE_2D;
1100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two;
1102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   tex->MinSize = 16;  /* 16 x 16 at least */
1104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   assert(tex->MaxSize > 0);
1105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_GenTextures(1, &tex->TexObj);
1107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1108ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1109ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void
1110ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangcleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex)
1111ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (!tex->TexObj)
1113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang     return;
1114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_DeleteTextures(1, &tex->TexObj);
1115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   tex->TexObj = 0;
1116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
1120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Return pointer to temp_texture info for non-bitmap ops.
1121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * This does some one-time init if needed.
1122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic struct temp_texture *
1124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangget_temp_texture(struct gl_context *ctx)
1125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct temp_texture *tex = &ctx->Meta->TempTex;
1127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (!tex->TexObj) {
1129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      init_temp_texture(ctx, tex);
1130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   return tex;
1133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
1137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Return pointer to temp_texture info for _mesa_meta_bitmap().
1138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * We use a separate texture for bitmaps to reduce texture
1139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * allocation/deallocation.
1140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic struct temp_texture *
1142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangget_bitmap_temp_texture(struct gl_context *ctx)
1143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   struct temp_texture *tex = &ctx->Meta->Bitmap.Tex;
1145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (!tex->TexObj) {
1147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      init_temp_texture(ctx, tex);
1148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   return tex;
1151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
1155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Compute the width/height of texture needed to draw an image of the
1156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * given size.  Return a flag indicating whether the current texture
1157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * can be re-used (glTexSubImage2D) or if a new texture needs to be
1158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * allocated (glTexImage2D).
1159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Also, compute s/t texcoords for drawing.
1160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
1161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * \return GL_TRUE if new texture is needed, GL_FALSE otherwise
1162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic GLboolean
1164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangalloc_texture(struct temp_texture *tex,
1165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              GLsizei width, GLsizei height, GLenum intFormat)
1166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   GLboolean newTex = GL_FALSE;
1168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   ASSERT(width <= tex->MaxSize);
1170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   ASSERT(height <= tex->MaxSize);
1171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (width > tex->Width ||
1173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       height > tex->Height ||
1174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       intFormat != tex->IntFormat) {
1175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* alloc new texture (larger or different format) */
1176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (tex->NPOT) {
1178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         /* use non-power of two size */
1179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         tex->Width = MAX2(tex->MinSize, width);
1180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         tex->Height = MAX2(tex->MinSize, height);
1181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else {
1183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         /* find power of two size */
1184ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         GLsizei w, h;
1185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         w = h = tex->MinSize;
1186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         while (w < width)
1187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            w *= 2;
1188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         while (h < height)
1189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            h *= 2;
1190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         tex->Width = w;
1191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         tex->Height = h;
1192ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->IntFormat = intFormat;
1195ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      newTex = GL_TRUE;
1197ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1199ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /* compute texcoords */
1200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (tex->Target == GL_TEXTURE_RECTANGLE) {
1201ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->Sright = (GLfloat) width;
1202ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->Ttop = (GLfloat) height;
1203ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1204ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   else {
1205ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->Sright = (GLfloat) width / tex->Width;
1206ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tex->Ttop = (GLfloat) height / tex->Height;
1207ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1208ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   return newTex;
1210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1212ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1213ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
1214ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Setup/load texture for glCopyPixels or glBlitFramebuffer.
1215ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1216ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void
1217ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangsetup_copypix_texture(struct temp_texture *tex,
1218ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      GLboolean newTex,
1219ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      GLint srcX, GLint srcY,
1220ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      GLsizei width, GLsizei height, GLenum intFormat,
1221ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      GLenum filter)
1222ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang{
1223ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_BindTexture(tex->Target, tex->TexObj);
1224ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter);
1225ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter);
1226ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1227ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1228ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   /* copy framebuffer image to texture */
1229ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   if (newTex) {
1230ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* create new tex image */
1231ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (tex->Width == width && tex->Height == height) {
1232ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         /* create new tex with framebuffer data */
1233ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat,
1234ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                              srcX, srcY, width, height, 0);
1235ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1236ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else {
1237ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         /* create empty texture */
1238ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
1239ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                          tex->Width, tex->Height, 0,
1240ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                          intFormat, GL_UNSIGNED_BYTE, NULL);
1241ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         /* load image */
1242ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _mesa_CopyTexSubImage2D(tex->Target, 0,
1243ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                 0, 0, srcX, srcY, width, height);
1244ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1245ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1246ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   else {
12475ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      /* replace existing tex image */
1248ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_CopyTexSubImage2D(tex->Target, 0,
1249ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                              0, 0, srcX, srcY, width, height);
1250ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1251ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1252ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1253ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1254ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/**
12555ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * Setup/load texture for glDrawPixels.
12565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */
12575ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic void
12585ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangsetup_drawpix_texture(struct gl_context *ctx,
12595ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang		      struct temp_texture *tex,
12605ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                      GLboolean newTex,
12615ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                      GLenum texIntFormat,
12625ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                      GLsizei width, GLsizei height,
12635ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                      GLenum format, GLenum type,
12645ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                      const GLvoid *pixels)
12655ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang{
1266b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   _mesa_BindTexture(tex->Target, tex->TexObj);
12675ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12685ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12695ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
12705ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
12715ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   /* copy pixel data to texture */
12725ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   if (newTex) {
12735ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      /* create new tex image */
12745ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      if (tex->Width == width && tex->Height == height) {
12755ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         /* create new tex and load image data */
12765ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
1277b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                          tex->Width, tex->Height, 0, format, type, pixels);
12785ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      }
12795ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      else {
1280b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian	 struct gl_buffer_object *save_unpack_obj = NULL;
12815ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
12825ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang	 _mesa_reference_buffer_object(ctx, &save_unpack_obj,
12835ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang				       ctx->Unpack.BufferObj);
12845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang	 _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
12855ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         /* create empty texture */
12865ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
12875ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                          tex->Width, tex->Height, 0, format, type, NULL);
12885ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang	 if (save_unpack_obj != NULL)
12895ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang	    _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB,
12905ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang				save_unpack_obj->Name);
12915ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         /* load image */
12925ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_TexSubImage2D(tex->Target, 0,
1293b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                             0, 0, width, height, format, type, pixels);
1294ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1295ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1296ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   else {
1297ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      /* replace existing tex image */
1298ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _mesa_TexSubImage2D(tex->Target, 0,
1299ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                          0, 0, width, height, format, type, pixels);
1300ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang   }
1301ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
1302b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1303ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
13045ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13055ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/**
1306ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * One-time init for drawing depth pixels.
1307ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
1308ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void
13095ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuanginit_blit_depth_pixels(struct gl_context *ctx)
13105ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang{
13115ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   static const char *program =
13125ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      "!!ARBfp1.0\n"
1313ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
1314ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      "END \n";
13155ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   char program2[200];
13165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   struct blit_state *blit = &ctx->Meta->Blit;
13175ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   struct temp_texture *tex = get_temp_texture(ctx);
13185ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   const char *texTarget;
13195ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13205ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   assert(blit->DepthFP == 0);
13215ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13225ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   /* replace %s with "RECT" or "2D" */
13235ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   assert(strlen(program) + 4 < sizeof(program2));
13245ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   if (tex->Target == GL_TEXTURE_RECTANGLE)
13255ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      texTarget = "RECT";
13265ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   else
13275ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      texTarget = "2D";
13285ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_snprintf(program2, sizeof(program2), program, texTarget);
13295ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13305ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_GenPrograms(1, &blit->DepthFP);
13315ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
13325ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang   _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
13335ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                          strlen(program2), (const GLubyte *) program2);
13345ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang}
13355ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13365ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13375ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/**
13385ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * Try to do a glBlitFramebuffer using no-copy texturing.
13395ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * We can do this when the src renderbuffer is actually a texture.
13405ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * But if the src buffer == dst buffer we cannot do this.
13415ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang *
13425ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * \return new buffer mask indicating the buffers left to blit using the
13435ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang *         normal path.
13445ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */
13455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic GLbitfield
13465ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangblitframebuffer_texture(struct gl_context *ctx,
13475ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1348b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1349b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                        GLbitfield mask, GLenum filter)
1350b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1351b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   if (mask & GL_COLOR_BUFFER_BIT) {
1352b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
1353b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
1354b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      const struct gl_renderbuffer_attachment *drawAtt =
13555ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
13565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      const struct gl_renderbuffer_attachment *readAtt =
13575ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         &readFb->Attachment[readFb->_ColorReadBufferIndex];
13585ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13595ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      if (readAtt && readAtt->Texture) {
13605ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         const struct gl_texture_object *texObj = readAtt->Texture;
1361b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         const GLuint srcLevel = readAtt->TextureLevel;
1362b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         const GLint baseLevelSave = texObj->BaseLevel;
1363b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         const GLint maxLevelSave = texObj->MaxLevel;
1364b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         const GLenum fbo_srgb_save = ctx->Color.sRGBEnabled;
1365b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         const GLenum target = texObj->Target;
1366b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         GLuint sampler, samplerSave =
1367b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
13685ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang            ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
13695ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13705ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         if (drawAtt->Texture == readAtt->Texture) {
13715ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang            /* Can't use same texture as both the source and dest.  We need
1372b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian             * to handle overlapping blits and besides, some hw may not
1373b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian             * support this.
1374b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian             */
1375b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            return mask;
1376b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         }
1377b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1378b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) {
13795ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang            /* Can't handle other texture types at this time */
13805ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang            return mask;
13815ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         }
13825ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13835ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_GenSamplers(1, &sampler);
13845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler);
13855ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13865ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         /*
13875ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         printf("Blit from texture!\n");
13885ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         printf("  srcAtt %p  dstAtt %p\n", readAtt, drawAtt);
13895ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         printf("  srcTex %p  dstText %p\n", texObj, drawAtt->Texture);
13905ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         */
13915ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
13925ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         /* Prepare src texture state */
13935ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_BindTexture(target, texObj->Name);
13945ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter);
1395b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter);
13965ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         if (target != GL_TEXTURE_RECTANGLE_ARB) {
13975ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang            _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
13985ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang            _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
13995ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         }
14005ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
14015ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang         _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
14025ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
14035ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang	 /* Always do our blits with no sRGB decode or encode.*/
1404b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian	 if (ctx->Extensions.EXT_texture_sRGB_decode) {
14055ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang	    _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT,
1406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang				GL_SKIP_DECODE_EXT);
1407	 }
1408         if (ctx->Extensions.EXT_framebuffer_sRGB) {
1409            _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE);
1410         }
1411
1412         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1413         _mesa_set_enable(ctx, target, GL_TRUE);
1414
1415         /* Prepare vertex data (the VBO was previously created and bound) */
1416         {
1417            struct vertex {
1418               GLfloat x, y, s, t;
1419            };
1420            struct vertex verts[4];
1421            GLfloat s0, t0, s1, t1;
1422
1423            if (target == GL_TEXTURE_2D) {
1424               const struct gl_texture_image *texImage
1425                   = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
1426               s0 = srcX0 / (float) texImage->Width;
1427               s1 = srcX1 / (float) texImage->Width;
1428               t0 = srcY0 / (float) texImage->Height;
1429               t1 = srcY1 / (float) texImage->Height;
1430            }
1431            else {
1432               assert(target == GL_TEXTURE_RECTANGLE_ARB);
1433               s0 = srcX0;
1434               s1 = srcX1;
1435               t0 = srcY0;
1436               t1 = srcY1;
1437            }
1438
1439            verts[0].x = (GLfloat) dstX0;
1440            verts[0].y = (GLfloat) dstY0;
1441            verts[1].x = (GLfloat) dstX1;
1442            verts[1].y = (GLfloat) dstY0;
1443            verts[2].x = (GLfloat) dstX1;
1444            verts[2].y = (GLfloat) dstY1;
1445            verts[3].x = (GLfloat) dstX0;
1446            verts[3].y = (GLfloat) dstY1;
1447
1448            verts[0].s = s0;
1449            verts[0].t = t0;
1450            verts[1].s = s1;
1451            verts[1].t = t0;
1452            verts[2].s = s1;
1453            verts[2].t = t1;
1454            verts[3].s = s0;
1455            verts[3].t = t1;
1456
1457            _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
1458         }
1459
1460         _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1461
1462         /* Restore texture object state, the texture binding will
1463          * be restored by _mesa_meta_end().
1464          */
1465         if (target != GL_TEXTURE_RECTANGLE_ARB) {
1466            _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
1467            _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
1468         }
1469	 if (ctx->Extensions.EXT_framebuffer_sRGB && fbo_srgb_save) {
1470	    _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE);
1471	 }
1472
1473         _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);
1474         _mesa_DeleteSamplers(1, &sampler);
1475
1476         /* Done with color buffer */
1477         mask &= ~GL_COLOR_BUFFER_BIT;
1478      }
1479   }
1480
1481   return mask;
1482}
1483
1484
1485/**
1486 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
1487 * of texture mapping and polygon rendering.
1488 */
1489void
1490_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
1491                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1492                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1493                           GLbitfield mask, GLenum filter)
1494{
1495   struct blit_state *blit = &ctx->Meta->Blit;
1496   struct temp_texture *tex = get_temp_texture(ctx);
1497   const GLsizei maxTexSize = tex->MaxSize;
1498   const GLint srcX = MIN2(srcX0, srcX1);
1499   const GLint srcY = MIN2(srcY0, srcY1);
1500   const GLint srcW = abs(srcX1 - srcX0);
1501   const GLint srcH = abs(srcY1 - srcY0);
1502   const GLboolean srcFlipX = srcX1 < srcX0;
1503   const GLboolean srcFlipY = srcY1 < srcY0;
1504   struct vertex {
1505      GLfloat x, y, s, t;
1506   };
1507   struct vertex verts[4];
1508   GLboolean newTex;
1509
1510   /* In addition to falling back if the blit size is larger than the maximum
1511    * texture size, fallback if the source is multisampled.  This fallback can
1512    * be removed once Mesa gets support ARB_texture_multisample.
1513    */
1514   if (srcW > maxTexSize || srcH > maxTexSize
1515       || ctx->ReadBuffer->Visual.samples > 0) {
1516      /* XXX avoid this fallback */
1517      _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
1518                              dstX0, dstY0, dstX1, dstY1, mask, filter);
1519      return;
1520   }
1521
1522   if (srcFlipX) {
1523      GLint tmp = dstX0;
1524      dstX0 = dstX1;
1525      dstX1 = tmp;
1526   }
1527
1528   if (srcFlipY) {
1529      GLint tmp = dstY0;
1530      dstY0 = dstY1;
1531      dstY1 = tmp;
1532   }
1533
1534   /* only scissor effects blit so save/clear all other relevant state */
1535   _mesa_meta_begin(ctx, ~MESA_META_SCISSOR);
1536
1537   if (blit->ArrayObj == 0) {
1538      /* one-time setup */
1539
1540      /* create vertex array object */
1541      _mesa_GenVertexArrays(1, &blit->ArrayObj);
1542      _mesa_BindVertexArray(blit->ArrayObj);
1543
1544      /* create vertex array buffer */
1545      _mesa_GenBuffersARB(1, &blit->VBO);
1546      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
1547      _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
1548                          NULL, GL_DYNAMIC_DRAW_ARB);
1549
1550      /* setup vertex arrays */
1551      _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
1552      _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
1553      _mesa_EnableClientState(GL_VERTEX_ARRAY);
1554      _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
1555   }
1556   else {
1557      _mesa_BindVertexArray(blit->ArrayObj);
1558      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
1559   }
1560
1561   /* Try faster, direct texture approach first */
1562   mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1,
1563                                  dstX0, dstY0, dstX1, dstY1, mask, filter);
1564   if (mask == 0x0) {
1565      _mesa_meta_end(ctx);
1566      return;
1567   }
1568
1569   /* Continue with "normal" approach which involves copying the src rect
1570    * into a temporary texture and is "blitted" by drawing a textured quad.
1571    */
1572
1573   newTex = alloc_texture(tex, srcW, srcH, GL_RGBA);
1574
1575   /* vertex positions/texcoords (after texture allocation!) */
1576   {
1577      verts[0].x = (GLfloat) dstX0;
1578      verts[0].y = (GLfloat) dstY0;
1579      verts[1].x = (GLfloat) dstX1;
1580      verts[1].y = (GLfloat) dstY0;
1581      verts[2].x = (GLfloat) dstX1;
1582      verts[2].y = (GLfloat) dstY1;
1583      verts[3].x = (GLfloat) dstX0;
1584      verts[3].y = (GLfloat) dstY1;
1585
1586      verts[0].s = 0.0F;
1587      verts[0].t = 0.0F;
1588      verts[1].s = tex->Sright;
1589      verts[1].t = 0.0F;
1590      verts[2].s = tex->Sright;
1591      verts[2].t = tex->Ttop;
1592      verts[3].s = 0.0F;
1593      verts[3].t = tex->Ttop;
1594
1595      /* upload new vertex data */
1596      _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
1597   }
1598
1599   _mesa_set_enable(ctx, tex->Target, GL_TRUE);
1600
1601   if (mask & GL_COLOR_BUFFER_BIT) {
1602      setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH,
1603                            GL_RGBA, filter);
1604      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1605      mask &= ~GL_COLOR_BUFFER_BIT;
1606   }
1607
1608   if (mask & GL_DEPTH_BUFFER_BIT) {
1609      GLuint *tmp = (GLuint *) malloc(srcW * srcH * sizeof(GLuint));
1610      if (tmp) {
1611         if (!blit->DepthFP)
1612            init_blit_depth_pixels(ctx);
1613
1614         /* maybe change tex format here */
1615         newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT);
1616
1617         _mesa_ReadPixels(srcX, srcY, srcW, srcH,
1618                          GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
1619
1620         setup_drawpix_texture(ctx, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
1621                               GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
1622
1623         _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
1624         _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
1625         _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1626         _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
1627         _mesa_DepthFunc(GL_ALWAYS);
1628         _mesa_DepthMask(GL_TRUE);
1629
1630         _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1631         mask &= ~GL_DEPTH_BUFFER_BIT;
1632
1633         free(tmp);
1634      }
1635   }
1636
1637   if (mask & GL_STENCIL_BUFFER_BIT) {
1638      /* XXX can't easily do stencil */
1639   }
1640
1641   _mesa_set_enable(ctx, tex->Target, GL_FALSE);
1642
1643   _mesa_meta_end(ctx);
1644
1645   if (mask) {
1646      _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
1647                              dstX0, dstY0, dstX1, dstY1, mask, filter);
1648   }
1649}
1650
1651static void
1652meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit)
1653{
1654   if (blit->ArrayObj) {
1655      _mesa_DeleteVertexArraysAPPLE(1, &blit->ArrayObj);
1656      blit->ArrayObj = 0;
1657      _mesa_DeleteBuffersARB(1, &blit->VBO);
1658      blit->VBO = 0;
1659   }
1660   if (blit->DepthFP) {
1661      _mesa_DeletePrograms(1, &blit->DepthFP);
1662      blit->DepthFP = 0;
1663   }
1664}
1665
1666
1667/**
1668 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
1669 */
1670void
1671_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers)
1672{
1673   struct clear_state *clear = &ctx->Meta->Clear;
1674   struct vertex {
1675      GLfloat x, y, z, r, g, b, a;
1676   };
1677   struct vertex verts[4];
1678   /* save all state but scissor, pixel pack/unpack */
1679   GLbitfield metaSave = (MESA_META_ALL -
1680			  MESA_META_SCISSOR -
1681			  MESA_META_PIXEL_STORE -
1682			  MESA_META_CONDITIONAL_RENDER);
1683   const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
1684
1685   if (buffers & BUFFER_BITS_COLOR) {
1686      /* if clearing color buffers, don't save/restore colormask */
1687      metaSave -= MESA_META_COLOR_MASK;
1688   }
1689
1690   _mesa_meta_begin(ctx, metaSave);
1691
1692   if (clear->ArrayObj == 0) {
1693      /* one-time setup */
1694
1695      /* create vertex array object */
1696      _mesa_GenVertexArrays(1, &clear->ArrayObj);
1697      _mesa_BindVertexArray(clear->ArrayObj);
1698
1699      /* create vertex array buffer */
1700      _mesa_GenBuffersARB(1, &clear->VBO);
1701      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1702
1703      /* setup vertex arrays */
1704      _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
1705      _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
1706      _mesa_EnableClientState(GL_VERTEX_ARRAY);
1707      _mesa_EnableClientState(GL_COLOR_ARRAY);
1708   }
1709   else {
1710      _mesa_BindVertexArray(clear->ArrayObj);
1711      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1712   }
1713
1714   /* GL_COLOR_BUFFER_BIT */
1715   if (buffers & BUFFER_BITS_COLOR) {
1716      /* leave colormask, glDrawBuffer state as-is */
1717
1718      /* Clears never have the color clamped. */
1719      _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
1720   }
1721   else {
1722      ASSERT(metaSave & MESA_META_COLOR_MASK);
1723      _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1724   }
1725
1726   /* GL_DEPTH_BUFFER_BIT */
1727   if (buffers & BUFFER_BIT_DEPTH) {
1728      _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
1729      _mesa_DepthFunc(GL_ALWAYS);
1730      _mesa_DepthMask(GL_TRUE);
1731   }
1732   else {
1733      assert(!ctx->Depth.Test);
1734   }
1735
1736   /* GL_STENCIL_BUFFER_BIT */
1737   if (buffers & BUFFER_BIT_STENCIL) {
1738      _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
1739      _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
1740                              GL_REPLACE, GL_REPLACE, GL_REPLACE);
1741      _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
1742                                ctx->Stencil.Clear & stencilMax,
1743                                ctx->Stencil.WriteMask[0]);
1744   }
1745   else {
1746      assert(!ctx->Stencil.Enabled);
1747   }
1748
1749   /* vertex positions/colors */
1750   {
1751      const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
1752      const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
1753      const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
1754      const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
1755      const GLfloat z = invert_z(ctx->Depth.Clear);
1756      GLuint i;
1757
1758      verts[0].x = x0;
1759      verts[0].y = y0;
1760      verts[0].z = z;
1761      verts[1].x = x1;
1762      verts[1].y = y0;
1763      verts[1].z = z;
1764      verts[2].x = x1;
1765      verts[2].y = y1;
1766      verts[2].z = z;
1767      verts[3].x = x0;
1768      verts[3].y = y1;
1769      verts[3].z = z;
1770
1771      /* vertex colors */
1772      for (i = 0; i < 4; i++) {
1773         verts[i].r = ctx->Color.ClearColor.f[0];
1774         verts[i].g = ctx->Color.ClearColor.f[1];
1775         verts[i].b = ctx->Color.ClearColor.f[2];
1776         verts[i].a = ctx->Color.ClearColor.f[3];
1777      }
1778
1779      /* upload new vertex data */
1780      _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
1781			  GL_DYNAMIC_DRAW_ARB);
1782   }
1783
1784   /* draw quad */
1785   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1786
1787   _mesa_meta_end(ctx);
1788}
1789
1790static void
1791meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
1792{
1793   const char *vs_source =
1794      "attribute vec4 position;\n"
1795      "void main()\n"
1796      "{\n"
1797      "   gl_Position = position;\n"
1798      "}\n";
1799   const char *fs_source =
1800      "uniform vec4 color;\n"
1801      "void main()\n"
1802      "{\n"
1803      "   gl_FragColor = color;\n"
1804      "}\n";
1805   const char *vs_int_source =
1806      "#version 130\n"
1807      "attribute vec4 position;\n"
1808      "void main()\n"
1809      "{\n"
1810      "   gl_Position = position;\n"
1811      "}\n";
1812   const char *fs_int_source =
1813      "#version 130\n"
1814      "uniform ivec4 color;\n"
1815      "out ivec4 out_color;\n"
1816      "\n"
1817      "void main()\n"
1818      "{\n"
1819      "   out_color = color;\n"
1820      "}\n";
1821   GLuint vs, fs;
1822
1823   if (clear->ArrayObj != 0)
1824      return;
1825
1826   /* create vertex array object */
1827   _mesa_GenVertexArrays(1, &clear->ArrayObj);
1828   _mesa_BindVertexArray(clear->ArrayObj);
1829
1830   /* create vertex array buffer */
1831   _mesa_GenBuffersARB(1, &clear->VBO);
1832   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1833
1834   /* setup vertex arrays */
1835   _mesa_VertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
1836   _mesa_EnableVertexAttribArrayARB(0);
1837
1838   vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER);
1839   _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL);
1840   _mesa_CompileShaderARB(vs);
1841
1842   fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER);
1843   _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL);
1844   _mesa_CompileShaderARB(fs);
1845
1846   clear->ShaderProg = _mesa_CreateProgramObjectARB();
1847   _mesa_AttachShader(clear->ShaderProg, fs);
1848   _mesa_DeleteObjectARB(fs);
1849   _mesa_AttachShader(clear->ShaderProg, vs);
1850   _mesa_DeleteObjectARB(vs);
1851   _mesa_BindAttribLocationARB(clear->ShaderProg, 0, "position");
1852   _mesa_LinkProgramARB(clear->ShaderProg);
1853
1854   clear->ColorLocation = _mesa_GetUniformLocationARB(clear->ShaderProg,
1855						      "color");
1856
1857   if (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) {
1858      vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source);
1859      fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source);
1860
1861      clear->IntegerShaderProg = _mesa_CreateProgramObjectARB();
1862      _mesa_AttachShader(clear->IntegerShaderProg, fs);
1863      _mesa_DeleteObjectARB(fs);
1864      _mesa_AttachShader(clear->IntegerShaderProg, vs);
1865      _mesa_DeleteObjectARB(vs);
1866      _mesa_BindAttribLocationARB(clear->IntegerShaderProg, 0, "position");
1867
1868      /* Note that user-defined out attributes get automatically assigned
1869       * locations starting from 0, so we don't need to explicitly
1870       * BindFragDataLocation to 0.
1871       */
1872
1873      link_program_with_debug(ctx, clear->IntegerShaderProg);
1874
1875      clear->IntegerColorLocation =
1876	 _mesa_GetUniformLocationARB(clear->IntegerShaderProg, "color");
1877   }
1878}
1879
1880static void
1881meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear)
1882{
1883   if (clear->ArrayObj == 0)
1884      return;
1885   _mesa_DeleteVertexArraysAPPLE(1, &clear->ArrayObj);
1886   clear->ArrayObj = 0;
1887   _mesa_DeleteBuffersARB(1, &clear->VBO);
1888   clear->VBO = 0;
1889   _mesa_DeleteObjectARB(clear->ShaderProg);
1890   clear->ShaderProg = 0;
1891
1892   if (clear->IntegerShaderProg) {
1893      _mesa_DeleteObjectARB(clear->IntegerShaderProg);
1894      clear->IntegerShaderProg = 0;
1895   }
1896}
1897
1898/**
1899 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
1900 */
1901void
1902_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
1903{
1904   struct clear_state *clear = &ctx->Meta->Clear;
1905   GLbitfield metaSave;
1906   const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
1907   struct gl_framebuffer *fb = ctx->DrawBuffer;
1908   const float x0 = ((float)fb->_Xmin / fb->Width)  * 2.0f - 1.0f;
1909   const float y0 = ((float)fb->_Ymin / fb->Height) * 2.0f - 1.0f;
1910   const float x1 = ((float)fb->_Xmax / fb->Width)  * 2.0f - 1.0f;
1911   const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0f - 1.0f;
1912   const float z = -invert_z(ctx->Depth.Clear);
1913   struct vertex {
1914      GLfloat x, y, z;
1915   } verts[4];
1916
1917   metaSave = (MESA_META_ALPHA_TEST |
1918	       MESA_META_BLEND |
1919	       MESA_META_DEPTH_TEST |
1920	       MESA_META_RASTERIZATION |
1921	       MESA_META_SHADER |
1922	       MESA_META_STENCIL_TEST |
1923	       MESA_META_VERTEX |
1924	       MESA_META_VIEWPORT |
1925	       MESA_META_CLIP |
1926	       MESA_META_CLAMP_FRAGMENT_COLOR |
1927               MESA_META_MULTISAMPLE);
1928
1929   if (!(buffers & BUFFER_BITS_COLOR)) {
1930      /* We'll use colormask to disable color writes.  Otherwise,
1931       * respect color mask
1932       */
1933      metaSave |= MESA_META_COLOR_MASK;
1934   }
1935
1936   _mesa_meta_begin(ctx, metaSave);
1937
1938   meta_glsl_clear_init(ctx, clear);
1939
1940   if (fb->_IntegerColor) {
1941      _mesa_UseProgramObjectARB(clear->IntegerShaderProg);
1942      _mesa_Uniform4ivARB(clear->IntegerColorLocation, 1,
1943			  ctx->Color.ClearColor.i);
1944   } else {
1945      _mesa_UseProgramObjectARB(clear->ShaderProg);
1946      _mesa_Uniform4fvARB(clear->ColorLocation, 1,
1947			  ctx->Color.ClearColor.f);
1948   }
1949
1950   _mesa_BindVertexArray(clear->ArrayObj);
1951   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1952
1953   /* GL_COLOR_BUFFER_BIT */
1954   if (buffers & BUFFER_BITS_COLOR) {
1955      /* leave colormask, glDrawBuffer state as-is */
1956
1957      /* Clears never have the color clamped. */
1958      _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
1959   }
1960   else {
1961      ASSERT(metaSave & MESA_META_COLOR_MASK);
1962      _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1963   }
1964
1965   /* GL_DEPTH_BUFFER_BIT */
1966   if (buffers & BUFFER_BIT_DEPTH) {
1967      _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
1968      _mesa_DepthFunc(GL_ALWAYS);
1969      _mesa_DepthMask(GL_TRUE);
1970   }
1971   else {
1972      assert(!ctx->Depth.Test);
1973   }
1974
1975   /* GL_STENCIL_BUFFER_BIT */
1976   if (buffers & BUFFER_BIT_STENCIL) {
1977      _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
1978      _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
1979                              GL_REPLACE, GL_REPLACE, GL_REPLACE);
1980      _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
1981                                ctx->Stencil.Clear & stencilMax,
1982                                ctx->Stencil.WriteMask[0]);
1983   }
1984   else {
1985      assert(!ctx->Stencil.Enabled);
1986   }
1987
1988   /* vertex positions */
1989   verts[0].x = x0;
1990   verts[0].y = y0;
1991   verts[0].z = z;
1992   verts[1].x = x1;
1993   verts[1].y = y0;
1994   verts[1].z = z;
1995   verts[2].x = x1;
1996   verts[2].y = y1;
1997   verts[2].z = z;
1998   verts[3].x = x0;
1999   verts[3].y = y1;
2000   verts[3].z = z;
2001
2002   /* upload new vertex data */
2003   _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
2004		       GL_DYNAMIC_DRAW_ARB);
2005
2006   /* draw quad */
2007   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2008
2009   _mesa_meta_end(ctx);
2010}
2011
2012/**
2013 * Meta implementation of ctx->Driver.CopyPixels() in terms
2014 * of texture mapping and polygon rendering and GLSL shaders.
2015 */
2016void
2017_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
2018                      GLsizei width, GLsizei height,
2019                      GLint dstX, GLint dstY, GLenum type)
2020{
2021   struct copypix_state *copypix = &ctx->Meta->CopyPix;
2022   struct temp_texture *tex = get_temp_texture(ctx);
2023   struct vertex {
2024      GLfloat x, y, z, s, t;
2025   };
2026   struct vertex verts[4];
2027   GLboolean newTex;
2028   GLenum intFormat = GL_RGBA;
2029
2030   if (type != GL_COLOR ||
2031       ctx->_ImageTransferState ||
2032       ctx->Fog.Enabled ||
2033       width > tex->MaxSize ||
2034       height > tex->MaxSize) {
2035      /* XXX avoid this fallback */
2036      _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type);
2037      return;
2038   }
2039
2040   /* Most GL state applies to glCopyPixels, but a there's a few things
2041    * we need to override:
2042    */
2043   _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION |
2044                          MESA_META_SHADER |
2045                          MESA_META_TEXTURE |
2046                          MESA_META_TRANSFORM |
2047                          MESA_META_CLIP |
2048                          MESA_META_VERTEX |
2049                          MESA_META_VIEWPORT));
2050
2051   if (copypix->ArrayObj == 0) {
2052      /* one-time setup */
2053
2054      /* create vertex array object */
2055      _mesa_GenVertexArrays(1, &copypix->ArrayObj);
2056      _mesa_BindVertexArray(copypix->ArrayObj);
2057
2058      /* create vertex array buffer */
2059      _mesa_GenBuffersARB(1, &copypix->VBO);
2060      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
2061      _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
2062                          NULL, GL_DYNAMIC_DRAW_ARB);
2063
2064      /* setup vertex arrays */
2065      _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
2066      _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
2067      _mesa_EnableClientState(GL_VERTEX_ARRAY);
2068      _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
2069   }
2070   else {
2071      _mesa_BindVertexArray(copypix->ArrayObj);
2072      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
2073   }
2074
2075   newTex = alloc_texture(tex, width, height, intFormat);
2076
2077   /* vertex positions, texcoords (after texture allocation!) */
2078   {
2079      const GLfloat dstX0 = (GLfloat) dstX;
2080      const GLfloat dstY0 = (GLfloat) dstY;
2081      const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
2082      const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
2083      const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
2084
2085      verts[0].x = dstX0;
2086      verts[0].y = dstY0;
2087      verts[0].z = z;
2088      verts[0].s = 0.0F;
2089      verts[0].t = 0.0F;
2090      verts[1].x = dstX1;
2091      verts[1].y = dstY0;
2092      verts[1].z = z;
2093      verts[1].s = tex->Sright;
2094      verts[1].t = 0.0F;
2095      verts[2].x = dstX1;
2096      verts[2].y = dstY1;
2097      verts[2].z = z;
2098      verts[2].s = tex->Sright;
2099      verts[2].t = tex->Ttop;
2100      verts[3].x = dstX0;
2101      verts[3].y = dstY1;
2102      verts[3].z = z;
2103      verts[3].s = 0.0F;
2104      verts[3].t = tex->Ttop;
2105
2106      /* upload new vertex data */
2107      _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
2108   }
2109
2110   /* Alloc/setup texture */
2111   setup_copypix_texture(tex, newTex, srcX, srcY, width, height,
2112                         GL_RGBA, GL_NEAREST);
2113
2114   _mesa_set_enable(ctx, tex->Target, GL_TRUE);
2115
2116   /* draw textured quad */
2117   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2118
2119   _mesa_set_enable(ctx, tex->Target, GL_FALSE);
2120
2121   _mesa_meta_end(ctx);
2122}
2123
2124
2125
2126/**
2127 * When the glDrawPixels() image size is greater than the max rectangle
2128 * texture size we use this function to break the glDrawPixels() image
2129 * into tiles which fit into the max texture size.
2130 */
2131static void
2132tiled_draw_pixels(struct gl_context *ctx,
2133                  GLint tileSize,
2134                  GLint x, GLint y, GLsizei width, GLsizei height,
2135                  GLenum format, GLenum type,
2136                  const struct gl_pixelstore_attrib *unpack,
2137                  const GLvoid *pixels)
2138{
2139   struct gl_pixelstore_attrib tileUnpack = *unpack;
2140   GLint i, j;
2141
2142   if (tileUnpack.RowLength == 0)
2143      tileUnpack.RowLength = width;
2144
2145   for (i = 0; i < width; i += tileSize) {
2146      const GLint tileWidth = MIN2(tileSize, width - i);
2147      const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX);
2148
2149      tileUnpack.SkipPixels = unpack->SkipPixels + i;
2150
2151      for (j = 0; j < height; j += tileSize) {
2152         const GLint tileHeight = MIN2(tileSize, height - j);
2153         const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY);
2154
2155         tileUnpack.SkipRows = unpack->SkipRows + j;
2156
2157         _mesa_meta_DrawPixels(ctx, tileX, tileY, tileWidth, tileHeight,
2158                               format, type, &tileUnpack, pixels);
2159      }
2160   }
2161}
2162
2163
2164/**
2165 * One-time init for drawing stencil pixels.
2166 */
2167static void
2168init_draw_stencil_pixels(struct gl_context *ctx)
2169{
2170   /* This program is run eight times, once for each stencil bit.
2171    * The stencil values to draw are found in an 8-bit alpha texture.
2172    * We read the texture/stencil value and test if bit 'b' is set.
2173    * If the bit is not set, use KIL to kill the fragment.
2174    * Finally, we use the stencil test to update the stencil buffer.
2175    *
2176    * The basic algorithm for checking if a bit is set is:
2177    *   if (is_odd(value / (1 << bit)))
2178    *      result is one (or non-zero).
2179    *   else
2180    *      result is zero.
2181    * The program parameter contains three values:
2182    *   parm.x = 255 / (1 << bit)
2183    *   parm.y = 0.5
2184    *   parm.z = 0.0
2185    */
2186   static const char *program =
2187      "!!ARBfp1.0\n"
2188      "PARAM parm = program.local[0]; \n"
2189      "TEMP t; \n"
2190      "TEX t, fragment.texcoord[0], texture[0], %s; \n"   /* NOTE %s here! */
2191      "# t = t * 255 / bit \n"
2192      "MUL t.x, t.a, parm.x; \n"
2193      "# t = (int) t \n"
2194      "FRC t.y, t.x; \n"
2195      "SUB t.x, t.x, t.y; \n"
2196      "# t = t * 0.5 \n"
2197      "MUL t.x, t.x, parm.y; \n"
2198      "# t = fract(t.x) \n"
2199      "FRC t.x, t.x; # if t.x != 0, then the bit is set \n"
2200      "# t.x = (t.x == 0 ? 1 : 0) \n"
2201      "SGE t.x, -t.x, parm.z; \n"
2202      "KIL -t.x; \n"
2203      "# for debug only \n"
2204      "#MOV result.color, t.x; \n"
2205      "END \n";
2206   char program2[1000];
2207   struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
2208   struct temp_texture *tex = get_temp_texture(ctx);
2209   const char *texTarget;
2210
2211   assert(drawpix->StencilFP == 0);
2212
2213   /* replace %s with "RECT" or "2D" */
2214   assert(strlen(program) + 4 < sizeof(program2));
2215   if (tex->Target == GL_TEXTURE_RECTANGLE)
2216      texTarget = "RECT";
2217   else
2218      texTarget = "2D";
2219   _mesa_snprintf(program2, sizeof(program2), program, texTarget);
2220
2221   _mesa_GenPrograms(1, &drawpix->StencilFP);
2222   _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
2223   _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
2224                          strlen(program2), (const GLubyte *) program2);
2225}
2226
2227
2228/**
2229 * One-time init for drawing depth pixels.
2230 */
2231static void
2232init_draw_depth_pixels(struct gl_context *ctx)
2233{
2234   static const char *program =
2235      "!!ARBfp1.0\n"
2236      "PARAM color = program.local[0]; \n"
2237      "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
2238      "MOV result.color, color; \n"
2239      "END \n";
2240   char program2[200];
2241   struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
2242   struct temp_texture *tex = get_temp_texture(ctx);
2243   const char *texTarget;
2244
2245   assert(drawpix->DepthFP == 0);
2246
2247   /* replace %s with "RECT" or "2D" */
2248   assert(strlen(program) + 4 < sizeof(program2));
2249   if (tex->Target == GL_TEXTURE_RECTANGLE)
2250      texTarget = "RECT";
2251   else
2252      texTarget = "2D";
2253   _mesa_snprintf(program2, sizeof(program2), program, texTarget);
2254
2255   _mesa_GenPrograms(1, &drawpix->DepthFP);
2256   _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
2257   _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
2258                          strlen(program2), (const GLubyte *) program2);
2259}
2260
2261
2262/**
2263 * Meta implementation of ctx->Driver.DrawPixels() in terms
2264 * of texture mapping and polygon rendering.
2265 */
2266void
2267_mesa_meta_DrawPixels(struct gl_context *ctx,
2268                      GLint x, GLint y, GLsizei width, GLsizei height,
2269                      GLenum format, GLenum type,
2270                      const struct gl_pixelstore_attrib *unpack,
2271                      const GLvoid *pixels)
2272{
2273   struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
2274   struct temp_texture *tex = get_temp_texture(ctx);
2275   const struct gl_pixelstore_attrib unpackSave = ctx->Unpack;
2276   const GLuint origStencilMask = ctx->Stencil.WriteMask[0];
2277   struct vertex {
2278      GLfloat x, y, z, s, t;
2279   };
2280   struct vertex verts[4];
2281   GLenum texIntFormat;
2282   GLboolean fallback, newTex;
2283   GLbitfield metaExtraSave = 0x0;
2284   GLuint vbo;
2285
2286   /*
2287    * Determine if we can do the glDrawPixels with texture mapping.
2288    */
2289   fallback = GL_FALSE;
2290   if (ctx->Fog.Enabled) {
2291      fallback = GL_TRUE;
2292   }
2293
2294   if (_mesa_is_color_format(format)) {
2295      /* use more compact format when possible */
2296      /* XXX disable special case for GL_LUMINANCE for now to work around
2297       * apparent i965 driver bug (see bug #23670).
2298       */
2299      if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA)
2300         texIntFormat = format;
2301      else
2302         texIntFormat = GL_RGBA;
2303
2304      /* If we're not supposed to clamp the resulting color, then just
2305       * promote our texture to fully float.  We could do better by
2306       * just going for the matching set of channels, in floating
2307       * point.
2308       */
2309      if (ctx->Color.ClampFragmentColor != GL_TRUE &&
2310	  ctx->Extensions.ARB_texture_float)
2311	 texIntFormat = GL_RGBA32F;
2312   }
2313   else if (_mesa_is_stencil_format(format)) {
2314      if (ctx->Extensions.ARB_fragment_program &&
2315          ctx->Pixel.IndexShift == 0 &&
2316          ctx->Pixel.IndexOffset == 0 &&
2317          type == GL_UNSIGNED_BYTE) {
2318         /* We'll store stencil as alpha.  This only works for GLubyte
2319          * image data because of how incoming values are mapped to alpha
2320          * in [0,1].
2321          */
2322         texIntFormat = GL_ALPHA;
2323         metaExtraSave = (MESA_META_COLOR_MASK |
2324                          MESA_META_DEPTH_TEST |
2325                          MESA_META_PIXEL_TRANSFER |
2326                          MESA_META_SHADER |
2327                          MESA_META_STENCIL_TEST);
2328      }
2329      else {
2330         fallback = GL_TRUE;
2331      }
2332   }
2333   else if (_mesa_is_depth_format(format)) {
2334      if (ctx->Extensions.ARB_depth_texture &&
2335          ctx->Extensions.ARB_fragment_program) {
2336         texIntFormat = GL_DEPTH_COMPONENT;
2337         metaExtraSave = (MESA_META_SHADER);
2338      }
2339      else {
2340         fallback = GL_TRUE;
2341      }
2342   }
2343   else {
2344      fallback = GL_TRUE;
2345   }
2346
2347   if (fallback) {
2348      _swrast_DrawPixels(ctx, x, y, width, height,
2349                         format, type, unpack, pixels);
2350      return;
2351   }
2352
2353   /*
2354    * Check image size against max texture size, draw as tiles if needed.
2355    */
2356   if (width > tex->MaxSize || height > tex->MaxSize) {
2357      tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height,
2358                        format, type, unpack, pixels);
2359      return;
2360   }
2361
2362   /* Most GL state applies to glDrawPixels (like blending, stencil, etc),
2363    * but a there's a few things we need to override:
2364    */
2365   _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION |
2366                          MESA_META_SHADER |
2367                          MESA_META_TEXTURE |
2368                          MESA_META_TRANSFORM |
2369                          MESA_META_CLIP |
2370                          MESA_META_VERTEX |
2371                          MESA_META_VIEWPORT |
2372                          metaExtraSave));
2373
2374   newTex = alloc_texture(tex, width, height, texIntFormat);
2375
2376   /* vertex positions, texcoords (after texture allocation!) */
2377   {
2378      const GLfloat x0 = (GLfloat) x;
2379      const GLfloat y0 = (GLfloat) y;
2380      const GLfloat x1 = x + width * ctx->Pixel.ZoomX;
2381      const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
2382      const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
2383
2384      verts[0].x = x0;
2385      verts[0].y = y0;
2386      verts[0].z = z;
2387      verts[0].s = 0.0F;
2388      verts[0].t = 0.0F;
2389      verts[1].x = x1;
2390      verts[1].y = y0;
2391      verts[1].z = z;
2392      verts[1].s = tex->Sright;
2393      verts[1].t = 0.0F;
2394      verts[2].x = x1;
2395      verts[2].y = y1;
2396      verts[2].z = z;
2397      verts[2].s = tex->Sright;
2398      verts[2].t = tex->Ttop;
2399      verts[3].x = x0;
2400      verts[3].y = y1;
2401      verts[3].z = z;
2402      verts[3].s = 0.0F;
2403      verts[3].t = tex->Ttop;
2404   }
2405
2406   if (drawpix->ArrayObj == 0) {
2407      /* one-time setup: create vertex array object */
2408      _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
2409   }
2410   _mesa_BindVertexArray(drawpix->ArrayObj);
2411
2412   /* create vertex array buffer */
2413   _mesa_GenBuffersARB(1, &vbo);
2414   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
2415   _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
2416                       verts, GL_DYNAMIC_DRAW_ARB);
2417
2418   /* setup vertex arrays */
2419   _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
2420   _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
2421   _mesa_EnableClientState(GL_VERTEX_ARRAY);
2422   _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
2423
2424   /* set given unpack params */
2425   ctx->Unpack = *unpack;
2426
2427   _mesa_set_enable(ctx, tex->Target, GL_TRUE);
2428
2429   if (_mesa_is_stencil_format(format)) {
2430      /* Drawing stencil */
2431      GLint bit;
2432
2433      if (!drawpix->StencilFP)
2434         init_draw_stencil_pixels(ctx);
2435
2436      setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2437                            GL_ALPHA, type, pixels);
2438
2439      _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2440
2441      _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
2442
2443      /* set all stencil bits to 0 */
2444      _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
2445      _mesa_StencilFunc(GL_ALWAYS, 0, 255);
2446      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2447
2448      /* set stencil bits to 1 where needed */
2449      _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
2450
2451      _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
2452      _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
2453
2454      for (bit = 0; bit < ctx->DrawBuffer->Visual.stencilBits; bit++) {
2455         const GLuint mask = 1 << bit;
2456         if (mask & origStencilMask) {
2457            _mesa_StencilFunc(GL_ALWAYS, mask, mask);
2458            _mesa_StencilMask(mask);
2459
2460            _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
2461                                             255.0 / mask, 0.5, 0.0, 0.0);
2462
2463            _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2464         }
2465      }
2466   }
2467   else if (_mesa_is_depth_format(format)) {
2468      /* Drawing depth */
2469      if (!drawpix->DepthFP)
2470         init_draw_depth_pixels(ctx);
2471
2472      _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
2473      _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
2474
2475      /* polygon color = current raster color */
2476      _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
2477                                        ctx->Current.RasterColor);
2478
2479      setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2480                            format, type, pixels);
2481
2482      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2483   }
2484   else {
2485      /* Drawing RGBA */
2486      setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2487                            format, type, pixels);
2488      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2489   }
2490
2491   _mesa_set_enable(ctx, tex->Target, GL_FALSE);
2492
2493   _mesa_DeleteBuffersARB(1, &vbo);
2494
2495   /* restore unpack params */
2496   ctx->Unpack = unpackSave;
2497
2498   _mesa_meta_end(ctx);
2499}
2500
2501static GLboolean
2502alpha_test_raster_color(struct gl_context *ctx)
2503{
2504   GLfloat alpha = ctx->Current.RasterColor[ACOMP];
2505   GLfloat ref = ctx->Color.AlphaRef;
2506
2507   switch (ctx->Color.AlphaFunc) {
2508      case GL_NEVER:
2509	 return GL_FALSE;
2510      case GL_LESS:
2511	 return alpha < ref;
2512      case GL_EQUAL:
2513	 return alpha == ref;
2514      case GL_LEQUAL:
2515	 return alpha <= ref;
2516      case GL_GREATER:
2517	 return alpha > ref;
2518      case GL_NOTEQUAL:
2519	 return alpha != ref;
2520      case GL_GEQUAL:
2521	 return alpha >= ref;
2522      case GL_ALWAYS:
2523	 return GL_TRUE;
2524      default:
2525	 assert(0);
2526	 return GL_FALSE;
2527   }
2528}
2529
2530/**
2531 * Do glBitmap with a alpha texture quad.  Use the alpha test to cull
2532 * the 'off' bits.  A bitmap cache as in the gallium/mesa state
2533 * tracker would improve performance a lot.
2534 */
2535void
2536_mesa_meta_Bitmap(struct gl_context *ctx,
2537                  GLint x, GLint y, GLsizei width, GLsizei height,
2538                  const struct gl_pixelstore_attrib *unpack,
2539                  const GLubyte *bitmap1)
2540{
2541   struct bitmap_state *bitmap = &ctx->Meta->Bitmap;
2542   struct temp_texture *tex = get_bitmap_temp_texture(ctx);
2543   const GLenum texIntFormat = GL_ALPHA;
2544   const struct gl_pixelstore_attrib unpackSave = *unpack;
2545   GLubyte fg, bg;
2546   struct vertex {
2547      GLfloat x, y, z, s, t, r, g, b, a;
2548   };
2549   struct vertex verts[4];
2550   GLboolean newTex;
2551   GLubyte *bitmap8;
2552
2553   /*
2554    * Check if swrast fallback is needed.
2555    */
2556   if (ctx->_ImageTransferState ||
2557       ctx->FragmentProgram._Enabled ||
2558       ctx->Fog.Enabled ||
2559       ctx->Texture._EnabledUnits ||
2560       width > tex->MaxSize ||
2561       height > tex->MaxSize) {
2562      _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1);
2563      return;
2564   }
2565
2566   if (ctx->Color.AlphaEnabled && !alpha_test_raster_color(ctx))
2567      return;
2568
2569   /* Most GL state applies to glBitmap (like blending, stencil, etc),
2570    * but a there's a few things we need to override:
2571    */
2572   _mesa_meta_begin(ctx, (MESA_META_ALPHA_TEST |
2573                          MESA_META_PIXEL_STORE |
2574                          MESA_META_RASTERIZATION |
2575                          MESA_META_SHADER |
2576                          MESA_META_TEXTURE |
2577                          MESA_META_TRANSFORM |
2578                          MESA_META_CLIP |
2579                          MESA_META_VERTEX |
2580                          MESA_META_VIEWPORT));
2581
2582   if (bitmap->ArrayObj == 0) {
2583      /* one-time setup */
2584
2585      /* create vertex array object */
2586      _mesa_GenVertexArraysAPPLE(1, &bitmap->ArrayObj);
2587      _mesa_BindVertexArrayAPPLE(bitmap->ArrayObj);
2588
2589      /* create vertex array buffer */
2590      _mesa_GenBuffersARB(1, &bitmap->VBO);
2591      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
2592      _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
2593                          NULL, GL_DYNAMIC_DRAW_ARB);
2594
2595      /* setup vertex arrays */
2596      _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
2597      _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
2598      _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
2599      _mesa_EnableClientState(GL_VERTEX_ARRAY);
2600      _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
2601      _mesa_EnableClientState(GL_COLOR_ARRAY);
2602   }
2603   else {
2604      _mesa_BindVertexArray(bitmap->ArrayObj);
2605      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
2606   }
2607
2608   newTex = alloc_texture(tex, width, height, texIntFormat);
2609
2610   /* vertex positions, texcoords, colors (after texture allocation!) */
2611   {
2612      const GLfloat x0 = (GLfloat) x;
2613      const GLfloat y0 = (GLfloat) y;
2614      const GLfloat x1 = (GLfloat) (x + width);
2615      const GLfloat y1 = (GLfloat) (y + height);
2616      const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
2617      GLuint i;
2618
2619      verts[0].x = x0;
2620      verts[0].y = y0;
2621      verts[0].z = z;
2622      verts[0].s = 0.0F;
2623      verts[0].t = 0.0F;
2624      verts[1].x = x1;
2625      verts[1].y = y0;
2626      verts[1].z = z;
2627      verts[1].s = tex->Sright;
2628      verts[1].t = 0.0F;
2629      verts[2].x = x1;
2630      verts[2].y = y1;
2631      verts[2].z = z;
2632      verts[2].s = tex->Sright;
2633      verts[2].t = tex->Ttop;
2634      verts[3].x = x0;
2635      verts[3].y = y1;
2636      verts[3].z = z;
2637      verts[3].s = 0.0F;
2638      verts[3].t = tex->Ttop;
2639
2640      for (i = 0; i < 4; i++) {
2641         verts[i].r = ctx->Current.RasterColor[0];
2642         verts[i].g = ctx->Current.RasterColor[1];
2643         verts[i].b = ctx->Current.RasterColor[2];
2644         verts[i].a = ctx->Current.RasterColor[3];
2645      }
2646
2647      /* upload new vertex data */
2648      _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
2649   }
2650
2651   /* choose different foreground/background alpha values */
2652   CLAMPED_FLOAT_TO_UBYTE(fg, ctx->Current.RasterColor[ACOMP]);
2653   bg = (fg > 127 ? 0 : 255);
2654
2655   bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1);
2656   if (!bitmap1) {
2657      _mesa_meta_end(ctx);
2658      return;
2659   }
2660
2661   bitmap8 = (GLubyte *) malloc(width * height);
2662   if (bitmap8) {
2663      memset(bitmap8, bg, width * height);
2664      _mesa_expand_bitmap(width, height, &unpackSave, bitmap1,
2665                          bitmap8, width, fg);
2666
2667      _mesa_set_enable(ctx, tex->Target, GL_TRUE);
2668
2669      _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE);
2670      _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg));
2671
2672      setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2673                            GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8);
2674
2675      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2676
2677      _mesa_set_enable(ctx, tex->Target, GL_FALSE);
2678
2679      free(bitmap8);
2680   }
2681
2682   _mesa_unmap_pbo_source(ctx, &unpackSave);
2683
2684   _mesa_meta_end(ctx);
2685}
2686
2687
2688/**
2689 * Check if the call to _mesa_meta_GenerateMipmap() will require a
2690 * software fallback.  The fallback path will require that the texture
2691 * images are mapped.
2692 * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
2693 */
2694GLboolean
2695_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target,
2696                                          struct gl_texture_object *texObj)
2697{
2698   const GLuint fboSave = ctx->DrawBuffer->Name;
2699   struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
2700   struct gl_texture_image *baseImage;
2701   GLuint srcLevel;
2702   GLenum status;
2703
2704   /* check for fallbacks */
2705   if (!ctx->Extensions.EXT_framebuffer_object ||
2706       target == GL_TEXTURE_3D ||
2707       target == GL_TEXTURE_1D_ARRAY ||
2708       target == GL_TEXTURE_2D_ARRAY) {
2709      return GL_TRUE;
2710   }
2711
2712   srcLevel = texObj->BaseLevel;
2713   baseImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
2714   if (!baseImage || _mesa_is_format_compressed(baseImage->TexFormat)) {
2715      return GL_TRUE;
2716   }
2717
2718   if (_mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB &&
2719       !ctx->Extensions.EXT_texture_sRGB_decode) {
2720      /* The texture format is sRGB but we can't turn off sRGB->linear
2721       * texture sample conversion.  So we won't be able to generate the
2722       * right colors when rendering.  Need to use a fallback.
2723       */
2724      return GL_TRUE;
2725   }
2726
2727   /*
2728    * Test that we can actually render in the texture's format.
2729    */
2730   if (!mipmap->FBO)
2731      _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
2732   _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
2733
2734   if (target == GL_TEXTURE_1D) {
2735      _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
2736                                    GL_COLOR_ATTACHMENT0_EXT,
2737                                    target, texObj->Name, srcLevel);
2738   }
2739#if 0
2740   /* other work is needed to enable 3D mipmap generation */
2741   else if (target == GL_TEXTURE_3D) {
2742      GLint zoffset = 0;
2743      _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
2744                                    GL_COLOR_ATTACHMENT0_EXT,
2745                                    target, texObj->Name, srcLevel, zoffset);
2746   }
2747#endif
2748   else {
2749      /* 2D / cube */
2750      _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
2751                                    GL_COLOR_ATTACHMENT0_EXT,
2752                                    target, texObj->Name, srcLevel);
2753   }
2754
2755   status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
2756
2757   _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
2758
2759   if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2760      return GL_TRUE;
2761   }
2762
2763   return GL_FALSE;
2764}
2765
2766
2767/**
2768 * Compute the texture coordinates for the four vertices of a quad for
2769 * drawing a 2D texture image or slice of a cube/3D texture.
2770 * \param faceTarget  GL_TEXTURE_1D/2D/3D or cube face name
2771 * \param slice  slice of a 1D/2D array texture or 3D texture
2772 * \param width  width of the texture image
2773 * \param height  height of the texture image
2774 * \param coords0/1/2/3  returns the computed texcoords
2775 */
2776static void
2777setup_texture_coords(GLenum faceTarget,
2778                     GLint slice,
2779                     GLint width,
2780                     GLint height,
2781                     GLfloat coords0[3],
2782                     GLfloat coords1[3],
2783                     GLfloat coords2[3],
2784                     GLfloat coords3[3])
2785{
2786   static const GLfloat st[4][2] = {
2787      {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
2788   };
2789   GLuint i;
2790   GLfloat r;
2791
2792   switch (faceTarget) {
2793   case GL_TEXTURE_1D:
2794   case GL_TEXTURE_2D:
2795   case GL_TEXTURE_3D:
2796   case GL_TEXTURE_2D_ARRAY:
2797      if (faceTarget == GL_TEXTURE_3D)
2798         r = 1.0F / slice;
2799      else if (faceTarget == GL_TEXTURE_2D_ARRAY)
2800         r = slice;
2801      else
2802         r = 0.0F;
2803      coords0[0] = 0.0F; /* s */
2804      coords0[1] = 0.0F; /* t */
2805      coords0[2] = r; /* r */
2806      coords1[0] = 1.0F;
2807      coords1[1] = 0.0F;
2808      coords1[2] = r;
2809      coords2[0] = 1.0F;
2810      coords2[1] = 1.0F;
2811      coords2[2] = r;
2812      coords3[0] = 0.0F;
2813      coords3[1] = 1.0F;
2814      coords3[2] = r;
2815      break;
2816   case GL_TEXTURE_RECTANGLE_ARB:
2817      coords0[0] = 0.0F; /* s */
2818      coords0[1] = 0.0F; /* t */
2819      coords0[2] = 0.0F; /* r */
2820      coords1[0] = width;
2821      coords1[1] = 0.0F;
2822      coords1[2] = 0.0F;
2823      coords2[0] = width;
2824      coords2[1] = height;
2825      coords2[2] = 0.0F;
2826      coords3[0] = 0.0F;
2827      coords3[1] = height;
2828      coords3[2] = 0.0F;
2829      break;
2830   case GL_TEXTURE_1D_ARRAY:
2831      coords0[0] = 0.0F; /* s */
2832      coords0[1] = slice; /* t */
2833      coords0[2] = 0.0F; /* r */
2834      coords1[0] = 1.0f;
2835      coords1[1] = slice;
2836      coords1[2] = 0.0F;
2837      coords2[0] = 1.0F;
2838      coords2[1] = slice;
2839      coords2[2] = 0.0F;
2840      coords3[0] = 0.0F;
2841      coords3[1] = slice;
2842      coords3[2] = 0.0F;
2843      break;
2844
2845   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2846   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2847   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2848   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2849   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2850   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2851      /* loop over quad verts */
2852      for (i = 0; i < 4; i++) {
2853         /* Compute sc = +/-scale and tc = +/-scale.
2854          * Not +/-1 to avoid cube face selection ambiguity near the edges,
2855          * though that can still sometimes happen with this scale factor...
2856          */
2857         const GLfloat scale = 0.9999f;
2858         const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale;
2859         const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale;
2860         GLfloat *coord;
2861
2862         switch (i) {
2863         case 0:
2864            coord = coords0;
2865            break;
2866         case 1:
2867            coord = coords1;
2868            break;
2869         case 2:
2870            coord = coords2;
2871            break;
2872         case 3:
2873            coord = coords3;
2874            break;
2875         default:
2876            assert(0);
2877         }
2878
2879         switch (faceTarget) {
2880         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2881            coord[0] = 1.0f;
2882            coord[1] = -tc;
2883            coord[2] = -sc;
2884            break;
2885         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2886            coord[0] = -1.0f;
2887            coord[1] = -tc;
2888            coord[2] = sc;
2889            break;
2890         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2891            coord[0] = sc;
2892            coord[1] = 1.0f;
2893            coord[2] = tc;
2894            break;
2895         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2896            coord[0] = sc;
2897            coord[1] = -1.0f;
2898            coord[2] = -tc;
2899            break;
2900         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2901            coord[0] = sc;
2902            coord[1] = -tc;
2903            coord[2] = 1.0f;
2904            break;
2905         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2906            coord[0] = -sc;
2907            coord[1] = -tc;
2908            coord[2] = -1.0f;
2909            break;
2910         default:
2911            assert(0);
2912         }
2913      }
2914      break;
2915   default:
2916      assert(0 && "unexpected target in meta setup_texture_coords()");
2917   }
2918}
2919
2920
2921static void
2922setup_ff_generate_mipmap(struct gl_context *ctx,
2923                           struct gen_mipmap_state *mipmap)
2924{
2925   struct vertex {
2926      GLfloat x, y, tex[3];
2927   };
2928
2929   if (mipmap->ArrayObj == 0) {
2930      /* one-time setup */
2931      /* create vertex array object */
2932      _mesa_GenVertexArraysAPPLE(1, &mipmap->ArrayObj);
2933      _mesa_BindVertexArrayAPPLE(mipmap->ArrayObj);
2934
2935      /* create vertex array buffer */
2936      _mesa_GenBuffersARB(1, &mipmap->VBO);
2937      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
2938      /* setup vertex arrays */
2939      _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
2940      _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex));
2941      _mesa_EnableClientState(GL_VERTEX_ARRAY);
2942      _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
2943   }
2944
2945   /* setup projection matrix */
2946   _mesa_MatrixMode(GL_PROJECTION);
2947   _mesa_LoadIdentity();
2948   _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
2949}
2950
2951
2952static void
2953setup_glsl_generate_mipmap(struct gl_context *ctx,
2954                           struct gen_mipmap_state *mipmap)
2955{
2956   struct vertex {
2957      GLfloat x, y, tex[3];
2958   };
2959
2960   static const char *vs_source =
2961      "attribute vec2 position;\n"
2962      "attribute vec3 textureCoords;\n"
2963      "varying vec3 texCoords;\n"
2964      "void main()\n"
2965      "{\n"
2966      "   texCoords = textureCoords;\n"
2967      "   gl_Position = vec4(position, 0.0, 1.0);\n"
2968      "}\n";
2969   static const char *fs_source =
2970      "uniform sampler2D tex2d;\n"
2971      "varying vec3 texCoords;\n"
2972      "void main()\n"
2973      "{\n"
2974      "   gl_FragColor = texture2D(tex2d, texCoords.xy);\n"
2975      "}\n";
2976
2977   static const char *vs_int_source =
2978      "#version 130\n"
2979      "in vec2 position;\n"
2980      "in vec3 textureCoords;\n"
2981      "out vec3 texCoords;\n"
2982      "void main()\n"
2983      "{\n"
2984      "   texCoords = textureCoords;\n"
2985      "   gl_Position = gl_Vertex;\n"
2986      "}\n";
2987   static const char *fs_int_source =
2988      "#version 130\n"
2989      "uniform isampler2D tex2d;\n"
2990      "in vec3 texCoords;\n"
2991      "out ivec4 out_color;\n"
2992      "\n"
2993      "void main()\n"
2994      "{\n"
2995      "   out_color = texture(tex2d, texCoords.xy);\n"
2996      "}\n";
2997   GLuint vs, fs;
2998
2999   /* Check if already initialized */
3000   if (mipmap->ArrayObj != 0)
3001      return;
3002   /* create vertex array object */
3003   _mesa_GenVertexArrays(1, &mipmap->ArrayObj);
3004   _mesa_BindVertexArray(mipmap->ArrayObj);
3005
3006   /* create vertex array buffer */
3007   _mesa_GenBuffersARB(1, &mipmap->VBO);
3008   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
3009
3010   /* setup vertex arrays */
3011   _mesa_VertexAttribPointerARB(0, 2, GL_FLOAT, GL_FALSE,
3012                                sizeof(struct vertex), OFFSET(x));
3013   _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE,
3014                                sizeof(struct vertex), OFFSET(tex));
3015
3016   vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source);
3017   fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source);
3018
3019   mipmap->ShaderProg = _mesa_CreateProgramObjectARB();
3020   _mesa_AttachShader(mipmap->ShaderProg, fs);
3021   _mesa_DeleteObjectARB(fs);
3022   _mesa_AttachShader(mipmap->ShaderProg, vs);
3023   _mesa_DeleteObjectARB(vs);
3024   _mesa_BindAttribLocationARB(mipmap->ShaderProg, 0, "position");
3025   _mesa_BindAttribLocationARB(mipmap->ShaderProg, 1, "texcoords");
3026   _mesa_EnableVertexAttribArrayARB(0);
3027   _mesa_EnableVertexAttribArrayARB(1);
3028   link_program_with_debug(ctx, mipmap->ShaderProg);
3029
3030   if ((_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) ||
3031       _mesa_is_gles3(ctx)){
3032      vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source);
3033      fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source);
3034
3035      mipmap->IntegerShaderProg = _mesa_CreateProgramObjectARB();
3036      _mesa_AttachShader(mipmap->IntegerShaderProg, fs);
3037      _mesa_DeleteObjectARB(fs);
3038      _mesa_AttachShader(mipmap->IntegerShaderProg, vs);
3039      _mesa_DeleteObjectARB(vs);
3040      _mesa_BindAttribLocationARB(mipmap->IntegerShaderProg, 0, "position");
3041      _mesa_BindAttribLocationARB(mipmap->IntegerShaderProg, 1, "texcoords");
3042
3043      /* Note that user-defined out attributes get automatically assigned
3044       * locations starting from 0, so we don't need to explicitly
3045       * BindFragDataLocation to 0.
3046       */
3047      link_program_with_debug(ctx, mipmap->IntegerShaderProg);
3048   }
3049}
3050
3051
3052static void
3053meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
3054                                 struct gen_mipmap_state *mipmap)
3055{
3056   if (mipmap->ArrayObj == 0)
3057      return;
3058   _mesa_DeleteVertexArraysAPPLE(1, &mipmap->ArrayObj);
3059   mipmap->ArrayObj = 0;
3060   _mesa_DeleteBuffersARB(1, &mipmap->VBO);
3061   mipmap->VBO = 0;
3062   _mesa_DeleteObjectARB(mipmap->ShaderProg);
3063   mipmap->ShaderProg = 0;
3064
3065   if (mipmap->IntegerShaderProg) {
3066      _mesa_DeleteObjectARB(mipmap->IntegerShaderProg);
3067      mipmap->IntegerShaderProg = 0;
3068   }
3069}
3070
3071
3072/**
3073 * Called via ctx->Driver.GenerateMipmap()
3074 * Note: We don't yet support 3D textures, 1D/2D array textures or texture
3075 * borders.
3076 */
3077void
3078_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
3079                          struct gl_texture_object *texObj)
3080{
3081   struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
3082   struct vertex {
3083      GLfloat x, y, tex[3];
3084   };
3085   struct vertex verts[4];
3086   const GLuint baseLevel = texObj->BaseLevel;
3087   const GLuint maxLevel = texObj->MaxLevel;
3088   const GLint maxLevelSave = texObj->MaxLevel;
3089   const GLboolean genMipmapSave = texObj->GenerateMipmap;
3090   const GLenum srgbBufferSave = ctx->Color.sRGBEnabled;
3091   const GLuint fboSave = ctx->DrawBuffer->Name;
3092   const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit;
3093   const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
3094                                      ctx->Extensions.ARB_fragment_shader &&
3095				      (ctx->API != API_OPENGLES);
3096   GLenum faceTarget;
3097   GLuint dstLevel;
3098   const GLint slice = 0;
3099   GLuint samplerSave;
3100
3101   if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
3102      _mesa_generate_mipmap(ctx, target, texObj);
3103      return;
3104   }
3105
3106   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
3107       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
3108      faceTarget = target;
3109      target = GL_TEXTURE_CUBE_MAP;
3110   }
3111   else {
3112      faceTarget = target;
3113   }
3114
3115   _mesa_meta_begin(ctx, MESA_META_ALL);
3116
3117   /* Choose between glsl version and fixed function version of
3118    * GenerateMipmap function.
3119    */
3120   if (use_glsl_version) {
3121      setup_glsl_generate_mipmap(ctx, mipmap);
3122
3123      if (texObj->_IsIntegerFormat)
3124         _mesa_UseProgramObjectARB(mipmap->IntegerShaderProg);
3125      else
3126         _mesa_UseProgramObjectARB(mipmap->ShaderProg);
3127   }
3128   else {
3129      setup_ff_generate_mipmap(ctx, mipmap);
3130      _mesa_set_enable(ctx, target, GL_TRUE);
3131   }
3132
3133   _mesa_BindVertexArray(mipmap->ArrayObj);
3134   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
3135
3136   samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
3137      ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
3138
3139   if (currentTexUnitSave != 0)
3140      _mesa_BindTexture(target, texObj->Name);
3141
3142   if (!mipmap->FBO) {
3143      _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
3144   }
3145
3146   if (!mipmap->Sampler) {
3147      _mesa_GenSamplers(1, &mipmap->Sampler);
3148      _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler);
3149
3150      if (use_glsl_version && texObj->_IsIntegerFormat)
3151         _mesa_SamplerParameteri(mipmap->Sampler,
3152	                         GL_TEXTURE_MIN_FILTER,
3153	                         GL_NEAREST_MIPMAP_NEAREST);
3154      else
3155         _mesa_SamplerParameteri(mipmap->Sampler,
3156	                         GL_TEXTURE_MIN_FILTER,
3157	                         GL_LINEAR_MIPMAP_LINEAR);
3158
3159      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3160      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3161      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3162      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3163
3164      /* We don't want to encode or decode sRGB values; treat them as linear.
3165       * This is not technically correct for GLES3 but we don't get any API
3166       * error at the moment.
3167       */
3168      if (ctx->Extensions.EXT_texture_sRGB_decode) {
3169         _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_SRGB_DECODE_EXT,
3170               GL_SKIP_DECODE_EXT);
3171      }
3172
3173   } else {
3174      _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler);
3175   }
3176
3177   _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
3178
3179   if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES)
3180      _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
3181   else
3182      assert(!genMipmapSave);
3183
3184   if ((ctx->Extensions.EXT_framebuffer_sRGB &&
3185        _mesa_is_desktop_gl(ctx)) ||
3186       _mesa_is_gles3(ctx)) {
3187      _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE);
3188   }
3189
3190  /* Setup texture coordinates */
3191   setup_texture_coords(faceTarget,
3192                        slice,
3193                        0, 0, /* width, height never used here */
3194                        verts[0].tex,
3195                        verts[1].tex,
3196                        verts[2].tex,
3197                        verts[3].tex);
3198
3199   /* setup vertex positions */
3200   verts[0].x = -1.0F;
3201   verts[0].y = -1.0F;
3202   verts[1].x =  1.0F;
3203   verts[1].y = -1.0F;
3204   verts[2].x =  1.0F;
3205   verts[2].y =  1.0F;
3206   verts[3].x = -1.0F;
3207   verts[3].y =  1.0F;
3208
3209   /* upload vertex data */
3210   _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
3211                       verts, GL_DYNAMIC_DRAW_ARB);
3212
3213   /* texture is already locked, unlock now */
3214   _mesa_unlock_texture(ctx, texObj);
3215
3216   for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
3217      const struct gl_texture_image *srcImage;
3218      const GLuint srcLevel = dstLevel - 1;
3219      GLsizei srcWidth, srcHeight, srcDepth;
3220      GLsizei dstWidth, dstHeight, dstDepth;
3221      GLenum status;
3222
3223      srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel);
3224      assert(srcImage->Border == 0);
3225
3226      /* src size */
3227      srcWidth = srcImage->Width;
3228      srcHeight = srcImage->Height;
3229      srcDepth = srcImage->Depth;
3230
3231      /* new dst size */
3232      dstWidth = MAX2(1, srcWidth / 2);
3233      dstHeight = MAX2(1, srcHeight / 2);
3234      dstDepth = MAX2(1, srcDepth / 2);
3235
3236      if (dstWidth == srcImage->Width &&
3237          dstHeight == srcImage->Height &&
3238          dstDepth == srcImage->Depth) {
3239         /* all done */
3240         break;
3241      }
3242
3243      /* Allocate storage for the destination mipmap image(s) */
3244
3245      /* Set MaxLevel large enough to hold the new level when we allocate it */
3246      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
3247
3248      if (!_mesa_prepare_mipmap_level(ctx, texObj, dstLevel,
3249                                      dstWidth, dstHeight, dstDepth,
3250                                      srcImage->Border,
3251                                      srcImage->InternalFormat,
3252                                      srcImage->TexFormat)) {
3253         /* All done.  We either ran out of memory or we would go beyond the
3254          * last valid level of an immutable texture if we continued.
3255          */
3256         break;
3257      }
3258
3259      /* limit minification to src level */
3260      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
3261
3262      /* Set to draw into the current dstLevel */
3263      if (target == GL_TEXTURE_1D) {
3264         _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
3265                                       GL_COLOR_ATTACHMENT0_EXT,
3266                                       target,
3267                                       texObj->Name,
3268                                       dstLevel);
3269      }
3270      else if (target == GL_TEXTURE_3D) {
3271         GLint zoffset = 0; /* XXX unfinished */
3272         _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
3273                                       GL_COLOR_ATTACHMENT0_EXT,
3274                                       target,
3275                                       texObj->Name,
3276                                       dstLevel, zoffset);
3277      }
3278      else {
3279         /* 2D / cube */
3280         _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
3281                                       GL_COLOR_ATTACHMENT0_EXT,
3282                                       faceTarget,
3283                                       texObj->Name,
3284                                       dstLevel);
3285      }
3286
3287      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
3288
3289      /* sanity check */
3290      status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
3291      if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
3292         _mesa_problem(ctx, "Unexpected incomplete framebuffer in "
3293                       "_mesa_meta_GenerateMipmap()");
3294         break;
3295      }
3296
3297      assert(dstWidth == ctx->DrawBuffer->Width);
3298      assert(dstHeight == ctx->DrawBuffer->Height);
3299
3300      /* setup viewport */
3301      _mesa_set_viewport(ctx, 0, 0, dstWidth, dstHeight);
3302
3303      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
3304   }
3305
3306   if (ctx->Extensions.EXT_framebuffer_sRGB && srgbBufferSave) {
3307      _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE);
3308   }
3309
3310   _mesa_lock_texture(ctx, texObj); /* relock */
3311
3312   _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);
3313
3314   _mesa_meta_end(ctx);
3315
3316   _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
3317   if (genMipmapSave)
3318      _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
3319
3320   _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
3321}
3322
3323
3324/**
3325 * Determine the GL data type to use for the temporary image read with
3326 * ReadPixels() and passed to Tex[Sub]Image().
3327 */
3328static GLenum
3329get_temp_image_type(struct gl_context *ctx, gl_format format)
3330{
3331   GLenum baseFormat;
3332
3333   baseFormat = _mesa_get_format_base_format(format);
3334
3335   switch (baseFormat) {
3336   case GL_RGBA:
3337   case GL_RGB:
3338   case GL_RG:
3339   case GL_RED:
3340   case GL_ALPHA:
3341   case GL_LUMINANCE:
3342   case GL_LUMINANCE_ALPHA:
3343   case GL_INTENSITY:
3344      if (ctx->DrawBuffer->Visual.redBits <= 8)
3345         return GL_UNSIGNED_BYTE;
3346      else if (ctx->DrawBuffer->Visual.redBits <= 16)
3347         return GL_UNSIGNED_SHORT;
3348      else
3349         return _mesa_get_format_datatype(format);
3350   case GL_DEPTH_COMPONENT:
3351      return GL_UNSIGNED_INT;
3352   case GL_DEPTH_STENCIL:
3353      return GL_UNSIGNED_INT_24_8;
3354   default:
3355      _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()",
3356		    baseFormat);
3357      return 0;
3358   }
3359}
3360
3361
3362/**
3363 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
3364 * Have to be careful with locking and meta state for pixel transfer.
3365 */
3366void
3367_mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
3368                           struct gl_texture_image *texImage,
3369                           GLint xoffset, GLint yoffset, GLint zoffset,
3370                           struct gl_renderbuffer *rb,
3371                           GLint x, GLint y,
3372                           GLsizei width, GLsizei height)
3373{
3374   struct gl_texture_object *texObj = texImage->TexObject;
3375   GLenum format, type;
3376   GLint bpp;
3377   void *buf;
3378
3379   /* Choose format/type for temporary image buffer */
3380   format = _mesa_get_format_base_format(texImage->TexFormat);
3381   if (format == GL_LUMINANCE ||
3382       format == GL_LUMINANCE_ALPHA ||
3383       format == GL_INTENSITY) {
3384      /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the
3385       * temp image buffer because glReadPixels will do L=R+G+B which is
3386       * not what we want (should be L=R).
3387       */
3388      format = GL_RGBA;
3389   }
3390
3391   type = get_temp_image_type(ctx, texImage->TexFormat);
3392   if (_mesa_is_format_integer_color(texImage->TexFormat)) {
3393      format = _mesa_base_format_to_integer_format(format);
3394   }
3395   bpp = _mesa_bytes_per_pixel(format, type);
3396   if (bpp <= 0) {
3397      _mesa_problem(ctx, "Bad bpp in _mesa_meta_CopyTexSubImage()");
3398      return;
3399   }
3400
3401   /*
3402    * Alloc image buffer (XXX could use a PBO)
3403    */
3404   buf = malloc(width * height * bpp);
3405   if (!buf) {
3406      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims);
3407      return;
3408   }
3409
3410   _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
3411
3412   /*
3413    * Read image from framebuffer (disable pixel transfer ops)
3414    */
3415   _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER);
3416   ctx->Driver.ReadPixels(ctx, x, y, width, height,
3417			  format, type, &ctx->Pack, buf);
3418   _mesa_meta_end(ctx);
3419
3420   _mesa_update_state(ctx); /* to update pixel transfer state */
3421
3422   /*
3423    * Store texture data (with pixel transfer ops)
3424    */
3425   _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE);
3426
3427   ctx->Driver.TexSubImage(ctx, dims, texImage,
3428                           xoffset, yoffset, zoffset, width, height, 1,
3429                           format, type, buf, &ctx->Unpack);
3430
3431   _mesa_meta_end(ctx);
3432
3433   _mesa_lock_texture(ctx, texObj); /* re-lock */
3434
3435   free(buf);
3436}
3437
3438
3439/**
3440 * Decompress a texture image by drawing a quad with the compressed
3441 * texture and reading the pixels out of the color buffer.
3442 * \param slice  which slice of a 3D texture or layer of a 1D/2D texture
3443 * \param destFormat  format, ala glReadPixels
3444 * \param destType  type, ala glReadPixels
3445 * \param dest  destination buffer
3446 * \param destRowLength  dest image rowLength (ala GL_PACK_ROW_LENGTH)
3447 */
3448static void
3449decompress_texture_image(struct gl_context *ctx,
3450                         struct gl_texture_image *texImage,
3451                         GLuint slice,
3452                         GLenum destFormat, GLenum destType,
3453                         GLvoid *dest)
3454{
3455   struct decompress_state *decompress = &ctx->Meta->Decompress;
3456   struct gl_texture_object *texObj = texImage->TexObject;
3457   const GLint width = texImage->Width;
3458   const GLint height = texImage->Height;
3459   const GLenum target = texObj->Target;
3460   GLenum faceTarget;
3461   struct vertex {
3462      GLfloat x, y, tex[3];
3463   };
3464   struct vertex verts[4];
3465   GLuint fboDrawSave, fboReadSave;
3466   GLuint rbSave;
3467   GLuint samplerSave;
3468
3469   if (slice > 0) {
3470      assert(target == GL_TEXTURE_3D ||
3471             target == GL_TEXTURE_2D_ARRAY);
3472   }
3473
3474   if (target == GL_TEXTURE_CUBE_MAP) {
3475      faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face;
3476   }
3477   else {
3478      faceTarget = target;
3479   }
3480
3481   /* save fbo bindings (not saved by _mesa_meta_begin()) */
3482   fboDrawSave = ctx->DrawBuffer->Name;
3483   fboReadSave = ctx->ReadBuffer->Name;
3484   rbSave = ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0;
3485
3486   _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_PIXEL_STORE);
3487
3488   samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
3489         ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
3490
3491   /* Create/bind FBO/renderbuffer */
3492   if (decompress->FBO == 0) {
3493      _mesa_GenFramebuffersEXT(1, &decompress->FBO);
3494      _mesa_GenRenderbuffersEXT(1, &decompress->RBO);
3495      _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO);
3496      _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO);
3497      _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
3498                                       GL_COLOR_ATTACHMENT0_EXT,
3499                                       GL_RENDERBUFFER_EXT,
3500                                       decompress->RBO);
3501   }
3502   else {
3503      _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO);
3504   }
3505
3506   /* alloc dest surface */
3507   if (width > decompress->Width || height > decompress->Height) {
3508      _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO);
3509      _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA,
3510                                   width, height);
3511      decompress->Width = width;
3512      decompress->Height = height;
3513   }
3514
3515   /* setup VBO data */
3516   if (decompress->ArrayObj == 0) {
3517      /* create vertex array object */
3518      _mesa_GenVertexArrays(1, &decompress->ArrayObj);
3519      _mesa_BindVertexArray(decompress->ArrayObj);
3520
3521      /* create vertex array buffer */
3522      _mesa_GenBuffersARB(1, &decompress->VBO);
3523      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO);
3524      _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
3525                          NULL, GL_DYNAMIC_DRAW_ARB);
3526
3527      /* setup vertex arrays */
3528      _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
3529      _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex));
3530      _mesa_EnableClientState(GL_VERTEX_ARRAY);
3531      _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
3532   }
3533   else {
3534      _mesa_BindVertexArray(decompress->ArrayObj);
3535      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO);
3536   }
3537
3538   if (!decompress->Sampler) {
3539      _mesa_GenSamplers(1, &decompress->Sampler);
3540      _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler);
3541      /* nearest filtering */
3542      _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3543      _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3544      /* No sRGB decode or encode.*/
3545      if (ctx->Extensions.EXT_texture_sRGB_decode) {
3546         _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_SRGB_DECODE_EXT,
3547                             GL_SKIP_DECODE_EXT);
3548      }
3549
3550   } else {
3551      _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler);
3552   }
3553
3554   setup_texture_coords(faceTarget, slice, width, height,
3555                        verts[0].tex,
3556                        verts[1].tex,
3557                        verts[2].tex,
3558                        verts[3].tex);
3559
3560   /* setup vertex positions */
3561   verts[0].x = 0.0F;
3562   verts[0].y = 0.0F;
3563   verts[1].x = width;
3564   verts[1].y = 0.0F;
3565   verts[2].x = width;
3566   verts[2].y = height;
3567   verts[3].x = 0.0F;
3568   verts[3].y = height;
3569
3570   /* upload new vertex data */
3571   _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
3572
3573   /* setup texture state */
3574   _mesa_BindTexture(target, texObj->Name);
3575   _mesa_set_enable(ctx, target, GL_TRUE);
3576
3577   {
3578      /* save texture object state */
3579      const GLint baseLevelSave = texObj->BaseLevel;
3580      const GLint maxLevelSave = texObj->MaxLevel;
3581
3582      /* restrict sampling to the texture level of interest */
3583      if (target != GL_TEXTURE_RECTANGLE_ARB) {
3584         _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, texImage->Level);
3585         _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, texImage->Level);
3586      }
3587
3588      /* No sRGB decode or encode.*/
3589      if (ctx->Extensions.EXT_framebuffer_sRGB) {
3590         _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE);
3591      }
3592
3593      /* render quad w/ texture into renderbuffer */
3594      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
3595
3596      /* Restore texture object state, the texture binding will
3597       * be restored by _mesa_meta_end().
3598       */
3599      if (target != GL_TEXTURE_RECTANGLE_ARB) {
3600         _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
3601         _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
3602      }
3603
3604   }
3605
3606   /* read pixels from renderbuffer */
3607   {
3608      GLenum baseTexFormat = texImage->_BaseFormat;
3609
3610      /* The pixel transfer state will be set to default values at this point
3611       * (see MESA_META_PIXEL_TRANSFER) so pixel transfer ops are effectively
3612       * turned off (as required by glGetTexImage) but we need to handle some
3613       * special cases.  In particular, single-channel texture values are
3614       * returned as red and two-channel texture values are returned as
3615       * red/alpha.
3616       */
3617      if (baseTexFormat == GL_LUMINANCE ||
3618          baseTexFormat == GL_LUMINANCE_ALPHA ||
3619          baseTexFormat == GL_INTENSITY) {
3620         /* Green and blue must be zero */
3621         _mesa_PixelTransferf(GL_GREEN_SCALE, 0.0f);
3622         _mesa_PixelTransferf(GL_BLUE_SCALE, 0.0f);
3623      }
3624
3625      _mesa_ReadPixels(0, 0, width, height, destFormat, destType, dest);
3626   }
3627
3628   /* disable texture unit */
3629   _mesa_set_enable(ctx, target, GL_FALSE);
3630
3631   _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);
3632
3633   _mesa_meta_end(ctx);
3634
3635   /* restore fbo bindings */
3636   if (fboDrawSave == fboReadSave) {
3637      _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboDrawSave);
3638   }
3639   else {
3640      _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboDrawSave);
3641      _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fboReadSave);
3642   }
3643   _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbSave);
3644}
3645
3646
3647/**
3648 * This is just a wrapper around _mesa_get_tex_image() and
3649 * decompress_texture_image().  Meta functions should not be directly called
3650 * from core Mesa.
3651 */
3652void
3653_mesa_meta_GetTexImage(struct gl_context *ctx,
3654                       GLenum format, GLenum type, GLvoid *pixels,
3655                       struct gl_texture_image *texImage)
3656{
3657   /* We can only use the decompress-with-blit method here if the texels are
3658    * unsigned, normalized values.  We could handle signed and unnormalized
3659    * with floating point renderbuffers...
3660    */
3661   if (_mesa_is_format_compressed(texImage->TexFormat) &&
3662       _mesa_get_format_datatype(texImage->TexFormat)
3663       == GL_UNSIGNED_NORMALIZED) {
3664      struct gl_texture_object *texObj = texImage->TexObject;
3665      const GLuint slice = 0; /* only 2D compressed textures for now */
3666      /* Need to unlock the texture here to prevent deadlock... */
3667      _mesa_unlock_texture(ctx, texObj);
3668      decompress_texture_image(ctx, texImage, slice, format, type, pixels);
3669      /* ... and relock it */
3670      _mesa_lock_texture(ctx, texObj);
3671   }
3672   else {
3673      _mesa_get_teximage(ctx, format, type, pixels, texImage);
3674   }
3675}
3676
3677
3678/**
3679 * Meta implementation of ctx->Driver.DrawTex() in terms
3680 * of polygon rendering.
3681 */
3682void
3683_mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
3684                   GLfloat width, GLfloat height)
3685{
3686#if FEATURE_OES_draw_texture
3687   struct drawtex_state *drawtex = &ctx->Meta->DrawTex;
3688   struct vertex {
3689      GLfloat x, y, z, st[MAX_TEXTURE_UNITS][2];
3690   };
3691   struct vertex verts[4];
3692   GLuint i;
3693
3694   _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION |
3695                          MESA_META_SHADER |
3696                          MESA_META_TRANSFORM |
3697                          MESA_META_VERTEX |
3698                          MESA_META_VIEWPORT));
3699
3700   if (drawtex->ArrayObj == 0) {
3701      /* one-time setup */
3702      GLint active_texture;
3703
3704      /* create vertex array object */
3705      _mesa_GenVertexArrays(1, &drawtex->ArrayObj);
3706      _mesa_BindVertexArray(drawtex->ArrayObj);
3707
3708      /* create vertex array buffer */
3709      _mesa_GenBuffersARB(1, &drawtex->VBO);
3710      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawtex->VBO);
3711      _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
3712                          NULL, GL_DYNAMIC_DRAW_ARB);
3713
3714      /* client active texture is not part of the array object */
3715      active_texture = ctx->Array.ActiveTexture;
3716
3717      /* setup vertex arrays */
3718      _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
3719      _mesa_EnableClientState(GL_VERTEX_ARRAY);
3720      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
3721         _mesa_ClientActiveTextureARB(GL_TEXTURE0 + i);
3722         _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(st[i]));
3723         _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
3724      }
3725
3726      /* restore client active texture */
3727      _mesa_ClientActiveTextureARB(GL_TEXTURE0 + active_texture);
3728   }
3729   else {
3730      _mesa_BindVertexArray(drawtex->ArrayObj);
3731      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawtex->VBO);
3732   }
3733
3734   /* vertex positions, texcoords */
3735   {
3736      const GLfloat x1 = x + width;
3737      const GLfloat y1 = y + height;
3738
3739      z = CLAMP(z, 0.0, 1.0);
3740      z = invert_z(z);
3741
3742      verts[0].x = x;
3743      verts[0].y = y;
3744      verts[0].z = z;
3745
3746      verts[1].x = x1;
3747      verts[1].y = y;
3748      verts[1].z = z;
3749
3750      verts[2].x = x1;
3751      verts[2].y = y1;
3752      verts[2].z = z;
3753
3754      verts[3].x = x;
3755      verts[3].y = y1;
3756      verts[3].z = z;
3757
3758      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
3759         const struct gl_texture_object *texObj;
3760         const struct gl_texture_image *texImage;
3761         GLfloat s, t, s1, t1;
3762         GLuint tw, th;
3763
3764         if (!ctx->Texture.Unit[i]._ReallyEnabled) {
3765            GLuint j;
3766            for (j = 0; j < 4; j++) {
3767               verts[j].st[i][0] = 0.0f;
3768               verts[j].st[i][1] = 0.0f;
3769            }
3770            continue;
3771         }
3772
3773         texObj = ctx->Texture.Unit[i]._Current;
3774         texImage = texObj->Image[0][texObj->BaseLevel];
3775         tw = texImage->Width2;
3776         th = texImage->Height2;
3777
3778         s = (GLfloat) texObj->CropRect[0] / tw;
3779         t = (GLfloat) texObj->CropRect[1] / th;
3780         s1 = (GLfloat) (texObj->CropRect[0] + texObj->CropRect[2]) / tw;
3781         t1 = (GLfloat) (texObj->CropRect[1] + texObj->CropRect[3]) / th;
3782
3783         verts[0].st[i][0] = s;
3784         verts[0].st[i][1] = t;
3785
3786         verts[1].st[i][0] = s1;
3787         verts[1].st[i][1] = t;
3788
3789         verts[2].st[i][0] = s1;
3790         verts[2].st[i][1] = t1;
3791
3792         verts[3].st[i][0] = s;
3793         verts[3].st[i][1] = t1;
3794      }
3795
3796      _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
3797   }
3798
3799   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
3800
3801   _mesa_meta_end(ctx);
3802#endif /* FEATURE_OES_draw_texture */
3803}
3804