diff options
author | Brian Paul <[email protected]> | 2005-11-08 14:45:48 +0000 |
---|---|---|
committer | Brian Paul <[email protected]> | 2005-11-08 14:45:48 +0000 |
commit | 0bffb1192a599b11af11604ad590f6a50c054bf1 (patch) | |
tree | 5f9ecae6fbcdecbbeabaab66841d56a0ba128ae8 /src/mesa/main/fbobject.c | |
parent | 3e9c099088424c149931dcf546ae0a4d9ac2ae76 (diff) |
some initial work on upcoming GL_EXT_framebuffer_blit extension
Diffstat (limited to 'src/mesa/main/fbobject.c')
-rw-r--r-- | src/mesa/main/fbobject.c | 209 |
1 files changed, 184 insertions, 25 deletions
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index f5ae4518beb..dc32caae158 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 */ |