Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2008  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 #include "main/glheader.h"
     26 #include "main/accum.h"
     27 #include "main/condrender.h"
     28 #include "main/format_pack.h"
     29 #include "main/macros.h"
     30 #include "main/imports.h"
     31 #include "main/mtypes.h"
     32 
     33 #include "s_context.h"
     34 #include "s_depth.h"
     35 #include "s_stencil.h"
     36 
     37 
     38 
     39 /**
     40  * Clear an rgba color buffer with masking if needed.
     41  */
     42 static void
     43 clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
     44                   const GLubyte colorMask[4])
     45 {
     46    const GLint x = ctx->DrawBuffer->_Xmin;
     47    const GLint y = ctx->DrawBuffer->_Ymin;
     48    const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
     49    const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
     50    const GLuint pixelSize = _mesa_get_format_bytes(rb->Format);
     51    const GLboolean doMasking = (colorMask[0] == 0 ||
     52                                 colorMask[1] == 0 ||
     53                                 colorMask[2] == 0 ||
     54                                 colorMask[3] == 0);
     55    const GLfloat (*clearColor)[4] =
     56       (const GLfloat (*)[4]) ctx->Color.ClearColor.f;
     57    GLbitfield mapMode = GL_MAP_WRITE_BIT;
     58    GLubyte *map;
     59    GLint rowStride;
     60    GLint i, j;
     61 
     62    if (doMasking) {
     63       /* we'll need to read buffer values too */
     64       mapMode |= GL_MAP_READ_BIT;
     65    }
     66 
     67    /* map dest buffer */
     68    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
     69                                mapMode, &map, &rowStride);
     70    if (!map) {
     71       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
     72       return;
     73    }
     74 
     75    /* for 1, 2, 4-byte clearing */
     76 #define SIMPLE_TYPE_CLEAR(TYPE)                                         \
     77    do {                                                                 \
     78       TYPE pixel, pixelMask;                                            \
     79       _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel);     \
     80       if (doMasking) {                                                  \
     81          _mesa_pack_colormask(rb->Format, colorMask, &pixelMask);       \
     82          pixel &= pixelMask;                                            \
     83          pixelMask = ~pixelMask;                                        \
     84       }                                                                 \
     85       for (i = 0; i < height; i++) {                                    \
     86          TYPE *row = (TYPE *) map;                                      \
     87          if (doMasking) {                                               \
     88             for (j = 0; j < width; j++) {                               \
     89                row[j] = (row[j] & pixelMask) | pixel;                   \
     90             }                                                           \
     91          }                                                              \
     92          else {                                                         \
     93             for (j = 0; j < width; j++) {                               \
     94                row[j] = pixel;                                          \
     95             }                                                           \
     96          }                                                              \
     97          map += rowStride;                                              \
     98       }                                                                 \
     99    } while (0)
    100 
    101 
    102    /* for 3, 6, 8, 12, 16-byte clearing */
    103 #define MULTI_WORD_CLEAR(TYPE, N)                                       \
    104    do {                                                                 \
    105       TYPE pixel[N], pixelMask[N];                                      \
    106       GLuint k;                                                         \
    107       _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel);      \
    108       if (doMasking) {                                                  \
    109          _mesa_pack_colormask(rb->Format, colorMask, pixelMask);        \
    110          for (k = 0; k < N; k++) {                                      \
    111             pixel[k] &= pixelMask[k];                                   \
    112             pixelMask[k] = ~pixelMask[k];                               \
    113          }                                                              \
    114       }                                                                 \
    115       for (i = 0; i < height; i++) {                                    \
    116          TYPE *row = (TYPE *) map;                                      \
    117          if (doMasking) {                                               \
    118             for (j = 0; j < width; j++) {                               \
    119                for (k = 0; k < N; k++) {                                \
    120                   row[j * N + k] =                                      \
    121                      (row[j * N + k] & pixelMask[k]) | pixel[k];        \
    122                }                                                        \
    123             }                                                           \
    124          }                                                              \
    125          else {                                                         \
    126             for (j = 0; j < width; j++) {                               \
    127                for (k = 0; k < N; k++) {                                \
    128                   row[j * N + k] = pixel[k];                            \
    129                }                                                        \
    130             }                                                           \
    131          }                                                              \
    132          map += rowStride;                                              \
    133       }                                                                 \
    134    } while(0)
    135 
    136    switch (pixelSize) {
    137    case 1:
    138       SIMPLE_TYPE_CLEAR(GLubyte);
    139       break;
    140    case 2:
    141       SIMPLE_TYPE_CLEAR(GLushort);
    142       break;
    143    case 3:
    144       MULTI_WORD_CLEAR(GLubyte, 3);
    145       break;
    146    case 4:
    147       SIMPLE_TYPE_CLEAR(GLuint);
    148       break;
    149    case 6:
    150       MULTI_WORD_CLEAR(GLushort, 3);
    151       break;
    152    case 8:
    153       MULTI_WORD_CLEAR(GLuint, 2);
    154       break;
    155    case 12:
    156       MULTI_WORD_CLEAR(GLuint, 3);
    157       break;
    158    case 16:
    159       MULTI_WORD_CLEAR(GLuint, 4);
    160       break;
    161    default:
    162       _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
    163    }
    164 
    165    /* unmap buffer */
    166    ctx->Driver.UnmapRenderbuffer(ctx, rb);
    167 }
    168 
    169 
    170 /**
    171  * Clear the front/back/left/right/aux color buffers.
    172  * This function is usually only called if the device driver can't
    173  * clear its own color buffers for some reason (such as with masking).
    174  */
    175 static void
    176 clear_color_buffers(struct gl_context *ctx)
    177 {
    178    GLuint buf;
    179 
    180    for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
    181       struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
    182 
    183       /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
    184        * the framebuffer can be complete with some attachments be missing.  In
    185        * this case the _ColorDrawBuffers pointer will be NULL.
    186        */
    187       if (rb == NULL)
    188 	 continue;
    189 
    190       clear_rgba_buffer(ctx, rb, ctx->Color.ColorMask[buf]);
    191    }
    192 }
    193 
    194 
    195 /**
    196  * Called via the device driver's ctx->Driver.Clear() function if the
    197  * device driver can't clear one or more of the buffers itself.
    198  * \param buffers  bitfield of BUFFER_BIT_* values indicating which
    199  *                 renderbuffers are to be cleared.
    200  * \param all  if GL_TRUE, clear whole buffer, else clear specified region.
    201  */
    202 void
    203 _swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
    204 {
    205    const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL;
    206 
    207 #ifdef DEBUG_FOO
    208    {
    209       const GLbitfield legalBits =
    210          BUFFER_BIT_FRONT_LEFT |
    211 	 BUFFER_BIT_FRONT_RIGHT |
    212 	 BUFFER_BIT_BACK_LEFT |
    213 	 BUFFER_BIT_BACK_RIGHT |
    214 	 BUFFER_BIT_DEPTH |
    215 	 BUFFER_BIT_STENCIL |
    216 	 BUFFER_BIT_ACCUM |
    217          BUFFER_BIT_AUX0;
    218       assert((buffers & (~legalBits)) == 0);
    219    }
    220 #endif
    221 
    222    if (!_mesa_check_conditional_render(ctx))
    223       return; /* don't clear */
    224 
    225    if (SWRAST_CONTEXT(ctx)->NewState)
    226       _swrast_validate_derived(ctx);
    227 
    228    if ((buffers & BUFFER_BITS_COLOR)
    229        && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) {
    230       clear_color_buffers(ctx);
    231    }
    232 
    233    if (buffers & BUFFER_BIT_ACCUM) {
    234       _mesa_clear_accum_buffer(ctx);
    235    }
    236 
    237    if (buffers & BUFFER_DS) {
    238       struct gl_renderbuffer *depthRb =
    239          ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
    240       struct gl_renderbuffer *stencilRb =
    241          ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
    242 
    243       if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) {
    244          /* clear depth and stencil together */
    245          _swrast_clear_depth_stencil_buffer(ctx);
    246       }
    247       else {
    248          /* clear depth, stencil separately */
    249          if (buffers & BUFFER_BIT_DEPTH) {
    250             _swrast_clear_depth_buffer(ctx);
    251          }
    252          if (buffers & BUFFER_BIT_STENCIL) {
    253             _swrast_clear_stencil_buffer(ctx);
    254          }
    255       }
    256    }
    257 }
    258