Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. /**
  27.  * \file buffers.c
  28.  * glReadBuffer, DrawBuffer functions.
  29.  */
  30.  
  31.  
  32.  
  33. #include "glheader.h"
  34. #include "buffers.h"
  35. #include "colormac.h"
  36. #include "context.h"
  37. #include "enums.h"
  38. #include "fbobject.h"
  39. #include "mtypes.h"
  40.  
  41.  
  42. #define BAD_MASK ~0u
  43.  
  44.  
  45. /**
  46.  * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are
  47.  * available to the rendering context (for drawing or reading).
  48.  * This depends on the type of framebuffer.  For window system framebuffers
  49.  * we look at the framebuffer's visual.  But for user-create framebuffers we
  50.  * look at the number of supported color attachments.
  51.  * \param fb  the framebuffer to draw to, or read from
  52.  * \return  bitmask of BUFFER_BIT_* flags
  53.  */
  54. static GLbitfield
  55. supported_buffer_bitmask(const struct gl_context *ctx,
  56.                          const struct gl_framebuffer *fb)
  57. {
  58.    GLbitfield mask = 0x0;
  59.  
  60.    if (_mesa_is_user_fbo(fb)) {
  61.       /* A user-created renderbuffer */
  62.       GLuint i;
  63.       for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
  64.          mask |= (BUFFER_BIT_COLOR0 << i);
  65.       }
  66.    }
  67.    else {
  68.       /* A window system framebuffer */
  69.       GLint i;
  70.       mask = BUFFER_BIT_FRONT_LEFT; /* always have this */
  71.       if (fb->Visual.stereoMode) {
  72.          mask |= BUFFER_BIT_FRONT_RIGHT;
  73.          if (fb->Visual.doubleBufferMode) {
  74.             mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
  75.          }
  76.       }
  77.       else if (fb->Visual.doubleBufferMode) {
  78.          mask |= BUFFER_BIT_BACK_LEFT;
  79.       }
  80.  
  81.       for (i = 0; i < fb->Visual.numAuxBuffers; i++) {
  82.          mask |= (BUFFER_BIT_AUX0 << i);
  83.       }
  84.    }
  85.  
  86.    return mask;
  87. }
  88.  
  89.  
  90. /**
  91.  * Helper routine used by glDrawBuffer and glDrawBuffersARB.
  92.  * Given a GLenum naming one or more color buffers (such as
  93.  * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags.
  94.  */
  95. static GLbitfield
  96. draw_buffer_enum_to_bitmask(const struct gl_context *ctx, GLenum buffer)
  97. {
  98.    switch (buffer) {
  99.       case GL_NONE:
  100.          return 0;
  101.       case GL_FRONT:
  102.          return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT;
  103.       case GL_BACK:
  104.          if (_mesa_is_gles3(ctx)) {
  105.             /* Page 181 (page 192 of the PDF) in section 4.2.1 of the OpenGL
  106.              * ES 3.0.1 specification says:
  107.              *
  108.              *     "When draw buffer zero is BACK, color values are written
  109.              *     into the sole buffer for single-buffered contexts, or into
  110.              *     the back buffer for double-buffered contexts."
  111.              *
  112.              * Since there is no stereo rendering in ES 3.0, only return the
  113.              * LEFT bits.  This also satisfies the "n must be 1" requirement.
  114.              */
  115.             if (ctx->DrawBuffer->Visual.doubleBufferMode)
  116.                return BUFFER_BIT_BACK_LEFT;
  117.             return BUFFER_BIT_FRONT_LEFT;
  118.          }
  119.          return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
  120.       case GL_RIGHT:
  121.          return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
  122.       case GL_FRONT_RIGHT:
  123.          return BUFFER_BIT_FRONT_RIGHT;
  124.       case GL_BACK_RIGHT:
  125.          return BUFFER_BIT_BACK_RIGHT;
  126.       case GL_BACK_LEFT:
  127.          return BUFFER_BIT_BACK_LEFT;
  128.       case GL_FRONT_AND_BACK:
  129.          return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT
  130.               | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
  131.       case GL_LEFT:
  132.          return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT;
  133.       case GL_FRONT_LEFT:
  134.          return BUFFER_BIT_FRONT_LEFT;
  135.       case GL_AUX0:
  136.          return BUFFER_BIT_AUX0;
  137.       case GL_AUX1:
  138.       case GL_AUX2:
  139.       case GL_AUX3:
  140.          return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */
  141.       case GL_COLOR_ATTACHMENT0_EXT:
  142.          return BUFFER_BIT_COLOR0;
  143.       case GL_COLOR_ATTACHMENT1_EXT:
  144.          return BUFFER_BIT_COLOR1;
  145.       case GL_COLOR_ATTACHMENT2_EXT:
  146.          return BUFFER_BIT_COLOR2;
  147.       case GL_COLOR_ATTACHMENT3_EXT:
  148.          return BUFFER_BIT_COLOR3;
  149.       case GL_COLOR_ATTACHMENT4_EXT:
  150.          return BUFFER_BIT_COLOR4;
  151.       case GL_COLOR_ATTACHMENT5_EXT:
  152.          return BUFFER_BIT_COLOR5;
  153.       case GL_COLOR_ATTACHMENT6_EXT:
  154.          return BUFFER_BIT_COLOR6;
  155.       case GL_COLOR_ATTACHMENT7_EXT:
  156.          return BUFFER_BIT_COLOR7;
  157.       default:
  158.          /* error */
  159.          return BAD_MASK;
  160.    }
  161. }
  162.  
  163.  
  164. /**
  165.  * Helper routine used by glReadBuffer.
  166.  * Given a GLenum naming a color buffer, return the index of the corresponding
  167.  * renderbuffer (a BUFFER_* value).
  168.  * return -1 for an invalid buffer.
  169.  */
  170. static GLint
  171. read_buffer_enum_to_index(GLenum buffer)
  172. {
  173.    switch (buffer) {
  174.       case GL_FRONT:
  175.          return BUFFER_FRONT_LEFT;
  176.       case GL_BACK:
  177.          return BUFFER_BACK_LEFT;
  178.       case GL_RIGHT:
  179.          return BUFFER_FRONT_RIGHT;
  180.       case GL_FRONT_RIGHT:
  181.          return BUFFER_FRONT_RIGHT;
  182.       case GL_BACK_RIGHT:
  183.          return BUFFER_BACK_RIGHT;
  184.       case GL_BACK_LEFT:
  185.          return BUFFER_BACK_LEFT;
  186.       case GL_LEFT:
  187.          return BUFFER_FRONT_LEFT;
  188.       case GL_FRONT_LEFT:
  189.          return BUFFER_FRONT_LEFT;
  190.       case GL_AUX0:
  191.          return BUFFER_AUX0;
  192.       case GL_AUX1:
  193.       case GL_AUX2:
  194.       case GL_AUX3:
  195.          return BUFFER_COUNT; /* invalid, but not -1 */
  196.       case GL_COLOR_ATTACHMENT0_EXT:
  197.          return BUFFER_COLOR0;
  198.       case GL_COLOR_ATTACHMENT1_EXT:
  199.          return BUFFER_COLOR1;
  200.       case GL_COLOR_ATTACHMENT2_EXT:
  201.          return BUFFER_COLOR2;
  202.       case GL_COLOR_ATTACHMENT3_EXT:
  203.          return BUFFER_COLOR3;
  204.       case GL_COLOR_ATTACHMENT4_EXT:
  205.          return BUFFER_COLOR4;
  206.       case GL_COLOR_ATTACHMENT5_EXT:
  207.          return BUFFER_COLOR5;
  208.       case GL_COLOR_ATTACHMENT6_EXT:
  209.          return BUFFER_COLOR6;
  210.       case GL_COLOR_ATTACHMENT7_EXT:
  211.          return BUFFER_COLOR7;
  212.       default:
  213.          /* error */
  214.          return -1;
  215.    }
  216. }
  217.  
  218.  
  219. /**
  220.  * Called by glDrawBuffer().
  221.  * Specify which renderbuffer(s) to draw into for the first color output.
  222.  * <buffer> can name zero, one, two or four renderbuffers!
  223.  * \sa _mesa_DrawBuffers
  224.  *
  225.  * \param buffer  buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc.
  226.  *
  227.  * Note that the behaviour of this function depends on whether the
  228.  * current ctx->DrawBuffer is a window-system framebuffer or a user-created
  229.  * framebuffer object.
  230.  *   In the former case, we update the per-context ctx->Color.DrawBuffer
  231.  *   state var _and_ the FB's ColorDrawBuffer state.
  232.  *   In the later case, we update the FB's ColorDrawBuffer state only.
  233.  *
  234.  * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the
  235.  * new FB is a window system FB, we need to re-update the FB's
  236.  * ColorDrawBuffer state to match the context.  This is handled in
  237.  * _mesa_update_framebuffer().
  238.  *
  239.  * See the GL_EXT_framebuffer_object spec for more info.
  240.  */
  241. void GLAPIENTRY
  242. _mesa_DrawBuffer(GLenum buffer)
  243. {
  244.    GLbitfield destMask;
  245.    GET_CURRENT_CONTEXT(ctx);
  246.  
  247.    FLUSH_VERTICES(ctx, 0);
  248.  
  249.    if (MESA_VERBOSE & VERBOSE_API) {
  250.       _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
  251.    }
  252.  
  253.    if (buffer == GL_NONE) {
  254.       destMask = 0x0;
  255.    }
  256.    else {
  257.       const GLbitfield supportedMask
  258.          = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
  259.       destMask = draw_buffer_enum_to_bitmask(ctx, buffer);
  260.       if (destMask == BAD_MASK) {
  261.          /* totally bogus buffer */
  262.          _mesa_error(ctx, GL_INVALID_ENUM,
  263.                      "glDrawBuffer(buffer=0x%x)", buffer);
  264.          return;
  265.       }
  266.       destMask &= supportedMask;
  267.       if (destMask == 0x0) {
  268.          /* none of the named color buffers exist! */
  269.          _mesa_error(ctx, GL_INVALID_OPERATION,
  270.                      "glDrawBuffer(buffer=0x%x)", buffer);
  271.          return;
  272.       }
  273.    }
  274.  
  275.    /* if we get here, there's no error so set new state */
  276.    _mesa_drawbuffers(ctx, 1, &buffer, &destMask);
  277.  
  278.    /*
  279.     * Call device driver function.
  280.     */
  281.    if (ctx->Driver.DrawBuffers)
  282.       ctx->Driver.DrawBuffers(ctx, 1, &buffer);
  283.    else if (ctx->Driver.DrawBuffer)
  284.       ctx->Driver.DrawBuffer(ctx, buffer);
  285. }
  286.  
  287.  
  288. /**
  289.  * Called by glDrawBuffersARB; specifies the destination color renderbuffers
  290.  * for N fragment program color outputs.
  291.  * \sa _mesa_DrawBuffer
  292.  * \param n  number of outputs
  293.  * \param buffers  array [n] of renderbuffer names.  Unlike glDrawBuffer, the
  294.  *                 names cannot specify more than one buffer.  For example,
  295.  *                 GL_FRONT_AND_BACK is illegal.
  296.  */
  297. void GLAPIENTRY
  298. _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
  299. {
  300.    GLint output;
  301.    GLbitfield usedBufferMask, supportedMask;
  302.    GLbitfield destMask[MAX_DRAW_BUFFERS];
  303.    GET_CURRENT_CONTEXT(ctx);
  304.  
  305.    FLUSH_VERTICES(ctx, 0);
  306.  
  307.    /* Turns out n==0 is a valid input that should not produce an error.
  308.     * The remaining code below correctly handles the n==0 case.
  309.     *
  310.     * From the OpenGL 3.0 specification, page 258:
  311.     * "An INVALID_VALUE error is generated if n is greater than
  312.     *  MAX_DRAW_BUFFERS."
  313.     */
  314.    if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
  315.       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
  316.       return;
  317.    }
  318.  
  319.    supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
  320.    usedBufferMask = 0x0;
  321.  
  322.    /* From the ES 3.0 specification, page 180:
  323.     * "If the GL is bound to the default framebuffer, then n must be 1
  324.     *  and the constant must be BACK or NONE."
  325.     */
  326.    if (_mesa_is_gles3(ctx) && _mesa_is_winsys_fbo(ctx->DrawBuffer) &&
  327.        (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) {
  328.       _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
  329.       return;
  330.    }
  331.  
  332.    /* complicated error checking... */
  333.    for (output = 0; output < n; output++) {
  334.       if (buffers[output] == GL_NONE) {
  335.          destMask[output] = 0x0;
  336.       }
  337.       else {
  338.          /* Page 259 (page 275 of the PDF) in section 4.2.1 of the OpenGL 3.0
  339.           * spec (20080923) says:
  340.           *
  341.           *     "If the GL is bound to a framebuffer object and DrawBuffers is
  342.           *     supplied with [...] COLOR_ATTACHMENTm where m is greater than
  343.           *     or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
  344.           *     INVALID_OPERATION results."
  345.           */
  346.          if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >=
  347.              GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) {
  348.             _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)");
  349.             return;
  350.          }
  351.  
  352.          destMask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);
  353.  
  354.          /* From the OpenGL 3.0 specification, page 258:
  355.           * "Each buffer listed in bufs must be one of the values from tables
  356.           *  4.5 or 4.6.  Otherwise, an INVALID_ENUM error is generated.
  357.           */
  358.          if (destMask[output] == BAD_MASK) {
  359.             _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
  360.             return;
  361.          }        
  362.  
  363.          /* From the OpenGL 3.0 specification, page 259:
  364.           * "For both the default framebuffer and framebuffer objects, the
  365.           *  constants FRONT, BACK, LEFT, RIGHT, and FRONT_AND_BACK are not
  366.           *  valid in the bufs array passed to DrawBuffers, and will result in
  367.           *  the error INVALID_OPERATION.  This restriction is because these
  368.           *  constants may themselves refer to multiple buffers, as shown in
  369.           *  table 4.4."
  370.           */
  371.          if (_mesa_bitcount(destMask[output]) > 1) {
  372.             _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)");
  373.             return;
  374.          }
  375.  
  376.          /* From the OpenGL 3.0 specification, page 259:
  377.           * "If the GL is bound to the default framebuffer and DrawBuffers is
  378.           *  supplied with a constant (other than NONE) that does not indicate
  379.           *  any of the color buffers allocated to the GL context by the window
  380.           *  system, the error INVALID_OPERATION will be generated.
  381.           *
  382.           *  If the GL is bound to a framebuffer object and DrawBuffers is
  383.           *  supplied with a constant from table 4.6 [...] then the error
  384.           *  INVALID_OPERATION results."
  385.           */
  386.          destMask[output] &= supportedMask;
  387.          if (destMask[output] == 0) {
  388.             _mesa_error(ctx, GL_INVALID_OPERATION,
  389.                         "glDrawBuffersARB(unsupported buffer)");
  390.             return;
  391.          }
  392.  
  393.          /* ES 3.0 is even more restrictive.  From the ES 3.0 spec, page 180:
  394.           * "If the GL is bound to a framebuffer object, the ith buffer listed
  395.           *  in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION."
  396.           */
  397.          if (_mesa_is_gles3(ctx) && _mesa_is_user_fbo(ctx->DrawBuffer) &&
  398.              buffers[output] != GL_NONE &&
  399.              buffers[output] != GL_COLOR_ATTACHMENT0 + output) {
  400.             _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
  401.             return;
  402.          }
  403.  
  404.          /* From the OpenGL 3.0 specification, page 258:
  405.           * "Except for NONE, a buffer may not appear more than once in the
  406.           *  array pointed to by bufs.  Specifying a buffer more then once will
  407.           *  result in the error INVALID_OPERATION."
  408.           */
  409.          if (destMask[output] & usedBufferMask) {
  410.             _mesa_error(ctx, GL_INVALID_OPERATION,
  411.                         "glDrawBuffersARB(duplicated buffer)");
  412.             return;
  413.          }
  414.  
  415.          /* update bitmask */
  416.          usedBufferMask |= destMask[output];
  417.       }
  418.    }
  419.  
  420.    /* OK, if we get here, there were no errors so set the new state */
  421.    _mesa_drawbuffers(ctx, n, buffers, destMask);
  422.  
  423.    /*
  424.     * Call device driver function.  Note that n can be equal to 0,
  425.     * in which case we don't want to reference buffers[0], which
  426.     * may not be valid.
  427.     */
  428.    if (ctx->Driver.DrawBuffers)
  429.       ctx->Driver.DrawBuffers(ctx, n, buffers);
  430.    else if (ctx->Driver.DrawBuffer)
  431.       ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE);
  432. }
  433.  
  434.  
  435. /**
  436.  * Performs necessary state updates when _mesa_drawbuffers makes an
  437.  * actual change.
  438.  */
  439. static void
  440. updated_drawbuffers(struct gl_context *ctx)
  441. {
  442.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  443.  
  444.    if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) {
  445.       struct gl_framebuffer *fb = ctx->DrawBuffer;
  446.  
  447.       /* Flag the FBO as requiring validation. */
  448.       if (_mesa_is_user_fbo(fb)) {
  449.          fb->_Status = 0;
  450.       }
  451.    }
  452. }
  453.  
  454.  
  455. /**
  456.  * Helper function to set the GL_DRAW_BUFFER state in the context and
  457.  * current FBO.  Called via glDrawBuffer(), glDrawBuffersARB()
  458.  *
  459.  * All error checking will have been done prior to calling this function
  460.  * so nothing should go wrong at this point.
  461.  *
  462.  * \param ctx  current context
  463.  * \param n    number of color outputs to set
  464.  * \param buffers  array[n] of colorbuffer names, like GL_LEFT.
  465.  * \param destMask  array[n] of BUFFER_BIT_* bitmasks which correspond to the
  466.  *                  colorbuffer names.  (i.e. GL_FRONT_AND_BACK =>
  467.  *                  BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
  468.  */
  469. void
  470. _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
  471.                   const GLbitfield *destMask)
  472. {
  473.    struct gl_framebuffer *fb = ctx->DrawBuffer;
  474.    GLbitfield mask[MAX_DRAW_BUFFERS];
  475.    GLuint buf;
  476.  
  477.    if (!destMask) {
  478.       /* compute destMask values now */
  479.       const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb);
  480.       GLuint output;
  481.       for (output = 0; output < n; output++) {
  482.          mask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);
  483.          ASSERT(mask[output] != BAD_MASK);
  484.          mask[output] &= supportedMask;
  485.       }
  486.       destMask = mask;
  487.    }
  488.  
  489.    /*
  490.     * If n==1, destMask[0] may have up to four bits set.
  491.     * Otherwise, destMask[x] can only have one bit set.
  492.     */
  493.    if (n == 1) {
  494.       GLuint count = 0, destMask0 = destMask[0];
  495.       while (destMask0) {
  496.          GLint bufIndex = ffs(destMask0) - 1;
  497.          if (fb->_ColorDrawBufferIndexes[count] != bufIndex) {
  498.             updated_drawbuffers(ctx);
  499.             fb->_ColorDrawBufferIndexes[count] = bufIndex;
  500.          }
  501.          count++;
  502.          destMask0 &= ~(1 << bufIndex);
  503.       }
  504.       fb->ColorDrawBuffer[0] = buffers[0];
  505.       fb->_NumColorDrawBuffers = count;
  506.    }
  507.    else {
  508.       GLuint count = 0;
  509.       for (buf = 0; buf < n; buf++ ) {
  510.          if (destMask[buf]) {
  511.             GLint bufIndex = ffs(destMask[buf]) - 1;
  512.             /* only one bit should be set in the destMask[buf] field */
  513.             ASSERT(_mesa_bitcount(destMask[buf]) == 1);
  514.             if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) {
  515.                updated_drawbuffers(ctx);
  516.                fb->_ColorDrawBufferIndexes[buf] = bufIndex;
  517.             }
  518.             count = buf + 1;
  519.          }
  520.          else {
  521.             if (fb->_ColorDrawBufferIndexes[buf] != -1) {
  522.                updated_drawbuffers(ctx);
  523.                fb->_ColorDrawBufferIndexes[buf] = -1;
  524.             }
  525.          }
  526.          fb->ColorDrawBuffer[buf] = buffers[buf];
  527.       }
  528.       fb->_NumColorDrawBuffers = count;
  529.    }
  530.  
  531.    /* set remaining outputs to -1 (GL_NONE) */
  532.    for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) {
  533.       if (fb->_ColorDrawBufferIndexes[buf] != -1) {
  534.          updated_drawbuffers(ctx);
  535.          fb->_ColorDrawBufferIndexes[buf] = -1;
  536.       }
  537.    }
  538.    for (buf = n; buf < ctx->Const.MaxDrawBuffers; buf++) {
  539.       fb->ColorDrawBuffer[buf] = GL_NONE;
  540.    }
  541.  
  542.    if (_mesa_is_winsys_fbo(fb)) {
  543.       /* also set context drawbuffer state */
  544.       for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
  545.          if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) {
  546.             updated_drawbuffers(ctx);
  547.             ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
  548.          }
  549.       }
  550.    }
  551. }
  552.  
  553.  
  554. /**
  555.  * Update the current drawbuffer's _ColorDrawBufferIndex[] list, etc.
  556.  * from the context's Color.DrawBuffer[] state.
  557.  * Use when changing contexts.
  558.  */
  559. void
  560. _mesa_update_draw_buffers(struct gl_context *ctx)
  561. {
  562.    GLenum buffers[MAX_DRAW_BUFFERS];
  563.    GLuint i;
  564.  
  565.    /* should be a window system FBO */
  566.    assert(_mesa_is_winsys_fbo(ctx->DrawBuffer));
  567.  
  568.    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++)
  569.       buffers[i] = ctx->Color.DrawBuffer[i];
  570.  
  571.    _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL);
  572. }
  573.  
  574.  
  575. /**
  576.  * Like \sa _mesa_drawbuffers(), this is a helper function for setting
  577.  * GL_READ_BUFFER state in the context and current FBO.
  578.  * \param ctx  the rendering context
  579.  * \param buffer  GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc.
  580.  * \param bufferIndex  the numerical index corresponding to 'buffer'
  581.  */
  582. void
  583. _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex)
  584. {
  585.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  586.  
  587.    if (_mesa_is_winsys_fbo(fb)) {
  588.       /* Only update the per-context READ_BUFFER state if we're bound to
  589.        * a window-system framebuffer.
  590.        */
  591.       ctx->Pixel.ReadBuffer = buffer;
  592.    }
  593.  
  594.    fb->ColorReadBuffer = buffer;
  595.    fb->_ColorReadBufferIndex = bufferIndex;
  596.  
  597.    ctx->NewState |= _NEW_BUFFERS;
  598. }
  599.  
  600.  
  601.  
  602. /**
  603.  * Called by glReadBuffer to set the source renderbuffer for reading pixels.
  604.  * \param mode color buffer such as GL_FRONT, GL_BACK, etc.
  605.  */
  606. void GLAPIENTRY
  607. _mesa_ReadBuffer(GLenum buffer)
  608. {
  609.    struct gl_framebuffer *fb;
  610.    GLbitfield supportedMask;
  611.    GLint srcBuffer;
  612.    GET_CURRENT_CONTEXT(ctx);
  613.  
  614.    FLUSH_VERTICES(ctx, 0);
  615.  
  616.    if (MESA_VERBOSE & VERBOSE_API)
  617.       _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
  618.  
  619.    fb = ctx->ReadBuffer;
  620.  
  621.    if (MESA_VERBOSE & VERBOSE_API)
  622.       _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
  623.  
  624.    if (buffer == GL_NONE) {
  625.       /* This is legal--it means that no buffer should be bound for reading. */
  626.       srcBuffer = -1;
  627.    }
  628.    else {
  629.       /* general case / window-system framebuffer */
  630.       srcBuffer = read_buffer_enum_to_index(buffer);
  631.       if (srcBuffer == -1) {
  632.          _mesa_error(ctx, GL_INVALID_ENUM,
  633.                      "glReadBuffer(buffer=0x%x)", buffer);
  634.          return;
  635.       }
  636.       supportedMask = supported_buffer_bitmask(ctx, fb);
  637.       if (((1 << srcBuffer) & supportedMask) == 0) {
  638.          _mesa_error(ctx, GL_INVALID_OPERATION,
  639.                      "glReadBuffer(buffer=0x%x)", buffer);
  640.          return;
  641.       }
  642.    }
  643.  
  644.    /* OK, all error checking has been completed now */
  645.  
  646.    _mesa_readbuffer(ctx, buffer, srcBuffer);
  647.  
  648.    /*
  649.     * Call device driver function.
  650.     */
  651.    if (ctx->Driver.ReadBuffer)
  652.       (*ctx->Driver.ReadBuffer)(ctx, buffer);
  653. }
  654.