blob: 56ad8f809b9b82f5a31b60f99dd800f8ff9eefbb [file] [log] [blame]
Brian Paul33a838b2009-08-10 13:35:58 -06001/*
2 * Mesa 3-D graphics library
3 * Version: 7.6
4 *
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 * 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.
23 */
24
25/**
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.
29 *
30 * \author Brian Paul
31 */
32
33
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/depth.h"
41#include "main/enable.h"
42#include "main/macros.h"
43#include "main/matrix.h"
44#include "main/polygon.h"
45#include "main/scissor.h"
46#include "main/shaders.h"
47#include "main/stencil.h"
48#include "main/texobj.h"
49#include "main/texenv.h"
50#include "main/teximage.h"
51#include "main/texparam.h"
52#include "main/texstate.h"
53#include "main/varray.h"
54#include "main/viewport.h"
55#include "shader/program.h"
56#include "swrast/swrast.h"
57#include "drivers/common/meta.h"
58
59
60/**
61 * State which we may save/restore across meta ops.
62 * XXX this may be incomplete...
63 */
64struct save_state
65{
66 GLbitfield SavedState; /**< bitmask of META_* flags */
67
68 /** META_ALPHA_TEST */
69 GLboolean AlphaEnabled;
70
71 /** META_BLEND */
72 GLboolean BlendEnabled;
73 GLboolean ColorLogicOpEnabled;
74
75 /** META_COLOR_MASK */
76 GLubyte ColorMask[4];
77
78 /** META_DEPTH_TEST */
79 struct gl_depthbuffer_attrib Depth;
80
81 /** META_PIXELSTORE */
82 /* XXX / TO-DO */
83
84 /** META_RASTERIZATION */
85 GLenum FrontPolygonMode, BackPolygonMode;
86 GLboolean PolygonOffset;
87 GLboolean PolygonSmooth;
88 GLboolean PolygonStipple;
89 GLboolean PolygonCull;
90
91 /** META_SCISSOR */
92 struct gl_scissor_attrib Scissor;
93
94 /** META_SHADER */
95 GLboolean VertexProgramEnabled;
96 struct gl_vertex_program *VertexProgram;
97 GLboolean FragmentProgramEnabled;
98 struct gl_fragment_program *FragmentProgram;
99 GLuint Shader;
100
101 /** META_STENCIL_TEST */
102 struct gl_stencil_attrib Stencil;
103
104 /** META_TRANSFORM */
105 GLenum MatrixMode;
106 GLfloat ModelviewMatrix[16];
107 GLfloat ProjectionMatrix[16];
Brian Pauledb991b2009-08-10 15:44:05 -0600108 GLfloat TextureMatrix[16];
Brian Paul33a838b2009-08-10 13:35:58 -0600109 GLbitfield ClipPlanesEnabled;
110
111 /** META_TEXTURE */
112 GLuint ActiveUnit;
113 GLuint ClientActiveUnit;
114 /** for unit[0] only */
115 struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
116 /** mask of TEXTURE_2D_BIT, etc */
117 GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
118 GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
119 GLuint EnvMode; /* unit[0] only */
120
121 /** META_VERTEX */
122 struct gl_array_object *ArrayObj;
123 struct gl_buffer_object *ArrayBufferObj;
124
125 /** META_VIEWPORT */
126 GLint ViewportX, ViewportY, ViewportW, ViewportH;
127 GLclampd DepthNear, DepthFar;
128
129 /** Miscellaneous (always disabled) */
130 GLboolean Lighting;
131 GLboolean Fog;
132};
133
134
135/**
136 * State for glBlitFramebufer()
137 */
138struct blit_state
139{
140 GLuint TexObj;
Brian Paul2ad10c92009-08-10 15:05:53 -0600141 GLsizei TexWidth, TexHeight;
142 GLenum TexType;
Brian Paul33a838b2009-08-10 13:35:58 -0600143 GLuint ArrayObj;
144 GLuint VBO;
145 GLfloat verts[4][4]; /** four verts of X,Y,S,T */
146};
147
148
149/**
150 * State for glClear()
151 */
152struct clear_state
153{
154 GLuint ArrayObj;
155 GLuint VBO;
156 GLfloat verts[4][7]; /** four verts of X,Y,Z,R,G,B,A */
157};
158
159
160/**
Brian Paulc16fa382009-08-10 14:43:15 -0600161 * State for glCopyPixels()
162 */
163struct copypix_state
164{
165 GLuint TexObj;
166 GLsizei TexWidth, TexHeight;
167 GLenum TexType;
168 GLuint ArrayObj;
169 GLuint VBO;
170 GLfloat verts[4][5]; /** four verts of X,Y,Z,S,T */
171};
172
173
174
175/**
Brian Paul33a838b2009-08-10 13:35:58 -0600176 * All per-context meta state.
177 */
178struct gl_meta_state
179{
180 struct save_state Save; /**< state saved during meta-ops */
181
182 struct blit_state Blit; /**< For _mesa_meta_blit_framebuffer() */
183 struct clear_state Clear; /**< For _mesa_meta_clear() */
Brian Paulc16fa382009-08-10 14:43:15 -0600184 struct copypix_state CopyPix; /**< For _mesa_meta_copy_pixels() */
Brian Paul33a838b2009-08-10 13:35:58 -0600185
186 /* other possible meta-ops:
187 * glDrawPixels()
188 * glCopyPixels()
189 * glBitmap()
190 */
191};
192
193
194/**
195 * Initialize meta-ops for a context.
196 * To be called once during context creation.
197 */
198void
199_mesa_meta_init(GLcontext *ctx)
200{
201 ASSERT(!ctx->Meta);
202
203 ctx->Meta = CALLOC_STRUCT(gl_meta_state);
204}
205
206
207/**
208 * Free context meta-op state.
209 * To be called once during context destruction.
210 */
211void
212_mesa_meta_free(GLcontext *ctx)
213{
214 struct gl_meta_state *meta = ctx->Meta;
215
216 if (meta->Blit.TexObj) {
217 _mesa_DeleteTextures(1, &meta->Blit.TexObj);
218 _mesa_DeleteBuffersARB(1, & meta->Blit.VBO);
219 _mesa_DeleteVertexArraysAPPLE(1, &meta->Blit.ArrayObj);
220 }
221
222 if (meta->Clear.VBO) {
223 _mesa_DeleteBuffersARB(1, & meta->Clear.VBO);
224 _mesa_DeleteVertexArraysAPPLE(1, &meta->Clear.ArrayObj);
225 }
226
Brian Paulc16fa382009-08-10 14:43:15 -0600227 if (meta->CopyPix.TexObj) {
228 _mesa_DeleteTextures(1, &meta->CopyPix.TexObj);
229 _mesa_DeleteBuffersARB(1, & meta->CopyPix.VBO);
230 _mesa_DeleteVertexArraysAPPLE(1, &meta->CopyPix.ArrayObj);
231 }
232
Brian Paul33a838b2009-08-10 13:35:58 -0600233 _mesa_free(ctx->Meta);
234 ctx->Meta = NULL;
235}
236
237
238/**
239 * Enter meta state. This is like a light-weight version of glPushAttrib
240 * but it also resets most GL state back to default values.
241 *
242 * \param state bitmask of META_* flags indicating which attribute groups
243 * to save and reset to their defaults
244 */
245static void
246_mesa_meta_begin(GLcontext *ctx, GLbitfield state)
247{
248 struct save_state *save = &ctx->Meta->Save;
249
250 save->SavedState = state;
251
252 if (state & META_ALPHA_TEST) {
253 save->AlphaEnabled = ctx->Color.AlphaEnabled;
254 if (ctx->Color.AlphaEnabled)
255 _mesa_Disable(GL_ALPHA_TEST);
256 }
257
258 if (state & META_BLEND) {
259 save->BlendEnabled = ctx->Color.BlendEnabled;
260 if (ctx->Color.BlendEnabled)
261 _mesa_Disable(GL_BLEND);
262 save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
263 if (ctx->Color.ColorLogicOpEnabled)
264 _mesa_Disable(GL_COLOR_LOGIC_OP);
265 }
266
267 if (state & META_COLOR_MASK) {
268 COPY_4V(save->ColorMask, ctx->Color.ColorMask);
269 if (!ctx->Color.ColorMask[0] ||
270 !ctx->Color.ColorMask[1] ||
271 !ctx->Color.ColorMask[2] ||
272 !ctx->Color.ColorMask[3])
273 _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
274 }
275
276 if (state & META_DEPTH_TEST) {
277 save->Depth = ctx->Depth; /* struct copy */
278 if (ctx->Depth.Test)
279 _mesa_Disable(GL_DEPTH_TEST);
280 }
281
282 if (state & META_RASTERIZATION) {
283 save->FrontPolygonMode = ctx->Polygon.FrontMode;
284 save->BackPolygonMode = ctx->Polygon.BackMode;
285 save->PolygonOffset = ctx->Polygon.OffsetFill;
286 save->PolygonSmooth = ctx->Polygon.SmoothFlag;
287 save->PolygonStipple = ctx->Polygon.StippleFlag;
288 save->PolygonCull = ctx->Polygon.CullFlag;
289 _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
290 _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
291 _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
292 _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
293 _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
294 }
295
296 if (state & META_SCISSOR) {
297 save->Scissor = ctx->Scissor; /* struct copy */
298 }
299
300 if (state & META_SHADER) {
301 if (ctx->Extensions.ARB_vertex_program) {
302 save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
303 save->VertexProgram = ctx->VertexProgram.Current;
304 _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
305 }
306
307 if (ctx->Extensions.ARB_fragment_program) {
308 save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
309 save->FragmentProgram = ctx->FragmentProgram.Current;
310 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
311 }
312
313 if (ctx->Extensions.ARB_shader_objects) {
314 save->Shader = ctx->Shader.CurrentProgram ?
315 ctx->Shader.CurrentProgram->Name : 0;
316 _mesa_UseProgramObjectARB(0);
317 }
318 }
319
320 if (state & META_STENCIL_TEST) {
321 save->Stencil = ctx->Stencil; /* struct copy */
322 if (ctx->Stencil.Enabled)
323 _mesa_Disable(GL_STENCIL_TEST);
324 /* NOTE: other stencil state not reset */
325 }
326
327 if (state & META_TEXTURE) {
328 GLuint u, tgt;
329
330 save->ActiveUnit = ctx->Texture.CurrentUnit;
331 save->ClientActiveUnit = ctx->Array.ActiveTexture;
332 save->EnvMode = ctx->Texture.Unit[0].EnvMode;
333
334 /* Disable all texture units */
335 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
336 save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
337 save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
338 _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
339 _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
340 _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
341 _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
342 _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
343 _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
344 _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
345 _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
346 _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
347 _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
348 }
349
350 /* save current texture objects for unit[0] only */
351 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
352 _mesa_reference_texobj(&save->CurrentTexture[tgt],
353 ctx->Texture.Unit[0].CurrentTex[tgt]);
354 }
355
356 /* set defaults for unit[0] */
357 _mesa_ActiveTextureARB(GL_TEXTURE0);
358 _mesa_ClientActiveTextureARB(GL_TEXTURE0);
359 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
360 _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
361 _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
362 _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
363 _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
364 }
365
366 if (state & META_TRANSFORM) {
Brian Pauledb991b2009-08-10 15:44:05 -0600367 GLuint activeTexture = ctx->Texture.CurrentUnit;
Brian Paul33a838b2009-08-10 13:35:58 -0600368 _mesa_memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
369 16 * sizeof(GLfloat));
370 _mesa_memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
371 16 * sizeof(GLfloat));
Brian Pauledb991b2009-08-10 15:44:05 -0600372 _mesa_memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m,
373 16 * sizeof(GLfloat));
Brian Paul33a838b2009-08-10 13:35:58 -0600374 save->MatrixMode = ctx->Transform.MatrixMode;
375 /* set 1:1 vertex:pixel coordinate transform */
Brian Pauledb991b2009-08-10 15:44:05 -0600376 _mesa_ActiveTextureARB(GL_TEXTURE0);
377 _mesa_MatrixMode(GL_TEXTURE);
378 _mesa_LoadIdentity();
379 _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
Brian Paul33a838b2009-08-10 13:35:58 -0600380 _mesa_MatrixMode(GL_MODELVIEW);
381 _mesa_LoadIdentity();
382 _mesa_MatrixMode(GL_PROJECTION);
383 _mesa_LoadIdentity();
384 _mesa_Ortho(0.0F, ctx->DrawBuffer->Width,
385 0.0F, ctx->DrawBuffer->Height,
386 -1.0F, 1.0F);
387 save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
388 if (ctx->Transform.ClipPlanesEnabled) {
389 GLuint i;
390 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
391 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
392 }
393 }
394 }
395
396 if (state & META_VERTEX) {
397 /* save vertex array object state */
398 _mesa_reference_array_object(ctx, &save->ArrayObj,
399 ctx->Array.ArrayObj);
400 _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
401 ctx->Array.ArrayBufferObj);
402 /* set some default state? */
403 }
404
405 if (state & META_VIEWPORT) {
406 save->ViewportX = ctx->Viewport.X;
407 save->ViewportY = ctx->Viewport.Y;
408 save->ViewportW = ctx->Viewport.Width;
409 save->ViewportH = ctx->Viewport.Height;
410 _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
411 save->DepthNear = ctx->Viewport.Near;
412 save->DepthFar = ctx->Viewport.Far;
413 _mesa_DepthRange(0.0, 1.0);
414 }
415
416 /* misc */
417 {
418 save->Lighting = ctx->Light.Enabled;
419 if (ctx->Light.Enabled)
420 _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
421
422 save->Fog = ctx->Fog.Enabled;
423 if (ctx->Fog.Enabled)
424 _mesa_set_enable(ctx, GL_FOG, GL_FALSE);
425 }
426}
427
428
429/**
430 * Leave meta state. This is like a light-weight version of glPopAttrib().
431 */
432static void
433_mesa_meta_end(GLcontext *ctx)
434{
435 struct save_state *save = &ctx->Meta->Save;
436 const GLbitfield state = save->SavedState;
437
438 if (state & META_ALPHA_TEST) {
439 if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
440 _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
441 }
442
443 if (state & META_BLEND) {
444 if (ctx->Color.BlendEnabled != save->BlendEnabled)
445 _mesa_set_enable(ctx, GL_BLEND, save->BlendEnabled);
446 if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
447 _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
448 }
449
450 if (state & META_COLOR_MASK) {
451 if (!TEST_EQ_4V(ctx->Color.ColorMask, save->ColorMask))
452 _mesa_ColorMask(save->ColorMask[0], save->ColorMask[1],
453 save->ColorMask[2], save->ColorMask[3]);
454 }
455
456 if (state & META_DEPTH_TEST) {
457 if (ctx->Depth.Test != save->Depth.Test)
458 _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
459 _mesa_DepthFunc(save->Depth.Func);
460 _mesa_DepthMask(save->Depth.Mask);
461 }
462
463 if (state & META_RASTERIZATION) {
464 _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
465 _mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
466 _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
467 _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
468 _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
469 _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
470 }
471
472 if (state & META_SCISSOR) {
473 _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
474 _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
475 save->Scissor.Width, save->Scissor.Height);
476 }
477
478 if (state & META_SHADER) {
479 if (ctx->Extensions.ARB_vertex_program) {
480 _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
481 save->VertexProgramEnabled);
482 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
483 save->VertexProgram);
484 }
485
486 if (ctx->Extensions.ARB_fragment_program) {
487 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
488 save->FragmentProgramEnabled);
489 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
490 save->FragmentProgram);
491 }
492
493 if (ctx->Extensions.ARB_shader_objects) {
494 _mesa_UseProgramObjectARB(save->Shader);
495 }
496 }
497
498 if (state & META_STENCIL_TEST) {
499 const struct gl_stencil_attrib *stencil = &save->Stencil;
500
501 _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
502 _mesa_ClearStencil(stencil->Clear);
503 if (ctx->Extensions.EXT_stencil_two_side) {
504 _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
505 stencil->TestTwoSide);
506 _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
507 ? GL_BACK : GL_FRONT);
508 }
509 /* front state */
510 _mesa_StencilFuncSeparate(GL_FRONT,
511 stencil->Function[0],
512 stencil->Ref[0],
513 stencil->ValueMask[0]);
514 _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
515 _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
516 stencil->ZFailFunc[0],
517 stencil->ZPassFunc[0]);
518 /* back state */
519 _mesa_StencilFuncSeparate(GL_BACK,
520 stencil->Function[1],
521 stencil->Ref[1],
522 stencil->ValueMask[1]);
523 _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
524 _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
525 stencil->ZFailFunc[1],
526 stencil->ZPassFunc[1]);
527 }
528
529 if (state & META_TEXTURE) {
530 GLuint u, tgt;
531
532 ASSERT(ctx->Texture.CurrentUnit == 0);
533
534 /* restore texenv for unit[0] */
535 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
536
537 /* restore texture objects for unit[0] only */
538 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
539 _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
540 save->CurrentTexture[tgt]);
541 }
542
543 /* Re-enable textures, texgen */
544 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
545 if (save->TexEnabled[u]) {
546 _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
547
548 if (save->TexEnabled[u] & TEXTURE_1D_BIT)
549 _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_TRUE);
550 if (save->TexEnabled[u] & TEXTURE_2D_BIT)
551 _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_TRUE);
552 if (save->TexEnabled[u] & TEXTURE_3D_BIT)
553 _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_TRUE);
554 if (save->TexEnabled[u] & TEXTURE_CUBE_BIT)
555 _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_TRUE);
556 if (save->TexEnabled[u] & TEXTURE_RECT_BIT)
557 _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_TRUE);
558 }
559
560 if (save->TexGenEnabled[u]) {
561 _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
562
563 if (save->TexGenEnabled[u] & S_BIT)
564 _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_TRUE);
565 if (save->TexGenEnabled[u] & T_BIT)
566 _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_TRUE);
567 if (save->TexGenEnabled[u] & R_BIT)
568 _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_TRUE);
569 if (save->TexGenEnabled[u] & Q_BIT)
570 _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
571 }
572 }
573
574 /* restore current unit state */
575 _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit);
576 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit);
577 }
578
579 if (state & META_TRANSFORM) {
Brian Pauledb991b2009-08-10 15:44:05 -0600580 GLuint activeTexture = ctx->Texture.CurrentUnit;
581 _mesa_ActiveTextureARB(GL_TEXTURE0);
582 _mesa_MatrixMode(GL_TEXTURE);
583 _mesa_LoadMatrixf(save->TextureMatrix);
584 _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
585
Brian Paul33a838b2009-08-10 13:35:58 -0600586 _mesa_MatrixMode(GL_MODELVIEW);
587 _mesa_LoadMatrixf(save->ModelviewMatrix);
Brian Pauledb991b2009-08-10 15:44:05 -0600588
Brian Paul33a838b2009-08-10 13:35:58 -0600589 _mesa_MatrixMode(GL_PROJECTION);
590 _mesa_LoadMatrixf(save->ProjectionMatrix);
Brian Pauledb991b2009-08-10 15:44:05 -0600591
Brian Paul33a838b2009-08-10 13:35:58 -0600592 _mesa_MatrixMode(save->MatrixMode);
Brian Pauledb991b2009-08-10 15:44:05 -0600593
Brian Paul33a838b2009-08-10 13:35:58 -0600594 save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
595 if (save->ClipPlanesEnabled) {
596 GLuint i;
597 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
598 if (save->ClipPlanesEnabled & (1 << i)) {
599 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
600 }
601 }
602 }
603 }
604
605 if (state & META_VERTEX) {
606 /* restore vertex buffer object */
607 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
608 _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
609
610 /* restore vertex array object */
611 _mesa_BindVertexArray(save->ArrayObj->Name);
612 _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
613 }
614
615 if (state & META_VIEWPORT) {
616 _mesa_Viewport(save->ViewportX, save->ViewportY,
617 save->ViewportW, save->ViewportH);
618 _mesa_DepthRange(save->DepthNear, save->DepthFar);
619 }
620
621 /* misc */
622 if (save->Lighting) {
623 _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
624 }
625 if (save->Fog) {
626 _mesa_set_enable(ctx, GL_FOG, GL_TRUE);
627 }
628}
629
630
631/**
632 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
633 * of texture mapping and polygon rendering.
634 * Note: this function requires GL_ARB_texture_rectangle support.
635 */
636void
637_mesa_meta_blit_framebuffer(GLcontext *ctx,
638 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
639 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
640 GLbitfield mask, GLenum filter)
641{
642 struct blit_state *blit = &ctx->Meta->Blit;
643 const GLint srcX = MIN2(srcX0, srcX1);
644 const GLint srcY = MIN2(srcY0, srcY1);
645 const GLint srcW = abs(srcX1 - srcX0);
646 const GLint srcH = abs(srcY1 - srcY0);
647 GLboolean srcFlipX = srcX1 < srcX0;
648 GLboolean srcFlipY = srcY1 < srcY0;
649
650 ASSERT(ctx->Extensions.NV_texture_rectangle);
651
Brian Paul2ad10c92009-08-10 15:05:53 -0600652 if (srcW > ctx->Const.MaxTextureRectSize ||
653 srcH > ctx->Const.MaxTextureRectSize) {
654 /* XXX avoid this fallback */
655 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
656 dstX0, dstY0, dstX1, dstY1, mask, filter);
657 return;
658 }
659
660
Brian Paul33a838b2009-08-10 13:35:58 -0600661 if (srcFlipX) {
662 GLint tmp = dstX0;
663 dstX0 = dstX1;
664 dstX1 = tmp;
665 }
666
667 if (srcFlipY) {
668 GLint tmp = dstY0;
669 dstY0 = dstY1;
670 dstY1 = tmp;
671 }
672
673 /* only scissor effects blit so save/clear all other relevant state */
674 _mesa_meta_begin(ctx, ~META_SCISSOR);
675
676 if (blit->TexObj == 0) {
677 /* one-time setup */
678
679 /* create texture object */
680 _mesa_GenTextures(1, &blit->TexObj);
681 _mesa_BindTexture(GL_TEXTURE_RECTANGLE, blit->TexObj);
682 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
683 }
684 else {
685 _mesa_BindTexture(GL_TEXTURE_RECTANGLE, blit->TexObj);
686 }
687
688 _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, filter);
689 _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, filter);
690
691 if (blit->ArrayObj == 0) {
692 /* one-time setup */
693
694 /* create vertex array object */
695 _mesa_GenVertexArrays(1, &blit->ArrayObj);
696 _mesa_BindVertexArray(blit->ArrayObj);
697
698 /* create vertex array buffer */
699 _mesa_GenBuffersARB(1, &blit->VBO);
700 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
701 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(blit->verts),
702 blit->verts, GL_STREAM_DRAW_ARB);
703
704 /* setup vertex arrays */
705 _mesa_VertexPointer(2, GL_FLOAT, 4 * sizeof(GLfloat),
706 (void*) (0 * sizeof(GLfloat)));
707 _mesa_TexCoordPointer(2, GL_FLOAT, 4 * sizeof(GLfloat),
708 (void *) (2 * sizeof(GLfloat)));
709 _mesa_EnableClientState(GL_VERTEX_ARRAY);
710 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
711 }
712 else {
713 _mesa_BindVertexArray(blit->ArrayObj);
714 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
715 }
716
717 /* vertex positions */
718 blit->verts[0][0] = (GLfloat) dstX0;
719 blit->verts[0][1] = (GLfloat) dstY0;
720 blit->verts[1][0] = (GLfloat) dstX1;
721 blit->verts[1][1] = (GLfloat) dstY0;
722 blit->verts[2][0] = (GLfloat) dstX1;
723 blit->verts[2][1] = (GLfloat) dstY1;
724 blit->verts[3][0] = (GLfloat) dstX0;
725 blit->verts[3][1] = (GLfloat) dstY1;
726
727 /* texcoords */
728 blit->verts[0][2] = 0.0F;
729 blit->verts[0][3] = 0.0F;
730 blit->verts[1][2] = (GLfloat) srcW;
731 blit->verts[1][3] = 0.0F;
732 blit->verts[2][2] = (GLfloat) srcW;
733 blit->verts[2][3] = (GLfloat) srcH;
734 blit->verts[3][2] = 0.0F;
735 blit->verts[3][3] = (GLfloat) srcH;
736
737 /* upload new vertex data */
738 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0,
739 sizeof(blit->verts), blit->verts);
740
741 /* copy framebuffer image to texture */
742 if (mask & GL_COLOR_BUFFER_BIT) {
Brian Paul2ad10c92009-08-10 15:05:53 -0600743 if (blit->TexWidth == srcW &&
744 blit->TexHeight == srcH &&
745 blit->TexType == GL_RGBA) {
746 /* replace existing tex image */
747 _mesa_CopyTexSubImage2D(GL_TEXTURE_RECTANGLE, 0,
748 0, 0, srcX, srcY, srcW, srcH);
749 }
750 else {
751 /* create new tex image */
752 _mesa_CopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA,
753 srcX, srcY, srcW, srcH, 0);
754 blit->TexWidth = srcW;
755 blit->TexHeight = srcH;
756 blit->TexType = GL_RGBA;
757 }
758
Brian Paul33a838b2009-08-10 13:35:58 -0600759 mask &= ~GL_COLOR_BUFFER_BIT;
760 }
761
762 _mesa_Enable(GL_TEXTURE_RECTANGLE);
763
764 /* draw textured quad */
765 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
766
767 _mesa_Disable(GL_TEXTURE_RECTANGLE);
768
769 _mesa_meta_end(ctx);
770
771 /* XXX, TO-DO: try to handle these cases above! */
772 if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
773 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
774 dstX0, dstY0, dstX1, dstY1, mask, filter);
775 }
Brian Paul33a838b2009-08-10 13:35:58 -0600776}
777
778
779/**
780 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
781 */
782void
783_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers)
784{
785 struct clear_state *clear = &ctx->Meta->Clear;
786 GLfloat z = 1.0 - 2.0 * ctx->Depth.Clear;
787 GLuint i;
788
789 /* only scissor and color mask effects clearing */
790 _mesa_meta_begin(ctx, ~(META_SCISSOR | META_COLOR_MASK));
791
792 if (clear->ArrayObj == 0) {
793 /* one-time setup */
794
795 /* create vertex array object */
796 _mesa_GenVertexArrays(1, &clear->ArrayObj);
797 _mesa_BindVertexArray(clear->ArrayObj);
798
799 /* create vertex array buffer */
800 _mesa_GenBuffersARB(1, &clear->VBO);
801 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
802 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(clear->verts),
803 clear->verts, GL_STREAM_DRAW_ARB);
804
805 /* setup vertex arrays */
806 _mesa_VertexPointer(3, GL_FLOAT, 7 * sizeof(GLfloat), (void *) 0);
807 _mesa_ColorPointer(4, GL_FLOAT, 7 * sizeof(GLfloat),
808 (void *) (3 * sizeof(GLfloat)));
809 _mesa_EnableClientState(GL_VERTEX_ARRAY);
810 _mesa_EnableClientState(GL_COLOR_ARRAY);
811 }
812 else {
813 _mesa_BindVertexArray(clear->ArrayObj);
814 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
815 }
816
817 /* GL_COLOR_BUFFER_BIT */
818 if (buffers & BUFFER_BITS_COLOR) {
819 /* leave colormask, glDrawBuffer state as-is */
820 }
821 else {
822 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
823 }
824
825 /* GL_DEPTH_BUFFER_BIT */
826 if (buffers & BUFFER_BIT_DEPTH) {
827 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
828 _mesa_DepthFunc(GL_ALWAYS);
829 _mesa_DepthMask(GL_TRUE);
830 }
831 else {
832 assert(!ctx->Depth.Test);
833 }
834
835 /* GL_STENCIL_BUFFER_BIT */
836 if (buffers & BUFFER_BIT_STENCIL) {
837 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
838 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
839 GL_REPLACE, GL_REPLACE, GL_REPLACE);
840 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
841 ctx->Stencil.Clear & 0x7fffffff,
842 ctx->Stencil.WriteMask[0]);
843 }
844 else {
845 assert(!ctx->Stencil.Enabled);
846 }
847
848 /* vertex positions */
849 clear->verts[0][0] = (GLfloat) ctx->DrawBuffer->_Xmin;
850 clear->verts[0][1] = (GLfloat) ctx->DrawBuffer->_Ymin;
851 clear->verts[0][2] = z;
852 clear->verts[1][0] = (GLfloat) ctx->DrawBuffer->_Xmax;
853 clear->verts[1][1] = (GLfloat) ctx->DrawBuffer->_Ymin;
854 clear->verts[1][2] = z;
855 clear->verts[2][0] = (GLfloat) ctx->DrawBuffer->_Xmax;
856 clear->verts[2][1] = (GLfloat) ctx->DrawBuffer->_Ymax;
857 clear->verts[2][2] = z;
858 clear->verts[3][0] = (GLfloat) ctx->DrawBuffer->_Xmin;
859 clear->verts[3][1] = (GLfloat) ctx->DrawBuffer->_Ymax;
860 clear->verts[3][2] = z;
861
862 /* vertex colors */
863 for (i = 0; i < 4; i++) {
864 COPY_4FV(&clear->verts[i][3], ctx->Color.ClearColor);
865 }
866
867 /* upload new vertex data */
868 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0,
869 sizeof(clear->verts), clear->verts);
870
871 /* draw quad */
872 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
873
874 _mesa_meta_end(ctx);
875}
876
Brian Paulc16fa382009-08-10 14:43:15 -0600877
878/**
879 * Meta implementation of ctx->Driver.CopyPixels() in terms
880 * of texture mapping and polygon rendering.
881 * Note: this function requires GL_ARB_texture_rectangle support.
882 */
883void
884_mesa_meta_copy_pixels(GLcontext *ctx, GLint srcX, GLint srcY,
885 GLsizei width, GLsizei height,
886 GLint dstX, GLint dstY, GLenum type)
887{
888 const GLenum filter = GL_NEAREST;
889 struct copypix_state *copypix = &ctx->Meta->CopyPix;
890 const GLfloat z = ctx->Current.RasterPos[2];
891 const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
892 const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
893
894 ASSERT(ctx->Extensions.NV_texture_rectangle);
895
896 if (type != GL_COLOR ||
897 ctx->_ImageTransferState ||
898 width > ctx->Const.MaxTextureRectSize ||
899 height > ctx->Const.MaxTextureRectSize) {
900 /* XXX avoid this fallback */
901 _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type);
902 return;
903 }
904
905 /* Most GL state applies to glCopyPixels, but a there's a few things
906 * we need to override:
907 */
908 _mesa_meta_begin(ctx, (META_RASTERIZATION |
909 META_SHADER |
Brian Pauledb991b2009-08-10 15:44:05 -0600910 META_TEXTURE |
Brian Paulc16fa382009-08-10 14:43:15 -0600911 META_TRANSFORM |
Brian Pauledb991b2009-08-10 15:44:05 -0600912 META_VERTEX |
913 META_VIEWPORT));
Brian Paulc16fa382009-08-10 14:43:15 -0600914
915 if (copypix->TexObj == 0) {
916 /* one-time setup */
917
918 /* create texture object */
919 _mesa_GenTextures(1, &copypix->TexObj);
920 _mesa_BindTexture(GL_TEXTURE_RECTANGLE, copypix->TexObj);
921 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
922 _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, filter);
923 _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, filter);
924 }
925 else {
926 _mesa_BindTexture(GL_TEXTURE_RECTANGLE, copypix->TexObj);
927 }
928
929 if (copypix->ArrayObj == 0) {
930 /* one-time setup */
931
932 /* create vertex array object */
933 _mesa_GenVertexArrays(1, &copypix->ArrayObj);
934 _mesa_BindVertexArray(copypix->ArrayObj);
935
936 /* create vertex array buffer */
937 _mesa_GenBuffersARB(1, &copypix->VBO);
938 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
939 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(copypix->verts),
940 copypix->verts, GL_STREAM_DRAW_ARB);
941
942 /* setup vertex arrays */
943 _mesa_VertexPointer(3, GL_FLOAT, sizeof(copypix->verts[0]),
944 (void*) (0 * sizeof(GLfloat)));
945 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(copypix->verts[0]),
946 (void *) (3 * sizeof(GLfloat)));
947 _mesa_EnableClientState(GL_VERTEX_ARRAY);
948 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
949 }
950 else {
951 _mesa_BindVertexArray(copypix->ArrayObj);
952 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
953 }
954
955 /* vertex positions, texcoords */
956 copypix->verts[0][0] = (GLfloat) dstX;
957 copypix->verts[0][1] = (GLfloat) dstY;
958 copypix->verts[0][2] = z;
959 copypix->verts[0][3] = 0.0F;
960 copypix->verts[0][4] = 0.0F;
961 copypix->verts[1][0] = (GLfloat) dstX1;
962 copypix->verts[1][1] = (GLfloat) dstY;
963 copypix->verts[1][2] = z;
964 copypix->verts[1][3] = (GLfloat) width;
965 copypix->verts[1][4] = 0.0F;
966 copypix->verts[2][0] = (GLfloat) dstX1;
967 copypix->verts[2][1] = (GLfloat) dstY1;
968 copypix->verts[2][2] = z;
969 copypix->verts[2][3] = (GLfloat) width;
970 copypix->verts[2][4] = (GLfloat) height;
971 copypix->verts[3][0] = (GLfloat) dstX;
972 copypix->verts[3][1] = (GLfloat) dstY1;
973 copypix->verts[3][2] = z;
974 copypix->verts[3][3] = 0.0F;
975 copypix->verts[3][4] = (GLfloat) height;
976
977 /* upload new vertex data */
978 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0,
979 sizeof(copypix->verts), copypix->verts);
980
981 /* copy framebuffer image to texture */
982 if (type == GL_COLOR) {
983 if (copypix->TexWidth == width &&
984 copypix->TexHeight == height &&
985 copypix->TexType == type) {
986 /* replace existing tex image */
987 _mesa_CopyTexSubImage2D(GL_TEXTURE_RECTANGLE, 0,
988 0, 0, srcX, srcY, width, height);
989 }
990 else {
991 /* create new tex image */
992 _mesa_CopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA,
993 srcX, srcY, width, height, 0);
994 copypix->TexWidth = width;
995 copypix->TexHeight = height;
996 copypix->TexType = type;
997 }
998 }
999 else if (type == GL_DEPTH) {
1000 /* TO-DO: Use a GL_DEPTH_COMPONENT texture and a fragment program/shader
1001 * that replaces the fragment.z value.
1002 */
1003 }
1004 else {
1005 ASSERT(type == GL_STENCIL);
1006 /* have to use sw fallback */
1007 }
1008
1009 _mesa_Enable(GL_TEXTURE_RECTANGLE);
1010
1011 /* draw textured quad */
1012 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1013
1014 _mesa_Disable(GL_TEXTURE_RECTANGLE);
1015
1016 _mesa_meta_end(ctx);
1017}