mesa: add support for memory object creation/import/delete
[mesa.git] / src / mesa / main / fbobject.c
index 4759441becc111a3aa2efa68237b70d14b9f5773..4d6fdfcd6bd90be08c9dbb5b16b65d21c1febe6e 100644 (file)
@@ -1705,11 +1705,6 @@ create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
    GLuint first;
    GLint i;
 
-   if (n < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
-      return;
-   }
-
    if (!renderbuffers)
       return;
 
@@ -1734,8 +1729,23 @@ create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
 }
 
 
+static void
+create_render_buffers_err(struct gl_context *ctx, GLsizei n,
+                          GLuint *renderbuffers, bool dsa)
+{
+   const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
+
+   if (n < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
+      return;
+   }
+
+   create_render_buffers(ctx, n, renderbuffers, dsa);
+}
+
+
 void GLAPIENTRY
-_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+_mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
 {
    GET_CURRENT_CONTEXT(ctx);
    create_render_buffers(ctx, n, renderbuffers, false);
@@ -1743,13 +1753,29 @@ _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
 
 
 void GLAPIENTRY
-_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
+_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   create_render_buffers_err(ctx, n, renderbuffers, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
 {
    GET_CURRENT_CONTEXT(ctx);
    create_render_buffers(ctx, n, renderbuffers, true);
 }
 
 
+void GLAPIENTRY
+_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   create_render_buffers_err(ctx, n, renderbuffers, true);
+}
+
+
 /**
  * Given an internal format token for a render buffer, return the
  * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
@@ -2822,6 +2848,16 @@ _mesa_check_framebuffer_status(struct gl_context *ctx,
 }
 
 
+GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatus_no_error(GLenum target)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
+   return _mesa_check_framebuffer_status(ctx, fb);
+}
+
+
 GLenum GLAPIENTRY
 _mesa_CheckFramebufferStatus(GLenum target)
 {
@@ -3303,6 +3339,28 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
 }
 
 
+static void
+framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
+                                       GLenum textarget, GLuint texture,
+                                       GLint level, GLint layer)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* Get the framebuffer object */
+   struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
+
+   /* Get the texture object */
+   struct gl_texture_object *texObj =
+      get_texture_for_framebuffer(ctx, texture);
+
+   struct gl_renderbuffer_attachment *att =
+      get_attachment(ctx, fb, attachment, NULL);
+
+   _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
+                             level, layer, GL_FALSE);
+}
+
+
 static void
 framebuffer_texture_with_dims(int dims, GLenum target,
                               GLenum attachment, GLenum textarget,
@@ -3346,6 +3404,16 @@ framebuffer_texture_with_dims(int dims, GLenum target,
 }
 
 
+void GLAPIENTRY
+_mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
+                                    GLenum textarget, GLuint texture,
+                                    GLint level)
+{
+   framebuffer_texture_with_dims_no_error(target, attachment, textarget,
+                                          texture, level, 0);
+}
+
+
 void GLAPIENTRY
 _mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
                            GLenum textarget, GLuint texture, GLint level)
@@ -3355,6 +3423,16 @@ _mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
 }
 
 
+void GLAPIENTRY
+_mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
+                                    GLenum textarget, GLuint texture,
+                                    GLint level)
+{
+   framebuffer_texture_with_dims_no_error(target, attachment, textarget,
+                                          texture, level, 0);
+}
+
+
 void GLAPIENTRY
 _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
                            GLenum textarget, GLuint texture, GLint level)
@@ -3364,6 +3442,16 @@ _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
 }
 
 
+void GLAPIENTRY
+_mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
+                                    GLenum textarget, GLuint texture,
+                                    GLint level, GLint layer)
+{
+   framebuffer_texture_with_dims_no_error(target, attachment, textarget,
+                                          texture, level, layer);
+}
+
+
 void GLAPIENTRY
 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
                            GLenum textarget, GLuint texture,
@@ -3374,101 +3462,140 @@ _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
 }
 
 
-void GLAPIENTRY
-_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
-                              GLuint texture, GLint level, GLint layer)
+static ALWAYS_INLINE void
+frame_buffer_texture(GLuint framebuffer, GLenum target,
+                     GLenum attachment, GLuint texture,
+                     GLint level, GLint layer, const char *func,
+                     bool dsa, bool no_error, bool check_layered)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *fb;
-   struct gl_texture_object *texObj;
-   GLenum textarget = 0;
+   GLboolean layered = GL_FALSE;
 
-   const char *func = "glFramebufferTextureLayer";
+   if (!no_error && check_layered) {
+      if (!_mesa_has_geometry_shaders(ctx)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "unsupported function (%s) called", func);
+         return;
+      }
+   }
 
    /* Get the framebuffer object */
-   fb = get_framebuffer_target(ctx, target);
-   if (!fb) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glFramebufferTextureLayer(invalid target %s)",
-                  _mesa_enum_to_string(target));
-      return;
+   struct gl_framebuffer *fb;
+   if (no_error) {
+      if (dsa) {
+         fb = _mesa_lookup_framebuffer(ctx, framebuffer);
+      } else {
+         fb = get_framebuffer_target(ctx, target);
+      }
+   } else {
+      if (dsa) {
+         fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
+         if (!fb)
+            return;
+      } else {
+         fb = get_framebuffer_target(ctx, target);
+         if (!fb) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
+                        func, _mesa_enum_to_string(target));
+            return;
+         }
+      }
    }
 
-   /* Get the texture object */
-   if (!get_texture_for_framebuffer_err(ctx, texture, false, func, &texObj))
-      return;
-
-   if (texObj) {
-      if (!check_texture_target(ctx, texObj->Target, func))
+   /* Get the texture object and framebuffer attachment*/
+   struct gl_renderbuffer_attachment *att;
+   struct gl_texture_object *texObj;
+   if (no_error) {
+      texObj = get_texture_for_framebuffer(ctx, texture);
+      att = get_attachment(ctx, fb, attachment, NULL);
+   } else {
+      if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
+                                           &texObj))
          return;
 
-      if (!check_layer(ctx, texObj->Target, layer, func))
+      att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
+      if (!att)
          return;
+   }
 
-      if (!check_level(ctx, texObj->Target, level, func))
-         return;
+   GLenum textarget = 0;
+   if (texObj) {
+      if (check_layered) {
+         /* We do this regardless of no_error because this sets layered */
+         if (!check_layered_texture_target(ctx, texObj->Target, func,
+                                           &layered))
+            return;
+      }
+
+      if (!no_error) {
+         if (!check_layered) {
+            if (!check_texture_target(ctx, texObj->Target, func))
+               return;
+
+            if (!check_layer(ctx, texObj->Target, layer, func))
+               return;
+         }
 
-      if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+         if (!check_level(ctx, texObj->Target, level, func))
+            return;
+      }
+
+      if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
          assert(layer >= 0 && layer < 6);
          textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
          layer = 0;
       }
    }
 
-   struct gl_renderbuffer_attachment *att =
-      _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
-   if (!att)
-      return;
-
    _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
-                             level, layer, GL_FALSE);
+                             level, layer, layered);
 }
 
-
 void GLAPIENTRY
-_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
-                                   GLuint texture, GLint level, GLint layer)
+_mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
+                                       GLuint texture, GLint level,
+                                       GLint layer)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *fb;
-   struct gl_texture_object *texObj;
-   GLenum textarget = 0;
-
-   const char *func = "glNamedFramebufferTextureLayer";
+   frame_buffer_texture(0, target, attachment, texture, level, layer,
+                        "glFramebufferTextureLayer", false, true, false);
+}
 
-   /* Get the framebuffer object */
-   fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
-   if (!fb)
-      return;
 
-   /* Get the texture object */
-   if (!get_texture_for_framebuffer_err(ctx, texture, false, func, &texObj))
-      return;
+void GLAPIENTRY
+_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
+                              GLuint texture, GLint level, GLint layer)
+{
+   frame_buffer_texture(0, target, attachment, texture, level, layer,
+                        "glFramebufferTextureLayer", false, false, false);
+}
 
-   if (texObj) {
-      if (!check_texture_target(ctx, texObj->Target, func))
-         return;
 
-      if (!check_layer(ctx, texObj->Target, layer, func))
-         return;
+void GLAPIENTRY
+_mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
+                                            GLenum attachment,
+                                            GLuint texture, GLint level,
+                                            GLint layer)
+{
+   frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
+                        "glNamedFramebufferTextureLayer", true, true, false);
+}
 
-      if (!check_level(ctx, texObj->Target, level, func))
-         return;
 
-      if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
-         assert(layer >= 0 && layer < 6);
-         textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
-         layer = 0;
-      }
-   }
+void GLAPIENTRY
+_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
+                                   GLuint texture, GLint level, GLint layer)
+{
+   frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
+                        "glNamedFramebufferTextureLayer", true, false, false);
+}
 
-   struct gl_renderbuffer_attachment *att =
-      _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
-   if (!att)
-      return;
 
-   _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
-                             level, layer, GL_FALSE);
+void GLAPIENTRY
+_mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
+                                  GLuint texture, GLint level)
+{
+   frame_buffer_texture(0, target, attachment, texture, level, 0,
+                        "glFramebufferTexture", false, true, true);
 }
 
 
@@ -3476,47 +3603,16 @@ void GLAPIENTRY
 _mesa_FramebufferTexture(GLenum target, GLenum attachment,
                          GLuint texture, GLint level)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *fb;
-   struct gl_texture_object *texObj;
-   GLboolean layered = GL_FALSE;
-
-   const char *func = "FramebufferTexture";
-
-   if (!_mesa_has_geometry_shaders(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "unsupported function (glFramebufferTexture) called");
-      return;
-   }
-
-   /* Get the framebuffer object */
-   fb = get_framebuffer_target(ctx, target);
-   if (!fb) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glFramebufferTexture(invalid target %s)",
-                  _mesa_enum_to_string(target));
-      return;
-   }
-
-   /* Get the texture object */
-   if (!get_texture_for_framebuffer_err(ctx, texture, true, func, &texObj))
-      return;
-
-   if (texObj) {
-      if (!check_layered_texture_target(ctx, texObj->Target, func, &layered))
-         return;
-
-      if (!check_level(ctx, texObj->Target, level, func))
-         return;
-   }
-
-   struct gl_renderbuffer_attachment *att =
-      _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
-   if (!att)
-      return;
+   frame_buffer_texture(0, target, attachment, texture, level, 0,
+                        "glFramebufferTexture", false, false, true);
+}
 
-   _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, 0, level,
-                             0, layered);
+void GLAPIENTRY
+_mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
+                                       GLuint texture, GLint level)
+{
+   frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
+                        "glNamedFramebufferTexture", true, true, true);
 }
 
 
@@ -3524,44 +3620,8 @@ void GLAPIENTRY
 _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
                               GLuint texture, GLint level)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *fb;
-   struct gl_texture_object *texObj;
-   GLboolean layered = GL_FALSE;
-
-   const char *func = "glNamedFramebufferTexture";
-
-   if (!_mesa_has_geometry_shaders(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "unsupported function (glNamedFramebufferTexture) called");
-      return;
-   }
-
-   /* Get the framebuffer object */
-   fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
-   if (!fb)
-      return;
-
-   /* Get the texture object */
-   if (!get_texture_for_framebuffer_err(ctx, texture, true, func, &texObj))
-      return;
-
-   if (texObj) {
-      if (!check_layered_texture_target(ctx, texObj->Target, func,
-                                        &layered))
-         return;
-
-      if (!check_level(ctx, texObj->Target, level, func))
-         return;
-   }
-
-   struct gl_renderbuffer_attachment *att =
-      _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
-   if (!att)
-      return;
-
-   _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, 0, level,
-                             0, layered);
+   frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
+                        "glNamedFramebufferTexture", true, false, true);
 }
 
 
@@ -3584,70 +3644,121 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
    _mesa_update_framebuffer_visual(ctx, fb);
 }
 
-static void
-framebuffer_renderbuffer(struct gl_context *ctx,
-                         struct gl_framebuffer *fb,
-                         GLenum attachment,
-                         struct gl_renderbuffer *rb,
-                         const char *func)
+static ALWAYS_INLINE void
+framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+                         GLenum attachment, GLenum renderbuffertarget,
+                         GLuint renderbuffer, const char *func, bool no_error)
 {
    struct gl_renderbuffer_attachment *att;
+   struct gl_renderbuffer *rb;
    bool is_color_attachment;
 
-   if (_mesa_is_winsys_fbo(fb)) {
-      /* Can't attach new renderbuffers to a window system framebuffer */
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(window-system framebuffer)", func);
+   if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
       return;
    }
 
-   att = get_attachment(ctx, fb, attachment, &is_color_attachment);
-   if (att == NULL) {
-      /*
-       * 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));
+   if (renderbuffer) {
+      if (!no_error) {
+         rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
+         if (!rb)
+            return;
       } else {
-         _mesa_error(ctx, GL_INVALID_ENUM,
-                     "%s(invalid attachment %s)", func,
-                     _mesa_enum_to_string(attachment));
+         rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
       }
-
-      return;
+   } else {
+      /* remove renderbuffer attachment */
+      rb = NULL;
    }
 
-   if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
-       rb && rb->Format != MESA_FORMAT_NONE) {
-      /* make sure the renderbuffer is a depth/stencil format */
-      const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
-      if (baseFormat != GL_DEPTH_STENCIL) {
+   if (!no_error) {
+      if (_mesa_is_winsys_fbo(fb)) {
+         /* Can't attach new renderbuffers to a window system framebuffer */
          _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(renderbuffer is not DEPTH_STENCIL format)", func);
+                     "%s(window-system framebuffer)", func);
+         return;
+      }
+
+      att = get_attachment(ctx, fb, attachment, &is_color_attachment);
+      if (att == NULL) {
+         /*
+          * 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;
       }
+
+      if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
+          rb && rb->Format != MESA_FORMAT_NONE) {
+         /* make sure the renderbuffer is a depth/stencil format */
+         const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
+         if (baseFormat != GL_DEPTH_STENCIL) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "%s(renderbuffer is not DEPTH_STENCIL format)", func);
+            return;
+         }
+      }
    }
 
    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
 }
 
+static void
+framebuffer_renderbuffer_error(struct gl_context *ctx,
+                               struct gl_framebuffer *fb, GLenum attachment,
+                               GLenum renderbuffertarget,
+                               GLuint renderbuffer, const char *func)
+{
+   framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
+                            renderbuffer, func, false);
+}
+
+static void
+framebuffer_renderbuffer_no_error(struct gl_context *ctx,
+                                  struct gl_framebuffer *fb, GLenum attachment,
+                                  GLenum renderbuffertarget,
+                                  GLuint renderbuffer, const char *func)
+{
+   framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
+                            renderbuffer, func, true);
+}
+
+void GLAPIENTRY
+_mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
+                                       GLenum renderbuffertarget,
+                                       GLuint renderbuffer)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
+   framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
+                                     renderbuffer, "glFramebufferRenderbuffer");
+}
+
 void GLAPIENTRY
 _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
                               GLenum renderbuffertarget,
                               GLuint renderbuffer)
 {
    struct gl_framebuffer *fb;
-   struct gl_renderbuffer *rb;
    GET_CURRENT_CONTEXT(ctx);
 
    fb = get_framebuffer_target(ctx, target);
@@ -3658,36 +3769,30 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
       return;
    }
 
-   if (renderbuffertarget != GL_RENDERBUFFER) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glFramebufferRenderbuffer(renderbuffertarget is not "
-                  "GL_RENDERBUFFER)");
-      return;
-   }
+   framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
+                                  renderbuffer, "glFramebufferRenderbuffer");
+}
 
-   if (renderbuffer) {
-      rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
-                                         "glFramebufferRenderbuffer");
-      if (!rb)
-         return;
-   }
-   else {
-      /* remove renderbuffer attachment */
-      rb = NULL;
-   }
+void GLAPIENTRY
+_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
+                                            GLenum attachment,
+                                            GLenum renderbuffertarget,
+                                            GLuint renderbuffer)
+{
+   GET_CURRENT_CONTEXT(ctx);
 
-   framebuffer_renderbuffer(ctx, fb, attachment, rb,
-                            "glFramebufferRenderbuffer");
+   struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
+   framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
+                                     renderbuffer,
+                                     "glNamedFramebufferRenderbuffer");
 }
 
-
 void GLAPIENTRY
 _mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
                                    GLenum renderbuffertarget,
                                    GLuint renderbuffer)
 {
    struct gl_framebuffer *fb;
-   struct gl_renderbuffer *rb;
    GET_CURRENT_CONTEXT(ctx);
 
    fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
@@ -3695,26 +3800,9 @@ _mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
    if (!fb)
       return;
 
-   if (renderbuffertarget != GL_RENDERBUFFER) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glNamedFramebufferRenderbuffer(renderbuffertarget is not "
-                  "GL_RENDERBUFFER)");
-      return;
-   }
-
-   if (renderbuffer) {
-      rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
-                                         "glNamedFramebufferRenderbuffer");
-      if (!rb)
-         return;
-   }
-   else {
-      /* remove renderbuffer attachment */
-      rb = NULL;
-   }
-
-   framebuffer_renderbuffer(ctx, fb, attachment, rb,
-                            "glNamedFramebufferRenderbuffer");
+   framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
+                                  renderbuffer,
+                                  "glNamedFramebufferRenderbuffer");
 }
 
 
@@ -4289,6 +4377,15 @@ invalid_enum:
 }
 
 
+void GLAPIENTRY
+_mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
+                                        const GLenum *attachments, GLint x,
+                                        GLint y, GLsizei width, GLsizei height)
+{
+   /* no-op */
+}
+
+
 void GLAPIENTRY
 _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
                                const GLenum *attachments, GLint x, GLint y,
@@ -4340,6 +4437,14 @@ _mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
 }
 
 
+void GLAPIENTRY
+_mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
+                                     const GLenum *attachments)
+{
+   /* no-op */
+}
+
+
 void GLAPIENTRY
 _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
                             const GLenum *attachments)