summaryrefslogtreecommitdiff
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.c236
1 files changed, 180 insertions, 56 deletions
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 706d346695..1f4c9f4722 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -629,6 +629,8 @@ _mesa_set_tex_image(struct gl_texture_object *tObj,
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
tObj->Image[0][level] = texImage;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
@@ -733,7 +735,9 @@ _mesa_is_proxy_texture(GLenum target)
target == GL_PROXY_TEXTURE_2D ||
target == GL_PROXY_TEXTURE_3D ||
target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
- target == GL_PROXY_TEXTURE_RECTANGLE_NV);
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
+ target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
}
@@ -783,6 +787,18 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
case GL_PROXY_TEXTURE_RECTANGLE_NV:
return ctx->Extensions.NV_texture_rectangle
? ctx->Texture.ProxyRect : NULL;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? texUnit->Current1DArray : NULL;
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? ctx->Texture.Proxy1DArray : NULL;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? texUnit->Current2DArray : NULL;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? ctx->Texture.Proxy2DArray : NULL;
default:
_mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
return NULL;
@@ -848,6 +864,13 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
else
return NULL;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array)
+ ? texObj->Image[0][level] : NULL;
+
default:
return NULL;
}
@@ -973,6 +996,36 @@ _mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
texImage->TexObject = ctx->Texture.ProxyRect;
}
return texImage;
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texImage = ctx->Texture.Proxy1DArray->Image[0][level];
+ if (!texImage) {
+ texImage = ctx->Driver.NewTextureImage(ctx);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
+ return NULL;
+ }
+ ctx->Texture.Proxy1DArray->Image[0][level] = texImage;
+ /* Set the 'back' pointer */
+ texImage->TexObject = ctx->Texture.Proxy1DArray;
+ }
+ return texImage;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texImage = ctx->Texture.Proxy2DArray->Image[0][level];
+ if (!texImage) {
+ texImage = ctx->Driver.NewTextureImage(ctx);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
+ return NULL;
+ }
+ ctx->Texture.Proxy2DArray->Image[0][level] = texImage;
+ /* Set the 'back' pointer */
+ texImage->TexObject = ctx->Texture.Proxy2DArray;
+ }
+ return texImage;
default:
return NULL;
}
@@ -998,6 +1051,10 @@ _mesa_max_texture_levels(GLcontext *ctx, GLenum target)
case GL_PROXY_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
return ctx->Const.MaxTextureLevels;
case GL_TEXTURE_3D:
case GL_PROXY_TEXTURE_3D:
@@ -1292,6 +1349,36 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
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 &&
+ _mesa_bitcount(width - 2 * border) != 1) ||
+ level >= ctx->Const.MaxTextureLevels) {
+ /* bad width or level */
+ return GL_FALSE;
+ }
+
+ if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
+ 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 &&
+ _mesa_bitcount(width - 2 * border) != 1) ||
+ height < 2 * border || height > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ _mesa_bitcount(height - 2 * border) != 1) ||
+ level >= ctx->Const.MaxTextureLevels) {
+ /* bad width or height or level */
+ return GL_FALSE;
+ }
+ if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
+ return GL_FALSE;
+ }
+ return GL_TRUE;
default:
_mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
return GL_FALSE;
@@ -1300,6 +1387,23 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
/**
+ * Helper function to determine whether a target supports compressed textures
+ */
+static GLboolean
+target_can_be_compressed(GLcontext *ctx, GLenum target)
+{
+ return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
+ || ((ctx->Extensions.ARB_texture_cube_map &&
+ (target == GL_PROXY_TEXTURE_CUBE_MAP ||
+ (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))
+ || ((ctx->Extensions.MESA_texture_array &&
+ ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) ||
+ (target == GL_TEXTURE_2D_ARRAY_EXT)))));
+}
+
+
+/**
* Test the glTexImage[123]D() parameters for errors.
*
* \param ctx GL context.
@@ -1329,8 +1433,9 @@ texture_error_check( GLcontext *ctx, GLenum target,
GLint depth, GLint border )
{
const GLboolean isProxy = _mesa_is_proxy_texture(target);
- GLboolean sizeOK;
+ 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) {
@@ -1365,10 +1470,9 @@ texture_error_check( GLcontext *ctx, GLenum target,
*/
if (dimensions == 1) {
if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
- sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
- level, internalFormat,
- format, type,
- width, 1, 1, border);
+ proxy_target = GL_PROXY_TEXTURE_1D;
+ height = 1;
+ width = 1;
}
else {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
@@ -1376,11 +1480,9 @@ texture_error_check( GLcontext *ctx, GLenum target,
}
}
else if (dimensions == 2) {
+ depth = 1;
if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
- sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
- level, internalFormat,
- format, type,
- width, height, 1, border);
+ proxy_target = GL_PROXY_TEXTURE_2D;
}
else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
(target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
@@ -1389,10 +1491,8 @@ texture_error_check( GLcontext *ctx, GLenum target,
_mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(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);
+ proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
+ sizeOK = (width == height);
}
else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
target == GL_TEXTURE_RECTANGLE_NV) {
@@ -1400,11 +1500,11 @@ texture_error_check( GLcontext *ctx, GLenum target,
_mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
return GL_TRUE;
}
- sizeOK = ctx->Driver.TestProxyTexImage(ctx,
- GL_PROXY_TEXTURE_RECTANGLE_NV,
- level, internalFormat,
- format, type,
- width, height, 1, border);
+ 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)");
@@ -1413,10 +1513,11 @@ texture_error_check( GLcontext *ctx, GLenum target,
}
else if (dimensions == 3) {
if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
- sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_3D,
- level, internalFormat,
- format, type,
- width, height, depth, border);
+ 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)" );
@@ -1428,6 +1529,10 @@ texture_error_check( GLcontext *ctx, GLenum target,
return GL_TRUE;
}
+ sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
+ internalFormat, format,
+ type, width, height,
+ depth, border);
if (!sizeOK) {
if (!isProxy) {
_mesa_error(ctx, GL_INVALID_VALUE,
@@ -1522,21 +1627,10 @@ texture_error_check( GLcontext *ctx, GLenum target,
/* additional checks for compressed textures */
if (is_compressed_format(ctx, internalFormat)) {
- if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
- /* OK */
- }
- else if (ctx->Extensions.ARB_texture_cube_map &&
- (target == GL_PROXY_TEXTURE_CUBE_MAP ||
- (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
- /* OK */
- }
- else {
- if (!isProxy) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexImage%d(target)", dimensions);
- return GL_TRUE;
- }
+ if (!target_can_be_compressed(ctx, target) && !isProxy) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexImage%d(target)", dimensions);
+ return GL_TRUE;
}
if (border != 0) {
if (!isProxy) {
@@ -1602,13 +1696,25 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
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_3D) {
+ 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;
}
@@ -1711,16 +1817,7 @@ subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
#endif
if (destTex->IsCompressed) {
- if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
- /* OK */
- }
- else if (ctx->Extensions.ARB_texture_cube_map &&
- (target == GL_PROXY_TEXTURE_CUBE_MAP ||
- (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
- /* OK */
- }
- else {
+ if (!target_can_be_compressed(ctx, target)) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glTexSubImage%D(target)", dimensions);
return GL_TRUE;
@@ -1862,6 +1959,17 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
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;
@@ -1975,15 +2083,23 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
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_3D) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
- return GL_TRUE;
+ 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;
}
}
@@ -2400,7 +2516,9 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
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)) {
+ target == GL_TEXTURE_RECTANGLE_NV) ||
+ (ctx->Extensions.MESA_texture_array &&
+ target == GL_TEXTURE_1D_ARRAY_EXT)) {
/* non-proxy target */
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
@@ -2458,7 +2576,9 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
(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.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);
@@ -2498,7 +2618,9 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (target == GL_TEXTURE_3D) {
+ if (target == GL_TEXTURE_3D ||
+ (ctx->Extensions.MESA_texture_array &&
+ target == GL_TEXTURE_2D_ARRAY_EXT)) {
/* non-proxy target */
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
@@ -2551,7 +2673,9 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
out:
_mesa_unlock_texture(ctx, texObj);
}
- else if (target == GL_PROXY_TEXTURE_3D) {
+ 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);