diff options
Diffstat (limited to 'src/mesa/main/fbobject.c')
| -rw-r--r-- | src/mesa/main/fbobject.c | 473 | 
1 files changed, 276 insertions, 197 deletions
| diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index ed1db0feca..2d0bfb3ad7 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -34,7 +34,9 @@  #include "buffers.h"  #include "context.h" +#include "enums.h"  #include "fbobject.h" +#include "formats.h"  #include "framebuffer.h"  #include "hash.h"  #include "macros.h" @@ -44,6 +46,14 @@  #include "teximage.h"  #include "texobj.h"  #include "texstore.h" +#include "texstate.h" + + +/** Set this to 1 to help debug FBO incompleteness problems */ +#define DEBUG_FBO 0 + +/** Set this to 1 to debug/log glBlitFramebuffer() calls */ +#define DEBUG_BLIT 0  /** @@ -223,9 +233,13 @@ _mesa_set_texture_attachment(GLcontext *ctx,     if (att->Texture == texObj) {        /* re-attaching same texture */        ASSERT(att->Type == GL_TEXTURE); +      if (ctx->Driver.FinishRenderTexture) +	 ctx->Driver.FinishRenderTexture(ctx, att);     }     else {        /* new attachment */ +      if (ctx->Driver.FinishRenderTexture && att->Texture) +	 ctx->Driver.FinishRenderTexture(ctx, att);        _mesa_remove_attachment(ctx, att);        att->Type = GL_TEXTURE;        assert(!att->Texture); @@ -234,12 +248,7 @@ _mesa_set_texture_attachment(GLcontext *ctx,     /* always update these fields */     att->TextureLevel = level; -   if (IS_CUBE_FACE(texTarget)) { -      att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X; -   } -   else { -      att->CubeMapFace = 0; -   } +   att->CubeMapFace = _mesa_tex_target_to_face(texTarget);     att->Zoffset = zoffset;     att->Complete = GL_FALSE; @@ -308,8 +317,8 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,  static void  att_incomplete(const char *msg)  { -#if 0 -   _mesa_printf("attachment incomplete: %s\n", msg); +#if DEBUG_FBO +   _mesa_debug(NULL, "attachment incomplete: %s\n", msg);  #else     (void) msg;  #endif @@ -317,6 +326,23 @@ att_incomplete(const char *msg)  /** + * For debug only. + */ +static void +fbo_incomplete(const char *msg, int index) +{ +#if DEBUG_FBO +   _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index); +#else +   (void) msg; +   (void) index; +#endif +} + + + + +/**   * Test if an attachment point is complete and update its Complete field.   * \param format if GL_COLOR, this is a color attachment point,   *               if GL_DEPTH, this is a depth component attachment point, @@ -335,6 +361,7 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,     if (att->Type == GL_TEXTURE) {        const struct gl_texture_object *texObj = att->Texture;        struct gl_texture_image *texImage; +      GLenum baseFormat;        if (!texObj) {           att_incomplete("no texobj"); @@ -361,26 +388,28 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,           return;        } +      baseFormat = _mesa_get_format_base_format(texImage->TexFormat); +        if (format == GL_COLOR) { -         if (texImage->TexFormat->BaseFormat != GL_RGB && -             texImage->TexFormat->BaseFormat != GL_RGBA) { +         if (baseFormat != GL_RGB && +             baseFormat != GL_RGBA) {              att_incomplete("bad format");              att->Complete = GL_FALSE;              return;           } -         if (texImage->TexFormat->TexelBytes == 0) { +         if (_mesa_is_format_compressed(texImage->TexFormat)) {              att_incomplete("compressed internalformat");              att->Complete = GL_FALSE;              return;           }        }        else if (format == GL_DEPTH) { -         if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) { +         if (baseFormat == GL_DEPTH_COMPONENT) {              /* OK */           }           else if (ctx->Extensions.EXT_packed_depth_stencil &&                    ctx->Extensions.ARB_depth_texture && -                  texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) { +                  baseFormat == GL_DEPTH_STENCIL_EXT) {              /* OK */           }           else { @@ -391,10 +420,9 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,        }        else {           ASSERT(format == GL_STENCIL); -         ASSERT(att->Renderbuffer->StencilBits);           if (ctx->Extensions.EXT_packed_depth_stencil &&               ctx->Extensions.ARB_depth_texture && -             att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) { +             baseFormat == GL_DEPTH_STENCIL_EXT) {              /* OK */           }           else { @@ -406,6 +434,9 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,        }     }     else if (att->Type == GL_RENDERBUFFER_EXT) { +      const GLenum baseFormat = +         _mesa_get_format_base_format(att->Renderbuffer->Format); +        ASSERT(att->Renderbuffer);        if (!att->Renderbuffer->InternalFormat ||            att->Renderbuffer->Width < 1 || @@ -415,24 +446,19 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,           return;        }        if (format == GL_COLOR) { -         if (att->Renderbuffer->_BaseFormat != GL_RGB && -             att->Renderbuffer->_BaseFormat != GL_RGBA) { +         if (baseFormat != GL_RGB && +             baseFormat != GL_RGBA) {              att_incomplete("bad renderbuffer color format");              att->Complete = GL_FALSE;              return;           } -         ASSERT(att->Renderbuffer->RedBits); -         ASSERT(att->Renderbuffer->GreenBits); -         ASSERT(att->Renderbuffer->BlueBits);        }        else if (format == GL_DEPTH) { -         if (att->Renderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) { -            ASSERT(att->Renderbuffer->DepthBits); +         if (baseFormat == GL_DEPTH_COMPONENT) {              /* OK */           }           else if (ctx->Extensions.EXT_packed_depth_stencil && -                  att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) { -            ASSERT(att->Renderbuffer->DepthBits); +                  baseFormat == GL_DEPTH_STENCIL_EXT) {              /* OK */           }           else { @@ -443,13 +469,11 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,        }        else {           assert(format == GL_STENCIL); -         if (att->Renderbuffer->_BaseFormat == GL_STENCIL_INDEX) { -            ASSERT(att->Renderbuffer->StencilBits); +         if (baseFormat == GL_STENCIL_INDEX) {              /* OK */           }           else if (ctx->Extensions.EXT_packed_depth_stencil && -                  att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) { -            ASSERT(att->Renderbuffer->StencilBits); +                  baseFormat == GL_DEPTH_STENCIL_EXT) {              /* OK */           }           else { @@ -468,20 +492,6 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,  /** - * Helpful for debugging - */ -static void -fbo_incomplete(const char *msg, int index) -{ -   (void) msg; -   (void) index; -   /* -   _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index); -   */ -} - - -/**   * Test if the given framebuffer object is complete and update its   * Status field with the results.   * Calls the ctx->Driver.ValidateFramebuffer() function to allow the @@ -644,6 +654,8 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)           return;        }     } +#else +   (void) j;  #endif     if (numImages == 0) { @@ -704,18 +716,13 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)     ASSERT_OUTSIDE_BEGIN_END(ctx);     if (target != GL_RENDERBUFFER_EXT) { -         _mesa_error(ctx, GL_INVALID_ENUM, -                  "glBindRenderbufferEXT(target)"); +      _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");        return;     } -   FLUSH_CURRENT(ctx, _NEW_BUFFERS); -   /* The above doesn't fully flush the drivers in the way that a -    * glFlush does, but that is required here: +   /* No need to flush here since the render buffer binding has no +    * effect on rendering state.      */ -   if (ctx->Driver.Flush) -      ctx->Driver.Flush(ctx); -     if (renderbuffer) {        newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); @@ -969,42 +976,27 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,     }     /* These MUST get set by the AllocStorage func */ -   rb->_ActualFormat = 0; -   rb->RedBits = -   rb->GreenBits = -   rb->BlueBits = -   rb->AlphaBits = -   rb->IndexBits = -   rb->DepthBits = -   rb->StencilBits = 0; +   rb->Format = MESA_FORMAT_NONE;     rb->NumSamples = samples;     /* Now allocate the storage */     ASSERT(rb->AllocStorage);     if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {        /* No error - check/set fields now */ -      assert(rb->_ActualFormat); +      assert(rb->Format != MESA_FORMAT_NONE);        assert(rb->Width == (GLuint) width);        assert(rb->Height == (GLuint) height); -      assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits || -             rb->DepthBits || rb->StencilBits || rb->IndexBits);        rb->InternalFormat = internalFormat; -      rb->_BaseFormat = baseFormat; +      rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); +      assert(rb->_BaseFormat != 0);     }     else {        /* Probably ran out of memory - clear the fields */        rb->Width = 0;        rb->Height = 0; +      rb->Format = MESA_FORMAT_NONE;        rb->InternalFormat = GL_NONE; -      rb->_ActualFormat = GL_NONE;        rb->_BaseFormat = GL_NONE; -      rb->RedBits = -      rb->GreenBits = -      rb->BlueBits = -      rb->AlphaBits = -      rb->IndexBits = -      rb->DepthBits = -      rb->StencilBits =        rb->NumSamples = 0;     } @@ -1017,6 +1009,53 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,  } +/** + * Helper function for _mesa_GetRenderbufferParameterivEXT() and + * _mesa_GetFramebufferAttachmentParameterivEXT() + * We have to be careful to respect the base format.  For example, if a + * renderbuffer/texture was created with internalFormat=GL_RGB but the + * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE + * we need to return zero. + */ +static GLint +get_component_bits(GLenum pname, GLenum baseFormat, gl_format format) +{ +   switch (pname) { +   case GL_RENDERBUFFER_RED_SIZE_EXT: +   case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: +   case GL_RENDERBUFFER_GREEN_SIZE_EXT: +   case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: +   case GL_RENDERBUFFER_BLUE_SIZE_EXT: +   case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: +      if (baseFormat == GL_RGB || baseFormat == GL_RGBA) +         return _mesa_get_format_bits(format, pname); +      else +         return 0; +   case GL_RENDERBUFFER_ALPHA_SIZE_EXT: +   case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: +      if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA) +         return _mesa_get_format_bits(format, pname); +      else +         return 0; +   case GL_RENDERBUFFER_DEPTH_SIZE_EXT: +   case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: +      if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) +         return _mesa_get_format_bits(format, pname); +      else +         return 0; +   case GL_RENDERBUFFER_STENCIL_SIZE_EXT: +   case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: +      if (baseFormat == GL_STENCIL_INDEX || baseFormat == GL_DEPTH_STENCIL) +         return _mesa_get_format_bits(format, pname); +      else +         return 0; +   default: +      return 0; +   } +} + + +  void GLAPIENTRY  _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,                               GLsizei width, GLsizei height) @@ -1060,7 +1099,9 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)        return;     } -   FLUSH_VERTICES(ctx, _NEW_BUFFERS); +   /* No need to flush here since we're just quering state which is +    * not effected by rendering. +    */     switch (pname) {     case GL_RENDERBUFFER_WIDTH_EXT: @@ -1073,22 +1114,12 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)        *params = rb->InternalFormat;        return;     case GL_RENDERBUFFER_RED_SIZE_EXT: -      *params = rb->RedBits; -      break;     case GL_RENDERBUFFER_GREEN_SIZE_EXT: -      *params = rb->GreenBits; -      break;     case GL_RENDERBUFFER_BLUE_SIZE_EXT: -      *params = rb->BlueBits; -      break;     case GL_RENDERBUFFER_ALPHA_SIZE_EXT: -      *params = rb->AlphaBits; -      break;     case GL_RENDERBUFFER_DEPTH_SIZE_EXT: -      *params = rb->DepthBits; -      break;     case GL_RENDERBUFFER_STENCIL_SIZE_EXT: -      *params = rb->StencilBits; +      *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);        break;     case GL_RENDERBUFFER_SAMPLES:        if (ctx->Extensions.ARB_framebuffer_object) { @@ -1118,16 +1149,25 @@ _mesa_IsFramebufferEXT(GLuint framebuffer)  } +/** + * Check if any of the attachments of the given framebuffer are textures + * (render to texture).  Call ctx->Driver.RenderTexture() for such + * attachments. + */  static void  check_begin_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)  {     GLuint i;     ASSERT(ctx->Driver.RenderTexture); + +   if (fb->Name == 0) +      return; /* can't render to texture with winsys framebuffers */ +     for (i = 0; i < BUFFER_COUNT; i++) {        struct gl_renderbuffer_attachment *att = fb->Attachment + i;        struct gl_texture_object *texObj = att->Texture;        if (texObj -          && att->Texture->Image[att->CubeMapFace][att->TextureLevel]) { +          && texObj->Image[att->CubeMapFace][att->TextureLevel]) {           ctx->Driver.RenderTexture(ctx, fb, att);        }     } @@ -1142,6 +1182,9 @@ check_begin_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)  static void  check_end_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)  { +   if (fb->Name == 0) +      return; /* can't render to texture with winsys framebuffers */ +     if (ctx->Driver.FinishRenderTexture) {        GLuint i;        for (i = 0; i < BUFFER_COUNT; i++) { @@ -1157,7 +1200,8 @@ check_end_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)  void GLAPIENTRY  _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)  { -   struct gl_framebuffer *newFb, *newFbread; +   struct gl_framebuffer *newDrawFb, *newReadFb; +   struct gl_framebuffer *oldDrawFb, *oldReadFb;     GLboolean bindReadBuf, bindDrawBuf;     GET_CURRENT_CONTEXT(ctx); @@ -1204,76 +1248,90 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)        return;     } -   FLUSH_CURRENT(ctx, _NEW_BUFFERS); -   if (ctx->Driver.Flush) {   -      ctx->Driver.Flush(ctx); -   } -     if (framebuffer) {        /* Binding a user-created framebuffer object */ -      newFb = _mesa_lookup_framebuffer(ctx, framebuffer); -      if (newFb == &DummyFramebuffer) { +      newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer); +      if (newDrawFb == &DummyFramebuffer) {           /* ID was reserved, but no real framebuffer object made yet */ -         newFb = NULL; +         newDrawFb = NULL;        } -      else if (!newFb && ctx->Extensions.ARB_framebuffer_object) { +      else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) {           /* All FBO IDs must be Gen'd */           _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");           return;        } -      if (!newFb) { +      if (!newDrawFb) {  	 /* create new framebuffer object */ -	 newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); -	 if (!newFb) { +	 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); +	 if (!newDrawFb) {  	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");  	    return;  	 } -         _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb); +         _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);        } -      newFbread = newFb; +      newReadFb = newDrawFb;     }     else {        /* Binding the window system framebuffer (which was originally set         * with MakeCurrent).         */ -      newFb = ctx->WinSysDrawBuffer; -      newFbread = ctx->WinSysReadBuffer; +      newDrawFb = ctx->WinSysDrawBuffer; +      newReadFb = ctx->WinSysReadBuffer;     } -   ASSERT(newFb); -   ASSERT(newFb != &DummyFramebuffer); +   ASSERT(newDrawFb); +   ASSERT(newDrawFb != &DummyFramebuffer); + +   /* save pointers to current/old framebuffers */ +   oldDrawFb = ctx->DrawBuffer; +   oldReadFb = ctx->ReadBuffer; + +   /* check if really changing bindings */ +   if (oldDrawFb == newDrawFb) +      bindDrawBuf = GL_FALSE; +   if (oldReadFb == newReadFb) +      bindReadBuf = GL_FALSE;     /*      * OK, now bind the new Draw/Read framebuffers, if they're changing. +    * +    * We also check if we're beginning and/or ending render-to-texture. +    * When a framebuffer with texture attachments is unbound, call +    * ctx->Driver.FinishRenderTexture(). +    * When a framebuffer with texture attachments is bound, call +    * ctx->Driver.RenderTexture(). +    * +    * Note that if the ReadBuffer has texture attachments we don't consider +    * that a render-to-texture case.      */ -     if (bindReadBuf) { -      if (ctx->ReadBuffer == newFbread) -         bindReadBuf = GL_FALSE; /* no change */ -      else -         _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread); +      FLUSH_VERTICES(ctx, _NEW_BUFFERS); + +      /* check if old readbuffer was render-to-texture */ +      check_end_texture_render(ctx, oldReadFb); + +      _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);     }     if (bindDrawBuf) { -      /* check if old FB had any texture attachments */ -      if (ctx->DrawBuffer->Name != 0) { -         check_end_texture_render(ctx, ctx->DrawBuffer); -      } +      FLUSH_VERTICES(ctx, _NEW_BUFFERS); -      if (ctx->DrawBuffer == newFb) -         bindDrawBuf = GL_FALSE; /* no change */ -      else -         _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb); +      /* check if old read/draw buffers were render-to-texture */ +      if (!bindReadBuf) +         check_end_texture_render(ctx, oldReadFb); -      if (newFb->Name != 0) { -         /* check if newly bound framebuffer has any texture attachments */ -         check_begin_texture_render(ctx, newFb); -      } +      if (oldDrawFb != oldReadFb) +         check_end_texture_render(ctx, oldDrawFb); + +      /* check if newly bound framebuffer has any texture attachments */ +      check_begin_texture_render(ctx, newDrawFb); + +      _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);     }     if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) { -      ctx->Driver.BindFramebuffer(ctx, target, newFb, newFbread); +      ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);     }  } @@ -1285,12 +1343,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)     GET_CURRENT_CONTEXT(ctx);     ASSERT_OUTSIDE_BEGIN_END(ctx); -   FLUSH_CURRENT(ctx, _NEW_BUFFERS); -   /* The above doesn't fully flush the drivers in the way that a -    * glFlush does, but that is required here: -    */ -   if (ctx->Driver.Flush) -      ctx->Driver.Flush(ctx); +   FLUSH_VERTICES(ctx, _NEW_BUFFERS);     for (i = 0; i < n; i++) {        if (framebuffers[i] > 0) { @@ -1395,7 +1448,7 @@ _mesa_CheckFramebufferStatusEXT(GLenum target)        return GL_FRAMEBUFFER_COMPLETE_EXT;     } -   FLUSH_VERTICES(ctx, _NEW_BUFFERS); +   /* No need to flush here */     if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {        _mesa_test_framebuffer_completeness(ctx, buffer); @@ -1511,12 +1564,7 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target,        return;     } -   FLUSH_CURRENT(ctx, _NEW_BUFFERS); -   /* The above doesn't fully flush the drivers in the way that a -    * glFlush does, but that is required here: -    */ -   if (ctx->Driver.Flush) -      ctx->Driver.Flush(ctx); +   FLUSH_VERTICES(ctx, _NEW_BUFFERS);     _glthread_LOCK_MUTEX(fb->Mutex);     if (texObj) { @@ -1664,7 +1712,8 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,     att = _mesa_get_attachment(ctx, fb, attachment);     if (att == NULL) {        _mesa_error(ctx, GL_INVALID_ENUM, -                 "glFramebufferRenderbufferEXT(attachment)"); +                  "glFramebufferRenderbufferEXT(invalid attachment %s)", +                  _mesa_lookup_enum_by_nr(attachment));        return;     } @@ -1672,7 +1721,8 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,        rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);        if (!rb) {  	 _mesa_error(ctx, GL_INVALID_OPERATION, -		     "glFramebufferRenderbufferEXT(renderbuffer)"); +		     "glFramebufferRenderbufferEXT(non-existant" +                     " renderbuffer %u)", renderbuffer);  	 return;        }     } @@ -1683,7 +1733,9 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,     if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {        /* make sure the renderbuffer is a depth/stencil format */ -      if (rb->_BaseFormat != GL_DEPTH_STENCIL) { +      const GLenum baseFormat = +         _mesa_get_format_base_format(att->Renderbuffer->Format); +      if (baseFormat != GL_DEPTH_STENCIL) {           _mesa_error(ctx, GL_INVALID_OPERATION,                       "glFramebufferRenderbufferEXT(renderbuffer"                       " is not DEPTH_STENCIL format)"); @@ -1692,12 +1744,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,     } -   FLUSH_CURRENT(ctx, _NEW_BUFFERS); -   /* The above doesn't fully flush the drivers in the way that a -    * glFlush does, but that is required here: -    */ -   if (ctx->Driver.Flush) -      ctx->Driver.Flush(ctx); +   FLUSH_VERTICES(ctx, _NEW_BUFFERS);     assert(ctx->Driver.FramebufferRenderbuffer);     ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); @@ -1773,12 +1820,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,        }     } -   FLUSH_CURRENT(ctx, _NEW_BUFFERS); -   /* The above doesn't fully flush the drivers in the way that a -    * glFlush does, but that is required here: -    */ -   if (ctx->Driver.Flush) -      ctx->Driver.Flush(ctx); +   /* No need to flush here */     switch (pname) {     case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: @@ -1839,7 +1881,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,                       "glGetFramebufferAttachmentParameterivEXT(pname)");        }        else { -         *params = att->Renderbuffer->ColorEncoding; +         *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);        }        return;     case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: @@ -1849,61 +1891,44 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,           return;        }        else { -         *params = att->Renderbuffer->ComponentType; +         gl_format format = att->Renderbuffer->Format; +         if (format == MESA_FORMAT_CI8 || format == MESA_FORMAT_S8) { +            /* special cases */ +            *params = GL_INDEX; +         } +         else { +            *params = _mesa_get_format_datatype(format); +         }        }        return;     case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: -      if (!ctx->Extensions.ARB_framebuffer_object) { -         _mesa_error(ctx, GL_INVALID_ENUM, -                     "glGetFramebufferAttachmentParameterivEXT(pname)"); -      } -      else { -         *params = att->Renderbuffer->RedBits; -      } -      return;     case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: -      if (!ctx->Extensions.ARB_framebuffer_object) { -         _mesa_error(ctx, GL_INVALID_ENUM, -                     "glGetFramebufferAttachmentParameterivEXT(pname)"); -      } -      else { -         *params = att->Renderbuffer->GreenBits; -      } -      return;     case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: -      if (!ctx->Extensions.ARB_framebuffer_object) { -         _mesa_error(ctx, GL_INVALID_ENUM, -                     "glGetFramebufferAttachmentParameterivEXT(pname)"); -      } -      else { -         *params = att->Renderbuffer->BlueBits; -      } -      return;     case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: -      if (!ctx->Extensions.ARB_framebuffer_object) { -         _mesa_error(ctx, GL_INVALID_ENUM, -                     "glGetFramebufferAttachmentParameterivEXT(pname)"); -      } -      else { -         *params = att->Renderbuffer->AlphaBits; -      } -      return;     case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: +   case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:        if (!ctx->Extensions.ARB_framebuffer_object) {           _mesa_error(ctx, GL_INVALID_ENUM,                       "glGetFramebufferAttachmentParameterivEXT(pname)");        } -      else { -         *params = att->Renderbuffer->DepthBits; +      else if (att->Texture) { +         const struct gl_texture_image *texImage = +            _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target, +                                   att->TextureLevel); +         if (texImage) { +            *params = get_component_bits(pname, texImage->_BaseFormat, +                                         texImage->TexFormat); +         } +         else { +            *params = 0; +         }        } -      return; -   case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: -      if (!ctx->Extensions.ARB_framebuffer_object) { -         _mesa_error(ctx, GL_INVALID_ENUM, -                     "glGetFramebufferAttachmentParameterivEXT(pname)"); +      else if (att->Renderbuffer) { +         *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat, +                                      att->Renderbuffer->Format);        }        else { -         *params = att->Renderbuffer->StencilBits; +         *params = 0;        }        return;     default: @@ -1936,18 +1961,18 @@ _mesa_GenerateMipmapEXT(GLenum target)        return;     } -   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; +   texUnit = _mesa_get_current_tex_unit(ctx);     texObj = _mesa_select_tex_object(ctx, texUnit, target);     _mesa_lock_texture(ctx, texObj);     if (target == GL_TEXTURE_CUBE_MAP) { -      int face; - +      GLuint face;        for (face = 0; face < 6; face++)  	 ctx->Driver.GenerateMipmap(ctx,  				    GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,  				    texObj); -   } else { +   } +   else {        ctx->Driver.GenerateMipmap(ctx, target, texObj);     }     _mesa_unlock_texture(ctx, texObj); @@ -1955,6 +1980,20 @@ _mesa_GenerateMipmapEXT(GLenum target)  #if FEATURE_EXT_framebuffer_blit + +static const struct gl_renderbuffer_attachment * +find_attachment(const struct gl_framebuffer *fb, const struct gl_renderbuffer *rb) +{ +   GLuint i; +   for (i = 0; i < Elements(fb->Attachment); i++) { +      if (fb->Attachment[i].Renderbuffer == rb) +         return &fb->Attachment[i]; +   } +   return NULL; +} + + +  /**   * Blit rectangular region, optionally from one framebuffer to another.   * @@ -2030,7 +2069,8 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,        struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer;        if (!readRb ||            !drawRb || -          readRb->StencilBits != drawRb->StencilBits) { +          _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=  +          _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {           _mesa_error(ctx, GL_INVALID_OPERATION,                       "glBlitFramebufferEXT(stencil buffer size mismatch");           return; @@ -2042,7 +2082,8 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,        struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer;        if (!readRb ||            !drawRb || -          readRb->DepthBits != drawRb->DepthBits) { +          _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=  +          _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) {           _mesa_error(ctx, GL_INVALID_OPERATION,                       "glBlitFramebufferEXT(depth buffer size mismatch");           return; @@ -2070,7 +2111,7 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,        /* color formats must match */        if (colorReadRb &&            colorDrawRb && -          colorReadRb->_ActualFormat != colorDrawRb->_ActualFormat) { +          colorReadRb->Format != colorDrawRb->Format) {           _mesa_error(ctx, GL_INVALID_OPERATION,                  "glBlitFramebufferEXT(bad src/dst multisample pixel formats");           return; @@ -2082,6 +2123,44 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,        return;     } +   /* Debug code */ +   if (DEBUG_BLIT) { +      _mesa_printf("glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d," +                   " 0x%x, 0x%x)\n", +                   srcX0, srcY0, srcX1, srcY1, +                   dstX0, dstY0, dstX1, dstY1, +                   mask, filter); +      if (colorReadRb) { +         const struct gl_renderbuffer_attachment *att; + +         att = find_attachment(readFb, colorReadRb); +         _mesa_printf("  Src FBO %u  RB %u (%dx%d)  ", +                      readFb->Name, colorReadRb->Name, +                      colorReadRb->Width, colorReadRb->Height); +         if (att && att->Texture) { +            _mesa_printf("Tex %u  tgt 0x%x  level %u  face %u", +                         att->Texture->Name, +                         att->Texture->Target, +                         att->TextureLevel, +                         att->CubeMapFace); +         } +         _mesa_printf("\n"); + +         att = find_attachment(drawFb, colorDrawRb); +         _mesa_printf("  Dst FBO %u  RB %u (%dx%d)  ", +                      drawFb->Name, colorDrawRb->Name, +                      colorDrawRb->Width, colorDrawRb->Height); +         if (att && att->Texture) { +            _mesa_printf("Tex %u  tgt 0x%x  level %u  face %u", +                         att->Texture->Name, +                         att->Texture->Target, +                         att->TextureLevel, +                         att->CubeMapFace); +         } +         _mesa_printf("\n"); +      } +   } +     ASSERT(ctx->Driver.BlitFramebuffer);     ctx->Driver.BlitFramebuffer(ctx,                                 srcX0, srcY0, srcX1, srcY1, | 
