mesa: add support for memory object creation/import/delete
[mesa.git] / src / mesa / main / blit.c
index fac97245082246b0bd5739066a1da981abd6c540..8bb3ba328a32c03c530ea9cca5cf197343ff4ea7 100644 (file)
@@ -37,6 +37,7 @@
 #include "framebuffer.h"
 #include "glformats.h"
 #include "mtypes.h"
+#include "macros.h"
 #include "state.h"
 
 
@@ -58,6 +59,31 @@ find_attachment(const struct gl_framebuffer *fb,
 }
 
 
+/**
+ * \return true if two regions overlap, false otherwise
+ */
+bool
+_mesa_regions_overlap(int srcX0, int srcY0,
+                      int srcX1, int srcY1,
+                      int dstX0, int dstY0,
+                      int dstX1, int dstY1)
+{
+   if (MAX2(srcX0, srcX1) <= MIN2(dstX0, dstX1))
+      return false; /* dst completely right of src */
+
+   if (MAX2(dstX0, dstX1) <= MIN2(srcX0, srcX1))
+      return false; /* dst completely left of src */
+
+   if (MAX2(srcY0, srcY1) <= MIN2(dstY0, dstY1))
+      return false; /* dst completely above src */
+
+   if (MAX2(dstY0, dstY1) <= MIN2(srcY0, srcY1))
+      return false; /* dst completely below src */
+
+   return true; /* some overlap */
+}
+
+
 /**
  * Helper function for checking if the datatypes of color buffers are
  * compatible for glBlitFramebuffer.  From the 3.1 spec, page 198:
@@ -103,20 +129,22 @@ compatible_resolve_formats(const struct gl_renderbuffer *readRb,
 {
    GLenum readFormat, drawFormat;
 
-   /* The simple case where we know the backing Mesa formats are the same.
-    */
-   if (_mesa_get_srgb_format_linear(readRb->Format) ==
-       _mesa_get_srgb_format_linear(drawRb->Format)) {
-      return GL_TRUE;
-   }
-
-   /* The Mesa formats are different, so we must check whether the internal
-    * formats are compatible.
+   /* This checks whether the internal formats are compatible rather than the
+    * Mesa format for two reasons:
     *
-    * Under some circumstances, the user may request e.g. two GL_RGBA8
-    * textures and get two entirely different Mesa formats like RGBA8888 and
-    * ARGB8888. Drivers behaving like that should be able to cope with
-    * non-matching formats by themselves, because it's not the user's fault.
+    * • Under some circumstances, the user may request e.g. two GL_RGBA8
+    *   textures and get two entirely different Mesa formats like RGBA8888 and
+    *   ARGB8888. Drivers behaving like that should be able to cope with
+    *   non-matching formats by themselves, because it's not the user's fault.
+    *
+    * • Picking two different internal formats can end up with the same Mesa
+    *   format. For example the driver might be simulating GL_RGB textures
+    *   with GL_RGBA internally and in that case both internal formats would
+    *   end up with RGBA8888.
+    *
+    * This function is used to generate a GL error according to the spec so in
+    * both cases we want to be looking at the application-level format, which
+    * is InternalFormat.
     *
     * Blits between linear and sRGB formats are also allowed.
     */
@@ -149,74 +177,290 @@ is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
 }
 
 
-void
-_mesa_blit_framebuffer(struct gl_context *ctx,
-                       struct gl_framebuffer *readFb,
-                       struct gl_framebuffer *drawFb,
-                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                       GLbitfield mask, GLenum filter, const char *func)
+static bool
+validate_color_buffer(struct gl_context *ctx, struct gl_framebuffer *readFb,
+                      struct gl_framebuffer *drawFb, GLenum filter,
+                      const char *func)
 {
-   const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
-                                     GL_DEPTH_BUFFER_BIT |
-                                     GL_STENCIL_BUFFER_BIT);
+   const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
+   const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
+   const struct gl_renderbuffer *colorDrawRb = NULL;
+   GLuint i;
 
-   FLUSH_VERTICES(ctx, 0);
+   for (i = 0; i < numColorDrawBuffers; i++) {
+      colorDrawRb = drawFb->_ColorDrawBuffers[i];
+      if (!colorDrawRb)
+         continue;
 
-   /* Update completeness status of readFb and drawFb. */
-   _mesa_update_framebuffer(ctx, readFb, drawFb);
+      /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
+       * ES 3.0.1 spec says:
+       *
+       *     "If the source and destination buffers are identical, an
+       *     INVALID_OPERATION error is generated. Different mipmap levels of a
+       *     texture, different layers of a three- dimensional texture or
+       *     two-dimensional array texture, and different faces of a cube map
+       *     texture do not constitute identical buffers."
+       */
+      if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(source and destination color buffer cannot be the "
+                     "same)", func);
+         return false;
+      }
 
-   /* Make sure drawFb has an initialized bounding box. */
-   _mesa_update_draw_buffer_bounds(ctx, drawFb);
+      if (!compatible_color_datatypes(colorReadRb->Format,
+                                      colorDrawRb->Format)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(color buffer datatypes mismatch)", func);
+         return false;
+      }
 
-   if (!readFb || !drawFb) {
-      /* This will normally never happen but someday we may want to
-       * support MakeCurrent() with no drawables.
+      /* extra checks for multisample copies... */
+      if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
+         /* color formats must match on GLES. This isn't checked on desktop GL
+          * because the GL 4.4 spec was changed to allow it.  In the section
+          * entitled “Changes in the released
+          * Specification of July 22, 2013” it says:
+          *
+          * “Relax BlitFramebuffer in section 18.3.1 so that format conversion
+          * can take place during multisample blits, since drivers already
+          * allow this and some apps depend on it.”
+          */
+         if (_mesa_is_gles(ctx) &&
+             !compatible_resolve_formats(colorReadRb, colorDrawRb)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "%s(bad src/dst multisample pixel formats)", func);
+            return false;
+         }
+      }
+
+   }
+
+   if (filter != GL_NEAREST) {
+      /* From EXT_framebuffer_multisample_blit_scaled specification:
+       * "Calling BlitFramebuffer will result in an INVALID_OPERATION error if
+       * filter is not NEAREST and read buffer contains integer data."
        */
-      return;
+      GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
+      if (type == GL_INT || type == GL_UNSIGNED_INT) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(integer color type)", func);
+         return false;
+      }
    }
+   return true;
+}
 
-   /* check for complete framebuffers */
-   if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
-       readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
-                  "%s(incomplete draw/read buffers)", func);
-      return;
+
+static bool
+validate_stencil_buffer(struct gl_context *ctx, struct gl_framebuffer *readFb,
+                        struct gl_framebuffer *drawFb, const char *func)
+{
+   struct gl_renderbuffer *readRb =
+      readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
+   struct gl_renderbuffer *drawRb =
+      drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
+   int read_z_bits, draw_z_bits;
+
+   if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(source and destination stencil buffer cannot be the "
+                  "same)", func);
+      return false;
    }
 
-   if (!is_valid_blit_filter(ctx, filter)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
-                  _mesa_lookup_enum_by_nr(filter));
-      return;
+   if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
+       _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
+      /* There is no need to check the stencil datatype here, because
+       * there is only one: GL_UNSIGNED_INT.
+       */
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(stencil attachment format mismatch)", func);
+      return false;
    }
 
-   if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
-        filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
-        (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
-                  _mesa_lookup_enum_by_nr(filter));
-      return;
+   read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
+   draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
+
+   /* If both buffers also have depth data, the depth formats must match
+    * as well.  If one doesn't have depth, it's not blitted, so we should
+    * ignore the depth format check.
+    */
+   if (read_z_bits > 0 && draw_z_bits > 0 &&
+       (read_z_bits != draw_z_bits ||
+        _mesa_get_format_datatype(readRb->Format) !=
+        _mesa_get_format_datatype(drawRb->Format))) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(stencil attachment depth format mismatch)", func);
+      return false;
    }
+   return true;
+}
 
-   if (mask & ~legalMaskBits) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
-      return;
+
+static bool
+validate_depth_buffer(struct gl_context *ctx, struct gl_framebuffer *readFb,
+                      struct gl_framebuffer *drawFb, const char *func)
+{
+   struct gl_renderbuffer *readRb =
+      readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
+   struct gl_renderbuffer *drawRb =
+      drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
+   int read_s_bit, draw_s_bit;
+
+   if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(source and destination depth buffer cannot be the same)",
+                  func);
+      return false;
    }
 
-   /* depth/stencil must be blitted with nearest filtering */
-   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
-        && filter != GL_NEAREST) {
+   if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
+        _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
+       (_mesa_get_format_datatype(readRb->Format) !=
+        _mesa_get_format_datatype(drawRb->Format))) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
-             "%s(depth/stencil requires GL_NEAREST filter)", func);
+                  "%s(depth attachment format mismatch)", func);
+      return false;
+   }
+
+   read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
+   draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
+
+   /* If both buffers also have stencil data, the stencil formats must match as
+    * well.  If one doesn't have stencil, it's not blitted, so we should ignore
+    * the stencil format check.
+    */
+   if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(depth attachment stencil bits mismatch)", func);
+      return false;
+   }
+   return true;
+}
+
+
+static ALWAYS_INLINE void
+blit_framebuffer(struct gl_context *ctx,
+                 struct gl_framebuffer *readFb, struct gl_framebuffer *drawFb,
+                 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                 GLbitfield mask, GLenum filter, bool no_error, const char *func)
+{
+   FLUSH_VERTICES(ctx, 0);
+
+   if (!readFb || !drawFb) {
+      /* This will normally never happen but someday we may want to
+       * support MakeCurrent() with no drawables.
+       */
       return;
    }
 
+   /* Update completeness status of readFb and drawFb. */
+   _mesa_update_framebuffer(ctx, readFb, drawFb);
+
+   /* Make sure drawFb has an initialized bounding box. */
+   _mesa_update_draw_buffer_bounds(ctx, drawFb);
+
+   if (!no_error) {
+      const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
+                                        GL_DEPTH_BUFFER_BIT |
+                                        GL_STENCIL_BUFFER_BIT);
+
+      /* check for complete framebuffers */
+      if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+          readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                     "%s(incomplete draw/read buffers)", func);
+         return;
+      }
+
+      if (!is_valid_blit_filter(ctx, filter)) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
+                     _mesa_enum_to_string(filter));
+         return;
+      }
+
+      if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
+           filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
+           (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
+                     _mesa_enum_to_string(filter));
+         return;
+      }
+
+      if (mask & ~legalMaskBits) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
+         return;
+      }
+
+      /* depth/stencil must be blitted with nearest filtering */
+      if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+           && filter != GL_NEAREST) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                "%s(depth/stencil requires GL_NEAREST filter)", func);
+         return;
+      }
+
+      if (_mesa_is_gles3(ctx)) {
+         /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
+          * 3.0.1 spec says:
+          *
+          *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than
+          *     zero, an INVALID_OPERATION error is generated."
+          */
+         if (drawFb->Visual.samples > 0) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "%s(destination samples must be 0)", func);
+            return;
+         }
+
+         /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
+          * 3.0.1 spec says:
+          *
+          *     "If SAMPLE_BUFFERS for the read framebuffer is greater than
+          *     zero, no copy is performed and an INVALID_OPERATION error is
+          *     generated if the formats of the read and draw framebuffers are
+          *     not identical or if the source and destination rectangles are
+          *     not defined with the same (X0, Y0) and (X1, Y1) bounds."
+          *
+          * The format check was made above because desktop OpenGL has the same
+          * requirement.
+          */
+         if (readFb->Visual.samples > 0
+             && (srcX0 != dstX0 || srcY0 != dstY0
+                 || srcX1 != dstX1 || srcY1 != dstY1)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "%s(bad src/dst multisample region)", func);
+            return;
+         }
+      } else {
+         if (readFb->Visual.samples > 0 &&
+             drawFb->Visual.samples > 0 &&
+             readFb->Visual.samples != drawFb->Visual.samples) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "%s(mismatched samples)", func);
+            return;
+         }
+
+         /* extra checks for multisample copies... */
+         if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
+             (filter == GL_NEAREST || filter == GL_LINEAR)) {
+            /* src and dest region sizes must be the same */
+            if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
+                abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
+               _mesa_error(ctx, GL_INVALID_OPERATION,
+                           "%s(bad src/dst multisample region sizes)", func);
+               return;
+            }
+         }
+      }
+   }
+
    /* get color read/draw renderbuffers */
    if (mask & GL_COLOR_BUFFER_BIT) {
       const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
       const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
-      const struct gl_renderbuffer *colorDrawRb = NULL;
-      GLuint i;
 
       /* From the EXT_framebuffer_object spec:
        *
@@ -226,58 +470,9 @@ _mesa_blit_framebuffer(struct gl_context *ctx,
        */
       if (!colorReadRb || numColorDrawBuffers == 0) {
          mask &= ~GL_COLOR_BUFFER_BIT;
-      }
-      else {
-         for (i = 0; i < numColorDrawBuffers; i++) {
-            colorDrawRb = drawFb->_ColorDrawBuffers[i];
-            if (!colorDrawRb)
-               continue;
-
-            /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
-             * ES 3.0.1 spec says:
-             *
-             *     "If the source and destination buffers are identical, an
-             *     INVALID_OPERATION error is generated. Different mipmap
-             *     levels of a texture, different layers of a three-
-             *     dimensional texture or two-dimensional array texture, and
-             *     different faces of a cube map texture do not constitute
-             *     identical buffers."
-             */
-            if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
-               _mesa_error(ctx, GL_INVALID_OPERATION,
-                           "%s(source and destination color "
-                           "buffer cannot be the same)", func);
-               return;
-            }
-
-            if (!compatible_color_datatypes(colorReadRb->Format,
-                                            colorDrawRb->Format)) {
-               _mesa_error(ctx, GL_INVALID_OPERATION,
-                           "%s(color buffer datatypes mismatch)", func);
-               return;
-            }
-            /* extra checks for multisample copies... */
-            if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
-               /* color formats must match */
-               if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
-                  _mesa_error(ctx, GL_INVALID_OPERATION,
-                         "%s(bad src/dst multisample pixel formats)", func);
-                  return;
-               }
-            }
-         }
-         if (filter != GL_NEAREST) {
-            /* From EXT_framebuffer_multisample_blit_scaled specification:
-             * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
-             * if filter is not NEAREST and read buffer contains integer data."
-             */
-            GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
-            if (type == GL_INT || type == GL_UNSIGNED_INT) {
-               _mesa_error(ctx, GL_INVALID_OPERATION,
-                           "%s(integer color type)", func);
-               return;
-            }
-         }
+      } else if (!no_error) {
+         if (!validate_color_buffer(ctx, readFb, drawFb, filter, func))
+            return;
       }
    }
 
@@ -295,43 +490,9 @@ _mesa_blit_framebuffer(struct gl_context *ctx,
        */
       if ((readRb == NULL) || (drawRb == NULL)) {
          mask &= ~GL_STENCIL_BUFFER_BIT;
-      }
-      else {
-         int read_z_bits, draw_z_bits;
-
-         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "%s(source and destination stencil "
-                        "buffer cannot be the same)", func);
-            return;
-         }
-
-         if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
-             _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
-            /* There is no need to check the stencil datatype here, because
-             * there is only one: GL_UNSIGNED_INT.
-             */
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "%s(stencil attachment format mismatch)", func);
+      } else if (!no_error) {
+         if (!validate_stencil_buffer(ctx, readFb, drawFb, func))
             return;
-         }
-
-         read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
-         draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
-
-         /* If both buffers also have depth data, the depth formats must match
-          * as well.  If one doesn't have depth, it's not blitted, so we should
-          * ignore the depth format check.
-          */
-         if (read_z_bits > 0 && draw_z_bits > 0 &&
-             (read_z_bits != draw_z_bits ||
-              _mesa_get_format_datatype(readRb->Format) !=
-              _mesa_get_format_datatype(drawRb->Format))) {
-
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "%s(stencil attachment depth format mismatch)", func);
-            return;
-         }
       }
    }
 
@@ -349,93 +510,9 @@ _mesa_blit_framebuffer(struct gl_context *ctx,
        */
       if ((readRb == NULL) || (drawRb == NULL)) {
          mask &= ~GL_DEPTH_BUFFER_BIT;
-      }
-      else {
-         int read_s_bit, draw_s_bit;
-
-         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "%s(source and destination depth "
-                        "buffer cannot be the same)", func);
-            return;
-         }
-
-         if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
-              _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
-             (_mesa_get_format_datatype(readRb->Format) !=
-              _mesa_get_format_datatype(drawRb->Format))) {
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "%s(depth attachment format mismatch)", func);
+      } else if (!no_error) {
+         if (!validate_depth_buffer(ctx, readFb, drawFb, func))
             return;
-         }
-
-         read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
-         draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
-
-         /* If both buffers also have stencil data, the stencil formats must
-          * match as well.  If one doesn't have stencil, it's not blitted, so
-          * we should ignore the stencil format check.
-          */
-         if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "%s(depth attachment stencil bits mismatch)", func);
-            return;
-         }
-      }
-   }
-
-
-   if (_mesa_is_gles3(ctx)) {
-      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
-       * 3.0.1 spec says:
-       *
-       *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
-       *     an INVALID_OPERATION error is generated."
-       */
-      if (drawFb->Visual.samples > 0) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(destination samples must be 0)", func);
-         return;
-      }
-
-      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
-       * 3.0.1 spec says:
-       *
-       *     "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
-       *     no copy is performed and an INVALID_OPERATION error is generated
-       *     if the formats of the read and draw framebuffers are not
-       *     identical or if the source and destination rectangles are not
-       *     defined with the same (X0, Y0) and (X1, Y1) bounds."
-       *
-       * The format check was made above because desktop OpenGL has the same
-       * requirement.
-       */
-      if (readFb->Visual.samples > 0
-          && (srcX0 != dstX0 || srcY0 != dstY0
-              || srcX1 != dstX1 || srcY1 != dstY1)) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(bad src/dst multisample region)", func);
-         return;
-      }
-   } else {
-      if (readFb->Visual.samples > 0 &&
-          drawFb->Visual.samples > 0 &&
-          readFb->Visual.samples != drawFb->Visual.samples) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(mismatched samples)", func);
-         return;
-      }
-
-      /* extra checks for multisample copies... */
-      if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
-          (filter == GL_NEAREST || filter == GL_LINEAR)) {
-         /* src and dest region sizes must be the same */
-         if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
-             abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "%s(bad src/dst multisample region sizes)", func);
-            return;
-         }
       }
    }
 
@@ -503,12 +580,43 @@ _mesa_blit_framebuffer(struct gl_context *ctx,
 }
 
 
+static void
+blit_framebuffer_err(struct gl_context *ctx,
+                     struct gl_framebuffer *readFb,
+                     struct gl_framebuffer *drawFb,
+                     GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                     GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                     GLbitfield mask, GLenum filter, const char *func)
+{
+   /* We are wrapping the err variant of the always inlined
+    * blit_framebuffer() to avoid inlining it in every caller.
+    */
+   blit_framebuffer(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
+                    dstX0, dstY0, dstX1, dstY1, mask, filter, false, func);
+}
+
+
 /**
  * Blit rectangular region, optionally from one framebuffer to another.
  *
  * Note, if the src buffer is multisampled and the dest is not, this is
  * when the samples must be resolved to a single color.
  */
+void GLAPIENTRY
+_mesa_BlitFramebuffer_no_error(GLint srcX0, GLint srcY0, GLint srcX1,
+                               GLint srcY1, GLint dstX0, GLint dstY0,
+                               GLint dstX1, GLint dstY1,
+                               GLbitfield mask, GLenum filter)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
+                    srcX0, srcY0, srcX1, srcY1,
+                    dstX0, dstY0, dstX1, dstY1,
+                    mask, filter, true, "glBlitFramebuffer");
+}
+
+
 void GLAPIENTRY
 _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
@@ -522,12 +630,80 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   " %d, %d, %d, %d, 0x%x, %s)\n",
                   srcX0, srcY0, srcX1, srcY1,
                   dstX0, dstY0, dstX1, dstY1,
-                  mask, _mesa_lookup_enum_by_nr(filter));
+                  mask, _mesa_enum_to_string(filter));
+
+   blit_framebuffer_err(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
+                        srcX0, srcY0, srcX1, srcY1,
+                        dstX0, dstY0, dstX1, dstY1,
+                        mask, filter, "glBlitFramebuffer");
+}
+
+
+static ALWAYS_INLINE void
+blit_named_framebuffer(struct gl_context *ctx,
+                       GLuint readFramebuffer, GLuint drawFramebuffer,
+                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                       GLbitfield mask, GLenum filter, bool no_error)
+{
+   struct gl_framebuffer *readFb, *drawFb;
+
+   /*
+    * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014,
+    * Section 18.3 Copying Pixels):
+    *   "... if readFramebuffer or drawFramebuffer is zero (for
+    *   BlitNamedFramebuffer), then the default read or draw framebuffer is
+    *   used as the corresponding source or destination framebuffer,
+    *   respectively."
+    */
+   if (readFramebuffer) {
+      if (no_error) {
+         readFb = _mesa_lookup_framebuffer(ctx, readFramebuffer);
+      } else {
+         readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
+                                               "glBlitNamedFramebuffer");
+         if (!readFb)
+            return;
+      }
+   } else {
+      readFb = ctx->WinSysReadBuffer;
+   }
+
+   if (drawFramebuffer) {
+      if (no_error) {
+         drawFb = _mesa_lookup_framebuffer(ctx, drawFramebuffer);
+      } else {
+         drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
+                                               "glBlitNamedFramebuffer");
+         if (!drawFb)
+            return;
+      }
+   } else {
+      drawFb = ctx->WinSysDrawBuffer;
+   }
 
-   _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
+   blit_framebuffer(ctx, readFb, drawFb,
+                    srcX0, srcY0, srcX1, srcY1,
+                    dstX0, dstY0, dstX1, dstY1,
+                    mask, filter, no_error, "glBlitNamedFramebuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_BlitNamedFramebuffer_no_error(GLuint readFramebuffer,
+                                    GLuint drawFramebuffer,
+                                    GLint srcX0, GLint srcY0,
+                                    GLint srcX1, GLint srcY1,
+                                    GLint dstX0, GLint dstY0,
+                                    GLint dstX1, GLint dstY1,
+                                    GLbitfield mask, GLenum filter)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   blit_named_framebuffer(ctx, readFramebuffer, drawFramebuffer,
                           srcX0, srcY0, srcX1, srcY1,
                           dstX0, dstY0, dstX1, dstY1,
-                          mask, filter, "glBlitFramebuffer");
+                          mask, filter, true);
 }
 
 
@@ -538,14 +714,6 @@ _mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
                            GLbitfield mask, GLenum filter)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *readFb, *drawFb;
-
-   if (!ctx->Extensions.ARB_direct_state_access) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glBlitNamedFramebuffer(GL_ARB_direct_state_access "
-                  "is not supported)");
-      return;
-   }
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx,
@@ -554,36 +722,10 @@ _mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
                   readFramebuffer, drawFramebuffer,
                   srcX0, srcY0, srcX1, srcY1,
                   dstX0, dstY0, dstX1, dstY1,
-                  mask, _mesa_lookup_enum_by_nr(filter));
-
-   /*
-    * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014,
-    * Section 18.3 Copying Pixels):
-    *   "... if readFramebuffer or drawFramebuffer is zero (for
-    *   BlitNamedFramebuffer), then the default read or draw framebuffer is
-    *   used as the corresponding source or destination framebuffer,
-    *   respectively."
-    */
-   if (readFramebuffer) {
-      readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
-                                            "glBlitNamedFramebuffer");
-      if (!readFb)
-         return;
-   }
-   else
-      readFb = ctx->WinSysReadBuffer;
-
-   if (drawFramebuffer) {
-      drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
-                                            "glBlitNamedFramebuffer");
-      if (!drawFb)
-         return;
-   }
-   else
-      drawFb = ctx->WinSysDrawBuffer;
+                  mask, _mesa_enum_to_string(filter));
 
-   _mesa_blit_framebuffer(ctx, readFb, drawFb,
+   blit_named_framebuffer(ctx, readFramebuffer, drawFramebuffer,
                           srcX0, srcY0, srcX1, srcY1,
                           dstX0, dstY0, dstX1, dstY1,
-                          mask, filter, "glBlitNamedFramebuffer");
+                          mask, filter, false);
 }