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