meta_blit.c revision 848b8605
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include "main/glheader.h"
26#include "main/mtypes.h"
27#include "main/imports.h"
28#include "main/arbprogram.h"
29#include "main/arrayobj.h"
30#include "main/blend.h"
31#include "main/condrender.h"
32#include "main/depth.h"
33#include "main/enable.h"
34#include "main/enums.h"
35#include "main/fbobject.h"
36#include "main/image.h"
37#include "main/macros.h"
38#include "main/matrix.h"
39#include "main/multisample.h"
40#include "main/objectlabel.h"
41#include "main/readpix.h"
42#include "main/scissor.h"
43#include "main/shaderapi.h"
44#include "main/texobj.h"
45#include "main/texenv.h"
46#include "main/teximage.h"
47#include "main/texparam.h"
48#include "main/varray.h"
49#include "main/viewport.h"
50#include "swrast/swrast.h"
51#include "drivers/common/meta.h"
52#include "util/ralloc.h"
53
54/** Return offset in bytes of the field within a vertex struct */
55#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
56
57static void
58setup_glsl_msaa_blit_shader(struct gl_context *ctx,
59                            struct blit_state *blit,
60                            struct gl_renderbuffer *src_rb,
61                            GLenum target)
62{
63   const char *vs_source;
64   char *fs_source;
65   void *mem_ctx;
66   enum blit_msaa_shader shader_index;
67   bool dst_is_msaa = false;
68   GLenum src_datatype;
69   const char *vec4_prefix;
70   const char *sampler_array_suffix = "";
71   char *name;
72   const char *texcoord_type = "vec2";
73
74   if (src_rb) {
75      src_datatype = _mesa_get_format_datatype(src_rb->Format);
76   } else {
77      /* depth-or-color glCopyTexImage fallback path that passes a NULL rb and
78       * doesn't handle integer.
79       */
80      src_datatype = GL_UNSIGNED_NORMALIZED;
81   }
82
83   if (ctx->DrawBuffer->Visual.samples > 1) {
84      /* If you're calling meta_BlitFramebuffer with the destination
85       * multisampled, this is the only path that will work -- swrast and
86       * CopyTexImage won't work on it either.
87       */
88      assert(ctx->Extensions.ARB_sample_shading);
89
90      dst_is_msaa = true;
91
92      /* We need shader invocation per sample, not per pixel */
93      _mesa_set_enable(ctx, GL_MULTISAMPLE, GL_TRUE);
94      _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_TRUE);
95      _mesa_MinSampleShading(1.0);
96   }
97
98   switch (target) {
99   case GL_TEXTURE_2D_MULTISAMPLE:
100   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
101      if (src_rb->_BaseFormat == GL_DEPTH_COMPONENT ||
102          src_rb->_BaseFormat == GL_DEPTH_STENCIL) {
103         if (dst_is_msaa)
104            shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY;
105         else
106            shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE;
107      } else {
108         if (dst_is_msaa)
109            shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY;
110         else
111            shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE;
112      }
113
114      if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
115         shader_index += (BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_RESOLVE -
116                          BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE);
117         sampler_array_suffix = "Array";
118         texcoord_type = "vec3";
119      }
120      break;
121   default:
122      _mesa_problem(ctx, "Unkown texture target %s\n",
123                    _mesa_lookup_enum_by_nr(target));
124      shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE;
125   }
126
127   /* We rely on the enum being sorted this way. */
128   STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT ==
129                 BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 1);
130   STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT ==
131                 BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 2);
132   if (src_datatype == GL_INT) {
133      shader_index++;
134      vec4_prefix = "i";
135   } else if (src_datatype == GL_UNSIGNED_INT) {
136      shader_index += 2;
137      vec4_prefix = "u";
138   } else {
139      vec4_prefix = "";
140   }
141
142   if (blit->msaa_shaders[shader_index]) {
143      _mesa_UseProgram(blit->msaa_shaders[shader_index]);
144      return;
145   }
146
147   mem_ctx = ralloc_context(NULL);
148
149   if (shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE ||
150       shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_DEPTH_RESOLVE ||
151       shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_DEPTH_COPY ||
152       shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY) {
153      char *sample_index;
154      const char *arb_sample_shading_extension_string;
155
156      if (dst_is_msaa) {
157         arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable";
158         sample_index = "gl_SampleID";
159         name = "depth MSAA copy";
160      } else {
161         /* Don't need that extension, since we're drawing to a single-sampled
162          * destination.
163          */
164         arb_sample_shading_extension_string = "";
165         /* From the GL 4.3 spec:
166          *
167          *     "If there is a multisample buffer (the value of SAMPLE_BUFFERS
168          *      is one), then values are obtained from the depth samples in
169          *      this buffer. It is recommended that the depth value of the
170          *      centermost sample be used, though implementations may choose
171          *      any function of the depth sample values at each pixel.
172          *
173          * We're slacking and instead of choosing centermost, we've got 0.
174          */
175         sample_index = "0";
176         name = "depth MSAA resolve";
177      }
178
179      vs_source = ralloc_asprintf(mem_ctx,
180                                  "#version 130\n"
181                                  "in vec2 position;\n"
182                                  "in %s textureCoords;\n"
183                                  "out %s texCoords;\n"
184                                  "void main()\n"
185                                  "{\n"
186                                  "   texCoords = textureCoords;\n"
187                                  "   gl_Position = vec4(position, 0.0, 1.0);\n"
188                                  "}\n",
189                                  texcoord_type,
190                                  texcoord_type);
191      fs_source = ralloc_asprintf(mem_ctx,
192                                  "#version 130\n"
193                                  "#extension GL_ARB_texture_multisample : enable\n"
194                                  "%s\n"
195                                  "uniform sampler2DMS%s texSampler;\n"
196                                  "in %s texCoords;\n"
197                                  "out vec4 out_color;\n"
198                                  "\n"
199                                  "void main()\n"
200                                  "{\n"
201                                  "   gl_FragDepth = texelFetch(texSampler, i%s(texCoords), %s).r;\n"
202                                  "}\n",
203                                  arb_sample_shading_extension_string,
204                                  sampler_array_suffix,
205                                  texcoord_type,
206                                  texcoord_type,
207                                  sample_index);
208   } else {
209      /* You can create 2D_MULTISAMPLE textures with 0 sample count (meaning 1
210       * sample).  Yes, this is ridiculous.
211       */
212      int samples;
213      char *sample_resolve;
214      const char *arb_sample_shading_extension_string;
215      const char *merge_function;
216      name = ralloc_asprintf(mem_ctx, "%svec4 MSAA %s",
217                             vec4_prefix,
218                             dst_is_msaa ? "copy" : "resolve");
219
220      samples = MAX2(src_rb->NumSamples, 1);
221
222      if (dst_is_msaa) {
223         arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable";
224         sample_resolve = ralloc_asprintf(mem_ctx, "   out_color = texelFetch(texSampler, i%s(texCoords), gl_SampleID);", texcoord_type);
225         merge_function = "";
226      } else {
227         int i;
228         int step;
229
230         if (src_datatype == GL_INT || src_datatype == GL_UNSIGNED_INT) {
231            merge_function =
232               "gvec4 merge(gvec4 a, gvec4 b) { return (a >> gvec4(1)) + (b >> gvec4(1)) + (a & b & gvec4(1)); }\n";
233         } else {
234            /* The divide will happen at the end for floats. */
235            merge_function =
236               "vec4 merge(vec4 a, vec4 b) { return (a + b); }\n";
237         }
238
239         arb_sample_shading_extension_string = "";
240
241         /* We're assuming power of two samples for this resolution procedure.
242          *
243          * To avoid losing any floating point precision if the samples all
244          * happen to have the same value, we merge pairs of values at a time
245          * (so the floating point exponent just gets increased), rather than
246          * doing a naive sum and dividing.
247          */
248         assert((samples & (samples - 1)) == 0);
249         /* Fetch each individual sample. */
250         sample_resolve = rzalloc_size(mem_ctx, 1);
251         for (i = 0; i < samples; i++) {
252            ralloc_asprintf_append(&sample_resolve,
253                                   "   gvec4 sample_1_%d = texelFetch(texSampler, i%s(texCoords), %d);\n",
254                                   i, texcoord_type, i);
255         }
256         /* Now, merge each pair of samples, then merge each pair of those,
257          * etc.
258          */
259         for (step = 2; step <= samples; step *= 2) {
260            for (i = 0; i < samples; i += step) {
261               ralloc_asprintf_append(&sample_resolve,
262                                      "   gvec4 sample_%d_%d = merge(sample_%d_%d, sample_%d_%d);\n",
263                                      step, i,
264                                      step / 2, i,
265                                      step / 2, i + step / 2);
266            }
267         }
268
269         /* Scale the final result. */
270         if (src_datatype == GL_UNSIGNED_INT || src_datatype == GL_INT) {
271            ralloc_asprintf_append(&sample_resolve,
272                                   "   out_color = sample_%d_0;\n",
273                                   samples);
274         } else {
275            ralloc_asprintf_append(&sample_resolve,
276                                   "   gl_FragColor = sample_%d_0 / %f;\n",
277                                   samples, (float)samples);
278         }
279      }
280
281      vs_source = ralloc_asprintf(mem_ctx,
282                                  "#version 130\n"
283                                  "in vec2 position;\n"
284                                  "in %s textureCoords;\n"
285                                  "out %s texCoords;\n"
286                                  "void main()\n"
287                                  "{\n"
288                                  "   texCoords = textureCoords;\n"
289                                  "   gl_Position = vec4(position, 0.0, 1.0);\n"
290                                  "}\n",
291                                  texcoord_type,
292                                  texcoord_type);
293      fs_source = ralloc_asprintf(mem_ctx,
294                                  "#version 130\n"
295                                  "#extension GL_ARB_texture_multisample : enable\n"
296                                  "%s\n"
297                                  "#define gvec4 %svec4\n"
298                                  "uniform %ssampler2DMS%s texSampler;\n"
299                                  "in %s texCoords;\n"
300                                  "out gvec4 out_color;\n"
301                                  "\n"
302                                  "%s" /* merge_function */
303                                  "void main()\n"
304                                  "{\n"
305                                  "%s\n" /* sample_resolve */
306                                  "}\n",
307                                  arb_sample_shading_extension_string,
308                                  vec4_prefix,
309                                  vec4_prefix,
310                                  sampler_array_suffix,
311                                  texcoord_type,
312                                  merge_function,
313                                  sample_resolve);
314   }
315
316   _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, name,
317                                       &blit->msaa_shaders[shader_index]);
318
319   ralloc_free(mem_ctx);
320}
321
322static void
323setup_glsl_blit_framebuffer(struct gl_context *ctx,
324                            struct blit_state *blit,
325                            struct gl_renderbuffer *src_rb,
326                            GLenum target)
327{
328   unsigned texcoord_size;
329
330   /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
331   assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D);
332
333   texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0);
334
335   _mesa_meta_setup_vertex_objects(&blit->VAO, &blit->VBO, true,
336                                   2, texcoord_size, 0);
337
338   if (target == GL_TEXTURE_2D_MULTISAMPLE ||
339       target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
340      setup_glsl_msaa_blit_shader(ctx, blit, src_rb, target);
341   } else {
342      _mesa_meta_setup_blit_shader(ctx, target, &blit->shaders);
343   }
344}
345
346/**
347 * Try to do a color or depth glBlitFramebuffer using texturing.
348 *
349 * We can do this when the src renderbuffer is actually a texture, or when the
350 * driver exposes BindRenderbufferTexImage().
351 */
352static bool
353blitframebuffer_texture(struct gl_context *ctx,
354                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
355                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
356                        GLenum filter, GLint flipX, GLint flipY,
357                        GLboolean glsl_version, GLboolean do_depth)
358{
359   const struct gl_framebuffer *readFb = ctx->ReadBuffer;
360   int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex;
361   const struct gl_renderbuffer_attachment *readAtt =
362      &readFb->Attachment[att_index];
363   struct blit_state *blit = &ctx->Meta->Blit;
364   struct fb_tex_blit_state fb_tex_blit;
365   const GLint dstX = MIN2(dstX0, dstX1);
366   const GLint dstY = MIN2(dstY0, dstY1);
367   const GLint dstW = abs(dstX1 - dstX0);
368   const GLint dstH = abs(dstY1 - dstY0);
369   struct gl_texture_object *texObj;
370   GLuint srcLevel;
371   GLenum target;
372   struct gl_renderbuffer *rb = readAtt->Renderbuffer;
373   struct temp_texture *meta_temp_texture;
374
375   if (rb->NumSamples && !ctx->Extensions.ARB_texture_multisample)
376      return false;
377
378   if (filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
379       filter == GL_SCALED_RESOLVE_NICEST_EXT) {
380      filter = GL_LINEAR;
381   }
382
383   _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit);
384
385   if (readAtt->Texture &&
386       (readAtt->Texture->Target == GL_TEXTURE_2D ||
387        readAtt->Texture->Target == GL_TEXTURE_RECTANGLE ||
388        readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE ||
389        readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
390      /* If there's a texture attached of a type we can handle, then just use
391       * it directly.
392       */
393      srcLevel = readAtt->TextureLevel;
394      texObj = readAtt->Texture;
395      target = texObj->Target;
396   } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) {
397      if (!_mesa_meta_bind_rb_as_tex_image(ctx, rb, &fb_tex_blit.tempTex,
398                                           &texObj, &target))
399         return false;
400
401      srcLevel = 0;
402      if (_mesa_is_winsys_fbo(readFb)) {
403         GLint temp = srcY0;
404         srcY0 = rb->Height - srcY1;
405         srcY1 = rb->Height - temp;
406         flipY = -flipY;
407      }
408   } else {
409      GLenum tex_base_format;
410      int srcW = abs(srcX1 - srcX0);
411      int srcH = abs(srcY1 - srcY0);
412      /* Fall back to doing a CopyTexSubImage to get the destination
413       * renderbuffer into a texture.
414       */
415      if (ctx->Meta->Blit.no_ctsi_fallback)
416         return false;
417
418      if (rb->NumSamples > 1)
419         return false;
420
421      if (do_depth) {
422         meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx);
423         tex_base_format = GL_DEPTH_COMPONENT;
424      } else {
425         meta_temp_texture = _mesa_meta_get_temp_texture(ctx);
426         tex_base_format =
427            _mesa_base_tex_format(ctx, rb->InternalFormat);
428      }
429
430      srcLevel = 0;
431      target = meta_temp_texture->Target;
432      texObj = _mesa_lookup_texture(ctx, meta_temp_texture->TexObj);
433      if (texObj == NULL) {
434         return false;
435      }
436
437      _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture,
438                                       srcX0, srcY0,
439                                       srcW, srcH,
440                                       tex_base_format,
441                                       filter);
442
443
444      srcX0 = 0;
445      srcY0 = 0;
446      srcX1 = srcW;
447      srcY1 = srcH;
448   }
449
450   fb_tex_blit.baseLevelSave = texObj->BaseLevel;
451   fb_tex_blit.maxLevelSave = texObj->MaxLevel;
452   fb_tex_blit.stencilSamplingSave = texObj->StencilSampling;
453
454   if (glsl_version) {
455      setup_glsl_blit_framebuffer(ctx, blit, rb, target);
456   }
457   else {
458      _mesa_meta_setup_ff_tnl_for_blit(&ctx->Meta->Blit.VAO,
459                                       &ctx->Meta->Blit.VBO,
460                                       2);
461   }
462
463   /*
464     printf("Blit from texture!\n");
465     printf("  srcAtt %p  dstAtt %p\n", readAtt, drawAtt);
466     printf("  srcTex %p  dstText %p\n", texObj, drawAtt->Texture);
467   */
468
469   fb_tex_blit.sampler = _mesa_meta_setup_sampler(ctx, texObj, target, filter,
470                                                  srcLevel);
471
472   /* Always do our blits with no net sRGB decode or encode.
473    *
474    * However, if both the src and dst can be srgb decode/encoded, enable them
475    * so that we do any blending (from scaling or from MSAA resolves) in the
476    * right colorspace.
477    *
478    * Our choice of not doing any net encode/decode is from the GL 3.0
479    * specification:
480    *
481    *     "Blit operations bypass the fragment pipeline. The only fragment
482    *      operations which affect a blit are the pixel ownership test and the
483    *      scissor test."
484    *
485    * The GL 4.4 specification disagrees and says that the sRGB part of the
486    * fragment pipeline applies, but this was found to break applications.
487    */
488   if (ctx->Extensions.EXT_texture_sRGB_decode) {
489      if (_mesa_get_format_color_encoding(rb->Format) == GL_SRGB &&
490          ctx->DrawBuffer->Visual.sRGBCapable) {
491         _mesa_SamplerParameteri(fb_tex_blit.sampler,
492                                 GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
493         _mesa_set_framebuffer_srgb(ctx, GL_TRUE);
494      } else {
495         _mesa_SamplerParameteri(fb_tex_blit.sampler,
496                                 GL_TEXTURE_SRGB_DECODE_EXT,
497                                 GL_SKIP_DECODE_EXT);
498         /* set_framebuffer_srgb was set by _mesa_meta_begin(). */
499      }
500   }
501
502   if (!glsl_version) {
503      _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
504      _mesa_set_enable(ctx, target, GL_TRUE);
505   }
506
507   /* Prepare vertex data (the VBO was previously created and bound) */
508   {
509      struct vertex verts[4];
510      GLfloat s0, t0, s1, t1;
511
512      if (target == GL_TEXTURE_2D) {
513         const struct gl_texture_image *texImage
514            = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
515         s0 = srcX0 / (float) texImage->Width;
516         s1 = srcX1 / (float) texImage->Width;
517         t0 = srcY0 / (float) texImage->Height;
518         t1 = srcY1 / (float) texImage->Height;
519      }
520      else {
521         assert(target == GL_TEXTURE_RECTANGLE_ARB ||
522                target == GL_TEXTURE_2D_MULTISAMPLE ||
523                target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
524         s0 = (float) srcX0;
525         s1 = (float) srcX1;
526         t0 = (float) srcY0;
527         t1 = (float) srcY1;
528      }
529
530      /* Silence valgrind warnings about reading uninitialized stack. */
531      memset(verts, 0, sizeof(verts));
532
533      /* setup vertex positions */
534      verts[0].x = -1.0F * flipX;
535      verts[0].y = -1.0F * flipY;
536      verts[1].x =  1.0F * flipX;
537      verts[1].y = -1.0F * flipY;
538      verts[2].x =  1.0F * flipX;
539      verts[2].y =  1.0F * flipY;
540      verts[3].x = -1.0F * flipX;
541      verts[3].y =  1.0F * flipY;
542
543      verts[0].tex[0] = s0;
544      verts[0].tex[1] = t0;
545      verts[0].tex[2] = readAtt->Zoffset;
546      verts[1].tex[0] = s1;
547      verts[1].tex[1] = t0;
548      verts[1].tex[2] = readAtt->Zoffset;
549      verts[2].tex[0] = s1;
550      verts[2].tex[1] = t1;
551      verts[2].tex[2] = readAtt->Zoffset;
552      verts[3].tex[0] = s0;
553      verts[3].tex[1] = t1;
554      verts[3].tex[2] = readAtt->Zoffset;
555
556      _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
557   }
558
559   /* setup viewport */
560   _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
561   _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth);
562   _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth);
563   _mesa_DepthMask(do_depth);
564   _mesa_DepthFunc(GL_ALWAYS);
565
566   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
567   _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit);
568
569   return true;
570}
571
572void
573_mesa_meta_fb_tex_blit_begin(const struct gl_context *ctx,
574                             struct fb_tex_blit_state *blit)
575{
576   blit->samplerSave =
577      ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
578      ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
579   blit->tempTex = 0;
580}
581
582void
583_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
584                           struct fb_tex_blit_state *blit)
585{
586   /* Restore texture object state, the texture binding will
587    * be restored by _mesa_meta_end().
588    */
589   if (target != GL_TEXTURE_RECTANGLE_ARB) {
590      _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, blit->baseLevelSave);
591      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, blit->maxLevelSave);
592
593      if (ctx->Extensions.ARB_stencil_texturing) {
594         const struct gl_texture_object *texObj =
595            _mesa_get_current_tex_object(ctx, target);
596
597         if (texObj->StencilSampling != blit->stencilSamplingSave)
598            _mesa_TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE,
599                                blit->stencilSamplingSave ?
600                                   GL_STENCIL_INDEX : GL_DEPTH_COMPONENT);
601      }
602   }
603
604   _mesa_BindSampler(ctx->Texture.CurrentUnit, blit->samplerSave);
605   _mesa_DeleteSamplers(1, &blit->sampler);
606   if (blit->tempTex)
607      _mesa_DeleteTextures(1, &blit->tempTex);
608}
609
610GLboolean
611_mesa_meta_bind_rb_as_tex_image(struct gl_context *ctx,
612                                struct gl_renderbuffer *rb,
613                                GLuint *tex,
614                                struct gl_texture_object **texObj,
615                                GLenum *target)
616{
617   struct gl_texture_image *texImage;
618
619   if (rb->NumSamples > 1)
620      *target = GL_TEXTURE_2D_MULTISAMPLE;
621   else
622      *target = GL_TEXTURE_2D;
623
624   _mesa_GenTextures(1, tex);
625   _mesa_BindTexture(*target, *tex);
626   *texObj = _mesa_lookup_texture(ctx, *tex);
627   texImage = _mesa_get_tex_image(ctx, *texObj, *target, 0);
628
629   if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
630      _mesa_DeleteTextures(1, tex);
631      return false;
632   }
633
634   if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
635      rb->NeedsFinishRenderTexture = true;
636      ctx->Driver.FinishRenderTexture(ctx, rb);
637   }
638
639   return true;
640}
641
642GLuint
643_mesa_meta_setup_sampler(struct gl_context *ctx,
644                         const struct gl_texture_object *texObj,
645                         GLenum target, GLenum filter, GLuint srcLevel)
646{
647   GLuint sampler;
648
649   _mesa_GenSamplers(1, &sampler);
650   _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler);
651
652   /* Prepare src texture state */
653   _mesa_BindTexture(target, texObj->Name);
654   _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter);
655   _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter);
656   if (target != GL_TEXTURE_RECTANGLE_ARB) {
657      _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
658      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
659   }
660   _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
661   _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
662
663   return sampler;
664}
665
666/**
667 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
668 * of texture mapping and polygon rendering.
669 */
670GLbitfield
671_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
672                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
673                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
674                           GLbitfield mask, GLenum filter)
675{
676   const GLint dstW = abs(dstX1 - dstX0);
677   const GLint dstH = abs(dstY1 - dstY0);
678   const GLint dstFlipX = (dstX1 - dstX0) / dstW;
679   const GLint dstFlipY = (dstY1 - dstY0) / dstH;
680
681   struct {
682      GLint srcX0, srcY0, srcX1, srcY1;
683      GLint dstX0, dstY0, dstX1, dstY1;
684   } clip = {
685      srcX0, srcY0, srcX1, srcY1,
686      dstX0, dstY0, dstX1, dstY1
687   };
688
689   const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
690                                      ctx->Extensions.ARB_fragment_shader;
691
692   /* Multisample texture blit support requires texture multisample. */
693   if (ctx->ReadBuffer->Visual.samples > 0 &&
694       !ctx->Extensions.ARB_texture_multisample) {
695      return mask;
696   }
697
698   /* Clip a copy of the blit coordinates. If these differ from the input
699    * coordinates, then we'll set the scissor.
700    */
701   if (!_mesa_clip_blit(ctx, &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
702                        &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
703      /* clipped/scissored everything away */
704      return 0;
705   }
706
707   /* Only scissor affects blit, but we're doing to set a custom scissor if
708    * necessary anyway, so save/clear state.
709    */
710   _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
711
712   /* Dithering shouldn't be performed for glBlitFramebuffer */
713   _mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
714
715   /* If the clipping earlier changed the destination rect at all, then
716    * enable the scissor to clip to it.
717    */
718   if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 ||
719       clip.dstX1 != dstX1 || clip.dstY1 != dstY1) {
720      _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
721      _mesa_Scissor(MIN2(clip.dstX0, clip.dstX1),
722                    MIN2(clip.dstY0, clip.dstY1),
723                    abs(clip.dstX0 - clip.dstX1),
724                    abs(clip.dstY0 - clip.dstY1));
725   }
726
727   /* Try faster, direct texture approach first */
728   if (mask & GL_COLOR_BUFFER_BIT) {
729      if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1,
730                                  dstX0, dstY0, dstX1, dstY1,
731                                  filter, dstFlipX, dstFlipY,
732                                  use_glsl_version, false)) {
733         mask &= ~GL_COLOR_BUFFER_BIT;
734      }
735   }
736
737   if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) {
738      if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1,
739                                  dstX0, dstY0, dstX1, dstY1,
740                                  filter, dstFlipX, dstFlipY,
741                                  use_glsl_version, true)) {
742         mask &= ~GL_DEPTH_BUFFER_BIT;
743      }
744   }
745
746   if (mask & GL_STENCIL_BUFFER_BIT) {
747      /* XXX can't easily do stencil */
748   }
749
750   _mesa_meta_end(ctx);
751
752   return mask;
753}
754
755void
756_mesa_meta_glsl_blit_cleanup(struct blit_state *blit)
757{
758   if (blit->VAO) {
759      _mesa_DeleteVertexArrays(1, &blit->VAO);
760      blit->VAO = 0;
761      _mesa_DeleteBuffers(1, &blit->VBO);
762      blit->VBO = 0;
763   }
764
765   _mesa_meta_blit_shader_table_cleanup(&blit->shaders);
766
767   _mesa_DeleteTextures(1, &blit->depthTex.TexObj);
768   blit->depthTex.TexObj = 0;
769}
770
771void
772_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx,
773                                      GLint srcX0, GLint srcY0,
774                                      GLint srcX1, GLint srcY1,
775                                      GLint dstX0, GLint dstY0,
776                                      GLint dstX1, GLint dstY1,
777                                      GLbitfield mask, GLenum filter)
778{
779   mask = _mesa_meta_BlitFramebuffer(ctx,
780                                     srcX0, srcY0, srcX1, srcY1,
781                                     dstX0, dstY0, dstX1, dstY1,
782                                     mask, filter);
783   if (mask == 0x0)
784      return;
785
786   _swrast_BlitFramebuffer(ctx,
787                           srcX0, srcY0, srcX1, srcY1,
788                           dstX0, dstY0, dstX1, dstY1,
789                           mask, filter);
790}
791