summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Roberts <[email protected]>2014-07-31 14:07:50 +0100
committerNeil Roberts <[email protected]>2014-08-12 18:23:50 +0100
commita018a3f3f5542534fd3b274673ef2c2e9c2c2c05 (patch)
tree498a56114768f834358a1ebab5d71770c25d89cf
parent817051ab5b71b2c00e20f1b92ccf69c71e7ab70e (diff)
mesa/meta: Support decompressing floating-point formats
Previously the Meta implementation of glGetTexImage would fall back to _mesa_get_teximage if the texturing is not using an unsigned normalised format. However in order to support the half-float formats of BPTC textures we can make it render to a floating-point renderbuffer instead. This patch makes decompression_state have two FBOs, one for the GL_RGBA format and one for GL_RGBA32F. If a floating-point texture is encountered it will try setting up a floating-point FBO. It will now also check the status of the FBO and fall back to _mesa_get_teximage if the FBO is not complete. Reviewed-by: Ian Romanick <[email protected]>
-rw-r--r--src/mesa/drivers/common/meta.c97
-rw-r--r--src/mesa/drivers/common/meta.h14
2 files changed, 78 insertions, 33 deletions
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index a1d06d4123b..439c7e2f685 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -2943,14 +2943,22 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
free(buf);
}
+static void
+meta_decompress_fbo_cleanup(struct decompress_fbo_state *decompress_fbo)
+{
+ if (decompress_fbo->FBO != 0) {
+ _mesa_DeleteFramebuffers(1, &decompress_fbo->FBO);
+ _mesa_DeleteRenderbuffers(1, &decompress_fbo->RBO);
+ }
+
+ memset(decompress_fbo, 0, sizeof(*decompress_fbo));
+}
static void
meta_decompress_cleanup(struct decompress_state *decompress)
{
- if (decompress->FBO != 0) {
- _mesa_DeleteFramebuffers(1, &decompress->FBO);
- _mesa_DeleteRenderbuffers(1, &decompress->RBO);
- }
+ meta_decompress_fbo_cleanup(&decompress->byteFBO);
+ meta_decompress_fbo_cleanup(&decompress->floatFBO);
if (decompress->VAO != 0) {
_mesa_DeleteVertexArrays(1, &decompress->VAO);
@@ -2972,7 +2980,7 @@ meta_decompress_cleanup(struct decompress_state *decompress)
* \param dest destination buffer
* \param destRowLength dest image rowLength (ala GL_PACK_ROW_LENGTH)
*/
-static void
+static bool
decompress_texture_image(struct gl_context *ctx,
struct gl_texture_image *texImage,
GLuint slice,
@@ -2980,17 +2988,33 @@ decompress_texture_image(struct gl_context *ctx,
GLvoid *dest)
{
struct decompress_state *decompress = &ctx->Meta->Decompress;
+ struct decompress_fbo_state *decompress_fbo;
struct gl_texture_object *texObj = texImage->TexObject;
const GLint width = texImage->Width;
const GLint height = texImage->Height;
const GLint depth = texImage->Height;
const GLenum target = texObj->Target;
+ GLenum rbFormat;
GLenum faceTarget;
struct vertex verts[4];
GLuint samplerSave;
+ GLenum status;
const bool use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
ctx->Extensions.ARB_fragment_shader;
+ switch (_mesa_get_format_datatype(texImage->TexFormat)) {
+ case GL_FLOAT:
+ decompress_fbo = &decompress->floatFBO;
+ rbFormat = GL_RGBA32F;
+ break;
+ case GL_UNSIGNED_NORMALIZED:
+ decompress_fbo = &decompress->byteFBO;
+ rbFormat = GL_RGBA;
+ break;
+ default:
+ return false;
+ }
+
if (slice > 0) {
assert(target == GL_TEXTURE_3D ||
target == GL_TEXTURE_2D_ARRAY ||
@@ -3001,11 +3025,11 @@ decompress_texture_image(struct gl_context *ctx,
case GL_TEXTURE_1D:
case GL_TEXTURE_1D_ARRAY:
assert(!"No compressed 1D textures.");
- return;
+ return false;
case GL_TEXTURE_3D:
assert(!"No compressed 3D textures.");
- return;
+ return false;
case GL_TEXTURE_CUBE_MAP_ARRAY:
faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (slice % 6);
@@ -3027,27 +3051,35 @@ decompress_texture_image(struct gl_context *ctx,
ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
/* Create/bind FBO/renderbuffer */
- if (decompress->FBO == 0) {
- _mesa_GenFramebuffers(1, &decompress->FBO);
- _mesa_GenRenderbuffers(1, &decompress->RBO);
- _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress->FBO);
- _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress->RBO);
+ if (decompress_fbo->FBO == 0) {
+ _mesa_GenFramebuffers(1, &decompress_fbo->FBO);
+ _mesa_GenRenderbuffers(1, &decompress_fbo->RBO);
+ _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress_fbo->FBO);
+ _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress_fbo->RBO);
_mesa_FramebufferRenderbuffer(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT,
- decompress->RBO);
+ decompress_fbo->RBO);
}
else {
- _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress->FBO);
+ _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress_fbo->FBO);
}
/* alloc dest surface */
- if (width > decompress->Width || height > decompress->Height) {
- _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress->RBO);
- _mesa_RenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA,
- width, height);
- decompress->Width = width;
- decompress->Height = height;
+ if (width > decompress_fbo->Width || height > decompress_fbo->Height) {
+ _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress_fbo->RBO);
+ _mesa_RenderbufferStorage(GL_RENDERBUFFER_EXT, rbFormat,
+ width, height);
+ status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ /* If the framebuffer isn't complete then we'll leave
+ * decompress_fbo->Width as zero so that it will fail again next time
+ * too */
+ _mesa_meta_end(ctx);
+ return false;
+ }
+ decompress_fbo->Width = width;
+ decompress_fbo->Height = height;
}
if (use_glsl_version) {
@@ -3169,6 +3201,8 @@ decompress_texture_image(struct gl_context *ctx,
_mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);
_mesa_meta_end(ctx);
+
+ return true;
}
@@ -3182,15 +3216,11 @@ _mesa_meta_GetTexImage(struct gl_context *ctx,
GLenum format, GLenum type, GLvoid *pixels,
struct gl_texture_image *texImage)
{
- /* We can only use the decompress-with-blit method here if the texels are
- * unsigned, normalized values. We could handle signed and unnormalized
- * with floating point renderbuffers...
- */
- if (_mesa_is_format_compressed(texImage->TexFormat) &&
- _mesa_get_format_datatype(texImage->TexFormat)
- == GL_UNSIGNED_NORMALIZED) {
+ if (_mesa_is_format_compressed(texImage->TexFormat)) {
struct gl_texture_object *texObj = texImage->TexObject;
GLuint slice;
+ bool result;
+
/* Need to unlock the texture here to prevent deadlock... */
_mesa_unlock_texture(ctx, texObj);
for (slice = 0; slice < texImage->Depth; slice++) {
@@ -3212,14 +3242,19 @@ _mesa_meta_GetTexImage(struct gl_context *ctx,
else {
dst = pixels;
}
- decompress_texture_image(ctx, texImage, slice, format, type, dst);
+ result = decompress_texture_image(ctx, texImage, slice,
+ format, type, dst);
+ if (!result)
+ break;
}
/* ... and relock it */
_mesa_lock_texture(ctx, texObj);
+
+ if (result)
+ return;
}
- else {
- _mesa_get_teximage(ctx, format, type, pixels, texImage);
- }
+
+ _mesa_get_teximage(ctx, format, type, pixels, texImage);
}
diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
index e2da2f4278c..3ec73982258 100644
--- a/src/mesa/drivers/common/meta.h
+++ b/src/mesa/drivers/common/meta.h
@@ -343,13 +343,23 @@ struct gen_mipmap_state
};
/**
+ * One of the FBO states for decompress_state. There will be one for each
+ * required renderbuffer format.
+ */
+struct decompress_fbo_state
+{
+ GLuint FBO, RBO;
+ GLint Width, Height;
+};
+
+/**
* State for texture decompression
*/
struct decompress_state
{
GLuint VAO;
- GLuint VBO, FBO, RBO, Sampler;
- GLint Width, Height;
+ struct decompress_fbo_state byteFBO, floatFBO;
+ GLuint VBO, Sampler;
struct blit_shader_table shaders;
};