Home | History | Annotate | Download | only in main
      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 clear.c
     28  * glClearColor, glClearIndex, glClear() functions.
     29  */
     30 
     31 
     32 
     33 #include "glheader.h"
     34 #include "clear.h"
     35 #include "context.h"
     36 #include "enums.h"
     37 #include "fbobject.h"
     38 #include "get.h"
     39 #include "macros.h"
     40 #include "mtypes.h"
     41 #include "state.h"
     42 
     43 
     44 
     45 void GLAPIENTRY
     46 _mesa_ClearIndex( GLfloat c )
     47 {
     48    GET_CURRENT_CONTEXT(ctx);
     49 
     50    ctx->Color.ClearIndex = (GLuint) c;
     51 }
     52 
     53 
     54 /**
     55  * Specify the clear values for the color buffers.
     56  *
     57  * \param red red color component.
     58  * \param green green color component.
     59  * \param blue blue color component.
     60  * \param alpha alpha component.
     61  *
     62  * \sa glClearColor().
     63  */
     64 void GLAPIENTRY
     65 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
     66 {
     67    GET_CURRENT_CONTEXT(ctx);
     68 
     69    ctx->Color.ClearColor.f[0] = red;
     70    ctx->Color.ClearColor.f[1] = green;
     71    ctx->Color.ClearColor.f[2] = blue;
     72    ctx->Color.ClearColor.f[3] = alpha;
     73 }
     74 
     75 
     76 /**
     77  * GL_EXT_texture_integer
     78  */
     79 void GLAPIENTRY
     80 _mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
     81 {
     82    GET_CURRENT_CONTEXT(ctx);
     83 
     84    ctx->Color.ClearColor.i[0] = r;
     85    ctx->Color.ClearColor.i[1] = g;
     86    ctx->Color.ClearColor.i[2] = b;
     87    ctx->Color.ClearColor.i[3] = a;
     88 }
     89 
     90 
     91 /**
     92  * GL_EXT_texture_integer
     93  */
     94 void GLAPIENTRY
     95 _mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
     96 {
     97    GET_CURRENT_CONTEXT(ctx);
     98 
     99    ctx->Color.ClearColor.ui[0] = r;
    100    ctx->Color.ClearColor.ui[1] = g;
    101    ctx->Color.ClearColor.ui[2] = b;
    102    ctx->Color.ClearColor.ui[3] = a;
    103 }
    104 
    105 
    106 /**
    107  * Returns true if color writes are enabled for the given color attachment.
    108  *
    109  * Beyond checking ColorMask, this uses _mesa_format_has_color_component to
    110  * ignore components that don't actually exist in the format (such as X in
    111  * XRGB).
    112  */
    113 static bool
    114 color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx)
    115 {
    116    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx];
    117    GLuint c;
    118    GLubyte colorMask = 0;
    119 
    120    if (rb) {
    121       for (c = 0; c < 4; c++) {
    122          if (_mesa_format_has_color_component(rb->Format, c))
    123             colorMask |= ctx->Color.ColorMask[idx][c];
    124       }
    125    }
    126 
    127    return colorMask != 0;
    128 }
    129 
    130 
    131 /**
    132  * Clear buffers.
    133  *
    134  * \param mask bit-mask indicating the buffers to be cleared.
    135  *
    136  * Flushes the vertices and verifies the parameter.
    137  * If __struct gl_contextRec::NewState is set then calls _mesa_update_state()
    138  * to update gl_frame_buffer::_Xmin, etc.  If the rasterization mode is set to
    139  * GL_RENDER then requests the driver to clear the buffers, via the
    140  * dd_function_table::Clear callback.
    141  */
    142 void GLAPIENTRY
    143 _mesa_Clear( GLbitfield mask )
    144 {
    145    GET_CURRENT_CONTEXT(ctx);
    146    FLUSH_VERTICES(ctx, 0);
    147 
    148    FLUSH_CURRENT(ctx, 0);
    149 
    150    if (MESA_VERBOSE & VERBOSE_API)
    151       _mesa_debug(ctx, "glClear 0x%x\n", mask);
    152 
    153    if (mask & ~(GL_COLOR_BUFFER_BIT |
    154                 GL_DEPTH_BUFFER_BIT |
    155                 GL_STENCIL_BUFFER_BIT |
    156                 GL_ACCUM_BUFFER_BIT)) {
    157       /* invalid bit set */
    158       _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
    159       return;
    160    }
    161 
    162    /* Accumulation buffers were removed in core contexts, and they never
    163     * existed in OpenGL ES.
    164     */
    165    if ((mask & GL_ACCUM_BUFFER_BIT) != 0
    166        && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) {
    167       _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)");
    168       return;
    169    }
    170 
    171    if (ctx->NewState) {
    172       _mesa_update_state( ctx );	/* update _Xmin, etc */
    173    }
    174 
    175    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
    176       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
    177                   "glClear(incomplete framebuffer)");
    178       return;
    179    }
    180 
    181    if (ctx->RasterDiscard)
    182       return;
    183 
    184    if (ctx->RenderMode == GL_RENDER) {
    185       GLbitfield bufferMask;
    186 
    187       /* don't clear depth buffer if depth writing disabled */
    188       if (!ctx->Depth.Mask)
    189          mask &= ~GL_DEPTH_BUFFER_BIT;
    190 
    191       /* Build the bitmask to send to device driver's Clear function.
    192        * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
    193        * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
    194        * BUFFER_BIT_COLORn flags.
    195        */
    196       bufferMask = 0;
    197       if (mask & GL_COLOR_BUFFER_BIT) {
    198          GLuint i;
    199          for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
    200             GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
    201 
    202             if (buf >= 0 && color_buffer_writes_enabled(ctx, i)) {
    203                bufferMask |= 1 << buf;
    204             }
    205          }
    206       }
    207 
    208       if ((mask & GL_DEPTH_BUFFER_BIT)
    209           && ctx->DrawBuffer->Visual.haveDepthBuffer) {
    210          bufferMask |= BUFFER_BIT_DEPTH;
    211       }
    212 
    213       if ((mask & GL_STENCIL_BUFFER_BIT)
    214           && ctx->DrawBuffer->Visual.haveStencilBuffer) {
    215          bufferMask |= BUFFER_BIT_STENCIL;
    216       }
    217 
    218       if ((mask & GL_ACCUM_BUFFER_BIT)
    219           && ctx->DrawBuffer->Visual.haveAccumBuffer) {
    220          bufferMask |= BUFFER_BIT_ACCUM;
    221       }
    222 
    223       assert(ctx->Driver.Clear);
    224       ctx->Driver.Clear(ctx, bufferMask);
    225    }
    226 }
    227 
    228 
    229 /** Returned by make_color_buffer_mask() for errors */
    230 #define INVALID_MASK ~0x0U
    231 
    232 
    233 /**
    234  * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
    235  * BUFFER_BIT_x values.
    236  * Return INVALID_MASK if the drawbuffer value is invalid.
    237  */
    238 static GLbitfield
    239 make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
    240 {
    241    const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
    242    GLbitfield mask = 0x0;
    243 
    244    /* From the GL 4.0 specification:
    245     *	If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is
    246     *	specified by passing i as the parameter drawbuffer, and value
    247     *	points to a four-element vector specifying the R, G, B, and A
    248     *	color to clear that draw buffer to. If the draw buffer is one
    249     *	of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying
    250     *	multiple buffers, each selected buffer is cleared to the same
    251     *	value.
    252     *
    253     * Note that "drawbuffer" and "draw buffer" have different meaning.
    254     * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's
    255     * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK,
    256     * etc.
    257     */
    258    if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
    259       return INVALID_MASK;
    260    }
    261 
    262    switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) {
    263    case GL_FRONT:
    264       if (att[BUFFER_FRONT_LEFT].Renderbuffer)
    265          mask |= BUFFER_BIT_FRONT_LEFT;
    266       if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
    267          mask |= BUFFER_BIT_FRONT_RIGHT;
    268       break;
    269    case GL_BACK:
    270       /* For GLES contexts with a single buffered configuration, we actually
    271        * only have a front renderbuffer, so any clear calls to GL_BACK should
    272        * affect that buffer. See draw_buffer_enum_to_bitmask for details.
    273        */
    274       if (_mesa_is_gles(ctx))
    275          if (!ctx->DrawBuffer->Visual.doubleBufferMode)
    276             if (att[BUFFER_FRONT_LEFT].Renderbuffer)
    277                mask |= BUFFER_BIT_FRONT_LEFT;
    278       if (att[BUFFER_BACK_LEFT].Renderbuffer)
    279          mask |= BUFFER_BIT_BACK_LEFT;
    280       if (att[BUFFER_BACK_RIGHT].Renderbuffer)
    281          mask |= BUFFER_BIT_BACK_RIGHT;
    282       break;
    283    case GL_LEFT:
    284       if (att[BUFFER_FRONT_LEFT].Renderbuffer)
    285          mask |= BUFFER_BIT_FRONT_LEFT;
    286       if (att[BUFFER_BACK_LEFT].Renderbuffer)
    287          mask |= BUFFER_BIT_BACK_LEFT;
    288       break;
    289    case GL_RIGHT:
    290       if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
    291          mask |= BUFFER_BIT_FRONT_RIGHT;
    292       if (att[BUFFER_BACK_RIGHT].Renderbuffer)
    293          mask |= BUFFER_BIT_BACK_RIGHT;
    294       break;
    295    case GL_FRONT_AND_BACK:
    296       if (att[BUFFER_FRONT_LEFT].Renderbuffer)
    297          mask |= BUFFER_BIT_FRONT_LEFT;
    298       if (att[BUFFER_BACK_LEFT].Renderbuffer)
    299          mask |= BUFFER_BIT_BACK_LEFT;
    300       if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
    301          mask |= BUFFER_BIT_FRONT_RIGHT;
    302       if (att[BUFFER_BACK_RIGHT].Renderbuffer)
    303          mask |= BUFFER_BIT_BACK_RIGHT;
    304       break;
    305    default:
    306       {
    307          GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer];
    308 
    309          if (buf >= 0 && att[buf].Renderbuffer) {
    310             mask |= 1 << buf;
    311          }
    312       }
    313    }
    314 
    315    return mask;
    316 }
    317 
    318 
    319 
    320 /**
    321  * New in GL 3.0
    322  * Clear signed integer color buffer or stencil buffer (not depth).
    323  */
    324 void GLAPIENTRY
    325 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
    326 {
    327    GET_CURRENT_CONTEXT(ctx);
    328    FLUSH_VERTICES(ctx, 0);
    329 
    330    FLUSH_CURRENT(ctx, 0);
    331 
    332    if (ctx->NewState) {
    333       _mesa_update_state( ctx );
    334    }
    335 
    336    switch (buffer) {
    337    case GL_STENCIL:
    338       /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
    339        *
    340        *     "ClearBuffer generates an INVALID VALUE error if buffer is
    341        *     COLOR and drawbuffer is less than zero, or greater than the
    342        *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
    343        *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
    344        */
    345       if (drawbuffer != 0) {
    346          _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
    347                      drawbuffer);
    348          return;
    349       }
    350       else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer
    351                && !ctx->RasterDiscard) {
    352          /* Save current stencil clear value, set to 'value', do the
    353           * stencil clear and restore the clear value.
    354           * XXX in the future we may have a new ctx->Driver.ClearBuffer()
    355           * hook instead.
    356           */
    357          const GLuint clearSave = ctx->Stencil.Clear;
    358          ctx->Stencil.Clear = *value;
    359          ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
    360          ctx->Stencil.Clear = clearSave;
    361       }
    362       break;
    363    case GL_COLOR:
    364       {
    365          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
    366          if (mask == INVALID_MASK) {
    367             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
    368                         drawbuffer);
    369             return;
    370          }
    371          else if (mask && !ctx->RasterDiscard) {
    372             union gl_color_union clearSave;
    373 
    374             /* save color */
    375             clearSave = ctx->Color.ClearColor;
    376             /* set color */
    377             COPY_4V(ctx->Color.ClearColor.i, value);
    378             /* clear buffer(s) */
    379             ctx->Driver.Clear(ctx, mask);
    380             /* restore color */
    381             ctx->Color.ClearColor = clearSave;
    382          }
    383       }
    384       break;
    385    default:
    386       /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
    387        * of the OpenGL 4.5 spec states:
    388        *
    389        *    "An INVALID_ENUM error is generated by ClearBufferiv and
    390        *     ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
    391        */
    392       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
    393                   _mesa_enum_to_string(buffer));
    394       return;
    395    }
    396 }
    397 
    398 
    399 /**
    400  * The ClearBuffer framework is so complicated and so riddled with the
    401  * assumption that the framebuffer is bound that, for now, we will just fake
    402  * direct state access clearing for the user.
    403  */
    404 void GLAPIENTRY
    405 _mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
    406                               GLint drawbuffer, const GLint *value)
    407 {
    408    GLint oldfb;
    409 
    410    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
    411    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    412    _mesa_ClearBufferiv(buffer, drawbuffer, value);
    413    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
    414 }
    415 
    416 
    417 /**
    418  * New in GL 3.0
    419  * Clear unsigned integer color buffer (not depth, not stencil).
    420  */
    421 void GLAPIENTRY
    422 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
    423 {
    424    GET_CURRENT_CONTEXT(ctx);
    425 
    426    FLUSH_VERTICES(ctx, 0);
    427    FLUSH_CURRENT(ctx, 0);
    428 
    429    if (ctx->NewState) {
    430       _mesa_update_state( ctx );
    431    }
    432 
    433    switch (buffer) {
    434    case GL_COLOR:
    435       {
    436          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
    437          if (mask == INVALID_MASK) {
    438             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
    439                         drawbuffer);
    440             return;
    441          }
    442          else if (mask && !ctx->RasterDiscard) {
    443             union gl_color_union clearSave;
    444 
    445             /* save color */
    446             clearSave = ctx->Color.ClearColor;
    447             /* set color */
    448             COPY_4V(ctx->Color.ClearColor.ui, value);
    449             /* clear buffer(s) */
    450             ctx->Driver.Clear(ctx, mask);
    451             /* restore color */
    452             ctx->Color.ClearColor = clearSave;
    453          }
    454       }
    455       break;
    456    default:
    457       /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
    458        * of the OpenGL 4.5 spec states:
    459        *
    460        *    "An INVALID_ENUM error is generated by ClearBufferuiv and
    461        *     ClearNamedFramebufferuiv if buffer is not COLOR."
    462        */
    463       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
    464                   _mesa_enum_to_string(buffer));
    465       return;
    466    }
    467 }
    468 
    469 
    470 /**
    471  * The ClearBuffer framework is so complicated and so riddled with the
    472  * assumption that the framebuffer is bound that, for now, we will just fake
    473  * direct state access clearing for the user.
    474  */
    475 void GLAPIENTRY
    476 _mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
    477                                GLint drawbuffer, const GLuint *value)
    478 {
    479    GLint oldfb;
    480 
    481    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
    482    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    483    _mesa_ClearBufferuiv(buffer, drawbuffer, value);
    484    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
    485 }
    486 
    487 
    488 /**
    489  * New in GL 3.0
    490  * Clear fixed-pt or float color buffer or depth buffer (not stencil).
    491  */
    492 void GLAPIENTRY
    493 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
    494 {
    495    GET_CURRENT_CONTEXT(ctx);
    496 
    497    FLUSH_VERTICES(ctx, 0);
    498    FLUSH_CURRENT(ctx, 0);
    499 
    500    if (ctx->NewState) {
    501       _mesa_update_state( ctx );
    502    }
    503 
    504    switch (buffer) {
    505    case GL_DEPTH:
    506       /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
    507        *
    508        *     "ClearBuffer generates an INVALID VALUE error if buffer is
    509        *     COLOR and drawbuffer is less than zero, or greater than the
    510        *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
    511        *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
    512        */
    513       if (drawbuffer != 0) {
    514          _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
    515                      drawbuffer);
    516          return;
    517       }
    518       else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer
    519                && !ctx->RasterDiscard) {
    520          /* Save current depth clear value, set to 'value', do the
    521           * depth clear and restore the clear value.
    522           * XXX in the future we may have a new ctx->Driver.ClearBuffer()
    523           * hook instead.
    524           */
    525          const GLclampd clearSave = ctx->Depth.Clear;
    526          ctx->Depth.Clear = *value;
    527          ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
    528          ctx->Depth.Clear = clearSave;
    529       }
    530       /* clear depth buffer to value */
    531       break;
    532    case GL_COLOR:
    533       {
    534          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
    535          if (mask == INVALID_MASK) {
    536             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
    537                         drawbuffer);
    538             return;
    539          }
    540          else if (mask && !ctx->RasterDiscard) {
    541             union gl_color_union clearSave;
    542 
    543             /* save color */
    544             clearSave = ctx->Color.ClearColor;
    545             /* set color */
    546             COPY_4V(ctx->Color.ClearColor.f, value);
    547             /* clear buffer(s) */
    548             ctx->Driver.Clear(ctx, mask);
    549             /* restore color */
    550             ctx->Color.ClearColor = clearSave;
    551          }
    552       }
    553       break;
    554    default:
    555       /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
    556        * of the OpenGL 4.5 spec states:
    557        *
    558        *    "An INVALID_ENUM error is generated by ClearBufferfv and
    559        *     ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
    560        */
    561       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
    562                   _mesa_enum_to_string(buffer));
    563       return;
    564    }
    565 }
    566 
    567 
    568 /**
    569  * The ClearBuffer framework is so complicated and so riddled with the
    570  * assumption that the framebuffer is bound that, for now, we will just fake
    571  * direct state access clearing for the user.
    572  */
    573 void GLAPIENTRY
    574 _mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
    575                               GLint drawbuffer, const GLfloat *value)
    576 {
    577    GLint oldfb;
    578 
    579    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
    580    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    581    _mesa_ClearBufferfv(buffer, drawbuffer, value);
    582    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
    583 }
    584 
    585 
    586 /**
    587  * New in GL 3.0
    588  * Clear depth/stencil buffer only.
    589  */
    590 void GLAPIENTRY
    591 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
    592                     GLfloat depth, GLint stencil)
    593 {
    594    GET_CURRENT_CONTEXT(ctx);
    595    GLbitfield mask = 0;
    596 
    597    FLUSH_VERTICES(ctx, 0);
    598    FLUSH_CURRENT(ctx, 0);
    599 
    600    if (buffer != GL_DEPTH_STENCIL) {
    601       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
    602                   _mesa_enum_to_string(buffer));
    603       return;
    604    }
    605 
    606    /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
    607     *
    608     *     "ClearBuffer generates an INVALID VALUE error if buffer is
    609     *     COLOR and drawbuffer is less than zero, or greater than the
    610     *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
    611     *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
    612     */
    613    if (drawbuffer != 0) {
    614       _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
    615                   drawbuffer);
    616       return;
    617    }
    618 
    619    if (ctx->RasterDiscard)
    620       return;
    621 
    622    if (ctx->NewState) {
    623       _mesa_update_state( ctx );
    624    }
    625 
    626    if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
    627       mask |= BUFFER_BIT_DEPTH;
    628    if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
    629       mask |= BUFFER_BIT_STENCIL;
    630 
    631    if (mask) {
    632       /* save current clear values */
    633       const GLclampd clearDepthSave = ctx->Depth.Clear;
    634       const GLuint clearStencilSave = ctx->Stencil.Clear;
    635 
    636       /* set new clear values */
    637       ctx->Depth.Clear = depth;
    638       ctx->Stencil.Clear = stencil;
    639 
    640       /* clear buffers */
    641       ctx->Driver.Clear(ctx, mask);
    642 
    643       /* restore */
    644       ctx->Depth.Clear = clearDepthSave;
    645       ctx->Stencil.Clear = clearStencilSave;
    646    }
    647 }
    648 
    649 
    650 /**
    651  * The ClearBuffer framework is so complicated and so riddled with the
    652  * assumption that the framebuffer is bound that, for now, we will just fake
    653  * direct state access clearing for the user.
    654  */
    655 void GLAPIENTRY
    656 _mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
    657                               GLint drawbuffer, GLfloat depth, GLint stencil)
    658 {
    659    GLint oldfb;
    660 
    661    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
    662    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    663    _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil);
    664    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
    665 }
    666