+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, n, buffers);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, buffers[0]);
+}
+
+
+/**
+ * Set color output state. Traditionally, there was only one color
+ * output, but fragment programs can now have several distinct color
+ * outputs (see GL_ARB_draw_buffers). This function sets the state
+ * for one such color output.
+ * \param ctx current context
+ * \param output which fragment program output
+ * \param buffer buffer to write to (like GL_LEFT)
+ * \param destMask BUFFER_* bitmask
+ * (like BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
+ */
+static void
+set_color_output(GLcontext *ctx, GLuint output, GLenum buffer,
+ GLbitfield destMask)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+ ASSERT(output < ctx->Const.MaxDrawBuffers);
+
+ /* Set per-FBO state */
+ fb->ColorDrawBuffer[output] = buffer;
+ fb->_ColorDrawBufferMask[output] = destMask;
+ /* not really needed, will be set later */
+ fb->_NumColorDrawBuffers[output] = 0;
+
+ if (fb->Name == 0)
+ /* Set traditional state var */
+ ctx->Color.DrawBuffer[output] = buffer;
+}
+
+
+/**
+ * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and
+ * other places (window fbo fixup) to set fbo (and the old ctx) fields.
+ * All error checking will have been done prior to calling this function
+ * so nothing should go wrong at this point.
+ * \param ctx current context
+ * \param n number of color outputs to set
+ * \param buffers array[n] of colorbuffer names, like GL_LEFT.
+ * \param destMask array[n] of BUFFER_* bitmasks which correspond to the
+ * colorbuffer names. (i.e. GL_FRONT_AND_BACK =>
+ * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
+ */
+void
+_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
+ const GLbitfield *destMask)
+{
+ GLbitfield mask[MAX_DRAW_BUFFERS];
+ GLuint output;
+
+ if (!destMask) {
+ /* compute destMask values now */
+ const GLbitfield supportedMask
+ = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
+ for (output = 0; output < n; output++) {
+ mask[output] = draw_buffer_enum_to_bitmask(buffers[output]);
+ ASSERT(mask[output] != BAD_MASK);
+ mask[output] &= supportedMask;
+ }
+ destMask = mask;
+ }
+
+ for (output = 0; output < n; output++) {
+ set_color_output(ctx, output, buffers[output], destMask[output]);
+ }
+
+ /* set remaining color outputs to NONE */
+ for (output = n; output < ctx->Const.MaxDrawBuffers; output++) {
+ set_color_output(ctx, output, GL_NONE, 0x0);
+ }
+
+ ctx->NewState |= _NEW_BUFFERS;
+}
+
+
+GLboolean
+_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer)
+{
+ struct gl_framebuffer *fb;
+ GLbitfield supportedMask;
+ GLint srcBuffer;
+
+ fb = ctx->ReadBuffer;
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+
+ if (fb->Name > 0 && buffer == GL_NONE) {
+ /* This is legal for user-created framebuffer objects */
+ srcBuffer = -1;