Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. |
||
5 | * Copyright (C) 2009 VMware, Inc. All Rights Reserved. |
||
6 | * |
||
7 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
8 | * copy of this software and associated documentation files (the "Software"), |
||
9 | * to deal in the Software without restriction, including without limitation |
||
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
11 | * and/or sell copies of the Software, and to permit persons to whom the |
||
12 | * Software is furnished to do so, subject to the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice shall be included |
||
15 | * in all copies or substantial portions of the Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
23 | * OTHER DEALINGS IN THE SOFTWARE. |
||
24 | */ |
||
25 | |||
26 | #include "glheader.h" |
||
27 | #include "imports.h" |
||
28 | #include "accum.h" |
||
29 | #include "arrayobj.h" |
||
30 | #include "attrib.h" |
||
31 | #include "blend.h" |
||
32 | #include "buffers.h" |
||
33 | #include "bufferobj.h" |
||
34 | #include "clear.h" |
||
35 | #include "context.h" |
||
36 | #include "depth.h" |
||
37 | #include "enable.h" |
||
38 | #include "enums.h" |
||
39 | #include "fog.h" |
||
40 | #include "hint.h" |
||
41 | #include "light.h" |
||
42 | #include "lines.h" |
||
43 | #include "macros.h" |
||
44 | #include "matrix.h" |
||
45 | #include "multisample.h" |
||
46 | #include "points.h" |
||
47 | #include "polygon.h" |
||
48 | #include "shared.h" |
||
49 | #include "scissor.h" |
||
50 | #include "stencil.h" |
||
51 | #include "texenv.h" |
||
52 | #include "texgen.h" |
||
53 | #include "texobj.h" |
||
54 | #include "texparam.h" |
||
55 | #include "texstate.h" |
||
56 | #include "varray.h" |
||
57 | #include "viewport.h" |
||
58 | #include "mtypes.h" |
||
59 | #include "main/dispatch.h" |
||
60 | #include "hash.h" |
||
61 | #include |
||
62 | |||
63 | |||
64 | /** |
||
65 | * glEnable()/glDisable() attribute group (GL_ENABLE_BIT). |
||
66 | */ |
||
67 | struct gl_enable_attrib |
||
68 | { |
||
69 | GLboolean AlphaTest; |
||
70 | GLboolean AutoNormal; |
||
71 | GLboolean Blend; |
||
72 | GLbitfield ClipPlanes; |
||
73 | GLboolean ColorMaterial; |
||
74 | GLboolean CullFace; |
||
75 | GLboolean DepthClamp; |
||
76 | GLboolean DepthTest; |
||
77 | GLboolean Dither; |
||
78 | GLboolean Fog; |
||
79 | GLboolean Light[MAX_LIGHTS]; |
||
80 | GLboolean Lighting; |
||
81 | GLboolean LineSmooth; |
||
82 | GLboolean LineStipple; |
||
83 | GLboolean IndexLogicOp; |
||
84 | GLboolean ColorLogicOp; |
||
85 | |||
86 | GLboolean Map1Color4; |
||
87 | GLboolean Map1Index; |
||
88 | GLboolean Map1Normal; |
||
89 | GLboolean Map1TextureCoord1; |
||
90 | GLboolean Map1TextureCoord2; |
||
91 | GLboolean Map1TextureCoord3; |
||
92 | GLboolean Map1TextureCoord4; |
||
93 | GLboolean Map1Vertex3; |
||
94 | GLboolean Map1Vertex4; |
||
95 | GLboolean Map2Color4; |
||
96 | GLboolean Map2Index; |
||
97 | GLboolean Map2Normal; |
||
98 | GLboolean Map2TextureCoord1; |
||
99 | GLboolean Map2TextureCoord2; |
||
100 | GLboolean Map2TextureCoord3; |
||
101 | GLboolean Map2TextureCoord4; |
||
102 | GLboolean Map2Vertex3; |
||
103 | GLboolean Map2Vertex4; |
||
104 | |||
105 | GLboolean Normalize; |
||
106 | GLboolean PixelTexture; |
||
107 | GLboolean PointSmooth; |
||
108 | GLboolean PolygonOffsetPoint; |
||
109 | GLboolean PolygonOffsetLine; |
||
110 | GLboolean PolygonOffsetFill; |
||
111 | GLboolean PolygonSmooth; |
||
112 | GLboolean PolygonStipple; |
||
113 | GLboolean RescaleNormals; |
||
114 | GLbitfield Scissor; |
||
115 | GLboolean Stencil; |
||
116 | GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */ |
||
117 | GLboolean MultisampleEnabled; /* GL_ARB_multisample */ |
||
118 | GLboolean SampleAlphaToCoverage; /* GL_ARB_multisample */ |
||
119 | GLboolean SampleAlphaToOne; /* GL_ARB_multisample */ |
||
120 | GLboolean SampleCoverage; /* GL_ARB_multisample */ |
||
121 | GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */ |
||
122 | |||
123 | GLbitfield Texture[MAX_TEXTURE_UNITS]; |
||
124 | GLbitfield TexGen[MAX_TEXTURE_UNITS]; |
||
125 | |||
126 | /* GL_ARB_vertex_program */ |
||
127 | GLboolean VertexProgram; |
||
128 | GLboolean VertexProgramPointSize; |
||
129 | GLboolean VertexProgramTwoSide; |
||
130 | |||
131 | /* GL_ARB_fragment_program */ |
||
132 | GLboolean FragmentProgram; |
||
133 | |||
134 | /* GL_ARB_point_sprite / GL_NV_point_sprite */ |
||
135 | GLboolean PointSprite; |
||
136 | GLboolean FragmentShaderATI; |
||
137 | |||
138 | /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */ |
||
139 | GLboolean sRGBEnabled; |
||
140 | }; |
||
141 | |||
142 | |||
143 | /** |
||
144 | * Node for the attribute stack. |
||
145 | */ |
||
146 | struct gl_attrib_node |
||
147 | { |
||
148 | GLbitfield kind; |
||
149 | void *data; |
||
150 | struct gl_attrib_node *next; |
||
151 | }; |
||
152 | |||
153 | |||
154 | |||
155 | /** |
||
156 | * Special struct for saving/restoring texture state (GL_TEXTURE_BIT) |
||
157 | */ |
||
158 | struct texture_state |
||
159 | { |
||
160 | struct gl_texture_attrib Texture; /**< The usual context state */ |
||
161 | |||
162 | /** to save per texture object state (wrap modes, filters, etc): */ |
||
163 | struct gl_texture_object SavedObj[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS]; |
||
164 | |||
165 | /** |
||
166 | * To save references to texture objects (so they don't get accidentally |
||
167 | * deleted while saved in the attribute stack). |
||
168 | */ |
||
169 | struct gl_texture_object *SavedTexRef[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS]; |
||
170 | |||
171 | /* We need to keep a reference to the shared state. That's where the |
||
172 | * default texture objects are kept. We don't want that state to be |
||
173 | * freed while the attribute stack contains pointers to any default |
||
174 | * texture objects. |
||
175 | */ |
||
176 | struct gl_shared_state *SharedRef; |
||
177 | }; |
||
178 | |||
179 | |||
180 | /** |
||
181 | * Allocate new attribute node of given type/kind. Attach payload data. |
||
182 | * Insert it into the linked list named by 'head'. |
||
183 | */ |
||
184 | static bool |
||
185 | save_attrib_data(struct gl_attrib_node **head, |
||
186 | GLbitfield kind, void *payload) |
||
187 | { |
||
188 | struct gl_attrib_node *n = MALLOC_STRUCT(gl_attrib_node); |
||
189 | if (n) { |
||
190 | n->kind = kind; |
||
191 | n->data = payload; |
||
192 | /* insert at head */ |
||
193 | n->next = *head; |
||
194 | *head = n; |
||
195 | } |
||
196 | else { |
||
197 | /* out of memory! */ |
||
198 | return false; |
||
199 | } |
||
200 | return true; |
||
201 | } |
||
202 | |||
203 | |||
204 | /** |
||
205 | * Helper function for_mesa_PushAttrib for simple attributes. |
||
206 | * Allocates memory for attribute data and copies the given attribute data. |
||
207 | * \param head head of linked list to insert attribute data into |
||
208 | * \param attr_bit one of the GL_ |
||
209 | * \param attr_size number of bytes to allocate for attribute data |
||
210 | * \param attr_data the attribute data to copy |
||
211 | * \return true for success, false for out of memory |
||
212 | */ |
||
213 | static bool |
||
214 | push_attrib(struct gl_context *ctx, struct gl_attrib_node **head, |
||
215 | GLbitfield attr_bit, GLuint attr_size, const void *attr_data) |
||
216 | { |
||
217 | void *attribute; |
||
218 | |||
219 | attribute = malloc(attr_size); |
||
220 | if (attribute == NULL) { |
||
221 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
222 | return false; |
||
223 | } |
||
224 | |||
225 | if (save_attrib_data(head, attr_bit, attribute)) { |
||
226 | memcpy(attribute, attr_data, attr_size); |
||
227 | } |
||
228 | else { |
||
229 | free(attribute); |
||
230 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
231 | return false; |
||
232 | } |
||
233 | return true; |
||
234 | } |
||
235 | |||
236 | |||
237 | void GLAPIENTRY |
||
238 | _mesa_PushAttrib(GLbitfield mask) |
||
239 | { |
||
240 | struct gl_attrib_node *head; |
||
241 | |||
242 | GET_CURRENT_CONTEXT(ctx); |
||
243 | |||
244 | if (MESA_VERBOSE & VERBOSE_API) |
||
245 | _mesa_debug(ctx, "glPushAttrib %x\n", (int) mask); |
||
246 | |||
247 | if (ctx->AttribStackDepth >= MAX_ATTRIB_STACK_DEPTH) { |
||
248 | _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushAttrib" ); |
||
249 | return; |
||
250 | } |
||
251 | |||
252 | /* Build linked list of attribute nodes which save all attribute */ |
||
253 | /* groups specified by the mask. */ |
||
254 | head = NULL; |
||
255 | |||
256 | if (mask & GL_ACCUM_BUFFER_BIT) { |
||
257 | if (!push_attrib(ctx, &head, GL_ACCUM_BUFFER_BIT, |
||
258 | sizeof(struct gl_accum_attrib), |
||
259 | (void*)&ctx->Accum)) |
||
260 | goto end; |
||
261 | } |
||
262 | |||
263 | if (mask & GL_COLOR_BUFFER_BIT) { |
||
264 | GLuint i; |
||
265 | struct gl_colorbuffer_attrib *attr; |
||
266 | attr = MALLOC_STRUCT( gl_colorbuffer_attrib ); |
||
267 | if (attr == NULL) { |
||
268 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
269 | goto end; |
||
270 | } |
||
271 | |||
272 | if (save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr)) { |
||
273 | memcpy(attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib)); |
||
274 | /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */ |
||
275 | for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++) |
||
276 | attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i]; |
||
277 | } |
||
278 | else { |
||
279 | free(attr); |
||
280 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
281 | goto end; |
||
282 | } |
||
283 | } |
||
284 | |||
285 | if (mask & GL_CURRENT_BIT) { |
||
286 | FLUSH_CURRENT(ctx, 0); |
||
287 | if (!push_attrib(ctx, &head, GL_CURRENT_BIT, |
||
288 | sizeof(struct gl_current_attrib), |
||
289 | (void*)&ctx->Current)) |
||
290 | goto end; |
||
291 | } |
||
292 | |||
293 | if (mask & GL_DEPTH_BUFFER_BIT) { |
||
294 | if (!push_attrib(ctx, &head, GL_DEPTH_BUFFER_BIT, |
||
295 | sizeof(struct gl_depthbuffer_attrib), |
||
296 | (void*)&ctx->Depth)) |
||
297 | goto end; |
||
298 | } |
||
299 | |||
300 | if (mask & GL_ENABLE_BIT) { |
||
301 | struct gl_enable_attrib *attr; |
||
302 | GLuint i; |
||
303 | attr = MALLOC_STRUCT( gl_enable_attrib ); |
||
304 | if (attr == NULL) { |
||
305 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
306 | goto end; |
||
307 | } |
||
308 | |||
309 | /* Copy enable flags from all other attributes into the enable struct. */ |
||
310 | attr->AlphaTest = ctx->Color.AlphaEnabled; |
||
311 | attr->AutoNormal = ctx->Eval.AutoNormal; |
||
312 | attr->Blend = ctx->Color.BlendEnabled; |
||
313 | attr->ClipPlanes = ctx->Transform.ClipPlanesEnabled; |
||
314 | attr->ColorMaterial = ctx->Light.ColorMaterialEnabled; |
||
315 | attr->CullFace = ctx->Polygon.CullFlag; |
||
316 | attr->DepthClamp = ctx->Transform.DepthClamp; |
||
317 | attr->DepthTest = ctx->Depth.Test; |
||
318 | attr->Dither = ctx->Color.DitherFlag; |
||
319 | attr->Fog = ctx->Fog.Enabled; |
||
320 | for (i = 0; i < ctx->Const.MaxLights; i++) { |
||
321 | attr->Light[i] = ctx->Light.Light[i].Enabled; |
||
322 | } |
||
323 | attr->Lighting = ctx->Light.Enabled; |
||
324 | attr->LineSmooth = ctx->Line.SmoothFlag; |
||
325 | attr->LineStipple = ctx->Line.StippleFlag; |
||
326 | attr->IndexLogicOp = ctx->Color.IndexLogicOpEnabled; |
||
327 | attr->ColorLogicOp = ctx->Color.ColorLogicOpEnabled; |
||
328 | attr->Map1Color4 = ctx->Eval.Map1Color4; |
||
329 | attr->Map1Index = ctx->Eval.Map1Index; |
||
330 | attr->Map1Normal = ctx->Eval.Map1Normal; |
||
331 | attr->Map1TextureCoord1 = ctx->Eval.Map1TextureCoord1; |
||
332 | attr->Map1TextureCoord2 = ctx->Eval.Map1TextureCoord2; |
||
333 | attr->Map1TextureCoord3 = ctx->Eval.Map1TextureCoord3; |
||
334 | attr->Map1TextureCoord4 = ctx->Eval.Map1TextureCoord4; |
||
335 | attr->Map1Vertex3 = ctx->Eval.Map1Vertex3; |
||
336 | attr->Map1Vertex4 = ctx->Eval.Map1Vertex4; |
||
337 | attr->Map2Color4 = ctx->Eval.Map2Color4; |
||
338 | attr->Map2Index = ctx->Eval.Map2Index; |
||
339 | attr->Map2Normal = ctx->Eval.Map2Normal; |
||
340 | attr->Map2TextureCoord1 = ctx->Eval.Map2TextureCoord1; |
||
341 | attr->Map2TextureCoord2 = ctx->Eval.Map2TextureCoord2; |
||
342 | attr->Map2TextureCoord3 = ctx->Eval.Map2TextureCoord3; |
||
343 | attr->Map2TextureCoord4 = ctx->Eval.Map2TextureCoord4; |
||
344 | attr->Map2Vertex3 = ctx->Eval.Map2Vertex3; |
||
345 | attr->Map2Vertex4 = ctx->Eval.Map2Vertex4; |
||
346 | attr->Normalize = ctx->Transform.Normalize; |
||
347 | attr->RasterPositionUnclipped = ctx->Transform.RasterPositionUnclipped; |
||
348 | attr->PointSmooth = ctx->Point.SmoothFlag; |
||
349 | attr->PointSprite = ctx->Point.PointSprite; |
||
350 | attr->PolygonOffsetPoint = ctx->Polygon.OffsetPoint; |
||
351 | attr->PolygonOffsetLine = ctx->Polygon.OffsetLine; |
||
352 | attr->PolygonOffsetFill = ctx->Polygon.OffsetFill; |
||
353 | attr->PolygonSmooth = ctx->Polygon.SmoothFlag; |
||
354 | attr->PolygonStipple = ctx->Polygon.StippleFlag; |
||
355 | attr->RescaleNormals = ctx->Transform.RescaleNormals; |
||
356 | attr->Scissor = ctx->Scissor.EnableFlags; |
||
357 | attr->Stencil = ctx->Stencil.Enabled; |
||
358 | attr->StencilTwoSide = ctx->Stencil.TestTwoSide; |
||
359 | attr->MultisampleEnabled = ctx->Multisample.Enabled; |
||
360 | attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage; |
||
361 | attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne; |
||
362 | attr->SampleCoverage = ctx->Multisample.SampleCoverage; |
||
363 | for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { |
||
364 | attr->Texture[i] = ctx->Texture.Unit[i].Enabled; |
||
365 | attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled; |
||
366 | } |
||
367 | /* GL_ARB_vertex_program */ |
||
368 | attr->VertexProgram = ctx->VertexProgram.Enabled; |
||
369 | attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled; |
||
370 | attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled; |
||
371 | |||
372 | /* GL_ARB_fragment_program */ |
||
373 | attr->FragmentProgram = ctx->FragmentProgram.Enabled; |
||
374 | |||
375 | if (!save_attrib_data(&head, GL_ENABLE_BIT, attr)) { |
||
376 | free(attr); |
||
377 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
378 | goto end; |
||
379 | } |
||
380 | |||
381 | /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */ |
||
382 | attr->sRGBEnabled = ctx->Color.sRGBEnabled; |
||
383 | } |
||
384 | |||
385 | if (mask & GL_EVAL_BIT) { |
||
386 | if (!push_attrib(ctx, &head, GL_EVAL_BIT, |
||
387 | sizeof(struct gl_eval_attrib), |
||
388 | (void*)&ctx->Eval)) |
||
389 | goto end; |
||
390 | } |
||
391 | |||
392 | if (mask & GL_FOG_BIT) { |
||
393 | if (!push_attrib(ctx, &head, GL_FOG_BIT, |
||
394 | sizeof(struct gl_fog_attrib), |
||
395 | (void*)&ctx->Fog)) |
||
396 | goto end; |
||
397 | } |
||
398 | |||
399 | if (mask & GL_HINT_BIT) { |
||
400 | if (!push_attrib(ctx, &head, GL_HINT_BIT, |
||
401 | sizeof(struct gl_hint_attrib), |
||
402 | (void*)&ctx->Hint)) |
||
403 | goto end; |
||
404 | } |
||
405 | |||
406 | if (mask & GL_LIGHTING_BIT) { |
||
407 | FLUSH_CURRENT(ctx, 0); /* flush material changes */ |
||
408 | if (!push_attrib(ctx, &head, GL_LIGHTING_BIT, |
||
409 | sizeof(struct gl_light_attrib), |
||
410 | (void*)&ctx->Light)) |
||
411 | goto end; |
||
412 | } |
||
413 | |||
414 | if (mask & GL_LINE_BIT) { |
||
415 | if (!push_attrib(ctx, &head, GL_LINE_BIT, |
||
416 | sizeof(struct gl_line_attrib), |
||
417 | (void*)&ctx->Line)) |
||
418 | goto end; |
||
419 | } |
||
420 | |||
421 | if (mask & GL_LIST_BIT) { |
||
422 | if (!push_attrib(ctx, &head, GL_LIST_BIT, |
||
423 | sizeof(struct gl_list_attrib), |
||
424 | (void*)&ctx->List)) |
||
425 | goto end; |
||
426 | } |
||
427 | |||
428 | if (mask & GL_PIXEL_MODE_BIT) { |
||
429 | struct gl_pixel_attrib *attr; |
||
430 | attr = MALLOC_STRUCT( gl_pixel_attrib ); |
||
431 | if (attr == NULL) { |
||
432 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
433 | goto end; |
||
434 | } |
||
435 | |||
436 | if (save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr)) { |
||
437 | memcpy(attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib)); |
||
438 | /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */ |
||
439 | attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer; |
||
440 | } |
||
441 | else { |
||
442 | free(attr); |
||
443 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); |
||
444 | goto end; |
||
445 | } |
||
446 | } |
||
447 | |||
448 | if (mask & GL_POINT_BIT) { |
||
449 | if (!push_attrib(ctx, &head, GL_POINT_BIT, |
||
450 | sizeof(struct gl_point_attrib), |
||
451 | (void*)&ctx->Point)) |
||
452 | goto end; |
||
453 | } |
||
454 | |||
455 | if (mask & GL_POLYGON_BIT) { |
||
456 | if (!push_attrib(ctx, &head, GL_POLYGON_BIT, |
||
457 | sizeof(struct gl_polygon_attrib), |
||
458 | (void*)&ctx->Polygon)) |
||
459 | goto end; |
||
460 | } |
||
461 | |||
462 | if (mask & GL_POLYGON_STIPPLE_BIT) { |
||
463 | if (!push_attrib(ctx, &head, GL_POLYGON_STIPPLE_BIT, |
||
464 | sizeof(ctx->PolygonStipple), |
||
465 | (void*)&ctx->PolygonStipple)) |
||
466 | goto end; |
||
467 | } |
||
468 | |||
469 | if (mask & GL_SCISSOR_BIT) { |
||
470 | if (!push_attrib(ctx, &head, GL_SCISSOR_BIT, |
||
471 | sizeof(struct gl_scissor_attrib), |
||
472 | (void*)&ctx->Scissor)) |
||
473 | goto end; |
||
474 | } |
||
475 | |||
476 | if (mask & GL_STENCIL_BUFFER_BIT) { |
||
477 | if (!push_attrib(ctx, &head, GL_STENCIL_BUFFER_BIT, |
||
478 | sizeof(struct gl_stencil_attrib), |
||
479 | (void*)&ctx->Stencil)) |
||
480 | goto end; |
||
481 | } |
||
482 | |||
483 | if (mask & GL_TEXTURE_BIT) { |
||
484 | struct texture_state *texstate = CALLOC_STRUCT(texture_state); |
||
485 | GLuint u, tex; |
||
486 | |||
487 | if (!texstate) { |
||
488 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)"); |
||
489 | goto end; |
||
490 | } |
||
491 | |||
492 | if (!save_attrib_data(&head, GL_TEXTURE_BIT, texstate)) { |
||
493 | free(texstate); |
||
494 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)"); |
||
495 | goto end; |
||
496 | } |
||
497 | |||
498 | _mesa_lock_context_textures(ctx); |
||
499 | |||
500 | /* copy/save the bulk of texture state here */ |
||
501 | memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture)); |
||
502 | |||
503 | /* Save references to the currently bound texture objects so they don't |
||
504 | * accidentally get deleted while referenced in the attribute stack. |
||
505 | */ |
||
506 | for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
||
507 | for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { |
||
508 | _mesa_reference_texobj(&texstate->SavedTexRef[u][tex], |
||
509 | ctx->Texture.Unit[u].CurrentTex[tex]); |
||
510 | } |
||
511 | } |
||
512 | |||
513 | /* copy state/contents of the currently bound texture objects */ |
||
514 | for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
||
515 | for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { |
||
516 | _mesa_copy_texture_object(&texstate->SavedObj[u][tex], |
||
517 | ctx->Texture.Unit[u].CurrentTex[tex]); |
||
518 | } |
||
519 | } |
||
520 | |||
521 | _mesa_reference_shared_state(ctx, &texstate->SharedRef, ctx->Shared); |
||
522 | |||
523 | _mesa_unlock_context_textures(ctx); |
||
524 | } |
||
525 | |||
526 | if (mask & GL_TRANSFORM_BIT) { |
||
527 | if (!push_attrib(ctx, &head, GL_TRANSFORM_BIT, |
||
528 | sizeof(struct gl_transform_attrib), |
||
529 | (void*)&ctx->Transform)) |
||
530 | goto end; |
||
531 | } |
||
532 | |||
533 | if (mask & GL_VIEWPORT_BIT) { |
||
534 | if (!push_attrib(ctx, &head, GL_VIEWPORT_BIT, |
||
535 | sizeof(struct gl_viewport_attrib) |
||
536 | * ctx->Const.MaxViewports, |
||
537 | (void*)&ctx->ViewportArray)) |
||
538 | goto end; |
||
539 | } |
||
540 | |||
541 | /* GL_ARB_multisample */ |
||
542 | if (mask & GL_MULTISAMPLE_BIT_ARB) { |
||
543 | if (!push_attrib(ctx, &head, GL_MULTISAMPLE_BIT_ARB, |
||
544 | sizeof(struct gl_multisample_attrib), |
||
545 | (void*)&ctx->Multisample)) |
||
546 | goto end; |
||
547 | } |
||
548 | |||
549 | end: |
||
550 | if (head != NULL) { |
||
551 | ctx->AttribStack[ctx->AttribStackDepth] = head; |
||
552 | ctx->AttribStackDepth++; |
||
553 | } |
||
554 | } |
||
555 | |||
556 | |||
557 | |||
558 | static void |
||
559 | pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable) |
||
560 | { |
||
561 | const GLuint curTexUnitSave = ctx->Texture.CurrentUnit; |
||
562 | GLuint i; |
||
563 | |||
564 | #define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \ |
||
565 | if ((VALUE) != (NEWVALUE)) { \ |
||
566 | _mesa_set_enable( ctx, ENUM, (NEWVALUE) ); \ |
||
567 | } |
||
568 | |||
569 | TEST_AND_UPDATE(ctx->Color.AlphaEnabled, enable->AlphaTest, GL_ALPHA_TEST); |
||
570 | if (ctx->Color.BlendEnabled != enable->Blend) { |
||
571 | if (ctx->Extensions.EXT_draw_buffers2) { |
||
572 | GLuint i; |
||
573 | for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { |
||
574 | _mesa_set_enablei(ctx, GL_BLEND, i, (enable->Blend >> i) & 1); |
||
575 | } |
||
576 | } |
||
577 | else { |
||
578 | _mesa_set_enable(ctx, GL_BLEND, (enable->Blend & 1)); |
||
579 | } |
||
580 | } |
||
581 | |||
582 | for (i=0;i |
||
583 | const GLuint mask = 1 << i; |
||
584 | if ((ctx->Transform.ClipPlanesEnabled & mask) != (enable->ClipPlanes & mask)) |
||
585 | _mesa_set_enable(ctx, (GLenum) (GL_CLIP_PLANE0 + i), |
||
586 | !!(enable->ClipPlanes & mask)); |
||
587 | } |
||
588 | |||
589 | TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial, |
||
590 | GL_COLOR_MATERIAL); |
||
591 | TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE); |
||
592 | TEST_AND_UPDATE(ctx->Transform.DepthClamp, enable->DepthClamp, |
||
593 | GL_DEPTH_CLAMP); |
||
594 | TEST_AND_UPDATE(ctx->Depth.Test, enable->DepthTest, GL_DEPTH_TEST); |
||
595 | TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER); |
||
596 | TEST_AND_UPDATE(ctx->Fog.Enabled, enable->Fog, GL_FOG); |
||
597 | TEST_AND_UPDATE(ctx->Light.Enabled, enable->Lighting, GL_LIGHTING); |
||
598 | TEST_AND_UPDATE(ctx->Line.SmoothFlag, enable->LineSmooth, GL_LINE_SMOOTH); |
||
599 | TEST_AND_UPDATE(ctx->Line.StippleFlag, enable->LineStipple, |
||
600 | GL_LINE_STIPPLE); |
||
601 | TEST_AND_UPDATE(ctx->Color.IndexLogicOpEnabled, enable->IndexLogicOp, |
||
602 | GL_INDEX_LOGIC_OP); |
||
603 | TEST_AND_UPDATE(ctx->Color.ColorLogicOpEnabled, enable->ColorLogicOp, |
||
604 | GL_COLOR_LOGIC_OP); |
||
605 | |||
606 | TEST_AND_UPDATE(ctx->Eval.Map1Color4, enable->Map1Color4, GL_MAP1_COLOR_4); |
||
607 | TEST_AND_UPDATE(ctx->Eval.Map1Index, enable->Map1Index, GL_MAP1_INDEX); |
||
608 | TEST_AND_UPDATE(ctx->Eval.Map1Normal, enable->Map1Normal, GL_MAP1_NORMAL); |
||
609 | TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord1, enable->Map1TextureCoord1, |
||
610 | GL_MAP1_TEXTURE_COORD_1); |
||
611 | TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord2, enable->Map1TextureCoord2, |
||
612 | GL_MAP1_TEXTURE_COORD_2); |
||
613 | TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord3, enable->Map1TextureCoord3, |
||
614 | GL_MAP1_TEXTURE_COORD_3); |
||
615 | TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord4, enable->Map1TextureCoord4, |
||
616 | GL_MAP1_TEXTURE_COORD_4); |
||
617 | TEST_AND_UPDATE(ctx->Eval.Map1Vertex3, enable->Map1Vertex3, |
||
618 | GL_MAP1_VERTEX_3); |
||
619 | TEST_AND_UPDATE(ctx->Eval.Map1Vertex4, enable->Map1Vertex4, |
||
620 | GL_MAP1_VERTEX_4); |
||
621 | |||
622 | TEST_AND_UPDATE(ctx->Eval.Map2Color4, enable->Map2Color4, GL_MAP2_COLOR_4); |
||
623 | TEST_AND_UPDATE(ctx->Eval.Map2Index, enable->Map2Index, GL_MAP2_INDEX); |
||
624 | TEST_AND_UPDATE(ctx->Eval.Map2Normal, enable->Map2Normal, GL_MAP2_NORMAL); |
||
625 | TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord1, enable->Map2TextureCoord1, |
||
626 | GL_MAP2_TEXTURE_COORD_1); |
||
627 | TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord2, enable->Map2TextureCoord2, |
||
628 | GL_MAP2_TEXTURE_COORD_2); |
||
629 | TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord3, enable->Map2TextureCoord3, |
||
630 | GL_MAP2_TEXTURE_COORD_3); |
||
631 | TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord4, enable->Map2TextureCoord4, |
||
632 | GL_MAP2_TEXTURE_COORD_4); |
||
633 | TEST_AND_UPDATE(ctx->Eval.Map2Vertex3, enable->Map2Vertex3, |
||
634 | GL_MAP2_VERTEX_3); |
||
635 | TEST_AND_UPDATE(ctx->Eval.Map2Vertex4, enable->Map2Vertex4, |
||
636 | GL_MAP2_VERTEX_4); |
||
637 | |||
638 | TEST_AND_UPDATE(ctx->Eval.AutoNormal, enable->AutoNormal, GL_AUTO_NORMAL); |
||
639 | TEST_AND_UPDATE(ctx->Transform.Normalize, enable->Normalize, GL_NORMALIZE); |
||
640 | TEST_AND_UPDATE(ctx->Transform.RescaleNormals, enable->RescaleNormals, |
||
641 | GL_RESCALE_NORMAL_EXT); |
||
642 | TEST_AND_UPDATE(ctx->Transform.RasterPositionUnclipped, |
||
643 | enable->RasterPositionUnclipped, |
||
644 | GL_RASTER_POSITION_UNCLIPPED_IBM); |
||
645 | TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth, |
||
646 | GL_POINT_SMOOTH); |
||
647 | if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) { |
||
648 | TEST_AND_UPDATE(ctx->Point.PointSprite, enable->PointSprite, |
||
649 | GL_POINT_SPRITE_NV); |
||
650 | } |
||
651 | TEST_AND_UPDATE(ctx->Polygon.OffsetPoint, enable->PolygonOffsetPoint, |
||
652 | GL_POLYGON_OFFSET_POINT); |
||
653 | TEST_AND_UPDATE(ctx->Polygon.OffsetLine, enable->PolygonOffsetLine, |
||
654 | GL_POLYGON_OFFSET_LINE); |
||
655 | TEST_AND_UPDATE(ctx->Polygon.OffsetFill, enable->PolygonOffsetFill, |
||
656 | GL_POLYGON_OFFSET_FILL); |
||
657 | TEST_AND_UPDATE(ctx->Polygon.SmoothFlag, enable->PolygonSmooth, |
||
658 | GL_POLYGON_SMOOTH); |
||
659 | TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple, |
||
660 | GL_POLYGON_STIPPLE); |
||
661 | if (ctx->Scissor.EnableFlags != enable->Scissor) { |
||
662 | unsigned i; |
||
663 | |||
664 | for (i = 0; i < ctx->Const.MaxViewports; i++) { |
||
665 | _mesa_set_enablei(ctx, GL_SCISSOR_TEST, i, (enable->Scissor >> i) & 1); |
||
666 | } |
||
667 | } |
||
668 | TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST); |
||
669 | if (ctx->Extensions.EXT_stencil_two_side) { |
||
670 | TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT); |
||
671 | } |
||
672 | TEST_AND_UPDATE(ctx->Multisample.Enabled, enable->MultisampleEnabled, |
||
673 | GL_MULTISAMPLE_ARB); |
||
674 | TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage, |
||
675 | enable->SampleAlphaToCoverage, |
||
676 | GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); |
||
677 | TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToOne, |
||
678 | enable->SampleAlphaToOne, |
||
679 | GL_SAMPLE_ALPHA_TO_ONE_ARB); |
||
680 | TEST_AND_UPDATE(ctx->Multisample.SampleCoverage, |
||
681 | enable->SampleCoverage, |
||
682 | GL_SAMPLE_COVERAGE_ARB); |
||
683 | /* GL_ARB_vertex_program */ |
||
684 | TEST_AND_UPDATE(ctx->VertexProgram.Enabled, |
||
685 | enable->VertexProgram, |
||
686 | GL_VERTEX_PROGRAM_ARB); |
||
687 | TEST_AND_UPDATE(ctx->VertexProgram.PointSizeEnabled, |
||
688 | enable->VertexProgramPointSize, |
||
689 | GL_VERTEX_PROGRAM_POINT_SIZE_ARB); |
||
690 | TEST_AND_UPDATE(ctx->VertexProgram.TwoSideEnabled, |
||
691 | enable->VertexProgramTwoSide, |
||
692 | GL_VERTEX_PROGRAM_TWO_SIDE_ARB); |
||
693 | |||
694 | /* GL_ARB_fragment_program */ |
||
695 | TEST_AND_UPDATE(ctx->FragmentProgram.Enabled, |
||
696 | enable->FragmentProgram, |
||
697 | GL_FRAGMENT_PROGRAM_ARB); |
||
698 | |||
699 | /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */ |
||
700 | TEST_AND_UPDATE(ctx->Color.sRGBEnabled, enable->sRGBEnabled, |
||
701 | GL_FRAMEBUFFER_SRGB); |
||
702 | |||
703 | /* texture unit enables */ |
||
704 | for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { |
||
705 | const GLbitfield enabled = enable->Texture[i]; |
||
706 | const GLbitfield genEnabled = enable->TexGen[i]; |
||
707 | |||
708 | if (ctx->Texture.Unit[i].Enabled != enabled) { |
||
709 | _mesa_ActiveTexture(GL_TEXTURE0 + i); |
||
710 | |||
711 | _mesa_set_enable(ctx, GL_TEXTURE_1D, !!(enabled & TEXTURE_1D_BIT)); |
||
712 | _mesa_set_enable(ctx, GL_TEXTURE_2D, !!(enabled & TEXTURE_2D_BIT)); |
||
713 | _mesa_set_enable(ctx, GL_TEXTURE_3D, !!(enabled & TEXTURE_3D_BIT)); |
||
714 | if (ctx->Extensions.NV_texture_rectangle) { |
||
715 | _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_ARB, |
||
716 | !!(enabled & TEXTURE_RECT_BIT)); |
||
717 | } |
||
718 | if (ctx->Extensions.ARB_texture_cube_map) { |
||
719 | _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, |
||
720 | !!(enabled & TEXTURE_CUBE_BIT)); |
||
721 | } |
||
722 | } |
||
723 | |||
724 | if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) { |
||
725 | _mesa_ActiveTexture(GL_TEXTURE0 + i); |
||
726 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, !!(genEnabled & S_BIT)); |
||
727 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, !!(genEnabled & T_BIT)); |
||
728 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, !!(genEnabled & R_BIT)); |
||
729 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, !!(genEnabled & Q_BIT)); |
||
730 | } |
||
731 | } |
||
732 | |||
733 | _mesa_ActiveTexture(GL_TEXTURE0 + curTexUnitSave); |
||
734 | } |
||
735 | |||
736 | |||
737 | /** |
||
738 | * Pop/restore texture attribute/group state. |
||
739 | */ |
||
740 | static void |
||
741 | pop_texture_group(struct gl_context *ctx, struct texture_state *texstate) |
||
742 | { |
||
743 | GLuint u; |
||
744 | |||
745 | _mesa_lock_context_textures(ctx); |
||
746 | |||
747 | for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
||
748 | const struct gl_texture_unit *unit = &texstate->Texture.Unit[u]; |
||
749 | GLuint tgt; |
||
750 | |||
751 | _mesa_ActiveTexture(GL_TEXTURE0_ARB + u); |
||
752 | _mesa_set_enable(ctx, GL_TEXTURE_1D, !!(unit->Enabled & TEXTURE_1D_BIT)); |
||
753 | _mesa_set_enable(ctx, GL_TEXTURE_2D, !!(unit->Enabled & TEXTURE_2D_BIT)); |
||
754 | _mesa_set_enable(ctx, GL_TEXTURE_3D, !!(unit->Enabled & TEXTURE_3D_BIT)); |
||
755 | if (ctx->Extensions.ARB_texture_cube_map) { |
||
756 | _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB, |
||
757 | !!(unit->Enabled & TEXTURE_CUBE_BIT)); |
||
758 | } |
||
759 | if (ctx->Extensions.NV_texture_rectangle) { |
||
760 | _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV, |
||
761 | !!(unit->Enabled & TEXTURE_RECT_BIT)); |
||
762 | } |
||
763 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode); |
||
764 | _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor); |
||
765 | _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode); |
||
766 | _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenT.Mode); |
||
767 | _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenR.Mode); |
||
768 | _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenQ.Mode); |
||
769 | _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->GenS.ObjectPlane); |
||
770 | _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->GenT.ObjectPlane); |
||
771 | _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->GenR.ObjectPlane); |
||
772 | _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->GenQ.ObjectPlane); |
||
773 | /* Eye plane done differently to avoid re-transformation */ |
||
774 | { |
||
775 | struct gl_texture_unit *destUnit = &ctx->Texture.Unit[u]; |
||
776 | COPY_4FV(destUnit->GenS.EyePlane, unit->GenS.EyePlane); |
||
777 | COPY_4FV(destUnit->GenT.EyePlane, unit->GenT.EyePlane); |
||
778 | COPY_4FV(destUnit->GenR.EyePlane, unit->GenR.EyePlane); |
||
779 | COPY_4FV(destUnit->GenQ.EyePlane, unit->GenQ.EyePlane); |
||
780 | if (ctx->Driver.TexGen) { |
||
781 | ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->GenS.EyePlane); |
||
782 | ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->GenT.EyePlane); |
||
783 | ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->GenR.EyePlane); |
||
784 | ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->GenQ.EyePlane); |
||
785 | } |
||
786 | } |
||
787 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, !!(unit->TexGenEnabled & S_BIT)); |
||
788 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, !!(unit->TexGenEnabled & T_BIT)); |
||
789 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, !!(unit->TexGenEnabled & R_BIT)); |
||
790 | _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, !!(unit->TexGenEnabled & Q_BIT)); |
||
791 | _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, |
||
792 | unit->LodBias); |
||
793 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, |
||
794 | unit->Combine.ModeRGB); |
||
795 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, |
||
796 | unit->Combine.ModeA); |
||
797 | { |
||
798 | const GLuint n = ctx->Extensions.NV_texture_env_combine4 ? 4 : 3; |
||
799 | GLuint i; |
||
800 | for (i = 0; i < n; i++) { |
||
801 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB + i, |
||
802 | unit->Combine.SourceRGB[i]); |
||
803 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA + i, |
||
804 | unit->Combine.SourceA[i]); |
||
805 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB + i, |
||
806 | unit->Combine.OperandRGB[i]); |
||
807 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA + i, |
||
808 | unit->Combine.OperandA[i]); |
||
809 | } |
||
810 | } |
||
811 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, |
||
812 | 1 << unit->Combine.ScaleShiftRGB); |
||
813 | _mesa_TexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, |
||
814 | 1 << unit->Combine.ScaleShiftA); |
||
815 | |||
816 | /* Restore texture object state for each target */ |
||
817 | for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { |
||
818 | const struct gl_texture_object *obj = NULL; |
||
819 | const struct gl_sampler_object *samp; |
||
820 | GLenum target; |
||
821 | |||
822 | obj = &texstate->SavedObj[u][tgt]; |
||
823 | |||
824 | /* don't restore state for unsupported targets to prevent |
||
825 | * raising GL errors. |
||
826 | */ |
||
827 | if (obj->Target == GL_TEXTURE_CUBE_MAP_ARB && |
||
828 | !ctx->Extensions.ARB_texture_cube_map) { |
||
829 | continue; |
||
830 | } |
||
831 | else if (obj->Target == GL_TEXTURE_RECTANGLE_NV && |
||
832 | !ctx->Extensions.NV_texture_rectangle) { |
||
833 | continue; |
||
834 | } |
||
835 | else if ((obj->Target == GL_TEXTURE_1D_ARRAY_EXT || |
||
836 | obj->Target == GL_TEXTURE_2D_ARRAY_EXT) && |
||
837 | !ctx->Extensions.EXT_texture_array) { |
||
838 | continue; |
||
839 | } |
||
840 | else if (obj->Target == GL_TEXTURE_CUBE_MAP_ARRAY && |
||
841 | !ctx->Extensions.ARB_texture_cube_map_array) { |
||
842 | continue; |
||
843 | } else if (obj->Target == GL_TEXTURE_BUFFER) |
||
844 | continue; |
||
845 | else if (obj->Target == GL_TEXTURE_EXTERNAL_OES) |
||
846 | continue; |
||
847 | else if (obj->Target == GL_TEXTURE_2D_MULTISAMPLE || |
||
848 | obj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
||
849 | continue; |
||
850 | |||
851 | target = obj->Target; |
||
852 | |||
853 | _mesa_BindTexture(target, obj->Name); |
||
854 | |||
855 | samp = &obj->Sampler; |
||
856 | |||
857 | _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, samp->BorderColor.f); |
||
858 | _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, samp->WrapS); |
||
859 | _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, samp->WrapT); |
||
860 | _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, samp->WrapR); |
||
861 | _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, samp->MinFilter); |
||
862 | _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, samp->MagFilter); |
||
863 | _mesa_TexParameterf(target, GL_TEXTURE_MIN_LOD, samp->MinLod); |
||
864 | _mesa_TexParameterf(target, GL_TEXTURE_MAX_LOD, samp->MaxLod); |
||
865 | _mesa_TexParameterf(target, GL_TEXTURE_LOD_BIAS, samp->LodBias); |
||
866 | _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority); |
||
867 | _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, obj->BaseLevel); |
||
868 | if (target != GL_TEXTURE_RECTANGLE_ARB) |
||
869 | _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel); |
||
870 | if (ctx->Extensions.EXT_texture_filter_anisotropic) { |
||
871 | _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, |
||
872 | samp->MaxAnisotropy); |
||
873 | } |
||
874 | if (ctx->Extensions.ARB_shadow) { |
||
875 | _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_MODE, |
||
876 | samp->CompareMode); |
||
877 | _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_FUNC, |
||
878 | samp->CompareFunc); |
||
879 | } |
||
880 | if (ctx->Extensions.ARB_depth_texture) |
||
881 | _mesa_TexParameteri(target, GL_DEPTH_TEXTURE_MODE, obj->DepthMode); |
||
882 | } |
||
883 | |||
884 | /* remove saved references to the texture objects */ |
||
885 | for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { |
||
886 | _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL); |
||
887 | } |
||
888 | } |
||
889 | |||
890 | _mesa_ActiveTexture(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit); |
||
891 | |||
892 | _mesa_reference_shared_state(ctx, &texstate->SharedRef, NULL); |
||
893 | |||
894 | _mesa_unlock_context_textures(ctx); |
||
895 | } |
||
896 | |||
897 | |||
898 | /* |
||
899 | * This function is kind of long just because we have to call a lot |
||
900 | * of device driver functions to update device driver state. |
||
901 | * |
||
902 | * XXX As it is now, most of the pop-code calls immediate-mode Mesa functions |
||
903 | * in order to restore GL state. This isn't terribly efficient but it |
||
904 | * ensures that dirty flags and any derived state gets updated correctly. |
||
905 | * We could at least check if the value to restore equals the current value |
||
906 | * and then skip the Mesa call. |
||
907 | */ |
||
908 | void GLAPIENTRY |
||
909 | _mesa_PopAttrib(void) |
||
910 | { |
||
911 | struct gl_attrib_node *attr, *next; |
||
912 | GET_CURRENT_CONTEXT(ctx); |
||
913 | FLUSH_VERTICES(ctx, 0); |
||
914 | |||
915 | if (ctx->AttribStackDepth == 0) { |
||
916 | _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" ); |
||
917 | return; |
||
918 | } |
||
919 | |||
920 | ctx->AttribStackDepth--; |
||
921 | attr = ctx->AttribStack[ctx->AttribStackDepth]; |
||
922 | |||
923 | while (attr) { |
||
924 | |||
925 | if (MESA_VERBOSE & VERBOSE_API) { |
||
926 | _mesa_debug(ctx, "glPopAttrib %s\n", |
||
927 | _mesa_lookup_enum_by_nr(attr->kind)); |
||
928 | } |
||
929 | |||
930 | switch (attr->kind) { |
||
931 | case GL_ACCUM_BUFFER_BIT: |
||
932 | { |
||
933 | const struct gl_accum_attrib *accum; |
||
934 | accum = (const struct gl_accum_attrib *) attr->data; |
||
935 | _mesa_ClearAccum(accum->ClearColor[0], |
||
936 | accum->ClearColor[1], |
||
937 | accum->ClearColor[2], |
||
938 | accum->ClearColor[3]); |
||
939 | } |
||
940 | break; |
||
941 | case GL_COLOR_BUFFER_BIT: |
||
942 | { |
||
943 | const struct gl_colorbuffer_attrib *color; |
||
944 | |||
945 | color = (const struct gl_colorbuffer_attrib *) attr->data; |
||
946 | _mesa_ClearIndex((GLfloat) color->ClearIndex); |
||
947 | _mesa_ClearColor(color->ClearColor.f[0], |
||
948 | color->ClearColor.f[1], |
||
949 | color->ClearColor.f[2], |
||
950 | color->ClearColor.f[3]); |
||
951 | _mesa_IndexMask(color->IndexMask); |
||
952 | if (!ctx->Extensions.EXT_draw_buffers2) { |
||
953 | _mesa_ColorMask((GLboolean) (color->ColorMask[0][0] != 0), |
||
954 | (GLboolean) (color->ColorMask[0][1] != 0), |
||
955 | (GLboolean) (color->ColorMask[0][2] != 0), |
||
956 | (GLboolean) (color->ColorMask[0][3] != 0)); |
||
957 | } |
||
958 | else { |
||
959 | GLuint i; |
||
960 | for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { |
||
961 | _mesa_ColorMaski(i, |
||
962 | (GLboolean) (color->ColorMask[i][0] != 0), |
||
963 | (GLboolean) (color->ColorMask[i][1] != 0), |
||
964 | (GLboolean) (color->ColorMask[i][2] != 0), |
||
965 | (GLboolean) (color->ColorMask[i][3] != 0)); |
||
966 | } |
||
967 | } |
||
968 | { |
||
969 | /* Need to determine if more than one color output is |
||
970 | * specified. If so, call glDrawBuffersARB, else call |
||
971 | * glDrawBuffer(). This is a subtle, but essential point |
||
972 | * since GL_FRONT (for example) is illegal for the former |
||
973 | * function, but legal for the later. |
||
974 | */ |
||
975 | GLboolean multipleBuffers = GL_FALSE; |
||
976 | GLuint i; |
||
977 | |||
978 | for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) { |
||
979 | if (color->DrawBuffer[i] != GL_NONE) { |
||
980 | multipleBuffers = GL_TRUE; |
||
981 | break; |
||
982 | } |
||
983 | } |
||
984 | /* Call the API_level functions, not _mesa_drawbuffers() |
||
985 | * since we need to do error checking on the pop'd |
||
986 | * GL_DRAW_BUFFER. |
||
987 | * Ex: if GL_FRONT were pushed, but we're popping with a |
||
988 | * user FBO bound, GL_FRONT will be illegal and we'll need |
||
989 | * to record that error. Per OpenGL ARB decision. |
||
990 | */ |
||
991 | if (multipleBuffers) |
||
992 | _mesa_DrawBuffers(ctx->Const.MaxDrawBuffers, |
||
993 | color->DrawBuffer); |
||
994 | else |
||
995 | _mesa_DrawBuffer(color->DrawBuffer[0]); |
||
996 | } |
||
997 | _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled); |
||
998 | _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRefUnclamped); |
||
999 | if (ctx->Color.BlendEnabled != color->BlendEnabled) { |
||
1000 | if (ctx->Extensions.EXT_draw_buffers2) { |
||
1001 | GLuint i; |
||
1002 | for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { |
||
1003 | _mesa_set_enablei(ctx, GL_BLEND, i, |
||
1004 | (color->BlendEnabled >> i) & 1); |
||
1005 | } |
||
1006 | } |
||
1007 | else { |
||
1008 | _mesa_set_enable(ctx, GL_BLEND, (color->BlendEnabled & 1)); |
||
1009 | } |
||
1010 | } |
||
1011 | if (ctx->Color._BlendFuncPerBuffer || |
||
1012 | ctx->Color._BlendEquationPerBuffer) { |
||
1013 | /* set blend per buffer */ |
||
1014 | GLuint buf; |
||
1015 | for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { |
||
1016 | _mesa_BlendFuncSeparateiARB(buf, color->Blend[buf].SrcRGB, |
||
1017 | color->Blend[buf].DstRGB, |
||
1018 | color->Blend[buf].SrcA, |
||
1019 | color->Blend[buf].DstA); |
||
1020 | _mesa_BlendEquationSeparateiARB(buf, |
||
1021 | color->Blend[buf].EquationRGB, |
||
1022 | color->Blend[buf].EquationA); |
||
1023 | } |
||
1024 | } |
||
1025 | else { |
||
1026 | /* set same blend modes for all buffers */ |
||
1027 | _mesa_BlendFuncSeparate(color->Blend[0].SrcRGB, |
||
1028 | color->Blend[0].DstRGB, |
||
1029 | color->Blend[0].SrcA, |
||
1030 | color->Blend[0].DstA); |
||
1031 | /* This special case is because glBlendEquationSeparateEXT |
||
1032 | * cannot take GL_LOGIC_OP as a parameter. |
||
1033 | */ |
||
1034 | if (color->Blend[0].EquationRGB == |
||
1035 | color->Blend[0].EquationA) { |
||
1036 | _mesa_BlendEquation(color->Blend[0].EquationRGB); |
||
1037 | } |
||
1038 | else { |
||
1039 | _mesa_BlendEquationSeparate( |
||
1040 | color->Blend[0].EquationRGB, |
||
1041 | color->Blend[0].EquationA); |
||
1042 | } |
||
1043 | } |
||
1044 | _mesa_BlendColor(color->BlendColorUnclamped[0], |
||
1045 | color->BlendColorUnclamped[1], |
||
1046 | color->BlendColorUnclamped[2], |
||
1047 | color->BlendColorUnclamped[3]); |
||
1048 | _mesa_LogicOp(color->LogicOp); |
||
1049 | _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, |
||
1050 | color->ColorLogicOpEnabled); |
||
1051 | _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP, |
||
1052 | color->IndexLogicOpEnabled); |
||
1053 | _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag); |
||
1054 | if (ctx->Extensions.ARB_color_buffer_float) |
||
1055 | _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, |
||
1056 | color->ClampFragmentColor); |
||
1057 | _mesa_ClampColor(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor); |
||
1058 | |||
1059 | /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */ |
||
1060 | if (ctx->Extensions.EXT_framebuffer_sRGB) |
||
1061 | _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB, color->sRGBEnabled); |
||
1062 | } |
||
1063 | break; |
||
1064 | case GL_CURRENT_BIT: |
||
1065 | FLUSH_CURRENT( ctx, 0 ); |
||
1066 | memcpy( &ctx->Current, attr->data, |
||
1067 | sizeof(struct gl_current_attrib) ); |
||
1068 | break; |
||
1069 | case GL_DEPTH_BUFFER_BIT: |
||
1070 | { |
||
1071 | const struct gl_depthbuffer_attrib *depth; |
||
1072 | depth = (const struct gl_depthbuffer_attrib *) attr->data; |
||
1073 | _mesa_DepthFunc(depth->Func); |
||
1074 | _mesa_ClearDepth(depth->Clear); |
||
1075 | _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test); |
||
1076 | _mesa_DepthMask(depth->Mask); |
||
1077 | } |
||
1078 | break; |
||
1079 | case GL_ENABLE_BIT: |
||
1080 | { |
||
1081 | const struct gl_enable_attrib *enable; |
||
1082 | enable = (const struct gl_enable_attrib *) attr->data; |
||
1083 | pop_enable_group(ctx, enable); |
||
1084 | ctx->NewState |= _NEW_ALL; |
||
1085 | } |
||
1086 | break; |
||
1087 | case GL_EVAL_BIT: |
||
1088 | memcpy( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) ); |
||
1089 | ctx->NewState |= _NEW_EVAL; |
||
1090 | break; |
||
1091 | case GL_FOG_BIT: |
||
1092 | { |
||
1093 | const struct gl_fog_attrib *fog; |
||
1094 | fog = (const struct gl_fog_attrib *) attr->data; |
||
1095 | _mesa_set_enable(ctx, GL_FOG, fog->Enabled); |
||
1096 | _mesa_Fogfv(GL_FOG_COLOR, fog->Color); |
||
1097 | _mesa_Fogf(GL_FOG_DENSITY, fog->Density); |
||
1098 | _mesa_Fogf(GL_FOG_START, fog->Start); |
||
1099 | _mesa_Fogf(GL_FOG_END, fog->End); |
||
1100 | _mesa_Fogf(GL_FOG_INDEX, fog->Index); |
||
1101 | _mesa_Fogi(GL_FOG_MODE, fog->Mode); |
||
1102 | } |
||
1103 | break; |
||
1104 | case GL_HINT_BIT: |
||
1105 | { |
||
1106 | const struct gl_hint_attrib *hint; |
||
1107 | hint = (const struct gl_hint_attrib *) attr->data; |
||
1108 | _mesa_Hint(GL_PERSPECTIVE_CORRECTION_HINT, |
||
1109 | hint->PerspectiveCorrection ); |
||
1110 | _mesa_Hint(GL_POINT_SMOOTH_HINT, hint->PointSmooth); |
||
1111 | _mesa_Hint(GL_LINE_SMOOTH_HINT, hint->LineSmooth); |
||
1112 | _mesa_Hint(GL_POLYGON_SMOOTH_HINT, hint->PolygonSmooth); |
||
1113 | _mesa_Hint(GL_FOG_HINT, hint->Fog); |
||
1114 | _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB, |
||
1115 | hint->TextureCompression); |
||
1116 | } |
||
1117 | break; |
||
1118 | case GL_LIGHTING_BIT: |
||
1119 | { |
||
1120 | GLuint i; |
||
1121 | const struct gl_light_attrib *light; |
||
1122 | light = (const struct gl_light_attrib *) attr->data; |
||
1123 | /* lighting enable */ |
||
1124 | _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled); |
||
1125 | /* per-light state */ |
||
1126 | if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) |
||
1127 | _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); |
||
1128 | |||
1129 | for (i = 0; i < ctx->Const.MaxLights; i++) { |
||
1130 | const struct gl_light *l = &light->Light[i]; |
||
1131 | _mesa_set_enable(ctx, GL_LIGHT0 + i, l->Enabled); |
||
1132 | _mesa_light(ctx, i, GL_AMBIENT, l->Ambient); |
||
1133 | _mesa_light(ctx, i, GL_DIFFUSE, l->Diffuse); |
||
1134 | _mesa_light(ctx, i, GL_SPECULAR, l->Specular ); |
||
1135 | _mesa_light(ctx, i, GL_POSITION, l->EyePosition); |
||
1136 | _mesa_light(ctx, i, GL_SPOT_DIRECTION, l->SpotDirection); |
||
1137 | { |
||
1138 | GLfloat p[4] = { 0 }; |
||
1139 | p[0] = l->SpotExponent; |
||
1140 | _mesa_light(ctx, i, GL_SPOT_EXPONENT, p); |
||
1141 | } |
||
1142 | { |
||
1143 | GLfloat p[4] = { 0 }; |
||
1144 | p[0] = l->SpotCutoff; |
||
1145 | _mesa_light(ctx, i, GL_SPOT_CUTOFF, p); |
||
1146 | } |
||
1147 | { |
||
1148 | GLfloat p[4] = { 0 }; |
||
1149 | p[0] = l->ConstantAttenuation; |
||
1150 | _mesa_light(ctx, i, GL_CONSTANT_ATTENUATION, p); |
||
1151 | } |
||
1152 | { |
||
1153 | GLfloat p[4] = { 0 }; |
||
1154 | p[0] = l->LinearAttenuation; |
||
1155 | _mesa_light(ctx, i, GL_LINEAR_ATTENUATION, p); |
||
1156 | } |
||
1157 | { |
||
1158 | GLfloat p[4] = { 0 }; |
||
1159 | p[0] = l->QuadraticAttenuation; |
||
1160 | _mesa_light(ctx, i, GL_QUADRATIC_ATTENUATION, p); |
||
1161 | } |
||
1162 | } |
||
1163 | /* light model */ |
||
1164 | _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT, |
||
1165 | light->Model.Ambient); |
||
1166 | _mesa_LightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, |
||
1167 | (GLfloat) light->Model.LocalViewer); |
||
1168 | _mesa_LightModelf(GL_LIGHT_MODEL_TWO_SIDE, |
||
1169 | (GLfloat) light->Model.TwoSide); |
||
1170 | _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL, |
||
1171 | (GLfloat) light->Model.ColorControl); |
||
1172 | /* shade model */ |
||
1173 | _mesa_ShadeModel(light->ShadeModel); |
||
1174 | /* color material */ |
||
1175 | _mesa_ColorMaterial(light->ColorMaterialFace, |
||
1176 | light->ColorMaterialMode); |
||
1177 | _mesa_set_enable(ctx, GL_COLOR_MATERIAL, |
||
1178 | light->ColorMaterialEnabled); |
||
1179 | /* materials */ |
||
1180 | memcpy(&ctx->Light.Material, &light->Material, |
||
1181 | sizeof(struct gl_material)); |
||
1182 | if (ctx->Extensions.ARB_color_buffer_float) { |
||
1183 | _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR_ARB, |
||
1184 | light->ClampVertexColor); |
||
1185 | } |
||
1186 | } |
||
1187 | break; |
||
1188 | case GL_LINE_BIT: |
||
1189 | { |
||
1190 | const struct gl_line_attrib *line; |
||
1191 | line = (const struct gl_line_attrib *) attr->data; |
||
1192 | _mesa_set_enable(ctx, GL_LINE_SMOOTH, line->SmoothFlag); |
||
1193 | _mesa_set_enable(ctx, GL_LINE_STIPPLE, line->StippleFlag); |
||
1194 | _mesa_LineStipple(line->StippleFactor, line->StipplePattern); |
||
1195 | _mesa_LineWidth(line->Width); |
||
1196 | } |
||
1197 | break; |
||
1198 | case GL_LIST_BIT: |
||
1199 | memcpy( &ctx->List, attr->data, sizeof(struct gl_list_attrib) ); |
||
1200 | break; |
||
1201 | case GL_PIXEL_MODE_BIT: |
||
1202 | memcpy( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) ); |
||
1203 | /* XXX what other pixel state needs to be set by function calls? */ |
||
1204 | _mesa_ReadBuffer(ctx->Pixel.ReadBuffer); |
||
1205 | ctx->NewState |= _NEW_PIXEL; |
||
1206 | break; |
||
1207 | case GL_POINT_BIT: |
||
1208 | { |
||
1209 | const struct gl_point_attrib *point; |
||
1210 | point = (const struct gl_point_attrib *) attr->data; |
||
1211 | _mesa_PointSize(point->Size); |
||
1212 | _mesa_set_enable(ctx, GL_POINT_SMOOTH, point->SmoothFlag); |
||
1213 | if (ctx->Extensions.EXT_point_parameters) { |
||
1214 | _mesa_PointParameterfv(GL_DISTANCE_ATTENUATION_EXT, |
||
1215 | point->Params); |
||
1216 | _mesa_PointParameterf(GL_POINT_SIZE_MIN_EXT, |
||
1217 | point->MinSize); |
||
1218 | _mesa_PointParameterf(GL_POINT_SIZE_MAX_EXT, |
||
1219 | point->MaxSize); |
||
1220 | _mesa_PointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT, |
||
1221 | point->Threshold); |
||
1222 | } |
||
1223 | if (ctx->Extensions.NV_point_sprite |
||
1224 | || ctx->Extensions.ARB_point_sprite) { |
||
1225 | GLuint u; |
||
1226 | for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
||
1227 | _mesa_TexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV, |
||
1228 | (GLint) point->CoordReplace[u]); |
||
1229 | } |
||
1230 | _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite); |
||
1231 | if (ctx->Extensions.NV_point_sprite) |
||
1232 | _mesa_PointParameteri(GL_POINT_SPRITE_R_MODE_NV, |
||
1233 | ctx->Point.SpriteRMode); |
||
1234 | |||
1235 | if ((ctx->API == API_OPENGL_COMPAT && ctx->Version >= 20) |
||
1236 | || ctx->API == API_OPENGL_CORE) |
||
1237 | _mesa_PointParameterf(GL_POINT_SPRITE_COORD_ORIGIN, |
||
1238 | (GLfloat)ctx->Point.SpriteOrigin); |
||
1239 | } |
||
1240 | } |
||
1241 | break; |
||
1242 | case GL_POLYGON_BIT: |
||
1243 | { |
||
1244 | const struct gl_polygon_attrib *polygon; |
||
1245 | polygon = (const struct gl_polygon_attrib *) attr->data; |
||
1246 | _mesa_CullFace(polygon->CullFaceMode); |
||
1247 | _mesa_FrontFace(polygon->FrontFace); |
||
1248 | _mesa_PolygonMode(GL_FRONT, polygon->FrontMode); |
||
1249 | _mesa_PolygonMode(GL_BACK, polygon->BackMode); |
||
1250 | _mesa_polygon_offset_clamp(ctx, |
||
1251 | polygon->OffsetFactor, |
||
1252 | polygon->OffsetUnits, |
||
1253 | polygon->OffsetClamp); |
||
1254 | _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, polygon->SmoothFlag); |
||
1255 | _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, polygon->StippleFlag); |
||
1256 | _mesa_set_enable(ctx, GL_CULL_FACE, polygon->CullFlag); |
||
1257 | _mesa_set_enable(ctx, GL_POLYGON_OFFSET_POINT, |
||
1258 | polygon->OffsetPoint); |
||
1259 | _mesa_set_enable(ctx, GL_POLYGON_OFFSET_LINE, |
||
1260 | polygon->OffsetLine); |
||
1261 | _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, |
||
1262 | polygon->OffsetFill); |
||
1263 | } |
||
1264 | break; |
||
1265 | case GL_POLYGON_STIPPLE_BIT: |
||
1266 | memcpy( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) ); |
||
1267 | ctx->NewState |= _NEW_POLYGONSTIPPLE; |
||
1268 | if (ctx->Driver.PolygonStipple) |
||
1269 | ctx->Driver.PolygonStipple( ctx, (const GLubyte *) attr->data ); |
||
1270 | break; |
||
1271 | case GL_SCISSOR_BIT: |
||
1272 | { |
||
1273 | unsigned i; |
||
1274 | const struct gl_scissor_attrib *scissor; |
||
1275 | scissor = (const struct gl_scissor_attrib *) attr->data; |
||
1276 | |||
1277 | for (i = 0; i < ctx->Const.MaxViewports; i++) { |
||
1278 | _mesa_set_scissor(ctx, i, |
||
1279 | scissor->ScissorArray[i].X, |
||
1280 | scissor->ScissorArray[i].Y, |
||
1281 | scissor->ScissorArray[i].Width, |
||
1282 | scissor->ScissorArray[i].Height); |
||
1283 | _mesa_set_enablei(ctx, GL_SCISSOR_TEST, i, |
||
1284 | (scissor->EnableFlags >> i) & 1); |
||
1285 | } |
||
1286 | } |
||
1287 | break; |
||
1288 | case GL_STENCIL_BUFFER_BIT: |
||
1289 | { |
||
1290 | const struct gl_stencil_attrib *stencil; |
||
1291 | stencil = (const struct gl_stencil_attrib *) attr->data; |
||
1292 | _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); |
||
1293 | _mesa_ClearStencil(stencil->Clear); |
||
1294 | if (ctx->Extensions.EXT_stencil_two_side) { |
||
1295 | _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, |
||
1296 | stencil->TestTwoSide); |
||
1297 | _mesa_ActiveStencilFaceEXT(stencil->ActiveFace |
||
1298 | ? GL_BACK : GL_FRONT); |
||
1299 | } |
||
1300 | /* front state */ |
||
1301 | _mesa_StencilFuncSeparate(GL_FRONT, |
||
1302 | stencil->Function[0], |
||
1303 | stencil->Ref[0], |
||
1304 | stencil->ValueMask[0]); |
||
1305 | _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]); |
||
1306 | _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0], |
||
1307 | stencil->ZFailFunc[0], |
||
1308 | stencil->ZPassFunc[0]); |
||
1309 | /* back state */ |
||
1310 | _mesa_StencilFuncSeparate(GL_BACK, |
||
1311 | stencil->Function[1], |
||
1312 | stencil->Ref[1], |
||
1313 | stencil->ValueMask[1]); |
||
1314 | _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]); |
||
1315 | _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1], |
||
1316 | stencil->ZFailFunc[1], |
||
1317 | stencil->ZPassFunc[1]); |
||
1318 | } |
||
1319 | break; |
||
1320 | case GL_TRANSFORM_BIT: |
||
1321 | { |
||
1322 | GLuint i; |
||
1323 | const struct gl_transform_attrib *xform; |
||
1324 | xform = (const struct gl_transform_attrib *) attr->data; |
||
1325 | _mesa_MatrixMode(xform->MatrixMode); |
||
1326 | if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top)) |
||
1327 | _math_matrix_analyse( ctx->ProjectionMatrixStack.Top ); |
||
1328 | |||
1329 | /* restore clip planes */ |
||
1330 | for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { |
||
1331 | const GLuint mask = 1 << i; |
||
1332 | const GLfloat *eyePlane = xform->EyeUserPlane[i]; |
||
1333 | COPY_4V(ctx->Transform.EyeUserPlane[i], eyePlane); |
||
1334 | _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, |
||
1335 | !!(xform->ClipPlanesEnabled & mask)); |
||
1336 | if (ctx->Driver.ClipPlane) |
||
1337 | ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, eyePlane ); |
||
1338 | } |
||
1339 | |||
1340 | /* normalize/rescale */ |
||
1341 | if (xform->Normalize != ctx->Transform.Normalize) |
||
1342 | _mesa_set_enable(ctx, GL_NORMALIZE,ctx->Transform.Normalize); |
||
1343 | if (xform->RescaleNormals != ctx->Transform.RescaleNormals) |
||
1344 | _mesa_set_enable(ctx, GL_RESCALE_NORMAL_EXT, |
||
1345 | ctx->Transform.RescaleNormals); |
||
1346 | if (xform->DepthClamp != ctx->Transform.DepthClamp) |
||
1347 | _mesa_set_enable(ctx, GL_DEPTH_CLAMP, |
||
1348 | ctx->Transform.DepthClamp); |
||
1349 | if (ctx->Extensions.ARB_clip_control) |
||
1350 | _mesa_ClipControl(xform->ClipOrigin, xform->ClipDepthMode); |
||
1351 | } |
||
1352 | break; |
||
1353 | case GL_TEXTURE_BIT: |
||
1354 | { |
||
1355 | struct texture_state *texstate |
||
1356 | = (struct texture_state *) attr->data; |
||
1357 | pop_texture_group(ctx, texstate); |
||
1358 | ctx->NewState |= _NEW_TEXTURE; |
||
1359 | } |
||
1360 | break; |
||
1361 | case GL_VIEWPORT_BIT: |
||
1362 | { |
||
1363 | unsigned i; |
||
1364 | const struct gl_viewport_attrib *vp; |
||
1365 | vp = (const struct gl_viewport_attrib *) attr->data; |
||
1366 | |||
1367 | for (i = 0; i < ctx->Const.MaxViewports; i++) { |
||
1368 | _mesa_set_viewport(ctx, i, vp[i].X, vp[i].Y, vp[i].Width, |
||
1369 | vp[i].Height); |
||
1370 | _mesa_set_depth_range(ctx, i, vp[i].Near, vp[i].Far); |
||
1371 | } |
||
1372 | } |
||
1373 | break; |
||
1374 | case GL_MULTISAMPLE_BIT_ARB: |
||
1375 | { |
||
1376 | const struct gl_multisample_attrib *ms; |
||
1377 | ms = (const struct gl_multisample_attrib *) attr->data; |
||
1378 | |||
1379 | TEST_AND_UPDATE(ctx->Multisample.Enabled, |
||
1380 | ms->Enabled, |
||
1381 | GL_MULTISAMPLE); |
||
1382 | |||
1383 | TEST_AND_UPDATE(ctx->Multisample.SampleCoverage, |
||
1384 | ms->SampleCoverage, |
||
1385 | GL_SAMPLE_COVERAGE); |
||
1386 | |||
1387 | TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage, |
||
1388 | ms->SampleAlphaToCoverage, |
||
1389 | GL_SAMPLE_ALPHA_TO_COVERAGE); |
||
1390 | |||
1391 | TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToOne, |
||
1392 | ms->SampleAlphaToOne, |
||
1393 | GL_SAMPLE_ALPHA_TO_ONE); |
||
1394 | |||
1395 | _mesa_SampleCoverage(ms->SampleCoverageValue, |
||
1396 | ms->SampleCoverageInvert); |
||
1397 | } |
||
1398 | break; |
||
1399 | |||
1400 | default: |
||
1401 | _mesa_problem( ctx, "Bad attrib flag in PopAttrib"); |
||
1402 | break; |
||
1403 | } |
||
1404 | |||
1405 | next = attr->next; |
||
1406 | free(attr->data); |
||
1407 | free(attr); |
||
1408 | attr = next; |
||
1409 | } |
||
1410 | } |
||
1411 | |||
1412 | |||
1413 | /** |
||
1414 | * Copy gl_pixelstore_attrib from src to dst, updating buffer |
||
1415 | * object refcounts. |
||
1416 | */ |
||
1417 | static void |
||
1418 | copy_pixelstore(struct gl_context *ctx, |
||
1419 | struct gl_pixelstore_attrib *dst, |
||
1420 | const struct gl_pixelstore_attrib *src) |
||
1421 | { |
||
1422 | dst->Alignment = src->Alignment; |
||
1423 | dst->RowLength = src->RowLength; |
||
1424 | dst->SkipPixels = src->SkipPixels; |
||
1425 | dst->SkipRows = src->SkipRows; |
||
1426 | dst->ImageHeight = src->ImageHeight; |
||
1427 | dst->SkipImages = src->SkipImages; |
||
1428 | dst->SwapBytes = src->SwapBytes; |
||
1429 | dst->LsbFirst = src->LsbFirst; |
||
1430 | dst->Invert = src->Invert; |
||
1431 | _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); |
||
1432 | } |
||
1433 | |||
1434 | |||
1435 | #define GL_CLIENT_PACK_BIT (1<<20) |
||
1436 | #define GL_CLIENT_UNPACK_BIT (1<<21) |
||
1437 | |||
1438 | /** |
||
1439 | * Copy gl_vertex_array_object from src to dest. |
||
1440 | * 'dest' must be in an initialized state. |
||
1441 | */ |
||
1442 | static void |
||
1443 | copy_array_object(struct gl_context *ctx, |
||
1444 | struct gl_vertex_array_object *dest, |
||
1445 | struct gl_vertex_array_object *src) |
||
1446 | { |
||
1447 | GLuint i; |
||
1448 | |||
1449 | /* skip Name */ |
||
1450 | /* skip RefCount */ |
||
1451 | |||
1452 | /* In theory must be the same anyway, but on recreate make sure it matches */ |
||
1453 | dest->ARBsemantics = src->ARBsemantics; |
||
1454 | |||
1455 | for (i = 0; i < ARRAY_SIZE(src->VertexAttrib); i++) { |
||
1456 | _mesa_copy_client_array(ctx, &dest->_VertexAttrib[i], &src->_VertexAttrib[i]); |
||
1457 | _mesa_copy_vertex_attrib_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]); |
||
1458 | _mesa_copy_vertex_buffer_binding(ctx, &dest->VertexBinding[i], &src->VertexBinding[i]); |
||
1459 | } |
||
1460 | |||
1461 | /* _Enabled must be the same than on push */ |
||
1462 | dest->_Enabled = src->_Enabled; |
||
1463 | dest->NewArrays = src->NewArrays; |
||
1464 | } |
||
1465 | |||
1466 | /** |
||
1467 | * Copy gl_array_attrib from src to dest. |
||
1468 | * 'dest' must be in an initialized state. |
||
1469 | */ |
||
1470 | static void |
||
1471 | copy_array_attrib(struct gl_context *ctx, |
||
1472 | struct gl_array_attrib *dest, |
||
1473 | struct gl_array_attrib *src, |
||
1474 | bool vbo_deleted) |
||
1475 | { |
||
1476 | /* skip ArrayObj */ |
||
1477 | /* skip DefaultArrayObj, Objects */ |
||
1478 | dest->ActiveTexture = src->ActiveTexture; |
||
1479 | dest->LockFirst = src->LockFirst; |
||
1480 | dest->LockCount = src->LockCount; |
||
1481 | dest->PrimitiveRestart = src->PrimitiveRestart; |
||
1482 | dest->PrimitiveRestartFixedIndex = src->PrimitiveRestartFixedIndex; |
||
1483 | dest->_PrimitiveRestart = src->_PrimitiveRestart; |
||
1484 | dest->RestartIndex = src->RestartIndex; |
||
1485 | /* skip NewState */ |
||
1486 | /* skip RebindArrays */ |
||
1487 | |||
1488 | if (!vbo_deleted) |
||
1489 | copy_array_object(ctx, dest->VAO, src->VAO); |
||
1490 | |||
1491 | /* skip ArrayBufferObj */ |
||
1492 | /* skip IndexBufferObj */ |
||
1493 | |||
1494 | /* Invalidate draw state. It will be updated during the next draw. */ |
||
1495 | dest->DrawMethod = DRAW_NONE; |
||
1496 | dest->_DrawArrays = NULL; |
||
1497 | } |
||
1498 | |||
1499 | /** |
||
1500 | * Save the content of src to dest. |
||
1501 | */ |
||
1502 | static void |
||
1503 | save_array_attrib(struct gl_context *ctx, |
||
1504 | struct gl_array_attrib *dest, |
||
1505 | struct gl_array_attrib *src) |
||
1506 | { |
||
1507 | /* Set the Name, needed for restore, but do never overwrite. |
||
1508 | * Needs to match value in the object hash. */ |
||
1509 | dest->VAO->Name = src->VAO->Name; |
||
1510 | /* And copy all of the rest. */ |
||
1511 | copy_array_attrib(ctx, dest, src, false); |
||
1512 | |||
1513 | /* Just reference them here */ |
||
1514 | _mesa_reference_buffer_object(ctx, &dest->ArrayBufferObj, |
||
1515 | src->ArrayBufferObj); |
||
1516 | _mesa_reference_buffer_object(ctx, &dest->VAO->IndexBufferObj, |
||
1517 | src->VAO->IndexBufferObj); |
||
1518 | } |
||
1519 | |||
1520 | /** |
||
1521 | * Restore the content of src to dest. |
||
1522 | */ |
||
1523 | static void |
||
1524 | restore_array_attrib(struct gl_context *ctx, |
||
1525 | struct gl_array_attrib *dest, |
||
1526 | struct gl_array_attrib *src) |
||
1527 | { |
||
1528 | /* The ARB_vertex_array_object spec says: |
||
1529 | * |
||
1530 | * "BindVertexArray fails and an INVALID_OPERATION error is generated |
||
1531 | * if array is not a name returned from a previous call to |
||
1532 | * GenVertexArrays, or if such a name has since been deleted with |
||
1533 | * DeleteVertexArrays." |
||
1534 | * |
||
1535 | * Therefore popping a deleted VAO cannot magically recreate it. |
||
1536 | * |
||
1537 | * The semantics of objects created using APPLE_vertex_array_objects behave |
||
1538 | * differently. These objects expect to be recreated by pop. Alas. |
||
1539 | */ |
||
1540 | const bool arb_vao = (src->VAO->Name != 0 |
||
1541 | && src->VAO->ARBsemantics); |
||
1542 | |||
1543 | if (arb_vao && !_mesa_IsVertexArray(src->VAO->Name)) |
||
1544 | return; |
||
1545 | |||
1546 | _mesa_BindVertexArrayAPPLE(src->VAO->Name); |
||
1547 | |||
1548 | /* Restore or recreate the buffer objects by the names ... */ |
||
1549 | if (!arb_vao |
||
1550 | || src->ArrayBufferObj->Name == 0 |
||
1551 | || _mesa_IsBuffer(src->ArrayBufferObj->Name)) { |
||
1552 | /* ... and restore its content */ |
||
1553 | copy_array_attrib(ctx, dest, src, false); |
||
1554 | |||
1555 | _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, |
||
1556 | src->ArrayBufferObj->Name); |
||
1557 | } else { |
||
1558 | copy_array_attrib(ctx, dest, src, true); |
||
1559 | } |
||
1560 | |||
1561 | if (!arb_vao |
||
1562 | || src->VAO->IndexBufferObj->Name == 0 |
||
1563 | || _mesa_IsBuffer(src->VAO->IndexBufferObj->Name)) |
||
1564 | _mesa_BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, |
||
1565 | src->VAO->IndexBufferObj->Name); |
||
1566 | } |
||
1567 | |||
1568 | /** |
||
1569 | * init/alloc the fields of 'attrib'. |
||
1570 | * Needs to the init part matching free_array_attrib_data below. |
||
1571 | */ |
||
1572 | static bool |
||
1573 | init_array_attrib_data(struct gl_context *ctx, |
||
1574 | struct gl_array_attrib *attrib) |
||
1575 | { |
||
1576 | /* Get a non driver gl_vertex_array_object. */ |
||
1577 | attrib->VAO = CALLOC_STRUCT( gl_vertex_array_object ); |
||
1578 | |||
1579 | if (attrib->VAO == NULL) { |
||
1580 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); |
||
1581 | return false; |
||
1582 | } |
||
1583 | |||
1584 | _mesa_initialize_vao(ctx, attrib->VAO, 0); |
||
1585 | return true; |
||
1586 | } |
||
1587 | |||
1588 | /** |
||
1589 | * Free/unreference the fields of 'attrib' but don't delete it (that's |
||
1590 | * done later in the calling code). |
||
1591 | * Needs to the cleanup part matching init_array_attrib_data above. |
||
1592 | */ |
||
1593 | static void |
||
1594 | free_array_attrib_data(struct gl_context *ctx, |
||
1595 | struct gl_array_attrib *attrib) |
||
1596 | { |
||
1597 | /* We use a non driver array object, so don't just unref since we would |
||
1598 | * end up using the drivers DeleteArrayObject function for deletion. */ |
||
1599 | _mesa_delete_vao(ctx, attrib->VAO); |
||
1600 | attrib->VAO = 0; |
||
1601 | _mesa_reference_buffer_object(ctx, &attrib->ArrayBufferObj, NULL); |
||
1602 | } |
||
1603 | |||
1604 | |||
1605 | void GLAPIENTRY |
||
1606 | _mesa_PushClientAttrib(GLbitfield mask) |
||
1607 | { |
||
1608 | struct gl_attrib_node *head; |
||
1609 | |||
1610 | GET_CURRENT_CONTEXT(ctx); |
||
1611 | |||
1612 | if (ctx->ClientAttribStackDepth >= MAX_CLIENT_ATTRIB_STACK_DEPTH) { |
||
1613 | _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushClientAttrib" ); |
||
1614 | return; |
||
1615 | } |
||
1616 | |||
1617 | /* Build linked list of attribute nodes which save all attribute |
||
1618 | * groups specified by the mask. |
||
1619 | */ |
||
1620 | head = NULL; |
||
1621 | |||
1622 | if (mask & GL_CLIENT_PIXEL_STORE_BIT) { |
||
1623 | struct gl_pixelstore_attrib *attr; |
||
1624 | /* packing attribs */ |
||
1625 | attr = CALLOC_STRUCT( gl_pixelstore_attrib ); |
||
1626 | if (attr == NULL) { |
||
1627 | _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" ); |
||
1628 | goto end; |
||
1629 | } |
||
1630 | if (save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr)) { |
||
1631 | copy_pixelstore(ctx, attr, &ctx->Pack); |
||
1632 | } |
||
1633 | else { |
||
1634 | _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" ); |
||
1635 | free(attr); |
||
1636 | goto end; |
||
1637 | } |
||
1638 | |||
1639 | /* unpacking attribs */ |
||
1640 | attr = CALLOC_STRUCT( gl_pixelstore_attrib ); |
||
1641 | if (attr == NULL) { |
||
1642 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); |
||
1643 | goto end; |
||
1644 | } |
||
1645 | |||
1646 | if (save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr)) { |
||
1647 | copy_pixelstore(ctx, attr, &ctx->Unpack); |
||
1648 | } |
||
1649 | else { |
||
1650 | _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" ); |
||
1651 | free(attr); |
||
1652 | goto end; |
||
1653 | } |
||
1654 | } |
||
1655 | |||
1656 | if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { |
||
1657 | struct gl_array_attrib *attr; |
||
1658 | attr = CALLOC_STRUCT( gl_array_attrib ); |
||
1659 | if (attr == NULL) { |
||
1660 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); |
||
1661 | goto end; |
||
1662 | } |
||
1663 | |||
1664 | if (!init_array_attrib_data(ctx, attr)) { |
||
1665 | free(attr); |
||
1666 | goto end; |
||
1667 | } |
||
1668 | |||
1669 | if (save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr)) { |
||
1670 | save_array_attrib(ctx, attr, &ctx->Array); |
||
1671 | } |
||
1672 | else { |
||
1673 | free_array_attrib_data(ctx, attr); |
||
1674 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); |
||
1675 | free(attr); |
||
1676 | /* goto to keep safe from possible later changes */ |
||
1677 | goto end; |
||
1678 | } |
||
1679 | } |
||
1680 | end: |
||
1681 | if (head != NULL) { |
||
1682 | ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head; |
||
1683 | ctx->ClientAttribStackDepth++; |
||
1684 | } |
||
1685 | } |
||
1686 | |||
1687 | |||
1688 | |||
1689 | |||
1690 | void GLAPIENTRY |
||
1691 | _mesa_PopClientAttrib(void) |
||
1692 | { |
||
1693 | struct gl_attrib_node *node, *next; |
||
1694 | |||
1695 | GET_CURRENT_CONTEXT(ctx); |
||
1696 | FLUSH_VERTICES(ctx, 0); |
||
1697 | |||
1698 | if (ctx->ClientAttribStackDepth == 0) { |
||
1699 | _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" ); |
||
1700 | return; |
||
1701 | } |
||
1702 | |||
1703 | ctx->ClientAttribStackDepth--; |
||
1704 | node = ctx->ClientAttribStack[ctx->ClientAttribStackDepth]; |
||
1705 | |||
1706 | while (node) { |
||
1707 | switch (node->kind) { |
||
1708 | case GL_CLIENT_PACK_BIT: |
||
1709 | { |
||
1710 | struct gl_pixelstore_attrib *store = |
||
1711 | (struct gl_pixelstore_attrib *) node->data; |
||
1712 | copy_pixelstore(ctx, &ctx->Pack, store); |
||
1713 | _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL); |
||
1714 | } |
||
1715 | break; |
||
1716 | case GL_CLIENT_UNPACK_BIT: |
||
1717 | { |
||
1718 | struct gl_pixelstore_attrib *store = |
||
1719 | (struct gl_pixelstore_attrib *) node->data; |
||
1720 | copy_pixelstore(ctx, &ctx->Unpack, store); |
||
1721 | _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL); |
||
1722 | } |
||
1723 | break; |
||
1724 | case GL_CLIENT_VERTEX_ARRAY_BIT: { |
||
1725 | struct gl_array_attrib * attr = |
||
1726 | (struct gl_array_attrib *) node->data; |
||
1727 | restore_array_attrib(ctx, &ctx->Array, attr); |
||
1728 | free_array_attrib_data(ctx, attr); |
||
1729 | ctx->NewState |= _NEW_ARRAY; |
||
1730 | break; |
||
1731 | } |
||
1732 | default: |
||
1733 | _mesa_problem( ctx, "Bad attrib flag in PopClientAttrib"); |
||
1734 | break; |
||
1735 | } |
||
1736 | |||
1737 | next = node->next; |
||
1738 | free(node->data); |
||
1739 | free(node); |
||
1740 | node = next; |
||
1741 | } |
||
1742 | } |
||
1743 | |||
1744 | |||
1745 | /** |
||
1746 | * Free any attribute state data that might be attached to the context. |
||
1747 | */ |
||
1748 | void |
||
1749 | _mesa_free_attrib_data(struct gl_context *ctx) |
||
1750 | { |
||
1751 | while (ctx->AttribStackDepth > 0) { |
||
1752 | struct gl_attrib_node *attr, *next; |
||
1753 | |||
1754 | ctx->AttribStackDepth--; |
||
1755 | attr = ctx->AttribStack[ctx->AttribStackDepth]; |
||
1756 | |||
1757 | while (attr) { |
||
1758 | if (attr->kind == GL_TEXTURE_BIT) { |
||
1759 | struct texture_state *texstate = (struct texture_state*)attr->data; |
||
1760 | GLuint u, tgt; |
||
1761 | /* clear references to the saved texture objects */ |
||
1762 | for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
||
1763 | for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { |
||
1764 | _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL); |
||
1765 | } |
||
1766 | } |
||
1767 | _mesa_reference_shared_state(ctx, &texstate->SharedRef, NULL); |
||
1768 | } |
||
1769 | else { |
||
1770 | /* any other chunks of state that requires special handling? */ |
||
1771 | } |
||
1772 | |||
1773 | next = attr->next; |
||
1774 | free(attr->data); |
||
1775 | free(attr); |
||
1776 | attr = next; |
||
1777 | } |
||
1778 | } |
||
1779 | } |
||
1780 | |||
1781 | |||
1782 | void _mesa_init_attrib( struct gl_context *ctx ) |
||
1783 | { |
||
1784 | /* Renderer and client attribute stacks */ |
||
1785 | ctx->AttribStackDepth = 0; |
||
1786 | ctx->ClientAttribStackDepth = 0; |
||
1787 | }>>>21) |