X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Ffbobject.c;h=e3e006bb948d0d0d5e9026a11ee8007bbf64b1f1;hb=4fb2daf42c8171579cdc18605c5ceeb1963f8b31;hp=319d0f2ce9773379c0b907f2a34890a70d38a5dc;hpb=800e553e7a1703e33e54f45d0638b67001665fc5;p=mesa.git diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 319d0f2ce97..e3e006bb948 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -40,13 +40,10 @@ #include "framebuffer.h" #include "hash.h" #include "macros.h" -#include "mipmap.h" #include "renderbuffer.h" #include "state.h" #include "teximage.h" #include "texobj.h" -#include "texstore.h" -#include "texstate.h" /** Set this to 1 to help debug FBO incompleteness problems */ @@ -183,8 +180,12 @@ _mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, return &fb->Attachment[BUFFER_COLOR0 + i]; case GL_DEPTH_STENCIL_ATTACHMENT: /* fall-through */ + case GL_DEPTH_BUFFER: + /* fall-through / new in GL 3.0 */ case GL_DEPTH_ATTACHMENT_EXT: return &fb->Attachment[BUFFER_DEPTH]; + case GL_STENCIL_BUFFER: + /* fall-through / new in GL 3.0 */ case GL_STENCIL_ATTACHMENT_EXT: return &fb->Attachment[BUFFER_STENCIL]; default: @@ -233,9 +234,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); @@ -373,8 +378,8 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, } if (texImage->Width < 1 || texImage->Height < 1) { att_incomplete("teximage width/height=0"); - _mesa_printf("texobj = %u\n", texObj->Name); - _mesa_printf("level = %d\n", att->TextureLevel); + printf("texobj = %u\n", texObj->Name); + printf("level = %d\n", att->TextureLevel); att->Complete = GL_FALSE; return; } @@ -624,7 +629,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb) } } -#ifndef FEATURE_OES_framebuffer_object +#if !FEATURE_OES_framebuffer_object /* Check that all DrawBuffers are present */ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { if (fb->ColorDrawBuffer[j] != GL_NONE) { @@ -857,6 +862,9 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) * * \return one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT * GL_DEPTH_STENCIL_EXT or zero if error. + * + * XXX in the future when we support red-only and red-green formats + * we'll also return GL_RED and GL_RG. */ GLenum _mesa_base_fbo_format(GLcontext *ctx, GLenum internalFormat) @@ -950,7 +958,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, /* NumSamples == 0 indicates non-multisampling */ samples = 0; } - else if (samples > ctx->Const.MaxSamples) { + else if (samples > (GLsizei) ctx->Const.MaxSamples) { /* note: driver may choose to use more samples than what's requested */ _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func); return; @@ -983,7 +991,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, assert(rb->Width == (GLuint) width); assert(rb->Height == (GLuint) height); rb->InternalFormat = internalFormat; - rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); + rb->_BaseFormat = baseFormat; assert(rb->_BaseFormat != 0); } else { @@ -1004,6 +1012,30 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, */ } +#if FEATURE_OES_EGL_image +void GLAPIENTRY +_mesa_EGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image) +{ + struct gl_renderbuffer *rb; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_RENDERBUFFER) { + _mesa_error(ctx, GL_INVALID_ENUM, "EGLImageTargetRenderbufferStorageOES"); + return; + } + + rb = ctx->CurrentRenderbuffer; + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, "EGLImageTargetRenderbufferStorageOES"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image); +} +#endif /** * Helper function for _mesa_GetRenderbufferParameterivEXT() and @@ -1145,11 +1177,20 @@ _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; @@ -1169,6 +1210,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++) { @@ -1184,7 +1228,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); @@ -1233,74 +1278,88 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) 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 { - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - _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 { - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - _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); } } @@ -1322,15 +1381,26 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); /* check if deleting currently bound framebuffer object */ - if (fb == ctx->DrawBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + if (ctx->Extensions.EXT_framebuffer_blit) { + /* separate draw/read binding points */ + if (fb == ctx->DrawBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + } + if (fb == ctx->ReadBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); + } } - if (fb == ctx->ReadBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); + else { + /* only one binding point for read/draw buffers */ + if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } } /* remove from hash table immediately, to free the ID */ @@ -1483,6 +1553,7 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target, texObj = _mesa_lookup_texture(ctx, texture); if (texObj != NULL) { if (textarget == 0) { + /* XXX what's the purpose of this? */ err = (texObj->Target != GL_TEXTURE_3D) && (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); @@ -1493,6 +1564,13 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target, : (texObj->Target != textarget); } } + else { + /* can't render to a non-existant texture */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture%sEXT(non existant texture)", + caller); + return; + } if (err) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -1911,7 +1989,6 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, void GLAPIENTRY _mesa_GenerateMipmapEXT(GLenum target) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); @@ -1930,8 +2007,12 @@ _mesa_GenerateMipmapEXT(GLenum target) return; } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); + + if (texObj->BaseLevel >= texObj->MaxLevel) { + /* nothing to do */ + return; + } _mesa_lock_texture(ctx, texObj); if (target == GL_TEXTURE_CUBE_MAP) { @@ -2094,39 +2175,39 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, /* 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); + 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); + 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); + printf("Tex %u tgt 0x%x level %u face %u", + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); } - _mesa_printf("\n"); + printf("\n"); att = find_attachment(drawFb, colorDrawRb); - _mesa_printf(" Dst FBO %u RB %u (%dx%d) ", - drawFb->Name, colorDrawRb->Name, - colorDrawRb->Width, colorDrawRb->Height); + 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); + printf("Tex %u tgt 0x%x level %u face %u", + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); } - _mesa_printf("\n"); + printf("\n"); } }