diff options
author | marha <marha@users.sourceforge.net> | 2012-09-18 08:21:05 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-09-18 08:21:05 +0200 |
commit | d7ddd6ead83965a10d450a580a9b6042c7b86f38 (patch) | |
tree | 9ca8c23b6aa54418990c4d851e8da97c577636a7 /mesalib/src/mesa/main/teximage.c | |
parent | c72f683c50e774b21967f0121245a286539fa555 (diff) | |
parent | 52213f2cd11c6cc7210cea6896ed464fddfe3fec (diff) | |
download | vcxsrv-d7ddd6ead83965a10d450a580a9b6042c7b86f38.tar.gz vcxsrv-d7ddd6ead83965a10d450a580a9b6042c7b86f38.tar.bz2 vcxsrv-d7ddd6ead83965a10d450a580a9b6042c7b86f38.zip |
Merge remote-tracking branch 'origin/released'
Diffstat (limited to 'mesalib/src/mesa/main/teximage.c')
-rw-r--r-- | mesalib/src/mesa/main/teximage.c | 415 |
1 files changed, 180 insertions, 235 deletions
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); |