meta: Fix saving the active program
[mesa.git] / src / 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/arbprogram.h"
38 #include "main/arrayobj.h"
39 #include "main/blend.h"
40 #include "main/bufferobj.h"
41 #include "main/buffers.h"
42 #include "main/colortab.h"
43 #include "main/condrender.h"
44 #include "main/depth.h"
45 #include "main/enable.h"
46 #include "main/fbobject.h"
47 #include "main/formats.h"
48 #include "main/image.h"
49 #include "main/macros.h"
50 #include "main/matrix.h"
51 #include "main/mipmap.h"
52 #include "main/pixel.h"
53 #include "main/pbo.h"
54 #include "main/polygon.h"
55 #include "main/readpix.h"
56 #include "main/scissor.h"
57 #include "main/shaderapi.h"
58 #include "main/shaderobj.h"
59 #include "main/state.h"
60 #include "main/stencil.h"
61 #include "main/texobj.h"
62 #include "main/texenv.h"
63 #include "main/texgetimage.h"
64 #include "main/teximage.h"
65 #include "main/texparam.h"
66 #include "main/texstate.h"
67 #include "main/uniforms.h"
68 #include "main/varray.h"
69 #include "main/viewport.h"
70 #include "program/program.h"
71 #include "swrast/swrast.h"
72 #include "drivers/common/meta.h"
73
74
75 /** Return offset in bytes of the field within a vertex struct */
76 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
77
78 /**
79 * State which we may save/restore across meta ops.
80 * XXX this may be incomplete...
81 */
82 struct save_state
83 {
84 GLbitfield SavedState; /**< bitmask of MESA_META_* flags */
85
86 /** MESA_META_ALPHA_TEST */
87 GLboolean AlphaEnabled;
88 GLenum AlphaFunc;
89 GLclampf AlphaRef;
90
91 /** MESA_META_BLEND */
92 GLbitfield BlendEnabled;
93 GLboolean ColorLogicOpEnabled;
94
95 /** MESA_META_COLOR_MASK */
96 GLubyte ColorMask[MAX_DRAW_BUFFERS][4];
97
98 /** MESA_META_DEPTH_TEST */
99 struct gl_depthbuffer_attrib Depth;
100
101 /** MESA_META_FOG */
102 GLboolean Fog;
103
104 /** MESA_META_PIXEL_STORE */
105 struct gl_pixelstore_attrib Pack, Unpack;
106
107 /** MESA_META_PIXEL_TRANSFER */
108 GLfloat RedBias, RedScale;
109 GLfloat GreenBias, GreenScale;
110 GLfloat BlueBias, BlueScale;
111 GLfloat AlphaBias, AlphaScale;
112 GLfloat DepthBias, DepthScale;
113 GLboolean MapColorFlag;
114
115 /** MESA_META_RASTERIZATION */
116 GLenum FrontPolygonMode, BackPolygonMode;
117 GLboolean PolygonOffset;
118 GLboolean PolygonSmooth;
119 GLboolean PolygonStipple;
120 GLboolean PolygonCull;
121
122 /** MESA_META_SCISSOR */
123 struct gl_scissor_attrib Scissor;
124
125 /** MESA_META_SHADER */
126 GLboolean VertexProgramEnabled;
127 struct gl_vertex_program *VertexProgram;
128 GLboolean FragmentProgramEnabled;
129 struct gl_fragment_program *FragmentProgram;
130 struct gl_shader_program *VertexShader;
131 struct gl_shader_program *GeometryShader;
132 struct gl_shader_program *FragmentShader;
133 struct gl_shader_program *ActiveShader;
134
135 /** MESA_META_STENCIL_TEST */
136 struct gl_stencil_attrib Stencil;
137
138 /** MESA_META_TRANSFORM */
139 GLenum MatrixMode;
140 GLfloat ModelviewMatrix[16];
141 GLfloat ProjectionMatrix[16];
142 GLfloat TextureMatrix[16];
143
144 /** MESA_META_CLIP */
145 GLbitfield ClipPlanesEnabled;
146
147 /** MESA_META_TEXTURE */
148 GLuint ActiveUnit;
149 GLuint ClientActiveUnit;
150 /** for unit[0] only */
151 struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
152 /** mask of TEXTURE_2D_BIT, etc */
153 GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
154 GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
155 GLuint EnvMode; /* unit[0] only */
156
157 /** MESA_META_VERTEX */
158 struct gl_array_object *ArrayObj;
159 struct gl_buffer_object *ArrayBufferObj;
160
161 /** MESA_META_VIEWPORT */
162 GLint ViewportX, ViewportY, ViewportW, ViewportH;
163 GLclampd DepthNear, DepthFar;
164
165 /** MESA_META_CLAMP_FRAGMENT_COLOR */
166 GLenum ClampFragmentColor;
167
168 /** MESA_META_CLAMP_VERTEX_COLOR */
169 GLenum ClampVertexColor;
170
171 /** MESA_META_CONDITIONAL_RENDER */
172 struct gl_query_object *CondRenderQuery;
173 GLenum CondRenderMode;
174
175 /** Miscellaneous (always disabled) */
176 GLboolean Lighting;
177 };
178
179
180 /**
181 * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
182 * This is currently shared by all the meta ops. But we could create a
183 * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
184 */
185 struct temp_texture
186 {
187 GLuint TexObj;
188 GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */
189 GLsizei MinSize; /**< Min texture size to allocate */
190 GLsizei MaxSize; /**< Max possible texture size */
191 GLboolean NPOT; /**< Non-power of two size OK? */
192 GLsizei Width, Height; /**< Current texture size */
193 GLenum IntFormat;
194 GLfloat Sright, Ttop; /**< right, top texcoords */
195 };
196
197
198 /**
199 * State for glBlitFramebufer()
200 */
201 struct blit_state
202 {
203 GLuint ArrayObj;
204 GLuint VBO;
205 GLuint DepthFP;
206 };
207
208
209 /**
210 * State for glClear()
211 */
212 struct clear_state
213 {
214 GLuint ArrayObj;
215 GLuint VBO;
216 GLuint ShaderProg;
217 GLint ColorLocation;
218 };
219
220
221 /**
222 * State for glCopyPixels()
223 */
224 struct copypix_state
225 {
226 GLuint ArrayObj;
227 GLuint VBO;
228 };
229
230
231 /**
232 * State for glDrawPixels()
233 */
234 struct drawpix_state
235 {
236 GLuint ArrayObj;
237
238 GLuint StencilFP; /**< Fragment program for drawing stencil images */
239 GLuint DepthFP; /**< Fragment program for drawing depth images */
240 };
241
242
243 /**
244 * State for glBitmap()
245 */
246 struct bitmap_state
247 {
248 GLuint ArrayObj;
249 GLuint VBO;
250 struct temp_texture Tex; /**< separate texture from other meta ops */
251 };
252
253
254 /**
255 * State for _mesa_meta_generate_mipmap()
256 */
257 struct gen_mipmap_state
258 {
259 GLuint ArrayObj;
260 GLuint VBO;
261 GLuint FBO;
262 };
263
264
265 /**
266 * State for texture decompression
267 */
268 struct decompress_state
269 {
270 GLuint ArrayObj;
271 GLuint VBO, FBO, RBO;
272 GLint Width, Height;
273 };
274
275
276 #define MAX_META_OPS_DEPTH 2
277 /**
278 * All per-context meta state.
279 */
280 struct gl_meta_state
281 {
282 /** Stack of state saved during meta-ops */
283 struct save_state Save[MAX_META_OPS_DEPTH];
284 /** Save stack depth */
285 GLuint SaveStackDepth;
286
287 struct temp_texture TempTex;
288
289 struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */
290 struct clear_state Clear; /**< For _mesa_meta_Clear() */
291 struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */
292 struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */
293 struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */
294 struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */
295 struct decompress_state Decompress; /**< For texture decompression */
296 };
297
298
299 /**
300 * Initialize meta-ops for a context.
301 * To be called once during context creation.
302 */
303 void
304 _mesa_meta_init(struct gl_context *ctx)
305 {
306 ASSERT(!ctx->Meta);
307
308 ctx->Meta = CALLOC_STRUCT(gl_meta_state);
309 }
310
311
312 /**
313 * Free context meta-op state.
314 * To be called once during context destruction.
315 */
316 void
317 _mesa_meta_free(struct gl_context *ctx)
318 {
319 /* Note: Any textures, VBOs, etc, that we allocate should get
320 * freed by the normal context destruction code. But this would be
321 * the place to free other meta data someday.
322 */
323 free(ctx->Meta);
324 ctx->Meta = NULL;
325 }
326
327
328 /**
329 * Enter meta state. This is like a light-weight version of glPushAttrib
330 * but it also resets most GL state back to default values.
331 *
332 * \param state bitmask of MESA_META_* flags indicating which attribute groups
333 * to save and reset to their defaults
334 */
335 void
336 _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
337 {
338 struct save_state *save;
339
340 /* hope MAX_META_OPS_DEPTH is large enough */
341 assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH);
342
343 save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++];
344 memset(save, 0, sizeof(*save));
345 save->SavedState = state;
346
347 if (state & MESA_META_ALPHA_TEST) {
348 save->AlphaEnabled = ctx->Color.AlphaEnabled;
349 save->AlphaFunc = ctx->Color.AlphaFunc;
350 save->AlphaRef = ctx->Color.AlphaRef;
351 if (ctx->Color.AlphaEnabled)
352 _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE);
353 }
354
355 if (state & MESA_META_BLEND) {
356 save->BlendEnabled = ctx->Color.BlendEnabled;
357 if (ctx->Color.BlendEnabled) {
358 if (ctx->Extensions.EXT_draw_buffers2) {
359 GLuint i;
360 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
361 _mesa_set_enablei(ctx, GL_BLEND, i, GL_FALSE);
362 }
363 }
364 else {
365 _mesa_set_enable(ctx, GL_BLEND, GL_FALSE);
366 }
367 }
368 save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
369 if (ctx->Color.ColorLogicOpEnabled)
370 _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
371 }
372
373 if (state & MESA_META_COLOR_MASK) {
374 memcpy(save->ColorMask, ctx->Color.ColorMask,
375 sizeof(ctx->Color.ColorMask));
376 if (!ctx->Color.ColorMask[0][0] ||
377 !ctx->Color.ColorMask[0][1] ||
378 !ctx->Color.ColorMask[0][2] ||
379 !ctx->Color.ColorMask[0][3])
380 _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
381 }
382
383 if (state & MESA_META_DEPTH_TEST) {
384 save->Depth = ctx->Depth; /* struct copy */
385 if (ctx->Depth.Test)
386 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
387 }
388
389 if (state & MESA_META_FOG) {
390 save->Fog = ctx->Fog.Enabled;
391 if (ctx->Fog.Enabled)
392 _mesa_set_enable(ctx, GL_FOG, GL_FALSE);
393 }
394
395 if (state & MESA_META_PIXEL_STORE) {
396 save->Pack = ctx->Pack;
397 save->Unpack = ctx->Unpack;
398 ctx->Pack = ctx->DefaultPacking;
399 ctx->Unpack = ctx->DefaultPacking;
400 }
401
402 if (state & MESA_META_PIXEL_TRANSFER) {
403 save->RedScale = ctx->Pixel.RedScale;
404 save->RedBias = ctx->Pixel.RedBias;
405 save->GreenScale = ctx->Pixel.GreenScale;
406 save->GreenBias = ctx->Pixel.GreenBias;
407 save->BlueScale = ctx->Pixel.BlueScale;
408 save->BlueBias = ctx->Pixel.BlueBias;
409 save->AlphaScale = ctx->Pixel.AlphaScale;
410 save->AlphaBias = ctx->Pixel.AlphaBias;
411 save->MapColorFlag = ctx->Pixel.MapColorFlag;
412 ctx->Pixel.RedScale = 1.0F;
413 ctx->Pixel.RedBias = 0.0F;
414 ctx->Pixel.GreenScale = 1.0F;
415 ctx->Pixel.GreenBias = 0.0F;
416 ctx->Pixel.BlueScale = 1.0F;
417 ctx->Pixel.BlueBias = 0.0F;
418 ctx->Pixel.AlphaScale = 1.0F;
419 ctx->Pixel.AlphaBias = 0.0F;
420 ctx->Pixel.MapColorFlag = GL_FALSE;
421 /* XXX more state */
422 ctx->NewState |=_NEW_PIXEL;
423 }
424
425 if (state & MESA_META_RASTERIZATION) {
426 save->FrontPolygonMode = ctx->Polygon.FrontMode;
427 save->BackPolygonMode = ctx->Polygon.BackMode;
428 save->PolygonOffset = ctx->Polygon.OffsetFill;
429 save->PolygonSmooth = ctx->Polygon.SmoothFlag;
430 save->PolygonStipple = ctx->Polygon.StippleFlag;
431 save->PolygonCull = ctx->Polygon.CullFlag;
432 _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
433 _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
434 _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
435 _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
436 _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
437 }
438
439 if (state & MESA_META_SCISSOR) {
440 save->Scissor = ctx->Scissor; /* struct copy */
441 _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE);
442 }
443
444 if (state & MESA_META_SHADER) {
445 if (ctx->Extensions.ARB_vertex_program) {
446 save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
447 _mesa_reference_vertprog(ctx, &save->VertexProgram,
448 ctx->VertexProgram.Current);
449 _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
450 }
451
452 if (ctx->Extensions.ARB_fragment_program) {
453 save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
454 _mesa_reference_fragprog(ctx, &save->FragmentProgram,
455 ctx->FragmentProgram.Current);
456 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
457 }
458
459 if (ctx->Extensions.ARB_shader_objects) {
460 _mesa_reference_shader_program(ctx, &save->VertexShader,
461 ctx->Shader.CurrentVertexProgram);
462 _mesa_reference_shader_program(ctx, &save->GeometryShader,
463 ctx->Shader.CurrentGeometryProgram);
464 _mesa_reference_shader_program(ctx, &save->FragmentShader,
465 ctx->Shader.CurrentFragmentProgram);
466 _mesa_reference_shader_program(ctx, &save->ActiveShader,
467 ctx->Shader.ActiveProgram);
468
469 _mesa_UseProgramObjectARB(0);
470 }
471 }
472
473 if (state & MESA_META_STENCIL_TEST) {
474 save->Stencil = ctx->Stencil; /* struct copy */
475 if (ctx->Stencil.Enabled)
476 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);
477 /* NOTE: other stencil state not reset */
478 }
479
480 if (state & MESA_META_TEXTURE) {
481 GLuint u, tgt;
482
483 save->ActiveUnit = ctx->Texture.CurrentUnit;
484 save->ClientActiveUnit = ctx->Array.ActiveTexture;
485 save->EnvMode = ctx->Texture.Unit[0].EnvMode;
486
487 /* Disable all texture units */
488 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
489 save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
490 save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
491 if (ctx->Texture.Unit[u].Enabled ||
492 ctx->Texture.Unit[u].TexGenEnabled) {
493 _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
494 _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
495 _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
496 _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
497 if (ctx->Extensions.ARB_texture_cube_map)
498 _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
499 if (ctx->Extensions.NV_texture_rectangle)
500 _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
501 _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
502 _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
503 _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
504 _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
505 }
506 }
507
508 /* save current texture objects for unit[0] only */
509 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
510 _mesa_reference_texobj(&save->CurrentTexture[tgt],
511 ctx->Texture.Unit[0].CurrentTex[tgt]);
512 }
513
514 /* set defaults for unit[0] */
515 _mesa_ActiveTextureARB(GL_TEXTURE0);
516 _mesa_ClientActiveTextureARB(GL_TEXTURE0);
517 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
518 }
519
520 if (state & MESA_META_TRANSFORM) {
521 GLuint activeTexture = ctx->Texture.CurrentUnit;
522 memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
523 16 * sizeof(GLfloat));
524 memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
525 16 * sizeof(GLfloat));
526 memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m,
527 16 * sizeof(GLfloat));
528 save->MatrixMode = ctx->Transform.MatrixMode;
529 /* set 1:1 vertex:pixel coordinate transform */
530 _mesa_ActiveTextureARB(GL_TEXTURE0);
531 _mesa_MatrixMode(GL_TEXTURE);
532 _mesa_LoadIdentity();
533 _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
534 _mesa_MatrixMode(GL_MODELVIEW);
535 _mesa_LoadIdentity();
536 _mesa_MatrixMode(GL_PROJECTION);
537 _mesa_LoadIdentity();
538 _mesa_Ortho(0.0, ctx->DrawBuffer->Width,
539 0.0, ctx->DrawBuffer->Height,
540 -1.0, 1.0);
541 }
542
543 if (state & MESA_META_CLIP) {
544 save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
545 if (ctx->Transform.ClipPlanesEnabled) {
546 GLuint i;
547 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
548 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
549 }
550 }
551 }
552
553 if (state & MESA_META_VERTEX) {
554 /* save vertex array object state */
555 _mesa_reference_array_object(ctx, &save->ArrayObj,
556 ctx->Array.ArrayObj);
557 _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
558 ctx->Array.ArrayBufferObj);
559 /* set some default state? */
560 }
561
562 if (state & MESA_META_VIEWPORT) {
563 /* save viewport state */
564 save->ViewportX = ctx->Viewport.X;
565 save->ViewportY = ctx->Viewport.Y;
566 save->ViewportW = ctx->Viewport.Width;
567 save->ViewportH = ctx->Viewport.Height;
568 /* set viewport to match window size */
569 if (ctx->Viewport.X != 0 ||
570 ctx->Viewport.Y != 0 ||
571 ctx->Viewport.Width != ctx->DrawBuffer->Width ||
572 ctx->Viewport.Height != ctx->DrawBuffer->Height) {
573 _mesa_set_viewport(ctx, 0, 0,
574 ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
575 }
576 /* save depth range state */
577 save->DepthNear = ctx->Viewport.Near;
578 save->DepthFar = ctx->Viewport.Far;
579 /* set depth range to default */
580 _mesa_DepthRange(0.0, 1.0);
581 }
582
583 if (state & MESA_META_CLAMP_FRAGMENT_COLOR) {
584 save->ClampFragmentColor = ctx->Color.ClampFragmentColor;
585
586 /* Generally in here we want to do clamping according to whether
587 * it's for the pixel path (ClampFragmentColor is GL_TRUE),
588 * regardless of the internal implementation of the metaops.
589 */
590 if (ctx->Color.ClampFragmentColor != GL_TRUE)
591 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
592 }
593
594 if (state & MESA_META_CLAMP_VERTEX_COLOR) {
595 save->ClampVertexColor = ctx->Light.ClampVertexColor;
596
597 /* Generally in here we never want vertex color clamping --
598 * result clamping is only dependent on fragment clamping.
599 */
600 _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR, GL_FALSE);
601 }
602
603 if (state & MESA_META_CONDITIONAL_RENDER) {
604 save->CondRenderQuery = ctx->Query.CondRenderQuery;
605 save->CondRenderMode = ctx->Query.CondRenderMode;
606
607 if (ctx->Query.CondRenderQuery)
608 _mesa_EndConditionalRender();
609 }
610
611 /* misc */
612 {
613 save->Lighting = ctx->Light.Enabled;
614 if (ctx->Light.Enabled)
615 _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
616 }
617 }
618
619
620 /**
621 * Leave meta state. This is like a light-weight version of glPopAttrib().
622 */
623 void
624 _mesa_meta_end(struct gl_context *ctx)
625 {
626 struct save_state *save = &ctx->Meta->Save[--ctx->Meta->SaveStackDepth];
627 const GLbitfield state = save->SavedState;
628
629 if (state & MESA_META_ALPHA_TEST) {
630 if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
631 _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
632 _mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef);
633 }
634
635 if (state & MESA_META_BLEND) {
636 if (ctx->Color.BlendEnabled != save->BlendEnabled) {
637 if (ctx->Extensions.EXT_draw_buffers2) {
638 GLuint i;
639 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
640 _mesa_set_enablei(ctx, GL_BLEND, i, (save->BlendEnabled >> i) & 1);
641 }
642 }
643 else {
644 _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1));
645 }
646 }
647 if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
648 _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
649 }
650
651 if (state & MESA_META_COLOR_MASK) {
652 GLuint i;
653 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
654 if (!TEST_EQ_4V(ctx->Color.ColorMask[i], save->ColorMask[i])) {
655 if (i == 0) {
656 _mesa_ColorMask(save->ColorMask[i][0], save->ColorMask[i][1],
657 save->ColorMask[i][2], save->ColorMask[i][3]);
658 }
659 else {
660 _mesa_ColorMaskIndexed(i,
661 save->ColorMask[i][0],
662 save->ColorMask[i][1],
663 save->ColorMask[i][2],
664 save->ColorMask[i][3]);
665 }
666 }
667 }
668 }
669
670 if (state & MESA_META_DEPTH_TEST) {
671 if (ctx->Depth.Test != save->Depth.Test)
672 _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
673 _mesa_DepthFunc(save->Depth.Func);
674 _mesa_DepthMask(save->Depth.Mask);
675 }
676
677 if (state & MESA_META_FOG) {
678 _mesa_set_enable(ctx, GL_FOG, save->Fog);
679 }
680
681 if (state & MESA_META_PIXEL_STORE) {
682 ctx->Pack = save->Pack;
683 ctx->Unpack = save->Unpack;
684 }
685
686 if (state & MESA_META_PIXEL_TRANSFER) {
687 ctx->Pixel.RedScale = save->RedScale;
688 ctx->Pixel.RedBias = save->RedBias;
689 ctx->Pixel.GreenScale = save->GreenScale;
690 ctx->Pixel.GreenBias = save->GreenBias;
691 ctx->Pixel.BlueScale = save->BlueScale;
692 ctx->Pixel.BlueBias = save->BlueBias;
693 ctx->Pixel.AlphaScale = save->AlphaScale;
694 ctx->Pixel.AlphaBias = save->AlphaBias;
695 ctx->Pixel.MapColorFlag = save->MapColorFlag;
696 /* XXX more state */
697 ctx->NewState |=_NEW_PIXEL;
698 }
699
700 if (state & MESA_META_RASTERIZATION) {
701 _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
702 _mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
703 _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
704 _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
705 _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
706 _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
707 }
708
709 if (state & MESA_META_SCISSOR) {
710 _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
711 _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
712 save->Scissor.Width, save->Scissor.Height);
713 }
714
715 if (state & MESA_META_SHADER) {
716 if (ctx->Extensions.ARB_vertex_program) {
717 _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
718 save->VertexProgramEnabled);
719 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
720 save->VertexProgram);
721 _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL);
722 }
723
724 if (ctx->Extensions.ARB_fragment_program) {
725 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
726 save->FragmentProgramEnabled);
727 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
728 save->FragmentProgram);
729 _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL);
730 }
731
732 if (ctx->Extensions.ARB_vertex_shader)
733 _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader);
734
735 if (ctx->Extensions.ARB_geometry_shader4)
736 _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
737 save->GeometryShader);
738
739 if (ctx->Extensions.ARB_fragment_shader)
740 _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER,
741 save->FragmentShader);
742
743 _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
744 save->ActiveShader);
745
746 _mesa_reference_shader_program(ctx, &save->VertexShader, NULL);
747 _mesa_reference_shader_program(ctx, &save->GeometryShader, NULL);
748 _mesa_reference_shader_program(ctx, &save->FragmentShader, NULL);
749 _mesa_reference_shader_program(ctx, &save->ActiveShader, NULL);
750 }
751
752 if (state & MESA_META_STENCIL_TEST) {
753 const struct gl_stencil_attrib *stencil = &save->Stencil;
754
755 _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
756 _mesa_ClearStencil(stencil->Clear);
757 if (ctx->Extensions.EXT_stencil_two_side) {
758 _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
759 stencil->TestTwoSide);
760 _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
761 ? GL_BACK : GL_FRONT);
762 }
763 /* front state */
764 _mesa_StencilFuncSeparate(GL_FRONT,
765 stencil->Function[0],
766 stencil->Ref[0],
767 stencil->ValueMask[0]);
768 _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
769 _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
770 stencil->ZFailFunc[0],
771 stencil->ZPassFunc[0]);
772 /* back state */
773 _mesa_StencilFuncSeparate(GL_BACK,
774 stencil->Function[1],
775 stencil->Ref[1],
776 stencil->ValueMask[1]);
777 _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
778 _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
779 stencil->ZFailFunc[1],
780 stencil->ZPassFunc[1]);
781 }
782
783 if (state & MESA_META_TEXTURE) {
784 GLuint u, tgt;
785
786 ASSERT(ctx->Texture.CurrentUnit == 0);
787
788 /* restore texenv for unit[0] */
789 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
790
791 /* restore texture objects for unit[0] only */
792 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
793 _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
794 save->CurrentTexture[tgt]);
795 _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
796 }
797
798 /* Re-enable textures, texgen */
799 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
800 if (save->TexEnabled[u]) {
801 _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
802
803 if (save->TexEnabled[u] & TEXTURE_1D_BIT)
804 _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_TRUE);
805 if (save->TexEnabled[u] & TEXTURE_2D_BIT)
806 _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_TRUE);
807 if (save->TexEnabled[u] & TEXTURE_3D_BIT)
808 _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_TRUE);
809 if (save->TexEnabled[u] & TEXTURE_CUBE_BIT)
810 _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_TRUE);
811 if (save->TexEnabled[u] & TEXTURE_RECT_BIT)
812 _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_TRUE);
813 }
814
815 if (save->TexGenEnabled[u]) {
816 _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
817
818 if (save->TexGenEnabled[u] & S_BIT)
819 _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_TRUE);
820 if (save->TexGenEnabled[u] & T_BIT)
821 _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_TRUE);
822 if (save->TexGenEnabled[u] & R_BIT)
823 _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_TRUE);
824 if (save->TexGenEnabled[u] & Q_BIT)
825 _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
826 }
827 }
828
829 /* restore current unit state */
830 _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit);
831 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit);
832 }
833
834 if (state & MESA_META_TRANSFORM) {
835 GLuint activeTexture = ctx->Texture.CurrentUnit;
836 _mesa_ActiveTextureARB(GL_TEXTURE0);
837 _mesa_MatrixMode(GL_TEXTURE);
838 _mesa_LoadMatrixf(save->TextureMatrix);
839 _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
840
841 _mesa_MatrixMode(GL_MODELVIEW);
842 _mesa_LoadMatrixf(save->ModelviewMatrix);
843
844 _mesa_MatrixMode(GL_PROJECTION);
845 _mesa_LoadMatrixf(save->ProjectionMatrix);
846
847 _mesa_MatrixMode(save->MatrixMode);
848 }
849
850 if (state & MESA_META_CLIP) {
851 if (save->ClipPlanesEnabled) {
852 GLuint i;
853 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
854 if (save->ClipPlanesEnabled & (1 << i)) {
855 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
856 }
857 }
858 }
859 }
860
861 if (state & MESA_META_VERTEX) {
862 /* restore vertex buffer object */
863 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
864 _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
865
866 /* restore vertex array object */
867 _mesa_BindVertexArray(save->ArrayObj->Name);
868 _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
869 }
870
871 if (state & MESA_META_VIEWPORT) {
872 if (save->ViewportX != ctx->Viewport.X ||
873 save->ViewportY != ctx->Viewport.Y ||
874 save->ViewportW != ctx->Viewport.Width ||
875 save->ViewportH != ctx->Viewport.Height) {
876 _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
877 save->ViewportW, save->ViewportH);
878 }
879 _mesa_DepthRange(save->DepthNear, save->DepthFar);
880 }
881
882 if (state & MESA_META_CLAMP_FRAGMENT_COLOR) {
883 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, save->ClampFragmentColor);
884 }
885
886 if (state & MESA_META_CLAMP_VERTEX_COLOR) {
887 _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR, save->ClampVertexColor);
888 }
889
890 if (state & MESA_META_CONDITIONAL_RENDER) {
891 if (save->CondRenderQuery)
892 _mesa_BeginConditionalRender(save->CondRenderQuery->Id,
893 save->CondRenderMode);
894 }
895
896 /* misc */
897 if (save->Lighting) {
898 _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
899 }
900 }
901
902
903 /**
904 * Convert Z from a normalized value in the range [0, 1] to an object-space
905 * Z coordinate in [-1, +1] so that drawing at the new Z position with the
906 * default/identity ortho projection results in the original Z value.
907 * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z
908 * value comes from the clear value or raster position.
909 */
910 static INLINE GLfloat
911 invert_z(GLfloat normZ)
912 {
913 GLfloat objZ = 1.0 - 2.0 * normZ;
914 return objZ;
915 }
916
917
918 /**
919 * One-time init for a temp_texture object.
920 * Choose tex target, compute max tex size, etc.
921 */
922 static void
923 init_temp_texture(struct gl_context *ctx, struct temp_texture *tex)
924 {
925 /* prefer texture rectangle */
926 if (ctx->Extensions.NV_texture_rectangle) {
927 tex->Target = GL_TEXTURE_RECTANGLE;
928 tex->MaxSize = ctx->Const.MaxTextureRectSize;
929 tex->NPOT = GL_TRUE;
930 }
931 else {
932 /* use 2D texture, NPOT if possible */
933 tex->Target = GL_TEXTURE_2D;
934 tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
935 tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two;
936 }
937 tex->MinSize = 16; /* 16 x 16 at least */
938 assert(tex->MaxSize > 0);
939
940 _mesa_GenTextures(1, &tex->TexObj);
941 }
942
943
944 /**
945 * Return pointer to temp_texture info for non-bitmap ops.
946 * This does some one-time init if needed.
947 */
948 static struct temp_texture *
949 get_temp_texture(struct gl_context *ctx)
950 {
951 struct temp_texture *tex = &ctx->Meta->TempTex;
952
953 if (!tex->TexObj) {
954 init_temp_texture(ctx, tex);
955 }
956
957 return tex;
958 }
959
960
961 /**
962 * Return pointer to temp_texture info for _mesa_meta_bitmap().
963 * We use a separate texture for bitmaps to reduce texture
964 * allocation/deallocation.
965 */
966 static struct temp_texture *
967 get_bitmap_temp_texture(struct gl_context *ctx)
968 {
969 struct temp_texture *tex = &ctx->Meta->Bitmap.Tex;
970
971 if (!tex->TexObj) {
972 init_temp_texture(ctx, tex);
973 }
974
975 return tex;
976 }
977
978
979 /**
980 * Compute the width/height of texture needed to draw an image of the
981 * given size. Return a flag indicating whether the current texture
982 * can be re-used (glTexSubImage2D) or if a new texture needs to be
983 * allocated (glTexImage2D).
984 * Also, compute s/t texcoords for drawing.
985 *
986 * \return GL_TRUE if new texture is needed, GL_FALSE otherwise
987 */
988 static GLboolean
989 alloc_texture(struct temp_texture *tex,
990 GLsizei width, GLsizei height, GLenum intFormat)
991 {
992 GLboolean newTex = GL_FALSE;
993
994 ASSERT(width <= tex->MaxSize);
995 ASSERT(height <= tex->MaxSize);
996
997 if (width > tex->Width ||
998 height > tex->Height ||
999 intFormat != tex->IntFormat) {
1000 /* alloc new texture (larger or different format) */
1001
1002 if (tex->NPOT) {
1003 /* use non-power of two size */
1004 tex->Width = MAX2(tex->MinSize, width);
1005 tex->Height = MAX2(tex->MinSize, height);
1006 }
1007 else {
1008 /* find power of two size */
1009 GLsizei w, h;
1010 w = h = tex->MinSize;
1011 while (w < width)
1012 w *= 2;
1013 while (h < height)
1014 h *= 2;
1015 tex->Width = w;
1016 tex->Height = h;
1017 }
1018
1019 tex->IntFormat = intFormat;
1020
1021 newTex = GL_TRUE;
1022 }
1023
1024 /* compute texcoords */
1025 if (tex->Target == GL_TEXTURE_RECTANGLE) {
1026 tex->Sright = (GLfloat) width;
1027 tex->Ttop = (GLfloat) height;
1028 }
1029 else {
1030 tex->Sright = (GLfloat) width / tex->Width;
1031 tex->Ttop = (GLfloat) height / tex->Height;
1032 }
1033
1034 return newTex;
1035 }
1036
1037
1038 /**
1039 * Setup/load texture for glCopyPixels or glBlitFramebuffer.
1040 */
1041 static void
1042 setup_copypix_texture(struct temp_texture *tex,
1043 GLboolean newTex,
1044 GLint srcX, GLint srcY,
1045 GLsizei width, GLsizei height, GLenum intFormat,
1046 GLenum filter)
1047 {
1048 _mesa_BindTexture(tex->Target, tex->TexObj);
1049 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter);
1050 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter);
1051 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1052
1053 /* copy framebuffer image to texture */
1054 if (newTex) {
1055 /* create new tex image */
1056 if (tex->Width == width && tex->Height == height) {
1057 /* create new tex with framebuffer data */
1058 _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat,
1059 srcX, srcY, width, height, 0);
1060 }
1061 else {
1062 /* create empty texture */
1063 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
1064 tex->Width, tex->Height, 0,
1065 intFormat, GL_UNSIGNED_BYTE, NULL);
1066 /* load image */
1067 _mesa_CopyTexSubImage2D(tex->Target, 0,
1068 0, 0, srcX, srcY, width, height);
1069 }
1070 }
1071 else {
1072 /* replace existing tex image */
1073 _mesa_CopyTexSubImage2D(tex->Target, 0,
1074 0, 0, srcX, srcY, width, height);
1075 }
1076 }
1077
1078
1079 /**
1080 * Setup/load texture for glDrawPixels.
1081 */
1082 static void
1083 setup_drawpix_texture(struct gl_context *ctx,
1084 struct temp_texture *tex,
1085 GLboolean newTex,
1086 GLenum texIntFormat,
1087 GLsizei width, GLsizei height,
1088 GLenum format, GLenum type,
1089 const GLvoid *pixels)
1090 {
1091 _mesa_BindTexture(tex->Target, tex->TexObj);
1092 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1093 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1094 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1095
1096 /* copy pixel data to texture */
1097 if (newTex) {
1098 /* create new tex image */
1099 if (tex->Width == width && tex->Height == height) {
1100 /* create new tex and load image data */
1101 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
1102 tex->Width, tex->Height, 0, format, type, pixels);
1103 }
1104 else {
1105 struct gl_buffer_object *save_unpack_obj = NULL;
1106
1107 _mesa_reference_buffer_object(ctx, &save_unpack_obj,
1108 ctx->Unpack.BufferObj);
1109 _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
1110 /* create empty texture */
1111 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
1112 tex->Width, tex->Height, 0, format, type, NULL);
1113 if (save_unpack_obj != NULL)
1114 _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB,
1115 save_unpack_obj->Name);
1116 /* load image */
1117 _mesa_TexSubImage2D(tex->Target, 0,
1118 0, 0, width, height, format, type, pixels);
1119 }
1120 }
1121 else {
1122 /* replace existing tex image */
1123 _mesa_TexSubImage2D(tex->Target, 0,
1124 0, 0, width, height, format, type, pixels);
1125 }
1126 }
1127
1128
1129
1130 /**
1131 * One-time init for drawing depth pixels.
1132 */
1133 static void
1134 init_blit_depth_pixels(struct gl_context *ctx)
1135 {
1136 static const char *program =
1137 "!!ARBfp1.0\n"
1138 "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
1139 "END \n";
1140 char program2[200];
1141 struct blit_state *blit = &ctx->Meta->Blit;
1142 struct temp_texture *tex = get_temp_texture(ctx);
1143 const char *texTarget;
1144
1145 assert(blit->DepthFP == 0);
1146
1147 /* replace %s with "RECT" or "2D" */
1148 assert(strlen(program) + 4 < sizeof(program2));
1149 if (tex->Target == GL_TEXTURE_RECTANGLE)
1150 texTarget = "RECT";
1151 else
1152 texTarget = "2D";
1153 _mesa_snprintf(program2, sizeof(program2), program, texTarget);
1154
1155 _mesa_GenPrograms(1, &blit->DepthFP);
1156 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
1157 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1158 strlen(program2), (const GLubyte *) program2);
1159 }
1160
1161
1162 /**
1163 * Try to do a glBlitFramebuffer using no-copy texturing.
1164 * We can do this when the src renderbuffer is actually a texture.
1165 * But if the src buffer == dst buffer we cannot do this.
1166 *
1167 * \return new buffer mask indicating the buffers left to blit using the
1168 * normal path.
1169 */
1170 static GLbitfield
1171 blitframebuffer_texture(struct gl_context *ctx,
1172 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1173 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1174 GLbitfield mask, GLenum filter)
1175 {
1176 if (mask & GL_COLOR_BUFFER_BIT) {
1177 const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
1178 const struct gl_framebuffer *readFb = ctx->ReadBuffer;
1179 const struct gl_renderbuffer_attachment *drawAtt =
1180 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
1181 const struct gl_renderbuffer_attachment *readAtt =
1182 &readFb->Attachment[readFb->_ColorReadBufferIndex];
1183
1184 if (readAtt && readAtt->Texture) {
1185 const struct gl_texture_object *texObj = readAtt->Texture;
1186 const GLuint srcLevel = readAtt->TextureLevel;
1187 const GLenum minFilterSave = texObj->Sampler.MinFilter;
1188 const GLenum magFilterSave = texObj->Sampler.MagFilter;
1189 const GLint baseLevelSave = texObj->BaseLevel;
1190 const GLint maxLevelSave = texObj->MaxLevel;
1191 const GLenum wrapSSave = texObj->Sampler.WrapS;
1192 const GLenum wrapTSave = texObj->Sampler.WrapT;
1193 const GLenum srgbSave = texObj->Sampler.sRGBDecode;
1194 const GLenum fbo_srgb_save = ctx->Color.sRGBEnabled;
1195 const GLenum target = texObj->Target;
1196
1197 if (drawAtt->Texture == readAtt->Texture) {
1198 /* Can't use same texture as both the source and dest. We need
1199 * to handle overlapping blits and besides, some hw may not
1200 * support this.
1201 */
1202 return mask;
1203 }
1204
1205 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) {
1206 /* Can't handle other texture types at this time */
1207 return mask;
1208 }
1209
1210 /*
1211 printf("Blit from texture!\n");
1212 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
1213 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
1214 */
1215
1216 /* Prepare src texture state */
1217 _mesa_BindTexture(target, texObj->Name);
1218 _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
1219 _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
1220 if (target != GL_TEXTURE_RECTANGLE_ARB) {
1221 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
1222 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
1223 }
1224 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1225 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1226
1227 /* Always do our blits with no sRGB decode or encode.*/
1228 if (ctx->Extensions.EXT_texture_sRGB_decode) {
1229 _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT,
1230 GL_SKIP_DECODE_EXT);
1231 }
1232 if (ctx->Extensions.EXT_framebuffer_sRGB) {
1233 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE);
1234 }
1235
1236 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1237 _mesa_set_enable(ctx, target, GL_TRUE);
1238
1239 /* Prepare vertex data (the VBO was previously created and bound) */
1240 {
1241 struct vertex {
1242 GLfloat x, y, s, t;
1243 };
1244 struct vertex verts[4];
1245 GLfloat s0, t0, s1, t1;
1246
1247 if (target == GL_TEXTURE_2D) {
1248 const struct gl_texture_image *texImage
1249 = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
1250 s0 = srcX0 / (float) texImage->Width;
1251 s1 = srcX1 / (float) texImage->Width;
1252 t0 = srcY0 / (float) texImage->Height;
1253 t1 = srcY1 / (float) texImage->Height;
1254 }
1255 else {
1256 assert(target == GL_TEXTURE_RECTANGLE_ARB);
1257 s0 = srcX0;
1258 s1 = srcX1;
1259 t0 = srcY0;
1260 t1 = srcY1;
1261 }
1262
1263 verts[0].x = (GLfloat) dstX0;
1264 verts[0].y = (GLfloat) dstY0;
1265 verts[1].x = (GLfloat) dstX1;
1266 verts[1].y = (GLfloat) dstY0;
1267 verts[2].x = (GLfloat) dstX1;
1268 verts[2].y = (GLfloat) dstY1;
1269 verts[3].x = (GLfloat) dstX0;
1270 verts[3].y = (GLfloat) dstY1;
1271
1272 verts[0].s = s0;
1273 verts[0].t = t0;
1274 verts[1].s = s1;
1275 verts[1].t = t0;
1276 verts[2].s = s1;
1277 verts[2].t = t1;
1278 verts[3].s = s0;
1279 verts[3].t = t1;
1280
1281 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
1282 }
1283
1284 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1285
1286 /* Restore texture object state, the texture binding will
1287 * be restored by _mesa_meta_end().
1288 */
1289 _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
1290 _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
1291 if (target != GL_TEXTURE_RECTANGLE_ARB) {
1292 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
1293 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
1294 }
1295 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
1296 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
1297 if (ctx->Extensions.EXT_texture_sRGB_decode) {
1298 _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT, srgbSave);
1299 }
1300 if (ctx->Extensions.EXT_framebuffer_sRGB && fbo_srgb_save) {
1301 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE);
1302 }
1303
1304 /* Done with color buffer */
1305 mask &= ~GL_COLOR_BUFFER_BIT;
1306 }
1307 }
1308
1309 return mask;
1310 }
1311
1312
1313 /**
1314 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
1315 * of texture mapping and polygon rendering.
1316 */
1317 void
1318 _mesa_meta_BlitFramebuffer(struct gl_context *ctx,
1319 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1320 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1321 GLbitfield mask, GLenum filter)
1322 {
1323 struct blit_state *blit = &ctx->Meta->Blit;
1324 struct temp_texture *tex = get_temp_texture(ctx);
1325 const GLsizei maxTexSize = tex->MaxSize;
1326 const GLint srcX = MIN2(srcX0, srcX1);
1327 const GLint srcY = MIN2(srcY0, srcY1);
1328 const GLint srcW = abs(srcX1 - srcX0);
1329 const GLint srcH = abs(srcY1 - srcY0);
1330 const GLboolean srcFlipX = srcX1 < srcX0;
1331 const GLboolean srcFlipY = srcY1 < srcY0;
1332 struct vertex {
1333 GLfloat x, y, s, t;
1334 };
1335 struct vertex verts[4];
1336 GLboolean newTex;
1337
1338 if (srcW > maxTexSize || srcH > maxTexSize) {
1339 /* XXX avoid this fallback */
1340 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
1341 dstX0, dstY0, dstX1, dstY1, mask, filter);
1342 return;
1343 }
1344
1345 if (srcFlipX) {
1346 GLint tmp = dstX0;
1347 dstX0 = dstX1;
1348 dstX1 = tmp;
1349 }
1350
1351 if (srcFlipY) {
1352 GLint tmp = dstY0;
1353 dstY0 = dstY1;
1354 dstY1 = tmp;
1355 }
1356
1357 /* only scissor effects blit so save/clear all other relevant state */
1358 _mesa_meta_begin(ctx, ~MESA_META_SCISSOR);
1359
1360 if (blit->ArrayObj == 0) {
1361 /* one-time setup */
1362
1363 /* create vertex array object */
1364 _mesa_GenVertexArrays(1, &blit->ArrayObj);
1365 _mesa_BindVertexArray(blit->ArrayObj);
1366
1367 /* create vertex array buffer */
1368 _mesa_GenBuffersARB(1, &blit->VBO);
1369 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
1370 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
1371 NULL, GL_DYNAMIC_DRAW_ARB);
1372
1373 /* setup vertex arrays */
1374 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
1375 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
1376 _mesa_EnableClientState(GL_VERTEX_ARRAY);
1377 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
1378 }
1379 else {
1380 _mesa_BindVertexArray(blit->ArrayObj);
1381 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
1382 }
1383
1384 /* Try faster, direct texture approach first */
1385 mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1,
1386 dstX0, dstY0, dstX1, dstY1, mask, filter);
1387 if (mask == 0x0) {
1388 _mesa_meta_end(ctx);
1389 return;
1390 }
1391
1392 /* Continue with "normal" approach which involves copying the src rect
1393 * into a temporary texture and is "blitted" by drawing a textured quad.
1394 */
1395
1396 newTex = alloc_texture(tex, srcW, srcH, GL_RGBA);
1397
1398 /* vertex positions/texcoords (after texture allocation!) */
1399 {
1400 verts[0].x = (GLfloat) dstX0;
1401 verts[0].y = (GLfloat) dstY0;
1402 verts[1].x = (GLfloat) dstX1;
1403 verts[1].y = (GLfloat) dstY0;
1404 verts[2].x = (GLfloat) dstX1;
1405 verts[2].y = (GLfloat) dstY1;
1406 verts[3].x = (GLfloat) dstX0;
1407 verts[3].y = (GLfloat) dstY1;
1408
1409 verts[0].s = 0.0F;
1410 verts[0].t = 0.0F;
1411 verts[1].s = tex->Sright;
1412 verts[1].t = 0.0F;
1413 verts[2].s = tex->Sright;
1414 verts[2].t = tex->Ttop;
1415 verts[3].s = 0.0F;
1416 verts[3].t = tex->Ttop;
1417
1418 /* upload new vertex data */
1419 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
1420 }
1421
1422 _mesa_set_enable(ctx, tex->Target, GL_TRUE);
1423
1424 if (mask & GL_COLOR_BUFFER_BIT) {
1425 setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH,
1426 GL_RGBA, filter);
1427 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1428 mask &= ~GL_COLOR_BUFFER_BIT;
1429 }
1430
1431 if (mask & GL_DEPTH_BUFFER_BIT) {
1432 GLuint *tmp = (GLuint *) malloc(srcW * srcH * sizeof(GLuint));
1433 if (tmp) {
1434 if (!blit->DepthFP)
1435 init_blit_depth_pixels(ctx);
1436
1437 /* maybe change tex format here */
1438 newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT);
1439
1440 _mesa_ReadPixels(srcX, srcY, srcW, srcH,
1441 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
1442
1443 setup_drawpix_texture(ctx, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
1444 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
1445
1446 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
1447 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
1448 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1449 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
1450 _mesa_DepthFunc(GL_ALWAYS);
1451 _mesa_DepthMask(GL_TRUE);
1452
1453 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1454 mask &= ~GL_DEPTH_BUFFER_BIT;
1455
1456 free(tmp);
1457 }
1458 }
1459
1460 if (mask & GL_STENCIL_BUFFER_BIT) {
1461 /* XXX can't easily do stencil */
1462 }
1463
1464 _mesa_set_enable(ctx, tex->Target, GL_FALSE);
1465
1466 _mesa_meta_end(ctx);
1467
1468 if (mask) {
1469 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
1470 dstX0, dstY0, dstX1, dstY1, mask, filter);
1471 }
1472 }
1473
1474
1475 /**
1476 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
1477 */
1478 void
1479 _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers)
1480 {
1481 struct clear_state *clear = &ctx->Meta->Clear;
1482 struct vertex {
1483 GLfloat x, y, z, r, g, b, a;
1484 };
1485 struct vertex verts[4];
1486 /* save all state but scissor, pixel pack/unpack */
1487 GLbitfield metaSave = (MESA_META_ALL -
1488 MESA_META_SCISSOR -
1489 MESA_META_PIXEL_STORE -
1490 MESA_META_CONDITIONAL_RENDER);
1491 const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
1492
1493 if (buffers & BUFFER_BITS_COLOR) {
1494 /* if clearing color buffers, don't save/restore colormask */
1495 metaSave -= MESA_META_COLOR_MASK;
1496 }
1497
1498 _mesa_meta_begin(ctx, metaSave);
1499
1500 if (clear->ArrayObj == 0) {
1501 /* one-time setup */
1502
1503 /* create vertex array object */
1504 _mesa_GenVertexArrays(1, &clear->ArrayObj);
1505 _mesa_BindVertexArray(clear->ArrayObj);
1506
1507 /* create vertex array buffer */
1508 _mesa_GenBuffersARB(1, &clear->VBO);
1509 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1510
1511 /* setup vertex arrays */
1512 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
1513 _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
1514 _mesa_EnableClientState(GL_VERTEX_ARRAY);
1515 _mesa_EnableClientState(GL_COLOR_ARRAY);
1516 }
1517 else {
1518 _mesa_BindVertexArray(clear->ArrayObj);
1519 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1520 }
1521
1522 /* GL_COLOR_BUFFER_BIT */
1523 if (buffers & BUFFER_BITS_COLOR) {
1524 /* leave colormask, glDrawBuffer state as-is */
1525
1526 /* Clears never have the color clamped. */
1527 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
1528 }
1529 else {
1530 ASSERT(metaSave & MESA_META_COLOR_MASK);
1531 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1532 }
1533
1534 /* GL_DEPTH_BUFFER_BIT */
1535 if (buffers & BUFFER_BIT_DEPTH) {
1536 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
1537 _mesa_DepthFunc(GL_ALWAYS);
1538 _mesa_DepthMask(GL_TRUE);
1539 }
1540 else {
1541 assert(!ctx->Depth.Test);
1542 }
1543
1544 /* GL_STENCIL_BUFFER_BIT */
1545 if (buffers & BUFFER_BIT_STENCIL) {
1546 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
1547 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
1548 GL_REPLACE, GL_REPLACE, GL_REPLACE);
1549 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
1550 ctx->Stencil.Clear & stencilMax,
1551 ctx->Stencil.WriteMask[0]);
1552 }
1553 else {
1554 assert(!ctx->Stencil.Enabled);
1555 }
1556
1557 /* vertex positions/colors */
1558 {
1559 const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
1560 const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
1561 const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
1562 const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
1563 const GLfloat z = invert_z(ctx->Depth.Clear);
1564 GLuint i;
1565
1566 verts[0].x = x0;
1567 verts[0].y = y0;
1568 verts[0].z = z;
1569 verts[1].x = x1;
1570 verts[1].y = y0;
1571 verts[1].z = z;
1572 verts[2].x = x1;
1573 verts[2].y = y1;
1574 verts[2].z = z;
1575 verts[3].x = x0;
1576 verts[3].y = y1;
1577 verts[3].z = z;
1578
1579 /* vertex colors */
1580 for (i = 0; i < 4; i++) {
1581 verts[i].r = ctx->Color.ClearColor.f[0];
1582 verts[i].g = ctx->Color.ClearColor.f[1];
1583 verts[i].b = ctx->Color.ClearColor.f[2];
1584 verts[i].a = ctx->Color.ClearColor.f[3];
1585 }
1586
1587 /* upload new vertex data */
1588 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
1589 GL_DYNAMIC_DRAW_ARB);
1590 }
1591
1592 /* draw quad */
1593 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1594
1595 _mesa_meta_end(ctx);
1596 }
1597
1598 static void
1599 meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
1600 {
1601 const char *vs_source =
1602 "attribute vec4 position;\n"
1603 "void main()\n"
1604 "{\n"
1605 " gl_Position = position;\n"
1606 "}\n";
1607 const char *fs_source =
1608 "uniform vec4 color;\n"
1609 "void main()\n"
1610 "{\n"
1611 " gl_FragColor = color;\n"
1612 "}\n";
1613 GLuint vs, fs;
1614
1615 if (clear->ArrayObj != 0)
1616 return;
1617
1618 /* create vertex array object */
1619 _mesa_GenVertexArrays(1, &clear->ArrayObj);
1620 _mesa_BindVertexArray(clear->ArrayObj);
1621
1622 /* create vertex array buffer */
1623 _mesa_GenBuffersARB(1, &clear->VBO);
1624 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1625
1626 /* setup vertex arrays */
1627 _mesa_VertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
1628 _mesa_EnableVertexAttribArrayARB(0);
1629
1630 vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER);
1631 _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL);
1632 _mesa_CompileShaderARB(vs);
1633
1634 fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER);
1635 _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL);
1636 _mesa_CompileShaderARB(fs);
1637
1638 clear->ShaderProg = _mesa_CreateProgramObjectARB();
1639 _mesa_AttachShader(clear->ShaderProg, fs);
1640 _mesa_AttachShader(clear->ShaderProg, vs);
1641 _mesa_BindAttribLocationARB(clear->ShaderProg, 0, "position");
1642 _mesa_LinkProgramARB(clear->ShaderProg);
1643
1644 clear->ColorLocation = _mesa_GetUniformLocationARB(clear->ShaderProg,
1645 "color");
1646 }
1647
1648 /**
1649 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
1650 */
1651 void
1652 _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
1653 {
1654 struct clear_state *clear = &ctx->Meta->Clear;
1655 GLbitfield metaSave;
1656 const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
1657 struct gl_framebuffer *fb = ctx->DrawBuffer;
1658 const float x0 = ((float)fb->_Xmin / fb->Width) * 2.0f - 1.0f;
1659 const float y0 = ((float)fb->_Ymin / fb->Height) * 2.0f - 1.0f;
1660 const float x1 = ((float)fb->_Xmax / fb->Width) * 2.0f - 1.0f;
1661 const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0f - 1.0f;
1662 const float z = -invert_z(ctx->Depth.Clear);
1663 struct vertex {
1664 GLfloat x, y, z;
1665 } verts[4];
1666
1667 metaSave = (MESA_META_ALPHA_TEST |
1668 MESA_META_BLEND |
1669 MESA_META_DEPTH_TEST |
1670 MESA_META_RASTERIZATION |
1671 MESA_META_SHADER |
1672 MESA_META_STENCIL_TEST |
1673 MESA_META_VERTEX |
1674 MESA_META_VIEWPORT |
1675 MESA_META_CLIP |
1676 MESA_META_CLAMP_FRAGMENT_COLOR);
1677
1678 if (!(buffers & BUFFER_BITS_COLOR)) {
1679 /* We'll use colormask to disable color writes. Otherwise,
1680 * respect color mask
1681 */
1682 metaSave |= MESA_META_COLOR_MASK;
1683 }
1684
1685 _mesa_meta_begin(ctx, metaSave);
1686
1687 meta_glsl_clear_init(ctx, clear);
1688
1689 _mesa_UseProgramObjectARB(clear->ShaderProg);
1690 _mesa_Uniform4fvARB(clear->ColorLocation, 1,
1691 ctx->Color.ClearColor.f);
1692
1693 _mesa_BindVertexArray(clear->ArrayObj);
1694 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
1695
1696 /* GL_COLOR_BUFFER_BIT */
1697 if (buffers & BUFFER_BITS_COLOR) {
1698 /* leave colormask, glDrawBuffer state as-is */
1699
1700 /* Clears never have the color clamped. */
1701 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
1702 }
1703 else {
1704 ASSERT(metaSave & MESA_META_COLOR_MASK);
1705 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1706 }
1707
1708 /* GL_DEPTH_BUFFER_BIT */
1709 if (buffers & BUFFER_BIT_DEPTH) {
1710 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
1711 _mesa_DepthFunc(GL_ALWAYS);
1712 _mesa_DepthMask(GL_TRUE);
1713 }
1714 else {
1715 assert(!ctx->Depth.Test);
1716 }
1717
1718 /* GL_STENCIL_BUFFER_BIT */
1719 if (buffers & BUFFER_BIT_STENCIL) {
1720 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
1721 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
1722 GL_REPLACE, GL_REPLACE, GL_REPLACE);
1723 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
1724 ctx->Stencil.Clear & stencilMax,
1725 ctx->Stencil.WriteMask[0]);
1726 }
1727 else {
1728 assert(!ctx->Stencil.Enabled);
1729 }
1730
1731 /* vertex positions */
1732 verts[0].x = x0;
1733 verts[0].y = y0;
1734 verts[0].z = z;
1735 verts[1].x = x1;
1736 verts[1].y = y0;
1737 verts[1].z = z;
1738 verts[2].x = x1;
1739 verts[2].y = y1;
1740 verts[2].z = z;
1741 verts[3].x = x0;
1742 verts[3].y = y1;
1743 verts[3].z = z;
1744
1745 /* upload new vertex data */
1746 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
1747 GL_DYNAMIC_DRAW_ARB);
1748
1749 /* draw quad */
1750 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1751
1752 _mesa_meta_end(ctx);
1753 }
1754
1755 /**
1756 * Meta implementation of ctx->Driver.CopyPixels() in terms
1757 * of texture mapping and polygon rendering and GLSL shaders.
1758 */
1759 void
1760 _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
1761 GLsizei width, GLsizei height,
1762 GLint dstX, GLint dstY, GLenum type)
1763 {
1764 struct copypix_state *copypix = &ctx->Meta->CopyPix;
1765 struct temp_texture *tex = get_temp_texture(ctx);
1766 struct vertex {
1767 GLfloat x, y, z, s, t;
1768 };
1769 struct vertex verts[4];
1770 GLboolean newTex;
1771 GLenum intFormat = GL_RGBA;
1772
1773 if (type != GL_COLOR ||
1774 ctx->_ImageTransferState ||
1775 ctx->Fog.Enabled ||
1776 width > tex->MaxSize ||
1777 height > tex->MaxSize) {
1778 /* XXX avoid this fallback */
1779 _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type);
1780 return;
1781 }
1782
1783 /* Most GL state applies to glCopyPixels, but a there's a few things
1784 * we need to override:
1785 */
1786 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION |
1787 MESA_META_SHADER |
1788 MESA_META_TEXTURE |
1789 MESA_META_TRANSFORM |
1790 MESA_META_CLIP |
1791 MESA_META_VERTEX |
1792 MESA_META_VIEWPORT));
1793
1794 if (copypix->ArrayObj == 0) {
1795 /* one-time setup */
1796
1797 /* create vertex array object */
1798 _mesa_GenVertexArrays(1, &copypix->ArrayObj);
1799 _mesa_BindVertexArray(copypix->ArrayObj);
1800
1801 /* create vertex array buffer */
1802 _mesa_GenBuffersARB(1, &copypix->VBO);
1803 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
1804 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
1805 NULL, GL_DYNAMIC_DRAW_ARB);
1806
1807 /* setup vertex arrays */
1808 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
1809 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
1810 _mesa_EnableClientState(GL_VERTEX_ARRAY);
1811 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
1812 }
1813 else {
1814 _mesa_BindVertexArray(copypix->ArrayObj);
1815 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
1816 }
1817
1818 newTex = alloc_texture(tex, width, height, intFormat);
1819
1820 /* vertex positions, texcoords (after texture allocation!) */
1821 {
1822 const GLfloat dstX0 = (GLfloat) dstX;
1823 const GLfloat dstY0 = (GLfloat) dstY;
1824 const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
1825 const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
1826 const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
1827
1828 verts[0].x = dstX0;
1829 verts[0].y = dstY0;
1830 verts[0].z = z;
1831 verts[0].s = 0.0F;
1832 verts[0].t = 0.0F;
1833 verts[1].x = dstX1;
1834 verts[1].y = dstY0;
1835 verts[1].z = z;
1836 verts[1].s = tex->Sright;
1837 verts[1].t = 0.0F;
1838 verts[2].x = dstX1;
1839 verts[2].y = dstY1;
1840 verts[2].z = z;
1841 verts[2].s = tex->Sright;
1842 verts[2].t = tex->Ttop;
1843 verts[3].x = dstX0;
1844 verts[3].y = dstY1;
1845 verts[3].z = z;
1846 verts[3].s = 0.0F;
1847 verts[3].t = tex->Ttop;
1848
1849 /* upload new vertex data */
1850 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
1851 }
1852
1853 /* Alloc/setup texture */
1854 setup_copypix_texture(tex, newTex, srcX, srcY, width, height,
1855 GL_RGBA, GL_NEAREST);
1856
1857 _mesa_set_enable(ctx, tex->Target, GL_TRUE);
1858
1859 /* draw textured quad */
1860 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
1861
1862 _mesa_set_enable(ctx, tex->Target, GL_FALSE);
1863
1864 _mesa_meta_end(ctx);
1865 }
1866
1867
1868
1869 /**
1870 * When the glDrawPixels() image size is greater than the max rectangle
1871 * texture size we use this function to break the glDrawPixels() image
1872 * into tiles which fit into the max texture size.
1873 */
1874 static void
1875 tiled_draw_pixels(struct gl_context *ctx,
1876 GLint tileSize,
1877 GLint x, GLint y, GLsizei width, GLsizei height,
1878 GLenum format, GLenum type,
1879 const struct gl_pixelstore_attrib *unpack,
1880 const GLvoid *pixels)
1881 {
1882 struct gl_pixelstore_attrib tileUnpack = *unpack;
1883 GLint i, j;
1884
1885 if (tileUnpack.RowLength == 0)
1886 tileUnpack.RowLength = width;
1887
1888 for (i = 0; i < width; i += tileSize) {
1889 const GLint tileWidth = MIN2(tileSize, width - i);
1890 const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX);
1891
1892 tileUnpack.SkipPixels = unpack->SkipPixels + i;
1893
1894 for (j = 0; j < height; j += tileSize) {
1895 const GLint tileHeight = MIN2(tileSize, height - j);
1896 const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY);
1897
1898 tileUnpack.SkipRows = unpack->SkipRows + j;
1899
1900 _mesa_meta_DrawPixels(ctx, tileX, tileY, tileWidth, tileHeight,
1901 format, type, &tileUnpack, pixels);
1902 }
1903 }
1904 }
1905
1906
1907 /**
1908 * One-time init for drawing stencil pixels.
1909 */
1910 static void
1911 init_draw_stencil_pixels(struct gl_context *ctx)
1912 {
1913 /* This program is run eight times, once for each stencil bit.
1914 * The stencil values to draw are found in an 8-bit alpha texture.
1915 * We read the texture/stencil value and test if bit 'b' is set.
1916 * If the bit is not set, use KIL to kill the fragment.
1917 * Finally, we use the stencil test to update the stencil buffer.
1918 *
1919 * The basic algorithm for checking if a bit is set is:
1920 * if (is_odd(value / (1 << bit)))
1921 * result is one (or non-zero).
1922 * else
1923 * result is zero.
1924 * The program parameter contains three values:
1925 * parm.x = 255 / (1 << bit)
1926 * parm.y = 0.5
1927 * parm.z = 0.0
1928 */
1929 static const char *program =
1930 "!!ARBfp1.0\n"
1931 "PARAM parm = program.local[0]; \n"
1932 "TEMP t; \n"
1933 "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */
1934 "# t = t * 255 / bit \n"
1935 "MUL t.x, t.a, parm.x; \n"
1936 "# t = (int) t \n"
1937 "FRC t.y, t.x; \n"
1938 "SUB t.x, t.x, t.y; \n"
1939 "# t = t * 0.5 \n"
1940 "MUL t.x, t.x, parm.y; \n"
1941 "# t = fract(t.x) \n"
1942 "FRC t.x, t.x; # if t.x != 0, then the bit is set \n"
1943 "# t.x = (t.x == 0 ? 1 : 0) \n"
1944 "SGE t.x, -t.x, parm.z; \n"
1945 "KIL -t.x; \n"
1946 "# for debug only \n"
1947 "#MOV result.color, t.x; \n"
1948 "END \n";
1949 char program2[1000];
1950 struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
1951 struct temp_texture *tex = get_temp_texture(ctx);
1952 const char *texTarget;
1953
1954 assert(drawpix->StencilFP == 0);
1955
1956 /* replace %s with "RECT" or "2D" */
1957 assert(strlen(program) + 4 < sizeof(program2));
1958 if (tex->Target == GL_TEXTURE_RECTANGLE)
1959 texTarget = "RECT";
1960 else
1961 texTarget = "2D";
1962 _mesa_snprintf(program2, sizeof(program2), program, texTarget);
1963
1964 _mesa_GenPrograms(1, &drawpix->StencilFP);
1965 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
1966 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1967 strlen(program2), (const GLubyte *) program2);
1968 }
1969
1970
1971 /**
1972 * One-time init for drawing depth pixels.
1973 */
1974 static void
1975 init_draw_depth_pixels(struct gl_context *ctx)
1976 {
1977 static const char *program =
1978 "!!ARBfp1.0\n"
1979 "PARAM color = program.local[0]; \n"
1980 "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
1981 "MOV result.color, color; \n"
1982 "END \n";
1983 char program2[200];
1984 struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
1985 struct temp_texture *tex = get_temp_texture(ctx);
1986 const char *texTarget;
1987
1988 assert(drawpix->DepthFP == 0);
1989
1990 /* replace %s with "RECT" or "2D" */
1991 assert(strlen(program) + 4 < sizeof(program2));
1992 if (tex->Target == GL_TEXTURE_RECTANGLE)
1993 texTarget = "RECT";
1994 else
1995 texTarget = "2D";
1996 _mesa_snprintf(program2, sizeof(program2), program, texTarget);
1997
1998 _mesa_GenPrograms(1, &drawpix->DepthFP);
1999 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
2000 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
2001 strlen(program2), (const GLubyte *) program2);
2002 }
2003
2004
2005 /**
2006 * Meta implementation of ctx->Driver.DrawPixels() in terms
2007 * of texture mapping and polygon rendering.
2008 */
2009 void
2010 _mesa_meta_DrawPixels(struct gl_context *ctx,
2011 GLint x, GLint y, GLsizei width, GLsizei height,
2012 GLenum format, GLenum type,
2013 const struct gl_pixelstore_attrib *unpack,
2014 const GLvoid *pixels)
2015 {
2016 struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
2017 struct temp_texture *tex = get_temp_texture(ctx);
2018 const struct gl_pixelstore_attrib unpackSave = ctx->Unpack;
2019 const GLuint origStencilMask = ctx->Stencil.WriteMask[0];
2020 struct vertex {
2021 GLfloat x, y, z, s, t;
2022 };
2023 struct vertex verts[4];
2024 GLenum texIntFormat;
2025 GLboolean fallback, newTex;
2026 GLbitfield metaExtraSave = 0x0;
2027 GLuint vbo;
2028
2029 /*
2030 * Determine if we can do the glDrawPixels with texture mapping.
2031 */
2032 fallback = GL_FALSE;
2033 if (ctx->_ImageTransferState ||
2034 ctx->Fog.Enabled) {
2035 fallback = GL_TRUE;
2036 }
2037
2038 if (_mesa_is_color_format(format)) {
2039 /* use more compact format when possible */
2040 /* XXX disable special case for GL_LUMINANCE for now to work around
2041 * apparent i965 driver bug (see bug #23670).
2042 */
2043 if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA)
2044 texIntFormat = format;
2045 else
2046 texIntFormat = GL_RGBA;
2047
2048 /* If we're not supposed to clamp the resulting color, then just
2049 * promote our texture to fully float. We could do better by
2050 * just going for the matching set of channels, in floating
2051 * point.
2052 */
2053 if (ctx->Color.ClampFragmentColor != GL_TRUE &&
2054 ctx->Extensions.ARB_texture_float)
2055 texIntFormat = GL_RGBA32F;
2056 }
2057 else if (_mesa_is_stencil_format(format)) {
2058 if (ctx->Extensions.ARB_fragment_program &&
2059 ctx->Pixel.IndexShift == 0 &&
2060 ctx->Pixel.IndexOffset == 0 &&
2061 type == GL_UNSIGNED_BYTE) {
2062 /* We'll store stencil as alpha. This only works for GLubyte
2063 * image data because of how incoming values are mapped to alpha
2064 * in [0,1].
2065 */
2066 texIntFormat = GL_ALPHA;
2067 metaExtraSave = (MESA_META_COLOR_MASK |
2068 MESA_META_DEPTH_TEST |
2069 MESA_META_SHADER |
2070 MESA_META_STENCIL_TEST);
2071 }
2072 else {
2073 fallback = GL_TRUE;
2074 }
2075 }
2076 else if (_mesa_is_depth_format(format)) {
2077 if (ctx->Extensions.ARB_depth_texture &&
2078 ctx->Extensions.ARB_fragment_program) {
2079 texIntFormat = GL_DEPTH_COMPONENT;
2080 metaExtraSave = (MESA_META_SHADER);
2081 }
2082 else {
2083 fallback = GL_TRUE;
2084 }
2085 }
2086 else {
2087 fallback = GL_TRUE;
2088 }
2089
2090 if (fallback) {
2091 _swrast_DrawPixels(ctx, x, y, width, height,
2092 format, type, unpack, pixels);
2093 return;
2094 }
2095
2096 /*
2097 * Check image size against max texture size, draw as tiles if needed.
2098 */
2099 if (width > tex->MaxSize || height > tex->MaxSize) {
2100 tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height,
2101 format, type, unpack, pixels);
2102 return;
2103 }
2104
2105 /* Most GL state applies to glDrawPixels (like blending, stencil, etc),
2106 * but a there's a few things we need to override:
2107 */
2108 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION |
2109 MESA_META_SHADER |
2110 MESA_META_TEXTURE |
2111 MESA_META_TRANSFORM |
2112 MESA_META_CLIP |
2113 MESA_META_VERTEX |
2114 MESA_META_VIEWPORT |
2115 MESA_META_CLAMP_FRAGMENT_COLOR |
2116 metaExtraSave));
2117
2118 newTex = alloc_texture(tex, width, height, texIntFormat);
2119
2120 /* vertex positions, texcoords (after texture allocation!) */
2121 {
2122 const GLfloat x0 = (GLfloat) x;
2123 const GLfloat y0 = (GLfloat) y;
2124 const GLfloat x1 = x + width * ctx->Pixel.ZoomX;
2125 const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
2126 const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
2127
2128 verts[0].x = x0;
2129 verts[0].y = y0;
2130 verts[0].z = z;
2131 verts[0].s = 0.0F;
2132 verts[0].t = 0.0F;
2133 verts[1].x = x1;
2134 verts[1].y = y0;
2135 verts[1].z = z;
2136 verts[1].s = tex->Sright;
2137 verts[1].t = 0.0F;
2138 verts[2].x = x1;
2139 verts[2].y = y1;
2140 verts[2].z = z;
2141 verts[2].s = tex->Sright;
2142 verts[2].t = tex->Ttop;
2143 verts[3].x = x0;
2144 verts[3].y = y1;
2145 verts[3].z = z;
2146 verts[3].s = 0.0F;
2147 verts[3].t = tex->Ttop;
2148 }
2149
2150 if (drawpix->ArrayObj == 0) {
2151 /* one-time setup: create vertex array object */
2152 _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
2153 }
2154 _mesa_BindVertexArray(drawpix->ArrayObj);
2155
2156 /* create vertex array buffer */
2157 _mesa_GenBuffersARB(1, &vbo);
2158 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
2159 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
2160 verts, GL_DYNAMIC_DRAW_ARB);
2161
2162 /* setup vertex arrays */
2163 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
2164 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
2165 _mesa_EnableClientState(GL_VERTEX_ARRAY);
2166 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
2167
2168 /* set given unpack params */
2169 ctx->Unpack = *unpack;
2170
2171 _mesa_set_enable(ctx, tex->Target, GL_TRUE);
2172
2173 if (_mesa_is_stencil_format(format)) {
2174 /* Drawing stencil */
2175 GLint bit;
2176
2177 if (!drawpix->StencilFP)
2178 init_draw_stencil_pixels(ctx);
2179
2180 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2181 GL_ALPHA, type, pixels);
2182
2183 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2184
2185 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
2186
2187 /* set all stencil bits to 0 */
2188 _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
2189 _mesa_StencilFunc(GL_ALWAYS, 0, 255);
2190 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2191
2192 /* set stencil bits to 1 where needed */
2193 _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
2194
2195 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
2196 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
2197
2198 for (bit = 0; bit < ctx->DrawBuffer->Visual.stencilBits; bit++) {
2199 const GLuint mask = 1 << bit;
2200 if (mask & origStencilMask) {
2201 _mesa_StencilFunc(GL_ALWAYS, mask, mask);
2202 _mesa_StencilMask(mask);
2203
2204 _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
2205 255.0 / mask, 0.5, 0.0, 0.0);
2206
2207 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2208 }
2209 }
2210 }
2211 else if (_mesa_is_depth_format(format)) {
2212 /* Drawing depth */
2213 if (!drawpix->DepthFP)
2214 init_draw_depth_pixels(ctx);
2215
2216 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
2217 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
2218
2219 /* polygon color = current raster color */
2220 _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
2221 ctx->Current.RasterColor);
2222
2223 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2224 format, type, pixels);
2225
2226 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2227 }
2228 else {
2229 /* Drawing RGBA */
2230 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2231 format, type, pixels);
2232 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2233 }
2234
2235 _mesa_set_enable(ctx, tex->Target, GL_FALSE);
2236
2237 _mesa_DeleteBuffersARB(1, &vbo);
2238
2239 /* restore unpack params */
2240 ctx->Unpack = unpackSave;
2241
2242 _mesa_meta_end(ctx);
2243 }
2244
2245 static GLboolean
2246 alpha_test_raster_color(struct gl_context *ctx)
2247 {
2248 GLfloat alpha = ctx->Current.RasterColor[ACOMP];
2249 GLfloat ref = ctx->Color.AlphaRef;
2250
2251 switch (ctx->Color.AlphaFunc) {
2252 case GL_NEVER:
2253 return GL_FALSE;
2254 case GL_LESS:
2255 return alpha < ref;
2256 case GL_EQUAL:
2257 return alpha == ref;
2258 case GL_LEQUAL:
2259 return alpha <= ref;
2260 case GL_GREATER:
2261 return alpha > ref;
2262 case GL_NOTEQUAL:
2263 return alpha != ref;
2264 case GL_GEQUAL:
2265 return alpha >= ref;
2266 case GL_ALWAYS:
2267 return GL_TRUE;
2268 default:
2269 assert(0);
2270 return GL_FALSE;
2271 }
2272 }
2273
2274 /**
2275 * Do glBitmap with a alpha texture quad. Use the alpha test to cull
2276 * the 'off' bits. A bitmap cache as in the gallium/mesa state
2277 * tracker would improve performance a lot.
2278 */
2279 void
2280 _mesa_meta_Bitmap(struct gl_context *ctx,
2281 GLint x, GLint y, GLsizei width, GLsizei height,
2282 const struct gl_pixelstore_attrib *unpack,
2283 const GLubyte *bitmap1)
2284 {
2285 struct bitmap_state *bitmap = &ctx->Meta->Bitmap;
2286 struct temp_texture *tex = get_bitmap_temp_texture(ctx);
2287 const GLenum texIntFormat = GL_ALPHA;
2288 const struct gl_pixelstore_attrib unpackSave = *unpack;
2289 GLubyte fg, bg;
2290 struct vertex {
2291 GLfloat x, y, z, s, t, r, g, b, a;
2292 };
2293 struct vertex verts[4];
2294 GLboolean newTex;
2295 GLubyte *bitmap8;
2296
2297 /*
2298 * Check if swrast fallback is needed.
2299 */
2300 if (ctx->_ImageTransferState ||
2301 ctx->FragmentProgram._Enabled ||
2302 ctx->Fog.Enabled ||
2303 ctx->Texture._EnabledUnits ||
2304 width > tex->MaxSize ||
2305 height > tex->MaxSize) {
2306 _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1);
2307 return;
2308 }
2309
2310 if (ctx->Color.AlphaEnabled && !alpha_test_raster_color(ctx))
2311 return;
2312
2313 /* Most GL state applies to glBitmap (like blending, stencil, etc),
2314 * but a there's a few things we need to override:
2315 */
2316 _mesa_meta_begin(ctx, (MESA_META_ALPHA_TEST |
2317 MESA_META_PIXEL_STORE |
2318 MESA_META_RASTERIZATION |
2319 MESA_META_SHADER |
2320 MESA_META_TEXTURE |
2321 MESA_META_TRANSFORM |
2322 MESA_META_CLIP |
2323 MESA_META_VERTEX |
2324 MESA_META_VIEWPORT));
2325
2326 if (bitmap->ArrayObj == 0) {
2327 /* one-time setup */
2328
2329 /* create vertex array object */
2330 _mesa_GenVertexArraysAPPLE(1, &bitmap->ArrayObj);
2331 _mesa_BindVertexArrayAPPLE(bitmap->ArrayObj);
2332
2333 /* create vertex array buffer */
2334 _mesa_GenBuffersARB(1, &bitmap->VBO);
2335 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
2336 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
2337 NULL, GL_DYNAMIC_DRAW_ARB);
2338
2339 /* setup vertex arrays */
2340 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
2341 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
2342 _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
2343 _mesa_EnableClientState(GL_VERTEX_ARRAY);
2344 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
2345 _mesa_EnableClientState(GL_COLOR_ARRAY);
2346 }
2347 else {
2348 _mesa_BindVertexArray(bitmap->ArrayObj);
2349 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
2350 }
2351
2352 newTex = alloc_texture(tex, width, height, texIntFormat);
2353
2354 /* vertex positions, texcoords, colors (after texture allocation!) */
2355 {
2356 const GLfloat x0 = (GLfloat) x;
2357 const GLfloat y0 = (GLfloat) y;
2358 const GLfloat x1 = (GLfloat) (x + width);
2359 const GLfloat y1 = (GLfloat) (y + height);
2360 const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
2361 GLuint i;
2362
2363 verts[0].x = x0;
2364 verts[0].y = y0;
2365 verts[0].z = z;
2366 verts[0].s = 0.0F;
2367 verts[0].t = 0.0F;
2368 verts[1].x = x1;
2369 verts[1].y = y0;
2370 verts[1].z = z;
2371 verts[1].s = tex->Sright;
2372 verts[1].t = 0.0F;
2373 verts[2].x = x1;
2374 verts[2].y = y1;
2375 verts[2].z = z;
2376 verts[2].s = tex->Sright;
2377 verts[2].t = tex->Ttop;
2378 verts[3].x = x0;
2379 verts[3].y = y1;
2380 verts[3].z = z;
2381 verts[3].s = 0.0F;
2382 verts[3].t = tex->Ttop;
2383
2384 for (i = 0; i < 4; i++) {
2385 verts[i].r = ctx->Current.RasterColor[0];
2386 verts[i].g = ctx->Current.RasterColor[1];
2387 verts[i].b = ctx->Current.RasterColor[2];
2388 verts[i].a = ctx->Current.RasterColor[3];
2389 }
2390
2391 /* upload new vertex data */
2392 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
2393 }
2394
2395 /* choose different foreground/background alpha values */
2396 CLAMPED_FLOAT_TO_UBYTE(fg, ctx->Current.RasterColor[ACOMP]);
2397 bg = (fg > 127 ? 0 : 255);
2398
2399 bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1);
2400 if (!bitmap1) {
2401 _mesa_meta_end(ctx);
2402 return;
2403 }
2404
2405 bitmap8 = (GLubyte *) malloc(width * height);
2406 if (bitmap8) {
2407 memset(bitmap8, bg, width * height);
2408 _mesa_expand_bitmap(width, height, &unpackSave, bitmap1,
2409 bitmap8, width, fg);
2410
2411 _mesa_set_enable(ctx, tex->Target, GL_TRUE);
2412
2413 _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE);
2414 _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg));
2415
2416 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
2417 GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8);
2418
2419 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2420
2421 _mesa_set_enable(ctx, tex->Target, GL_FALSE);
2422
2423 free(bitmap8);
2424 }
2425
2426 _mesa_unmap_pbo_source(ctx, &unpackSave);
2427
2428 _mesa_meta_end(ctx);
2429 }
2430
2431
2432 /**
2433 * Check if the call to _mesa_meta_GenerateMipmap() will require a
2434 * software fallback. The fallback path will require that the texture
2435 * images are mapped.
2436 * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
2437 */
2438 GLboolean
2439 _mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target,
2440 struct gl_texture_object *texObj)
2441 {
2442 const GLuint fboSave = ctx->DrawBuffer->Name;
2443 struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
2444 struct gl_texture_image *baseImage;
2445 GLuint srcLevel;
2446 GLenum status;
2447
2448 /* check for fallbacks */
2449 if (!ctx->Extensions.EXT_framebuffer_object ||
2450 target == GL_TEXTURE_3D ||
2451 target == GL_TEXTURE_1D_ARRAY ||
2452 target == GL_TEXTURE_2D_ARRAY) {
2453 return GL_TRUE;
2454 }
2455
2456 srcLevel = texObj->BaseLevel;
2457 baseImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
2458 if (!baseImage || _mesa_is_format_compressed(baseImage->TexFormat)) {
2459 return GL_TRUE;
2460 }
2461
2462 if (_mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB &&
2463 !ctx->Extensions.EXT_texture_sRGB_decode) {
2464 /* The texture format is sRGB but we can't turn off sRGB->linear
2465 * texture sample conversion. So we won't be able to generate the
2466 * right colors when rendering. Need to use a fallback.
2467 */
2468 return GL_TRUE;
2469 }
2470
2471 /*
2472 * Test that we can actually render in the texture's format.
2473 */
2474 if (!mipmap->FBO)
2475 _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
2476 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
2477
2478 if (target == GL_TEXTURE_1D) {
2479 _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
2480 GL_COLOR_ATTACHMENT0_EXT,
2481 target, texObj->Name, srcLevel);
2482 }
2483 #if 0
2484 /* other work is needed to enable 3D mipmap generation */
2485 else if (target == GL_TEXTURE_3D) {
2486 GLint zoffset = 0;
2487 _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
2488 GL_COLOR_ATTACHMENT0_EXT,
2489 target, texObj->Name, srcLevel, zoffset);
2490 }
2491 #endif
2492 else {
2493 /* 2D / cube */
2494 _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
2495 GL_COLOR_ATTACHMENT0_EXT,
2496 target, texObj->Name, srcLevel);
2497 }
2498
2499 status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
2500
2501 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
2502
2503 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2504 return GL_TRUE;
2505 }
2506
2507 return GL_FALSE;
2508 }
2509
2510
2511 /**
2512 * Compute the texture coordinates for the four vertices of a quad for
2513 * drawing a 2D texture image or slice of a cube/3D texture.
2514 * \param faceTarget GL_TEXTURE_1D/2D/3D or cube face name
2515 * \param slice slice of a 1D/2D array texture or 3D texture
2516 * \param width width of the texture image
2517 * \param height height of the texture image
2518 * \param coords0/1/2/3 returns the computed texcoords
2519 */
2520 static void
2521 setup_texture_coords(GLenum faceTarget,
2522 GLint slice,
2523 GLint width,
2524 GLint height,
2525 GLfloat coords0[3],
2526 GLfloat coords1[3],
2527 GLfloat coords2[3],
2528 GLfloat coords3[3])
2529 {
2530 static const GLfloat st[4][2] = {
2531 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
2532 };
2533 GLuint i;
2534 GLfloat r;
2535
2536 switch (faceTarget) {
2537 case GL_TEXTURE_1D:
2538 case GL_TEXTURE_2D:
2539 case GL_TEXTURE_3D:
2540 case GL_TEXTURE_2D_ARRAY:
2541 if (faceTarget == GL_TEXTURE_3D)
2542 r = 1.0F / slice;
2543 else if (faceTarget == GL_TEXTURE_2D_ARRAY)
2544 r = slice;
2545 else
2546 r = 0.0F;
2547 coords0[0] = 0.0F; /* s */
2548 coords0[1] = 0.0F; /* t */
2549 coords0[2] = r; /* r */
2550 coords1[0] = 1.0F;
2551 coords1[1] = 0.0F;
2552 coords1[2] = r;
2553 coords2[0] = 1.0F;
2554 coords2[1] = 1.0F;
2555 coords2[2] = r;
2556 coords3[0] = 0.0F;
2557 coords3[1] = 1.0F;
2558 coords3[2] = r;
2559 break;
2560 case GL_TEXTURE_RECTANGLE_ARB:
2561 coords0[0] = 0.0F; /* s */
2562 coords0[1] = 0.0F; /* t */
2563 coords0[2] = 0.0F; /* r */
2564 coords1[0] = width;
2565 coords1[1] = 0.0F;
2566 coords1[2] = 0.0F;
2567 coords2[0] = width;
2568 coords2[1] = height;
2569 coords2[2] = 0.0F;
2570 coords3[0] = 0.0F;
2571 coords3[1] = height;
2572 coords3[2] = 0.0F;
2573 break;
2574 case GL_TEXTURE_1D_ARRAY:
2575 coords0[0] = 0.0F; /* s */
2576 coords0[1] = slice; /* t */
2577 coords0[2] = 0.0F; /* r */
2578 coords1[0] = 1.0f;
2579 coords1[1] = slice;
2580 coords1[2] = 0.0F;
2581 coords2[0] = 1.0F;
2582 coords2[1] = slice;
2583 coords2[2] = 0.0F;
2584 coords3[0] = 0.0F;
2585 coords3[1] = slice;
2586 coords3[2] = 0.0F;
2587 break;
2588
2589 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2590 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2591 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2592 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2593 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2594 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2595 /* loop over quad verts */
2596 for (i = 0; i < 4; i++) {
2597 /* Compute sc = +/-scale and tc = +/-scale.
2598 * Not +/-1 to avoid cube face selection ambiguity near the edges,
2599 * though that can still sometimes happen with this scale factor...
2600 */
2601 const GLfloat scale = 0.9999f;
2602 const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale;
2603 const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale;
2604 GLfloat *coord;
2605
2606 switch (i) {
2607 case 0:
2608 coord = coords0;
2609 break;
2610 case 1:
2611 coord = coords1;
2612 break;
2613 case 2:
2614 coord = coords2;
2615 break;
2616 case 3:
2617 coord = coords3;
2618 break;
2619 default:
2620 assert(0);
2621 }
2622
2623 switch (faceTarget) {
2624 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2625 coord[0] = 1.0f;
2626 coord[1] = -tc;
2627 coord[2] = -sc;
2628 break;
2629 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2630 coord[0] = -1.0f;
2631 coord[1] = -tc;
2632 coord[2] = sc;
2633 break;
2634 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2635 coord[0] = sc;
2636 coord[1] = 1.0f;
2637 coord[2] = tc;
2638 break;
2639 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2640 coord[0] = sc;
2641 coord[1] = -1.0f;
2642 coord[2] = -tc;
2643 break;
2644 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2645 coord[0] = sc;
2646 coord[1] = -tc;
2647 coord[2] = 1.0f;
2648 break;
2649 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2650 coord[0] = -sc;
2651 coord[1] = -tc;
2652 coord[2] = -1.0f;
2653 break;
2654 default:
2655 assert(0);
2656 }
2657 }
2658 break;
2659 default:
2660 assert(0 && "unexpected target in meta setup_texture_coords()");
2661 }
2662 }
2663
2664
2665 /**
2666 * Called via ctx->Driver.GenerateMipmap()
2667 * Note: We don't yet support 3D textures, 1D/2D array textures or texture
2668 * borders.
2669 */
2670 void
2671 _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
2672 struct gl_texture_object *texObj)
2673 {
2674 struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
2675 struct vertex {
2676 GLfloat x, y, tex[3];
2677 };
2678 struct vertex verts[4];
2679 const GLuint baseLevel = texObj->BaseLevel;
2680 const GLuint maxLevel = texObj->MaxLevel;
2681 const GLenum minFilterSave = texObj->Sampler.MinFilter;
2682 const GLenum magFilterSave = texObj->Sampler.MagFilter;
2683 const GLint maxLevelSave = texObj->MaxLevel;
2684 const GLboolean genMipmapSave = texObj->GenerateMipmap;
2685 const GLenum wrapSSave = texObj->Sampler.WrapS;
2686 const GLenum wrapTSave = texObj->Sampler.WrapT;
2687 const GLenum wrapRSave = texObj->Sampler.WrapR;
2688 const GLenum srgbDecodeSave = texObj->Sampler.sRGBDecode;
2689 const GLenum srgbBufferSave = ctx->Color.sRGBEnabled;
2690 const GLuint fboSave = ctx->DrawBuffer->Name;
2691 const GLuint original_active_unit = ctx->Texture.CurrentUnit;
2692 GLenum faceTarget;
2693 GLuint dstLevel;
2694 const GLuint border = 0;
2695 const GLint slice = 0;
2696
2697 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
2698 _mesa_generate_mipmap(ctx, target, texObj);
2699 return;
2700 }
2701
2702 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
2703 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
2704 faceTarget = target;
2705 target = GL_TEXTURE_CUBE_MAP;
2706 }
2707 else {
2708 faceTarget = target;
2709 }
2710
2711 _mesa_meta_begin(ctx, MESA_META_ALL);
2712
2713 if (original_active_unit != 0)
2714 _mesa_BindTexture(target, texObj->Name);
2715
2716 if (mipmap->ArrayObj == 0) {
2717 /* one-time setup */
2718
2719 /* create vertex array object */
2720 _mesa_GenVertexArraysAPPLE(1, &mipmap->ArrayObj);
2721 _mesa_BindVertexArrayAPPLE(mipmap->ArrayObj);
2722
2723 /* create vertex array buffer */
2724 _mesa_GenBuffersARB(1, &mipmap->VBO);
2725 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
2726 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
2727 NULL, GL_DYNAMIC_DRAW_ARB);
2728
2729 /* setup vertex arrays */
2730 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
2731 _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex));
2732 _mesa_EnableClientState(GL_VERTEX_ARRAY);
2733 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
2734 }
2735 else {
2736 _mesa_BindVertexArray(mipmap->ArrayObj);
2737 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
2738 }
2739
2740 if (!mipmap->FBO) {
2741 _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
2742 }
2743 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
2744
2745 _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
2746 _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2747 _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
2748 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2749 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2750 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
2751
2752 /* We don't want to encode or decode sRGB values; treat them as linear */
2753 if (ctx->Extensions.EXT_texture_sRGB_decode) {
2754 _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT,
2755 GL_SKIP_DECODE_EXT);
2756 }
2757 if (ctx->Extensions.EXT_framebuffer_sRGB) {
2758 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE);
2759 }
2760
2761 _mesa_set_enable(ctx, target, GL_TRUE);
2762
2763 /* setup texcoords (XXX what about border?) */
2764 setup_texture_coords(faceTarget,
2765 0.0, 0.0, /* width, height never used here */
2766 slice,
2767 verts[0].tex,
2768 verts[1].tex,
2769 verts[2].tex,
2770 verts[3].tex);
2771
2772 /* setup vertex positions */
2773 verts[0].x = 0.0F;
2774 verts[0].y = 0.0F;
2775 verts[1].x = 1.0F;
2776 verts[1].y = 0.0F;
2777 verts[2].x = 1.0F;
2778 verts[2].y = 1.0F;
2779 verts[3].x = 0.0F;
2780 verts[3].y = 1.0F;
2781
2782 /* upload new vertex data */
2783 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
2784
2785 /* setup projection matrix */
2786 _mesa_MatrixMode(GL_PROJECTION);
2787 _mesa_LoadIdentity();
2788 _mesa_Ortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
2789
2790 /* texture is already locked, unlock now */
2791 _mesa_unlock_texture(ctx, texObj);
2792
2793 for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
2794 const struct gl_texture_image *srcImage;
2795 const GLuint srcLevel = dstLevel - 1;
2796 GLsizei srcWidth, srcHeight, srcDepth;
2797 GLsizei dstWidth, dstHeight, dstDepth;
2798 GLenum status;
2799
2800 srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel);
2801 assert(srcImage->Border == 0); /* XXX we can fix this */
2802
2803 /* src size w/out border */
2804 srcWidth = srcImage->Width - 2 * border;
2805 srcHeight = srcImage->Height - 2 * border;
2806 srcDepth = srcImage->Depth - 2 * border;
2807
2808 /* new dst size w/ border */
2809 dstWidth = MAX2(1, srcWidth / 2) + 2 * border;
2810 dstHeight = MAX2(1, srcHeight / 2) + 2 * border;
2811 dstDepth = MAX2(1, srcDepth / 2) + 2 * border;
2812
2813 if (dstWidth == srcImage->Width &&
2814 dstHeight == srcImage->Height &&
2815 dstDepth == srcImage->Depth) {
2816 /* all done */
2817 break;
2818 }
2819
2820 /* Set MaxLevel large enough to hold the new level when we allocate it */
2821 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
2822
2823 /* Create empty dest image */
2824 if (target == GL_TEXTURE_1D) {
2825 _mesa_TexImage1D(target, dstLevel, srcImage->InternalFormat,
2826 dstWidth, border,
2827 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2828 }
2829 else if (target == GL_TEXTURE_3D) {
2830 _mesa_TexImage3D(target, dstLevel, srcImage->InternalFormat,
2831 dstWidth, dstHeight, dstDepth, border,
2832 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2833 }
2834 else {
2835 /* 2D or cube */
2836 _mesa_TexImage2D(faceTarget, dstLevel, srcImage->InternalFormat,
2837 dstWidth, dstHeight, border,
2838 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2839
2840 if (target == GL_TEXTURE_CUBE_MAP) {
2841 /* If texturing from a cube, we need to make sure all src faces
2842 * have been defined (even if we're not sampling from them.)
2843 * Otherwise the texture object will be 'incomplete' and
2844 * texturing from it will not be allowed.
2845 */
2846 GLuint face;
2847 for (face = 0; face < 6; face++) {
2848 if (!texObj->Image[face][srcLevel] ||
2849 texObj->Image[face][srcLevel]->Width != srcWidth) {
2850 _mesa_TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
2851 srcLevel, srcImage->InternalFormat,
2852 srcWidth, srcHeight, border,
2853 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2854 }
2855 }
2856 }
2857 }
2858
2859 /* limit minification to src level */
2860 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
2861
2862 /* Set to draw into the current dstLevel */
2863 if (target == GL_TEXTURE_1D) {
2864 _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
2865 GL_COLOR_ATTACHMENT0_EXT,
2866 target,
2867 texObj->Name,
2868 dstLevel);
2869 }
2870 else if (target == GL_TEXTURE_3D) {
2871 GLint zoffset = 0; /* XXX unfinished */
2872 _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
2873 GL_COLOR_ATTACHMENT0_EXT,
2874 target,
2875 texObj->Name,
2876 dstLevel, zoffset);
2877 }
2878 else {
2879 /* 2D / cube */
2880 _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
2881 GL_COLOR_ATTACHMENT0_EXT,
2882 faceTarget,
2883 texObj->Name,
2884 dstLevel);
2885 }
2886
2887 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
2888
2889 /* sanity check */
2890 status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
2891 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2892 abort();
2893 break;
2894 }
2895
2896 assert(dstWidth == ctx->DrawBuffer->Width);
2897 assert(dstHeight == ctx->DrawBuffer->Height);
2898
2899 /* setup viewport */
2900 _mesa_set_viewport(ctx, 0, 0, dstWidth, dstHeight);
2901
2902 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
2903 }
2904
2905 if (ctx->Extensions.EXT_texture_sRGB_decode) {
2906 _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT,
2907 srgbDecodeSave);
2908 }
2909 if (ctx->Extensions.EXT_framebuffer_sRGB && srgbBufferSave) {
2910 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE);
2911 }
2912
2913 _mesa_lock_texture(ctx, texObj); /* relock */
2914
2915 _mesa_meta_end(ctx);
2916
2917 _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
2918 _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
2919 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
2920 _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
2921 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
2922 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
2923 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, wrapRSave);
2924
2925 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
2926 }
2927
2928
2929 /**
2930 * Determine the GL data type to use for the temporary image read with
2931 * ReadPixels() and passed to Tex[Sub]Image().
2932 */
2933 static GLenum
2934 get_temp_image_type(struct gl_context *ctx, GLenum baseFormat)
2935 {
2936 switch (baseFormat) {
2937 case GL_RGBA:
2938 case GL_RGB:
2939 case GL_ALPHA:
2940 case GL_LUMINANCE:
2941 case GL_LUMINANCE_ALPHA:
2942 case GL_INTENSITY:
2943 if (ctx->DrawBuffer->Visual.redBits <= 8)
2944 return GL_UNSIGNED_BYTE;
2945 else if (ctx->DrawBuffer->Visual.redBits <= 16)
2946 return GL_UNSIGNED_SHORT;
2947 else
2948 return GL_FLOAT;
2949 case GL_DEPTH_COMPONENT:
2950 return GL_UNSIGNED_INT;
2951 case GL_DEPTH_STENCIL:
2952 return GL_UNSIGNED_INT_24_8;
2953 default:
2954 _mesa_problem(ctx, "Unexpected format in get_temp_image_type()");
2955 return 0;
2956 }
2957 }
2958
2959
2960 /**
2961 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
2962 * Have to be careful with locking and meta state for pixel transfer.
2963 */
2964 static void
2965 copy_tex_sub_image(struct gl_context *ctx,
2966 GLuint dims, GLenum target, GLint level,
2967 GLint xoffset, GLint yoffset, GLint zoffset,
2968 GLint x, GLint y,
2969 GLsizei width, GLsizei height)
2970 {
2971 struct gl_texture_object *texObj;
2972 struct gl_texture_image *texImage;
2973 GLenum format, type;
2974 GLint bpp;
2975 void *buf;
2976
2977 texObj = _mesa_get_current_tex_object(ctx, target);
2978 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2979
2980 /* Choose format/type for temporary image buffer */
2981 format = _mesa_get_format_base_format(texImage->TexFormat);
2982 if (format == GL_LUMINANCE ||
2983 format == GL_LUMINANCE_ALPHA ||
2984 format == GL_INTENSITY) {
2985 /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the
2986 * temp image buffer because glReadPixels will do L=R+G+B which is
2987 * not what we want (should be L=R).
2988 */
2989 format = GL_RGBA;
2990 }
2991
2992 type = get_temp_image_type(ctx, format);
2993 bpp = _mesa_bytes_per_pixel(format, type);
2994 if (bpp <= 0) {
2995 _mesa_problem(ctx, "Bad bpp in meta copy_tex_sub_image()");
2996 return;
2997 }
2998
2999 /*
3000 * Alloc image buffer (XXX could use a PBO)
3001 */
3002 buf = malloc(width * height * bpp);
3003 if (!buf) {
3004 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims);
3005 return;
3006 }
3007
3008 _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
3009
3010 /*
3011 * Read image from framebuffer (disable pixel transfer ops)
3012 */
3013 _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER);
3014 ctx->Driver.ReadPixels(ctx, x, y, width, height,
3015 format, type, &ctx->Pack, buf);
3016 _mesa_meta_end(ctx);
3017
3018 _mesa_update_state(ctx); /* to update pixel transfer state */
3019
3020 /*
3021 * Store texture data (with pixel transfer ops)
3022 */
3023 _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE);
3024 if (target == GL_TEXTURE_1D) {
3025 ctx->Driver.TexSubImage1D(ctx, target, level, xoffset,
3026 width, format, type, buf,
3027 &ctx->Unpack, texObj, texImage);
3028 }
3029 else if (target == GL_TEXTURE_3D) {
3030 ctx->Driver.TexSubImage3D(ctx, target, level, xoffset, yoffset, zoffset,
3031 width, height, 1, format, type, buf,
3032 &ctx->Unpack, texObj, texImage);
3033 }
3034 else {
3035 ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
3036 width, height, format, type, buf,
3037 &ctx->Unpack, texObj, texImage);
3038 }
3039 _mesa_meta_end(ctx);
3040
3041 _mesa_lock_texture(ctx, texObj); /* re-lock */
3042
3043 free(buf);
3044 }
3045
3046
3047 void
3048 _mesa_meta_CopyTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level,
3049 GLint xoffset,
3050 GLint x, GLint y, GLsizei width)
3051 {
3052 copy_tex_sub_image(ctx, 1, target, level, xoffset, 0, 0,
3053 x, y, width, 1);
3054 }
3055
3056
3057 void
3058 _mesa_meta_CopyTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level,
3059 GLint xoffset, GLint yoffset,
3060 GLint x, GLint y,
3061 GLsizei width, GLsizei height)
3062 {
3063 copy_tex_sub_image(ctx, 2, target, level, xoffset, yoffset, 0,
3064 x, y, width, height);
3065 }
3066
3067
3068 void
3069 _mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level,
3070 GLint xoffset, GLint yoffset, GLint zoffset,
3071 GLint x, GLint y,
3072 GLsizei width, GLsizei height)
3073 {
3074 copy_tex_sub_image(ctx, 3, target, level, xoffset, yoffset, zoffset,
3075 x, y, width, height);
3076 }
3077
3078
3079 /**
3080 * Decompress a texture image by drawing a quad with the compressed
3081 * texture and reading the pixels out of the color buffer.
3082 * \param slice which slice of a 3D texture or layer of a 1D/2D texture
3083 * \param destFormat format, ala glReadPixels
3084 * \param destType type, ala glReadPixels
3085 * \param dest destination buffer
3086 * \param destRowLength dest image rowLength (ala GL_PACK_ROW_LENGTH)
3087 */
3088 static void
3089 decompress_texture_image(struct gl_context *ctx,
3090 struct gl_texture_image *texImage,
3091 GLuint slice,
3092 GLenum destFormat, GLenum destType,
3093 GLvoid *dest, GLint destRowLength)
3094 {
3095 struct decompress_state *decompress = &ctx->Meta->Decompress;
3096 struct gl_texture_object *texObj = texImage->TexObject;
3097 const GLint width = texImage->Width;
3098 const GLint height = texImage->Height;
3099 const GLenum target = texObj->Target;
3100 GLenum faceTarget;
3101 struct vertex {
3102 GLfloat x, y, tex[3];
3103 };
3104 struct vertex verts[4];
3105 GLuint fboDrawSave, fboReadSave;
3106
3107 if (slice > 0) {
3108 assert(target == GL_TEXTURE_3D ||
3109 target == GL_TEXTURE_2D_ARRAY);
3110 }
3111
3112 if (target == GL_TEXTURE_CUBE_MAP) {
3113 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face;
3114 }
3115 else {
3116 faceTarget = target;
3117 }
3118
3119 /* save fbo bindings (not saved by _mesa_meta_begin()) */
3120 fboDrawSave = ctx->DrawBuffer->Name;
3121 fboReadSave = ctx->ReadBuffer->Name;
3122
3123 _mesa_meta_begin(ctx, MESA_META_ALL);
3124
3125 /* Create/bind FBO/renderbuffer */
3126 if (decompress->FBO == 0) {
3127 _mesa_GenFramebuffersEXT(1, &decompress->FBO);
3128 _mesa_GenRenderbuffersEXT(1, &decompress->RBO);
3129 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO);
3130 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO);
3131 _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
3132 GL_COLOR_ATTACHMENT0_EXT,
3133 GL_RENDERBUFFER_EXT,
3134 decompress->RBO);
3135 }
3136 else {
3137 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO);
3138 }
3139
3140 /* alloc dest surface */
3141 if (width != decompress->Width || height != decompress->Height) {
3142 _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA,
3143 width, height);
3144 decompress->Width = width;
3145 decompress->Height = height;
3146 }
3147
3148 /* setup VBO data */
3149 if (decompress->ArrayObj == 0) {
3150 /* create vertex array object */
3151 _mesa_GenVertexArrays(1, &decompress->ArrayObj);
3152 _mesa_BindVertexArray(decompress->ArrayObj);
3153
3154 /* create vertex array buffer */
3155 _mesa_GenBuffersARB(1, &decompress->VBO);
3156 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO);
3157 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
3158 NULL, GL_DYNAMIC_DRAW_ARB);
3159
3160 /* setup vertex arrays */
3161 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
3162 _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex));
3163 _mesa_EnableClientState(GL_VERTEX_ARRAY);
3164 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
3165 }
3166 else {
3167 _mesa_BindVertexArray(decompress->ArrayObj);
3168 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO);
3169 }
3170
3171 setup_texture_coords(faceTarget, slice, width, height,
3172 verts[0].tex,
3173 verts[1].tex,
3174 verts[2].tex,
3175 verts[3].tex);
3176
3177 /* setup vertex positions */
3178 verts[0].x = 0.0F;
3179 verts[0].y = 0.0F;
3180 verts[1].x = width;
3181 verts[1].y = 0.0F;
3182 verts[2].x = width;
3183 verts[2].y = height;
3184 verts[3].x = 0.0F;
3185 verts[3].y = height;
3186
3187 /* upload new vertex data */
3188 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
3189
3190 /* setup texture state */
3191 _mesa_BindTexture(target, texObj->Name);
3192 _mesa_set_enable(ctx, target, GL_TRUE);
3193
3194 {
3195 /* save texture object state */
3196 const GLenum minFilterSave = texObj->Sampler.MinFilter;
3197 const GLenum magFilterSave = texObj->Sampler.MagFilter;
3198 const GLint baseLevelSave = texObj->BaseLevel;
3199 const GLint maxLevelSave = texObj->MaxLevel;
3200 const GLenum wrapSSave = texObj->Sampler.WrapS;
3201 const GLenum wrapTSave = texObj->Sampler.WrapT;
3202 const GLenum srgbSave = texObj->Sampler.sRGBDecode;
3203
3204 /* restrict sampling to the texture level of interest */
3205 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, texImage->Level);
3206 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, texImage->Level);
3207 /* nearest filtering */
3208 _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3209 _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3210
3211 /* No sRGB decode or encode.*/
3212 if (ctx->Extensions.EXT_texture_sRGB_decode) {
3213 _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT,
3214 GL_SKIP_DECODE_EXT);
3215 }
3216 if (ctx->Extensions.EXT_framebuffer_sRGB) {
3217 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE);
3218 }
3219
3220 /* render quad w/ texture into renderbuffer */
3221 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
3222
3223 /* Restore texture object state, the texture binding will
3224 * be restored by _mesa_meta_end().
3225 */
3226 _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
3227 _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
3228 if (target != GL_TEXTURE_RECTANGLE_ARB) {
3229 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
3230 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
3231 }
3232 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
3233 _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
3234 if (ctx->Extensions.EXT_texture_sRGB_decode) {
3235 _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT, srgbSave);
3236 }
3237 }
3238
3239 /* read pixels from renderbuffer */
3240 {
3241 GLenum baseTexFormat = texImage->_BaseFormat;
3242
3243 /* The pixel transfer state will be set to default values at this point
3244 * (see MESA_META_PIXEL_TRANSFER) so pixel transfer ops are effectively
3245 * turned off (as required by glGetTexImage) but we need to handle some
3246 * special cases. In particular, single-channel texture values are
3247 * returned as red and two-channel texture values are returned as
3248 * red/alpha.
3249 */
3250 if (baseTexFormat == GL_LUMINANCE ||
3251 baseTexFormat == GL_LUMINANCE_ALPHA ||
3252 baseTexFormat == GL_INTENSITY) {
3253 /* Green and blue must be zero */
3254 _mesa_PixelTransferf(GL_GREEN_SCALE, 0.0f);
3255 _mesa_PixelTransferf(GL_BLUE_SCALE, 0.0f);
3256 }
3257
3258 ctx->Pack.RowLength = destRowLength;
3259 _mesa_ReadPixels(0, 0, width, height, destFormat, destType, dest);
3260 }
3261
3262 /* disable texture unit */
3263 _mesa_set_enable(ctx, target, GL_FALSE);
3264
3265 _mesa_meta_end(ctx);
3266
3267 /* restore fbo bindings */
3268 if (fboDrawSave == fboReadSave) {
3269 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboDrawSave);
3270 }
3271 else {
3272 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboDrawSave);
3273 _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fboReadSave);
3274 }
3275 }
3276
3277
3278 /**
3279 * This is just a wrapper around _mesa_get_tex_image() and
3280 * decompress_texture_image(). Meta functions should not be directly called
3281 * from core Mesa.
3282 */
3283 void
3284 _mesa_meta_GetTexImage(struct gl_context *ctx,
3285 GLenum format, GLenum type, GLvoid *pixels,
3286 struct gl_texture_image *texImage)
3287 {
3288 /* We can only use the decompress-with-blit method here if the texels are
3289 * unsigned, normalized values. We could handle signed and unnormalized
3290 * with floating point renderbuffers...
3291 */
3292 if (_mesa_is_format_compressed(texImage->TexFormat) &&
3293 _mesa_get_format_datatype(texImage->TexFormat)
3294 == GL_UNSIGNED_NORMALIZED) {
3295 struct gl_texture_object *texObj = texImage->TexObject;
3296 const GLuint slice = 0; /* only 2D compressed textures for now */
3297 /* Need to unlock the texture here to prevent deadlock... */
3298 _mesa_unlock_texture(ctx, texObj);
3299 decompress_texture_image(ctx, texImage, slice, format, type, pixels,
3300 ctx->Pack.RowLength);
3301 /* ... and relock it */
3302 _mesa_lock_texture(ctx, texObj);
3303 }
3304 else {
3305 _mesa_get_teximage(ctx, format, type, pixels, texImage);
3306 }
3307 }