On Fri, Jul 04, 2014 at 05:26:44PM +0100, Neil Roberts wrote: > Here is version 3 of the glClearTexImage implementation. I figured out > I could avoid the whole issue of preserving the glClearColor state by > using glClearBuffer instead of glClear. I think the patch is a lot > neater this way.
I like it also, just a small nit below. > > I also fixed using sRGB textures and explicitly disabled dithering. > > - Neil > > ------- >8 --------------- (use git am --scissors to automatically chop here) > > Adds an implementation of the ClearTexSubImage driver entry point that tries > to set up an FBO to render to the texture and then calls glClearBuffer with a > scissor to perform the actual clear. If an FBO can't be created for the > texture then it will fall back to using _mesa_store_ClearTexSubImage. > > When used in combination with _mesa_store_ClearTexSubImage this should provide > an implementation that works for all DRI-based drivers. However as this has > only been tested with the i965 driver it is currently only enabled there. > > v2: Only enable the extension for the i965 driver instead of all DRI drivers. > Remove an unnecessary goto. Don't require GL_ARB_framebuffer_object. Add > some more comments. > > v3: Use glClearBuffer* to avoid having to modify glClearColor and friends. > Handle sRGB textures. Explicitly disable dithering. > > Reviewed-by: Topi Pohjolainen <topi.pohjolainen at intel.com> > --- > src/mesa/drivers/common/driverfuncs.c | 1 + > src/mesa/drivers/common/meta.c | 189 > +++++++++++++++++++++++++++ > src/mesa/drivers/common/meta.h | 7 + > src/mesa/drivers/dri/i965/intel_extensions.c | 1 + > 4 files changed, 198 insertions(+) > > 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 10dd418..a47b7b9 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" > @@ -3347,3 +3350,189 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, > GLfloat y, GLfloat z, > > _mesa_meta_end(ctx); > } > + > +static bool > +cleartexsubimage_color(struct gl_context *ctx, > + struct gl_texture_image *texImage, > + const GLvoid *clearValue, > + GLint zoffset) > +{ > + mesa_format format; > + union gl_color_union colorValue; > + GLenum datatype; > + GLenum status; > + > + _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, texImage, zoffset); > + > + status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); > + if (status != GL_FRAMEBUFFER_COMPLETE) > + return false; > + > + /* We don't want to apply an sRGB conversion so override the format */ > + format = _mesa_get_srgb_format_linear(texImage->TexFormat); > + datatype = _mesa_get_format_datatype(format); > + > + switch (datatype) { > + case GL_UNSIGNED_INT: > + case GL_INT: > + if (clearValue) > + _mesa_unpack_uint_rgba_row(format, 1, clearValue, > + (GLuint (*)[4]) colorValue.ui); > + else > + memset(&colorValue, 0, sizeof colorValue); > + if (datatype == GL_INT) > + glClearBufferiv(GL_COLOR, 0, colorValue.i); > + else > + glClearBufferuiv(GL_COLOR, 0, colorValue.ui); > + break; > + default: > + if (clearValue) > + _mesa_unpack_rgba_row(format, 1, clearValue, > + (GLfloat (*)[4]) colorValue.f); > + else > + memset(&colorValue, 0, sizeof colorValue); > + glClearBufferfv(GL_COLOR, 0, colorValue.f); Here in this function you use glClearBuffer*() and later on in cleartexsubimage_depth_stencil() you use _mesa_ClearBuffer*() - I would switch to the latter here also. > + break; > + } > + > + return true; > +} > + > +static bool > +cleartexsubimage_depth_stencil(struct gl_context *ctx, > + struct gl_texture_image *texImage, > + const GLvoid *clearValue, > + GLint zoffset) > +{ > + GLint stencilValue; > + GLfloat depthValue; > + GLenum status; > + > + _mesa_meta_bind_fbo_image(GL_DEPTH_ATTACHMENT, texImage, zoffset); > + > + if (texImage->_BaseFormat == GL_DEPTH_STENCIL) > + _mesa_meta_bind_fbo_image(GL_STENCIL_ATTACHMENT, texImage, zoffset); > + > + status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); > + if (status != GL_FRAMEBUFFER_COMPLETE) > + return false; > + > + if (clearValue) { > + GLuint depthStencilValue[2]; > + > + /* Convert the clearValue from whatever format it's in to a floating > + * point value for the depth and an integer value for the stencil index > + */ > + _mesa_unpack_float_32_uint_24_8_depth_stencil_row(texImage->TexFormat, > + 1, /* n */ > + clearValue, > + depthStencilValue); > + /* We need a memcpy here instead of a cast because we need to > + * reinterpret the bytes as a float rather than converting it > + */ > + memcpy(&depthValue, depthStencilValue, sizeof depthValue); > + stencilValue = depthStencilValue[1] & 0xff; > + } else { > + depthValue = 0.0f; > + stencilValue = 0; > + } > + > + if (texImage->_BaseFormat == GL_DEPTH_STENCIL) > + _mesa_ClearBufferfi(GL_DEPTH_STENCIL, 0, depthValue, stencilValue); > + else > + _mesa_ClearBufferfv(GL_DEPTH, 0, &depthValue); > + > + return true; > +} > + > +static bool > +cleartexsubimage_for_zoffset(struct gl_context *ctx, > + struct gl_texture_image *texImage, > + GLint zoffset, > + const GLvoid *clearValue) > +{ > + GLuint fbo; > + bool success; > + > + _mesa_GenFramebuffers(1, &fbo); > + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); > + > + switch(texImage->_BaseFormat) { > + case GL_DEPTH_STENCIL: > + case GL_DEPTH_COMPONENT: > + success = cleartexsubimage_depth_stencil(ctx, texImage, > + clearValue, zoffset); > + break; > + default: > + success = cleartexsubimage_color(ctx, texImage, clearValue, zoffset); > + break; > + } > + > + _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) > +{ > + bool success = true; > + GLint z; > + > + _mesa_meta_begin(ctx, > + MESA_META_SCISSOR | > + MESA_META_COLOR_MASK | > + MESA_META_DITHER | > + MESA_META_FRAMEBUFFER_SRGB); > + > + _mesa_set_enable(ctx, GL_DITHER, GL_FALSE); > + > + _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE); > + _mesa_Scissor(xoffset, yoffset, width, height); > + > + for (z = zoffset; z < zoffset + depth; z++) { > + if (!cleartexsubimage_for_zoffset(ctx, texImage, z, clearValue)) { > + success = false; > + break; > + } > + } > + > + _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 b8d992c..b269dce 100644 > --- a/src/mesa/drivers/common/meta.h > +++ b/src/mesa/drivers/common/meta.h > @@ -477,6 +477,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); > diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c > b/src/mesa/drivers/dri/i965/intel_extensions.c > index fe40068..4ee8636 100644 > --- a/src/mesa/drivers/dri/i965/intel_extensions.c > +++ b/src/mesa/drivers/dri/i965/intel_extensions.c > @@ -163,6 +163,7 @@ intelInitExtensions(struct gl_context *ctx) > assert(brw->gen >= 4); > > ctx->Extensions.ARB_buffer_storage = true; > + ctx->Extensions.ARB_clear_texture = true; > ctx->Extensions.ARB_depth_buffer_float = true; > ctx->Extensions.ARB_depth_clamp = true; > ctx->Extensions.ARB_depth_texture = true; > -- > 1.9.3 > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev