1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 */ 42static void 43clear_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 */ 175static void 176clear_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 */ 202void 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