Fix pow <small> and a very stypid bug with dummy srcs(0 equals to tmp0.x)</small...
[mesa.git] / src / mesa / main / fbobject.c
index dc32caae1589fa1e1219efc73ddf15872f4bedea..3e425bd6724ec122357c439759dbf67c23fcee26 100644 (file)
@@ -38,7 +38,6 @@
 #include "texstore.h"
 
 
-
 /* XXX temporarily here */
 #define GL_READ_FRAMEBUFFER_EXT                0x90
 #define GL_DRAW_FRAMEBUFFER_EXT                0x9a
@@ -108,8 +107,9 @@ lookup_framebuffer(GLcontext *ctx, GLuint id)
  * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
  * gl_renderbuffer_attachment object.
  */
-static struct gl_renderbuffer_attachment *
-get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment)
+struct gl_renderbuffer_attachment *
+_mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
+                     GLenum attachment)
 {
    GLuint i;
 
@@ -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.
-    */
 }
 
 
@@ -232,15 +237,17 @@ _mesa_set_renderbuffer_attachment(GLcontext *ctx,
 
 /**
  * Fallback for ctx->Driver.FramebufferRenderbuffer()
- * Sets a framebuffer attachment to a particular renderbuffer.
- * The framebuffer in question is ctx->DrawBuffer.
- * \sa _mesa_renderbuffer_texture
+ * Attach a renderbuffer object to a framebuffer object.
  */
 void
-_mesa_framebuffer_renderbuffer(GLcontext *ctx,
-                               struct gl_renderbuffer_attachment *att,
-                               struct gl_renderbuffer *rb)
+_mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+                               GLenum attachment, struct gl_renderbuffer *rb)
 {
+   struct gl_renderbuffer_attachment *att;
+
+   att = _mesa_get_attachment(ctx, fb, attachment);
+   ASSERT(att);
+
    if (rb) {
       _mesa_set_renderbuffer_attachment(ctx, att, rb);
    }
@@ -461,7 +468,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
       if (fb->ColorDrawBuffer[i] != GL_NONE) {
          const struct gl_renderbuffer_attachment *att
-            = get_attachment(ctx, fb, fb->ColorDrawBuffer[i]);
+            = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[i]);
          assert(att);
          if (att->Type == GL_NONE) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
@@ -473,7 +480,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
    /* Check that the ReadBuffer is present */
    if (fb->ColorReadBuffer != GL_NONE) {
       const struct gl_renderbuffer_attachment *att
-         = get_attachment(ctx, fb, fb->ColorReadBuffer);
+         = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
       assert(att);
       if (att->Type == GL_NONE) {
          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
@@ -742,6 +749,13 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
 
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
 
+   if (rb->InternalFormat == internalFormat &&
+       rb->Width == width &&
+       rb->Height == height) {
+      /* no change in allocation needed */
+      return;
+   }
+
    /* Now allocate the storage */
    ASSERT(rb->AllocStorage);
    if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
@@ -749,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 {
@@ -757,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;
    }
 
    /*
@@ -800,60 +823,23 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
       *params = ctx->CurrentRenderbuffer->InternalFormat;
       return;
    case GL_RENDERBUFFER_RED_SIZE_EXT:
-      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
-          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
-         *params = ctx->CurrentRenderbuffer->RedBits;
-      }
-      else {
-         *params = 0;
-      }
+      *params = ctx->CurrentRenderbuffer->RedBits;
       break;
    case GL_RENDERBUFFER_GREEN_SIZE_EXT:
-      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
-          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
-         *params = ctx->CurrentRenderbuffer->GreenBits;
-      }
-      else {
-         *params = 0;
-      }
+      *params = ctx->CurrentRenderbuffer->GreenBits;
       break;
    case GL_RENDERBUFFER_BLUE_SIZE_EXT:
-      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
-          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
-         *params = ctx->CurrentRenderbuffer->BlueBits;
-      }
-      else {
-         *params = 0;
-      }
+      *params = ctx->CurrentRenderbuffer->BlueBits;
       break;
    case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
-      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
-          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
-         *params = ctx->CurrentRenderbuffer->AlphaBits;
-      }
-      else {
-         *params = 0;
-      }
+      *params = ctx->CurrentRenderbuffer->AlphaBits;
       break;
    case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
-      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_COMPONENT ||
-          ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
-         *params = ctx->CurrentRenderbuffer->DepthBits;
-      }
-      else {
-         *params = 0;
-      }
+      *params = ctx->CurrentRenderbuffer->DepthBits;
       break;
    case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
-      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_STENCIL_INDEX ||
-          ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
-         *params = ctx->CurrentRenderbuffer->StencilBits;
-      }
-      else {
-         *params = 0;
-      }
+      *params = ctx->CurrentRenderbuffer->StencilBits;
       break;
-
    default:
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glGetRenderbufferParameterivEXT(target)");
@@ -876,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)
 {
@@ -959,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);
@@ -1151,7 +1164,7 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
    ASSERT(textarget == GL_TEXTURE_1D);
 
    /* XXX read blit */
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferTexture1DEXT(attachment)");
@@ -1200,7 +1213,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
          textarget == GL_TEXTURE_RECTANGLE_ARB ||
          IS_CUBE_FACE(textarget));
 
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferTexture2DEXT(attachment)");
@@ -1252,7 +1265,7 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
 
    ASSERT(textarget == GL_TEXTURE_3D);
 
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferTexture1DEXT(attachment)");
@@ -1342,7 +1355,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
       return;
    }
 
-   att = get_attachment(ctx, fb, attachment);
+   att = _mesa_get_attachment(ctx, fb, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferRenderbufferEXT(attachment)");
@@ -1365,7 +1378,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
 
    assert(ctx->Driver.FramebufferRenderbuffer);
-   ctx->Driver.FramebufferRenderbuffer(ctx, att, rb);
+   ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
 }
 
 
@@ -1413,7 +1426,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
       return;
    }
 
-   att = get_attachment(ctx, buffer, attachment);
+   att = _mesa_get_attachment(ctx, buffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glGetFramebufferAttachmentParameterivEXT(attachment)");