/** * 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); }
/** * Initialize a gl_framebuffer object. Typically used to initialize * window system-created framebuffers, not user-created framebuffers. * \sa _mesa_create_framebuffer */ void _mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual) { assert(fb); assert(visual); _mesa_bzero(fb, sizeof(struct gl_framebuffer)); _glthread_INIT_MUTEX(fb->Mutex); fb->RefCount = 1; /* save the visual */ fb->Visual = *visual; /* Init glRead/DrawBuffer state */ if (visual->doubleBufferMode) { fb->ColorDrawBuffer[0] = GL_BACK; fb->_ColorDrawBufferMask[0] = BUFFER_BIT_BACK_LEFT; fb->ColorReadBuffer = GL_BACK; fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; } else { fb->ColorDrawBuffer[0] = GL_FRONT; fb->_ColorDrawBufferMask[0] = BUFFER_BIT_FRONT_LEFT; fb->ColorReadBuffer = GL_FRONT; fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; } fb->Delete = _mesa_destroy_framebuffer; fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; compute_depth_max(fb); }
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); }
/** * Initialize a gl_framebuffer object. Typically used to initialize * window system-created framebuffers, not user-created framebuffers. * \sa _mesa_initialize_user_framebuffer */ void _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, const struct gl_config *visual) { assert(fb); assert(visual); memset(fb, 0, sizeof(struct gl_framebuffer)); mtx_init(&fb->Mutex, mtx_plain); fb->RefCount = 1; /* save the visual */ fb->Visual = *visual; /* Init read/draw renderbuffer state */ if (visual->doubleBufferMode) { fb->_NumColorDrawBuffers = 1; fb->ColorDrawBuffer[0] = GL_BACK; fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT; fb->ColorReadBuffer = GL_BACK; fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; } else { fb->_NumColorDrawBuffers = 1; fb->ColorDrawBuffer[0] = GL_FRONT; fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT; fb->ColorReadBuffer = GL_FRONT; fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; } fb->Delete = _mesa_destroy_framebuffer; fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; fb->_AllColorBuffersFixedPoint = !visual->floatMode; fb->_HasSNormOrFloatColorBuffer = visual->floatMode; fb->_HasAttachments = true; compute_depth_max(fb); }
/** * Initialize a gl_framebuffer object. Typically used to initialize * window system-created framebuffers, not user-created framebuffers. * \sa _mesa_initialize_user_framebuffer */ void _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, const struct gl_config *visual) { assert(fb); assert(visual); memset(fb, 0, sizeof(struct gl_framebuffer)); _glthread_INIT_MUTEX(fb->Mutex); fb->RefCount = 1; /* save the visual */ fb->Visual = *visual; /* Init read/draw renderbuffer state */ if (visual->doubleBufferMode) { fb->_NumColorDrawBuffers = 1; fb->ColorDrawBuffer[0] = GL_BACK; fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT; fb->ColorReadBuffer = GL_BACK; fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; } else { fb->_NumColorDrawBuffers = 1; fb->ColorDrawBuffer[0] = GL_FRONT; fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT; fb->ColorReadBuffer = GL_FRONT; fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; } fb->Delete = _mesa_destroy_framebuffer; fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; compute_depth_max(fb); }
/** * The glGet queries of the framebuffer red/green/blue size, stencil size, * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can * change depending on the renderbuffer bindings. This function updates * the given framebuffer's Visual from the current renderbuffer bindings. * * This may apply to user-created framebuffers or window system framebuffers. * * Also note: ctx->DrawBuffer->Visual.depthBits might not equal * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. * The former one is used to convert floating point depth values into * integer Z values. */ void _mesa_update_framebuffer_visual(struct gl_context *ctx, struct gl_framebuffer *fb) { GLuint i; memset(&fb->Visual, 0, sizeof(fb->Visual)); fb->Visual.rgbMode = GL_TRUE; /* assume this */ /* find first RGB renderbuffer */ for (i = 0; i < BUFFER_COUNT; i++) { if (fb->Attachment[i].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); const mesa_format fmt = rb->Format; /* Grab samples and sampleBuffers from any attachment point (assuming * the framebuffer is complete, we'll get the same answer from all * attachments). */ fb->Visual.samples = rb->NumSamples; fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0; if (_mesa_is_legal_color_format(ctx, baseFormat)) { fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS); fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); fb->Visual.rgbBits = fb->Visual.redBits + fb->Visual.greenBits + fb->Visual.blueBits; if (_mesa_get_format_color_encoding(fmt) == GL_SRGB) fb->Visual.sRGBCapable = ctx->Extensions.EXT_framebuffer_sRGB; break; } } } fb->Visual.floatMode = GL_FALSE; for (i = 0; i < BUFFER_COUNT; i++) { if (fb->Attachment[i].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; const mesa_format fmt = rb->Format; if (_mesa_get_format_datatype(fmt) == GL_FLOAT) { fb->Visual.floatMode = GL_TRUE; break; } } } if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; const mesa_format fmt = rb->Format; fb->Visual.haveDepthBuffer = GL_TRUE; fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS); } if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; const mesa_format fmt = rb->Format; fb->Visual.haveStencilBuffer = GL_TRUE; fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS); } if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[BUFFER_ACCUM].Renderbuffer; const mesa_format fmt = rb->Format; fb->Visual.haveAccumBuffer = GL_TRUE; fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS); fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); } compute_depth_max(fb); }
/** * The glGet queries of the framebuffer red/green/blue size, stencil size, * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can * change depending on the renderbuffer bindings. This function updates * the given framebuffer's Visual from the current renderbuffer bindings. * * This may apply to user-created framebuffers or window system framebuffers. * * Also note: ctx->DrawBuffer->Visual.depthBits might not equal * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. * The former one is used to convert floating point depth values into * integer Z values. */ void _mesa_update_framebuffer_visual(struct gl_context *ctx, struct gl_framebuffer *fb) { GLuint i; memset(&fb->Visual, 0, sizeof(fb->Visual)); fb->Visual.rgbMode = GL_TRUE; /* assume this */ #if 0 /* this _might_ be needed */ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { /* leave visual fields zero'd */ return; } #endif /* find first RGB renderbuffer */ for (i = 0; i < BUFFER_COUNT; i++) { if (fb->Attachment[i].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); const gl_format fmt = rb->Format; if (_mesa_is_legal_color_format(ctx, baseFormat)) { fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS); fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); fb->Visual.rgbBits = fb->Visual.redBits + fb->Visual.greenBits + fb->Visual.blueBits; fb->Visual.samples = rb->NumSamples; fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0; if (_mesa_get_format_color_encoding(fmt) == GL_SRGB) fb->Visual.sRGBCapable = ctx->Const.sRGBCapable; break; } } } fb->Visual.floatMode = GL_FALSE; for (i = 0; i < BUFFER_COUNT; i++) { if (fb->Attachment[i].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; const gl_format fmt = rb->Format; if (_mesa_get_format_datatype(fmt) == GL_FLOAT) { fb->Visual.floatMode = GL_TRUE; break; } } } if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; const gl_format fmt = rb->Format; fb->Visual.haveDepthBuffer = GL_TRUE; fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS); } if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; const gl_format fmt = rb->Format; fb->Visual.haveStencilBuffer = GL_TRUE; fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS); } if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[BUFFER_ACCUM].Renderbuffer; const gl_format fmt = rb->Format; fb->Visual.haveAccumBuffer = GL_TRUE; fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS); fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); } compute_depth_max(fb); }
/** * The glGet queries of the framebuffer red/green/blue size, stencil size, * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can * change depending on the renderbuffer bindings. This function updates * the given framebuffer's Visual from the current renderbuffer bindings. * * This may apply to user-created framebuffers or window system framebuffers. * * Also note: ctx->DrawBuffer->Visual.depthBits might not equal * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. * The former one is used to convert floating point depth values into * integer Z values. */ void _mesa_update_framebuffer_visual(struct gl_framebuffer *fb) { GLuint i; _mesa_bzero(&fb->Visual, sizeof(fb->Visual)); fb->Visual.rgbMode = GL_TRUE; /* assume this */ #if 0 /* this _might_ be needed */ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { /* leave visual fields zero'd */ return; } #endif /* find first RGB or CI renderbuffer */ for (i = 0; i < BUFFER_COUNT; i++) { if (fb->Attachment[i].Renderbuffer) { const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; if (rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB) { fb->Visual.redBits = rb->RedBits; fb->Visual.greenBits = rb->GreenBits; fb->Visual.blueBits = rb->BlueBits; fb->Visual.alphaBits = rb->AlphaBits; fb->Visual.rgbBits = fb->Visual.redBits + fb->Visual.greenBits + fb->Visual.blueBits; fb->Visual.floatMode = GL_FALSE; break; } else if (rb->_BaseFormat == GL_COLOR_INDEX) { fb->Visual.indexBits = rb->IndexBits; fb->Visual.rgbMode = GL_FALSE; break; } } } if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { fb->Visual.haveDepthBuffer = GL_TRUE; fb->Visual.depthBits = fb->Attachment[BUFFER_DEPTH].Renderbuffer->DepthBits; } if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { fb->Visual.haveStencilBuffer = GL_TRUE; fb->Visual.stencilBits = fb->Attachment[BUFFER_STENCIL].Renderbuffer->StencilBits; } if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { fb->Visual.haveAccumBuffer = GL_TRUE; fb->Visual.accumRedBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->RedBits; fb->Visual.accumGreenBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->GreenBits; fb->Visual.accumBlueBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->BlueBits; fb->Visual.accumAlphaBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->AlphaBits; } compute_depth_max(fb); }