d7d79dcf6a21d30cec5f212c99c78349bda33443
[reactos.git] / reactos / dll / opengl / mesa / drivers / common / meta.c
1 /*
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/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"
66
67
68 /** Return offset in bytes of the field within a vertex struct */
69 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
70
71 /**
72 * State which we may save/restore across meta ops.
73 * XXX this may be incomplete...
74 */
75 struct save_state
76 {
77 GLbitfield SavedState; /**< bitmask of MESA_META_* flags */
78
79 /** MESA_META_ALPHA_TEST */
80 GLboolean AlphaEnabled;
81 GLenum AlphaFunc;
82 GLclampf AlphaRef;
83
84 /** MESA_META_BLEND */
85 GLbitfield BlendEnabled;
86 GLboolean ColorLogicOpEnabled;
87
88 /** MESA_META_COLOR_MASK */
89 GLubyte ColorMask[4];
90
91 /** MESA_META_DEPTH_TEST */
92 struct gl_depthbuffer_attrib Depth;
93
94 /** MESA_META_FOG */
95 GLboolean Fog;
96
97 /** MESA_META_PIXEL_STORE */
98 struct gl_pixelstore_attrib Pack, Unpack;
99
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;
107
108 /** MESA_META_RASTERIZATION */
109 GLenum FrontPolygonMode, BackPolygonMode;
110 GLboolean PolygonOffset;
111 GLboolean PolygonSmooth;
112 GLboolean PolygonStipple;
113 GLboolean PolygonCull;
114
115 /** MESA_META_SCISSOR */
116 struct gl_scissor_attrib Scissor;
117
118 /** MESA_META_STENCIL_TEST */
119 struct gl_stencil_attrib Stencil;
120
121 /** MESA_META_TRANSFORM */
122 GLenum MatrixMode;
123 GLfloat ModelviewMatrix[16];
124 GLfloat ProjectionMatrix[16];
125 GLfloat TextureMatrix[16];
126
127 /** MESA_META_CLIP */
128 GLbitfield ClipPlanesEnabled;
129
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 */
136
137 /** MESA_META_VERTEX */
138 struct gl_array_object *ArrayObj;
139 struct gl_buffer_object *ArrayBufferObj;
140
141 /** MESA_META_VIEWPORT */
142 GLint ViewportX, ViewportY, ViewportW, ViewportH;
143 GLclampd DepthNear, DepthFar;
144
145 /** MESA_META_SELECT_FEEDBACK */
146 GLenum RenderMode;
147 struct gl_selection Select;
148 struct gl_feedback Feedback;
149
150 /** Miscellaneous (always disabled) */
151 GLboolean Lighting;
152 GLboolean RasterDiscard;
153 };
154
155
156 /**
157 * State for glBlitFramebufer()
158 */
159 struct blit_state
160 {
161 GLuint ArrayObj;
162 GLuint VBO;
163 GLuint DepthFP;
164 };
165
166
167 /**
168 * State for glClear()
169 */
170 struct clear_state
171 {
172 GLuint ArrayObj;
173 GLuint VBO;
174 GLuint ShaderProg;
175 GLint ColorLocation;
176
177 GLuint IntegerShaderProg;
178 GLint IntegerColorLocation;
179 };
180
181
182 /**
183 * State for glCopyPixels()
184 */
185 struct copypix_state
186 {
187 GLuint ArrayObj;
188 GLuint VBO;
189 };
190
191 #define MAX_META_OPS_DEPTH 8
192 /**
193 * All per-context meta state.
194 */
195 struct gl_meta_state
196 {
197 /** Stack of state saved during meta-ops */
198 struct save_state Save[MAX_META_OPS_DEPTH];
199 /** Save stack depth */
200 GLuint SaveStackDepth;
201
202 struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */
203 };
204
205 /**
206 * Initialize meta-ops for a context.
207 * To be called once during context creation.
208 */
209 void
210 _mesa_meta_init(struct gl_context *ctx)
211 {
212 ASSERT(!ctx->Meta);
213
214 ctx->Meta = CALLOC_STRUCT(gl_meta_state);
215 }
216
217
218 /**
219 * Free context meta-op state.
220 * To be called once during context destruction.
221 */
222 void
223 _mesa_meta_free(struct gl_context *ctx)
224 {
225 GET_CURRENT_CONTEXT(old_context);
226 _mesa_make_current(ctx, NULL, NULL);
227 if (old_context)
228 _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer);
229 else
230 _mesa_make_current(NULL, NULL, NULL);
231 free(ctx->Meta);
232 ctx->Meta = NULL;
233 }
234
235
236 /**
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.
239 *
240 * \param state bitmask of MESA_META_* flags indicating which attribute groups
241 * to save and reset to their defaults
242 */
243 void
244 _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
245 {
246 struct save_state *save;
247
248 /* hope MAX_META_OPS_DEPTH is large enough */
249 assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH);
250
251 save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++];
252 memset(save, 0, sizeof(*save));
253 save->SavedState = state;
254
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);
261 }
262
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);
267 }
268 save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
269 if (ctx->Color.ColorLogicOpEnabled)
270 _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
271 }
272
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);
281 }
282
283 if (state & MESA_META_DEPTH_TEST) {
284 save->Depth = ctx->Depth; /* struct copy */
285 if (ctx->Depth.Test)
286 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
287 }
288
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);
293 }
294
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;
300 }
301
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;
321 /* XXX more state */
322 ctx->NewState |=_NEW_PIXEL;
323 }
324
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);
337 }
338
339 if (state & MESA_META_SCISSOR) {
340 save->Scissor = ctx->Scissor; /* struct copy */
341 _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE);
342 }
343
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 */
349 }
350
351 if (state & MESA_META_TEXTURE) {
352 GLuint tgt;
353
354 save->EnvMode = ctx->Texture.Unit.EnvMode;
355
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);
369 }
370
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]);
375 }
376 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
377 }
378
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,
396 -1.0, 1.0);
397 }
398
399 if (state & MESA_META_CLIP) {
400 save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
401 if (ctx->Transform.ClipPlanesEnabled) {
402 GLuint i;
403 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
404 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
405 }
406 }
407 }
408
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? */
416 }
417
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);
431 }
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);
437 }
438
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);
447 }
448 }
449
450 /* misc */
451 {
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);
458 }
459 }
460
461
462 /**
463 * Leave meta state. This is like a light-weight version of glPopAttrib().
464 */
465 void
466 _mesa_meta_end(struct gl_context *ctx)
467 {
468 struct save_state *save = &ctx->Meta->Save[--ctx->Meta->SaveStackDepth];
469 const GLbitfield state = save->SavedState;
470
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);
475 }
476
477 if (state & MESA_META_BLEND) {
478 if (ctx->Color.BlendEnabled != save->BlendEnabled) {
479 _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1));
480 }
481 if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
482 _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
483 }
484
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]);
489 }
490 }
491
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);
497 }
498
499 if (state & MESA_META_FOG) {
500 _mesa_set_enable(ctx, GL_FOG, save->Fog);
501 }
502
503 if (state & MESA_META_PIXEL_STORE) {
504 ctx->Pack = save->Pack;
505 ctx->Unpack = save->Unpack;
506 }
507
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;
518 /* XXX more state */
519 ctx->NewState |=_NEW_PIXEL;
520 }
521
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);
529 }
530
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);
535 }
536
537 if (state & MESA_META_STENCIL_TEST) {
538 const struct gl_stencil_attrib *stencil = &save->Stencil;
539
540 _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
541 _mesa_ClearStencil(stencil->Clear);
542 _mesa_StencilFunc(stencil->Function,
543 stencil->Ref,
544 stencil->ValueMask);
545 _mesa_StencilMask(stencil->WriteMask);
546 _mesa_StencilOp(stencil->FailFunc, stencil->ZFailFunc, stencil->ZPassFunc);
547 }
548
549 if (state & MESA_META_TEXTURE) {
550 GLuint tgt;
551
552 /* restore texenv for unit[0] */
553 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
554
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]);
561 }
562 _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
563 }
564
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;
569 }
570
571 if (ctx->Texture.Unit.TexGenEnabled != save->TexGenEnabled) {
572 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
573 ctx->Texture.Unit.TexGenEnabled = save->TexGenEnabled;
574 }
575 }
576
577 if (state & MESA_META_TRANSFORM) {
578 _mesa_MatrixMode(GL_TEXTURE);
579 _mesa_LoadMatrixf(save->TextureMatrix);
580
581 _mesa_MatrixMode(GL_MODELVIEW);
582 _mesa_LoadMatrixf(save->ModelviewMatrix);
583
584 _mesa_MatrixMode(GL_PROJECTION);
585 _mesa_LoadMatrixf(save->ProjectionMatrix);
586
587 _mesa_MatrixMode(save->MatrixMode);
588 }
589
590 if (state & MESA_META_CLIP) {
591 if (save->ClipPlanesEnabled) {
592 GLuint i;
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);
596 }
597 }
598 }
599 }
600
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);
605
606 /* restore vertex array object */
607 _mesa_BindVertexArray(save->ArrayObj->Name);
608 _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
609 }
610
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);
618 }
619 _mesa_DepthRange(save->DepthNear, save->DepthFar);
620 }
621
622 /* misc */
623 if (save->Lighting) {
624 _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
625 }
626 if (save->RasterDiscard) {
627 _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE);
628 }
629 }
630
631
632 /**
633 * Determine whether Mesa is currently in a meta state.
634 */
635 GLboolean
636 _mesa_meta_in_progress(struct gl_context *ctx)
637 {
638 return ctx->Meta->SaveStackDepth != 0;
639 }
640
641
642 /**
643 * Determine the GL data type to use for the temporary image read with
644 * ReadPixels() and passed to Tex[Sub]Image().
645 */
646 static GLenum
647 get_temp_image_type(struct gl_context *ctx, GLenum baseFormat)
648 {
649 switch (baseFormat) {
650 case GL_RGBA:
651 case GL_RGB:
652 case GL_RG:
653 case GL_RED:
654 case GL_ALPHA:
655 case GL_LUMINANCE:
656 case GL_LUMINANCE_ALPHA:
657 case GL_INTENSITY:
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;
662 else
663 return GL_FLOAT;
664 case GL_DEPTH_COMPONENT:
665 return GL_UNSIGNED_INT;
666 default:
667 _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()",
668 baseFormat);
669 return 0;
670 }
671 }
672
673
674 /**
675 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
676 * Have to be careful with locking and meta state for pixel transfer.
677 */
678 static void
679 copy_tex_sub_image(struct gl_context *ctx,
680 GLuint dims,
681 struct gl_texture_image *texImage,
682 GLint xoffset, GLint yoffset, GLint zoffset,
683 struct gl_renderbuffer *rb,
684 GLint x, GLint y,
685 GLsizei width, GLsizei height)
686 {
687 struct gl_texture_object *texObj = texImage->TexObject;
688 const GLenum target = texObj->Target;
689 GLenum format, type;
690 GLint bpp;
691 void *buf;
692
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).
701 */
702 format = GL_RGBA;
703 }
704
705 if (_mesa_is_format_integer_color(texImage->TexFormat)) {
706 _mesa_problem(ctx, "unsupported integer color copyteximage");
707 return;
708 }
709
710 type = get_temp_image_type(ctx, format);
711 bpp = _mesa_bytes_per_pixel(format, type);
712 if (bpp <= 0) {
713 _mesa_problem(ctx, "Bad bpp in meta copy_tex_sub_image()");
714 return;
715 }
716
717 /*
718 * Alloc image buffer (XXX could use a PBO)
719 */
720 buf = malloc(width * height * bpp);
721 if (!buf) {
722 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims);
723 return;
724 }
725
726 _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
727
728 /*
729 * Read image from framebuffer (disable pixel transfer ops)
730 */
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);
734 _mesa_meta_end(ctx);
735
736 _mesa_update_state(ctx); /* to update pixel transfer state */
737
738 /*
739 * Store texture data (with pixel transfer ops)
740 */
741 _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE);
742 if (target == GL_TEXTURE_1D) {
743 ctx->Driver.TexSubImage1D(ctx, texImage,
744 xoffset, width,
745 format, type, buf, &ctx->Unpack);
746 }
747 else {
748 ctx->Driver.TexSubImage2D(ctx, texImage,
749 xoffset, yoffset, width, height,
750 format, type, buf, &ctx->Unpack);
751 }
752 _mesa_meta_end(ctx);
753
754 _mesa_lock_texture(ctx, texObj); /* re-lock */
755
756 free(buf);
757 }
758
759
760 void
761 _mesa_meta_CopyTexSubImage1D(struct gl_context *ctx,
762 struct gl_texture_image *texImage,
763 GLint xoffset,
764 struct gl_renderbuffer *rb,
765 GLint x, GLint y, GLsizei width)
766 {
767 copy_tex_sub_image(ctx, 1, texImage, xoffset, 0, 0,
768 rb, x, y, width, 1);
769 }
770
771
772 void
773 _mesa_meta_CopyTexSubImage2D(struct gl_context *ctx,
774 struct gl_texture_image *texImage,
775 GLint xoffset, GLint yoffset,
776 struct gl_renderbuffer *rb,
777 GLint x, GLint y,
778 GLsizei width, GLsizei height)
779 {
780 copy_tex_sub_image(ctx, 2, texImage, xoffset, yoffset, 0,
781 rb, x, y, width, height);
782 }
783