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.c363
1 files changed, 343 insertions, 20 deletions
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 2a3037f..8fb54c6 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -55,9 +55,7 @@
* In particular, we care about pixel transfer state and buffer state
* (such as glReadBuffer to make sure we read from the right renderbuffer).
*/
-#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
- _NEW_BUFFERS | \
- _NEW_PIXEL)
+#define NEW_COPY_TEX_STATE (_NEW_BUFFERS | _NEW_PIXEL)
@@ -313,11 +311,40 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
}
}
- if (ctx->Extensions.MESA_texture_signed_rgba) {
+ if (ctx->Extensions.EXT_texture_snorm) {
switch (internalFormat) {
+ case GL_RED_SNORM:
+ case GL_R8_SNORM:
+ case GL_R16_SNORM:
+ return GL_RED;
+ case GL_RG_SNORM:
+ case GL_RG8_SNORM:
+ case GL_RG16_SNORM:
+ return GL_RG;
+ case GL_RGB_SNORM:
+ case GL_RGB8_SNORM:
+ case GL_RGB16_SNORM:
+ return GL_RGB;
case GL_RGBA_SNORM:
case GL_RGBA8_SNORM:
+ case GL_RGBA16_SNORM:
return GL_RGBA;
+ case GL_ALPHA_SNORM:
+ case GL_ALPHA8_SNORM:
+ case GL_ALPHA16_SNORM:
+ return GL_ALPHA;
+ case GL_LUMINANCE_SNORM:
+ case GL_LUMINANCE8_SNORM:
+ case GL_LUMINANCE16_SNORM:
+ return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA_SNORM:
+ case GL_LUMINANCE8_ALPHA8_SNORM:
+ case GL_LUMINANCE16_ALPHA16_SNORM:
+ return GL_LUMINANCE_ALPHA;
+ case GL_INTENSITY_SNORM:
+ case GL_INTENSITY8_SNORM:
+ case GL_INTENSITY16_SNORM:
+ return GL_INTENSITY;
default:
; /* fallthrough */
}
@@ -654,8 +681,10 @@ _mesa_delete_texture_image(struct gl_context *ctx,
GLboolean
_mesa_is_proxy_texture(GLenum target)
{
- /* NUM_TEXTURE_TARGETS should match number of terms below */
- assert(NUM_TEXTURE_TARGETS == 7);
+ /* NUM_TEXTURE_TARGETS should match number of terms below,
+ * except there's no proxy for GL_TEXTURE_BUFFER.
+ */
+ assert(NUM_TEXTURE_TARGETS == 8);
return (target == GL_PROXY_TEXTURE_1D ||
target == GL_PROXY_TEXTURE_2D ||
@@ -767,6 +796,9 @@ _mesa_select_tex_object(struct gl_context *ctx,
return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
+ case GL_TEXTURE_BUFFER:
+ return ctx->Extensions.ARB_texture_buffer_object
+ ? texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
default:
_mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
return NULL;
@@ -954,6 +986,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
return (ctx->Extensions.MESA_texture_array ||
ctx->Extensions.EXT_texture_array)
? ctx->Const.MaxTextureLevels : 0;
+ case GL_TEXTURE_BUFFER:
+ /* fall-through */
default:
return 0; /* bad target */
}
@@ -990,6 +1024,8 @@ _mesa_get_texture_dimensions(GLenum target)
case GL_TEXTURE_2D_ARRAY:
case GL_PROXY_TEXTURE_2D_ARRAY:
return 3;
+ case GL_TEXTURE_BUFFER:
+ /* fall-through */
default:
_mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()",
target);
@@ -2224,7 +2260,7 @@ check_rtt_cb(GLuint key, void *data, void *userData)
att->Texture == texObj &&
att->TextureLevel == level &&
att->CubeMapFace == face) {
- ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
+ ASSERT(_mesa_get_attachment_teximage(att));
/* Tell driver about the new renderbuffer texture */
ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
/* Mark fb status as indeterminate to force re-validation */
@@ -2434,7 +2470,7 @@ teximage(struct gl_context *ctx, GLuint dims,
return; /* error was recorded */
}
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _NEW_PIXEL)
_mesa_update_state(ctx);
texObj = _mesa_get_current_tex_object(ctx, target);
@@ -2580,7 +2616,7 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
return;
}
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _NEW_PIXEL)
_mesa_update_state(ctx);
texObj = _mesa_get_current_tex_object(ctx, target);
@@ -2637,7 +2673,7 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
return;
}
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _NEW_PIXEL)
_mesa_update_state(ctx);
if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset,
@@ -2997,6 +3033,7 @@ get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
/**
* Error checking for glCompressedTexImage[123]D().
+ * \param reason returns reason for error, if any
* \return error code or GL_NO_ERROR.
*/
static GLenum
@@ -3004,36 +3041,49 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
GLenum target, GLint level,
GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLint border,
- GLsizei imageSize)
+ GLsizei imageSize, char **reason)
{
const GLenum proxyTarget = get_proxy_target(target);
const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
GLint expectedSize;
+ *reason = ""; /* no error */
+
/* check level */
- if (level < 0 || level >= maxLevels)
+ if (level < 0 || level >= maxLevels) {
+ *reason = "level";
return GL_INVALID_VALUE;
+ }
if (!target_can_be_compressed(ctx, target, internalFormat)) {
+ *reason = "target";
return GL_INVALID_ENUM;
}
/* This will detect any invalid internalFormat value */
- if (!_mesa_is_compressed_format(ctx, internalFormat))
+ if (!_mesa_is_compressed_format(ctx, internalFormat)) {
+ *reason = "internalFormat";
return GL_INVALID_ENUM;
+ }
/* This should really never fail */
- if (_mesa_base_tex_format(ctx, internalFormat) < 0)
+ if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
+ *reason = "internalFormat";
return GL_INVALID_ENUM;
+ }
/* No compressed formats support borders at this time */
- if (border != 0)
+ if (border != 0) {
+ *reason = "border != 0";
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)
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) {
+ *reason = "width != height";
return GL_INVALID_VALUE;
+ }
/* check image size against compression block size */
{
@@ -3050,6 +3100,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
* generated [...] if any parameter combinations are not
* supported by the specific compressed internal format.
*/
+ *reason = "invalid width or height for compression format";
return GL_INVALID_OPERATION;
}
}
@@ -3059,6 +3110,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
internalFormat, GL_NONE, GL_NONE,
width, height, depth, border)) {
/* See error comment above */
+ *reason = "invalid width, height or format";
return GL_INVALID_OPERATION;
}
@@ -3069,6 +3121,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
* if <imageSize> is not consistent with the format, dimensions, and
* contents of the specified image.
*/
+ *reason = "imageSize inconsistant with width/height/format";
return GL_INVALID_VALUE;
}
@@ -3223,6 +3276,7 @@ compressedteximage(struct gl_context *ctx, GLuint dims,
GLsizei imageSize, const GLvoid *data)
{
GLenum error;
+ char *reason = "";
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
@@ -3243,15 +3297,15 @@ compressedteximage(struct gl_context *ctx, GLuint dims,
error = compressed_texture_error_check(ctx, dims, target, level,
internalFormat, width, height, depth,
- border, imageSize);
+ border, imageSize, &reason);
-#if FEATURE_ES
- /* XXX this is kind of a hack */
if (error) {
- _mesa_error(ctx, error, "glTexImage2D");
+ _mesa_error(ctx, error, "glTexImage2D(%s)", reason);
return;
}
+#if FEATURE_ES
+ /* XXX this is kind of a hack */
if (dims == 2) {
switch (internalFormat) {
case GL_PALETTE4_RGB8_OES:
@@ -3524,3 +3578,272 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset,
width, height, depth, format, imageSize, data);
}
+
+
+/**
+ * Helper for glTexBuffer(). Check if internalFormat is legal. If so,
+ * return the basic data type and number of components for the format.
+ * \param return GL_TRUE if internalFormat is legal, GL_FALSE otherwise
+ */
+static GLboolean
+get_sized_format_info(const struct gl_context *ctx, GLenum internalFormat,
+ GLenum *datatype, GLuint *components)
+{
+ switch (internalFormat) {
+ case GL_ALPHA8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 1;
+ break;
+ case GL_ALPHA16:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 1;
+ break;
+ case GL_ALPHA16F_ARB:
+ *datatype = GL_HALF_FLOAT;
+ *components = 1;
+ break;
+ case GL_ALPHA32F_ARB:
+ *datatype = GL_FLOAT;
+ *components = 1;
+ break;
+ case GL_ALPHA8I_EXT:
+ *datatype = GL_BYTE;
+ *components = 1;
+ break;
+ case GL_ALPHA16I_EXT:
+ *datatype = GL_SHORT;
+ *components = 1;
+ break;
+ case GL_ALPHA32I_EXT:
+ *datatype = GL_INT;
+ *components = 1;
+ break;
+ case GL_ALPHA8UI_EXT:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 1;
+ break;
+ case GL_ALPHA16UI_EXT:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 1;
+ break;
+ case GL_ALPHA32UI_EXT:
+ *datatype = GL_UNSIGNED_INT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 1;
+ break;
+ case GL_LUMINANCE16:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE16F_ARB:
+ *datatype = GL_HALF_FLOAT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE32F_ARB:
+ *datatype = GL_FLOAT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE8I_EXT:
+ *datatype = GL_BYTE;
+ *components = 1;
+ break;
+ case GL_LUMINANCE16I_EXT:
+ *datatype = GL_SHORT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE32I_EXT:
+ *datatype = GL_INT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE8UI_EXT:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 1;
+ break;
+ case GL_LUMINANCE16UI_EXT:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE32UI_EXT:
+ *datatype = GL_UNSIGNED_INT;
+ *components = 1;
+ break;
+ case GL_LUMINANCE8_ALPHA8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 2;
+ break;
+ case GL_LUMINANCE16_ALPHA16:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ *datatype = GL_HALF_FLOAT;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ *datatype = GL_FLOAT;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA8I_EXT:
+ *datatype = GL_BYTE;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA16I_EXT:
+ *datatype = GL_SHORT;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA32I_EXT:
+ *datatype = GL_INT;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA8UI_EXT:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA16UI_EXT:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 2;
+ break;
+ case GL_LUMINANCE_ALPHA32UI_EXT:
+ *datatype = GL_UNSIGNED_INT;
+ *components = 2;
+ break;
+ case GL_INTENSITY8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 1;
+ break;
+ case GL_INTENSITY16:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 1;
+ break;
+ case GL_INTENSITY16F_ARB:
+ *datatype = GL_HALF_FLOAT;
+ *components = 1;
+ break;
+ case GL_INTENSITY32F_ARB:
+ *datatype = GL_FLOAT;
+ *components = 1;
+ break;
+ case GL_INTENSITY8I_EXT:
+ *datatype = GL_BYTE;
+ *components = 1;
+ break;
+ case GL_INTENSITY16I_EXT:
+ *datatype = GL_SHORT;
+ *components = 1;
+ break;
+ case GL_INTENSITY32I_EXT:
+ *datatype = GL_INT;
+ *components = 1;
+ break;
+ case GL_INTENSITY8UI_EXT:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 1;
+ break;
+ case GL_INTENSITY16UI_EXT:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 1;
+ break;
+ case GL_INTENSITY32UI_EXT:
+ *datatype = GL_UNSIGNED_INT;
+ *components = 1;
+ break;
+ case GL_RGBA8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 4;
+ break;
+ case GL_RGBA16:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 4;
+ break;
+ case GL_RGBA16F_ARB:
+ *datatype = GL_HALF_FLOAT;
+ *components = 4;
+ break;
+ case GL_RGBA32F_ARB:
+ *datatype = GL_FLOAT;
+ *components = 4;
+ break;
+ case GL_RGBA8I_EXT:
+ *datatype = GL_BYTE;
+ *components = 4;
+ break;
+ case GL_RGBA16I_EXT:
+ *datatype = GL_SHORT;
+ *components = 4;
+ break;
+ case GL_RGBA32I_EXT:
+ *datatype = GL_INT;
+ *components = 4;
+ break;
+ case GL_RGBA8UI_EXT:
+ *datatype = GL_UNSIGNED_BYTE;
+ *components = 4;
+ break;
+ case GL_RGBA16UI_EXT:
+ *datatype = GL_UNSIGNED_SHORT;
+ *components = 4;
+ break;
+ case GL_RGBA32UI_EXT:
+ *datatype = GL_UNSIGNED_INT;
+ *components = 4;
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ if (*datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float)
+ return GL_FALSE;
+
+ if (*datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/** GL_ARB_texture_buffer_object */
+void GLAPIENTRY
+_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
+{
+ struct gl_texture_object *texObj;
+ struct gl_buffer_object *bufObj;
+ GLenum dataType;
+ GLuint comps;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (!ctx->Extensions.ARB_texture_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer");
+ return;
+ }
+
+ if (target != GL_TEXTURE_BUFFER_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(target)");
+ return;
+ }
+
+ if (!get_sized_format_info(ctx, internalFormat, &dataType, &comps)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(internalFormat 0x%x)",
+ internalFormat);
+ return;
+ }
+
+ bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ if (buffer && !bufObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer(buffer %u)", buffer);
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ _mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj);
+ texObj->BufferObjectFormat = internalFormat;
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}