mesa: tidy up renderbuffer RefCount initialisation
[mesa.git] / src / mesa / main / fbobject.c
index ce5eeae048cab6e7ba40de9e24fe006607e81178..5048327e5ed3c1f7c058e89b80bfb00794cf8448 100644 (file)
@@ -1323,7 +1323,6 @@ allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
    }
    assert(newRb->AllocStorage);
    _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer, newRb);
-   newRb->RefCount = 1; /* referenced by hash table */
 
    return newRb;
 }
@@ -1477,10 +1476,47 @@ _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
    framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
 }
 
+static bool
+_pname_valid_for_default_framebuffer(struct gl_context *ctx,
+                                     GLenum pname)
+{
+   if (!_mesa_is_desktop_gl(ctx))
+      return false;
+
+   switch (pname) {
+   case GL_DOUBLEBUFFER:
+   case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+   case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+   case GL_SAMPLES:
+   case GL_SAMPLE_BUFFERS:
+   case GL_STEREO:
+      return true;
+   default:
+      return false;
+   }
+}
+
 static void
 get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
                             GLenum pname, GLint *params, const char *func)
 {
+   /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
+    *
+    *    "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
+    *     if the default framebuffer is bound to target and pname is not one
+    *     of the accepted values from table 23.73, other than
+    *     SAMPLE_POSITION."
+    *
+    * For OpenGL ES, using default framebuffer still raises INVALID_OPERATION
+    * for any pname.
+    */
+   if (_mesa_is_winsys_fbo(fb) &&
+       !_pname_valid_for_default_framebuffer(ctx, pname)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(invalid pname=0x%x for default framebuffer)", func, pname);
+      return;
+   }
+
    switch (pname) {
    case GL_FRAMEBUFFER_DEFAULT_WIDTH:
       *params = fb->DefaultGeometry.Width;
@@ -1505,6 +1541,24 @@ get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
    case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
       *params = fb->DefaultGeometry.FixedSampleLocations;
       break;
+   case GL_DOUBLEBUFFER:
+      *params = fb->Visual.doubleBufferMode;
+      break;
+   case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+      *params = _mesa_get_color_read_format(ctx, fb, func);
+      break;
+   case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+      *params = _mesa_get_color_read_type(ctx, fb, func);
+      break;
+   case GL_SAMPLES:
+      *params = _mesa_geometric_samples(fb);
+      break;
+   case GL_SAMPLE_BUFFERS:
+      *params = _mesa_geometric_samples(fb) > 0;
+      break;
+   case GL_STEREO:
+      *params = fb->Visual.stereoMode;
+      break;
    default:
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "%s(pname=0x%x)", func, pname);
@@ -1531,13 +1585,6 @@ _mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
       return;
    }
 
-   /* check framebuffer binding */
-   if (_mesa_is_winsys_fbo(fb)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetFramebufferParameteriv");
-      return;
-   }
-
    get_framebuffer_parameteriv(ctx, fb, pname, params,
                                "glGetFramebufferParameteriv");
 }
@@ -3150,6 +3197,7 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
                           const char *caller)
 {
    struct gl_renderbuffer_attachment *att;
+   bool is_color_attachment;
 
    /* The window-system framebuffer object is immutable */
    if (_mesa_is_winsys_fbo(fb)) {
@@ -3159,10 +3207,17 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
    }
 
    /* Not a hash lookup, so we can afford to get the attachment here. */
-   att = get_attachment(ctx, fb, attachment, NULL);
+   att = get_attachment(ctx, fb, attachment, &is_color_attachment);
    if (att == NULL) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
-                  _mesa_enum_to_string(attachment));
+      if (is_color_attachment) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(invalid color attachment %s)", caller,
+                     _mesa_enum_to_string(attachment));
+      } else {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "%s(invalid attachment %s)", caller,
+                     _mesa_enum_to_string(attachment));
+      }
       return;
    }
 
@@ -3495,6 +3550,7 @@ framebuffer_renderbuffer(struct gl_context *ctx,
                          const char *func)
 {
    struct gl_renderbuffer_attachment *att;
+   bool is_color_attachment;
 
    if (_mesa_is_winsys_fbo(fb)) {
       /* Can't attach new renderbuffers to a window system framebuffer */
@@ -3503,11 +3559,29 @@ framebuffer_renderbuffer(struct gl_context *ctx,
       return;
    }
 
-   att = get_attachment(ctx, fb, attachment, NULL);
+   att = get_attachment(ctx, fb, attachment, &is_color_attachment);
    if (att == NULL) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(invalid attachment %s)", func,
-                  _mesa_enum_to_string(attachment));
+      /*
+       * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images to
+       * a Framebuffer":
+       *
+       *    "An INVALID_OPERATION error is generated if attachment is COLOR_-
+       *     ATTACHMENTm where m is greater than or equal to the value of
+       *     MAX_COLOR_- ATTACHMENTS ."
+       *
+       * If we are at this point, is because the attachment is not valid, so
+       * if is_color_attachment is true, is because of the previous reason.
+       */
+      if (is_color_attachment) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(invalid color attachment %s)", func,
+                     _mesa_enum_to_string(attachment));
+      } else {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "%s(invalid attachment %s)", func,
+                     _mesa_enum_to_string(attachment));
+      }
+
       return;
    }
 
@@ -3609,6 +3683,7 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
                                            GLint *params, const char *caller)
 {
    const struct gl_renderbuffer_attachment *att;
+   bool is_color_attachment = false;
    GLenum err;
 
    /* The error code for an attachment type of GL_NONE differs between APIs.
@@ -3676,12 +3751,27 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
    }
    else {
       /* user-created framebuffer FBO */
-      att = get_attachment(ctx, buffer, attachment, NULL);
+      att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
    }
 
    if (att == NULL) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
-                  _mesa_enum_to_string(attachment));
+      /*
+       * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
+       *
+       *    "An INVALID_OPERATION error is generated if a framebuffer object
+       *     is bound to target and attachment is COLOR_ATTACHMENTm where m is
+       *     greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
+       *
+       * If we are at this point, is because the attachment is not valid, so
+       * if is_color_attachment is true, is because of the previous reason.
+       */
+      if (is_color_attachment) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
+                     caller, _mesa_enum_to_string(attachment));
+      } else {
+         _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
+                     _mesa_enum_to_string(attachment));
+      }
       return;
    }
 
@@ -3719,11 +3809,13 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
        *  either no framebuffer is bound to target; or the default framebuffer
        *  is bound, attachment is DEPTH or STENCIL, and the number of depth or
        *  stencil bits, respectively, is zero."
+       *
+       * Note that we don't need explicit checks on DEPTH and STENCIL, because
+       * on the case the spec is pointing, att->Type is already NONE, so we
+       * just need to check att->Type.
        */
-      *params = (_mesa_is_winsys_fbo(buffer) &&
-                 ((attachment != GL_DEPTH && attachment != GL_STENCIL) ||
-                  (att->Type != GL_NONE)))
-         ? GL_FRAMEBUFFER_DEFAULT : att->Type;
+      *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
+         GL_FRAMEBUFFER_DEFAULT : att->Type;
       return;
    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
       if (att->Type == GL_RENDERBUFFER_EXT) {