some initial work on upcoming GL_EXT_framebuffer_blit extension
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 8 Nov 2005 14:45:48 +0000 (14:45 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 8 Nov 2005 14:45:48 +0000 (14:45 +0000)
src/mesa/main/config.h
src/mesa/main/dd.h
src/mesa/main/extensions.c
src/mesa/main/fbobject.c
src/mesa/main/fbobject.h
src/mesa/main/mtypes.h

index ff764886bd72a6b40153af6a24cd1bfcb0431a55..a10542de22ed013ba089d85c6a539cf27cd5abb1 100644 (file)
 #define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects
 #define FEATURE_ATI_fragment_shader _HAVE_FULL_GL
 #define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL
+#define FEATURE_EXT_framebuffer_blit _HAVE_FULL_GL
 /*@}*/
 
 
index 5f680116e561b68a46de3ad528982749069ee5ae..d07a7a26b1e7ae0736b9cb8654da6f6c7a8f661f 100644 (file)
@@ -807,6 +807,12 @@ struct dd_function_table {
                                GLenum texTarget, GLuint level, GLuint zoffset);
    /*@}*/
 #endif
+#if FEATURE_EXT_framebuffer_blit
+   void (*BlitFramebuffer)(GLcontext *ctx,
+                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                           GLbitfield mask, GLenum filter);
+#endif
 
    /**
     * \name Query objects
index cd97b0ccb2411b86f4cc0896e0268957355925f1..816fca9957ea08d49c058526bb97e6e2a037b059 100644 (file)
@@ -92,6 +92,7 @@ static const struct {
    { OFF, "GL_EXT_depth_bounds_test",          F(EXT_depth_bounds_test) },
    { ON,  "GL_EXT_draw_range_elements",        F(EXT_draw_range_elements) },
    { OFF, "GL_EXT_framebuffer_object",         F(EXT_framebuffer_object) },
+   { OFF, "GL_EXT_framebuffer_blit",           F(EXT_framebuffer_blit) },
    { OFF, "GL_EXT_fog_coord",                  F(EXT_fog_coord) },
    { OFF, "GL_EXT_histogram",                  F(EXT_histogram) },
    { OFF, "GL_EXT_multi_draw_arrays",          F(EXT_multi_draw_arrays) },
@@ -230,6 +231,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
    ctx->Extensions.EXT_fog_coord = GL_TRUE;
 #if FEATURE_EXT_framebuffer_object
    ctx->Extensions.EXT_framebuffer_object = GL_TRUE;
+   ctx->Extensions.EXT_framebuffer_blit = GL_TRUE;
 #endif
    ctx->Extensions.EXT_histogram = GL_TRUE;
    ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;
index f5ae4518beb821addbd59d1c49e7748393437849..dc32caae1589fa1e1219efc73ddf15872f4bedea 100644 (file)
 #include "texstore.h"
 
 
+
+/* XXX temporarily here */
+#define GL_READ_FRAMEBUFFER_EXT                0x90
+#define GL_DRAW_FRAMEBUFFER_EXT                0x9a
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT        GL_FRAMEBUFFER_BINDING_EXT
+#define GL_READ_FRAMEBUFFER_BINDING_EXT        0x9b
+
+
 /**
  * Notes:
  *
@@ -871,12 +879,36 @@ _mesa_IsFramebufferEXT(GLuint framebuffer)
 void GLAPIENTRY
 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
 {
-   struct gl_framebuffer *newFb, *newReadFb, *oldFb;
+   struct gl_framebuffer *newFb, *oldFb;
+   GLboolean bindReadBuf, bindDrawBuf;
    GET_CURRENT_CONTEXT(ctx);
 
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (target != GL_FRAMEBUFFER_EXT) {
+   switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+   case GL_DRAW_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+         return;
+      }
+      bindDrawBuf = GL_TRUE;
+      bindReadBuf = GL_FALSE;
+      break;
+   case GL_READ_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+         return;
+      }
+      bindDrawBuf = GL_FALSE;
+      bindReadBuf = GL_TRUE;
+      break;
+#endif
+   case GL_FRAMEBUFFER_EXT:
+      bindDrawBuf = GL_TRUE;
+      bindReadBuf = GL_TRUE;
+      break;
+   default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
       return;
    }
@@ -899,30 +931,41 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
         }
          _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
       }
-      newFb->RefCount++;
-      newReadFb = newFb;
+      if (bindReadBuf)
+         newFb->RefCount++;
+      if (bindDrawBuf)
+         newFb->RefCount++;
    }
    else {
       /* Binding the window system framebuffer (which was originally set
        * with MakeCurrent).
        */
       newFb = ctx->WinSysDrawBuffer;
-      newReadFb = ctx->WinSysReadBuffer;
    }
 
-   oldFb = ctx->DrawBuffer;
-   if (oldFb && oldFb->Name != 0) {
-      oldFb->RefCount--;
-      if (oldFb->RefCount == 0) {
-         oldFb->Delete(oldFb);
+   ASSERT(newFb != &DummyFramebuffer);
+
+   if (bindReadBuf) {
+      oldFb = ctx->ReadBuffer;
+      if (oldFb && oldFb->Name != 0) {
+         oldFb->RefCount--;
+         if (oldFb->RefCount == 0) {
+            oldFb->Delete(oldFb);
+         }
       }
+      ctx->ReadBuffer = newFb;
    }
 
-   ASSERT(newFb != &DummyFramebuffer);
-
-   /* Note, we set both the GL_DRAW_BUFFER and GL_READ_BUFFER state: */
-   ctx->DrawBuffer = newFb;
-   ctx->ReadBuffer = newReadFb;
+   if (bindDrawBuf) {
+      oldFb = ctx->DrawBuffer;
+      if (oldFb && oldFb->Name != 0) {
+         oldFb->RefCount--;
+         if (oldFb->RefCount == 0) {
+            oldFb->Delete(oldFb);
+         }
+      }
+      ctx->DrawBuffer = newFb;
+   }
 }
 
 
@@ -1001,24 +1044,45 @@ _mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
 GLenum GLAPIENTRY
 _mesa_CheckFramebufferStatusEXT(GLenum target)
 {
+   struct gl_framebuffer *buffer;
    GET_CURRENT_CONTEXT(ctx);
 
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
 
-   if (target != GL_FRAMEBUFFER_EXT) {
+   switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+   case GL_DRAW_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+         return 0;
+      }
+      buffer = ctx->DrawBuffer;
+      break;
+   case GL_READ_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+         return 0;
+      }
+      buffer = ctx->ReadBuffer;
+      break;
+#endif
+   case GL_FRAMEBUFFER_EXT:
+      buffer = ctx->DrawBuffer;
+      break;
+   default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
       return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
    }
 
-   if (ctx->DrawBuffer->Name == 0) {
+   if (buffer->Name == 0) {
       /* The window system / default framebuffer is always complete */
       return GL_FRAMEBUFFER_COMPLETE_EXT;
    }
 
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
 
-   _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
-   return ctx->DrawBuffer->_Status;
+   _mesa_test_framebuffer_completeness(ctx, buffer);
+   return buffer->_Status;
 }
 
 
@@ -1086,6 +1150,7 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
 
    ASSERT(textarget == GL_TEXTURE_1D);
 
+   /* XXX read blit */
    att = get_attachment(ctx, ctx->DrawBuffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
@@ -1231,12 +1296,35 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
                                  GLuint renderbuffer)
 {
    struct gl_renderbuffer_attachment *att;
+   struct gl_framebuffer *fb;
    struct gl_renderbuffer *rb;
    GET_CURRENT_CONTEXT(ctx);
 
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (target != GL_FRAMEBUFFER_EXT) {
+   switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+   case GL_DRAW_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "glFramebufferRenderbufferEXT(target)");
+         return;
+      }
+      fb = ctx->DrawBuffer;
+      break;
+   case GL_READ_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "glFramebufferRenderbufferEXT(target)");
+         return;
+      }
+      fb = ctx->ReadBuffer;
+      break;
+#endif
+   case GL_FRAMEBUFFER_EXT:
+      fb = ctx->DrawBuffer;
+      break;
+   default:
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glFramebufferRenderbufferEXT(target)");
       return;
@@ -1248,13 +1336,13 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
       return;
    }
 
-   if (ctx->DrawBuffer->Name == 0) {
+   if (fb->Name == 0) {
       /* Can't attach new renderbuffers to a window system framebuffer */
       _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
       return;
    }
 
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = get_attachment(ctx, fb, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferRenderbufferEXT(attachment)");
@@ -1286,23 +1374,46 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
                                              GLenum pname, GLint *params)
 {
    const struct gl_renderbuffer_attachment *att;
+   struct gl_framebuffer *buffer;
    GET_CURRENT_CONTEXT(ctx);
 
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (target != GL_FRAMEBUFFER_EXT) {
+   switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+   case GL_DRAW_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "glGetFramebufferAttachmentParameterivEXT(target)");
+         return;
+      }
+      buffer = ctx->DrawBuffer;
+      break;
+   case GL_READ_FRAMEBUFFER_EXT:
+      if (!ctx->Extensions.EXT_framebuffer_blit) {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "glGetFramebufferAttachmentParameterivEXT(target)");
+         return;
+      }
+      buffer = ctx->ReadBuffer;
+      break;
+#endif
+   case GL_FRAMEBUFFER_EXT:
+      buffer = ctx->DrawBuffer;
+      break;
+   default:
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glGetFramebufferAttachmentParameterivEXT(target)");
       return;
    }
 
-   if (ctx->DrawBuffer->Name == 0) {
+   if (buffer->Name == 0) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glGetFramebufferAttachmentParameterivEXT");
       return;
    }
 
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = get_attachment(ctx, buffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glGetFramebufferAttachmentParameterivEXT(attachment)");
@@ -1390,3 +1501,51 @@ _mesa_GenerateMipmapEXT(GLenum target)
    /* XXX this might not handle cube maps correctly */
    _mesa_generate_mipmap(ctx, target, texUnit, texObj);
 }
+
+
+#if FEATURE_EXT_framebuffer_blit
+void GLAPIENTRY
+_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                         GLbitfield mask, GLenum filter)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+   /* check for complete framebuffers */
+   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+       ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "glBlitFramebufferEXT(incomplete draw/read buffers)");
+      return;
+   }
+
+   /* depth/stencil must be blitted with nearest filtering */
+   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+        && filter != GL_NEAREST) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+             "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter");
+      return;
+   }
+
+   if (mask & ~(GL_COLOR_BUFFER_BIT |
+                GL_DEPTH_BUFFER_BIT |
+                GL_STENCIL_BUFFER_BIT)) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
+      return;
+   }
+
+   if (!ctx->Extensions.EXT_framebuffer_blit) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
+      return;
+   }
+
+   ASSERT(ctx->Driver.BlitFramebuffer);
+   ctx->Driver.BlitFramebuffer(ctx,
+                               srcX0, srcY0, srcX1, srcY1,
+                               dstX0, dstY0, dstX1, dstY1,
+                               mask, filter);
+}
+#endif /* FEATURE_EXT_framebuffer_blit */
index 2c86ef93726bd751553a0ebcd7454b9c020ed108..59214ce81d863db2c610519fd4a6c8aead2734b2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5
  *
  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  *
@@ -111,4 +111,10 @@ extern void GLAPIENTRY
 _mesa_GenerateMipmapEXT(GLenum target);
 
 
+extern void GLAPIENTRY
+_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                         GLbitfield mask, GLenum filter);
+
+
 #endif /* FBOBJECT_H */
index 2d08b11cc6d8d7bbeb76e6b2c608a5879bff8a89..11a18c19bbd70b20e666e9234d2b02d00eadddbf 100644 (file)
@@ -2377,6 +2377,7 @@ struct gl_extensions
    GLboolean EXT_draw_range_elements;
    GLboolean EXT_framebuffer_object;
    GLboolean EXT_fog_coord;
+   GLboolean EXT_framebuffer_blit;
    GLboolean EXT_histogram;
    GLboolean EXT_multi_draw_arrays;
    GLboolean EXT_paletted_texture;