From ff73c783cc47361ff0dd819c82d067b4b85870dd Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 6 Jan 2008 10:43:20 -0700 Subject: Simplify ctx->_NumColorDrawBuffers, _ColorDrawBuffers and fix bug 13835. These fields are no longer indexed by shader output. Now, we just have a simple array of renderbuffer pointers. If the shader writes to gl_FragData[i], send those colors to the N _ColorDrawBuffers. Otherwise, replicate the single gl_FragColor (or the fixed-function color) to the N _ColorDrawBuffers. A few more changes and simplifications can follow from this... --- src/mesa/main/buffers.c | 5 ++- src/mesa/main/framebuffer.c | 97 +++++++++++++++++++++++++++++++++------------ src/mesa/main/mtypes.h | 4 +- 3 files changed, 76 insertions(+), 30 deletions(-) (limited to 'src/mesa/main') diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index 0fba73b3c2..2252bbd4c5 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -508,8 +508,9 @@ set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, /* Set per-FBO state */ fb->ColorDrawBuffer[output] = buffer; fb->_ColorDrawBufferMask[output] = destMask; - /* not really needed, will be set later */ - fb->_NumColorDrawBuffers[output] = 0; + + /* this will be computed later, but zero to be safe */ + fb->_NumColorDrawBuffers = 0; if (fb->Name == 0) { /* Only set the per-context DrawBuffer state if we're currently diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 3e36197d88..8f92fd3b42 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -583,6 +583,51 @@ _mesa_update_stencil_buffer(GLcontext *ctx, } +/* + * Example DrawBuffers scenarios: + * + * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to + * "gl_FragColor" or program writes to the "result.color" register: + * + * fragment color output renderbuffer + * --------------------- --------------- + * color[0] Front, Back + * + * + * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to + * gl_FragData[i] or program writes to result.color[i] registers: + * + * fragment color output renderbuffer + * --------------------- --------------- + * color[0] Front + * color[1] Aux0 + * color[3] Aux1 + * + * + * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to + * gl_FragColor, or fixed function: + * + * fragment color output renderbuffer + * --------------------- --------------- + * color[0] Front, Aux0, Aux1 + * + * + * In either case, the list of renderbuffers is stored in the + * framebuffer->_ColorDrawBuffers[] array and + * framebuffer->_NumColorDrawBuffers indicates the number of buffers. + * The renderer (like swrast) has to look at the current fragment shader + * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine + * how to map color outputs to renderbuffers. + * + * Note that these two calls are equivalent (for fixed function fragment + * shading anyway): + * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer) + * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]); + */ + + + + /** * Update the (derived) list of color drawing renderbuffer pointers. * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers @@ -591,39 +636,39 @@ _mesa_update_stencil_buffer(GLcontext *ctx, static void update_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb) { - GLuint output; + GLuint output, count = 0; - /* - * Fragment programs can write to multiple colorbuffers with - * the GL_ARB_draw_buffers extension. + /* First, interpret _ColorDrawBufferMask[] in the manner that would be + * used if the fragment program/shader writes to gl_FragData[] */ for (output = 0; output < ctx->Const.MaxDrawBuffers; output++) { - GLbitfield bufferMask = fb->_ColorDrawBufferMask[output]; - GLuint count = 0; + GLuint buf = _mesa_ffs(fb->_ColorDrawBufferMask[output]); + if (buf) { + struct gl_renderbuffer *rb = fb->Attachment[buf - 1].Renderbuffer; + fb->_ColorDrawBuffers[output] = rb; /* may be NULL */ + if (rb) + count = output + 1; + } + } + + /* Second, handle the GL_FRONT_AND_BACK case, overwriting the above + * if needed. + */ + GLbitfield bufferMask = fb->_ColorDrawBufferMask[0]; + if (_mesa_bitcount(bufferMask) > 1) { GLuint i; - if (!fb->DeletePending) { - /* We need the inner loop here because glDrawBuffer(GL_FRONT_AND_BACK) - * can specify writing to two or four color buffers (for example). - */ - for (i = 0; bufferMask && i < BUFFER_COUNT; i++) { - const GLuint bufferBit = 1 << i; - if (bufferBit & bufferMask) { - struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; - if (rb && rb->Width > 0 && rb->Height > 0) { - fb->_ColorDrawBuffers[output][count] = rb; - count++; - } - else { - /* - _mesa_warning(ctx, "DrawBuffer names a missing buffer!\n"); - */ - } - bufferMask &= ~bufferBit; - } + count = 0; + for (i = 0; bufferMask && i < BUFFER_COUNT; i++) { + if (bufferMask & (1 << i)) { + struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; + fb->_ColorDrawBuffers[count] = rb; + count++; } + bufferMask &= ~(1 << i); } - fb->_NumColorDrawBuffers[output] = count; } + + fb->_NumColorDrawBuffers = count; } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 0da487ea04..0e7364c08f 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2400,8 +2400,8 @@ struct gl_framebuffer GLint _ColorReadBufferIndex; /* -1 = None */ /* These are computed from _ColorDrawBufferMask and _ColorReadBufferIndex */ - GLuint _NumColorDrawBuffers[MAX_DRAW_BUFFERS]; - struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS][4]; + GLuint _NumColorDrawBuffers; + struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS]; struct gl_renderbuffer *_ColorReadBuffer; /** The Actual depth/stencil buffers to use. May be wrappers around the -- cgit v1.2.3