summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/teximage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/teximage.c')
-rw-r--r--src/mesa/main/teximage.c1953
1 files changed, 758 insertions, 1195 deletions
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 060f34b7f97..c5ae63052a7 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -636,6 +636,47 @@ _mesa_is_proxy_texture(GLenum target)
/**
+ * Return the proxy target which corresponds to the given texture target
+ */
+static GLenum
+get_proxy_target(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ return GL_PROXY_TEXTURE_1D;
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return GL_PROXY_TEXTURE_2D;
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ return GL_PROXY_TEXTURE_3D;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ return GL_PROXY_TEXTURE_CUBE_MAP_ARB;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return GL_PROXY_TEXTURE_RECTANGLE_NV;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ return GL_PROXY_TEXTURE_1D_ARRAY_EXT;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return GL_PROXY_TEXTURE_2D_ARRAY_EXT;
+ default:
+ _mesa_problem(NULL, "unexpected target in get_proxy_target()");
+ return 0;
+ }
+}
+
+
+/**
* Get the texture object that corresponds to the target of the given
* texture unit.
*
@@ -1178,94 +1219,110 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
switch (target) {
case GL_PROXY_TEXTURE_1D:
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
- level >= ctx->Const.MaxTextureLevels) {
- /* bad width or level */
+ if (width < 2 * border || width > 2 + maxSize)
return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
}
return GL_TRUE;
+
case GL_PROXY_TEXTURE_2D:
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
- height < 2 * border || height > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
- level >= ctx->Const.MaxTextureLevels) {
- /* bad width or height or level */
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 2 * border || height > 2 + maxSize)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
}
return GL_TRUE;
+
case GL_PROXY_TEXTURE_3D:
maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
- height < 2 * border || height > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
- depth < 2 * border || depth > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
- level >= ctx->Const.Max3DTextureLevels) {
- /* bad width or height or depth or level */
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 2 * border || height > 2 + maxSize)
+ return GL_FALSE;
+ if (depth < 2 * border || depth > 2 + maxSize)
return GL_FALSE;
+ if (level >= ctx->Const.Max3DTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
+ if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border))
+ return GL_FALSE;
}
return GL_TRUE;
+
case GL_PROXY_TEXTURE_RECTANGLE_NV:
- if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
- height < 0 || height > ctx->Const.MaxTextureRectSize ||
- level != 0) {
- /* bad width or height or level */
+ maxSize = ctx->Const.MaxTextureRectSize;
+ if (width < 0 || width > maxSize)
+ return GL_FALSE;
+ if (height < 0 || height > maxSize)
+ return GL_FALSE;
+ if (level != 0)
return GL_FALSE;
- }
return GL_TRUE;
+
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
- height < 2 * border || height > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
- level >= ctx->Const.MaxCubeTextureLevels) {
- /* bad width or height */
+ if (width < 2 * border || width > 2 + maxSize)
+ return GL_FALSE;
+ if (height < 2 * border || height > 2 + maxSize)
return GL_FALSE;
+ if (level >= ctx->Const.MaxCubeTextureLevels)
+ return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
}
return GL_TRUE;
+
case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
- level >= ctx->Const.MaxTextureLevels) {
- /* bad width or level */
+ if (width < 2 * border || width > 2 + maxSize)
return GL_FALSE;
- }
-
- if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
+ if (height < 1 || height > ctx->Const.MaxArrayTextureLayers)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
}
return GL_TRUE;
+
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- if (width < 2 * border || width > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
- height < 2 * border || height > 2 + maxSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two &&
- height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
- level >= ctx->Const.MaxTextureLevels) {
- /* bad width or height or level */
+ if (width < 2 * border || width > 2 + maxSize)
return GL_FALSE;
- }
- if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
+ if (height < 2 * border || height > 2 + maxSize)
+ return GL_FALSE;
+ if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers)
+ return GL_FALSE;
+ if (level >= ctx->Const.MaxTextureLevels)
return GL_FALSE;
+ if (!ctx->Extensions.ARB_texture_non_power_of_two) {
+ if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
+ return GL_FALSE;
+ if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
+ return GL_FALSE;
}
return GL_TRUE;
+
default:
_mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
return GL_FALSE;
@@ -1274,15 +1331,37 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
/**
- * Helper function to determine whether a target supports compressed textures
+ * Check if the memory used by the texture would exceed the driver's limit.
+ * This lets us support a max 3D texture size of 8K (for example) but
+ * prevents allocating a full 8K x 8K x 8K texture.
+ * XXX this could be rolled into the proxy texture size test (above) but
+ * we don't have the actual texture internal format at that point.
+ */
+static GLboolean
+legal_texture_size(struct gl_context *ctx, gl_format format,
+ GLint width, GLint height, GLint depth)
+{
+ uint64_t bytes = _mesa_format_image_size64(format, width, height, depth);
+ uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */
+ return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes;
+}
+
+
+
+/**
+ * Helper function to determine whether a target and specific compression
+ * format are supported.
*/
static GLboolean
-target_can_be_compressed(struct gl_context *ctx, GLenum target)
+target_can_be_compressed(const struct gl_context *ctx, GLenum target,
+ GLenum intFormat)
{
+ (void) intFormat; /* not used yet */
+
switch (target) {
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
- return GL_TRUE;
+ return GL_TRUE; /* true for any compressed format so far */
case GL_PROXY_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
@@ -1301,6 +1380,109 @@ target_can_be_compressed(struct gl_context *ctx, GLenum target)
/**
+ * Check if the given texture target value is legal for a
+ * glTexImage1/2/3D call.
+ */
+static GLboolean
+legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
+{
+ switch (dims) {
+ case 1:
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+ case 2:
+ switch (target) {
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ 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:
+ return ctx->Extensions.ARB_texture_cube_map;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array;
+ default:
+ return GL_FALSE;
+ }
+ case 3:
+ switch (target) {
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ return GL_TRUE;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array;
+ default:
+ return GL_FALSE;
+ }
+ default:
+ _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims);
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if the given texture target value is legal for a
+ * glTexSubImage, glCopyTexSubImage or glCopyTexImage call.
+ * The difference compared to legal_teximage_target() above is that
+ * proxy targets are not supported.
+ */
+static GLboolean
+legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
+{
+ switch (dims) {
+ case 1:
+ return target == GL_TEXTURE_1D;
+ case 2:
+ switch (target) {
+ case GL_TEXTURE_2D:
+ return GL_TRUE;
+ 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:
+ return ctx->Extensions.ARB_texture_cube_map;
+ case GL_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array;
+ default:
+ return GL_FALSE;
+ }
+ case 3:
+ switch (target) {
+ case GL_TEXTURE_3D:
+ return GL_TRUE;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array;
+ default:
+ return GL_FALSE;
+ }
+ default:
+ _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()",
+ dims);
+ return GL_FALSE;
+ }
+}
+
+
+/**
* Test the glTexImage[123]D() parameters for errors.
*
* \param ctx GL context.
@@ -1329,10 +1511,10 @@ texture_error_check( struct gl_context *ctx,
GLint width, GLint height,
GLint depth, GLint border )
{
- const GLboolean isProxy = _mesa_is_proxy_texture(target);
+ const GLenum proxyTarget = get_proxy_target(target);
+ const GLboolean isProxy = target == proxyTarget;
GLboolean sizeOK = GL_TRUE;
GLboolean colorFormat, indexFormat;
- GLenum proxy_target;
/* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
@@ -1362,71 +1544,16 @@ texture_error_check( struct gl_context *ctx,
return GL_TRUE;
}
- /* Check target and call ctx->Driver.TestProxyTexImage() to check the
- * level, width, height and depth.
- */
- if (dimensions == 1) {
- if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
- proxy_target = GL_PROXY_TEXTURE_1D;
- height = 1;
- depth = 1;
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
- return GL_TRUE;
- }
- }
- else if (dimensions == 2) {
- depth = 1;
- if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
- proxy_target = GL_PROXY_TEXTURE_2D;
- }
- else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
- (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
- if (!ctx->Extensions.ARB_texture_cube_map) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
- return GL_TRUE;
- }
- proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
- sizeOK = (width == height);
- }
- else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
- target == GL_TEXTURE_RECTANGLE_NV) {
- if (!ctx->Extensions.NV_texture_rectangle) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
- return GL_TRUE;
- }
- proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
- }
- else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
- target == GL_TEXTURE_1D_ARRAY_EXT) {
- proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
- return GL_TRUE;
- }
- }
- else if (dimensions == 3) {
- if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
- proxy_target = GL_PROXY_TEXTURE_3D;
- }
- else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
- target == GL_TEXTURE_2D_ARRAY_EXT) {
- proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
- return GL_TRUE;
- }
- }
- else {
- _mesa_problem( ctx, "bad dims in texture_error_check" );
- return GL_TRUE;
+ /* Do this simple check before calling the TestProxyTexImage() function */
+ if (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
+ sizeOK = (width == height);
}
- sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
+ /*
+ * Use the proxy texture driver hook to see if the size/level/etc are
+ * legal.
+ */
+ sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
internalFormat, format,
type, width, height,
depth, border);
@@ -1531,9 +1658,10 @@ texture_error_check( struct gl_context *ctx,
/* additional checks for compressed textures */
if (_mesa_is_compressed_format(ctx, internalFormat)) {
- if (!target_can_be_compressed(ctx, target) && !isProxy) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexImage%dD(target)", dimensions);
+ if (!target_can_be_compressed(ctx, target, internalFormat)) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexImage%dD(target)", dimensions);
return GL_TRUE;
}
if (border != 0) {
@@ -1591,61 +1719,13 @@ subtexture_error_check( struct gl_context *ctx, GLuint dimensions,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type )
{
- /* Check target */
- if (dimensions == 1) {
- if (target != GL_TEXTURE_1D) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
- return GL_TRUE;
- }
- }
- else if (dimensions == 2) {
- if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
- if (!ctx->Extensions.ARB_texture_cube_map) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (target == GL_TEXTURE_RECTANGLE_NV) {
- if (!ctx->Extensions.NV_texture_rectangle) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (target != GL_TEXTURE_2D) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (dimensions == 3) {
- if (target == GL_TEXTURE_2D_ARRAY_EXT) {
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
- return GL_TRUE;
- }
- }
- else if (target != GL_TEXTURE_3D) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
- return GL_TRUE;
- }
- }
- else {
- _mesa_problem( ctx, "invalid dims in texture_error_check" );
- return GL_TRUE;
- }
-
/* Basic level check */
if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
_mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
return GL_TRUE;
}
+ /* Check for negative sizes */
if (width < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glTexSubImage%dD(width=%d)", dimensions, width);
@@ -1732,13 +1812,6 @@ subtexture_error_check2( struct gl_context *ctx, GLuint dimensions,
if (_mesa_is_format_compressed(destTex->TexFormat)) {
GLuint bw, bh;
- if (!target_can_be_compressed(ctx, target)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexSubImage%dD(target=%s)", dimensions,
- _mesa_lookup_enum_by_nr(target));
- return GL_TRUE;
- }
-
/* do tests which depend on compression block size */
_mesa_get_format_block_size(destTex->TexFormat, &bw, &bh);
@@ -1789,10 +1862,18 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
GLenum target, GLint level, GLint internalFormat,
GLint width, GLint height, GLint border )
{
- GLenum type;
+ const GLenum proxyTarget = get_proxy_target(target);
+ const GLenum type = GL_FLOAT;
GLboolean sizeOK;
GLint format;
+ /* check target */
+ if (!legal_texsubimage_target(ctx, dimensions, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)",
+ dimensions, _mesa_lookup_enum_by_nr(target));
+ return GL_TRUE;
+ }
+
/* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
_mesa_error(ctx, GL_INVALID_VALUE,
@@ -1830,75 +1911,14 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
return GL_TRUE;
}
- /* NOTE: the format and type aren't really significant for
- * TestProxyTexImage(). Only the internalformat really matters.
- */
- type = GL_FLOAT;
+ /* Do size, level checking */
+ sizeOK = (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB)
+ ? (width == height) : 1;
- /* Check target and call ctx->Driver.TestProxyTexImage() to check the
- * level, width, height and depth.
- */
- if (dimensions == 1) {
- if (target == GL_TEXTURE_1D) {
- sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
- level, internalFormat,
- format, type,
- width, 1, 1, border);
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
- return GL_TRUE;
- }
- }
- else if (dimensions == 2) {
- if (target == GL_TEXTURE_2D) {
- sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
- level, internalFormat,
- format, type,
- width, height, 1, border);
- }
- else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
- if (!ctx->Extensions.ARB_texture_cube_map) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
- return GL_TRUE;
- }
- sizeOK = (width == height) &&
- ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
- level, internalFormat, format, type,
- width, height, 1, border);
- }
- else if (target == GL_TEXTURE_RECTANGLE_NV) {
- if (!ctx->Extensions.NV_texture_rectangle) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
- return GL_TRUE;
- }
- sizeOK = ctx->Driver.TestProxyTexImage(ctx,
- GL_PROXY_TEXTURE_RECTANGLE_NV,
- level, internalFormat,
- format, type,
- width, height, 1, border);
- }
- else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)");
- return GL_TRUE;
- }
- sizeOK = ctx->Driver.TestProxyTexImage(ctx,
- GL_PROXY_TEXTURE_1D_ARRAY_EXT,
- level, internalFormat,
- format, type,
- width, height, 1, border);
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
- return GL_TRUE;
- }
- }
- else {
- _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
- return GL_TRUE;
- }
+ sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
+ internalFormat, format,
+ type, width, height,
+ 1, border);
if (!sizeOK) {
if (dimensions == 1) {
@@ -1914,7 +1934,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
}
if (_mesa_is_compressed_format(ctx, internalFormat)) {
- if (!target_can_be_compressed(ctx, target)) {
+ if (!target_can_be_compressed(ctx, target, internalFormat)) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glCopyTexImage%dD(target)", dimensions);
return GL_TRUE;
@@ -1973,45 +1993,11 @@ copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions,
}
}
- /* Check target */
- if (dimensions == 1) {
- if (target != GL_TEXTURE_1D) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
- return GL_TRUE;
- }
- }
- else if (dimensions == 2) {
- if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
- if (!ctx->Extensions.ARB_texture_cube_map) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (target == GL_TEXTURE_RECTANGLE_NV) {
- if (!ctx->Extensions.NV_texture_rectangle) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (target != GL_TEXTURE_2D) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
- return GL_TRUE;
- }
- }
- else if (dimensions == 3) {
- if (((target != GL_TEXTURE_2D_ARRAY_EXT) ||
- (!ctx->Extensions.MESA_texture_array))
- && (target != GL_TEXTURE_3D)) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
- return GL_TRUE;
- }
+ /* check target (proxies not allowed) */
+ if (!legal_texsubimage_target(ctx, dimensions, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexSubImage%uD(target=%s)",
+ dimensions, _mesa_lookup_enum_by_nr(target));
+ return GL_TRUE;
}
/* Check level */
@@ -2100,11 +2086,6 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions,
}
if (_mesa_is_format_compressed(teximage->TexFormat)) {
- if (!target_can_be_compressed(ctx, target)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTexSubImage%dD(target)", dimensions);
- return GL_TRUE;
- }
/* offset must be multiple of 4 */
if ((xoffset & 3) || (yoffset & 3)) {
_mesa_error(ctx, GL_INVALID_VALUE,
@@ -2337,89 +2318,48 @@ _mesa_choose_texture_format(struct gl_context *ctx,
}
-
-/*
- * Called from the API. Note that width includes the border.
+/**
+ * Common code to implement all the glTexImage1D/2D/3D functions.
*/
-void GLAPIENTRY
-_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
- GLsizei width, GLint border, GLenum format,
- GLenum type, const GLvoid *pixels )
+static void
+teximage(struct gl_context *ctx, GLuint dims,
+ GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels)
{
- GET_CURRENT_CONTEXT(ctx);
+ GLboolean error;
+
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n",
+ _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n",
+ dims,
_mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat), width, border,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, depth, border,
_mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type), pixels);
- internalFormat = override_internal_format(internalFormat, width, 1);
-
- if (target == GL_TEXTURE_1D) {
- /* non-proxy target */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- const GLuint face = _mesa_tex_target_to_face(target);
-
- if (texture_error_check(ctx, 1, target, level, internalFormat,
- format, type, width, 1, 1, border)) {
- return; /* error was recorded */
- }
-
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
- _mesa_update_state(ctx);
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
-
- ASSERT(texImage->Data == NULL);
-
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, format,
- type);
-
- _mesa_init_teximage_fields(ctx, target, texImage,
- width, 1, 1,
- border, internalFormat,
- texFormat);
+ internalFormat = override_internal_format(internalFormat, width, height);
- /* Give the texture to the driver. <pixels> may be null. */
- ASSERT(ctx->Driver.TexImage1D);
- ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
- width, border, format, type, pixels,
- &ctx->Unpack, texObj, texImage);
+ /* target error checking */
+ if (!legal_teximage_target(ctx, dims, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)",
+ dims, _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- check_gen_mipmap(ctx, target, texObj, level);
+ /* general error checking */
+ error = texture_error_check(ctx, dims, target, level, internalFormat,
+ format, type, width, height, depth, border);
- update_fbo_texture(ctx, texObj, face, level);
+ if (_mesa_is_proxy_texture(target)) {
+ /* Proxy texture: just clear or set state depending on error checking */
+ struct gl_texture_image *texImage =
+ _mesa_get_proxy_tex_image(ctx, target, level);
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
- }
- else if (target == GL_PROXY_TEXTURE_1D) {
- /* Proxy texture: check for errors and update proxy state */
- struct gl_texture_image *texImage;
- texImage = _mesa_get_proxy_tex_image(ctx, target, level);
- if (texture_error_check(ctx, 1, target, level, internalFormat,
- format, type, width, 1, 1, border)) {
+ if (error) {
/* when error, clear all proxy texture image parameters */
if (texImage)
clear_teximage_fields(texImage);
@@ -2428,54 +2368,28 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
/* no error, set the tex image parameters */
struct gl_texture_object *texObj =
_mesa_get_current_tex_object(ctx, target);
- gl_format texFormat = _mesa_choose_texture_format(ctx, texObj, target,
- level,
+ gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
+ target, level,
internalFormat,
format, type);
- _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
- border, internalFormat, texFormat);
+
+ if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ depth, border, internalFormat,
+ texFormat);
+ }
+ else if (texImage) {
+ clear_teximage_fields(texImage);
+ }
}
}
else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
- return;
- }
-}
-
-
-void GLAPIENTRY
-_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
- GLsizei width, GLsizei height, GLint border,
- GLenum format, GLenum type,
- const GLvoid *pixels )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n",
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat), width, height,
- border, _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type), pixels);
-
- internalFormat = override_internal_format(internalFormat, width, height);
-
- if (target == GL_TEXTURE_2D ||
- (ctx->Extensions.ARB_texture_cube_map &&
- target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
- (ctx->Extensions.NV_texture_rectangle &&
- target == GL_TEXTURE_RECTANGLE_NV) ||
- (ctx->Extensions.MESA_texture_array &&
- target == GL_TEXTURE_1D_ARRAY_EXT)) {
/* non-proxy target */
+ const GLuint face = _mesa_tex_target_to_face(target);
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- const GLuint face = _mesa_tex_target_to_face(target);
- if (texture_error_check(ctx, 2, target, level, internalFormat,
- format, type, width, height, 1, border)) {
+ if (error) {
return; /* error was recorded */
}
@@ -2483,11 +2397,13 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
_mesa_update_state(ctx);
texObj = _mesa_get_current_tex_object(ctx, target);
+
_mesa_lock_texture(ctx, texObj);
{
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+
if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
}
else {
gl_format texFormat;
@@ -2497,63 +2413,81 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
}
ASSERT(texImage->Data == NULL);
-
texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
internalFormat, format,
type);
- _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
- border, internalFormat, texFormat);
-
- /* Give the texture to the driver. <pixels> may be null. */
- ASSERT(ctx->Driver.TexImage2D);
- ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
- width, height, border, format, type,
- pixels, &ctx->Unpack, texObj, texImage);
+ if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ width, height, depth,
+ border, internalFormat, texFormat);
+
+ /* Give the texture to the driver. <pixels> may be null. */
+ ASSERT(ctx->Driver.TexImage3D);
+ switch (dims) {
+ case 1:
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border, format,
+ type, pixels, &ctx->Unpack, texObj,
+ texImage);
+ break;
+ case 2:
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border, format,
+ type, pixels, &ctx->Unpack, texObj,
+ texImage);
+ break;
+ case 3:
+ ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
+ width, height, depth, border, format,
+ type, pixels, &ctx->Unpack, texObj,
+ texImage);
+ break;
+ default:
+ _mesa_problem(ctx, "invalid dims=%u in teximage()", dims);
+ }
- check_gen_mipmap(ctx, target, texObj, level);
+ check_gen_mipmap(ctx, target, texObj, level);
- update_fbo_texture(ctx, texObj, face, level);
+ update_fbo_texture(ctx, texObj, face, level);
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
+ }
}
}
_mesa_unlock_texture(ctx, texObj);
}
- else if (target == GL_PROXY_TEXTURE_2D ||
- (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
- ctx->Extensions.ARB_texture_cube_map) ||
- (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
- ctx->Extensions.NV_texture_rectangle) ||
- (ctx->Extensions.MESA_texture_array &&
- target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
- /* Proxy texture: check for errors and update proxy state */
- struct gl_texture_image *texImage;
- texImage = _mesa_get_proxy_tex_image(ctx, target, level);
- if (texture_error_check(ctx, 2, target, level, internalFormat,
- format, type, width, height, 1, border)) {
- /* when error, clear all proxy texture image parameters */
- if (texImage)
- clear_teximage_fields(texImage);
- }
- else {
- /* no error, set the tex image parameters */
- struct gl_texture_object *texObj =
- _mesa_get_current_tex_object(ctx, target);
- gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
- target, level,
- internalFormat,
- format, type);
- _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
- border, internalFormat, texFormat);
- }
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
- return;
- }
+}
+
+
+/*
+ * Called from the API. Note that width includes the border.
+ */
+void GLAPIENTRY
+_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLint border, GLenum format,
+ GLenum type, const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ teximage(ctx, 1, target, level, internalFormat, width, 1, 1,
+ border, format, type, pixels);
+}
+
+
+void GLAPIENTRY
+_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ teximage(ctx, 2, target, level, internalFormat, width, height, 1,
+ border, format, type, pixels);
}
@@ -2568,100 +2502,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
const GLvoid *pixels )
{
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n",
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat), width, height,
- depth, border, _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type), pixels);
-
- internalFormat = override_internal_format(internalFormat, width, height);
-
- if (target == GL_TEXTURE_3D ||
- (ctx->Extensions.MESA_texture_array &&
- target == GL_TEXTURE_2D_ARRAY_EXT)) {
- /* non-proxy target */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- const GLuint face = _mesa_tex_target_to_face(target);
-
- if (texture_error_check(ctx, 3, target, level, (GLint) internalFormat,
- format, type, width, height, depth, border)) {
- return; /* error was recorded */
- }
-
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
- _mesa_update_state(ctx);
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
-
- ASSERT(texImage->Data == NULL);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, format,
- type);
- _mesa_init_teximage_fields(ctx, target, texImage,
- width, height, depth,
- border, internalFormat, texFormat);
-
- /* Give the texture to the driver. <pixels> may be null. */
- ASSERT(ctx->Driver.TexImage3D);
- ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
- width, height, depth, border, format, type,
- pixels, &ctx->Unpack, texObj, texImage);
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- update_fbo_texture(ctx, texObj, face, level);
-
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
- }
- else if (target == GL_PROXY_TEXTURE_3D ||
- (ctx->Extensions.MESA_texture_array &&
- target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
- /* Proxy texture: check for errors and update proxy state */
- struct gl_texture_image *texImage;
- texImage = _mesa_get_proxy_tex_image(ctx, target, level);
- if (texture_error_check(ctx, 3, target, level, internalFormat,
- format, type, width, height, depth, border)) {
- /* when error, clear all proxy texture image parameters */
- if (texImage)
- clear_teximage_fields(texImage);
- }
- else {
- /* no error, set the tex image parameters */
- struct gl_texture_object *texObj =
- _mesa_get_current_tex_object(ctx, target);
- gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
- target, level,
- internalFormat,
- format, type);
- _mesa_init_teximage_fields(ctx, target, texImage, width, height,
- depth, border, internalFormat, texFormat);
- }
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
- return;
- }
+ teximage(ctx, 3, target, level, internalFormat, width, height, depth,
+ border, format, type, pixels);
}
@@ -2724,51 +2566,92 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
#endif
-void GLAPIENTRY
-_mesa_TexSubImage1D( GLenum target, GLint level,
- GLint xoffset, GLsizei width,
- GLenum format, GLenum type,
- const GLvoid *pixels )
+
+/**
+ * Implement all the glTexSubImage1/2/3D() functions.
+ */
+static void
+texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels )
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- GET_CURRENT_CONTEXT(ctx);
+
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n",
+ _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n",
+ dims,
_mesa_lookup_enum_by_nr(target), level,
- xoffset, width, _mesa_lookup_enum_by_nr(format),
+ xoffset, yoffset, zoffset, width, height, depth,
+ _mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type), pixels);
+ /* check target (proxies not allowed) */
+ if (!legal_texsubimage_target(ctx, dims, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
+ dims, _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
- if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
- width, 1, 1, format, type)) {
+ if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type)) {
return; /* error was detected */
}
-
texObj = _mesa_get_current_tex_object(ctx, target);
- assert(texObj);
_mesa_lock_texture(ctx, texObj);
{
texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
- width, 1, 1, format, type, texImage)) {
+ if (subtexture_error_check2(ctx, dims, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, texImage)) {
/* error was recorded */
}
- else if (width > 0) {
- /* If we have a border, xoffset=-1 is legal. Bias by border width */
- xoffset += texImage->Border;
+ else if (width > 0 && height > 0 && height > 0) {
+ /* If we have a border, offset=-1 is legal. Bias by border width. */
+ switch (dims) {
+ case 3:
+ zoffset += texImage->Border;
+ /* fall-through */
+ case 2:
+ yoffset += texImage->Border;
+ /* fall-through */
+ case 1:
+ xoffset += texImage->Border;
+ }
- ASSERT(ctx->Driver.TexSubImage1D);
- ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
- format, type, pixels, &ctx->Unpack,
- texObj, texImage);
+ switch (dims) {
+ case 1:
+ ctx->Driver.TexSubImage1D(ctx, target, level,
+ xoffset, width,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage );
+ break;
+ case 2:
+ ctx->Driver.TexSubImage2D(ctx, target, level,
+ xoffset, yoffset, width, height,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage );
+ break;
+ case 3:
+ ctx->Driver.TexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage );
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected dims in subteximage()");
+ }
check_gen_mipmap(ctx, target, texObj, level);
@@ -2780,58 +2663,31 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
void GLAPIENTRY
+_mesa_TexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ texsubimage(ctx, 1, target, level,
+ xoffset, 0, 0,
+ width, 1, 1,
+ format, type, pixels);
+}
+
+
+void GLAPIENTRY
_mesa_TexSubImage2D( GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels )
{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n",
- _mesa_lookup_enum_by_nr(target), level,
- xoffset, yoffset, width, height,
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type), pixels);
-
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
- _mesa_update_state(ctx);
-
- if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
- width, height, 1, format, type)) {
- return; /* error was detected */
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
- width, height, 1, format, type, texImage)) {
- /* error was recorded */
- }
- else if (width > 0 && height >= 0) {
- /* If we have a border, xoffset=-1 is legal. Bias by border width */
- xoffset += texImage->Border;
- yoffset += texImage->Border;
-
- ASSERT(ctx->Driver.TexSubImage2D);
- ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
- width, height, format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
+ texsubimage(ctx, 2, target, level,
+ xoffset, yoffset, 0,
+ width, height, 1,
+ format, type, pixels);
}
@@ -2843,84 +2699,41 @@ _mesa_TexSubImage3D( GLenum target, GLint level,
GLenum format, GLenum type,
const GLvoid *pixels )
{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n",
- _mesa_lookup_enum_by_nr(target), level,
- xoffset, yoffset, zoffset, width, height, depth,
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type), pixels);
-
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
- _mesa_update_state(ctx);
-
- if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
- width, height, depth, format, type)) {
- return; /* error was detected */
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (subtexture_error_check2(ctx, 3, target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, texImage)) {
- /* error was recorded */
- }
- else if (width > 0 && height > 0 && height > 0) {
- /* If we have a border, xoffset=-1 is legal. Bias by border width */
- xoffset += texImage->Border;
- yoffset += texImage->Border;
- zoffset += texImage->Border;
-
- ASSERT(ctx->Driver.TexSubImage3D);
- ctx->Driver.TexSubImage3D(ctx, target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage );
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
+ texsubimage(ctx, 3, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels);
}
-void GLAPIENTRY
-_mesa_CopyTexImage1D( GLenum target, GLint level,
- GLenum internalFormat,
- GLint x, GLint y,
- GLsizei width, GLint border )
+/**
+ * Implement the glCopyTexImage1/2D() functions.
+ */
+static void
+copyteximage(struct gl_context *ctx, GLuint dims,
+ GLenum target, GLint level, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
const GLuint face = _mesa_tex_target_to_face(target);
- GET_CURRENT_CONTEXT(ctx);
+
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n",
+ _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n",
+ dims,
_mesa_lookup_enum_by_nr(target), level,
_mesa_lookup_enum_by_nr(internalFormat),
- x, y, width, border);
+ x, y, width, height, border);
if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
- if (copytexture_error_check(ctx, 1, target, level, internalFormat,
- width, 1, border))
+ if (copytexture_error_check(ctx, dims, target, level, internalFormat,
+ width, height, border))
return;
texObj = _mesa_get_current_tex_object(ctx, target);
@@ -2928,8 +2741,9 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
_mesa_lock_texture(ctx, texObj);
{
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+
if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
}
else {
gl_format texFormat;
@@ -2944,20 +2758,29 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
internalFormat, GL_NONE,
GL_NONE);
- _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
- border, internalFormat, texFormat);
+ if (legal_texture_size(ctx, texFormat, width, height, 1)) {
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+ border, internalFormat, texFormat);
- ASSERT(ctx->Driver.CopyTexImage1D);
- ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
- x, y, width, border);
+ ASSERT(ctx->Driver.CopyTexImage2D);
+ if (dims == 1)
+ ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
+ x, y, width, border);
+ else
+ ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
+ x, y, width, height, border);
- check_gen_mipmap(ctx, target, texObj, level);
+ check_gen_mipmap(ctx, target, texObj, level);
- update_fbo_texture(ctx, texObj, face, level);
+ update_fbo_texture(ctx, texObj, face, level);
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
+ }
}
}
_mesa_unlock_texture(ctx, texObj);
@@ -2966,92 +2789,52 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
void GLAPIENTRY
-_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLint border )
+_mesa_CopyTexImage1D( GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- const GLuint face = _mesa_tex_target_to_face(target);
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n",
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat),
- x, y, width, height, border);
-
- if (ctx->NewState & NEW_COPY_TEX_STATE)
- _mesa_update_state(ctx);
-
- if (copytexture_error_check(ctx, 2, target, level, internalFormat,
- width, height, border))
- return;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
-
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
-
- ASSERT(texImage->Data == NULL);
-
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
-
- _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
- border, internalFormat, texFormat);
+ copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border);
+}
- ASSERT(ctx->Driver.CopyTexImage2D);
- ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
- x, y, width, height, border);
- check_gen_mipmap(ctx, target, texObj, level);
- update_fbo_texture(ctx, texObj, face, level);
-
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
+void GLAPIENTRY
+_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ copyteximage(ctx, 2, target, level, internalFormat,
+ x, y, width, height, border);
}
-void GLAPIENTRY
-_mesa_CopyTexSubImage1D( GLenum target, GLint level,
- GLint xoffset, GLint x, GLint y, GLsizei width )
+
+/**
+ * Implementation for glCopyTexSubImage1/2/3D() functions.
+ */
+static void
+copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height)
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- GLint yoffset = 0;
- GLsizei height = 1;
- GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n",
+ _mesa_debug(ctx, "glCopyTexSubImage%uD %s %d %d %d %d %d %d %d %d\n",
+ dims,
_mesa_lookup_enum_by_nr(target),
- level, xoffset, x, y, width);
+ level, xoffset, yoffset, zoffset, x, y, width, height);
if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
- if (copytexsubimage_error_check1(ctx, 1, target, level))
+ if (copytexsubimage_error_check1(ctx, dims, target, level))
return;
texObj = _mesa_get_current_tex_object(ctx, target);
@@ -3060,19 +2843,43 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
{
texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- if (copytexsubimage_error_check2(ctx, 1, target, level,
- xoffset, 0, 0, width, 1, texImage)) {
- /* error was recorded */
+ if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset,
+ zoffset, width, height, texImage)) {
+ /* error was recored */
}
else {
- /* If we have a border, xoffset=-1 is legal. Bias by border width */
- xoffset += texImage->Border;
+ /* If we have a border, offset=-1 is legal. Bias by border width. */
+ switch (dims) {
+ case 3:
+ zoffset += texImage->Border;
+ /* fall-through */
+ case 2:
+ yoffset += texImage->Border;
+ /* fall-through */
+ case 1:
+ xoffset += texImage->Border;
+ }
if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
&width, &height)) {
- ASSERT(ctx->Driver.CopyTexSubImage1D);
- ctx->Driver.CopyTexSubImage1D(ctx, target, level,
- xoffset, x, y, width);
+ switch (dims) {
+ case 1:
+ ctx->Driver.CopyTexSubImage1D(ctx, target, level,
+ xoffset, x, y, width);
+ break;
+ case 2:
+ ctx->Driver.CopyTexSubImage2D(ctx, target, level,
+ xoffset, yoffset,
+ x, y, width, height);
+ break;
+ case 3:
+ ctx->Driver.CopyTexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ x, y, width, height);
+ break;
+ default:
+ _mesa_problem(ctx, "bad dims in copytexsubimage()");
+ }
check_gen_mipmap(ctx, target, texObj, level);
@@ -3084,57 +2891,24 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
}
+void GLAPIENTRY
+_mesa_CopyTexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ copytexsubimage(ctx, 1, target, level, xoffset, 0, 0, x, y, width, 1);
+}
+
+
void GLAPIENTRY
_mesa_CopyTexSubImage2D( GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n",
- _mesa_lookup_enum_by_nr(target),
- level, xoffset, yoffset, x, y, width, height);
-
- if (ctx->NewState & NEW_COPY_TEX_STATE)
- _mesa_update_state(ctx);
-
- if (copytexsubimage_error_check1(ctx, 2, target, level))
- return;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (copytexsubimage_error_check2(ctx, 2, target, level,
- xoffset, yoffset, 0,
- width, height, texImage)) {
- /* error was recorded */
- }
- else {
- /* If we have a border, xoffset=-1 is legal. Bias by border width */
- xoffset += texImage->Border;
- yoffset += texImage->Border;
-
- if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
- &width, &height)) {
- ASSERT(ctx->Driver.CopyTexSubImage2D);
- ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset,
- x, y, width, height);
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- }
- _mesa_unlock_texture(ctx, texObj);
+ copytexsubimage(ctx, 2, target, level, xoffset, yoffset, 0, x, y,
+ width, height);
}
@@ -3144,52 +2918,9 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n",
- _mesa_lookup_enum_by_nr(target),
- level, xoffset, yoffset, zoffset, x, y, width, height);
-
- if (ctx->NewState & NEW_COPY_TEX_STATE)
- _mesa_update_state(ctx);
-
- if (copytexsubimage_error_check1(ctx, 3, target, level))
- return;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
- zoffset, width, height, texImage)) {
- /* error was recored */
- }
- else {
- /* If we have a border, xoffset=-1 is legal. Bias by border width */
- xoffset += texImage->Border;
- yoffset += texImage->Border;
- zoffset += texImage->Border;
-
- if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
- &width, &height)) {
- ASSERT(ctx->Driver.CopyTexSubImage3D);
- ctx->Driver.CopyTexSubImage3D(ctx, target, level,
- xoffset, yoffset, zoffset,
- x, y, width, height);
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- }
- _mesa_unlock_texture(ctx, texObj);
+ copytexsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
+ x, y, width, height);
}
@@ -3234,45 +2965,18 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
GLsizei height, GLsizei depth, GLint border,
GLsizei imageSize)
{
- GLint expectedSize, maxLevels = 0, maxTextureSize;
+ const GLenum proxyTarget = get_proxy_target(target);
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
+ GLint expectedSize;
- if (dimensions == 1) {
- /* 1D compressed textures not allowed */
- return GL_INVALID_ENUM;
- }
- else if (dimensions == 2) {
- if (target == GL_PROXY_TEXTURE_2D) {
- maxLevels = ctx->Const.MaxTextureLevels;
- }
- else if (target == GL_TEXTURE_2D) {
- maxLevels = ctx->Const.MaxTextureLevels;
- }
- else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
- if (!ctx->Extensions.ARB_texture_cube_map)
- return GL_INVALID_ENUM; /*target*/
- maxLevels = ctx->Const.MaxCubeTextureLevels;
- }
- else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
- if (!ctx->Extensions.ARB_texture_cube_map)
- return GL_INVALID_ENUM; /*target*/
- maxLevels = ctx->Const.MaxCubeTextureLevels;
- }
- else {
- return GL_INVALID_ENUM; /*target*/
- }
- }
- else if (dimensions == 3) {
- /* 3D compressed textures not allowed */
- return GL_INVALID_ENUM;
- }
- else {
- assert(0);
+ /* check level */
+ if (level < 0 || level >= maxLevels)
+ return GL_INVALID_VALUE;
+
+ if (!target_can_be_compressed(ctx, target, internalFormat)) {
return GL_INVALID_ENUM;
}
- maxTextureSize = 1 << (maxLevels - 1);
-
/* This will detect any invalid internalFormat value */
if (!_mesa_is_compressed_format(ctx, internalFormat))
return GL_INVALID_ENUM;
@@ -3281,47 +2985,51 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
if (_mesa_base_tex_format(ctx, internalFormat) < 0)
return GL_INVALID_ENUM;
+ /* No compressed formats support borders at this time */
if (border != 0)
return GL_INVALID_VALUE;
- /*
- * XXX We should probably use the proxy texture error check function here.
- */
- if (width < 1 || width > maxTextureSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
- return GL_INVALID_VALUE;
-
- if ((height < 1 || height > maxTextureSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
- && dimensions > 1)
- return GL_INVALID_VALUE;
-
- if ((depth < 1 || depth > maxTextureSize ||
- (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
- && dimensions > 2)
- return GL_INVALID_VALUE;
-
/* For cube map, width must equal height */
if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
return GL_INVALID_VALUE;
- if (level < 0 || level >= maxLevels)
- return GL_INVALID_VALUE;
+ /* check image size against compression block size */
+ {
+ gl_format texFormat =
+ ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
+ GL_NONE, GL_NONE);
+ GLuint bw, bh;
- expectedSize = compressed_tex_size(width, height, depth, internalFormat);
- if (expectedSize != imageSize)
- return GL_INVALID_VALUE;
+ _mesa_get_format_block_size(texFormat, &bw, &bh);
+ if ((width > bw && width % bw > 0) ||
+ (height > bh && height % bh > 0)) {
+ /*
+ * Per GL_ARB_texture_compression: GL_INVALID_OPERATION is
+ * generated [...] if any parameter combinations are not
+ * supported by the specific compressed internal format.
+ */
+ return GL_INVALID_OPERATION;
+ }
+ }
-#if FEATURE_EXT_texture_sRGB
- if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
- internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
- internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
- internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
- && border != 0) {
+ /* check image sizes */
+ if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
+ internalFormat, GL_NONE, GL_NONE,
+ width, height, depth, border)) {
+ /* See error comment above */
return GL_INVALID_OPERATION;
}
-#endif
+
+ /* check image size in bytes */
+ expectedSize = compressed_tex_size(width, height, depth, internalFormat);
+ if (expectedSize != imageSize) {
+ /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...]
+ * if <imageSize> is not consistent with the format, dimensions, and
+ * contents of the specified image.
+ */
+ return GL_INVALID_VALUE;
+ }
return GL_NO_ERROR;
}
@@ -3463,159 +3171,101 @@ compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims,
}
-
-void GLAPIENTRY
-_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
- GLenum internalFormat, GLsizei width,
- GLint border, GLsizei imageSize,
- const GLvoid *data)
+/**
+ * Implementation of the glCompressedTexImage1/2/3D() functions.
+ */
+static void
+compressedteximage(struct gl_context *ctx, GLuint dims,
+ GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid *data)
{
- GET_CURRENT_CONTEXT(ctx);
+ GLenum error;
+
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n",
+ _mesa_debug(ctx,
+ "glCompressedTexImage%uDARB %s %d %s %d %d %d %d %d %p\n",
+ dims,
_mesa_lookup_enum_by_nr(target), level,
_mesa_lookup_enum_by_nr(internalFormat),
- width, border, imageSize, data);
-
- if (target == GL_TEXTURE_1D) {
- /* non-proxy target */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GLenum error = compressed_texture_error_check(ctx, 1, target, level,
- internalFormat, width, 1, 1, border, imageSize);
- if (error) {
- _mesa_error(ctx, error, "glCompressedTexImage1D");
- return;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
- ASSERT(texImage->Data == NULL);
-
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
+ width, height, depth, border, imageSize, data);
- _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
- border, internalFormat, texFormat);
+ /* check target */
+ if (!legal_teximage_target(ctx, dims, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target=%s)",
+ dims, _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- ASSERT(ctx->Driver.CompressedTexImage1D);
- ctx->Driver.CompressedTexImage1D(ctx, target, level,
- internalFormat, width, border,
- imageSize, data,
- texObj, texImage);
+ error = compressed_texture_error_check(ctx, dims, target, level,
+ internalFormat, width, height, depth,
+ border, imageSize);
- check_gen_mipmap(ctx, target, texObj, level);
+#if FEATURE_ES
+ /* XXX this is kind of a hack */
+ if (error) {
+ _mesa_error(ctx, error, "glTexImage2D");
+ return;
+ }
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
+ if (dims == 2) {
+ switch (internalFormat) {
+ case GL_PALETTE4_RGB8_OES:
+ case GL_PALETTE4_RGBA8_OES:
+ case GL_PALETTE4_R5_G6_B5_OES:
+ case GL_PALETTE4_RGBA4_OES:
+ case GL_PALETTE4_RGB5_A1_OES:
+ case GL_PALETTE8_RGB8_OES:
+ case GL_PALETTE8_RGBA8_OES:
+ case GL_PALETTE8_R5_G6_B5_OES:
+ case GL_PALETTE8_RGBA4_OES:
+ case GL_PALETTE8_RGB5_A1_OES:
+ _mesa_cpal_compressed_teximage2d(target, level, internalFormat,
+ width, height, imageSize, data);
+ return;
}
- _mesa_unlock_texture(ctx, texObj);
}
- else if (target == GL_PROXY_TEXTURE_1D) {
- /* Proxy texture: check for errors and update proxy state */
- GLenum error = compressed_texture_error_check(ctx, 1, target, level,
- internalFormat, width, 1, 1, border, imageSize);
+#endif
+
+ if (_mesa_is_proxy_texture(target)) {
+ /* Proxy texture: just check for errors and update proxy state */
+ struct gl_texture_image *texImage;
+
if (!error) {
- ASSERT(ctx->Driver.TestProxyTexImage);
- error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
- internalFormat, GL_NONE, GL_NONE,
- width, 1, 1, border);
- }
- if (error) {
- /* if error, clear all proxy texture image parameters */
- struct gl_texture_image *texImage;
- texImage = _mesa_get_proxy_tex_image(ctx, target, level);
- if (texImage)
- clear_teximage_fields(texImage);
+ struct gl_texture_object *texObj =
+ _mesa_get_current_tex_object(ctx, target);
+ gl_format texFormat =
+ _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, GL_NONE, GL_NONE);
+ if (!legal_texture_size(ctx, texFormat, width, height, depth)) {
+ error = GL_OUT_OF_MEMORY;
+ }
}
- else {
- /* store the teximage parameters */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- gl_format texFormat;
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
- _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
- border, internalFormat, texFormat);
- }
- _mesa_unlock_texture(ctx, texObj);
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage) {
+ if (error) {
+ /* if error, clear all proxy texture image parameters */
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* no error: store the teximage parameters */
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ depth, border, internalFormat,
+ MESA_FORMAT_NONE);
+ }
}
}
else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
- return;
- }
-}
-
-void GLAPIENTRY
-_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
- GLenum internalFormat, GLsizei width,
- GLsizei height, GLint border, GLsizei imageSize,
- const GLvoid *data)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n",
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height, border, imageSize, data);
-
-#if FEATURE_ES
- switch (internalFormat) {
- case GL_PALETTE4_RGB8_OES:
- case GL_PALETTE4_RGBA8_OES:
- case GL_PALETTE4_R5_G6_B5_OES:
- case GL_PALETTE4_RGBA4_OES:
- case GL_PALETTE4_RGB5_A1_OES:
- case GL_PALETTE8_RGB8_OES:
- case GL_PALETTE8_RGBA8_OES:
- case GL_PALETTE8_R5_G6_B5_OES:
- case GL_PALETTE8_RGBA4_OES:
- case GL_PALETTE8_RGB5_A1_OES:
- _mesa_cpal_compressed_teximage2d(target, level, internalFormat,
- width, height, imageSize, data);
- return;
- }
-#endif
-
- if (target == GL_TEXTURE_2D ||
- (ctx->Extensions.ARB_texture_cube_map &&
- target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
/* non-proxy target */
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- GLenum error = compressed_texture_error_check(ctx, 2, target, level,
- internalFormat, width, height, 1, border, imageSize);
if (error) {
- _mesa_error(ctx, error, "glCompressedTexImage2D");
+ _mesa_error(ctx, error, "glCompressedTexImage%uD", dims);
return;
}
@@ -3625,7 +3275,8 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
{
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glCompressedTexImage%uD", dims);
}
else {
gl_format texFormat;
@@ -3639,67 +3290,78 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
internalFormat, GL_NONE,
GL_NONE);
- _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
- border, internalFormat, texFormat);
-
- ASSERT(ctx->Driver.CompressedTexImage2D);
- ctx->Driver.CompressedTexImage2D(ctx, target, level,
- internalFormat, width, height,
- border, imageSize, data,
- texObj, texImage);
+ if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ width, height, depth,
+ border, internalFormat, texFormat);
+
+ switch (dims) {
+ case 1:
+ ASSERT(ctx->Driver.CompressedTexImage1D);
+ ctx->Driver.CompressedTexImage1D(ctx, target, level,
+ internalFormat,
+ width,
+ border, imageSize, data,
+ texObj, texImage);
+ break;
+ case 2:
+ ASSERT(ctx->Driver.CompressedTexImage2D);
+ ctx->Driver.CompressedTexImage2D(ctx, target, level,
+ internalFormat,
+ width, height,
+ border, imageSize, data,
+ texObj, texImage);
+ break;
+ case 3:
+ ASSERT(ctx->Driver.CompressedTexImage3D);
+ ctx->Driver.CompressedTexImage3D(ctx, target, level,
+ internalFormat,
+ width, height, depth,
+ border, imageSize, data,
+ texObj, texImage);
+ break;
+ default:
+ _mesa_problem(ctx, "bad dims in compressedteximage");
+ }
- check_gen_mipmap(ctx, target, texObj, level);
+ check_gen_mipmap(ctx, target, texObj, level);
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glCompressedTexImage%uD", dims);
+ }
}
}
_mesa_unlock_texture(ctx, texObj);
}
- else if (target == GL_PROXY_TEXTURE_2D ||
- (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
- ctx->Extensions.ARB_texture_cube_map)) {
- /* Proxy texture: check for errors and update proxy state */
- GLenum error = compressed_texture_error_check(ctx, 2, target, level,
- internalFormat, width, height, 1, border, imageSize);
- if (!error) {
- ASSERT(ctx->Driver.TestProxyTexImage);
- error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
- internalFormat, GL_NONE, GL_NONE,
- width, height, 1, border);
- }
- if (error) {
- /* if error, clear all proxy texture image parameters */
- struct gl_texture_image *texImage;
- texImage = _mesa_get_proxy_tex_image(ctx, target, level);
- if (texImage)
- clear_teximage_fields(texImage);
- }
- else {
- /* store the teximage parameters */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- gl_format texFormat;
+}
- texObj = _mesa_get_current_tex_object(ctx, target);
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
- _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
- border, internalFormat, texFormat);
- }
- _mesa_unlock_texture(ctx, texObj);
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
- return;
- }
+void GLAPIENTRY
+_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ compressedteximage(ctx, 1, target, level, internalFormat,
+ width, 1, 1, border, imageSize, data);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLint border, GLsizei imageSize,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ compressedteximage(ctx, 2, target, level, internalFormat,
+ width, height, 1, border, imageSize, data);
}
@@ -3710,107 +3372,8 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
GLsizei imageSize, const GLvoid *data)
{
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n",
- _mesa_lookup_enum_by_nr(target), level,
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height, depth, border, imageSize, data);
-
- if (target == GL_TEXTURE_3D) {
- /* non-proxy target */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GLenum error = compressed_texture_error_check(ctx, 3, target, level,
- internalFormat, width, height, depth, border, imageSize);
- if (error) {
- _mesa_error(ctx, error, "glCompressedTexImage3D");
- return;
- }
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
- }
- else {
- gl_format texFormat;
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData( ctx, texImage );
- }
- ASSERT(texImage->Data == NULL);
-
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
-
- _mesa_init_teximage_fields(ctx, target, texImage,
- width, height, depth,
- border, internalFormat, texFormat);
-
- ASSERT(ctx->Driver.CompressedTexImage3D);
- ctx->Driver.CompressedTexImage3D(ctx, target, level,
- internalFormat,
- width, height, depth,
- border, imageSize, data,
- texObj, texImage);
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- /* state update */
- texObj->_Complete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
- }
- }
- _mesa_unlock_texture(ctx, texObj);
- }
- else if (target == GL_PROXY_TEXTURE_3D) {
- /* Proxy texture: check for errors and update proxy state */
- GLenum error = compressed_texture_error_check(ctx, 3, target, level,
- internalFormat, width, height, depth, border, imageSize);
- if (!error) {
- ASSERT(ctx->Driver.TestProxyTexImage);
- error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
- internalFormat, GL_NONE, GL_NONE,
- width, height, depth, border);
- }
- if (error) {
- /* if error, clear all proxy texture image parameters */
- struct gl_texture_image *texImage;
- texImage = _mesa_get_proxy_tex_image(ctx, target, level);
- if (texImage)
- clear_teximage_fields(texImage);
- }
- else {
- /* store the teximage parameters */
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- gl_format texFormat;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, GL_NONE,
- GL_NONE);
- _mesa_init_teximage_fields(ctx, target, texImage, width, height,
- depth, border, internalFormat,
- texFormat);
- }
- _mesa_unlock_texture(ctx, texObj);
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
- return;
- }
+ compressedteximage(ctx, 3, target, level, internalFormat,
+ width, height, depth, border, imageSize, data);
}