mesa: add 'no_error' parameter to blit_framebuffer()
[mesa.git] / src / mesa / main / framebuffer.c
index d18166d528ea6622919092c606009d499f068cf2..993cd37137b9583a7641c3cb76c4b8bc509e5811 100644 (file)
@@ -44,6 +44,7 @@
 #include "renderbuffer.h"
 #include "texobj.h"
 #include "glformats.h"
+#include "state.h"
 
 
 
@@ -256,7 +257,6 @@ _mesa_reference_framebuffer_(struct gl_framebuffer **ptr,
 
       *ptr = NULL;
    }
-   assert(!*ptr);
 
    if (fb) {
       mtx_lock(&fb->Mutex);
@@ -407,10 +407,10 @@ _mesa_intersect_scissor_bounding_box(const struct gl_context *ctx,
  *
  * \sa _mesa_clip_to_region
  */
-void
-_mesa_scissor_bounding_box(const struct gl_context *ctx,
-                           const struct gl_framebuffer *buffer,
-                           unsigned idx, int *bbox)
+static void
+scissor_bounding_box(const struct gl_context *ctx,
+                     const struct gl_framebuffer *buffer,
+                     unsigned idx, int *bbox)
 {
    bbox[0] = 0;
    bbox[2] = 0;
@@ -444,7 +444,7 @@ _mesa_update_draw_buffer_bounds(struct gl_context *ctx,
    }
 
    /* Default to the first scissor as that's always valid */
-   _mesa_scissor_bounding_box(ctx, buffer, 0, bbox);
+   scissor_bounding_box(ctx, buffer, 0, bbox);
    buffer->_Xmin = bbox[0];
    buffer->_Ymin = bbox[2];
    buffer->_Xmax = bbox[1];
@@ -474,13 +474,6 @@ _mesa_update_framebuffer_visual(struct gl_context *ctx,
    memset(&fb->Visual, 0, sizeof(fb->Visual));
    fb->Visual.rgbMode = GL_TRUE; /* assume this */
 
-#if 0 /* this _might_ be needed */
-   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-      /* leave visual fields zero'd */
-      return;
-   }
-#endif
-
    /* find first RGB renderbuffer */
    for (i = 0; i < BUFFER_COUNT; i++) {
       if (fb->Attachment[i].Renderbuffer) {
@@ -836,28 +829,62 @@ _mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format)
 
 
 /**
- * Used to answer the GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES query.
+ * Used to answer the GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES queries (using
+ * GetIntegerv, GetFramebufferParameteriv, etc)
+ *
+ * If @fb is NULL, the method returns the value for the current bound
+ * framebuffer.
  */
 GLenum
-_mesa_get_color_read_format(struct gl_context *ctx)
+_mesa_get_color_read_format(struct gl_context *ctx,
+                            struct gl_framebuffer *fb,
+                            const char *caller)
 {
-   if (!ctx->ReadBuffer || !ctx->ReadBuffer->_ColorReadBuffer) {
-      /* The spec is unclear how to handle this case, but NVIDIA's
-       * driver generates GL_INVALID_OPERATION.
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   if (fb == NULL)
+      fb = ctx->ReadBuffer;
+
+   if (!fb || !fb->_ColorReadBuffer) {
+      /*
+       * From OpenGL 4.5 spec, section 18.2.2 "ReadPixels":
+       *
+       *    "An INVALID_OPERATION error is generated by GetIntegerv if pname
+       *     is IMPLEMENTATION_COLOR_READ_FORMAT or IMPLEMENTATION_COLOR_-
+       *     READ_TYPE and any of:
+       *      * the read framebuffer is not framebuffer complete.
+       *      * the read framebuffer is a framebuffer object, and the selected
+       *        read buffer (see section 18.2.1) has no image attached.
+       *      * the selected read buffer is NONE."
+       *
+       * There is not equivalent quote for GetFramebufferParameteriv or
+       * GetNamedFramebufferParameteriv, but from section 9.2.3 "Framebuffer
+       * Object Queries":
+       *
+       *    "Values of framebuffer-dependent state are identical to those that
+       *     would be obtained were the framebuffer object bound and queried
+       *     using the simple state queries in that table."
+       *
+       * Where "using the simple state queries" refer to use GetIntegerv. So
+       * we will assume that on that situation the same error should be
+       * triggered too.
        */
       _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT: "
-                  "no GL_READ_BUFFER)");
+                  "%s(GL_IMPLEMENTATION_COLOR_READ_FORMAT: no GL_READ_BUFFER)",
+                  caller);
       return GL_NONE;
    }
    else {
-      const GLenum format = ctx->ReadBuffer->_ColorReadBuffer->Format;
+      const mesa_format format = fb->_ColorReadBuffer->Format;
       const GLenum data_type = _mesa_get_format_datatype(format);
 
       if (format == MESA_FORMAT_B8G8R8A8_UNORM)
          return GL_BGRA;
       else if (format == MESA_FORMAT_B5G6R5_UNORM)
-         return GL_BGR;
+         return GL_RGB;
+      else if (format == MESA_FORMAT_R_UNORM8)
+         return GL_RED;
 
       switch (data_type) {
       case GL_UNSIGNED_INT:
@@ -871,26 +898,38 @@ _mesa_get_color_read_format(struct gl_context *ctx)
 
 
 /**
- * Used to answer the GL_IMPLEMENTATION_COLOR_READ_TYPE_OES query.
+ * Used to answer the GL_IMPLEMENTATION_COLOR_READ_TYPE_OES queries (using
+ * GetIntegerv, GetFramebufferParameteriv, etc)
+ *
+ * If @fb is NULL, the method returns the value for the current bound
+ * framebuffer.
  */
 GLenum
-_mesa_get_color_read_type(struct gl_context *ctx)
+_mesa_get_color_read_type(struct gl_context *ctx,
+                          struct gl_framebuffer *fb,
+                          const char *caller)
 {
-   if (!ctx->ReadBuffer || !ctx->ReadBuffer->_ColorReadBuffer) {
-      /* The spec is unclear how to handle this case, but NVIDIA's
-       * driver generates GL_INVALID_OPERATION.
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   if (fb == NULL)
+      fb = ctx->ReadBuffer;
+
+   if (!fb || !fb->_ColorReadBuffer) {
+      /*
+       * See comment on _mesa_get_color_read_format
        */
       _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE: "
-                  "no GL_READ_BUFFER)");
+                  "%s(GL_IMPLEMENTATION_COLOR_READ_TYPE: no GL_READ_BUFFER)",
+                  caller);
       return GL_NONE;
    }
    else {
-      const GLenum format = ctx->ReadBuffer->_ColorReadBuffer->Format;
+      const GLenum format = fb->_ColorReadBuffer->Format;
       const GLenum data_type = _mesa_get_format_datatype(format);
 
       if (format == MESA_FORMAT_B5G6R5_UNORM)
-         return GL_UNSIGNED_SHORT_5_6_5_REV;
+         return GL_UNSIGNED_SHORT_5_6_5;
 
       switch (data_type) {
       case GL_SIGNED_NORMALIZED:
@@ -983,3 +1022,47 @@ _mesa_is_front_buffer_drawing(const struct gl_framebuffer *fb)
    return (fb->_NumColorDrawBuffers >= 1 &&
            fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT);
 }
+
+static inline GLuint
+_mesa_geometric_nonvalidated_samples(const struct gl_framebuffer *buffer)
+{
+   return buffer->_HasAttachments ?
+      buffer->Visual.samples :
+      buffer->DefaultGeometry.NumSamples;
+}
+
+bool
+_mesa_is_multisample_enabled(const struct gl_context *ctx)
+{
+   /* The sample count may not be validated by the driver, but when it is set,
+    * we know that is in a valid range and no driver should ever validate a
+    * multisampled framebuffer to non-multisampled and vice-versa.
+    */
+   return ctx->Multisample.Enabled &&
+          ctx->DrawBuffer &&
+          _mesa_geometric_nonvalidated_samples(ctx->DrawBuffer) >= 1;
+}
+
+/**
+ * Is alpha testing enabled and applicable to the currently bound
+ * framebuffer?
+ */
+bool
+_mesa_is_alpha_test_enabled(const struct gl_context *ctx)
+{
+   bool buffer0_is_integer = ctx->DrawBuffer->_IntegerBuffers & 0x1;
+   return (ctx->Color.AlphaEnabled && !buffer0_is_integer);
+}
+
+/**
+ * Is alpha to coverage enabled and applicable to the currently bound
+ * framebuffer?
+ */
+bool
+_mesa_is_alpha_to_coverage_enabled(const struct gl_context *ctx)
+{
+   bool buffer0_is_integer = ctx->DrawBuffer->_IntegerBuffers & 0x1;
+   return (ctx->Multisample.SampleAlphaToCoverage &&
+           _mesa_is_multisample_enabled(ctx) &&
+           !buffer0_is_integer);
+}