summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mesa/main/config.h1
-rw-r--r--src/mesa/main/dd.h6
-rw-r--r--src/mesa/main/extensions.c2
-rw-r--r--src/mesa/main/fbobject.c209
-rw-r--r--src/mesa/main/fbobject.h8
-rw-r--r--src/mesa/main/mtypes.h1
6 files changed, 201 insertions, 26 deletions
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index ff764886bd..a10542de22 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -302,6 +302,7 @@
#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
/*@}*/
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 5f680116e5..d07a7a26b1 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -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
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index cd97b0ccb2..816fca9957 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -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;
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index f5ae4518be..dc32caae15 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -38,6 +38,14 @@
#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 */
diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h
index 2c86ef9372..59214ce81d 100644
--- a/src/mesa/main/fbobject.h
+++ b/src/mesa/main/fbobject.h
@@ -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 */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 2d08b11cc6..11a18c19bb 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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;