diff options
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/dd.h | 12 | ||||
-rw-r--r-- | mesalib/src/mesa/main/teximage.c | 415 | ||||
-rw-r--r-- | mesalib/src/mesa/main/teximage.h | 9 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texobj.h | 8 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texstorage.c | 186 | ||||
-rw-r--r-- | mesalib/src/mesa/main/uniforms.h | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/version.c | 58 |
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 7b67765a2..7ee662714 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 "); } /** |