mesa: add support for memory object creation/import/delete
[mesa.git] / src / mesa / main / blit.c
index 970c35733546ddcf6e249fde28e9a0e2f6b92062..8bb3ba328a32c03c530ea9cca5cf197343ff4ea7 100644 (file)
@@ -177,7 +177,170 @@ is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
 }
 
 
-static void
+static bool
+validate_color_buffer(struct gl_context *ctx, struct gl_framebuffer *readFb,
+                      struct gl_framebuffer *drawFb, GLenum filter,
+                      const char *func)
+{
+   const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
+   const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
+   const struct gl_renderbuffer *colorDrawRb = NULL;
+   GLuint i;
+
+   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 false;
+      }
+
+      if (!compatible_color_datatypes(colorReadRb->Format,
+                                      colorDrawRb->Format)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(color buffer datatypes mismatch)", func);
+         return false;
+      }
+
+      /* 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."
+       */
+      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;
+}
+
+
+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 (_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;
+   }
+
+   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;
+}
+
+
+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;
+   }
+
+   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);
+      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,
@@ -186,12 +349,6 @@ blit_framebuffer(struct gl_context *ctx,
 {
    FLUSH_VERTICES(ctx, 0);
 
-   /* 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 (!readFb || !drawFb) {
       /* This will normally never happen but someday we may want to
        * support MakeCurrent() with no drawables.
@@ -199,6 +356,12 @@ blit_framebuffer(struct gl_context *ctx,
       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 |
@@ -298,8 +461,6 @@ blit_framebuffer(struct gl_context *ctx,
    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:
        *
@@ -310,65 +471,8 @@ blit_framebuffer(struct gl_context *ctx,
       if (!colorReadRb || numColorDrawBuffers == 0) {
          mask &= ~GL_COLOR_BUFFER_BIT;
       } else if (!no_error) {
-         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 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;
-               }
-            }
-         }
-         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;
-            }
-         }
+         if (!validate_color_buffer(ctx, readFb, drawFb, filter, func))
+            return;
       }
    }
 
@@ -387,41 +491,8 @@ blit_framebuffer(struct gl_context *ctx,
       if ((readRb == NULL) || (drawRb == NULL)) {
          mask &= ~GL_STENCIL_BUFFER_BIT;
       } else if (!no_error) {
-         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);
+         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;
-         }
       }
    }
 
@@ -440,36 +511,8 @@ blit_framebuffer(struct gl_context *ctx,
       if ((readRb == NULL) || (drawRb == NULL)) {
          mask &= ~GL_DEPTH_BUFFER_BIT;
       } else if (!no_error) {
-         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);
-            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);
+         if (!validate_depth_buffer(ctx, readFb, drawFb, func))
             return;
-         }
       }
    }
 
@@ -537,6 +580,22 @@ 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.
  *
@@ -544,45 +603,51 @@ blit_framebuffer(struct gl_context *ctx,
  * when the samples must be resolved to a single color.
  */
 void GLAPIENTRY
-_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-                      GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                      GLbitfield mask, GLenum filter)
+_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);
 
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx,
-                  "glBlitFramebuffer(%d, %d, %d, %d, "
-                  " %d, %d, %d, %d, 0x%x, %s)\n",
-                  srcX0, srcY0, srcX1, srcY1,
-                  dstX0, dstY0, dstX1, dstY1,
-                  mask, _mesa_enum_to_string(filter));
-
    blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                     srcX0, srcY0, srcX1, srcY1,
                     dstX0, dstY0, dstX1, dstY1,
-                    mask, filter, false, "glBlitFramebuffer");
+                    mask, filter, true, "glBlitFramebuffer");
 }
 
 
 void GLAPIENTRY
-_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
-                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                           GLbitfield mask, GLenum filter)
+_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                      GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                      GLbitfield mask, GLenum filter)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *readFb, *drawFb;
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx,
-                  "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, "
+                  "glBlitFramebuffer(%d, %d, %d, %d, "
                   " %d, %d, %d, %d, 0x%x, %s)\n",
-                  readFramebuffer, drawFramebuffer,
                   srcX0, srcY0, srcX1, srcY1,
                   dstX0, dstY0, dstX1, dstY1,
                   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):
@@ -592,25 +657,75 @@ _mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
     *   respectively."
     */
    if (readFramebuffer) {
-      readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
-                                            "glBlitNamedFramebuffer");
-      if (!readFb)
-         return;
-   }
-   else
+      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) {
-      drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
-                                            "glBlitNamedFramebuffer");
-      if (!drawFb)
-         return;
-   }
-   else
+      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;
+   }
 
    blit_framebuffer(ctx, readFb, drawFb,
                     srcX0, srcY0, srcX1, srcY1,
                     dstX0, dstY0, dstX1, dstY1,
-                    mask, filter, false, "glBlitNamedFramebuffer");
+                    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, true);
+}
+
+
+void GLAPIENTRY
+_mesa_BlitNamedFramebuffer(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);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx,
+                  "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, "
+                  " %d, %d, %d, %d, 0x%x, %s)\n",
+                  readFramebuffer, drawFramebuffer,
+                  srcX0, srcY0, srcX1, srcY1,
+                  dstX0, dstY0, dstX1, dstY1,
+                  mask, _mesa_enum_to_string(filter));
+
+   blit_named_framebuffer(ctx, readFramebuffer, drawFramebuffer,
+                          srcX0, srcY0, srcX1, srcY1,
+                          dstX0, dstY0, dstX1, dstY1,
+                          mask, filter, false);
 }