/** * Update a gl_framebuffer's derived state. * * Specifically, update these framebuffer fields: * _ColorDrawBuffers * _NumColorDrawBuffers * _ColorReadBuffer * * If the framebuffer is user-created, make sure it's complete. * * The following functions (at least) can effect framebuffer state: * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT, * glRenderbufferStorageEXT. */ static void update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) { if (_mesa_is_winsys_fbo(fb)) { /* This is a window-system framebuffer */ /* Need to update the FB's GL_DRAW_BUFFER state to match the * context state (GL_READ_BUFFER too). */ if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers, ctx->Color.DrawBuffer, NULL); } } else { /* This is a user-created framebuffer. * Completeness only matters for user-created framebuffers. */ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) { _mesa_test_framebuffer_completeness(ctx, fb); } } /* Strictly speaking, we don't need to update the draw-state * if this FB is bound as ctx->ReadBuffer (and conversely, the * read-state if this FB is bound as ctx->DrawBuffer), but no * harm. */ update_color_draw_buffers(ctx, fb); update_color_read_buffer(ctx, fb); compute_depth_max(fb); }
GLenum GLAPIENTRY _mesa_CheckFramebufferStatusEXT(GLenum target) { struct gl_framebuffer *buffer; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 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 (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, buffer); return buffer->_Status; }
static void update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) { /* Completeness only matters for user-created framebuffers */ if (fb->Name != 0) { /* XXX: EXT_framebuffer_blit: framebuffer must still be complete wrt read/draw? */ _mesa_test_framebuffer_completeness(ctx, fb); _mesa_update_framebuffer_visual(fb); } /* update_color_draw/read_buffers not needed for read/draw only fb, but shouldn't hurt ??? */ update_color_draw_buffers(ctx, fb); update_color_read_buffer(ctx, fb); _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); compute_depth_max(fb); }
/** * Check if the renderbuffer for a read/draw operation exists. * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. * \param reading if TRUE, we're going to read from the buffer, if FALSE, we're going to write to the buffer. * \return GL_TRUE if buffer exists, GL_FALSE otherwise */ static GLboolean renderbuffer_exists(struct gl_context *ctx, struct gl_framebuffer *fb, GLenum format, GLboolean reading) { const struct gl_renderbuffer_attachment *att = fb->Attachment; /* If we don't know the framebuffer status, update it now */ if (fb->_Status == 0) { _mesa_test_framebuffer_completeness(ctx, fb); } if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { return GL_FALSE; } switch (format) { case GL_COLOR: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_RG: case GL_RGB: case GL_BGR: case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: case GL_RED_INTEGER_EXT: case GL_RG_INTEGER: case GL_GREEN_INTEGER_EXT: case GL_BLUE_INTEGER_EXT: case GL_ALPHA_INTEGER_EXT: case GL_RGB_INTEGER_EXT: case GL_RGBA_INTEGER_EXT: case GL_BGR_INTEGER_EXT: case GL_BGRA_INTEGER_EXT: case GL_LUMINANCE_INTEGER_EXT: case GL_LUMINANCE_ALPHA_INTEGER_EXT: if (reading) { /* about to read from a color buffer */ const struct gl_renderbuffer *readBuf = fb->_ColorReadBuffer; if (!readBuf) { return GL_FALSE; } assert(_mesa_get_format_bits(readBuf->Format, GL_RED_BITS) > 0 || _mesa_get_format_bits(readBuf->Format, GL_ALPHA_BITS) > 0 || _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_LUMINANCE_SIZE) > 0 || _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_INTENSITY_SIZE) > 0 || _mesa_get_format_bits(readBuf->Format, GL_INDEX_BITS) > 0); } else { /* about to draw to zero or more color buffers (none is OK) */ return GL_TRUE; } break; case GL_DEPTH: case GL_DEPTH_COMPONENT: if (att[BUFFER_DEPTH].Type == GL_NONE) { return GL_FALSE; } break; case GL_STENCIL: case GL_STENCIL_INDEX: if (att[BUFFER_STENCIL].Type == GL_NONE) { return GL_FALSE; } break; case GL_DEPTH_STENCIL_EXT: if (att[BUFFER_DEPTH].Type == GL_NONE || att[BUFFER_STENCIL].Type == GL_NONE) { return GL_FALSE; } break; default: _mesa_problem(ctx, "Unexpected format 0x%x in renderbuffer_exists", format); return GL_FALSE; } /* OK */ return GL_TRUE; }
/** * As above, but for drawing operations. * XXX could do some code merging w/ above function. */ GLboolean _mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format) { const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; /* If we don't know the framebuffer status, update it now */ if (ctx->DrawBuffer->_Status == 0) { _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer); } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { return GL_FALSE; } switch (format) { case GL_COLOR: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_RGB: case GL_BGR: case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: case GL_COLOR_INDEX: case GL_RED_INTEGER_EXT: case GL_GREEN_INTEGER_EXT: case GL_BLUE_INTEGER_EXT: case GL_ALPHA_INTEGER_EXT: case GL_RGB_INTEGER_EXT: case GL_RGBA_INTEGER_EXT: case GL_BGR_INTEGER_EXT: case GL_BGRA_INTEGER_EXT: case GL_LUMINANCE_INTEGER_EXT: case GL_LUMINANCE_ALPHA_INTEGER_EXT: /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */ /* Could assert that colorbuffer has RedBits > 0 */ break; case GL_DEPTH: case GL_DEPTH_COMPONENT: if (!att[BUFFER_DEPTH].Renderbuffer) { return GL_FALSE; } /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/ break; case GL_STENCIL: case GL_STENCIL_INDEX: if (!att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/ break; case GL_DEPTH_STENCIL_EXT: if (!att[BUFFER_DEPTH].Renderbuffer || !att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } /* ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); */ break; default: _mesa_problem(ctx, "Unexpected format 0x%x in _mesa_dest_buffer_exists", format); return GL_FALSE; } /* OK */ return GL_TRUE; }
/** * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels, * glCopyTex[Sub]Image, etc) exists. * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. * \return GL_TRUE if buffer exists, GL_FALSE otherwise */ GLboolean _mesa_source_buffer_exists(struct gl_context *ctx, GLenum format) { const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment; /* If we don't know the framebuffer status, update it now */ if (ctx->ReadBuffer->_Status == 0) { _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); } if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { return GL_FALSE; } switch (format) { case GL_COLOR: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_RG: case GL_RGB: case GL_BGR: case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: case GL_COLOR_INDEX: case GL_RED_INTEGER_EXT: case GL_GREEN_INTEGER_EXT: case GL_BLUE_INTEGER_EXT: case GL_ALPHA_INTEGER_EXT: case GL_RGB_INTEGER_EXT: case GL_RGBA_INTEGER_EXT: case GL_BGR_INTEGER_EXT: case GL_BGRA_INTEGER_EXT: case GL_LUMINANCE_INTEGER_EXT: case GL_LUMINANCE_ALPHA_INTEGER_EXT: if (ctx->ReadBuffer->_ColorReadBuffer == NULL) { return GL_FALSE; } ASSERT(_mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_RED_BITS) > 0 || _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_ALPHA_BITS) > 0 || _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_INDEX_BITS) > 0); break; case GL_DEPTH: case GL_DEPTH_COMPONENT: if (!att[BUFFER_DEPTH].Renderbuffer) { return GL_FALSE; } /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/ break; case GL_STENCIL: case GL_STENCIL_INDEX: if (!att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/ break; case GL_DEPTH_STENCIL_EXT: if (!att[BUFFER_DEPTH].Renderbuffer || !att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } /* ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); */ break; default: _mesa_problem(ctx, "Unexpected format 0x%x in _mesa_source_buffer_exists", format); return GL_FALSE; } /* OK */ return GL_TRUE; }