The clear texture extension is used to clear a texture to a given value without having to provide a buffer for the whole texture and without having to create an FBO. This patch provides a generic implementation that works with any driver. There are two approaches, the first being in meta.c which tries to create a GL framebuffer to the texture and calls glClear. This can fail if the FBO extension is not supported or if the texture can't be used as a render target. In that case it will fall back to an implementation in texstore.c which maps a region of the texture and just directly writes in the values.
A small problem with this patch is that the fallback approach that maps the texture doesn't seem to work with depth-stencil textures. However I think this may be a general bug with mapping depth-stencil textures because I seem to get the same issue if I try to update the texture using glTexSubImage2D as well. You can replicate this if you run the Piglit test arb_clear_texture-depth-stencil and set MESA_EXTENSION_OVERRIDE to -GL_ARB_framebuffer_object. --- src/mapi/glapi/gen/ARB_clear_texture.xml | 32 ++++ src/mapi/glapi/gen/gl_API.xml | 6 +- src/mesa/drivers/common/driverfuncs.c | 1 + src/mesa/drivers/common/meta.c | 143 ++++++++++++++++++ src/mesa/drivers/common/meta.h | 14 ++ src/mesa/main/dd.h | 14 ++ src/mesa/main/extensions.c | 1 + src/mesa/main/teximage.c | 251 ++++++++++++++++++++++++++++++- src/mesa/main/teximage.h | 12 ++ src/mesa/main/texstore.c | 70 +++++++++ src/mesa/main/texstore.h | 7 + 11 files changed, 549 insertions(+), 2 deletions(-) create mode 100644 src/mapi/glapi/gen/ARB_clear_texture.xml diff --git a/src/mapi/glapi/gen/ARB_clear_texture.xml b/src/mapi/glapi/gen/ARB_clear_texture.xml new file mode 100644 index 0000000..9bb400a --- /dev/null +++ b/src/mapi/glapi/gen/ARB_clear_texture.xml @@ -0,0 +1,32 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_ARB_clear_texture" number="145"> + + <function name ="ClearTexImage" offset="assign"> + <param name="texture" type="GLuint"/> + <param name="level" type="GLint"/> + <param name="format" type="GLenum"/> + <param name="type" type="GLenum"/> + <param name="data" type="const GLvoid *"/> + </function> + + <function name ="ClearTexSubImage" offset="assign"> + <param name="texture" type="GLuint"/> + <param name="level" type="GLint"/> + <param name="xoffset" type="GLint"/> + <param name="yoffset" type="GLint"/> + <param name="zoffset" type="GLint"/> + <param name="width" type="GLsizei"/> + <param name="height" type="GLsizei"/> + <param name="depth" type="GLsizei"/> + <param name="format" type="GLenum"/> + <param name="type" type="GLenum"/> + <param name="data" type="const GLvoid *"/> + </function> + +</category> + +</OpenGLAPI> diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml index 0791bfc..181263a 100644 --- a/src/mapi/glapi/gen/gl_API.xml +++ b/src/mapi/glapi/gen/gl_API.xml @@ -8344,7 +8344,11 @@ </function> </category> -<!-- ARB extensions #145...#146 --> +<!-- ARB extension #145 --> + +<xi:include href="ARB_clear_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + +<!-- ARB extension #147 --> <xi:include href="ARB_multi_bind.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index 6ece5d8..4f0f7a6 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -95,6 +95,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->TexImage = _mesa_store_teximage; driver->TexSubImage = _mesa_store_texsubimage; driver->GetTexImage = _mesa_meta_GetTexImage; + driver->ClearTexSubImage = _mesa_meta_ClearTexSubImage; driver->CopyTexSubImage = _mesa_meta_CopyTexSubImage; driver->GenerateMipmap = _mesa_meta_GenerateMipmap; driver->TestProxyTexImage = _mesa_test_proxy_teximage; diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c index fec0d2b..e4aa8b2 100644 --- a/src/mesa/drivers/common/meta.c +++ b/src/mesa/drivers/common/meta.c @@ -40,6 +40,7 @@ #include "main/blit.h" #include "main/bufferobj.h" #include "main/buffers.h" +#include "main/clear.h" #include "main/colortab.h" #include "main/condrender.h" #include "main/depth.h" @@ -47,6 +48,7 @@ #include "main/fbobject.h" #include "main/feedback.h" #include "main/formats.h" +#include "main/format_unpack.h" #include "main/glformats.h" #include "main/image.h" #include "main/macros.h" @@ -71,6 +73,7 @@ #include "main/teximage.h" #include "main/texparam.h" #include "main/texstate.h" +#include "main/texstore.h" #include "main/transformfeedback.h" #include "main/uniforms.h" #include "main/varray.h" @@ -3359,3 +3362,143 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, _mesa_meta_end(ctx); } + +static bool +cleartexsubimage_using_fbo_for_zoffset(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, + GLint zoffset, + GLsizei width, GLsizei height, + const GLvoid *clearValue) +{ + GLuint fbo; + bool success = false; + GLbitfield mask; + GLenum status; + GLuint depthStencilValue[2]; + GLfloat depthValue; + + _mesa_GenFramebuffers(1, &fbo); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + + if (texImage->_BaseFormat == GL_DEPTH_STENCIL || + texImage->_BaseFormat == GL_DEPTH_COMPONENT) { + _mesa_meta_bind_fbo_image(GL_DEPTH_ATTACHMENT, texImage, zoffset); + mask = GL_DEPTH_BUFFER_BIT; + + if (clearValue) + _mesa_unpack_float_32_uint_24_8_depth_stencil_row(texImage->TexFormat, + 1, /* n */ + clearValue, + depthStencilValue); + else + memset(depthStencilValue, 0, sizeof depthStencilValue); + + memcpy(&depthValue, depthStencilValue, sizeof depthValue); + ctx->Depth.Clear = depthValue; + + if (texImage->_BaseFormat == GL_DEPTH_STENCIL) { + _mesa_meta_bind_fbo_image(GL_STENCIL_ATTACHMENT, texImage, zoffset); + mask |= GL_STENCIL_BUFFER_BIT; + ctx->Stencil.Clear = depthStencilValue[1] & 0xff; + } + _mesa_DrawBuffer(GL_NONE); + } else { + _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, texImage, zoffset); + _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); + mask = GL_COLOR_BUFFER_BIT; + + if (clearValue) + _mesa_unpack_rgba_row(texImage->TexFormat, 1, clearValue, + (GLfloat (*)[4]) ctx->Color.ClearColor.f); + else + memset(ctx->Color.ClearColor.f, 0, sizeof ctx->Color.ClearColor.f); + } + + status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + goto out; + + _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE); + _mesa_Scissor(xoffset, yoffset, width, height); + _mesa_Clear(mask); + + success = true; + + out: + _mesa_DeleteFramebuffers(1, &fbo); + return success; +} + +static bool +cleartexsubimage_using_fbo(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *clearValue) +{ + union gl_color_union saveColorValue; + bool success = false; + + if (!ctx->Extensions.ARB_framebuffer_object) + return false; + + /* This probably won't work with images that have a border */ + if (texImage->Border != 0) + return false; + + _mesa_meta_begin(ctx, + MESA_META_SCISSOR | + MESA_META_COLOR_MASK | + MESA_META_DEPTH_TEST | + MESA_META_STENCIL_TEST); + + /* _mesa_meta_begin doesn't seem to save this */ + saveColorValue = ctx->Color.ClearColor; + + while (depth-- > 0) { + if (!cleartexsubimage_using_fbo_for_zoffset(ctx, texImage, + xoffset, yoffset, zoffset++, + width, height, + clearValue)) + goto out; + } + + success = true; + + out: + ctx->Color.ClearColor = saveColorValue; + _mesa_meta_end(ctx); + return success; +} + +extern void +_mesa_meta_ClearTexSubImage(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *clearValue) +{ + bool res; + + _mesa_unlock_texture(ctx, texImage->TexObject); + + res = cleartexsubimage_using_fbo(ctx, texImage, + xoffset, yoffset, zoffset, + width, height, depth, + clearValue); + + _mesa_lock_texture(ctx, texImage->TexObject); + + if (res) + return; + + _mesa_warning(ctx, + "Falling back to mapping the texture in " + "glClearTexSubImage\n"); + + _mesa_store_ClearTexSubImage(ctx, texImage, + xoffset, yoffset, zoffset, + width, height, depth, + clearValue); +} diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h index 765f8df..456412b 100644 --- a/src/mesa/drivers/common/meta.h +++ b/src/mesa/drivers/common/meta.h @@ -473,6 +473,13 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, GLsizei width, GLsizei height); extern void +_mesa_meta_ClearTexSubImage(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *clearValue); + +extern void _mesa_meta_GetTexImage(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage); @@ -481,6 +488,13 @@ extern void _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); +extern void +_mesa_store_ClearTexSubImage(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *clearValue); + /* meta-internal functions */ GLuint _mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 633ea2c..8976535 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -239,6 +239,20 @@ struct dd_function_table { struct gl_texture_image *texImage ); /** + * Called by glClearTex[Sub]Image + * + * Clears a rectangular region of the image to a given value. The + * clearValue argument is either NULL or points to a single texel to use as + * the clear value in the same internal format as the texture image. If it + * is NULL then the texture should be cleared to zeroes. + */ + void (*ClearTexSubImage)(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *clearValue); + + /** * Called by glCopyTex[Sub]Image[123]D(). * * This function should copy a rectangular region in the rb to a single diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index c2ff7e3..bf7ef13 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -85,6 +85,7 @@ static const struct extension extension_table[] = { { "GL_ARB_blend_func_extended", o(ARB_blend_func_extended), GL, 2009 }, { "GL_ARB_buffer_storage", o(ARB_buffer_storage), GL, 2013 }, { "GL_ARB_clear_buffer_object", o(dummy_true), GL, 2012 }, + { "GL_ARB_clear_texture", o(dummy_true), GL, 2013 }, { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, { "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 }, { "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 }, diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 845ba80..43c5889 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -51,6 +51,7 @@ #include "textureview.h" #include "mtypes.h" #include "glformats.h" +#include "texstore.h" /** @@ -4544,7 +4545,6 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, "glTexStorage2DMultisample"); } - void GLAPIENTRY _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, @@ -4555,3 +4555,252 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, width, height, depth, fixedsamplelocations, GL_TRUE, "glTexStorage3DMultisample"); } + +static void +clear_tex_image(struct gl_context *ctx, + struct gl_texture_image *texImage, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const void *data) +{ + struct gl_texture_object *texObj = texImage->TexObject; + static const GLubyte zeroData[MAX_PIXEL_BYTES]; + GLubyte clearValue[MAX_PIXEL_BYTES]; + GLubyte *clearValuePtr = clearValue; + GLint dimensions; + GLenum err; + + dimensions = _mesa_get_texture_dimensions(texObj->Target); + + if (texObj->Target == GL_TEXTURE_BUFFER) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClear*TexImage(buffer texture)"); + return; + } + + if (_mesa_is_compressed_format(ctx, texImage->InternalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClear*TexImage(compressed texture)"); + return; + } + + /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the + * combinations of format and type that can be used. Formats and types + * that require additional extensions (e.g., GL_FLOAT requires + * GL_OES_texture_float) are filtered elsewhere. + */ + if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) { + err = _mesa_es_error_check_format_and_type(format, type, dimensions); + if (err != GL_NO_ERROR) { + _mesa_error(ctx, err, + "glClearTex*Image(format = %s, type = %s)", + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type)); + return; + } + } + + err = _mesa_error_check_format_and_type(ctx, format, type); + if (err != GL_NO_ERROR) { + _mesa_error(ctx, err, + "glClearTex*Image(incompatible format = %s, type = %s)", + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type)); + return; + } + + if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { + /* both source and dest must be integer-valued, or neither */ + if (_mesa_is_format_integer_color(texImage->TexFormat) != + _mesa_is_enum_format_integer(format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearTex*Image(integer/non-integer format mismatch)"); + return; + } + } + + if (!_mesa_texstore(ctx, + 1, /* dims */ + texImage->_BaseFormat, + texImage->TexFormat, + 0, /* dstRowStride */ + &clearValuePtr, + 1, 1, 1, /* srcWidth/Height/Depth */ + format, type, + data ? data : zeroData, + &ctx->DefaultPacking)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glClearTex*Image"); + return; + } + + ctx->Driver.ClearTexSubImage(ctx, + texImage, + xoffset, yoffset, zoffset, + width, height, depth, + data ? clearValue : NULL); +} + +static struct gl_texture_object * +get_tex_obj_for_clear(struct gl_context *ctx, + GLuint texture) +{ + struct gl_texture_object *texObj; + + if (texture == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glClear*TexImage(zero texture)"); + return NULL; + } + + texObj = _mesa_lookup_texture(ctx, texture); + + if (texObj == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glClear*TexImage(non-gen name)"); + return NULL; + } + + if (texObj->Target == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glClear*TexImage(unbound tex)"); + return NULL; + } + + return texObj; +} + +static int +get_tex_images_for_clear(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLint level, + struct gl_texture_image **texImages) +{ + GLenum target; + int i; + + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glClear*TexImage(invalid level)"); + return 0; + } + + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + for (i = 0; i < MAX_FACES; i++) { + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; + + texImages[i] = _mesa_select_tex_image(ctx, texObj, target, level); + if (texImages[i] == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClear*TexImage(invalid level)"); + return 0; + } + } + + return MAX_FACES; + } + + texImages[0] = _mesa_select_tex_image(ctx, texObj, texObj->Target, level); + + if (texImages[0] == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glClear*TexImage(invalid level)"); + return 0; + } + + return 1; +} + +void GLAPIENTRY +_mesa_ClearTexImage(GLuint texture, GLint level, + GLenum format, GLenum type, + const void *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_object *texObj; + struct gl_texture_image *texImages[MAX_FACES]; + int i, numImages; + + texObj = get_tex_obj_for_clear(ctx, texture); + + if (texObj == NULL) + return; + + _mesa_lock_texture(ctx, texObj); + + numImages = get_tex_images_for_clear(ctx, texObj, level, texImages); + if (numImages == 0) + goto out; + + for (i = 0; i < numImages; i++) { + clear_tex_image(ctx, texImages[i], level, + -texImages[i]->Border, /* xoffset */ + -texImages[i]->Border, /* yoffset */ + -texImages[i]->Border, /* zoffset */ + texImages[i]->Width, + texImages[i]->Height, + texImages[i]->Depth, + format, type, data); + } + + out: + _mesa_unlock_texture(ctx, texObj); +} + +void GLAPIENTRY +_mesa_ClearTexSubImage(GLuint texture, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const void *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_object *texObj; + struct gl_texture_image *texImages[MAX_FACES]; + int i, numImages; + int minDepth, maxDepth; + + texObj = get_tex_obj_for_clear(ctx, texture); + + if (texObj == NULL) + return; + + _mesa_lock_texture(ctx, texObj); + + numImages = get_tex_images_for_clear(ctx, texObj, level, texImages); + if (numImages == 0) + goto out; + + if (numImages == 1) { + minDepth = -texImages[0]->Border; + maxDepth = texImages[0]->Depth; + } else { + minDepth = 0; + maxDepth = numImages; + } + + if (xoffset < -texImages[0]->Border || + yoffset < -texImages[0]->Border || + zoffset < minDepth || + width < 0 || + height < 0 || + depth < 0 || + xoffset + width > texImages[0]->Width || + yoffset + height > texImages[0]->Height || + zoffset + depth > maxDepth) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearSubTexImage(invalid dimensions)"); + goto out; + } + + if (numImages == 1) { + clear_tex_image(ctx, texImages[0], level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, data); + } else { + for (i = zoffset; i < zoffset + depth; i++) + clear_tex_image(ctx, texImages[i], level, + xoffset, yoffset, 0, + width, height, 1, + format, type, data); + } + + out: + _mesa_unlock_texture(ctx, texObj); +} diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h index 51d94d1..68c568a 100644 --- a/src/mesa/main/teximage.h +++ b/src/mesa/main/teximage.h @@ -326,6 +326,18 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +extern void GLAPIENTRY +_mesa_ClearTexImage(GLuint texture, GLint level, + GLenum format, GLenum type, + const void *data); + +extern void GLAPIENTRY +_mesa_ClearTexSubImage(GLuint texture, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const void *data); + /*@}*/ #ifdef __cplusplus diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index 7642146..6b94b89 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -4157,6 +4157,76 @@ _mesa_store_texsubimage(struct gl_context *ctx, GLuint dims, format, type, pixels, packing, "glTexSubImage"); } +static void +clear_image_to_zero(GLubyte *dstMap, GLint dstRowStride, + GLsizei width, GLsizei height, + GLsizei clearValueSize) +{ + while (height-- > 0) { + memset(dstMap, 0, clearValueSize * width); + dstMap += dstRowStride; + } +} + +static void +clear_image_to_value(GLubyte *dstMap, GLint dstRowStride, + GLsizei width, GLsizei height, + const GLvoid *clearValue, + GLsizei clearValueSize) +{ + GLsizei x; + + while (height-- > 0) { + for (x = 0; x < width; x++) { + memcpy(dstMap, clearValue, clearValueSize); + dstMap += clearValueSize; + } + dstMap += dstRowStride - clearValueSize * width; + } +} + +/* + * Fallback for Driver.ClearTexSubImage(). + */ +void +_mesa_store_ClearTexSubImage(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *clearValue) +{ + GLubyte *dstMap; + GLint dstRowStride; + GLsizeiptr clearValueSize; + GLsizei z; + + clearValueSize = _mesa_get_format_bytes(texImage->TexFormat); + + for (z = 0; z < depth; z++) { + ctx->Driver.MapTextureImage(ctx, texImage, + z + zoffset, xoffset, yoffset, + width, height, + GL_MAP_WRITE_BIT, + &dstMap, &dstRowStride); + if (dstMap == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearTex*Image"); + return; + } + + if (clearValue) { + clear_image_to_value(dstMap, dstRowStride, + width, height, + clearValue, + clearValueSize); + } else { + clear_image_to_zero(dstMap, dstRowStride, + width, height, + clearValueSize); + } + + ctx->Driver.UnmapTextureImage(ctx, texImage, z + zoffset); + } +} /** * Fallback for Driver.CompressedTexImage() diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h index 490f9f5..91db152 100644 --- a/src/mesa/main/texstore.h +++ b/src/mesa/main/texstore.h @@ -118,6 +118,13 @@ _mesa_store_texsubimage(struct gl_context *ctx, GLuint dims, extern void +_mesa_store_ClearTexSubImage(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *clearValue); + +extern void _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage, GLsizei imageSize, const GLvoid *data); -- 1.9.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev