From 0bffb1192a599b11af11604ad590f6a50c054bf1 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 8 Nov 2005 14:45:48 +0000 Subject: [PATCH] some initial work on upcoming GL_EXT_framebuffer_blit extension --- src/mesa/main/config.h | 1 + src/mesa/main/dd.h | 6 ++ src/mesa/main/extensions.c | 2 + src/mesa/main/fbobject.c | 209 ++++++++++++++++++++++++++++++++----- src/mesa/main/fbobject.h | 8 +- src/mesa/main/mtypes.h | 1 + 6 files changed, 201 insertions(+), 26 deletions(-) diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index ff764886bd7..a10542de22e 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 5f680116e56..d07a7a26b1e 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 cd97b0ccb24..816fca9957e 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 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 */ diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h index 2c86ef93726..59214ce81d8 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 2d08b11cc6d..11a18c19bbd 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; -- 2.30.2