main: Major refactor of get_texture_for_framebuffer.
authorLaura Ekstrand <laura@jlekstrand.net>
Tue, 3 Mar 2015 00:48:59 +0000 (16:48 -0800)
committerFredrik Höglund <fredrik@kde.org>
Thu, 14 May 2015 13:48:13 +0000 (15:48 +0200)
This splits off the (still) rather large chunk that is
get_texture_for_framebuffer into lots of smaller functions specialized to
service the wide variety of unique needs of *FramebufferTexture* entry points.
The result is much cleaner because, rather than having a pile of branches and
confusing conditions (like the boolean layered), the uniqueness is baked into
the entry points. The entry points know whether or not they are layered or use
a textarget.

[Fredrik: - Mention the value of <textarget> in the error message.
          - Rename check_zoffset to check_layer, and zoffset to layer.
            The zoffset parameter was renamed to layer in
            ARB_framebuffer_object.
          - Make layered a GLboolean since the value is visible to the API.
          - Remove EXT suffixes in refactored code.
          - Whitespace fixes.]

Reviewed-by: Fredrik Höglund <fredrik@kde.org>
Signed-off-by: Fredrik Höglund <fredrik@kde.org>
src/mapi/glapi/gen/ARB_framebuffer_object.xml
src/mesa/main/fbobject.c
src/mesa/main/fbobject.h

index 7c547c1..999a8ef 100644 (file)
         <param name="textarget" type="GLenum"/>
         <param name="texture" type="GLuint"/>
         <param name="level" type="GLint"/>
-        <param name="zoffset" type="GLint"/>
+        <param name="layer" type="GLint"/>
        <glx rop="4323"/>
     </function>
 
index 8f759fb..807b629 100644 (file)
@@ -465,7 +465,7 @@ set_texture_attachment(struct gl_context *ctx,
                        struct gl_framebuffer *fb,
                        struct gl_renderbuffer_attachment *att,
                        struct gl_texture_object *texObj,
-                       GLenum texTarget, GLuint level, GLuint zoffset,
+                       GLenum texTarget, GLuint level, GLuint layer,
                        GLboolean layered)
 {
    struct gl_renderbuffer *rb = att->Renderbuffer;
@@ -489,7 +489,7 @@ set_texture_attachment(struct gl_context *ctx,
    /* always update these fields */
    att->TextureLevel = level;
    att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
-   att->Zoffset = zoffset;
+   att->Zoffset = layer;
    att->Layered = layered;
    att->Complete = GL_FALSE;
 
@@ -2563,14 +2563,7 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
 
 /**
  * Common code called by gl*FramebufferTexture*() to retrieve the correct
- * texture object pointer and check for associated errors.
- *
- * \param textarget is the textarget that was passed to the
- * glFramebufferTexture...() function, or 0 if the corresponding function
- * doesn't have a textarget parameter.
- *
- * \param layered is true if this function was called from
- * gl*FramebufferTexture(), false otherwise.
+ * texture object pointer.
  *
  * \param texObj where the pointer to the texture object is returned.  Note
  * that a successful call may return texObj = NULL.
@@ -2578,20 +2571,12 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
  * \return true if no errors, false if errors
  */
 static bool
-get_texture_for_framebuffer(struct gl_context *ctx,
-                            GLuint texture, GLenum textarget,
-                            GLint level, GLuint zoffset, GLboolean *layered,
-                            const char *caller,
+get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture,
+                            bool layered, const char *caller,
                             struct gl_texture_object **texObj)
 {
-   GLenum maxLevelsTarget;
-   GLboolean err = GL_TRUE;
-
    *texObj = NULL; /* This will get returned if texture = 0. */
 
-   /* The textarget, level, and zoffset parameters are only validated if
-    * texture is non-zero.
-    */
    if (!texture)
       return true;
 
@@ -2602,31 +2587,45 @@ get_texture_for_framebuffer(struct gl_context *ctx,
        * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
        * Managing Framebuffer Objects specifies a different error
        * depending upon the calling function (PDF pages 325-328).
-       * *FramebufferTexture (where *layered = GL_TRUE) throws invalid
+       * *FramebufferTexture (where layered = GL_TRUE) throws invalid
        * value, while the other commands throw invalid operation (where
-       * *layered = GL_FALSE).
+       * layered = GL_FALSE).
        */
-      const GLenum error = *layered ? GL_INVALID_VALUE :
+      const GLenum error = layered ? GL_INVALID_VALUE :
                            GL_INVALID_OPERATION;
       _mesa_error(ctx, error,
                   "%s(non-existent texture %u)", caller, texture);
       return false;
    }
 
-   if (textarget == 0) {
-      if (*layered) {
-         /* We're being called by gl*FramebufferTexture() and textarget
-          * is not used.
-          */
-         switch ((*texObj)->Target) {
+   return true;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTexture() to verify the texture target
+ * and decide whether or not the attachment should truly be considered
+ * layered.
+ *
+ * \param layered true if attachment should be considered layered, false if
+ * not
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_layered_texture_target(struct gl_context *ctx, GLenum target,
+                             const char *caller, GLboolean *layered)
+{
+   *layered = GL_TRUE;
+
+         switch (target) {
          case GL_TEXTURE_3D:
          case GL_TEXTURE_1D_ARRAY_EXT:
          case GL_TEXTURE_2D_ARRAY_EXT:
          case GL_TEXTURE_CUBE_MAP:
          case GL_TEXTURE_CUBE_MAP_ARRAY:
          case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
-            err = false;
-            break;
+            return true;
          case GL_TEXTURE_1D:
          case GL_TEXTURE_2D:
          case GL_TEXTURE_RECTANGLE:
@@ -2635,74 +2634,187 @@ get_texture_for_framebuffer(struct gl_context *ctx,
              * glFramebufferTexture(), but since they aren't layered, it
              * is equivalent to calling glFramebufferTexture{1D,2D}().
              */
-            err = false;
-            *layered = false;
-            textarget = (*texObj)->Target;
-            break;
-         default:
-            err = true;
-            break;
+            *layered = GL_FALSE;
+            return true;
          }
-      } else {
+
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(invalid texture target %s)", caller,
+                  _mesa_lookup_enum_by_nr(target));
+      return false;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTextureLayer() to verify the texture
+ * target.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_texture_target(struct gl_context *ctx, GLenum target,
+                     const char *caller)
+{
          /* We're being called by glFramebufferTextureLayer() and
           * textarget is not used.  The only legal texture types for
           * that function are 3D and 1D/2D arrays textures.
           */
-         err = ((*texObj)->Target != GL_TEXTURE_3D) &&
-            ((*texObj)->Target != GL_TEXTURE_1D_ARRAY) &&
-            ((*texObj)->Target != GL_TEXTURE_2D_ARRAY) &&
-            ((*texObj)->Target != GL_TEXTURE_CUBE_MAP_ARRAY) &&
-            ((*texObj)->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
+         switch (target) {
+         case GL_TEXTURE_3D:
+         case GL_TEXTURE_1D_ARRAY:
+         case GL_TEXTURE_2D_ARRAY:
+         case GL_TEXTURE_CUBE_MAP_ARRAY:
+         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+            return true;
+         }
+
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(invalid texture target %s)", caller,
+                  _mesa_lookup_enum_by_nr(target));
+      return false;
+}
+
+
+/**
+ * Common code called by glFramebufferTexture*D() to verify the texture
+ * target.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_textarget(struct gl_context *ctx, int dims, GLenum target,
+                GLenum textarget, const char *caller)
+{
+   bool err = false;
+
+   switch (dims) {
+   case 1:
+      switch (textarget) {
+      case GL_TEXTURE_1D:
+         break;
+      case GL_TEXTURE_1D_ARRAY:
+         err = !ctx->Extensions.EXT_texture_array;
+         break;
+      default:
+         err = true;
       }
+      break;
+   case 2:
+      switch (textarget) {
+      case GL_TEXTURE_2D:
+         break;
+      case GL_TEXTURE_RECTANGLE:
+         err = _mesa_is_gles(ctx)
+            || !ctx->Extensions.NV_texture_rectangle;
+         break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+         err = !ctx->Extensions.ARB_texture_cube_map;
+         break;
+      case GL_TEXTURE_2D_ARRAY:
+         err = (_mesa_is_gles(ctx) && ctx->Version < 30)
+               || !ctx->Extensions.EXT_texture_array;
+         break;
+      case GL_TEXTURE_2D_MULTISAMPLE:
+      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+         err = _mesa_is_gles(ctx)
+               || !ctx->Extensions.ARB_texture_multisample;
+         break;
+      default:
+         err = true;
+      }
+      break;
+   case 3:
+      if (textarget != GL_TEXTURE_3D)
+         err = true;
+      break;
+   default:
+      err = true;
    }
-   else {
-      /* Make sure textarget is consistent with the texture's type */
-      err = ((*texObj)->Target == GL_TEXTURE_CUBE_MAP)
-          ? !_mesa_is_cube_face(textarget)
-          : ((*texObj)->Target != textarget);
+
+   if (err) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(invalid textarget %s)",
+                  caller, _mesa_lookup_enum_by_nr(textarget));
+      return false;
    }
 
+   /* Make sure textarget is consistent with the texture's type */
+   err = (target == GL_TEXTURE_CUBE_MAP) ?
+          !_mesa_is_cube_face(textarget): (target != textarget);
+
    if (err) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(invalid or mismatched texture target)", caller);
+                  "%s(mismatched texture target)", caller);
       return false;
    }
 
+   return true;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTextureLayer() and
+ * glFramebufferTexture3D() to validate the layer.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_layer(struct gl_context *ctx, GLenum target, GLint layer,
+            const char *caller)
+{
    /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
     * spec says:
     *
     *    "An INVALID_VALUE error is generated if texture is non-zero
     *     and layer is negative."
     */
-   if (zoffset < 0) {
+   if (layer < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "%s(layer %u < 0)", caller, zoffset);
+                  "%s(layer %u < 0)", caller, layer);
       return false;
    }
 
-   if ((*texObj)->Target == GL_TEXTURE_3D) {
+   if (target == GL_TEXTURE_3D) {
       const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
-      if (zoffset >= maxSize) {
+      if (layer >= maxSize) {
          _mesa_error(ctx, GL_INVALID_VALUE,
-                     "%s(invalid zoffset %u)", caller, zoffset);
+                     "%s(invalid layer %u)", caller, layer);
          return false;
       }
    }
-   else if (((*texObj)->Target == GL_TEXTURE_1D_ARRAY) ||
-            ((*texObj)->Target == GL_TEXTURE_2D_ARRAY) ||
-            ((*texObj)->Target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
-            ((*texObj)->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
-      if (zoffset >= ctx->Const.MaxArrayTextureLayers) {
+   else if ((target == GL_TEXTURE_1D_ARRAY) ||
+            (target == GL_TEXTURE_2D_ARRAY) ||
+            (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
+            (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
+      if (layer >= ctx->Const.MaxArrayTextureLayers) {
          _mesa_error(ctx, GL_INVALID_VALUE,
                      "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
-                     caller, zoffset);
+                     caller, layer);
          return false;
       }
    }
 
-   maxLevelsTarget = textarget ? textarget : (*texObj)->Target;
+   return true;
+}
+
+
+/**
+ * Common code called by all gl*FramebufferTexture*() entry points to verify
+ * the level.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_level(struct gl_context *ctx, GLenum target, GLint level,
+            const char *caller)
+{
    if ((level < 0) ||
-       (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
+       (level >= _mesa_max_texture_levels(ctx, target))) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "%s(invalid level %d)", caller, level);
       return false;
@@ -2716,7 +2828,7 @@ void
 _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
                           GLenum attachment,
                           struct gl_texture_object *texObj, GLenum textarget,
-                          GLint level, GLuint zoffset, GLboolean layered,
+                          GLint level, GLuint layer, GLboolean layered,
                           const char *caller)
 {
    struct gl_renderbuffer_attachment *att;
@@ -2745,7 +2857,7 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
           level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
           _mesa_tex_target_to_face(textarget) ==
           fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
-          zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
+          layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
          /* The texture object is already attached to the stencil attachment
           * point. Don't create a new renderbuffer; just reuse the stencil
           * attachment's. This is required to prevent a GL error in
@@ -2758,13 +2870,13 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
                  level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
                  _mesa_tex_target_to_face(textarget) ==
                  fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
-                 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
+                 layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
          /* As above, but with depth and stencil transposed. */
          reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
                                               BUFFER_DEPTH);
       } else {
          set_texture_attachment(ctx, fb, att, texObj, textarget,
-                                level, zoffset, layered);
+                                level, layer, layered);
 
          if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
             /* Above we created a new renderbuffer and attached it to the
@@ -2801,166 +2913,69 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
 }
 
 
-void GLAPIENTRY
-_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
-                           GLenum textarget, GLuint texture, GLint level)
+static void
+framebuffer_texture_with_dims(int dims, GLenum target,
+                              GLenum attachment, GLenum textarget,
+                              GLuint texture, GLint level, GLint layer,
+                              const char *caller)
 {
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb;
    struct gl_texture_object *texObj;
-   GLboolean layered = GL_FALSE;
-
-   if (texture != 0) {
-      GLboolean error;
-
-      switch (textarget) {
-      case GL_TEXTURE_1D:
-         error = GL_FALSE;
-         break;
-      case GL_TEXTURE_1D_ARRAY:
-         error = !ctx->Extensions.EXT_texture_array;
-         break;
-      default:
-         error = GL_TRUE;
-      }
-
-      if (error) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glFramebufferTexture1D(invalid textarget %s)",
-                     _mesa_lookup_enum_by_nr(textarget));
-         return;
-      }
-   }
 
    /* Get the framebuffer object */
    fb = get_framebuffer_target(ctx, target);
    if (!fb) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glFramebufferTexture1D(invalid target %s)",
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
                   _mesa_lookup_enum_by_nr(target));
       return;
    }
 
    /* Get the texture object */
-   if (!get_texture_for_framebuffer(ctx, texture, textarget, level, 0,
-                                    &layered, "glFramebufferTexture1D",
-                                    &texObj)) {
-      /* Error already recorded */
+   if (!get_texture_for_framebuffer(ctx, texture, false, caller, &texObj))
       return;
+
+   if (texObj) {
+      if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
+         return;
+
+      if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
+         return;
    }
 
+   if (!check_level(ctx, textarget, level, caller))
+      return;
+
    _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
-                             0, layered, "glFramebufferTexture1D");
+                             layer, GL_FALSE, caller);
 }
 
 
 void GLAPIENTRY
-_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
+_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
                            GLenum textarget, GLuint texture, GLint level)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *fb;
-   struct gl_texture_object *texObj;
-   GLboolean layered = GL_FALSE;
-
-   if (texture != 0) {
-      GLboolean error;
-
-      switch (textarget) {
-      case GL_TEXTURE_2D:
-         error = GL_FALSE;
-         break;
-      case GL_TEXTURE_RECTANGLE:
-         error = _mesa_is_gles(ctx)
-            || !ctx->Extensions.NV_texture_rectangle;
-         break;
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-         error = !ctx->Extensions.ARB_texture_cube_map;
-         break;
-      case GL_TEXTURE_2D_ARRAY:
-         error = (_mesa_is_gles(ctx) && ctx->Version < 30)
-            || !ctx->Extensions.EXT_texture_array;
-         break;
-      case GL_TEXTURE_2D_MULTISAMPLE:
-      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
-         error = _mesa_is_gles(ctx)
-            || !ctx->Extensions.ARB_texture_multisample;
-         break;
-      default:
-         error = GL_TRUE;
-      }
-
-      if (error) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glFramebufferTexture2D(invalid textarget %s)",
-                     _mesa_lookup_enum_by_nr(textarget));
-         return;
-      }
-   }
+   framebuffer_texture_with_dims(1, target, attachment, textarget, texture,
+                                 level, 0, "glFramebufferTexture1D");
+}
 
-   /* Get the framebuffer object */
-   fb = get_framebuffer_target(ctx, target);
-   if (!fb) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glFramebufferTexture2D(invalid target %s)",
-                  _mesa_lookup_enum_by_nr(target));
-      return;
-   }
 
-   /* Get the texture object */
-   if (!get_texture_for_framebuffer(ctx, texture, textarget, level, 0,
-                                    &layered, "glFramebufferTexture2D",
-                                    &texObj)) {
-      /* Error already recorded */
-      return;
-   }
-
-   _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
-                             0, layered, "glFramebufferTexture2D");
+void GLAPIENTRY
+_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
+                           GLenum textarget, GLuint texture, GLint level)
+{
+   framebuffer_texture_with_dims(2, target, attachment, textarget, texture,
+                                 level, 0, "glFramebufferTexture2D");
 }
 
 
 void GLAPIENTRY
 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
                            GLenum textarget, GLuint texture,
-                           GLint level, GLint zoffset)
+                           GLint level, GLint layer)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_framebuffer *fb;
-   struct gl_texture_object *texObj;
-   GLboolean layered = GL_FALSE;
-
-   if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glFramebufferTexture3D(invalid textarget %s)",
-                  _mesa_lookup_enum_by_nr(textarget));
-      return;
-   }
-
-   /* Get the framebuffer object */
-   fb = get_framebuffer_target(ctx, target);
-   if (!fb) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glFramebufferTexture3D(invalid target %s)",
-                  _mesa_lookup_enum_by_nr(target));
-      return;
-   }
-
-   /* Get the texture object */
-   if (!get_texture_for_framebuffer(ctx, texture, textarget, level, zoffset,
-                                    &layered, "glFramebufferTexture3D",
-                                    &texObj)) {
-      /* Error already recorded */
-      return;
-   }
-
-   _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
-                             zoffset, layered, "glFramebufferTexture3D");
+   framebuffer_texture_with_dims(3, target, attachment, textarget, texture,
+                                 level, layer, "glFramebufferTexture3D");
 }
 
 
@@ -2971,7 +2986,8 @@ _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb;
    struct gl_texture_object *texObj;
-   GLboolean layered = GL_FALSE;
+
+   const char *func = "glFramebufferTextureLayer";
 
    /* Get the framebuffer object */
    fb = get_framebuffer_target(ctx, target);
@@ -2983,15 +2999,22 @@ _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
    }
 
    /* Get the texture object */
-   if (!get_texture_for_framebuffer(ctx, texture, 0, level, layer,
-                                    &layered, "glFramebufferTextureLayer",
-                                    &texObj)) {
-      /* Error already recorded */
+   if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
       return;
+
+   if (texObj) {
+      if (!check_texture_target(ctx, texObj->Target, func))
+         return;
+
+      if (!check_layer(ctx, texObj->Target, layer, func))
+         return;
+
+      if (!check_level(ctx, texObj->Target, level, func))
+         return;
    }
 
    _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
-                             layer, layered, "glFramebufferTextureLayer");
+                             layer, GL_FALSE, func);
 }
 
 
@@ -3002,26 +3025,31 @@ _mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb;
    struct gl_texture_object *texObj;
-   GLboolean layered = GL_FALSE;
+
+   const char *func = "glNamedFramebufferTextureLayer";
 
    /* Get the framebuffer object */
-   fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
-                                     "glNamedFramebufferTextureLayer");
+   fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
    if (!fb)
       return;
 
    /* Get the texture object */
-   if (!get_texture_for_framebuffer(ctx, texture, 0, level, layer,
-                                    &layered,
-                                    "glNamedFramebufferTextureLayer",
-                                    &texObj)) {
-      /* Error already recorded */
+   if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
       return;
+
+   if (texObj) {
+      if (!check_texture_target(ctx, texObj->Target, func))
+         return;
+
+      if (!check_layer(ctx, texObj->Target, layer, func))
+         return;
+
+      if (!check_level(ctx, texObj->Target, level, func))
+         return;
    }
 
    _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
-                             layer, layered,
-                             "glNamedFramebufferTextureLayer");
+                             layer, GL_FALSE, func);
 }
 
 
@@ -3032,7 +3060,9 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment,
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb;
    struct gl_texture_object *texObj;
-   GLboolean layered = GL_TRUE;
+   GLboolean layered;
+
+   const char *func = "FramebufferTexture";
 
    if (!_mesa_has_geometry_shaders(ctx)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -3050,15 +3080,19 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment,
    }
 
    /* Get the texture object */
-   if (!get_texture_for_framebuffer(ctx, texture, 0, level, 0,
-                                    &layered, "glFramebufferTexture",
-                                    &texObj)) {
-      /* Error already recorded */
+   if (!get_texture_for_framebuffer(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;
    }
 
    _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
-                             0, layered, "glFramebufferTexture");
+                             0, layered, func);
 }
 
 
@@ -3069,7 +3103,9 @@ _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
    GET_CURRENT_CONTEXT(ctx);
    struct gl_framebuffer *fb;
    struct gl_texture_object *texObj;
-   GLboolean layered = GL_TRUE;
+   GLboolean layered;
+
+   const char *func = "glNamedFramebufferTexture";
 
    if (!_mesa_has_geometry_shaders(ctx)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -3078,21 +3114,25 @@ _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
    }
 
    /* Get the framebuffer object */
-   fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
-                                     "glNamedFramebufferTexture");
+   fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
    if (!fb)
       return;
 
    /* Get the texture object */
-   if (!get_texture_for_framebuffer(ctx, texture, 0, level, 0,
-                                    &layered, "glNamedFramebufferTexture",
-                                    &texObj)) {
-      /* Error already recorded */
+   if (!get_texture_for_framebuffer(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;
    }
 
    _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
-                             0, layered, "glNamedFramebufferTexture");
+                             0, layered, func);
 }
 
 
index 81159d0..e68762b 100644 (file)
@@ -119,7 +119,7 @@ extern void
 _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
                           GLenum attachment,
                           struct gl_texture_object *texObj, GLenum textarget,
-                          GLint level, GLuint zoffset, GLboolean layered,
+                          GLint level, GLuint layer, GLboolean layered,
                           const char *caller);
 
 
@@ -206,7 +206,7 @@ _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
 extern void GLAPIENTRY
 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
                               GLenum textarget, GLuint texture,
-                              GLint level, GLint zoffset);
+                              GLint level, GLint layer);
 
 extern void GLAPIENTRY
 _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,