-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 08/15/2011 11:53 AM, Eric Anholt wrote: > From: Brian Paul <bri...@vmware.com> > > Decompress a texture by drawing quad with the texture. > --- > src/mesa/drivers/common/meta.c | 200 > ++++++++++++++++++++++++++++++++++++++++ > src/mesa/drivers/common/meta.h | 6 + > 2 files changed, 206 insertions(+), 0 deletions(-) > > diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c > index 19eae42..751f3b6 100644 > --- a/src/mesa/drivers/common/meta.c > +++ b/src/mesa/drivers/common/meta.c > @@ -287,6 +287,19 @@ struct gen_mipmap_state > GLuint FBO; > }; > > + > +/** > + * State for texture decompression > + */ > +struct decompress_state > +{ > + GLuint ArrayObj; > + GLuint VBO, FBO, RBO; > + GLint Width, Height; > + GLenum RBFormat; > +}; > + > + > #define MAX_META_OPS_DEPTH 2 > /** > * All per-context meta state. > @@ -306,6 +319,7 @@ struct gl_meta_state > struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */ > struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */ > struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */ > + struct decompress_state Decompress; /**< For texture decompression */ > }; > > > @@ -3094,3 +3108,189 @@ _mesa_meta_CopyColorSubTable(struct gl_context > *ctx,GLenum target, GLsizei start > > free(buf); > } > + > + > +/** > + * Decompress a texture image by drawing a quad with the compressed > + * texture and reading the pixels out of the color buffer. > + * \param slice which slice of a 3D texture or layer of a 1D/2D texture > + * \param destFormat format, ala glReadPixels > + * \param destType type, ala glReadPixels > + * \param dest destination buffer > + * \param destRowLength dest image rowLength (ala GL_PACK_ROW_LENGTH) > + */ > +void > +_mesa_meta_decompress_texture_image(struct gl_context *ctx, > + struct gl_texture_image *texImage, > + GLuint slice, > + GLenum destFormat, GLenum destType, > + GLvoid *dest, GLint destRowLength) > +{ > + struct decompress_state *decompress = &ctx->Meta->Decompress; > + struct gl_texture_object *texObj = texImage->TexObject; > + const GLint width = texImage->Width; > + const GLint height = texImage->Height; > + const GLenum target = texObj->Target; > + GLenum faceTarget, rbFormat; > + struct vertex { > + GLfloat x, y, tex[3]; > + }; > + struct vertex verts[4]; > + GLuint fboDrawSave, fboReadSave; > + GLenum destDataType = _mesa_get_format_datatype(texImage->TexFormat); > + > + if (slice > 0) { > + assert(target == GL_TEXTURE_3D || > + target == GL_TEXTURE_2D_ARRAY); > + } > + > + if (target == GL_TEXTURE_CUBE_MAP) { > + faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; > + } > + else { > + faceTarget = target; > + } > + > + /* save fbo bindings (not saved by _mesa_meta_begin()) */ > + fboDrawSave = ctx->DrawBuffer->Name; > + fboReadSave = ctx->ReadBuffer->Name; > + > + _mesa_meta_begin(ctx, META_ALL); > + > + /* Create/bind FBO/renderbuffer */ > + if (decompress->FBO == 0) { > + _mesa_GenFramebuffersEXT(1, &decompress->FBO); > + _mesa_GenRenderbuffersEXT(1, &decompress->RBO); > + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO); > + _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO); > + _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, > + GL_COLOR_ATTACHMENT0_EXT, > + GL_RENDERBUFFER_EXT, > + decompress->RBO); > + } > + else { > + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO); > + } > + > + if (destDataType == GL_SIGNED_NORMALIZED) { > + rbFormat = GL_RGBA32F; > + } else { > + rbFormat = GL_RGBA; > + }
This bit seems odd. Is GL_RGBA32F the right choice? Won't this fail on hardware that can do SIGNED_NORMALIZED but not float rendering? > + > + /* alloc dest surface */ > + if (width != decompress->Width || height != decompress->Height || > + decompress->RBFormat != rbFormat) { > + _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, rbFormat, > + width, height); > + decompress->Width = width; > + decompress->Height = height; > + decompress->RBFormat = rbFormat; > + } > + > + /* setup VBO data */ > + if (decompress->ArrayObj == 0) { > + /* create vertex array object */ > + _mesa_GenVertexArrays(1, &decompress->ArrayObj); > + _mesa_BindVertexArray(decompress->ArrayObj); > + > + /* create vertex array buffer */ > + _mesa_GenBuffersARB(1, &decompress->VBO); > + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO); > + > + /* setup vertex arrays */ > + _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); > + _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); > + _mesa_EnableClientState(GL_VERTEX_ARRAY); > + _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); > + } > + else { > + _mesa_BindVertexArray(decompress->ArrayObj); > + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO); > + } > + > + setup_texture_coords(faceTarget, slice, width, height, > + verts[0].tex, > + verts[1].tex, > + verts[2].tex, > + verts[3].tex); > + > + /* setup vertex positions */ > + verts[0].x = 0.0F; > + verts[0].y = 0.0F; > + verts[1].x = width; > + verts[1].y = 0.0F; > + verts[2].x = width; > + verts[2].y = height; > + verts[3].x = 0.0F; > + verts[3].y = height; > + > + /* upload new vertex data */ > + _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, > + GL_DYNAMIC_DRAW_ARB); > + > + /* setup texture state */ > + _mesa_BindTexture(target, texObj->Name); > + _mesa_Enable(target); > + > + { > + /* save texture object state */ > + const GLenum minFilterSave = texObj->Sampler.MinFilter; > + const GLenum magFilterSave = texObj->Sampler.MagFilter; > + const GLint baseLevelSave = texObj->BaseLevel; > + const GLint maxLevelSave = texObj->MaxLevel; > + const GLenum wrapSSave = texObj->Sampler.WrapS; > + const GLenum wrapTSave = texObj->Sampler.WrapT; > + const GLenum srgbSave = texObj->Sampler.sRGBDecode; > + > + /* restrict sampling to the texture level of interest */ > + _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, texImage->Level); > + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, texImage->Level); > + /* nearest filtering */ > + _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); > + _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); > + > + /* No sRGB decode or encode.*/ > + if (ctx->Extensions.EXT_texture_sRGB_decode) { > + _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT, > + GL_SKIP_DECODE_EXT); > + } > + if (ctx->Extensions.EXT_framebuffer_sRGB) { > + _mesa_Disable(GL_FRAMEBUFFER_SRGB_EXT); > + } > + > + /* render quad w/ texture into renderbuffer */ > + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); > + > + /* Restore texture object state, the texture binding will > + * be restored by _mesa_meta_end(). > + */ > + _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave); > + _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave); > + if (target != GL_TEXTURE_RECTANGLE_ARB) { > + _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); > + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); > + } > + _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave); > + _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave); > + if (ctx->Extensions.EXT_texture_sRGB_decode) { > + _mesa_TexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT, srgbSave); > + } > + } > + > + /* read pixels from renderbuffer */ > + ctx->Pack.RowLength = destRowLength; > + _mesa_ReadPixels(0, 0, width, height, destFormat, destType, dest); > + > + _mesa_meta_end(ctx); > + > + /* restore fbo bindings */ > + if (fboDrawSave == fboReadSave) { > + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboDrawSave); > + } > + else { > + _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboDrawSave); > + _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fboReadSave); > + } > +} > + > diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h > index 95b4b55..50389c9 100644 > --- a/src/mesa/drivers/common/meta.h > +++ b/src/mesa/drivers/common/meta.h > @@ -107,5 +107,11 @@ _mesa_meta_CopyConvolutionFilter2D(struct gl_context > *ctx, GLenum target, > GLenum internalFormat, GLint x, GLint y, > GLsizei width, GLsizei height); > > +void > +_mesa_meta_decompress_texture_image(struct gl_context *ctx, > + struct gl_texture_image *texImage, > + GLuint slice, > + GLenum destFormat, GLenum destType, > + GLvoid *dest, GLint destRowLength); > > #endif /* META_H */ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iEYEARECAAYFAk5JkwkACgkQX1gOwKyEAw/dmwCfYOivz5pJ81hNzdO1xp1LuAlH 2hEAn3RoDYcDvWQvn761mbZI6rKmFjl8 =ylMP -----END PGP SIGNATURE----- _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev