#include "glheader.h"
#include "imports.h"
+#include "buffers.h"
#include "context.h"
#include "depthstencil.h"
#include "mtypes.h"
#include "fbobject.h"
#include "framebuffer.h"
#include "renderbuffer.h"
+#include "texobj.h"
fb->_DepthMax = 0xffffffff;
}
fb->_DepthMaxF = (GLfloat) fb->_DepthMax;
- fb->_MRD = 1.0; /* Minimum resolvable depth value, for polygon offset */
-}
-
-/**
- * Set the framebuffer's _DepthBuffer field, taking care of
- * reference counts, etc.
- */
-static void
-set_depth_renderbuffer(struct gl_framebuffer *fb,
- struct gl_renderbuffer *rb)
-{
- if (fb->_DepthBuffer) {
- _mesa_unreference_renderbuffer(&fb->_DepthBuffer);
- }
- fb->_DepthBuffer = rb;
- if (rb) {
- rb->RefCount++;
- }
-}
-
-
-/**
- * Set the framebuffer's _StencilBuffer field, taking care of
- * reference counts, etc.
- */
-static void
-set_stencil_renderbuffer(struct gl_framebuffer *fb,
- struct gl_renderbuffer *rb)
-{
- if (fb->_StencilBuffer) {
- _mesa_unreference_renderbuffer(&fb->_StencilBuffer);
- }
- fb->_StencilBuffer = rb;
- if (rb) {
- rb->RefCount++;
- }
+ /* Minimum resolvable depth value, for polygon offset */
+ fb->_MRD = 1.0 / fb->_DepthMaxF;
}
/* save the visual */
fb->Visual = *visual;
- /* Init glRead/DrawBuffer state */
+ /* Init read/draw renderbuffer state */
if (visual->doubleBufferMode) {
fb->ColorDrawBuffer[0] = GL_BACK;
fb->_ColorDrawBufferMask[0] = BUFFER_BIT_BACK_LEFT;
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
if (att->Renderbuffer) {
- _mesa_unreference_renderbuffer(&att->Renderbuffer);
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
}
if (att->Texture) {
- /* render to texture */
- att->Texture->RefCount--;
- if (att->Texture->RefCount == 0) {
- GET_CURRENT_CONTEXT(ctx);
- if (ctx) {
- ctx->Driver.DeleteTexture(ctx, att->Texture);
- }
- }
+ _mesa_reference_texobj(&att->Texture, NULL);
}
+ ASSERT(!att->Renderbuffer);
+ ASSERT(!att->Texture);
att->Type = GL_NONE;
- att->Texture = NULL;
}
- /* unbind depth/stencil to decr ref counts */
- set_depth_renderbuffer(fb, NULL);
- set_stencil_renderbuffer(fb, NULL);
+ /* unbind _Depth/_StencilBuffer to decr ref counts */
+ _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL);
+ _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL);
}
/* need to update wrapper */
struct gl_renderbuffer *wrapper
= _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb);
- set_depth_renderbuffer(fb, wrapper);
+ _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
}
}
else {
/* depthRb may be null */
- set_depth_renderbuffer(fb, depthRb);
+ _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
}
}
/* need to update wrapper */
struct gl_renderbuffer *wrapper
= _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
- set_stencil_renderbuffer(fb, wrapper);
+ _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
}
}
else {
/* stencilRb may be null */
- set_stencil_renderbuffer(fb, stencilRb);
+ _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
}
}
/**
- * Update the list of color drawing renderbuffer pointers.
+ * Update the (derived) list of color drawing renderbuffer pointers.
* Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers
* writing colors.
*/
const GLuint bufferBit = 1 << i;
if (bufferBit & bufferMask) {
struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
- if (rb) {
+ if (rb && rb->Width > 0 && rb->Height > 0) {
fb->_ColorDrawBuffers[output][count] = rb;
count++;
}
/**
- * Update the color read renderbuffer pointer.
+ * Update the (derived) color read renderbuffer pointer.
* Unlike the DrawBuffer, we can only read from one (or zero) color buffers.
*/
static void
update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
{
(void) ctx;
- if (fb->_ColorReadBufferIndex == -1 || fb->DeletePending) {
+ if (fb->_ColorReadBufferIndex == -1 ||
+ fb->DeletePending ||
+ fb->Width == 0 ||
+ fb->Height == 0) {
fb->_ColorReadBuffer = NULL; /* legal! */
}
else {
/**
- * Update state related to the current draw/read framebuffers.
+ * Update a gl_framebuffer's derived state.
+ *
* Specifically, update these framebuffer fields:
* _ColorDrawBuffers
* _NumColorDrawBuffers
* _ColorReadBuffer
* _DepthBuffer
* _StencilBuffer
- * If the current framebuffer is user-created, make sure it's complete.
- * The following functions can effect this state: glReadBuffer,
- * glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT,
+ *
+ * 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.
*/
-void
-_mesa_update_framebuffer(GLcontext *ctx)
+static void
+update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
{
- struct gl_framebuffer *fb = ctx->DrawBuffer;
-
- /* Completeness only matters for user-created framebuffers */
- if (fb->Name != 0) {
+ if (fb->Name == 0) {
+ /* 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, ctx->Const.MaxDrawBuffers,
+ ctx->Color.DrawBuffer, NULL);
+ }
+ if (fb->ColorReadBuffer != ctx->Pixel.ReadBuffer) {
+
+ }
+ }
+ else {
+ /* This is a user-created framebuffer.
+ * Completeness only matters for user-created framebuffers.
+ */
_mesa_test_framebuffer_completeness(ctx, fb);
_mesa_update_framebuffer_visual(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);
_mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
}
+/**
+ * Update state related to the current draw/read framebuffers.
+ */
+void
+_mesa_update_framebuffer(GLcontext *ctx)
+{
+ struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+ struct gl_framebuffer *readFb = ctx->ReadBuffer;
+
+ update_framebuffer(ctx, drawFb);
+ if (readFb != drawFb)
+ update_framebuffer(ctx, readFb);
+}
+
+
/**
* Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
* glCopyTex[Sub]Image, etc. exists.