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