2 * Mesa 3-D graphics library
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Meta operations. Some GL operations can be expressed in terms of
27 * other GL operations. For example, glBlitFramebuffer() can be done
28 * with texture mapping and glClear() can be done with polygon rendering.
34 #include "main/glheader.h"
35 #include "main/mtypes.h"
36 #include "main/imports.h"
37 #include "main/arrayobj.h"
38 #include "main/blend.h"
39 #include "main/bufferobj.h"
40 #include "main/buffers.h"
41 #include "main/colortab.h"
42 #include "main/context.h"
43 #include "main/depth.h"
44 #include "main/enable.h"
45 #include "main/feedback.h"
46 #include "main/formats.h"
47 #include "main/image.h"
48 #include "main/macros.h"
49 #include "main/matrix.h"
50 #include "main/pixel.h"
51 #include "main/polygon.h"
52 #include "main/readpix.h"
53 #include "main/scissor.h"
54 #include "main/state.h"
55 #include "main/stencil.h"
56 #include "main/texobj.h"
57 #include "main/texenv.h"
58 #include "main/texgetimage.h"
59 #include "main/teximage.h"
60 #include "main/texparam.h"
61 #include "main/texstate.h"
62 #include "main/varray.h"
63 #include "main/viewport.h"
64 #include "swrast/swrast.h"
65 #include "drivers/common/meta.h"
68 /** Return offset in bytes of the field within a vertex struct */
69 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
72 * State which we may save/restore across meta ops.
73 * XXX this may be incomplete...
77 GLbitfield SavedState
; /**< bitmask of MESA_META_* flags */
79 /** MESA_META_ALPHA_TEST */
80 GLboolean AlphaEnabled
;
84 /** MESA_META_BLEND */
85 GLbitfield BlendEnabled
;
86 GLboolean ColorLogicOpEnabled
;
88 /** MESA_META_COLOR_MASK */
91 /** MESA_META_DEPTH_TEST */
92 struct gl_depthbuffer_attrib Depth
;
97 /** MESA_META_PIXEL_STORE */
98 struct gl_pixelstore_attrib Pack
, Unpack
;
100 /** MESA_META_PIXEL_TRANSFER */
101 GLfloat RedBias
, RedScale
;
102 GLfloat GreenBias
, GreenScale
;
103 GLfloat BlueBias
, BlueScale
;
104 GLfloat AlphaBias
, AlphaScale
;
105 GLfloat DepthBias
, DepthScale
;
106 GLboolean MapColorFlag
;
108 /** MESA_META_RASTERIZATION */
109 GLenum FrontPolygonMode
, BackPolygonMode
;
110 GLboolean PolygonOffset
;
111 GLboolean PolygonSmooth
;
112 GLboolean PolygonStipple
;
113 GLboolean PolygonCull
;
115 /** MESA_META_SCISSOR */
116 struct gl_scissor_attrib Scissor
;
118 /** MESA_META_STENCIL_TEST */
119 struct gl_stencil_attrib Stencil
;
121 /** MESA_META_TRANSFORM */
123 GLfloat ModelviewMatrix
[16];
124 GLfloat ProjectionMatrix
[16];
125 GLfloat TextureMatrix
[16];
127 /** MESA_META_CLIP */
128 GLbitfield ClipPlanesEnabled
;
130 /** MESA_META_TEXTURE */
131 struct gl_texture_object
*CurrentTexture
[NUM_TEXTURE_TARGETS
];
132 /** mask of TEXTURE_2D_BIT, etc */
133 GLbitfield TexEnabled
;
134 GLbitfield TexGenEnabled
;
135 GLuint EnvMode
; /* unit[0] only */
137 /** MESA_META_VERTEX */
138 struct gl_array_object
*ArrayObj
;
139 struct gl_buffer_object
*ArrayBufferObj
;
141 /** MESA_META_VIEWPORT */
142 GLint ViewportX
, ViewportY
, ViewportW
, ViewportH
;
143 GLclampd DepthNear
, DepthFar
;
145 /** MESA_META_SELECT_FEEDBACK */
147 struct gl_selection Select
;
148 struct gl_feedback Feedback
;
150 /** Miscellaneous (always disabled) */
152 GLboolean RasterDiscard
;
157 * State for glBlitFramebufer()
168 * State for glClear()
177 GLuint IntegerShaderProg
;
178 GLint IntegerColorLocation
;
183 * State for glCopyPixels()
191 #define MAX_META_OPS_DEPTH 8
193 * All per-context meta state.
197 /** Stack of state saved during meta-ops */
198 struct save_state Save
[MAX_META_OPS_DEPTH
];
199 /** Save stack depth */
200 GLuint SaveStackDepth
;
202 struct copypix_state CopyPix
; /**< For _mesa_meta_CopyPixels() */
206 * Initialize meta-ops for a context.
207 * To be called once during context creation.
210 _mesa_meta_init(struct gl_context
*ctx
)
214 ctx
->Meta
= CALLOC_STRUCT(gl_meta_state
);
219 * Free context meta-op state.
220 * To be called once during context destruction.
223 _mesa_meta_free(struct gl_context
*ctx
)
225 GET_CURRENT_CONTEXT(old_context
);
226 _mesa_make_current(ctx
, NULL
, NULL
);
228 _mesa_make_current(old_context
, old_context
->WinSysDrawBuffer
, old_context
->WinSysReadBuffer
);
230 _mesa_make_current(NULL
, NULL
, NULL
);
237 * Enter meta state. This is like a light-weight version of glPushAttrib
238 * but it also resets most GL state back to default values.
240 * \param state bitmask of MESA_META_* flags indicating which attribute groups
241 * to save and reset to their defaults
244 _mesa_meta_begin(struct gl_context
*ctx
, GLbitfield state
)
246 struct save_state
*save
;
248 /* hope MAX_META_OPS_DEPTH is large enough */
249 assert(ctx
->Meta
->SaveStackDepth
< MAX_META_OPS_DEPTH
);
251 save
= &ctx
->Meta
->Save
[ctx
->Meta
->SaveStackDepth
++];
252 memset(save
, 0, sizeof(*save
));
253 save
->SavedState
= state
;
255 if (state
& MESA_META_ALPHA_TEST
) {
256 save
->AlphaEnabled
= ctx
->Color
.AlphaEnabled
;
257 save
->AlphaFunc
= ctx
->Color
.AlphaFunc
;
258 save
->AlphaRef
= ctx
->Color
.AlphaRef
;
259 if (ctx
->Color
.AlphaEnabled
)
260 _mesa_set_enable(ctx
, GL_ALPHA_TEST
, GL_FALSE
);
263 if (state
& MESA_META_BLEND
) {
264 save
->BlendEnabled
= ctx
->Color
.BlendEnabled
;
265 if (ctx
->Color
.BlendEnabled
) {
266 _mesa_set_enable(ctx
, GL_BLEND
, GL_FALSE
);
268 save
->ColorLogicOpEnabled
= ctx
->Color
.ColorLogicOpEnabled
;
269 if (ctx
->Color
.ColorLogicOpEnabled
)
270 _mesa_set_enable(ctx
, GL_COLOR_LOGIC_OP
, GL_FALSE
);
273 if (state
& MESA_META_COLOR_MASK
) {
274 memcpy(save
->ColorMask
, ctx
->Color
.ColorMask
,
275 sizeof(ctx
->Color
.ColorMask
));
276 if (!ctx
->Color
.ColorMask
[0] ||
277 !ctx
->Color
.ColorMask
[1] ||
278 !ctx
->Color
.ColorMask
[2] ||
279 !ctx
->Color
.ColorMask
[3])
280 _mesa_ColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
283 if (state
& MESA_META_DEPTH_TEST
) {
284 save
->Depth
= ctx
->Depth
; /* struct copy */
286 _mesa_set_enable(ctx
, GL_DEPTH_TEST
, GL_FALSE
);
289 if (state
& MESA_META_FOG
) {
290 save
->Fog
= ctx
->Fog
.Enabled
;
291 if (ctx
->Fog
.Enabled
)
292 _mesa_set_enable(ctx
, GL_FOG
, GL_FALSE
);
295 if (state
& MESA_META_PIXEL_STORE
) {
296 save
->Pack
= ctx
->Pack
;
297 save
->Unpack
= ctx
->Unpack
;
298 ctx
->Pack
= ctx
->DefaultPacking
;
299 ctx
->Unpack
= ctx
->DefaultPacking
;
302 if (state
& MESA_META_PIXEL_TRANSFER
) {
303 save
->RedScale
= ctx
->Pixel
.RedScale
;
304 save
->RedBias
= ctx
->Pixel
.RedBias
;
305 save
->GreenScale
= ctx
->Pixel
.GreenScale
;
306 save
->GreenBias
= ctx
->Pixel
.GreenBias
;
307 save
->BlueScale
= ctx
->Pixel
.BlueScale
;
308 save
->BlueBias
= ctx
->Pixel
.BlueBias
;
309 save
->AlphaScale
= ctx
->Pixel
.AlphaScale
;
310 save
->AlphaBias
= ctx
->Pixel
.AlphaBias
;
311 save
->MapColorFlag
= ctx
->Pixel
.MapColorFlag
;
312 ctx
->Pixel
.RedScale
= 1.0F
;
313 ctx
->Pixel
.RedBias
= 0.0F
;
314 ctx
->Pixel
.GreenScale
= 1.0F
;
315 ctx
->Pixel
.GreenBias
= 0.0F
;
316 ctx
->Pixel
.BlueScale
= 1.0F
;
317 ctx
->Pixel
.BlueBias
= 0.0F
;
318 ctx
->Pixel
.AlphaScale
= 1.0F
;
319 ctx
->Pixel
.AlphaBias
= 0.0F
;
320 ctx
->Pixel
.MapColorFlag
= GL_FALSE
;
322 ctx
->NewState
|=_NEW_PIXEL
;
325 if (state
& MESA_META_RASTERIZATION
) {
326 save
->FrontPolygonMode
= ctx
->Polygon
.FrontMode
;
327 save
->BackPolygonMode
= ctx
->Polygon
.BackMode
;
328 save
->PolygonOffset
= ctx
->Polygon
.OffsetFill
;
329 save
->PolygonSmooth
= ctx
->Polygon
.SmoothFlag
;
330 save
->PolygonStipple
= ctx
->Polygon
.StippleFlag
;
331 save
->PolygonCull
= ctx
->Polygon
.CullFlag
;
332 _mesa_PolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
333 _mesa_set_enable(ctx
, GL_POLYGON_OFFSET_FILL
, GL_FALSE
);
334 _mesa_set_enable(ctx
, GL_POLYGON_SMOOTH
, GL_FALSE
);
335 _mesa_set_enable(ctx
, GL_POLYGON_STIPPLE
, GL_FALSE
);
336 _mesa_set_enable(ctx
, GL_CULL_FACE
, GL_FALSE
);
339 if (state
& MESA_META_SCISSOR
) {
340 save
->Scissor
= ctx
->Scissor
; /* struct copy */
341 _mesa_set_enable(ctx
, GL_SCISSOR_TEST
, GL_FALSE
);
344 if (state
& MESA_META_STENCIL_TEST
) {
345 save
->Stencil
= ctx
->Stencil
; /* struct copy */
346 if (ctx
->Stencil
.Enabled
)
347 _mesa_set_enable(ctx
, GL_STENCIL_TEST
, GL_FALSE
);
348 /* NOTE: other stencil state not reset */
351 if (state
& MESA_META_TEXTURE
) {
354 save
->EnvMode
= ctx
->Texture
.Unit
.EnvMode
;
356 /* Disable all texture units */
357 save
->TexEnabled
= ctx
->Texture
.Unit
.Enabled
;
358 save
->TexGenEnabled
= ctx
->Texture
.Unit
.TexGenEnabled
;
359 if (ctx
->Texture
.Unit
.Enabled
||
360 ctx
->Texture
.Unit
.TexGenEnabled
) {
361 _mesa_set_enable(ctx
, GL_TEXTURE_1D
, GL_FALSE
);
362 _mesa_set_enable(ctx
, GL_TEXTURE_2D
, GL_FALSE
);
363 if (ctx
->Extensions
.ARB_texture_cube_map
)
364 _mesa_set_enable(ctx
, GL_TEXTURE_CUBE_MAP
, GL_FALSE
);
365 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_S
, GL_FALSE
);
366 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_T
, GL_FALSE
);
367 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_R
, GL_FALSE
);
368 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_Q
, GL_FALSE
);
371 /* save current texture objects for unit[0] only */
372 for (tgt
= 0; tgt
< NUM_TEXTURE_TARGETS
; tgt
++) {
373 _mesa_reference_texobj(&save
->CurrentTexture
[tgt
],
374 ctx
->Texture
.Unit
.CurrentTex
[tgt
]);
376 _mesa_TexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
379 if (state
& MESA_META_TRANSFORM
) {
380 memcpy(save
->ModelviewMatrix
, ctx
->ModelviewMatrixStack
.Top
->m
,
381 16 * sizeof(GLfloat
));
382 memcpy(save
->ProjectionMatrix
, ctx
->ProjectionMatrixStack
.Top
->m
,
383 16 * sizeof(GLfloat
));
384 memcpy(save
->TextureMatrix
, ctx
->TextureMatrixStack
.Top
->m
,
385 16 * sizeof(GLfloat
));
386 save
->MatrixMode
= ctx
->Transform
.MatrixMode
;
387 /* set 1:1 vertex:pixel coordinate transform */
388 _mesa_MatrixMode(GL_TEXTURE
);
389 _mesa_LoadIdentity();
390 _mesa_MatrixMode(GL_MODELVIEW
);
391 _mesa_LoadIdentity();
392 _mesa_MatrixMode(GL_PROJECTION
);
393 _mesa_LoadIdentity();
394 _mesa_Ortho(0.0, ctx
->DrawBuffer
->Width
,
395 0.0, ctx
->DrawBuffer
->Height
,
399 if (state
& MESA_META_CLIP
) {
400 save
->ClipPlanesEnabled
= ctx
->Transform
.ClipPlanesEnabled
;
401 if (ctx
->Transform
.ClipPlanesEnabled
) {
403 for (i
= 0; i
< ctx
->Const
.MaxClipPlanes
; i
++) {
404 _mesa_set_enable(ctx
, GL_CLIP_PLANE0
+ i
, GL_FALSE
);
409 if (state
& MESA_META_VERTEX
) {
410 /* save vertex array object state */
411 _mesa_reference_array_object(ctx
, &save
->ArrayObj
,
412 ctx
->Array
.ArrayObj
);
413 _mesa_reference_buffer_object(ctx
, &save
->ArrayBufferObj
,
414 ctx
->Array
.ArrayBufferObj
);
415 /* set some default state? */
418 if (state
& MESA_META_VIEWPORT
) {
419 /* save viewport state */
420 save
->ViewportX
= ctx
->Viewport
.X
;
421 save
->ViewportY
= ctx
->Viewport
.Y
;
422 save
->ViewportW
= ctx
->Viewport
.Width
;
423 save
->ViewportH
= ctx
->Viewport
.Height
;
424 /* set viewport to match window size */
425 if (ctx
->Viewport
.X
!= 0 ||
426 ctx
->Viewport
.Y
!= 0 ||
427 ctx
->Viewport
.Width
!= ctx
->DrawBuffer
->Width
||
428 ctx
->Viewport
.Height
!= ctx
->DrawBuffer
->Height
) {
429 _mesa_set_viewport(ctx
, 0, 0,
430 ctx
->DrawBuffer
->Width
, ctx
->DrawBuffer
->Height
);
432 /* save depth range state */
433 save
->DepthNear
= ctx
->Viewport
.Near
;
434 save
->DepthFar
= ctx
->Viewport
.Far
;
435 /* set depth range to default */
436 _mesa_DepthRange(0.0, 1.0);
439 if (state
& MESA_META_SELECT_FEEDBACK
) {
440 save
->RenderMode
= ctx
->RenderMode
;
441 if (ctx
->RenderMode
== GL_SELECT
) {
442 save
->Select
= ctx
->Select
; /* struct copy */
443 _mesa_RenderMode(GL_RENDER
);
444 } else if (ctx
->RenderMode
== GL_FEEDBACK
) {
445 save
->Feedback
= ctx
->Feedback
; /* struct copy */
446 _mesa_RenderMode(GL_RENDER
);
452 save
->Lighting
= ctx
->Light
.Enabled
;
453 if (ctx
->Light
.Enabled
)
454 _mesa_set_enable(ctx
, GL_LIGHTING
, GL_FALSE
);
455 save
->RasterDiscard
= ctx
->RasterDiscard
;
456 if (ctx
->RasterDiscard
)
457 _mesa_set_enable(ctx
, GL_RASTERIZER_DISCARD
, GL_FALSE
);
463 * Leave meta state. This is like a light-weight version of glPopAttrib().
466 _mesa_meta_end(struct gl_context
*ctx
)
468 struct save_state
*save
= &ctx
->Meta
->Save
[--ctx
->Meta
->SaveStackDepth
];
469 const GLbitfield state
= save
->SavedState
;
471 if (state
& MESA_META_ALPHA_TEST
) {
472 if (ctx
->Color
.AlphaEnabled
!= save
->AlphaEnabled
)
473 _mesa_set_enable(ctx
, GL_ALPHA_TEST
, save
->AlphaEnabled
);
474 _mesa_AlphaFunc(save
->AlphaFunc
, save
->AlphaRef
);
477 if (state
& MESA_META_BLEND
) {
478 if (ctx
->Color
.BlendEnabled
!= save
->BlendEnabled
) {
479 _mesa_set_enable(ctx
, GL_BLEND
, (save
->BlendEnabled
& 1));
481 if (ctx
->Color
.ColorLogicOpEnabled
!= save
->ColorLogicOpEnabled
)
482 _mesa_set_enable(ctx
, GL_COLOR_LOGIC_OP
, save
->ColorLogicOpEnabled
);
485 if (state
& MESA_META_COLOR_MASK
) {
486 if (!TEST_EQ_4V(ctx
->Color
.ColorMask
, save
->ColorMask
)) {
487 _mesa_ColorMask(save
->ColorMask
[0], save
->ColorMask
[1],
488 save
->ColorMask
[2], save
->ColorMask
[3]);
492 if (state
& MESA_META_DEPTH_TEST
) {
493 if (ctx
->Depth
.Test
!= save
->Depth
.Test
)
494 _mesa_set_enable(ctx
, GL_DEPTH_TEST
, save
->Depth
.Test
);
495 _mesa_DepthFunc(save
->Depth
.Func
);
496 _mesa_DepthMask(save
->Depth
.Mask
);
499 if (state
& MESA_META_FOG
) {
500 _mesa_set_enable(ctx
, GL_FOG
, save
->Fog
);
503 if (state
& MESA_META_PIXEL_STORE
) {
504 ctx
->Pack
= save
->Pack
;
505 ctx
->Unpack
= save
->Unpack
;
508 if (state
& MESA_META_PIXEL_TRANSFER
) {
509 ctx
->Pixel
.RedScale
= save
->RedScale
;
510 ctx
->Pixel
.RedBias
= save
->RedBias
;
511 ctx
->Pixel
.GreenScale
= save
->GreenScale
;
512 ctx
->Pixel
.GreenBias
= save
->GreenBias
;
513 ctx
->Pixel
.BlueScale
= save
->BlueScale
;
514 ctx
->Pixel
.BlueBias
= save
->BlueBias
;
515 ctx
->Pixel
.AlphaScale
= save
->AlphaScale
;
516 ctx
->Pixel
.AlphaBias
= save
->AlphaBias
;
517 ctx
->Pixel
.MapColorFlag
= save
->MapColorFlag
;
519 ctx
->NewState
|=_NEW_PIXEL
;
522 if (state
& MESA_META_RASTERIZATION
) {
523 _mesa_PolygonMode(GL_FRONT
, save
->FrontPolygonMode
);
524 _mesa_PolygonMode(GL_BACK
, save
->BackPolygonMode
);
525 _mesa_set_enable(ctx
, GL_POLYGON_STIPPLE
, save
->PolygonStipple
);
526 _mesa_set_enable(ctx
, GL_POLYGON_OFFSET_FILL
, save
->PolygonOffset
);
527 _mesa_set_enable(ctx
, GL_POLYGON_SMOOTH
, save
->PolygonSmooth
);
528 _mesa_set_enable(ctx
, GL_CULL_FACE
, save
->PolygonCull
);
531 if (state
& MESA_META_SCISSOR
) {
532 _mesa_set_enable(ctx
, GL_SCISSOR_TEST
, save
->Scissor
.Enabled
);
533 _mesa_Scissor(save
->Scissor
.X
, save
->Scissor
.Y
,
534 save
->Scissor
.Width
, save
->Scissor
.Height
);
537 if (state
& MESA_META_STENCIL_TEST
) {
538 const struct gl_stencil_attrib
*stencil
= &save
->Stencil
;
540 _mesa_set_enable(ctx
, GL_STENCIL_TEST
, stencil
->Enabled
);
541 _mesa_ClearStencil(stencil
->Clear
);
542 _mesa_StencilFunc(stencil
->Function
,
545 _mesa_StencilMask(stencil
->WriteMask
);
546 _mesa_StencilOp(stencil
->FailFunc
, stencil
->ZFailFunc
, stencil
->ZPassFunc
);
549 if (state
& MESA_META_TEXTURE
) {
552 /* restore texenv for unit[0] */
553 _mesa_TexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, save
->EnvMode
);
555 /* restore texture objects for unit[0] only */
556 for (tgt
= 0; tgt
< NUM_TEXTURE_TARGETS
; tgt
++) {
557 if (ctx
->Texture
.Unit
.CurrentTex
[tgt
] != save
->CurrentTexture
[tgt
]) {
558 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
559 _mesa_reference_texobj(&ctx
->Texture
.Unit
.CurrentTex
[tgt
],
560 save
->CurrentTexture
[tgt
]);
562 _mesa_reference_texobj(&save
->CurrentTexture
[tgt
], NULL
);
565 /* Restore fixed function texture enables, texgen */
566 if (ctx
->Texture
.Unit
.Enabled
!= save
->TexEnabled
) {
567 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
568 ctx
->Texture
.Unit
.Enabled
= save
->TexEnabled
;
571 if (ctx
->Texture
.Unit
.TexGenEnabled
!= save
->TexGenEnabled
) {
572 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
573 ctx
->Texture
.Unit
.TexGenEnabled
= save
->TexGenEnabled
;
577 if (state
& MESA_META_TRANSFORM
) {
578 _mesa_MatrixMode(GL_TEXTURE
);
579 _mesa_LoadMatrixf(save
->TextureMatrix
);
581 _mesa_MatrixMode(GL_MODELVIEW
);
582 _mesa_LoadMatrixf(save
->ModelviewMatrix
);
584 _mesa_MatrixMode(GL_PROJECTION
);
585 _mesa_LoadMatrixf(save
->ProjectionMatrix
);
587 _mesa_MatrixMode(save
->MatrixMode
);
590 if (state
& MESA_META_CLIP
) {
591 if (save
->ClipPlanesEnabled
) {
593 for (i
= 0; i
< ctx
->Const
.MaxClipPlanes
; i
++) {
594 if (save
->ClipPlanesEnabled
& (1 << i
)) {
595 _mesa_set_enable(ctx
, GL_CLIP_PLANE0
+ i
, GL_TRUE
);
601 if (state
& MESA_META_VERTEX
) {
602 /* restore vertex buffer object */
603 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB
, save
->ArrayBufferObj
->Name
);
604 _mesa_reference_buffer_object(ctx
, &save
->ArrayBufferObj
, NULL
);
606 /* restore vertex array object */
607 _mesa_BindVertexArray(save
->ArrayObj
->Name
);
608 _mesa_reference_array_object(ctx
, &save
->ArrayObj
, NULL
);
611 if (state
& MESA_META_VIEWPORT
) {
612 if (save
->ViewportX
!= ctx
->Viewport
.X
||
613 save
->ViewportY
!= ctx
->Viewport
.Y
||
614 save
->ViewportW
!= ctx
->Viewport
.Width
||
615 save
->ViewportH
!= ctx
->Viewport
.Height
) {
616 _mesa_set_viewport(ctx
, save
->ViewportX
, save
->ViewportY
,
617 save
->ViewportW
, save
->ViewportH
);
619 _mesa_DepthRange(save
->DepthNear
, save
->DepthFar
);
623 if (save
->Lighting
) {
624 _mesa_set_enable(ctx
, GL_LIGHTING
, GL_TRUE
);
626 if (save
->RasterDiscard
) {
627 _mesa_set_enable(ctx
, GL_RASTERIZER_DISCARD
, GL_TRUE
);
633 * Determine whether Mesa is currently in a meta state.
636 _mesa_meta_in_progress(struct gl_context
*ctx
)
638 return ctx
->Meta
->SaveStackDepth
!= 0;
643 * Determine the GL data type to use for the temporary image read with
644 * ReadPixels() and passed to Tex[Sub]Image().
647 get_temp_image_type(struct gl_context
*ctx
, GLenum baseFormat
)
649 switch (baseFormat
) {
656 case GL_LUMINANCE_ALPHA
:
658 if (ctx
->DrawBuffer
->Visual
.redBits
<= 8)
659 return GL_UNSIGNED_BYTE
;
660 else if (ctx
->DrawBuffer
->Visual
.redBits
<= 16)
661 return GL_UNSIGNED_SHORT
;
664 case GL_DEPTH_COMPONENT
:
665 return GL_UNSIGNED_INT
;
667 _mesa_problem(ctx
, "Unexpected format %d in get_temp_image_type()",
675 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
676 * Have to be careful with locking and meta state for pixel transfer.
679 copy_tex_sub_image(struct gl_context
*ctx
,
681 struct gl_texture_image
*texImage
,
682 GLint xoffset
, GLint yoffset
, GLint zoffset
,
683 struct gl_renderbuffer
*rb
,
685 GLsizei width
, GLsizei height
)
687 struct gl_texture_object
*texObj
= texImage
->TexObject
;
688 const GLenum target
= texObj
->Target
;
693 /* Choose format/type for temporary image buffer */
694 format
= _mesa_get_format_base_format(texImage
->TexFormat
);
695 if (format
== GL_LUMINANCE
||
696 format
== GL_LUMINANCE_ALPHA
||
697 format
== GL_INTENSITY
) {
698 /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the
699 * temp image buffer because glReadPixels will do L=R+G+B which is
700 * not what we want (should be L=R).
705 if (_mesa_is_format_integer_color(texImage
->TexFormat
)) {
706 _mesa_problem(ctx
, "unsupported integer color copyteximage");
710 type
= get_temp_image_type(ctx
, format
);
711 bpp
= _mesa_bytes_per_pixel(format
, type
);
713 _mesa_problem(ctx
, "Bad bpp in meta copy_tex_sub_image()");
718 * Alloc image buffer (XXX could use a PBO)
720 buf
= malloc(width
* height
* bpp
);
722 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage%uD", dims
);
726 _mesa_unlock_texture(ctx
, texObj
); /* need to unlock first */
729 * Read image from framebuffer (disable pixel transfer ops)
731 _mesa_meta_begin(ctx
, MESA_META_PIXEL_STORE
| MESA_META_PIXEL_TRANSFER
);
732 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
733 format
, type
, &ctx
->Pack
, buf
);
736 _mesa_update_state(ctx
); /* to update pixel transfer state */
739 * Store texture data (with pixel transfer ops)
741 _mesa_meta_begin(ctx
, MESA_META_PIXEL_STORE
);
742 if (target
== GL_TEXTURE_1D
) {
743 ctx
->Driver
.TexSubImage1D(ctx
, texImage
,
745 format
, type
, buf
, &ctx
->Unpack
);
748 ctx
->Driver
.TexSubImage2D(ctx
, texImage
,
749 xoffset
, yoffset
, width
, height
,
750 format
, type
, buf
, &ctx
->Unpack
);
754 _mesa_lock_texture(ctx
, texObj
); /* re-lock */
761 _mesa_meta_CopyTexSubImage1D(struct gl_context
*ctx
,
762 struct gl_texture_image
*texImage
,
764 struct gl_renderbuffer
*rb
,
765 GLint x
, GLint y
, GLsizei width
)
767 copy_tex_sub_image(ctx
, 1, texImage
, xoffset
, 0, 0,
773 _mesa_meta_CopyTexSubImage2D(struct gl_context
*ctx
,
774 struct gl_texture_image
*texImage
,
775 GLint xoffset
, GLint yoffset
,
776 struct gl_renderbuffer
*rb
,
778 GLsizei width
, GLsizei height
)
780 copy_tex_sub_image(ctx
, 2, texImage
, xoffset
, yoffset
, 0,
781 rb
, x
, y
, width
, height
);