mesa: Support GL_TEXTURE_BUFFER in GetTexLevelParameter[if]v in GL 3.1+.
authorKenneth Graunke <kenneth@whitecape.org>
Mon, 11 Jun 2012 02:33:01 +0000 (19:33 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 17 Aug 2012 16:14:36 +0000 (09:14 -0700)
The OpenGL 3.1 specification explicitly allows this.  Oddly, the
ARB_texture_buffer_object spec's issues section claims this isn't
allowed, but proceeds to explain that the extension simply doesn't edit
the underlying spec to allow it, and thus it didn't appear in the list
of legal texture targets.

Thus, this patch legalizes it only in 3.1+ contexts, but still returns
INVALID_ENUM in earlier contexts that expose ARB_texture_buffer_object.

Unfortunately, the behavior of the call is horrendously undefined.

Fixes oglconform's tbo/negative.textureParams test.

v2: Require desktop OpenGL.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/main/teximage.c
src/mesa/main/texparam.c

index 9deaab2ad943064510963d2896c3f417472e0f02..fd02a1be23f6e966e37abc69907967f5c03a0146 100644 (file)
@@ -967,6 +967,9 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
               ctx->Extensions.EXT_texture_array)
          ? ctx->Const.MaxTextureLevels : 0;
    case GL_TEXTURE_BUFFER:
+      return _mesa_is_desktop_gl(ctx) &&
+         (ctx->Extensions.ARB_texture_buffer_object ||
+          (ctx->Version >= 31)) ? 1 : 0;
    case GL_TEXTURE_EXTERNAL_OES:
       /* fall-through */
    default:
index 7285c47d1731240e5dc3799979e9a32533283207..8a5abe5e1cc77a889727ee4ed90d601da25afeb4 100644 (file)
@@ -899,6 +899,25 @@ legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target)
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
       return (ctx->Extensions.MESA_texture_array ||
               ctx->Extensions.EXT_texture_array);
+   case GL_TEXTURE_BUFFER:
+      /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts,
+       * but not in earlier versions that expose ARB_texture_buffer_object.
+       *
+       * From the ARB_texture_buffer_object spec:
+       * "(7) Do buffer textures support texture parameters (TexParameter) or
+       *      queries (GetTexParameter, GetTexLevelParameter, GetTexImage)?
+       *
+       *    RESOLVED:  No. [...] Note that the spec edits above don't add
+       *    explicit error language for any of these cases.  That is because
+       *    each of the functions enumerate the set of valid <target>
+       *    parameters.  Not editing the spec to allow TEXTURE_BUFFER_ARB in
+       *    these cases means that target is not legal, and an INVALID_ENUM
+       *    error should be generated."
+       *
+       * From the OpenGL 3.1 spec:
+       * "target may also be TEXTURE_BUFFER, indicating the texture buffer."
+       */
+      return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
    default:
       return GL_FALSE;
    }
@@ -1052,6 +1071,110 @@ invalid_pname:
 }
 
 
+static void
+get_tex_level_parameter_buffer(struct gl_context *ctx,
+                               struct gl_texture_object *texObj,
+                               GLenum target, GLint level,
+                               GLenum pname, GLint *params)
+{
+   struct gl_buffer_object *bo = texObj->BufferObject;
+   gl_format texFormat = texObj->_BufferObjectFormat;
+   GLenum internalFormat = texObj->BufferObjectFormat;
+   GLenum baseFormat = _mesa_get_format_base_format(texFormat);
+
+   if (!bo) {
+      /* undefined texture buffer object */
+      *params = pname == GL_TEXTURE_COMPONENTS ? 1 : 0;
+      return;
+   }
+
+   switch (pname) {
+      case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
+         *params = bo->Name;
+         break;
+      case GL_TEXTURE_WIDTH:
+         *params = bo->Size;
+         break;
+      case GL_TEXTURE_HEIGHT:
+      case GL_TEXTURE_DEPTH:
+      case GL_TEXTURE_BORDER:
+      case GL_TEXTURE_SHARED_SIZE:
+      case GL_TEXTURE_COMPRESSED:
+         *params = 0;
+         break;
+      case GL_TEXTURE_INTERNAL_FORMAT:
+         *params = internalFormat;
+         break;
+      case GL_TEXTURE_RED_SIZE:
+      case GL_TEXTURE_GREEN_SIZE:
+      case GL_TEXTURE_BLUE_SIZE:
+      case GL_TEXTURE_ALPHA_SIZE:
+         if (_mesa_base_format_has_channel(baseFormat, pname))
+            *params = _mesa_get_format_bits(texFormat, pname);
+         else
+            *params = 0;
+         break;
+      case GL_TEXTURE_INTENSITY_SIZE:
+      case GL_TEXTURE_LUMINANCE_SIZE:
+         if (_mesa_base_format_has_channel(baseFormat, pname)) {
+            *params = _mesa_get_format_bits(texFormat, pname);
+            if (*params == 0) {
+               /* intensity or luminance is probably stored as RGB[A] */
+               *params = MIN2(_mesa_get_format_bits(texFormat,
+                                                    GL_TEXTURE_RED_SIZE),
+                              _mesa_get_format_bits(texFormat,
+                                                    GL_TEXTURE_GREEN_SIZE));
+            }
+         } else {
+            *params = 0;
+         }
+         break;
+      case GL_TEXTURE_DEPTH_SIZE_ARB:
+      case GL_TEXTURE_STENCIL_SIZE_EXT:
+         *params = _mesa_get_format_bits(texFormat, pname);
+         break;
+
+      /* GL_ARB_texture_compression */
+      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
+         if (_mesa_is_format_compressed(texFormat) &&
+             !_mesa_is_proxy_texture(target)) {
+            *params = _mesa_format_image_size(texFormat, bo->Size, 0, 0);
+         } else {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         break;
+
+      /* GL_ARB_texture_float */
+      case GL_TEXTURE_RED_TYPE_ARB:
+      case GL_TEXTURE_GREEN_TYPE_ARB:
+      case GL_TEXTURE_BLUE_TYPE_ARB:
+      case GL_TEXTURE_ALPHA_TYPE_ARB:
+      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
+      case GL_TEXTURE_INTENSITY_TYPE_ARB:
+      case GL_TEXTURE_DEPTH_TYPE_ARB:
+         if (!ctx->Extensions.ARB_texture_float)
+            goto invalid_pname;
+         if (_mesa_base_format_has_channel(baseFormat, pname))
+            *params = _mesa_get_format_datatype(texFormat);
+         else
+            *params = GL_NONE;
+         break;
+
+      default:
+         goto invalid_pname;
+   }
+
+   /* no error if we get here */
+   return;
+
+invalid_pname:
+   _mesa_error(ctx, GL_INVALID_ENUM,
+               "glGetTexLevelParameter[if]v(pname=%s)",
+               _mesa_lookup_enum_by_nr(pname));
+}
+
+
 void GLAPIENTRY
 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
                               GLenum pname, GLfloat *params )
@@ -1096,7 +1219,10 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
 
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
 
-   get_tex_level_parameter_image(ctx, texObj, target, level, pname, params);
+   if (target == GL_TEXTURE_BUFFER)
+      get_tex_level_parameter_buffer(ctx, texObj, target, level, pname, params);
+   else
+      get_tex_level_parameter_image(ctx, texObj, target, level, pname, params);
 }