blit.c revision 848b8605
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5 * Copyright (C) 1999-2013  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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/*
27 * glBlitFramebuffer functions.
28 */
29
30#include <stdbool.h>
31
32#include "context.h"
33#include "enums.h"
34#include "blit.h"
35#include "fbobject.h"
36#include "glformats.h"
37#include "mtypes.h"
38#include "state.h"
39
40
41/** Set this to 1 to debug/log glBlitFramebuffer() calls */
42#define DEBUG_BLIT 0
43
44
45
46static const struct gl_renderbuffer_attachment *
47find_attachment(const struct gl_framebuffer *fb,
48                const struct gl_renderbuffer *rb)
49{
50   GLuint i;
51   for (i = 0; i < Elements(fb->Attachment); i++) {
52      if (fb->Attachment[i].Renderbuffer == rb)
53         return &fb->Attachment[i];
54   }
55   return NULL;
56}
57
58
59/**
60 * Helper function for checking if the datatypes of color buffers are
61 * compatible for glBlitFramebuffer.  From the 3.1 spec, page 198:
62 *
63 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
64 *  and any of the following conditions hold:
65 *   - The read buffer contains fixed-point or floating-point values and any
66 *     draw buffer contains neither fixed-point nor floating-point values.
67 *   - The read buffer contains unsigned integer values and any draw buffer
68 *     does not contain unsigned integer values.
69 *   - The read buffer contains signed integer values and any draw buffer
70 *     does not contain signed integer values."
71 */
72static GLboolean
73compatible_color_datatypes(mesa_format srcFormat, mesa_format dstFormat)
74{
75   GLenum srcType = _mesa_get_format_datatype(srcFormat);
76   GLenum dstType = _mesa_get_format_datatype(dstFormat);
77
78   if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
79      assert(srcType == GL_UNSIGNED_NORMALIZED ||
80             srcType == GL_SIGNED_NORMALIZED ||
81             srcType == GL_FLOAT);
82      /* Boil any of those types down to GL_FLOAT */
83      srcType = GL_FLOAT;
84   }
85
86   if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
87      assert(dstType == GL_UNSIGNED_NORMALIZED ||
88             dstType == GL_SIGNED_NORMALIZED ||
89             dstType == GL_FLOAT);
90      /* Boil any of those types down to GL_FLOAT */
91      dstType = GL_FLOAT;
92   }
93
94   return srcType == dstType;
95}
96
97
98static GLboolean
99compatible_resolve_formats(const struct gl_renderbuffer *readRb,
100                           const struct gl_renderbuffer *drawRb)
101{
102   GLenum readFormat, drawFormat;
103
104   /* The simple case where we know the backing Mesa formats are the same.
105    */
106   if (_mesa_get_srgb_format_linear(readRb->Format) ==
107       _mesa_get_srgb_format_linear(drawRb->Format)) {
108      return GL_TRUE;
109   }
110
111   /* The Mesa formats are different, so we must check whether the internal
112    * formats are compatible.
113    *
114    * Under some circumstances, the user may request e.g. two GL_RGBA8
115    * textures and get two entirely different Mesa formats like RGBA8888 and
116    * ARGB8888. Drivers behaving like that should be able to cope with
117    * non-matching formats by themselves, because it's not the user's fault.
118    *
119    * Blits between linear and sRGB formats are also allowed.
120    */
121   readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
122   drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
123   readFormat = _mesa_get_linear_internalformat(readFormat);
124   drawFormat = _mesa_get_linear_internalformat(drawFormat);
125
126   if (readFormat == drawFormat) {
127      return GL_TRUE;
128   }
129
130   return GL_FALSE;
131}
132
133
134static GLboolean
135is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
136{
137   switch (filter) {
138   case GL_NEAREST:
139   case GL_LINEAR:
140      return true;
141   case GL_SCALED_RESOLVE_FASTEST_EXT:
142   case GL_SCALED_RESOLVE_NICEST_EXT:
143      return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
144   default:
145      return false;
146   }
147}
148
149
150/**
151 * Blit rectangular region, optionally from one framebuffer to another.
152 *
153 * Note, if the src buffer is multisampled and the dest is not, this is
154 * when the samples must be resolved to a single color.
155 */
156void GLAPIENTRY
157_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
158                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
159                         GLbitfield mask, GLenum filter)
160{
161   const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
162                                     GL_DEPTH_BUFFER_BIT |
163                                     GL_STENCIL_BUFFER_BIT);
164   const struct gl_framebuffer *readFb, *drawFb;
165   GET_CURRENT_CONTEXT(ctx);
166
167   FLUSH_VERTICES(ctx, 0);
168
169   if (MESA_VERBOSE & VERBOSE_API)
170      _mesa_debug(ctx,
171                  "glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d, 0x%x, %s)\n",
172                  srcX0, srcY0, srcX1, srcY1,
173                  dstX0, dstY0, dstX1, dstY1,
174                  mask, _mesa_lookup_enum_by_nr(filter));
175
176   if (ctx->NewState) {
177      _mesa_update_state(ctx);
178   }
179
180   readFb = ctx->ReadBuffer;
181   drawFb = ctx->DrawBuffer;
182
183   if (!readFb || !drawFb) {
184      /* This will normally never happen but someday we may want to
185       * support MakeCurrent() with no drawables.
186       */
187      return;
188   }
189
190   /* check for complete framebuffers */
191   if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
192       readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
193      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
194                  "glBlitFramebufferEXT(incomplete draw/read buffers)");
195      return;
196   }
197
198   if (!is_valid_blit_filter(ctx, filter)) {
199      _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
200                  _mesa_lookup_enum_by_nr(filter));
201      return;
202   }
203
204   if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
205        filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
206        (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
207      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)",
208                  _mesa_lookup_enum_by_nr(filter));
209      return;
210   }
211
212   if (mask & ~legalMaskBits) {
213      _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
214      return;
215   }
216
217   /* depth/stencil must be blitted with nearest filtering */
218   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
219        && filter != GL_NEAREST) {
220      _mesa_error(ctx, GL_INVALID_OPERATION,
221             "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
222      return;
223   }
224
225   /* get color read/draw renderbuffers */
226   if (mask & GL_COLOR_BUFFER_BIT) {
227      const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
228      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
229      const struct gl_renderbuffer *colorDrawRb = NULL;
230      GLuint i;
231
232      /* From the EXT_framebuffer_object spec:
233       *
234       *     "If a buffer is specified in <mask> and does not exist in both
235       *     the read and draw framebuffers, the corresponding bit is silently
236       *     ignored."
237       */
238      if (!colorReadRb || numColorDrawBuffers == 0) {
239         mask &= ~GL_COLOR_BUFFER_BIT;
240      }
241      else {
242         for (i = 0; i < numColorDrawBuffers; i++) {
243            colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
244            if (!colorDrawRb)
245               continue;
246
247            /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
248             * ES 3.0.1 spec says:
249             *
250             *     "If the source and destination buffers are identical, an
251             *     INVALID_OPERATION error is generated. Different mipmap
252             *     levels of a texture, different layers of a three-
253             *     dimensional texture or two-dimensional array texture, and
254             *     different faces of a cube map texture do not constitute
255             *     identical buffers."
256             */
257            if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
258               _mesa_error(ctx, GL_INVALID_OPERATION,
259                           "glBlitFramebuffer(source and destination color "
260                           "buffer cannot be the same)");
261               return;
262            }
263
264            if (!compatible_color_datatypes(colorReadRb->Format,
265                                            colorDrawRb->Format)) {
266               _mesa_error(ctx, GL_INVALID_OPERATION,
267                           "glBlitFramebufferEXT(color buffer datatypes mismatch)");
268               return;
269            }
270            /* extra checks for multisample copies... */
271            if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
272               /* color formats must match */
273               if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
274                  _mesa_error(ctx, GL_INVALID_OPERATION,
275                         "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
276                  return;
277               }
278            }
279         }
280         if (filter != GL_NEAREST) {
281            /* From EXT_framebuffer_multisample_blit_scaled specification:
282             * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
283             * if filter is not NEAREST and read buffer contains integer data."
284             */
285            GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
286            if (type == GL_INT || type == GL_UNSIGNED_INT) {
287               _mesa_error(ctx, GL_INVALID_OPERATION,
288                           "glBlitFramebufferEXT(integer color type)");
289               return;
290            }
291         }
292      }
293   }
294
295   if (mask & GL_STENCIL_BUFFER_BIT) {
296      struct gl_renderbuffer *readRb =
297         readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
298      struct gl_renderbuffer *drawRb =
299         drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
300
301      /* From the EXT_framebuffer_object spec:
302       *
303       *     "If a buffer is specified in <mask> and does not exist in both
304       *     the read and draw framebuffers, the corresponding bit is silently
305       *     ignored."
306       */
307      if ((readRb == NULL) || (drawRb == NULL)) {
308	 mask &= ~GL_STENCIL_BUFFER_BIT;
309      }
310      else {
311         int read_z_bits, draw_z_bits;
312
313         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
314            _mesa_error(ctx, GL_INVALID_OPERATION,
315                        "glBlitFramebuffer(source and destination stencil "
316                        "buffer cannot be the same)");
317            return;
318         }
319
320         if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
321             _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
322            /* There is no need to check the stencil datatype here, because
323             * there is only one: GL_UNSIGNED_INT.
324             */
325            _mesa_error(ctx, GL_INVALID_OPERATION,
326                        "glBlitFramebuffer(stencil attachment format mismatch)");
327            return;
328         }
329
330         read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
331         draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
332
333         /* If both buffers also have depth data, the depth formats must match
334          * as well.  If one doesn't have depth, it's not blitted, so we should
335          * ignore the depth format check.
336          */
337         if (read_z_bits > 0 && draw_z_bits > 0 &&
338             (read_z_bits != draw_z_bits ||
339              _mesa_get_format_datatype(readRb->Format) !=
340              _mesa_get_format_datatype(drawRb->Format))) {
341
342            _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
343                        "(stencil attachment depth format mismatch)");
344            return;
345         }
346      }
347   }
348
349   if (mask & GL_DEPTH_BUFFER_BIT) {
350      struct gl_renderbuffer *readRb =
351         readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
352      struct gl_renderbuffer *drawRb =
353         drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
354
355      /* From the EXT_framebuffer_object spec:
356       *
357       *     "If a buffer is specified in <mask> and does not exist in both
358       *     the read and draw framebuffers, the corresponding bit is silently
359       *     ignored."
360       */
361      if ((readRb == NULL) || (drawRb == NULL)) {
362	 mask &= ~GL_DEPTH_BUFFER_BIT;
363      }
364      else {
365         int read_s_bit, draw_s_bit;
366
367         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
368            _mesa_error(ctx, GL_INVALID_OPERATION,
369                        "glBlitFramebuffer(source and destination depth "
370                        "buffer cannot be the same)");
371            return;
372         }
373
374         if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
375              _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
376             (_mesa_get_format_datatype(readRb->Format) !=
377              _mesa_get_format_datatype(drawRb->Format))) {
378            _mesa_error(ctx, GL_INVALID_OPERATION,
379                        "glBlitFramebuffer(depth attachment format mismatch)");
380            return;
381         }
382
383         read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
384         draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
385
386         /* If both buffers also have stencil data, the stencil formats must
387          * match as well.  If one doesn't have stencil, it's not blitted, so
388          * we should ignore the stencil format check.
389          */
390         if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
391            _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
392                        "(depth attachment stencil bits mismatch)");
393            return;
394         }
395      }
396   }
397
398
399   if (_mesa_is_gles3(ctx)) {
400      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
401       * 3.0.1 spec says:
402       *
403       *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
404       *     an INVALID_OPERATION error is generated."
405       */
406      if (drawFb->Visual.samples > 0) {
407         _mesa_error(ctx, GL_INVALID_OPERATION,
408                     "glBlitFramebuffer(destination samples must be 0)");
409         return;
410      }
411
412      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
413       * 3.0.1 spec says:
414       *
415       *     "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
416       *     no copy is performed and an INVALID_OPERATION error is generated
417       *     if the formats of the read and draw framebuffers are not
418       *     identical or if the source and destination rectangles are not
419       *     defined with the same (X0, Y0) and (X1, Y1) bounds."
420       *
421       * The format check was made above because desktop OpenGL has the same
422       * requirement.
423       */
424      if (readFb->Visual.samples > 0
425          && (srcX0 != dstX0 || srcY0 != dstY0
426              || srcX1 != dstX1 || srcY1 != dstY1)) {
427         _mesa_error(ctx, GL_INVALID_OPERATION,
428                     "glBlitFramebuffer(bad src/dst multisample region)");
429         return;
430      }
431   } else {
432      if (readFb->Visual.samples > 0 &&
433          drawFb->Visual.samples > 0 &&
434          readFb->Visual.samples != drawFb->Visual.samples) {
435         _mesa_error(ctx, GL_INVALID_OPERATION,
436                     "glBlitFramebufferEXT(mismatched samples)");
437         return;
438      }
439
440      /* extra checks for multisample copies... */
441      if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
442          (filter == GL_NEAREST || filter == GL_LINEAR)) {
443         /* src and dest region sizes must be the same */
444         if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
445             abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
446            _mesa_error(ctx, GL_INVALID_OPERATION,
447                        "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
448            return;
449         }
450      }
451   }
452
453   /* Debug code */
454   if (DEBUG_BLIT) {
455      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
456      const struct gl_renderbuffer *colorDrawRb = NULL;
457      GLuint i = 0;
458
459      printf("glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d,"
460	     " 0x%x, 0x%x)\n",
461	     srcX0, srcY0, srcX1, srcY1,
462	     dstX0, dstY0, dstX1, dstY1,
463	     mask, filter);
464      if (colorReadRb) {
465         const struct gl_renderbuffer_attachment *att;
466
467         att = find_attachment(readFb, colorReadRb);
468         printf("  Src FBO %u  RB %u (%dx%d)  ",
469		readFb->Name, colorReadRb->Name,
470		colorReadRb->Width, colorReadRb->Height);
471         if (att && att->Texture) {
472            printf("Tex %u  tgt 0x%x  level %u  face %u",
473		   att->Texture->Name,
474		   att->Texture->Target,
475		   att->TextureLevel,
476		   att->CubeMapFace);
477         }
478         printf("\n");
479
480         /* Print all active color render buffers */
481         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
482            colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
483            if (!colorDrawRb)
484               continue;
485
486            att = find_attachment(drawFb, colorDrawRb);
487            printf("  Dst FBO %u  RB %u (%dx%d)  ",
488		   drawFb->Name, colorDrawRb->Name,
489		   colorDrawRb->Width, colorDrawRb->Height);
490            if (att && att->Texture) {
491               printf("Tex %u  tgt 0x%x  level %u  face %u",
492		      att->Texture->Name,
493		      att->Texture->Target,
494		      att->TextureLevel,
495		      att->CubeMapFace);
496            }
497            printf("\n");
498         }
499      }
500   }
501
502   if (!mask ||
503       (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
504       (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
505      return;
506   }
507
508   ASSERT(ctx->Driver.BlitFramebuffer);
509   ctx->Driver.BlitFramebuffer(ctx,
510                               srcX0, srcY0, srcX1, srcY1,
511                               dstX0, dstY0, dstX1, dstY1,
512                               mask, filter);
513}
514