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/arbprogram.h"
28#include "main/arrayobj.h"
29#include "main/blend.h"
30#include "main/depth.h"
31#include "main/enable.h"
32#include "main/enums.h"
33#include "main/fbobject.h"
34#include "main/image.h"
35#include "main/macros.h"
36#include "main/matrix.h"
37#include "main/readpix.h"
38#include "main/scissor.h"
39#include "main/shaderapi.h"
40#include "main/texobj.h"
41#include "main/texenv.h"
42#include "main/teximage.h"
43#include "main/texparam.h"
44#include "main/uniforms.h"
45#include "main/varray.h"
46#include "main/viewport.h"
47#include "swrast/swrast.h"
48#include "drivers/common/meta.h"
49
50static struct gl_texture_object *
51texture_object_from_renderbuffer(struct gl_context *, struct gl_renderbuffer *);
52
53static struct gl_sampler_object *
54setup_sampler(struct gl_context *, struct gl_texture_object *, GLenum target,
55              GLenum filter, GLuint srcLevel);
56
57/** Return offset in bytes of the field within a vertex struct */
58#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
59
60static void
61setup_glsl_blit_framebuffer(struct gl_context *ctx,
62                            struct blit_state *blit,
63                            const struct gl_framebuffer *drawFb,
64                            struct gl_renderbuffer *src_rb,
65                            GLenum target,
66                            bool do_depth)
67{
68   const unsigned texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0);
69
70   /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
71   assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D);
72
73
74   _mesa_meta_setup_vertex_objects(ctx, &blit->VAO, &blit->buf_obj, true,
75                                   2, texcoord_size, 0);
76
77   _mesa_meta_setup_blit_shader(ctx, target, do_depth,
78                                do_depth ? &blit->shaders_with_depth
79                                         : &blit->shaders_without_depth);
80}
81
82/**
83 * Try to do a color or depth glBlitFramebuffer using texturing.
84 *
85 * We can do this when the src renderbuffer is actually a texture, or when the
86 * driver exposes BindRenderbufferTexImage().
87 */
88static bool
89blitframebuffer_texture(struct gl_context *ctx,
90                        const struct gl_framebuffer *readFb,
91                        const struct gl_framebuffer *drawFb,
92                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
93                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
94                        GLenum filter, GLint flipX, GLint flipY,
95                        GLboolean glsl_version, GLboolean do_depth)
96{
97   int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex;
98   const struct gl_renderbuffer_attachment *readAtt =
99      &readFb->Attachment[att_index];
100   struct blit_state *blit = &ctx->Meta->Blit;
101   struct fb_tex_blit_state fb_tex_blit;
102   const GLint dstX = MIN2(dstX0, dstX1);
103   const GLint dstY = MIN2(dstY0, dstY1);
104   const GLint dstW = abs(dstX1 - dstX0);
105   const GLint dstH = abs(dstY1 - dstY0);
106   const int srcW = abs(srcX1 - srcX0);
107   const int srcH = abs(srcY1 - srcY0);
108   struct gl_texture_object *texObj;
109   GLuint srcLevel;
110   GLenum target;
111   struct gl_renderbuffer *rb = readAtt->Renderbuffer;
112   struct temp_texture *meta_temp_texture;
113
114   assert(rb->NumSamples == 0);
115
116   _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit);
117
118   if (readAtt->Texture &&
119       (readAtt->Texture->Target == GL_TEXTURE_2D ||
120        readAtt->Texture->Target == GL_TEXTURE_RECTANGLE)) {
121      /* If there's a texture attached of a type we can handle, then just use
122       * it directly.
123       */
124      srcLevel = readAtt->TextureLevel;
125      texObj = readAtt->Texture;
126   } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) {
127      texObj = texture_object_from_renderbuffer(ctx, rb);
128      if (texObj == NULL)
129         return false;
130
131      fb_tex_blit.temp_tex_obj = texObj;
132
133      srcLevel = 0;
134      if (_mesa_is_winsys_fbo(readFb)) {
135         GLint temp = srcY0;
136         srcY0 = rb->Height - srcY1;
137         srcY1 = rb->Height - temp;
138         flipY = -flipY;
139      }
140   } else {
141      GLenum tex_base_format;
142      /* Fall back to doing a CopyTexSubImage to get the destination
143       * renderbuffer into a texture.
144       */
145      if (ctx->Meta->Blit.no_ctsi_fallback)
146         return false;
147
148      if (do_depth) {
149         meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx);
150         tex_base_format = GL_DEPTH_COMPONENT;
151      } else {
152         meta_temp_texture = _mesa_meta_get_temp_texture(ctx);
153         tex_base_format =
154            _mesa_base_tex_format(ctx, rb->InternalFormat);
155      }
156
157      srcLevel = 0;
158      texObj = meta_temp_texture->tex_obj;
159      if (texObj == NULL) {
160         return false;
161      }
162
163      _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture,
164                                       srcX0, srcY0,
165                                       srcW, srcH,
166                                       tex_base_format,
167                                       filter);
168
169      assert(texObj->Target == meta_temp_texture->Target);
170
171      srcX0 = 0;
172      srcY0 = 0;
173      srcX1 = srcW;
174      srcY1 = srcH;
175   }
176
177   target = texObj->Target;
178   fb_tex_blit.tex_obj = texObj;
179   fb_tex_blit.baseLevelSave = texObj->Attrib.BaseLevel;
180   fb_tex_blit.maxLevelSave = texObj->Attrib.MaxLevel;
181   fb_tex_blit.stencilSamplingSave = texObj->StencilSampling;
182
183   if (glsl_version) {
184      setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, do_depth);
185   }
186   else {
187      _mesa_meta_setup_ff_tnl_for_blit(ctx,
188                                       &ctx->Meta->Blit.VAO,
189                                       &ctx->Meta->Blit.buf_obj,
190                                       2);
191   }
192
193   /*
194     printf("Blit from texture!\n");
195     printf("  srcAtt %p  dstAtt %p\n", readAtt, drawAtt);
196     printf("  srcTex %p  dstText %p\n", texObj, drawAtt->Texture);
197   */
198
199   fb_tex_blit.samp_obj = setup_sampler(ctx, texObj, target, filter, srcLevel);
200
201   if (ctx->Extensions.EXT_texture_sRGB_decode) {
202      /* The GL 4.4 spec, section 18.3.1 ("Blitting Pixel Rectangles") says:
203       *
204       *    "When values are taken from the read buffer, if FRAMEBUFFER_SRGB
205       *     is enabled and the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
206       *     for the framebuffer attachment corresponding to the read buffer
207       *     is SRGB (see section 9.2.3), the red, green, and blue components
208       *     are converted from the non-linear sRGB color space according to
209       *     equation 3.24.
210       *
211       *     When values are written to the draw buffers, blit operations
212       *     bypass most of the fragment pipeline.  The only fragment
213       *     operations which affect a blit are the pixel ownership test,
214       *     the scissor test, and sRGB conversion (see section 17.3.9)."
215       *
216       * ES 3.0 contains nearly the exact same text, but omits the part
217       * about GL_FRAMEBUFFER_SRGB as that doesn't exist in ES.  Mesa
218       * defaults it to on for ES contexts, so we can safely check it.
219       */
220      const bool decode =
221         ctx->Color.sRGBEnabled && _mesa_is_format_srgb(rb->Format);
222
223      _mesa_set_sampler_srgb_decode(ctx, fb_tex_blit.samp_obj,
224                                    decode ? GL_DECODE_EXT
225                                           : GL_SKIP_DECODE_EXT);
226   }
227
228   if (!glsl_version) {
229      _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
230      _mesa_set_enable(ctx, target, GL_TRUE);
231   }
232
233   /* Prepare vertex data (the VBO was previously created and bound) */
234   {
235      struct vertex verts[4];
236      GLfloat s0, t0, s1, t1;
237
238      if (target == GL_TEXTURE_2D) {
239         const struct gl_texture_image *texImage
240            = _mesa_select_tex_image(texObj, target, srcLevel);
241         s0 = srcX0 / (float) texImage->Width;
242         s1 = srcX1 / (float) texImage->Width;
243         t0 = srcY0 / (float) texImage->Height;
244         t1 = srcY1 / (float) texImage->Height;
245      }
246      else {
247         assert(target == GL_TEXTURE_RECTANGLE_ARB);
248         s0 = (float) srcX0;
249         s1 = (float) srcX1;
250         t0 = (float) srcY0;
251         t1 = (float) srcY1;
252      }
253
254      /* Silence valgrind warnings about reading uninitialized stack. */
255      memset(verts, 0, sizeof(verts));
256
257      /* setup vertex positions */
258      verts[0].x = -1.0F * flipX;
259      verts[0].y = -1.0F * flipY;
260      verts[1].x =  1.0F * flipX;
261      verts[1].y = -1.0F * flipY;
262      verts[2].x =  1.0F * flipX;
263      verts[2].y =  1.0F * flipY;
264      verts[3].x = -1.0F * flipX;
265      verts[3].y =  1.0F * flipY;
266
267      verts[0].tex[0] = s0;
268      verts[0].tex[1] = t0;
269      verts[0].tex[2] = readAtt->Zoffset;
270      verts[1].tex[0] = s1;
271      verts[1].tex[1] = t0;
272      verts[1].tex[2] = readAtt->Zoffset;
273      verts[2].tex[0] = s1;
274      verts[2].tex[1] = t1;
275      verts[2].tex[2] = readAtt->Zoffset;
276      verts[3].tex[0] = s0;
277      verts[3].tex[1] = t1;
278      verts[3].tex[2] = readAtt->Zoffset;
279
280      _mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts);
281   }
282
283   /* setup viewport */
284   _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
285   _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth);
286   _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth);
287   _mesa_DepthMask(do_depth);
288   _mesa_DepthFunc(GL_ALWAYS);
289
290   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
291   _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit);
292
293   return true;
294}
295
296void
297_mesa_meta_fb_tex_blit_begin(struct gl_context *ctx,
298                             struct fb_tex_blit_state *blit)
299{
300   /* None of the existing callers preinitialize fb_tex_blit_state to zeros,
301    * and both use stack variables.  If samp_obj_save is not NULL,
302    * _mesa_reference_sampler_object will try to dereference it.  Leaving
303    * random garbage in samp_obj_save can only lead to crashes.
304    *
305    * Since the state isn't persistent across calls, we won't catch ref
306    * counting problems.
307    */
308   blit->samp_obj_save = NULL;
309   _mesa_reference_sampler_object(ctx, &blit->samp_obj_save,
310                                  ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
311   blit->temp_tex_obj = NULL;
312}
313
314void
315_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
316                           struct fb_tex_blit_state *blit)
317{
318   struct gl_texture_object *const texObj =
319      _mesa_get_current_tex_object(ctx, target);
320
321   /* Either there is no temporary texture or the temporary texture is bound. */
322   assert(blit->temp_tex_obj == NULL || blit->temp_tex_obj == texObj);
323
324   /* Restore texture object state, the texture binding will be restored by
325    * _mesa_meta_end().  If the texture is the temporary texture that is about
326    * to be destroyed, don't bother restoring its state.
327    */
328   if (blit->temp_tex_obj == NULL) {
329      /* If the target restricts values for base level or max level, we assume
330       * that the original values were valid.
331       */
332      if (blit->baseLevelSave != texObj->Attrib.BaseLevel)
333         _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
334                                   &blit->baseLevelSave, false);
335
336      if (blit->maxLevelSave != texObj->Attrib.MaxLevel)
337         _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
338                                   &blit->maxLevelSave, false);
339
340      /* If ARB_stencil_texturing is not supported, the mode won't have changed. */
341      if (texObj->StencilSampling != blit->stencilSamplingSave) {
342         /* GLint so the compiler won't complain about type signedness mismatch
343          * in the call to _mesa_texture_parameteriv below.
344          */
345         const GLint param = blit->stencilSamplingSave ?
346            GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
347
348         _mesa_texture_parameteriv(ctx, texObj, GL_DEPTH_STENCIL_TEXTURE_MODE,
349                                   &param, false);
350      }
351   }
352
353   _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, blit->samp_obj_save);
354   _mesa_reference_sampler_object(ctx, &blit->samp_obj_save, NULL);
355   _mesa_reference_sampler_object(ctx, &blit->samp_obj, NULL);
356   _mesa_delete_nameless_texture(ctx, blit->temp_tex_obj);
357}
358
359static struct gl_texture_object *
360texture_object_from_renderbuffer(struct gl_context *ctx,
361                                 struct gl_renderbuffer *rb)
362{
363   struct gl_texture_image *texImage;
364   struct gl_texture_object *texObj;
365   const GLenum target = GL_TEXTURE_2D;
366
367   texObj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, target);
368   texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
369
370   if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
371      _mesa_delete_nameless_texture(ctx, texObj);
372      return NULL;
373   }
374
375   if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
376      rb->NeedsFinishRenderTexture = true;
377      ctx->Driver.FinishRenderTexture(ctx, rb);
378   }
379
380   return texObj;
381}
382
383static struct gl_sampler_object *
384setup_sampler(struct gl_context *ctx, struct gl_texture_object *texObj,
385              GLenum target, GLenum filter, GLuint srcLevel)
386{
387   struct gl_sampler_object *samp_obj =
388      ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
389
390   if (samp_obj == NULL)
391      return NULL;
392
393   _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj);
394   _mesa_set_sampler_filters(ctx, samp_obj, filter, filter);
395   _mesa_set_sampler_wrap(ctx, samp_obj, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
396                          samp_obj->Attrib.WrapR);
397
398   /* Prepare src texture state */
399   _mesa_bind_texture(ctx, target, texObj);
400   if (target != GL_TEXTURE_RECTANGLE_ARB) {
401      _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
402                                (GLint *) &srcLevel, false);
403      _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
404                                (GLint *) &srcLevel, false);
405   }
406
407   return samp_obj;
408}
409
410/**
411 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
412 * of texture mapping and polygon rendering.
413 */
414GLbitfield
415_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
416                           const struct gl_framebuffer *readFb,
417                           const struct gl_framebuffer *drawFb,
418                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
419                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
420                           GLbitfield mask, GLenum filter)
421{
422   const GLint dstW = abs(dstX1 - dstX0);
423   const GLint dstH = abs(dstY1 - dstY0);
424   const GLint dstFlipX = (dstX1 - dstX0) / dstW;
425   const GLint dstFlipY = (dstY1 - dstY0) / dstH;
426
427   struct {
428      GLint srcX0, srcY0, srcX1, srcY1;
429      GLint dstX0, dstY0, dstX1, dstY1;
430   } clip = {
431      srcX0, srcY0, srcX1, srcY1,
432      dstX0, dstY0, dstX1, dstY1
433   };
434
435   const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
436                                      ctx->Extensions.ARB_fragment_shader;
437
438   /* Multisample blit is not supported. */
439   if (readFb->Visual.samples > 0)
440      return mask;
441
442   /* Clip a copy of the blit coordinates. If these differ from the input
443    * coordinates, then we'll set the scissor.
444    */
445   if (!_mesa_clip_blit(ctx, readFb, drawFb,
446                        &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
447                        &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
448      /* clipped/scissored everything away */
449      return 0;
450   }
451
452   /* Only scissor and FRAMEBUFFER_SRGB affect blit.  Leave sRGB alone, but
453    * save restore scissor as we'll set a custom scissor if necessary.
454    */
455   _mesa_meta_begin(ctx, MESA_META_ALL &
456                         ~(MESA_META_DRAW_BUFFERS |
457                           MESA_META_FRAMEBUFFER_SRGB));
458
459   /* Dithering shouldn't be performed for glBlitFramebuffer */
460   _mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
461
462   /* If the clipping earlier changed the destination rect at all, then
463    * enable the scissor to clip to it.
464    */
465   if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 ||
466       clip.dstX1 != dstX1 || clip.dstY1 != dstY1) {
467      _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
468      _mesa_Scissor(MIN2(clip.dstX0, clip.dstX1),
469                    MIN2(clip.dstY0, clip.dstY1),
470                    abs(clip.dstX0 - clip.dstX1),
471                    abs(clip.dstY0 - clip.dstY1));
472   }
473
474   /* Try faster, direct texture approach first */
475   if (mask & GL_COLOR_BUFFER_BIT) {
476      if (blitframebuffer_texture(ctx, readFb, drawFb,
477                                  srcX0, srcY0, srcX1, srcY1,
478                                  dstX0, dstY0, dstX1, dstY1,
479                                  filter, dstFlipX, dstFlipY,
480                                  use_glsl_version, false)) {
481         mask &= ~GL_COLOR_BUFFER_BIT;
482      }
483   }
484
485   if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) {
486      if (blitframebuffer_texture(ctx, readFb, drawFb,
487                                  srcX0, srcY0, srcX1, srcY1,
488                                  dstX0, dstY0, dstX1, dstY1,
489                                  filter, dstFlipX, dstFlipY,
490                                  use_glsl_version, true)) {
491         mask &= ~GL_DEPTH_BUFFER_BIT;
492      }
493   }
494
495   if (mask & GL_STENCIL_BUFFER_BIT) {
496      /* XXX can't easily do stencil */
497   }
498
499   _mesa_meta_end(ctx);
500
501   return mask;
502}
503
504void
505_mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit)
506{
507   if (blit->VAO) {
508      _mesa_DeleteVertexArrays(1, &blit->VAO);
509      blit->VAO = 0;
510      _mesa_reference_buffer_object(ctx, &blit->buf_obj, NULL);
511   }
512
513   _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_with_depth);
514   _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_without_depth);
515
516   if (blit->depthTex.tex_obj != NULL) {
517      _mesa_delete_nameless_texture(ctx, blit->depthTex.tex_obj);
518      blit->depthTex.tex_obj = NULL;
519   }
520}
521
522void
523_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx,
524                                      struct gl_framebuffer *readFb,
525                                      struct gl_framebuffer *drawFb,
526                                      GLint srcX0, GLint srcY0,
527                                      GLint srcX1, GLint srcY1,
528                                      GLint dstX0, GLint dstY0,
529                                      GLint dstX1, GLint dstY1,
530                                      GLbitfield mask, GLenum filter)
531{
532   mask = _mesa_meta_BlitFramebuffer(ctx, readFb, drawFb,
533                                     srcX0, srcY0, srcX1, srcY1,
534                                     dstX0, dstY0, dstX1, dstY1,
535                                     mask, filter);
536   if (mask == 0x0)
537      return;
538
539   _swrast_BlitFramebuffer(ctx, readFb, drawFb,
540                           srcX0, srcY0, srcX1, srcY1,
541                           dstX0, dstY0, dstX1, dstY1,
542                           mask, filter);
543}
544