summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mesa/main/dd.h3
-rw-r--r--src/mesa/main/fbobject.c75
-rw-r--r--src/mesa/main/texrender.c6
3 files changed, 65 insertions, 19 deletions
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 1e7a93e939..8c7549162c 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -809,6 +809,9 @@ struct dd_function_table {
struct gl_renderbuffer_attachment *att,
struct gl_texture_object *texObj,
GLenum texTarget, GLuint level, GLuint zoffset);
+ void (*FinishRenderTexture)(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLuint face, GLuint level);
/*@}*/
#endif
#if FEATURE_EXT_framebuffer_blit
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 43e4793d55..3e425bd672 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -154,19 +154,21 @@ _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
{
if (att->Type == GL_TEXTURE) {
ASSERT(att->Texture);
- if (att->Renderbuffer) {
- /* delete/remove the 'wrapper' renderbuffer */
- /* XXX do we really want to do this??? */
- att->Renderbuffer->Delete(att->Renderbuffer);
- att->Renderbuffer = NULL;
- }
att->Texture->RefCount--;
if (att->Texture->RefCount == 0) {
ctx->Driver.DeleteTexture(ctx, att->Texture);
}
+ else {
+ /* tell driver that we're done rendering to this texture. */
+ if (ctx->Driver.FinishRenderTexture) {
+ ctx->Driver.FinishRenderTexture(ctx, att->Texture,
+ att->CubeMapFace,
+ att->TextureLevel);
+ }
+ }
att->Texture = NULL;
}
- else if (att->Type == GL_RENDERBUFFER_EXT) {
+ if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
ASSERT(att->Renderbuffer);
ASSERT(!att->Texture);
att->Renderbuffer->RefCount--;
@@ -190,9 +192,19 @@ _mesa_set_texture_attachment(GLcontext *ctx,
struct gl_texture_object *texObj,
GLenum texTarget, GLuint level, GLuint zoffset)
{
- _mesa_remove_attachment(ctx, att);
- att->Type = GL_TEXTURE;
- att->Texture = texObj;
+ if (att->Texture == texObj) {
+ /* re-attaching same texture */
+ ASSERT(att->Type == GL_TEXTURE);
+ }
+ else {
+ /* new attachment */
+ _mesa_remove_attachment(ctx, att);
+ att->Type = GL_TEXTURE;
+ att->Texture = texObj;
+ texObj->RefCount++;
+ }
+
+ /* always update these fields */
att->TextureLevel = level;
if (IS_CUBE_FACE(texTarget)) {
att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
@@ -202,13 +214,6 @@ _mesa_set_texture_attachment(GLcontext *ctx,
}
att->Zoffset = zoffset;
att->Complete = GL_FALSE;
-
- texObj->RefCount++;
-
- /* XXX when we attach to a texture, we should probably set the
- * att->Renderbuffer pointer to a "wrapper renderbuffer" which
- * makes the texture image look like renderbuffer.
- */
}
@@ -758,6 +763,8 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
assert(rb->Width == width);
assert(rb->Height == height);
assert(rb->InternalFormat);
+ assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits ||
+ rb->DepthBits || rb->StencilBits || rb->IndexBits);
rb->_BaseFormat = baseFormat;
}
else {
@@ -766,6 +773,13 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
rb->Height = 0;
rb->InternalFormat = GL_NONE;
rb->_BaseFormat = GL_NONE;
+ rb->RedBits =
+ rb->GreenBits =
+ rb->BlueBits =
+ rb->AlphaBits =
+ rb->IndexBits =
+ rb->DepthBits =
+ rb->StencilBits = 0;
}
/*
@@ -848,6 +862,28 @@ _mesa_IsFramebufferEXT(GLuint framebuffer)
}
+/**
+ * Examine all the framebuffer's attachments to see if any are textures.
+ * If so, call ctx->Driver.FinishRenderTexture() for each texture to
+ * notify the device driver that the texture image may have changed.
+ */
+static void
+check_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ if (ctx->Driver.FinishRenderTexture) {
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ struct gl_texture_object *texObj = att->Texture;
+ if (texObj) {
+ ctx->Driver.FinishRenderTexture(ctx, texObj, att->CubeMapFace,
+ att->TextureLevel);
+ }
+ }
+ }
+}
+
+
void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
{
@@ -931,6 +967,11 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
if (bindDrawBuf) {
oldFb = ctx->DrawBuffer;
if (oldFb && oldFb->Name != 0) {
+ /* check if old FB had any texture attachments */
+ if (ctx->Driver.FinishRenderTexture) {
+ check_texture_render(ctx, oldFb);
+ }
+ /* check if time to delete this framebuffer */
oldFb->RefCount--;
if (oldFb->RefCount == 0) {
oldFb->Delete(oldFb);
diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c
index 9c21e03515..a4efe64038 100644
--- a/src/mesa/main/texrender.c
+++ b/src/mesa/main/texrender.c
@@ -124,6 +124,7 @@ texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb,
static void
delete_texture_wrapper(struct gl_renderbuffer *rb)
{
+ ASSERT(rb->RefCount == 0);
_mesa_free(rb);
}
@@ -162,6 +163,7 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
trb->Zoffset = att->Zoffset;
+ trb->Base.RefCount = 1;
trb->Base.Width = trb->TexImage->Width;
trb->Base.Height = trb->TexImage->Height;
trb->Base.InternalFormat = trb->TexImage->InternalFormat; /* XXX fix? */
@@ -213,8 +215,8 @@ _mesa_renderbuffer_texture(GLcontext *ctx,
if (texObj) {
_mesa_set_texture_attachment(ctx, att, texObj,
texTarget, level, zoffset);
-
- wrap_texture(ctx, att);
+ if (!att->Renderbuffer)
+ wrap_texture(ctx, att);
}
else {
_mesa_remove_attachment(ctx, att);