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"
52 #include "main/polygon.h"
53 #include "main/readpix.h"
54 #include "main/scissor.h"
55 #include "main/state.h"
56 #include "main/stencil.h"
57 #include "main/texobj.h"
58 #include "main/texenv.h"
59 #include "main/texgetimage.h"
60 #include "main/teximage.h"
61 #include "main/texparam.h"
62 #include "main/texstate.h"
63 #include "main/varray.h"
64 #include "main/viewport.h"
65 #include "swrast/swrast.h"
66 #include "drivers/common/meta.h"
69 /** Return offset in bytes of the field within a vertex struct */
70 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
73 * State which we may save/restore across meta ops.
74 * XXX this may be incomplete...
78 GLbitfield SavedState
; /**< bitmask of MESA_META_* flags */
80 /** MESA_META_ALPHA_TEST */
81 GLboolean AlphaEnabled
;
85 /** MESA_META_BLEND */
86 GLbitfield BlendEnabled
;
87 GLboolean ColorLogicOpEnabled
;
89 /** MESA_META_COLOR_MASK */
92 /** MESA_META_DEPTH_TEST */
93 struct gl_depthbuffer_attrib Depth
;
98 /** MESA_META_PIXEL_STORE */
99 struct gl_pixelstore_attrib Pack
, Unpack
;
101 /** MESA_META_PIXEL_TRANSFER */
102 GLfloat RedBias
, RedScale
;
103 GLfloat GreenBias
, GreenScale
;
104 GLfloat BlueBias
, BlueScale
;
105 GLfloat AlphaBias
, AlphaScale
;
106 GLfloat DepthBias
, DepthScale
;
107 GLboolean MapColorFlag
;
109 /** MESA_META_RASTERIZATION */
110 GLenum FrontPolygonMode
, BackPolygonMode
;
111 GLboolean PolygonOffset
;
112 GLboolean PolygonSmooth
;
113 GLboolean PolygonStipple
;
114 GLboolean PolygonCull
;
116 /** MESA_META_SCISSOR */
117 struct gl_scissor_attrib Scissor
;
119 /** MESA_META_STENCIL_TEST */
120 struct gl_stencil_attrib Stencil
;
122 /** MESA_META_TRANSFORM */
124 GLfloat ModelviewMatrix
[16];
125 GLfloat ProjectionMatrix
[16];
126 GLfloat TextureMatrix
[16];
128 /** MESA_META_CLIP */
129 GLbitfield ClipPlanesEnabled
;
131 /** MESA_META_TEXTURE */
132 struct gl_texture_object
*CurrentTexture
[NUM_TEXTURE_TARGETS
];
133 /** mask of TEXTURE_2D_BIT, etc */
134 GLbitfield TexEnabled
;
135 GLbitfield TexGenEnabled
;
136 GLuint EnvMode
; /* unit[0] only */
138 /** MESA_META_VERTEX */
139 struct gl_array_object
*ArrayObj
;
140 struct gl_buffer_object
*ArrayBufferObj
;
142 /** MESA_META_VIEWPORT */
143 GLint ViewportX
, ViewportY
, ViewportW
, ViewportH
;
144 GLclampd DepthNear
, DepthFar
;
146 /** MESA_META_SELECT_FEEDBACK */
148 struct gl_selection Select
;
149 struct gl_feedback Feedback
;
151 /** Miscellaneous (always disabled) */
153 GLboolean RasterDiscard
;
157 * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
158 * This is currently shared by all the meta ops. But we could create a
159 * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
164 GLenum Target
; /**< GL_TEXTURE_2D */
165 GLsizei MinSize
; /**< Min texture size to allocate */
166 GLsizei MaxSize
; /**< Max possible texture size */
167 GLboolean NPOT
; /**< Non-power of two size OK? */
168 GLsizei Width
, Height
; /**< Current texture size */
170 GLfloat Sright
, Ttop
; /**< right, top texcoords */
175 * State for glBlitFramebufer()
186 * State for glClear()
195 GLuint IntegerShaderProg
;
196 GLint IntegerColorLocation
;
201 * State for glCopyPixels()
209 #define MAX_META_OPS_DEPTH 8
211 * All per-context meta state.
215 /** Stack of state saved during meta-ops */
216 struct save_state Save
[MAX_META_OPS_DEPTH
];
217 /** Save stack depth */
218 GLuint SaveStackDepth
;
220 struct temp_texture TempTex
;
222 struct copypix_state CopyPix
; /**< For _mesa_meta_CopyPixels() */
225 static void cleanup_temp_texture(struct gl_context
*ctx
, struct temp_texture
*tex
);
228 * Initialize meta-ops for a context.
229 * To be called once during context creation.
232 _mesa_meta_init(struct gl_context
*ctx
)
236 ctx
->Meta
= CALLOC_STRUCT(gl_meta_state
);
241 * Free context meta-op state.
242 * To be called once during context destruction.
245 _mesa_meta_free(struct gl_context
*ctx
)
247 GET_CURRENT_CONTEXT(old_context
);
248 _mesa_make_current(ctx
, NULL
, NULL
);
249 cleanup_temp_texture(ctx
, &ctx
->Meta
->TempTex
);
251 _mesa_make_current(old_context
, old_context
->WinSysDrawBuffer
, old_context
->WinSysReadBuffer
);
253 _mesa_make_current(NULL
, NULL
, NULL
);
260 * Enter meta state. This is like a light-weight version of glPushAttrib
261 * but it also resets most GL state back to default values.
263 * \param state bitmask of MESA_META_* flags indicating which attribute groups
264 * to save and reset to their defaults
267 _mesa_meta_begin(struct gl_context
*ctx
, GLbitfield state
)
269 struct save_state
*save
;
271 /* hope MAX_META_OPS_DEPTH is large enough */
272 assert(ctx
->Meta
->SaveStackDepth
< MAX_META_OPS_DEPTH
);
274 save
= &ctx
->Meta
->Save
[ctx
->Meta
->SaveStackDepth
++];
275 memset(save
, 0, sizeof(*save
));
276 save
->SavedState
= state
;
278 if (state
& MESA_META_ALPHA_TEST
) {
279 save
->AlphaEnabled
= ctx
->Color
.AlphaEnabled
;
280 save
->AlphaFunc
= ctx
->Color
.AlphaFunc
;
281 save
->AlphaRef
= ctx
->Color
.AlphaRef
;
282 if (ctx
->Color
.AlphaEnabled
)
283 _mesa_set_enable(ctx
, GL_ALPHA_TEST
, GL_FALSE
);
286 if (state
& MESA_META_BLEND
) {
287 save
->BlendEnabled
= ctx
->Color
.BlendEnabled
;
288 if (ctx
->Color
.BlendEnabled
) {
289 _mesa_set_enable(ctx
, GL_BLEND
, GL_FALSE
);
291 save
->ColorLogicOpEnabled
= ctx
->Color
.ColorLogicOpEnabled
;
292 if (ctx
->Color
.ColorLogicOpEnabled
)
293 _mesa_set_enable(ctx
, GL_COLOR_LOGIC_OP
, GL_FALSE
);
296 if (state
& MESA_META_COLOR_MASK
) {
297 memcpy(save
->ColorMask
, ctx
->Color
.ColorMask
,
298 sizeof(ctx
->Color
.ColorMask
));
299 if (!ctx
->Color
.ColorMask
[0] ||
300 !ctx
->Color
.ColorMask
[1] ||
301 !ctx
->Color
.ColorMask
[2] ||
302 !ctx
->Color
.ColorMask
[3])
303 _mesa_ColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
306 if (state
& MESA_META_DEPTH_TEST
) {
307 save
->Depth
= ctx
->Depth
; /* struct copy */
309 _mesa_set_enable(ctx
, GL_DEPTH_TEST
, GL_FALSE
);
312 if (state
& MESA_META_FOG
) {
313 save
->Fog
= ctx
->Fog
.Enabled
;
314 if (ctx
->Fog
.Enabled
)
315 _mesa_set_enable(ctx
, GL_FOG
, GL_FALSE
);
318 if (state
& MESA_META_PIXEL_STORE
) {
319 save
->Pack
= ctx
->Pack
;
320 save
->Unpack
= ctx
->Unpack
;
321 ctx
->Pack
= ctx
->DefaultPacking
;
322 ctx
->Unpack
= ctx
->DefaultPacking
;
325 if (state
& MESA_META_PIXEL_TRANSFER
) {
326 save
->RedScale
= ctx
->Pixel
.RedScale
;
327 save
->RedBias
= ctx
->Pixel
.RedBias
;
328 save
->GreenScale
= ctx
->Pixel
.GreenScale
;
329 save
->GreenBias
= ctx
->Pixel
.GreenBias
;
330 save
->BlueScale
= ctx
->Pixel
.BlueScale
;
331 save
->BlueBias
= ctx
->Pixel
.BlueBias
;
332 save
->AlphaScale
= ctx
->Pixel
.AlphaScale
;
333 save
->AlphaBias
= ctx
->Pixel
.AlphaBias
;
334 save
->MapColorFlag
= ctx
->Pixel
.MapColorFlag
;
335 ctx
->Pixel
.RedScale
= 1.0F
;
336 ctx
->Pixel
.RedBias
= 0.0F
;
337 ctx
->Pixel
.GreenScale
= 1.0F
;
338 ctx
->Pixel
.GreenBias
= 0.0F
;
339 ctx
->Pixel
.BlueScale
= 1.0F
;
340 ctx
->Pixel
.BlueBias
= 0.0F
;
341 ctx
->Pixel
.AlphaScale
= 1.0F
;
342 ctx
->Pixel
.AlphaBias
= 0.0F
;
343 ctx
->Pixel
.MapColorFlag
= GL_FALSE
;
345 ctx
->NewState
|=_NEW_PIXEL
;
348 if (state
& MESA_META_RASTERIZATION
) {
349 save
->FrontPolygonMode
= ctx
->Polygon
.FrontMode
;
350 save
->BackPolygonMode
= ctx
->Polygon
.BackMode
;
351 save
->PolygonOffset
= ctx
->Polygon
.OffsetFill
;
352 save
->PolygonSmooth
= ctx
->Polygon
.SmoothFlag
;
353 save
->PolygonStipple
= ctx
->Polygon
.StippleFlag
;
354 save
->PolygonCull
= ctx
->Polygon
.CullFlag
;
355 _mesa_PolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
356 _mesa_set_enable(ctx
, GL_POLYGON_OFFSET_FILL
, GL_FALSE
);
357 _mesa_set_enable(ctx
, GL_POLYGON_SMOOTH
, GL_FALSE
);
358 _mesa_set_enable(ctx
, GL_POLYGON_STIPPLE
, GL_FALSE
);
359 _mesa_set_enable(ctx
, GL_CULL_FACE
, GL_FALSE
);
362 if (state
& MESA_META_SCISSOR
) {
363 save
->Scissor
= ctx
->Scissor
; /* struct copy */
364 _mesa_set_enable(ctx
, GL_SCISSOR_TEST
, GL_FALSE
);
367 if (state
& MESA_META_STENCIL_TEST
) {
368 save
->Stencil
= ctx
->Stencil
; /* struct copy */
369 if (ctx
->Stencil
.Enabled
)
370 _mesa_set_enable(ctx
, GL_STENCIL_TEST
, GL_FALSE
);
371 /* NOTE: other stencil state not reset */
374 if (state
& MESA_META_TEXTURE
) {
377 save
->EnvMode
= ctx
->Texture
.Unit
.EnvMode
;
379 /* Disable all texture units */
380 save
->TexEnabled
= ctx
->Texture
.Unit
.Enabled
;
381 save
->TexGenEnabled
= ctx
->Texture
.Unit
.TexGenEnabled
;
382 if (ctx
->Texture
.Unit
.Enabled
||
383 ctx
->Texture
.Unit
.TexGenEnabled
) {
384 _mesa_set_enable(ctx
, GL_TEXTURE_1D
, GL_FALSE
);
385 _mesa_set_enable(ctx
, GL_TEXTURE_2D
, GL_FALSE
);
386 _mesa_set_enable(ctx
, GL_TEXTURE_3D
, GL_FALSE
);
387 if (ctx
->Extensions
.ARB_texture_cube_map
)
388 _mesa_set_enable(ctx
, GL_TEXTURE_CUBE_MAP
, GL_FALSE
);
389 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_S
, GL_FALSE
);
390 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_T
, GL_FALSE
);
391 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_R
, GL_FALSE
);
392 _mesa_set_enable(ctx
, GL_TEXTURE_GEN_Q
, GL_FALSE
);
395 /* save current texture objects for unit[0] only */
396 for (tgt
= 0; tgt
< NUM_TEXTURE_TARGETS
; tgt
++) {
397 _mesa_reference_texobj(&save
->CurrentTexture
[tgt
],
398 ctx
->Texture
.Unit
.CurrentTex
[tgt
]);
400 _mesa_TexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
403 if (state
& MESA_META_TRANSFORM
) {
404 memcpy(save
->ModelviewMatrix
, ctx
->ModelviewMatrixStack
.Top
->m
,
405 16 * sizeof(GLfloat
));
406 memcpy(save
->ProjectionMatrix
, ctx
->ProjectionMatrixStack
.Top
->m
,
407 16 * sizeof(GLfloat
));
408 memcpy(save
->TextureMatrix
, ctx
->TextureMatrixStack
.Top
->m
,
409 16 * sizeof(GLfloat
));
410 save
->MatrixMode
= ctx
->Transform
.MatrixMode
;
411 /* set 1:1 vertex:pixel coordinate transform */
412 _mesa_MatrixMode(GL_TEXTURE
);
413 _mesa_LoadIdentity();
414 _mesa_MatrixMode(GL_MODELVIEW
);
415 _mesa_LoadIdentity();
416 _mesa_MatrixMode(GL_PROJECTION
);
417 _mesa_LoadIdentity();
418 _mesa_Ortho(0.0, ctx
->DrawBuffer
->Width
,
419 0.0, ctx
->DrawBuffer
->Height
,
423 if (state
& MESA_META_CLIP
) {
424 save
->ClipPlanesEnabled
= ctx
->Transform
.ClipPlanesEnabled
;
425 if (ctx
->Transform
.ClipPlanesEnabled
) {
427 for (i
= 0; i
< ctx
->Const
.MaxClipPlanes
; i
++) {
428 _mesa_set_enable(ctx
, GL_CLIP_PLANE0
+ i
, GL_FALSE
);
433 if (state
& MESA_META_VERTEX
) {
434 /* save vertex array object state */
435 _mesa_reference_array_object(ctx
, &save
->ArrayObj
,
436 ctx
->Array
.ArrayObj
);
437 _mesa_reference_buffer_object(ctx
, &save
->ArrayBufferObj
,
438 ctx
->Array
.ArrayBufferObj
);
439 /* set some default state? */
442 if (state
& MESA_META_VIEWPORT
) {
443 /* save viewport state */
444 save
->ViewportX
= ctx
->Viewport
.X
;
445 save
->ViewportY
= ctx
->Viewport
.Y
;
446 save
->ViewportW
= ctx
->Viewport
.Width
;
447 save
->ViewportH
= ctx
->Viewport
.Height
;
448 /* set viewport to match window size */
449 if (ctx
->Viewport
.X
!= 0 ||
450 ctx
->Viewport
.Y
!= 0 ||
451 ctx
->Viewport
.Width
!= ctx
->DrawBuffer
->Width
||
452 ctx
->Viewport
.Height
!= ctx
->DrawBuffer
->Height
) {
453 _mesa_set_viewport(ctx
, 0, 0,
454 ctx
->DrawBuffer
->Width
, ctx
->DrawBuffer
->Height
);
456 /* save depth range state */
457 save
->DepthNear
= ctx
->Viewport
.Near
;
458 save
->DepthFar
= ctx
->Viewport
.Far
;
459 /* set depth range to default */
460 _mesa_DepthRange(0.0, 1.0);
463 if (state
& MESA_META_SELECT_FEEDBACK
) {
464 save
->RenderMode
= ctx
->RenderMode
;
465 if (ctx
->RenderMode
== GL_SELECT
) {
466 save
->Select
= ctx
->Select
; /* struct copy */
467 _mesa_RenderMode(GL_RENDER
);
468 } else if (ctx
->RenderMode
== GL_FEEDBACK
) {
469 save
->Feedback
= ctx
->Feedback
; /* struct copy */
470 _mesa_RenderMode(GL_RENDER
);
476 save
->Lighting
= ctx
->Light
.Enabled
;
477 if (ctx
->Light
.Enabled
)
478 _mesa_set_enable(ctx
, GL_LIGHTING
, GL_FALSE
);
479 save
->RasterDiscard
= ctx
->RasterDiscard
;
480 if (ctx
->RasterDiscard
)
481 _mesa_set_enable(ctx
, GL_RASTERIZER_DISCARD
, GL_FALSE
);
487 * Leave meta state. This is like a light-weight version of glPopAttrib().
490 _mesa_meta_end(struct gl_context
*ctx
)
492 struct save_state
*save
= &ctx
->Meta
->Save
[--ctx
->Meta
->SaveStackDepth
];
493 const GLbitfield state
= save
->SavedState
;
495 if (state
& MESA_META_ALPHA_TEST
) {
496 if (ctx
->Color
.AlphaEnabled
!= save
->AlphaEnabled
)
497 _mesa_set_enable(ctx
, GL_ALPHA_TEST
, save
->AlphaEnabled
);
498 _mesa_AlphaFunc(save
->AlphaFunc
, save
->AlphaRef
);
501 if (state
& MESA_META_BLEND
) {
502 if (ctx
->Color
.BlendEnabled
!= save
->BlendEnabled
) {
503 _mesa_set_enable(ctx
, GL_BLEND
, (save
->BlendEnabled
& 1));
505 if (ctx
->Color
.ColorLogicOpEnabled
!= save
->ColorLogicOpEnabled
)
506 _mesa_set_enable(ctx
, GL_COLOR_LOGIC_OP
, save
->ColorLogicOpEnabled
);
509 if (state
& MESA_META_COLOR_MASK
) {
510 if (!TEST_EQ_4V(ctx
->Color
.ColorMask
, save
->ColorMask
)) {
511 _mesa_ColorMask(save
->ColorMask
[0], save
->ColorMask
[1],
512 save
->ColorMask
[2], save
->ColorMask
[3]);
516 if (state
& MESA_META_DEPTH_TEST
) {
517 if (ctx
->Depth
.Test
!= save
->Depth
.Test
)
518 _mesa_set_enable(ctx
, GL_DEPTH_TEST
, save
->Depth
.Test
);
519 _mesa_DepthFunc(save
->Depth
.Func
);
520 _mesa_DepthMask(save
->Depth
.Mask
);
523 if (state
& MESA_META_FOG
) {
524 _mesa_set_enable(ctx
, GL_FOG
, save
->Fog
);
527 if (state
& MESA_META_PIXEL_STORE
) {
528 ctx
->Pack
= save
->Pack
;
529 ctx
->Unpack
= save
->Unpack
;
532 if (state
& MESA_META_PIXEL_TRANSFER
) {
533 ctx
->Pixel
.RedScale
= save
->RedScale
;
534 ctx
->Pixel
.RedBias
= save
->RedBias
;
535 ctx
->Pixel
.GreenScale
= save
->GreenScale
;
536 ctx
->Pixel
.GreenBias
= save
->GreenBias
;
537 ctx
->Pixel
.BlueScale
= save
->BlueScale
;
538 ctx
->Pixel
.BlueBias
= save
->BlueBias
;
539 ctx
->Pixel
.AlphaScale
= save
->AlphaScale
;
540 ctx
->Pixel
.AlphaBias
= save
->AlphaBias
;
541 ctx
->Pixel
.MapColorFlag
= save
->MapColorFlag
;
543 ctx
->NewState
|=_NEW_PIXEL
;
546 if (state
& MESA_META_RASTERIZATION
) {
547 _mesa_PolygonMode(GL_FRONT
, save
->FrontPolygonMode
);
548 _mesa_PolygonMode(GL_BACK
, save
->BackPolygonMode
);
549 _mesa_set_enable(ctx
, GL_POLYGON_STIPPLE
, save
->PolygonStipple
);
550 _mesa_set_enable(ctx
, GL_POLYGON_OFFSET_FILL
, save
->PolygonOffset
);
551 _mesa_set_enable(ctx
, GL_POLYGON_SMOOTH
, save
->PolygonSmooth
);
552 _mesa_set_enable(ctx
, GL_CULL_FACE
, save
->PolygonCull
);
555 if (state
& MESA_META_SCISSOR
) {
556 _mesa_set_enable(ctx
, GL_SCISSOR_TEST
, save
->Scissor
.Enabled
);
557 _mesa_Scissor(save
->Scissor
.X
, save
->Scissor
.Y
,
558 save
->Scissor
.Width
, save
->Scissor
.Height
);
561 if (state
& MESA_META_STENCIL_TEST
) {
562 const struct gl_stencil_attrib
*stencil
= &save
->Stencil
;
564 _mesa_set_enable(ctx
, GL_STENCIL_TEST
, stencil
->Enabled
);
565 _mesa_ClearStencil(stencil
->Clear
);
566 if (ctx
->Extensions
.EXT_stencil_two_side
) {
567 _mesa_set_enable(ctx
, GL_STENCIL_TEST_TWO_SIDE_EXT
,
568 stencil
->TestTwoSide
);
569 _mesa_ActiveStencilFaceEXT(stencil
->ActiveFace
570 ? GL_BACK
: GL_FRONT
);
573 _mesa_StencilFuncSeparate(GL_FRONT
,
574 stencil
->Function
[0],
576 stencil
->ValueMask
[0]);
577 _mesa_StencilMaskSeparate(GL_FRONT
, stencil
->WriteMask
[0]);
578 _mesa_StencilOpSeparate(GL_FRONT
, stencil
->FailFunc
[0],
579 stencil
->ZFailFunc
[0],
580 stencil
->ZPassFunc
[0]);
582 _mesa_StencilFuncSeparate(GL_BACK
,
583 stencil
->Function
[1],
585 stencil
->ValueMask
[1]);
586 _mesa_StencilMaskSeparate(GL_BACK
, stencil
->WriteMask
[1]);
587 _mesa_StencilOpSeparate(GL_BACK
, stencil
->FailFunc
[1],
588 stencil
->ZFailFunc
[1],
589 stencil
->ZPassFunc
[1]);
592 if (state
& MESA_META_TEXTURE
) {
595 /* restore texenv for unit[0] */
596 _mesa_TexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, save
->EnvMode
);
598 /* restore texture objects for unit[0] only */
599 for (tgt
= 0; tgt
< NUM_TEXTURE_TARGETS
; tgt
++) {
600 if (ctx
->Texture
.Unit
.CurrentTex
[tgt
] != save
->CurrentTexture
[tgt
]) {
601 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
602 _mesa_reference_texobj(&ctx
->Texture
.Unit
.CurrentTex
[tgt
],
603 save
->CurrentTexture
[tgt
]);
605 _mesa_reference_texobj(&save
->CurrentTexture
[tgt
], NULL
);
608 /* Restore fixed function texture enables, texgen */
609 if (ctx
->Texture
.Unit
.Enabled
!= save
->TexEnabled
) {
610 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
611 ctx
->Texture
.Unit
.Enabled
= save
->TexEnabled
;
614 if (ctx
->Texture
.Unit
.TexGenEnabled
!= save
->TexGenEnabled
) {
615 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
616 ctx
->Texture
.Unit
.TexGenEnabled
= save
->TexGenEnabled
;
620 if (state
& MESA_META_TRANSFORM
) {
621 _mesa_MatrixMode(GL_TEXTURE
);
622 _mesa_LoadMatrixf(save
->TextureMatrix
);
624 _mesa_MatrixMode(GL_MODELVIEW
);
625 _mesa_LoadMatrixf(save
->ModelviewMatrix
);
627 _mesa_MatrixMode(GL_PROJECTION
);
628 _mesa_LoadMatrixf(save
->ProjectionMatrix
);
630 _mesa_MatrixMode(save
->MatrixMode
);
633 if (state
& MESA_META_CLIP
) {
634 if (save
->ClipPlanesEnabled
) {
636 for (i
= 0; i
< ctx
->Const
.MaxClipPlanes
; i
++) {
637 if (save
->ClipPlanesEnabled
& (1 << i
)) {
638 _mesa_set_enable(ctx
, GL_CLIP_PLANE0
+ i
, GL_TRUE
);
644 if (state
& MESA_META_VERTEX
) {
645 /* restore vertex buffer object */
646 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB
, save
->ArrayBufferObj
->Name
);
647 _mesa_reference_buffer_object(ctx
, &save
->ArrayBufferObj
, NULL
);
649 /* restore vertex array object */
650 _mesa_BindVertexArray(save
->ArrayObj
->Name
);
651 _mesa_reference_array_object(ctx
, &save
->ArrayObj
, NULL
);
654 if (state
& MESA_META_VIEWPORT
) {
655 if (save
->ViewportX
!= ctx
->Viewport
.X
||
656 save
->ViewportY
!= ctx
->Viewport
.Y
||
657 save
->ViewportW
!= ctx
->Viewport
.Width
||
658 save
->ViewportH
!= ctx
->Viewport
.Height
) {
659 _mesa_set_viewport(ctx
, save
->ViewportX
, save
->ViewportY
,
660 save
->ViewportW
, save
->ViewportH
);
662 _mesa_DepthRange(save
->DepthNear
, save
->DepthFar
);
666 if (save
->Lighting
) {
667 _mesa_set_enable(ctx
, GL_LIGHTING
, GL_TRUE
);
669 if (save
->RasterDiscard
) {
670 _mesa_set_enable(ctx
, GL_RASTERIZER_DISCARD
, GL_TRUE
);
676 * Determine whether Mesa is currently in a meta state.
679 _mesa_meta_in_progress(struct gl_context
*ctx
)
681 return ctx
->Meta
->SaveStackDepth
!= 0;
686 * Convert Z from a normalized value in the range [0, 1] to an object-space
687 * Z coordinate in [-1, +1] so that drawing at the new Z position with the
688 * default/identity ortho projection results in the original Z value.
689 * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z
690 * value comes from the clear value or raster position.
692 static INLINE GLfloat
693 invert_z(GLfloat normZ
)
695 GLfloat objZ
= 1.0f
- 2.0f
* normZ
;
701 * One-time init for a temp_texture object.
702 * Choose tex target, compute max tex size, etc.
705 init_temp_texture(struct gl_context
*ctx
, struct temp_texture
*tex
)
707 /* use 2D texture, NPOT if possible */
708 tex
->Target
= GL_TEXTURE_2D
;
709 tex
->MaxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
710 tex
->NPOT
= ctx
->Extensions
.ARB_texture_non_power_of_two
;
711 tex
->MinSize
= 16; /* 16 x 16 at least */
712 assert(tex
->MaxSize
> 0);
714 _mesa_GenTextures(1, &tex
->TexObj
);
718 cleanup_temp_texture(struct gl_context
*ctx
, struct temp_texture
*tex
)
722 _mesa_DeleteTextures(1, &tex
->TexObj
);
728 * Return pointer to temp_texture info for non-bitmap ops.
729 * This does some one-time init if needed.
731 static struct temp_texture
*
732 get_temp_texture(struct gl_context
*ctx
)
734 struct temp_texture
*tex
= &ctx
->Meta
->TempTex
;
737 init_temp_texture(ctx
, tex
);
745 * Compute the width/height of texture needed to draw an image of the
746 * given size. Return a flag indicating whether the current texture
747 * can be re-used (glTexSubImage2D) or if a new texture needs to be
748 * allocated (glTexImage2D).
749 * Also, compute s/t texcoords for drawing.
751 * \return GL_TRUE if new texture is needed, GL_FALSE otherwise
754 alloc_texture(struct temp_texture
*tex
,
755 GLsizei width
, GLsizei height
, GLenum intFormat
)
757 GLboolean newTex
= GL_FALSE
;
759 ASSERT(width
<= tex
->MaxSize
);
760 ASSERT(height
<= tex
->MaxSize
);
762 if (width
> tex
->Width
||
763 height
> tex
->Height
||
764 intFormat
!= tex
->IntFormat
) {
765 /* alloc new texture (larger or different format) */
768 /* use non-power of two size */
769 tex
->Width
= MAX2(tex
->MinSize
, width
);
770 tex
->Height
= MAX2(tex
->MinSize
, height
);
773 /* find power of two size */
775 w
= h
= tex
->MinSize
;
784 tex
->IntFormat
= intFormat
;
789 /* compute texcoords */
790 tex
->Sright
= (GLfloat
) width
/ tex
->Width
;
791 tex
->Ttop
= (GLfloat
) height
/ tex
->Height
;
798 * Setup/load texture for glCopyPixels or glBlitFramebuffer.
801 setup_copypix_texture(struct temp_texture
*tex
,
803 GLint srcX
, GLint srcY
,
804 GLsizei width
, GLsizei height
, GLenum intFormat
,
807 _mesa_BindTexture(tex
->Target
, tex
->TexObj
);
808 _mesa_TexParameteri(tex
->Target
, GL_TEXTURE_MIN_FILTER
, filter
);
809 _mesa_TexParameteri(tex
->Target
, GL_TEXTURE_MAG_FILTER
, filter
);
810 _mesa_TexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
812 /* copy framebuffer image to texture */
814 /* create new tex image */
815 if (tex
->Width
== width
&& tex
->Height
== height
) {
816 /* create new tex with framebuffer data */
817 _mesa_CopyTexImage2D(tex
->Target
, 0, tex
->IntFormat
,
818 srcX
, srcY
, width
, height
, 0);
821 /* create empty texture */
822 _mesa_TexImage2D(tex
->Target
, 0, tex
->IntFormat
,
823 tex
->Width
, tex
->Height
, 0,
824 intFormat
, GL_UNSIGNED_BYTE
, NULL
);
826 _mesa_CopyTexSubImage2D(tex
->Target
, 0,
827 0, 0, srcX
, srcY
, width
, height
);
831 /* replace existing tex image */
832 _mesa_CopyTexSubImage2D(tex
->Target
, 0,
833 0, 0, srcX
, srcY
, width
, height
);
838 * Meta implementation of ctx->Driver.CopyPixels() in terms
839 * of texture mapping and polygon rendering and GLSL shaders.
842 _mesa_meta_CopyPixels(struct gl_context
*ctx
, GLint srcX
, GLint srcY
,
843 GLsizei width
, GLsizei height
,
844 GLint dstX
, GLint dstY
, GLenum type
)
846 struct copypix_state
*copypix
= &ctx
->Meta
->CopyPix
;
847 struct temp_texture
*tex
= get_temp_texture(ctx
);
849 GLfloat x
, y
, z
, s
, t
;
851 struct vertex verts
[4];
853 GLenum intFormat
= GL_RGBA
;
855 if (type
!= GL_COLOR
||
856 ctx
->_ImageTransferState
||
858 width
> tex
->MaxSize
||
859 height
> tex
->MaxSize
) {
860 /* XXX avoid this fallback */
861 _swrast_CopyPixels(ctx
, srcX
, srcY
, width
, height
, dstX
, dstY
, type
);
865 /* Most GL state applies to glCopyPixels, but a there's a few things
866 * we need to override:
868 _mesa_meta_begin(ctx
, (MESA_META_RASTERIZATION
|
870 MESA_META_TRANSFORM
|
873 MESA_META_VIEWPORT
));
875 if (copypix
->ArrayObj
== 0) {
878 /* create vertex array object */
879 _mesa_GenVertexArrays(1, ©pix
->ArrayObj
);
880 _mesa_BindVertexArray(copypix
->ArrayObj
);
882 /* create vertex array buffer */
883 _mesa_GenBuffersARB(1, ©pix
->VBO
);
884 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB
, copypix
->VBO
);
885 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB
, sizeof(verts
),
886 NULL
, GL_DYNAMIC_DRAW_ARB
);
888 /* setup vertex arrays */
889 _mesa_VertexPointer(3, GL_FLOAT
, sizeof(struct vertex
), OFFSET(x
));
890 _mesa_TexCoordPointer(2, GL_FLOAT
, sizeof(struct vertex
), OFFSET(s
));
891 _mesa_EnableClientState(GL_VERTEX_ARRAY
);
892 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY
);
895 _mesa_BindVertexArray(copypix
->ArrayObj
);
896 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB
, copypix
->VBO
);
899 newTex
= alloc_texture(tex
, width
, height
, intFormat
);
901 /* vertex positions, texcoords (after texture allocation!) */
903 const GLfloat dstX0
= (GLfloat
) dstX
;
904 const GLfloat dstY0
= (GLfloat
) dstY
;
905 const GLfloat dstX1
= dstX
+ width
* ctx
->Pixel
.ZoomX
;
906 const GLfloat dstY1
= dstY
+ height
* ctx
->Pixel
.ZoomY
;
907 const GLfloat z
= invert_z(ctx
->Current
.RasterPos
[2]);
917 verts
[1].s
= tex
->Sright
;
922 verts
[2].s
= tex
->Sright
;
923 verts
[2].t
= tex
->Ttop
;
928 verts
[3].t
= tex
->Ttop
;
930 /* upload new vertex data */
931 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB
, 0, sizeof(verts
), verts
);
934 /* Alloc/setup texture */
935 setup_copypix_texture(tex
, newTex
, srcX
, srcY
, width
, height
,
936 GL_RGBA
, GL_NEAREST
);
938 _mesa_set_enable(ctx
, tex
->Target
, GL_TRUE
);
940 /* draw textured quad */
941 _mesa_DrawArrays(GL_TRIANGLE_FAN
, 0, 4);
943 _mesa_set_enable(ctx
, tex
->Target
, GL_FALSE
);
950 * Determine the GL data type to use for the temporary image read with
951 * ReadPixels() and passed to Tex[Sub]Image().
954 get_temp_image_type(struct gl_context
*ctx
, GLenum baseFormat
)
956 switch (baseFormat
) {
963 case GL_LUMINANCE_ALPHA
:
965 if (ctx
->DrawBuffer
->Visual
.redBits
<= 8)
966 return GL_UNSIGNED_BYTE
;
967 else if (ctx
->DrawBuffer
->Visual
.redBits
<= 16)
968 return GL_UNSIGNED_SHORT
;
971 case GL_DEPTH_COMPONENT
:
972 return GL_UNSIGNED_INT
;
974 _mesa_problem(ctx
, "Unexpected format %d in get_temp_image_type()",
982 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
983 * Have to be careful with locking and meta state for pixel transfer.
986 copy_tex_sub_image(struct gl_context
*ctx
,
988 struct gl_texture_image
*texImage
,
989 GLint xoffset
, GLint yoffset
, GLint zoffset
,
990 struct gl_renderbuffer
*rb
,
992 GLsizei width
, GLsizei height
)
994 struct gl_texture_object
*texObj
= texImage
->TexObject
;
995 const GLenum target
= texObj
->Target
;
1000 /* Choose format/type for temporary image buffer */
1001 format
= _mesa_get_format_base_format(texImage
->TexFormat
);
1002 if (format
== GL_LUMINANCE
||
1003 format
== GL_LUMINANCE_ALPHA
||
1004 format
== GL_INTENSITY
) {
1005 /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the
1006 * temp image buffer because glReadPixels will do L=R+G+B which is
1007 * not what we want (should be L=R).
1012 if (_mesa_is_format_integer_color(texImage
->TexFormat
)) {
1013 _mesa_problem(ctx
, "unsupported integer color copyteximage");
1017 type
= get_temp_image_type(ctx
, format
);
1018 bpp
= _mesa_bytes_per_pixel(format
, type
);
1020 _mesa_problem(ctx
, "Bad bpp in meta copy_tex_sub_image()");
1025 * Alloc image buffer (XXX could use a PBO)
1027 buf
= malloc(width
* height
* bpp
);
1029 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage%uD", dims
);
1033 _mesa_unlock_texture(ctx
, texObj
); /* need to unlock first */
1036 * Read image from framebuffer (disable pixel transfer ops)
1038 _mesa_meta_begin(ctx
, MESA_META_PIXEL_STORE
| MESA_META_PIXEL_TRANSFER
);
1039 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
1040 format
, type
, &ctx
->Pack
, buf
);
1041 _mesa_meta_end(ctx
);
1043 _mesa_update_state(ctx
); /* to update pixel transfer state */
1046 * Store texture data (with pixel transfer ops)
1048 _mesa_meta_begin(ctx
, MESA_META_PIXEL_STORE
);
1049 if (target
== GL_TEXTURE_1D
) {
1050 ctx
->Driver
.TexSubImage1D(ctx
, texImage
,
1052 format
, type
, buf
, &ctx
->Unpack
);
1054 else if (target
== GL_TEXTURE_3D
) {
1055 ctx
->Driver
.TexSubImage3D(ctx
, texImage
,
1056 xoffset
, yoffset
, zoffset
, width
, height
, 1,
1057 format
, type
, buf
, &ctx
->Unpack
);
1060 ctx
->Driver
.TexSubImage2D(ctx
, texImage
,
1061 xoffset
, yoffset
, width
, height
,
1062 format
, type
, buf
, &ctx
->Unpack
);
1064 _mesa_meta_end(ctx
);
1066 _mesa_lock_texture(ctx
, texObj
); /* re-lock */
1073 _mesa_meta_CopyTexSubImage1D(struct gl_context
*ctx
,
1074 struct gl_texture_image
*texImage
,
1076 struct gl_renderbuffer
*rb
,
1077 GLint x
, GLint y
, GLsizei width
)
1079 copy_tex_sub_image(ctx
, 1, texImage
, xoffset
, 0, 0,
1080 rb
, x
, y
, width
, 1);
1085 _mesa_meta_CopyTexSubImage2D(struct gl_context
*ctx
,
1086 struct gl_texture_image
*texImage
,
1087 GLint xoffset
, GLint yoffset
,
1088 struct gl_renderbuffer
*rb
,
1090 GLsizei width
, GLsizei height
)
1092 copy_tex_sub_image(ctx
, 2, texImage
, xoffset
, yoffset
, 0,
1093 rb
, x
, y
, width
, height
);
1098 _mesa_meta_CopyTexSubImage3D(struct gl_context
*ctx
,
1099 struct gl_texture_image
*texImage
,
1100 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1101 struct gl_renderbuffer
*rb
,
1103 GLsizei width
, GLsizei height
)
1105 copy_tex_sub_image(ctx
, 3, texImage
, xoffset
, yoffset
, zoffset
,
1106 rb
, x
, y
, width
, height
);