summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2014-06-27 15:34:53 -0700
committerJason Ekstrand <[email protected]>2014-08-11 11:20:23 -0700
commit41b6460e08bf878ec3372937f63bef2a7b63c484 (patch)
treecd371b795ea620fee2feaba4851c3aa01bee4176 /src/mesa
parent23d782067ae834ad53522b46638ea21c62e94ca3 (diff)
mesa: Add GL API support for ARB_copy_image
This adds the API entrypoint, error checking logic, and a driver hook for the ARB_copy_image extension. v2: Fix a typo in ARB_copy_image.xml and add it to the makefile v3: Put ARB_copy_image.xml in the right place alphebetically in the makefile and properly prefix the commit message v4: Fixed some line wrapping and added a check for null v5: Check for incomplete renderbuffers Signed-off-by: Jason Ekstrand <[email protected]> Reviewed-by: Juha-Pekka Heikkila <[email protected]> Reviewed-by: Neil Roberts <[email protected]> v6: Update dispatch_sanity for the addition of CopyImageSubData
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/Makefile.sources1
-rw-r--r--src/mesa/main/copyimage.c356
-rw-r--r--src/mesa/main/copyimage.h49
-rw-r--r--src/mesa/main/dd.h16
-rw-r--r--src/mesa/main/extensions.c1
-rw-r--r--src/mesa/main/mtypes.h1
-rw-r--r--src/mesa/main/tests/dispatch_sanity.cpp2
-rw-r--r--src/mesa/main/textureview.c36
-rw-r--r--src/mesa/main/textureview.h4
9 files changed, 446 insertions, 20 deletions
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index 45c53ca0e0e..d02c174d912 100644
--- a/src/mesa/Makefile.sources
+++ b/src/mesa/Makefile.sources
@@ -31,6 +31,7 @@ MAIN_FILES = \
$(SRCDIR)main/condrender.c \
$(SRCDIR)main/context.c \
$(SRCDIR)main/convolve.c \
+ $(SRCDIR)main/copyimage.c \
$(SRCDIR)main/cpuinfo.c \
$(SRCDIR)main/debug.c \
$(SRCDIR)main/depth.c \
diff --git a/src/mesa/main/copyimage.c b/src/mesa/main/copyimage.c
new file mode 100644
index 00000000000..e1110dd7e00
--- /dev/null
+++ b/src/mesa/main/copyimage.c
@@ -0,0 +1,356 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jason Ekstrand <[email protected]>
+ */
+
+#include "glheader.h"
+#include "errors.h"
+#include "enums.h"
+#include "copyimage.h"
+#include "teximage.h"
+#include "texobj.h"
+#include "fbobject.h"
+#include "textureview.h"
+
+static bool
+prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level,
+ struct gl_texture_object **tex_obj,
+ struct gl_texture_image **tex_image, GLuint *tmp_tex,
+ const char *dbg_prefix)
+{
+ struct gl_renderbuffer *rb;
+
+ if (name == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sName = %d)", dbg_prefix, name);
+ return false;
+ }
+
+ /*
+ * INVALID_ENUM is generated
+ * * if either <srcTarget> or <dstTarget>
+ * - is not RENDERBUFFER or a valid non-proxy texture target
+ * - is TEXTURE_BUFFER, or
+ * - is one of the cubemap face selectors described in table 3.17,
+ */
+ switch (*target) {
+ case GL_RENDERBUFFER:
+ /* Not a texture target, but valid */
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ /* These are all valid */
+ break;
+ case GL_TEXTURE_EXTERNAL_OES:
+ /* Only exists in ES */
+ case GL_TEXTURE_BUFFER:
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
+ _mesa_lookup_enum_by_nr(*target));
+ return false;
+ }
+
+ if (*target == GL_RENDERBUFFER) {
+ rb = _mesa_lookup_renderbuffer(ctx, name);
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
+ return false;
+ }
+
+ if (!rb->Name) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubData(%sName incomplete)", dbg_prefix);
+ return false;
+ }
+
+ if (level != 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
+ return false;
+ }
+
+ if (rb->NumSamples > 1)
+ *target = GL_TEXTURE_2D_MULTISAMPLE;
+ else
+ *target = GL_TEXTURE_2D;
+
+ *tmp_tex = 0;
+ _mesa_GenTextures(1, tmp_tex);
+ if (*tmp_tex == 0)
+ return false; /* Error already set by GenTextures */
+
+ _mesa_BindTexture(*target, *tmp_tex);
+ *tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
+ *tex_image = _mesa_get_tex_image(ctx, *tex_obj, *target, 0);
+
+ if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, *tex_image)) {
+ _mesa_problem(ctx, "Failed to create texture from renderbuffer");
+ return false;
+ }
+
+ if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
+ rb->NeedsFinishRenderTexture = true;
+ ctx->Driver.FinishRenderTexture(ctx, rb);
+ }
+ } else {
+ *tex_obj = _mesa_lookup_texture(ctx, name);
+ if (!*tex_obj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
+ return false;
+ }
+
+ _mesa_test_texobj_completeness(ctx, *tex_obj);
+ if (!(*tex_obj)->_BaseComplete ||
+ (level != 0 && !(*tex_obj)->_MipmapComplete)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubData(%sName incomplete)", dbg_prefix);
+ return false;
+ }
+
+ if ((*tex_obj)->Target != *target) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
+ _mesa_lookup_enum_by_nr(*target));
+ return false;
+ }
+
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level);
+ return false;
+ }
+
+ *tex_image = _mesa_select_tex_image(ctx, *tex_obj, *target, level);
+ if (!*tex_image) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image,
+ int x, int y, int z, int width, int height, int depth,
+ const char *dbg_prefix)
+{
+ if (width < 0 || height < 0 || depth < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sWidth, %sHeight, or %sDepth is negative)",
+ dbg_prefix, dbg_prefix, dbg_prefix);
+ return false;
+ }
+
+ if (x < 0 || y < 0 || z < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sX, %sY, or %sZ is negative)",
+ dbg_prefix, dbg_prefix, dbg_prefix);
+ return false;
+ }
+
+ if (x + width > tex_image->Width) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sX or %sWidth exceeds image bounds)",
+ dbg_prefix, dbg_prefix);
+ return false;
+ }
+
+ switch (tex_image->TexObject->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_1D_ARRAY:
+ if (y != 0 || height != 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sY or %sHeight exceeds image bounds)",
+ dbg_prefix, dbg_prefix);
+ return false;
+ }
+ break;
+ default:
+ if (y + height > tex_image->Height) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sY or %sHeight exceeds image bounds)",
+ dbg_prefix, dbg_prefix);
+ return false;
+ }
+ break;
+ }
+
+ switch (tex_image->TexObject->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_RECTANGLE:
+ if (z != 0 || depth != 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
+ dbg_prefix, dbg_prefix);
+ return false;
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ if (z < 0 || z + depth > 6) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
+ dbg_prefix, dbg_prefix);
+ return false;
+ }
+ break;
+ case GL_TEXTURE_1D_ARRAY:
+ if (z < 0 || z + depth > tex_image->Height) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
+ dbg_prefix, dbg_prefix);
+ return false;
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ case GL_TEXTURE_3D:
+ if (z < 0 || z + depth > tex_image->Depth) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
+ dbg_prefix, dbg_prefix);
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
+void
+_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
+ GLint srcX, GLint srcY, GLint srcZ,
+ GLuint dstName, GLenum dstTarget, GLint dstLevel,
+ GLint dstX, GLint dstY, GLint dstZ,
+ GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint tmpTexNames[2] = { 0, 0 };
+ struct gl_texture_object *srcTexObj, *dstTexObj;
+ struct gl_texture_image *srcTexImage, *dstTexImage;
+ GLuint src_bw, src_bh, dst_bw, dst_bh;
+ int i, srcNewZ, dstNewZ, Bpt;
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
+ "%u, %s, %d, %d, %d, %d, "
+ "%d, %d, %d)\n",
+ srcName, _mesa_lookup_enum_by_nr(srcTarget), srcLevel,
+ srcX, srcY, srcZ,
+ dstName, _mesa_lookup_enum_by_nr(dstTarget), dstLevel,
+ dstX, dstY, dstZ,
+ srcWidth, srcHeight, srcWidth);
+
+ if (!prepare_target(ctx, srcName, &srcTarget, srcLevel,
+ &srcTexObj, &srcTexImage, &tmpTexNames[0], "src"))
+ goto cleanup;
+
+ if (!prepare_target(ctx, dstName, &dstTarget, dstLevel,
+ &dstTexObj, &dstTexImage, &tmpTexNames[1], "dst"))
+ goto cleanup;
+
+ _mesa_get_format_block_size(srcTexImage->TexFormat, &src_bw, &src_bh);
+ if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
+ (srcWidth % src_bw != 0) || (srcHeight % src_bh != 0)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(unaligned src rectangle)");
+ goto cleanup;
+ }
+
+ _mesa_get_format_block_size(dstTexImage->TexFormat, &dst_bw, &dst_bh);
+ if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(unaligned dst rectangle)");
+ goto cleanup;
+ }
+
+ /* Very simple sanity check. This is sufficient if one of the textures
+ * is compressed. */
+ Bpt = _mesa_get_format_bytes(srcTexImage->TexFormat);
+ if (_mesa_get_format_bytes(dstTexImage->TexFormat) != Bpt) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubData(internalFormat mismatch)");
+ goto cleanup;
+ }
+
+ if (!check_region_bounds(ctx, srcTexImage, srcX, srcY, srcZ,
+ srcWidth, srcHeight, srcDepth, "src"))
+ goto cleanup;
+
+ if (!check_region_bounds(ctx, dstTexImage, dstX, dstY, dstZ,
+ (srcWidth / src_bw) * dst_bw,
+ (srcHeight / src_bh) * dst_bh, srcDepth, "dst"))
+ goto cleanup;
+
+ if (_mesa_is_format_compressed(srcTexImage->TexFormat)) {
+ /* XXX: Technically, we should probaby do some more specific checking
+ * here. However, this should be sufficient for all compressed
+ * formats that mesa supports since it is a direct memory copy.
+ */
+ } else if (_mesa_is_format_compressed(dstTexImage->TexFormat)) {
+ } else if (_mesa_texture_view_compatible_format(ctx,
+ srcTexImage->InternalFormat,
+ dstTexImage->InternalFormat)) {
+ } else {
+ return; /* Error loged by _mesa_texture_view_compatible_format */
+ }
+
+ for (i = 0; i < srcDepth; ++i) {
+ if (srcTexObj->Target == GL_TEXTURE_CUBE_MAP) {
+ srcTexImage = srcTexObj->Image[i + srcZ][srcLevel];
+ srcNewZ = 0;
+ } else {
+ srcNewZ = srcZ + i;
+ }
+
+ if (dstTexObj->Target == GL_TEXTURE_CUBE_MAP) {
+ dstTexImage = dstTexObj->Image[i + dstZ][dstLevel];
+ dstNewZ = 0;
+ } else {
+ dstNewZ = dstZ + i;
+ }
+
+ ctx->Driver.CopyImageSubData(ctx, srcTexImage, srcX, srcY, srcNewZ,
+ dstTexImage, dstX, dstY, dstNewZ,
+ srcWidth, srcHeight);
+ }
+
+cleanup:
+ _mesa_DeleteTextures(2, tmpTexNames);
+}
diff --git a/src/mesa/main/copyimage.h b/src/mesa/main/copyimage.h
new file mode 100644
index 00000000000..40e95b66312
--- /dev/null
+++ b/src/mesa/main/copyimage.h
@@ -0,0 +1,49 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jason Ekstrand <[email protected]>
+ */
+
+
+#ifndef COPYIMAGE_H
+#define COPYIMAGE_H
+
+#include "mtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void GLAPIENTRY
+_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
+ GLint srcX, GLint srcY, GLint srcZ,
+ GLuint destName, GLenum destTarget, GLint destLevel,
+ GLint destX, GLint destY, GLint destZ,
+ GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* COPYIMAGE_H */
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 89765351e14..c130b14a522 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -269,6 +269,22 @@ struct dd_function_table {
GLsizei width, GLsizei height);
/**
+ * Called by glCopyImageSubData().
+ *
+ * This function should copy one 2-D slice from srcTexImage to
+ * dstTexImage. If one of the textures is 3-D or is a 1-D or 2-D array
+ * texture, this function will be called multiple times: once for each
+ * slice. If one of the textures is a cube map, this function will be
+ * called once for each face to be copied.
+ */
+ void (*CopyImageSubData)(struct gl_context *ctx,
+ struct gl_texture_image *src_image,
+ int src_x, int src_y, int src_z,
+ struct gl_texture_image *dstTexImage,
+ int dst_x, int dst_y, int dst_z,
+ int src_width, int src_height);
+
+ /**
* Called by glGenerateMipmap() or when GL_GENERATE_MIPMAP_SGIS is enabled.
* Note that if the texture is a cube map, the <target> parameter will
* indicate which cube face to generate (GL_POSITIVE/NEGATIVE_X/Y/Z).
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 9ac8377a475..d60838a1ce7 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -95,6 +95,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_compressed_texture_pixel_storage", o(dummy_true), GL, 2011 },
{ "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 },
{ "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 },
+ { "GL_ARB_copy_image", o(ARB_copy_image), GL, 2012 },
{ "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 },
{ "GL_ARB_debug_output", o(dummy_true), GL, 2009 },
{ "GL_ARB_depth_buffer_float", o(ARB_depth_buffer_float), GL, 2008 },
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index ff130da15d0..e141ac65893 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -3552,6 +3552,7 @@ struct gl_extensions
GLboolean ARB_color_buffer_float;
GLboolean ARB_compute_shader;
GLboolean ARB_conservative_depth;
+ GLboolean ARB_copy_image;
GLboolean ARB_depth_buffer_float;
GLboolean ARB_depth_clamp;
GLboolean ARB_depth_texture;
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index 5e751f493ff..04fa86b72db 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -838,7 +838,7 @@ const struct function gl_core_functions_possible[] = {
// { "glClearNamedBufferSubDataEXT", 43, -1 }, // XXX: Add to xml
{ "glDispatchCompute", 43, -1 },
{ "glDispatchComputeIndirect", 43, -1 },
-// { "glCopyImageSubData", 43, -1 }, // XXX: Add to xml
+ { "glCopyImageSubData", 43, -1 },
{ "glTextureView", 43, -1 },
{ "glBindVertexBuffer", 43, -1 },
{ "glVertexAttribFormat", 43, -1 },
diff --git a/src/mesa/main/textureview.c b/src/mesa/main/textureview.c
index 77a3b782b5a..b3521e2190e 100644
--- a/src/mesa/main/textureview.c
+++ b/src/mesa/main/textureview.c
@@ -320,15 +320,11 @@ target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget)
* If an error is found, record it with _mesa_error()
* \return false if any error, true otherwise.
*/
-static bool
-compatible_format(struct gl_context *ctx, const struct gl_texture_object *origTexObj,
- GLenum internalformat)
+GLboolean
+_mesa_texture_view_compatible_format(struct gl_context *ctx,
+ GLenum origInternalFormat,
+ GLenum newInternalFormat)
{
- /* Level 0 of a texture created by glTextureStorage or glTextureView
- * is always defined.
- */
- struct gl_texture_image *texImage = origTexObj->Image[0][0];
- GLint origInternalFormat = texImage->InternalFormat;
unsigned int origViewClass, newViewClass;
/* The two textures' internal formats must be compatible according to
@@ -337,19 +333,15 @@ compatible_format(struct gl_context *ctx, const struct gl_texture_object *origTe
* The internal formats must be identical if not in that table,
* or an INVALID_OPERATION error is generated.
*/
- if (origInternalFormat == internalformat)
- return true;
+ if (origInternalFormat == newInternalFormat)
+ return GL_TRUE;
origViewClass = lookup_view_class(ctx, origInternalFormat);
- newViewClass = lookup_view_class(ctx, internalformat);
+ newViewClass = lookup_view_class(ctx, newInternalFormat);
if ((origViewClass == newViewClass) && origViewClass != false)
- return true;
+ return GL_TRUE;
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTextureView(internalformat %s not compatible with origtexture %s)",
- _mesa_lookup_enum_by_nr(internalformat),
- _mesa_lookup_enum_by_nr(origInternalFormat));
- return false;
+ return GL_FALSE;
}
/**
* Helper function for TexStorage and teximagemultisample to set immutable
@@ -512,8 +504,14 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture,
return;
}
- if (!compatible_format(ctx, origTexObj, internalformat)) {
- return; /* Error logged */
+ if (!_mesa_texture_view_compatible_format(ctx,
+ origTexObj->Image[0][0]->InternalFormat,
+ internalformat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureView(internalformat %s not compatible with origtexture %s)",
+ _mesa_lookup_enum_by_nr(internalformat),
+ _mesa_lookup_enum_by_nr(origTexObj->Image[0][0]->InternalFormat));
+ return;
}
texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
diff --git a/src/mesa/main/textureview.h b/src/mesa/main/textureview.h
index 3088ac19393..549a13cd809 100644
--- a/src/mesa/main/textureview.h
+++ b/src/mesa/main/textureview.h
@@ -29,6 +29,10 @@
#ifndef TEXTUREVIEW_H
#define TEXTUREVIEW_H
+GLboolean
+_mesa_texture_view_compatible_format(struct gl_context *ctx,
+ GLenum origInternalFormat,
+ GLenum newInternalFormat);
extern void GLAPIENTRY
_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture,