aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/dd.h12
-rw-r--r--mesalib/src/mesa/main/teximage.c415
-rw-r--r--mesalib/src/mesa/main/teximage.h9
-rw-r--r--mesalib/src/mesa/main/texobj.h8
-rw-r--r--mesalib/src/mesa/main/texstorage.c186
-rw-r--r--mesalib/src/mesa/main/uniforms.h2
-rw-r--r--mesalib/src/mesa/main/version.c58
7 files changed, 320 insertions, 370 deletions
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index e6a1e68cb..0000a397a 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -251,14 +251,14 @@ struct dd_function_table {
struct gl_texture_object *texObj);
/**
- * Called by glTexImage[123]D when user specifies a proxy texture
- * target.
- *
- * \return GL_TRUE if the proxy test passes, or GL_FALSE if the test fails.
+ * Called by glTexImage, glCompressedTexImage, glCopyTexImage
+ * and glTexStorage to check if the dimensions of the texture image
+ * are too large.
+ * \param target any GL_PROXY_TEXTURE_x target
+ * \return GL_TRUE if the image is OK, GL_FALSE if too large
*/
GLboolean (*TestProxyTexImage)(struct gl_context *ctx, GLenum target,
- GLint level, GLint internalFormat,
- GLenum format, GLenum type,
+ GLint level, gl_format format,
GLint width, GLint height,
GLint depth, GLint border);
/*@}*/
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index da8fbcd32..83e79a5a3 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -1209,44 +1209,22 @@ _mesa_clear_texture_image(struct gl_context *ctx,
/**
- * This is the fallback for Driver.TestProxyTexImage(). Test the texture
- * level, width, height and depth against the ctx->Const limits for textures.
- *
- * A hardware driver might override this function if, for example, the
- * max 3D texture size is 512x512x64 (i.e. not a cube).
- *
- * Note that width, height, depth == 0 is not an error. However, a
- * texture with zero width/height/depth will be considered "incomplete"
- * and texturing will effectively be disabled.
- *
- * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
- * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
- * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
- * \param level as passed to glTexImage
- * \param internalFormat as passed to glTexImage
- * \param format as passed to glTexImage
- * \param type as passed to glTexImage
- * \param width as passed to glTexImage
- * \param height as passed to glTexImage
- * \param depth as passed to glTexImage
- * \param border as passed to glTexImage
- * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
+ * Check the width, height, depth and border of a texture image are legal.
+ * Used by all the glTexImage, glCompressedTexImage and glCopyTexImage
+ * functions.
+ * The target and level parameters will have already been validated.
+ * \return GL_TRUE if size is OK, GL_FALSE otherwise.
*/
GLboolean
-_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
- GLint internalFormat, GLenum format, GLenum type,
- GLint width, GLint height, GLint depth, GLint border)
+_mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
+ GLint level, GLint width, GLint height,
+ GLint depth, GLint border)
{
GLint maxSize;
- (void) internalFormat;
- (void) format;
- (void) type;
-
switch (target) {
+ case GL_TEXTURE_1D:
case GL_PROXY_TEXTURE_1D:
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); /* level zero size */
maxSize >>= level; /* level size */
if (width < 2 * border || width > 2 * border + maxSize)
@@ -1257,9 +1235,8 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
}
return GL_TRUE;
+ case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
maxSize >>= level;
if (width < 2 * border || width > 2 * border + maxSize)
@@ -1274,9 +1251,8 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
}
return GL_TRUE;
+ case GL_TEXTURE_3D:
case GL_PROXY_TEXTURE_3D:
- if (level >= ctx->Const.Max3DTextureLevels)
- return GL_FALSE;
maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
maxSize >>= level;
if (width < 2 * border || width > 2 * border + maxSize)
@@ -1295,6 +1271,7 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
}
return GL_TRUE;
+ case GL_TEXTURE_RECTANGLE_NV:
case GL_PROXY_TEXTURE_RECTANGLE_NV:
if (level != 0)
return GL_FALSE;
@@ -1305,9 +1282,13 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
return GL_FALSE;
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:
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
- if (level >= ctx->Const.MaxCubeTextureLevels)
- return GL_FALSE;
maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
maxSize >>= level;
if (width < 2 * border || width > 2 * border + maxSize)
@@ -1322,9 +1303,8 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
}
return GL_TRUE;
+ case GL_TEXTURE_1D_ARRAY_EXT:
case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
maxSize >>= level;
if (width < 2 * border || width > 2 * border + maxSize)
@@ -1337,9 +1317,8 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
}
return GL_TRUE;
+ case GL_TEXTURE_2D_ARRAY_EXT:
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- if (level >= ctx->Const.MaxTextureLevels)
- return GL_FALSE;
maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
maxSize >>= level;
if (width < 2 * border || width > 2 * border + maxSize)
@@ -1357,25 +1336,43 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
return GL_TRUE;
default:
- _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
+ _mesa_problem(ctx, "Invalid target in _mesa_legal_texture_dimensions()");
return GL_FALSE;
}
}
/**
- * 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.
+ * This is the fallback for Driver.TestProxyTexImage() for doing device-
+ * specific texture image size checks.
+ *
+ * A hardware driver might override this function if, for example, the
+ * max 3D texture size is 512x512x64 (i.e. not a cube).
+ *
+ * Note that width, height, depth == 0 is not an error. However, a
+ * texture with zero width/height/depth will be considered "incomplete"
+ * and texturing will effectively be disabled.
+ *
+ * \param target any texture target/type
+ * \param level as passed to glTexImage
+ * \param format the MESA_FORMAT_x for the tex image
+ * \param width as passed to glTexImage
+ * \param height as passed to glTexImage
+ * \param depth as passed to glTexImage
+ * \param border as passed to glTexImage
+ * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
*/
-static GLboolean
-legal_texture_size(struct gl_context *ctx, gl_format format,
- GLint width, GLint height, GLint depth)
+GLboolean
+_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
+ gl_format format,
+ GLint width, GLint height, GLint depth, GLint border)
{
+ /* We just check if the image size is less than MaxTextureMbytes.
+ * Some drivers may do more specific checks.
+ */
uint64_t bytes = _mesa_format_image_size64(format, width, height, depth);
uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */
+ mbytes *= _mesa_num_tex_faces(target);
return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes;
}
@@ -1664,19 +1661,11 @@ get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
/**
- * Special value returned by error some texture error checking functions when
- * an error is detected and the proxy texture image's width/height/depth/format
- * fields should be zeroed-out.
- */
-#define PROXY_ERROR 2
-
-
-/**
* Test the glTexImage[123]D() parameters for errors.
*
* \param ctx GL context.
* \param dimensions texture image dimensions (must be 1, 2 or 3).
- * \param target texture target given by the user.
+ * \param target texture target given by the user (already validated).
* \param level image level given by the user.
* \param internalFormat internal format given by the user.
* \param format pixel data format given by the user.
@@ -1686,14 +1675,17 @@ get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
* \param depth image depth given by the user.
* \param border image border given by the user.
*
- * \return PROXY_ERROR if there's an error that should zero-out the proxy image,
- * GL_TRUE if a regular GL error is found, or GL_FALSE if no error,
+ * \return GL_TRUE if a error is found, GL_FALSE otherwise
*
* Verifies each of the parameters against the constants specified in
* __struct gl_contextRec::Const and the supported extensions, and according
* to the OpenGL specification.
+ * Note that we don't fully error-check the width, height, depth values
+ * here. That's done in _mesa_legal_texture_dimensions() which is used
+ * by several other GL entrypoints. Plus, texture dims have a special
+ * interaction with proxy textures.
*/
-static GLenum
+static GLboolean
texture_error_check( struct gl_context *ctx,
GLuint dimensions, GLenum target,
GLint level, GLint internalFormat,
@@ -1701,9 +1693,6 @@ texture_error_check( struct gl_context *ctx,
GLint width, GLint height,
GLint depth, GLint border )
{
- const GLenum proxyTarget = _mesa_get_proxy_target(target);
- const GLboolean isProxy = target == proxyTarget;
- GLboolean sizeOK = GL_TRUE;
GLboolean colorFormat;
GLenum err;
@@ -1720,8 +1709,8 @@ texture_error_check( struct gl_context *ctx,
* zero-out behaviour is only used in cases related to memory allocation.
*/
- /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ /* level check */
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glTexImage%dD(level=%d)", dimensions, level);
return GL_TRUE;
@@ -1769,30 +1758,11 @@ texture_error_check( struct gl_context *ctx,
}
}
- /* Do this simple check before calling the TestProxyTexImage() function */
- if (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
- sizeOK = (width == height);
- }
-
- /*
- * 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);
- if (!sizeOK) {
- if (isProxy) {
- /* No GL error is recorded, but we need to zero-out the image dims */
- return PROXY_ERROR;
- }
- else {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
- dimensions, level, width, height, depth);
- return GL_TRUE;
- }
+ if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
+ _mesa_is_cube_face(target)) && width != height) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage2D(cube width != height)");
+ return GL_TRUE;
}
/* Check internalFormat */
@@ -1921,8 +1891,9 @@ texture_error_check( struct gl_context *ctx,
/**
* Error checking for glCompressedTexImage[123]D().
- * \param reason returns reason for error, if any
- * \return error code or GL_NO_ERROR or PROXY_ERROR.
+ * Note that the width, height and depth values are not fully error checked
+ * here.
+ * \return GL_TRUE if a error is found, GL_FALSE otherwise
*/
static GLenum
compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
@@ -1931,7 +1902,6 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
GLsizei height, GLsizei depth, GLint border,
GLsizei imageSize)
{
- const GLenum proxyTarget = _mesa_get_proxy_target(target);
const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
GLint expectedSize;
GLenum choose_format;
@@ -2033,13 +2003,15 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
}
/* For cube map, width must equal height */
- if (_mesa_is_cube_face(target) && width != height) {
+ if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
+ _mesa_is_cube_face(target)) && width != height) {
reason = "width != height";
error = GL_INVALID_VALUE;
goto error;
}
/* check image size against compression block size */
+ /* XXX possibly move this into the _mesa_legal_texture_dimensions() func */
{
gl_format texFormat =
ctx->Driver.ChooseTextureFormat(ctx, target, proxy_format,
@@ -2060,20 +2032,6 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
}
}
- /* check image sizes */
- if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
- proxy_format, choose_format,
- choose_type,
- width, height, depth, border)) {
- /* See error comment above */
- if (target == proxyTarget) {
- return PROXY_ERROR;
- }
- reason = "invalid width, height or format";
- error = GL_INVALID_OPERATION;
- goto error;
- }
-
/* check image size in bytes */
if (expectedSize != imageSize) {
/* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...]
@@ -2091,11 +2049,11 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
goto error;
}
- return GL_NO_ERROR;
+ return GL_FALSE;
error:
_mesa_error(ctx, error, "glCompressedTexImage%dD(%s)", dimensions, reason);
- return error;
+ return GL_TRUE;
}
@@ -2105,7 +2063,7 @@ error:
*
* \param ctx GL context.
* \param dimensions texture image dimensions (must be 1, 2 or 3).
- * \param target texture target given by the user.
+ * \param target texture target given by the user (already validated)
* \param level image level given by the user.
* \param xoffset sub-image x offset given by the user.
* \param yoffset sub-image y offset given by the user.
@@ -2131,8 +2089,8 @@ subtexture_error_check( struct gl_context *ctx, GLuint dimensions,
{
GLenum err;
- /* Basic level check */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ /* level check */
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
return GL_TRUE;
}
@@ -2306,9 +2264,6 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
GLenum target, GLint level, GLint internalFormat,
GLint width, GLint height, GLint border )
{
- const GLenum proxyTarget = _mesa_get_proxy_target(target);
- const GLenum type = GL_FLOAT;
- GLboolean sizeOK;
GLint baseFormat;
/* check target */
@@ -2318,8 +2273,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
return GL_TRUE;
}
- /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ /* level check */
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glCopyTexImage%dD(level=%d)", dimensions, level);
return GL_TRUE;
@@ -2403,25 +2358,10 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
}
}
- /* Do size, level checking */
- sizeOK = (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB)
- ? (width == height) : 1;
-
- sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
- internalFormat, baseFormat,
- type, width, height,
- 1, border);
-
- if (!sizeOK) {
- if (dimensions == 1) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage1D(width=%d)", width);
- }
- else {
- ASSERT(dimensions == 2);
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTexImage2D(width=%d, height=%d)", width, height);
- }
+ if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
+ _mesa_is_cube_face(target)) && width != height) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage2D(cube width != height)");
return GL_TRUE;
}
@@ -2497,7 +2437,7 @@ copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions,
}
/* Check level */
- if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glCopyTexSubImage%dD(level=%d)", dimensions, level);
return GL_TRUE;
@@ -2901,9 +2841,11 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
GLsizei imageSize, const GLvoid *pixels)
{
const char *func = compressed ? "glCompressedTexImage" : "glTexImage";
- GLenum error;
struct gl_pixelstore_attrib unpack_no_border;
const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
+ struct gl_texture_object *texObj;
+ gl_format texFormat;
+ GLboolean dimensionsOK, sizeOK;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
@@ -2937,22 +2879,23 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
/* general error checking */
if (compressed) {
- error = compressed_texture_error_check(ctx, dims, target, level,
- internalFormat,
- width, height, depth,
- border, imageSize);
+ if (compressed_texture_error_check(ctx, dims, target, level,
+ internalFormat,
+ width, height, depth,
+ border, imageSize))
+ return;
}
else {
- error = texture_error_check(ctx, dims, target, level, internalFormat,
- format, type, width, height, depth, border);
+ if (texture_error_check(ctx, dims, target, level, internalFormat,
+ format, type, width, height, depth, border))
+ return;
}
-#if FEATURE_ES
/* Here we convert a cpal compressed image into a regular glTexImage2D
* call by decompressing the texture. If we really want to support cpal
* textures in any driver this would have to be changed.
*/
- if (compressed && !error && dims == 2) {
+ if (ctx->API == API_OPENGLES && compressed && dims == 2) {
switch (internalFormat) {
case GL_PALETTE4_RGB8_OES:
case GL_PALETTE4_RGBA8_OES:
@@ -2969,50 +2912,55 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
return;
}
}
-#endif
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ assert(texObj);
+
+ texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, format, type);
+ assert(texFormat != MESA_FORMAT_NONE);
+
+ /* check that width, height, depth are legal for the mipmap level */
+ dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, level, width,
+ height, depth, border);
+
+ /* check that the texture won't take too much memory, etc */
+ sizeOK = ctx->Driver.TestProxyTexImage(ctx, _mesa_get_proxy_target(target),
+ level, texFormat,
+ width, height, depth, border);
if (_mesa_is_proxy_texture(target)) {
/* Proxy texture: just clear or set state depending on error checking */
struct gl_texture_image *texImage =
get_proxy_tex_image(ctx, target, level);
- gl_format texFormat = MESA_FORMAT_NONE;
- if (!error) {
- /* No parameter errors. Choose a texture format and see if we
- * can really allocate the texture.
- */
- struct gl_texture_object *texObj =
- _mesa_get_current_tex_object(ctx, target);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, format, type);
- if (!legal_texture_size(ctx, texFormat, width, height, depth)) {
- error = PROXY_ERROR;
- }
- }
+ if (!texImage)
+ return; /* GL_OUT_OF_MEMORY already recorded */
- if (error == PROXY_ERROR) {
- /* image too large, etc. Clear all proxy texture image parameters. */
- if (texImage)
- clear_teximage_fields(texImage);
- }
- else if (error == GL_FALSE) {
- /* no error: store the teximage parameters */
- if (texImage)
- _mesa_init_teximage_fields(ctx, texImage, width, height, depth,
- border, internalFormat, texFormat);
+ if (dimensionsOK && sizeOK) {
+ _mesa_init_teximage_fields(ctx, texImage, width, height, depth,
+ border, internalFormat, texFormat);
}
else {
- /* other, regular error (was already recorded) */
+ clear_teximage_fields(texImage);
}
}
else {
/* non-proxy target */
const GLuint face = _mesa_tex_target_to_face(target);
- struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- if (error) {
- return; /* error was recorded */
+ if (!dimensionsOK) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%uD(invalid width or height or depth)",
+ dims);
+ return;
+ }
+
+ if (!sizeOK) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glTexImage%uD(image too large)", dims);
+ return;
}
/* Allow a hardware driver to just strip out the border, to provide
@@ -3029,8 +2977,6 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
if (ctx->NewState & _NEW_PIXEL)
_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);
@@ -3039,38 +2985,27 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
_mesa_error(ctx, GL_OUT_OF_MEMORY, "%s%uD", func, dims);
}
else {
- gl_format texFormat;
-
ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, format,
- type);
-
- if (legal_texture_size(ctx, texFormat, width, height, depth)) {
- _mesa_init_teximage_fields(ctx, texImage,
- width, height, depth,
- border, internalFormat, texFormat);
-
- /* Give the texture to the driver. <pixels> may be null. */
- if (compressed) {
- ctx->Driver.CompressedTexImage(ctx, dims, texImage,
- imageSize, pixels);
- }
- else {
- ctx->Driver.TexImage(ctx, dims, texImage, format,
- type, pixels, unpack);
- }
-
- check_gen_mipmap(ctx, target, texObj, level);
-
- _mesa_update_fbo_texture(ctx, texObj, face, level);
+ _mesa_init_teximage_fields(ctx, texImage,
+ width, height, depth,
+ border, internalFormat, texFormat);
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+ /* Give the texture to the driver. <pixels> may be null. */
+ if (compressed) {
+ ctx->Driver.CompressedTexImage(ctx, dims, texImage,
+ imageSize, pixels);
}
else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s%uD", func, dims);
+ ctx->Driver.TexImage(ctx, dims, texImage, format,
+ type, pixels, unpack);
}
+
+ check_gen_mipmap(ctx, target, texObj, level);
+
+ _mesa_update_fbo_texture(ctx, texObj, face, level);
+
+ _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
}
}
_mesa_unlock_texture(ctx, texObj);
@@ -3078,6 +3013,7 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
}
+
/*
* Called from the API. Note that width includes the border.
*/
@@ -3343,6 +3279,7 @@ copyteximage(struct gl_context *ctx, GLuint dims,
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
const GLuint face = _mesa_tex_target_to_face(target);
+ gl_format texFormat;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
@@ -3360,7 +3297,27 @@ copyteximage(struct gl_context *ctx, GLuint dims,
width, height, border))
return;
+ if (!_mesa_legal_texture_dimensions(ctx, target, level, width, height,
+ 1, border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage%uD(invalid width or height)", dims);
+ return;
+ }
+
texObj = _mesa_get_current_tex_object(ctx, target);
+ assert(texObj);
+
+ texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, GL_NONE, GL_NONE);
+ assert(texFormat != MESA_FORMAT_NONE);
+
+ if (!ctx->Driver.TestProxyTexImage(ctx, _mesa_get_proxy_target(target),
+ level, texFormat,
+ width, height, 1, border)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glCopyTexImage%uD(image too large)", dims);
+ return;
+ }
if (border && ctx->Const.StripTextureBorder) {
x += border;
@@ -3380,45 +3337,33 @@ copyteximage(struct gl_context *ctx, GLuint dims,
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
}
else {
- /* choose actual hw format */
- gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
- target, level,
- internalFormat,
- GL_NONE, GL_NONE);
-
- if (legal_texture_size(ctx, texFormat, width, height, 1)) {
- GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0;
+ GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0;
- /* Free old texture image */
- ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
+ /* Free old texture image */
+ ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
- _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
- border, internalFormat, texFormat);
+ _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
+ border, internalFormat, texFormat);
- /* Allocate texture memory (no pixel data yet) */
- ctx->Driver.TexImage(ctx, dims, texImage,
- GL_NONE, GL_NONE,
- NULL, &ctx->Unpack);
+ /* Allocate texture memory (no pixel data yet) */
+ ctx->Driver.TexImage(ctx, dims, texImage,
+ GL_NONE, GL_NONE,
+ NULL, &ctx->Unpack);
- if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY,
- &width, &height)) {
- struct gl_renderbuffer *srcRb =
- get_copy_tex_image_source(ctx, texImage->TexFormat);
+ if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY,
+ &width, &height)) {
+ struct gl_renderbuffer *srcRb =
+ get_copy_tex_image_source(ctx, texImage->TexFormat);
- ctx->Driver.CopyTexSubImage(ctx, dims, texImage, dstX, dstY, dstZ,
- srcRb, srcX, srcY, width, height);
- }
+ ctx->Driver.CopyTexSubImage(ctx, dims, texImage, dstX, dstY, dstZ,
+ srcRb, srcX, srcY, width, height);
+ }
- check_gen_mipmap(ctx, target, texObj, level);
+ check_gen_mipmap(ctx, target, texObj, level);
- _mesa_update_fbo_texture(ctx, texObj, face, level);
+ _mesa_update_fbo_texture(ctx, texObj, face, level);
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
- }
- else {
- /* probably too large of image */
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
- }
+ _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
}
}
_mesa_unlock_texture(ctx, texObj);
diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h
index 36fd1c2bc..c7c32d8ac 100644
--- a/mesalib/src/mesa/main/teximage.h
+++ b/mesalib/src/mesa/main/teximage.h
@@ -128,8 +128,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target);
extern GLboolean
_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
- GLint internalFormat, GLenum format, GLenum type,
- GLint width, GLint height, GLint depth, GLint border);
+ gl_format format,
+ GLint width, GLint height, GLint depth, GLint border);
extern GLuint
@@ -142,6 +142,11 @@ extern GLenum
_mesa_es_error_check_format_and_type(GLenum format, GLenum type,
unsigned dimensions);
+extern GLboolean
+_mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
+ GLint level, GLint width, GLint height,
+ GLint depth, GLint border);
+
/**
* Lock a texture for updating. See also _mesa_lock_context_textures().
*/
diff --git a/mesalib/src/mesa/main/texobj.h b/mesalib/src/mesa/main/texobj.h
index a6f1d3a14..f22c58cad 100644
--- a/mesalib/src/mesa/main/texobj.h
+++ b/mesalib/src/mesa/main/texobj.h
@@ -85,7 +85,13 @@ _mesa_reference_texobj(struct gl_texture_object **ptr,
static inline GLuint
_mesa_num_tex_faces(GLenum target)
{
- return target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
+ switch (target) {
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ return 6;
+ default:
+ return 1;
+ }
}
diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c
index f8a939794..ca02ef301 100644
--- a/mesalib/src/mesa/main/texstorage.c
+++ b/mesalib/src/mesa/main/texstorage.c
@@ -118,42 +118,42 @@ next_mipmap_level_size(GLenum target,
}
-/**
- * Do actual memory allocation for glTexStorage1/2/3D().
- */
-static void
-setup_texstorage(struct gl_context *ctx,
- struct gl_texture_object *texObj,
- GLuint dims,
- GLsizei levels, GLenum internalFormat,
- GLsizei width, GLsizei height, GLsizei depth)
+/** Helper to get a particular texture image in a texture object */
+static struct gl_texture_image *
+get_tex_image(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ GLuint face, GLuint level)
+{
+ const GLenum faceTarget =
+ (texObj->Target == GL_TEXTURE_CUBE_MAP ||
+ texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP)
+ ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target;
+ return _mesa_get_tex_image(ctx, texObj, faceTarget, level);
+}
+
+
+
+static GLboolean
+initialize_texture_fields(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ GLint levels,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum internalFormat, gl_format texFormat)
{
const GLenum target = texObj->Target;
const GLuint numFaces = _mesa_num_tex_faces(target);
- gl_format texFormat;
GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
GLuint face;
- assert(levels > 0);
- assert(width > 0);
- assert(height > 0);
- assert(depth > 0);
-
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
- internalFormat, GL_NONE, GL_NONE);
-
/* Set up all the texture object's gl_texture_images */
for (level = 0; level < levels; level++) {
for (face = 0; face < numFaces; face++) {
- const GLenum faceTarget =
- (target == GL_TEXTURE_CUBE_MAP)
- ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : target;
struct gl_texture_image *texImage =
- _mesa_get_tex_image(ctx, texObj, faceTarget, level);
+ get_tex_image(ctx, texObj, face, level);
if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
- return;
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
+ return GL_FALSE;
}
_mesa_init_teximage_fields(ctx, texImage,
@@ -163,49 +163,18 @@ setup_texstorage(struct gl_context *ctx,
next_mipmap_level_size(target, &levelWidth, &levelHeight, &levelDepth);
}
-
- assert(levelWidth > 0);
- assert(levelHeight > 0);
- assert(levelDepth > 0);
-
- if (!_mesa_is_proxy_texture(texObj->Target)) {
- /* Do actual texture memory allocation */
- if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels,
- width, height, depth)) {
- /* Reset the texture images' info to zeros.
- * Strictly speaking, we probably don't have to do this since
- * generating GL_OUT_OF_MEMORY can leave things in an undefined
- * state but this puts things in a consistent state.
- */
- for (level = 0; level < levels; level++) {
- for (face = 0; face < numFaces; face++) {
- struct gl_texture_image *texImage = texObj->Image[face][level];
- if (texImage) {
- _mesa_init_teximage_fields(ctx, texImage,
- 0, 0, 0, 0,
- GL_NONE, MESA_FORMAT_NONE);
- }
- }
- }
-
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims);
-
- return;
- }
-
- /* Only set this field for non-proxy texture objects */
- texObj->Immutable = GL_TRUE;
- }
+ return GL_TRUE;
}
/**
* Clear all fields of texture object to zeros. Used for proxy texture tests.
+ * Used for proxy texture tests (and to clean up when a texture memory
+ * allocation fails).
*/
static void
-clear_image_fields(struct gl_context *ctx,
- GLuint dims,
- struct gl_texture_object *texObj)
+clear_texture_fields(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
{
const GLenum target = texObj->Target;
const GLuint numFaces = _mesa_num_tex_faces(target);
@@ -214,19 +183,17 @@ clear_image_fields(struct gl_context *ctx,
for (level = 0; level < Elements(texObj->Image[0]); level++) {
for (face = 0; face < numFaces; face++) {
- const GLenum faceTarget =
- (target == GL_TEXTURE_CUBE_MAP)
- ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : target;
struct gl_texture_image *texImage =
- _mesa_get_tex_image(ctx, texObj, faceTarget, level);
+ get_tex_image(ctx, texObj, face, level);
if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
return;
}
_mesa_init_teximage_fields(ctx, texImage,
- 0, 0, 0, 0, GL_NONE, MESA_FORMAT_NONE);
+ 0, 0, 0, 0, /* w, h, d, border */
+ GL_NONE, MESA_FORMAT_NONE);
}
}
}
@@ -301,13 +268,6 @@ tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target,
return GL_TRUE;
}
- /* levels check */
- if (levels < 1 || height < 1 || depth < 1) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)",
- dims);
- return GL_TRUE;
- }
-
/* target check */
if (!legal_texobj_target(ctx, dims, target)) {
_mesa_error(ctx, GL_INVALID_ENUM,
@@ -316,7 +276,14 @@ tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target,
return GL_TRUE;
}
- /* check levels against maximum */
+ /* levels check */
+ if (levels < 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)",
+ dims);
+ return GL_TRUE;
+ }
+
+ /* check levels against maximum (note different error than above) */
if (levels > _mesa_max_texture_levels(ctx, target)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glTexStorage%uD(levels too large)", dims);
@@ -359,37 +326,76 @@ texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth)
{
struct gl_texture_object *texObj;
- GLboolean sizeOK;
- GLenum proxyTarget = _mesa_get_proxy_target(target);
+ GLboolean sizeOK, dimensionsOK;
+ gl_format texFormat;
GET_CURRENT_CONTEXT(ctx);
- texObj = _mesa_get_current_tex_object(ctx, target);
-
if (tex_storage_error_check(ctx, dims, target, levels,
internalformat, width, height, depth)) {
return; /* error was recorded */
}
- sizeOK = ctx->Driver.TestProxyTexImage(ctx, proxyTarget, 0,
- internalformat, GL_NONE, GL_NONE,
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ assert(texObj);
+
+ texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
+ internalformat, GL_NONE, GL_NONE);
+ assert(texFormat != MESA_FORMAT_NONE);
+
+ /* check that width, height, depth are legal for the mipmap level */
+ dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
+ width, height, depth, 0);
+
+ sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, texFormat,
width, height, depth, 0);
- if (!sizeOK) {
- if (_mesa_is_proxy_texture(texObj->Target)) {
- /* clear all image fields for [levels] */
- clear_image_fields(ctx, dims, texObj);
+ if (_mesa_is_proxy_texture(texObj->Target)) {
+ if (dimensionsOK && sizeOK) {
+ initialize_texture_fields(ctx, texObj, levels, width, height, depth,
+ internalformat, texFormat);
}
else {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexStorage%uD(invalid width, height or depth)",
- dims);
- return;
+ /* clear all image fields for [levels] */
+ clear_texture_fields(ctx, texObj);
}
}
else {
- setup_texstorage(ctx, texObj, dims, levels, internalformat,
- width, height, depth);
+ if (!dimensionsOK) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexStorage%uD(invalid width, height or depth)", dims);
+ return;
+ }
+
+ if (!sizeOK) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glTexStorage%uD(texture too large)", dims);
+ }
+
+ assert(levels > 0);
+ assert(width > 0);
+ assert(height > 0);
+ assert(depth > 0);
+
+ if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
+ internalformat, texFormat)) {
+ return;
+ }
+
+ /* Do actual texture memory allocation */
+ if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels,
+ width, height, depth)) {
+ /* Reset the texture images' info to zeros.
+ * Strictly speaking, we probably don't have to do this since
+ * generating GL_OUT_OF_MEMORY can leave things in an undefined
+ * state but this puts things in a consistent state.
+ */
+ clear_texture_fields(ctx, texObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims);
+ return;
+ }
+
+ texObj->Immutable = GL_TRUE;
}
}
diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h
index bb0552476..e84964c6f 100644
--- a/mesalib/src/mesa/main/uniforms.h
+++ b/mesalib/src/mesa/main/uniforms.h
@@ -244,8 +244,6 @@ struct gl_builtin_uniform_desc {
unsigned int num_elements;
};
-extern const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[];
-
/**
* \name GLSL uniform arrays and structs require special handling.
*
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index bc7b1fa0e..55638a807 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -55,6 +55,27 @@ override_version(struct gl_context *ctx)
}
/**
+ * Builds the MESA version string.
+ */
+static void
+create_version_string(struct gl_context *ctx, const char *prefix)
+{
+ static const int max = 100;
+
+ ctx->VersionString = malloc(max);
+ if (ctx->VersionString) {
+ _mesa_snprintf(ctx->VersionString, max,
+ "%s%u.%u Mesa " MESA_VERSION_STRING
+#ifdef MESA_GIT_SHA1
+ " (" MESA_GIT_SHA1 ")"
+#endif
+ ,
+ prefix,
+ ctx->Version / 10, ctx->Version % 10);
+ }
+}
+
+/**
* Override the context's GLSL version if the environment variable
* MESA_GLSL_VERSION_OVERRIDE is set. Valid values for
* MESA_GLSL_VERSION_OVERRIDE are integers, such as "130".
@@ -85,7 +106,6 @@ static void
compute_version(struct gl_context *ctx)
{
GLuint major, minor;
- static const int max = 100;
const GLboolean ver_1_3 = (ctx->Extensions.ARB_texture_border_clamp &&
ctx->Extensions.ARB_texture_cube_map &&
@@ -224,23 +244,12 @@ compute_version(struct gl_context *ctx)
override_version(ctx);
- ctx->VersionString = malloc(max);
- if (ctx->VersionString) {
- _mesa_snprintf(ctx->VersionString, max,
- "%u.%u Mesa " MESA_VERSION_STRING
-#ifdef MESA_GIT_SHA1
- " (" MESA_GIT_SHA1 ")"
-#endif
- ,
- ctx->Version / 10, ctx->Version % 10);
- }
+ create_version_string(ctx, "");
}
static void
compute_version_es1(struct gl_context *ctx)
{
- static const int max = 100;
-
/* OpenGL ES 1.0 is derived from OpenGL 1.3 */
const GLboolean ver_1_0 = (ctx->Extensions.ARB_texture_env_combine &&
ctx->Extensions.ARB_texture_env_dot3);
@@ -256,23 +265,12 @@ compute_version_es1(struct gl_context *ctx)
_mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
}
- ctx->VersionString = malloc(max);
- if (ctx->VersionString) {
- _mesa_snprintf(ctx->VersionString, max,
- "OpenGL ES-CM 1.%d Mesa " MESA_VERSION_STRING
-#ifdef MESA_GIT_SHA1
- " (" MESA_GIT_SHA1 ")"
-#endif
- ,
- ctx->Version % 10);
- }
+ create_version_string(ctx, "OpenGL ES-CM ");
}
static void
compute_version_es2(struct gl_context *ctx)
{
- static const int max = 100;
-
/* OpenGL ES 2.0 is derived from OpenGL 2.0 */
const GLboolean ver_2_0 = (ctx->Extensions.ARB_texture_cube_map &&
ctx->Extensions.EXT_blend_color &&
@@ -289,15 +287,7 @@ compute_version_es2(struct gl_context *ctx)
_mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
}
- ctx->VersionString = malloc(max);
- if (ctx->VersionString) {
- _mesa_snprintf(ctx->VersionString, max,
- "OpenGL ES 2.0 Mesa " MESA_VERSION_STRING
-#ifdef MESA_GIT_SHA1
- " (" MESA_GIT_SHA1 ")"
-#endif
- );
- }
+ create_version_string(ctx, "OpenGL ES ");
}
/**