s_clear.c revision 4a49301e
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/colormac.h" 27#include "main/formats.h" 28#include "main/macros.h" 29#include "main/imports.h" 30#include "main/mtypes.h" 31 32#include "s_accum.h" 33#include "s_context.h" 34#include "s_depth.h" 35#include "s_masking.h" 36#include "s_stencil.h" 37 38 39/** 40 * Clear the color buffer when glColorMask is in effect. 41 */ 42static void 43clear_rgba_buffer_with_masking(GLcontext *ctx, struct gl_renderbuffer *rb) 44{ 45 const GLint x = ctx->DrawBuffer->_Xmin; 46 const GLint y = ctx->DrawBuffer->_Ymin; 47 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 48 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 49 SWspan span; 50 GLint i; 51 52 ASSERT(ctx->Visual.rgbMode); 53 ASSERT(rb->PutRow); 54 55 /* Initialize color span with clear color */ 56 /* XXX optimize for clearcolor == black/zero (bzero) */ 57 INIT_SPAN(span, GL_BITMAP); 58 span.end = width; 59 span.arrayMask = SPAN_RGBA; 60 span.array->ChanType = rb->DataType; 61 if (span.array->ChanType == GL_UNSIGNED_BYTE) { 62 GLubyte clearColor[4]; 63 UNCLAMPED_FLOAT_TO_UBYTE(clearColor[RCOMP], ctx->Color.ClearColor[0]); 64 UNCLAMPED_FLOAT_TO_UBYTE(clearColor[GCOMP], ctx->Color.ClearColor[1]); 65 UNCLAMPED_FLOAT_TO_UBYTE(clearColor[BCOMP], ctx->Color.ClearColor[2]); 66 UNCLAMPED_FLOAT_TO_UBYTE(clearColor[ACOMP], ctx->Color.ClearColor[3]); 67 for (i = 0; i < width; i++) { 68 COPY_4UBV(span.array->rgba[i], clearColor); 69 } 70 } 71 else if (span.array->ChanType == GL_UNSIGNED_SHORT) { 72 GLushort clearColor[4]; 73 UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor[0]); 74 UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor[1]); 75 UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor[2]); 76 UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor[3]); 77 for (i = 0; i < width; i++) { 78 COPY_4V(span.array->rgba[i], clearColor); 79 } 80 } 81 else { 82 ASSERT(span.array->ChanType == GL_FLOAT); 83 for (i = 0; i < width; i++) { 84 CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor[0]); 85 CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor[1]); 86 CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor[2]); 87 CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor[3]); 88 } 89 } 90 91 /* Note that masking will change the color values, but only the 92 * channels for which the write mask is GL_FALSE. The channels 93 * which which are write-enabled won't get modified. 94 */ 95 for (i = 0; i < height; i++) { 96 span.x = x; 97 span.y = y + i; 98 _swrast_mask_rgba_span(ctx, rb, &span); 99 /* write masked row */ 100 rb->PutRow(ctx, rb, width, x, y + i, span.array->rgba, NULL); 101 } 102} 103 104 105/** 106 * Clear color index buffer with masking. 107 */ 108static void 109clear_ci_buffer_with_masking(GLcontext *ctx, struct gl_renderbuffer *rb) 110{ 111 const GLint x = ctx->DrawBuffer->_Xmin; 112 const GLint y = ctx->DrawBuffer->_Ymin; 113 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 114 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 115 SWspan span; 116 GLint i; 117 118 ASSERT(!ctx->Visual.rgbMode); 119 ASSERT(rb->PutRow); 120 ASSERT(rb->DataType == GL_UNSIGNED_INT); 121 122 /* Initialize index span with clear index */ 123 INIT_SPAN(span, GL_BITMAP); 124 span.end = width; 125 span.arrayMask = SPAN_INDEX; 126 for (i = 0; i < width;i++) { 127 span.array->index[i] = ctx->Color.ClearIndex; 128 } 129 130 /* Note that masking will change the color indexes, but only the 131 * bits for which the write mask is GL_FALSE. The bits 132 * which are write-enabled won't get modified. 133 */ 134 for (i = 0; i < height;i++) { 135 span.x = x; 136 span.y = y + i; 137 _swrast_mask_ci_span(ctx, rb, &span); 138 /* write masked row */ 139 rb->PutRow(ctx, rb, width, x, y + i, span.array->index, NULL); 140 } 141} 142 143 144/** 145 * Clear an rgba color buffer without channel masking. 146 */ 147static void 148clear_rgba_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) 149{ 150 const GLint x = ctx->DrawBuffer->_Xmin; 151 const GLint y = ctx->DrawBuffer->_Ymin; 152 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 153 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 154 GLubyte clear8[4]; 155 GLushort clear16[4]; 156 GLvoid *clearVal; 157 GLint i; 158 159 ASSERT(ctx->Visual.rgbMode); 160 161 ASSERT(ctx->Color.ColorMask[0] && 162 ctx->Color.ColorMask[1] && 163 ctx->Color.ColorMask[2] && 164 ctx->Color.ColorMask[3]); 165 166 ASSERT(rb->PutMonoRow); 167 168 switch (rb->DataType) { 169 case GL_UNSIGNED_BYTE: 170 UNCLAMPED_FLOAT_TO_UBYTE(clear8[0], ctx->Color.ClearColor[0]); 171 UNCLAMPED_FLOAT_TO_UBYTE(clear8[1], ctx->Color.ClearColor[1]); 172 UNCLAMPED_FLOAT_TO_UBYTE(clear8[2], ctx->Color.ClearColor[2]); 173 UNCLAMPED_FLOAT_TO_UBYTE(clear8[3], ctx->Color.ClearColor[3]); 174 clearVal = clear8; 175 break; 176 case GL_UNSIGNED_SHORT: 177 UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor[0]); 178 UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor[1]); 179 UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor[2]); 180 UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor[3]); 181 clearVal = clear16; 182 break; 183 case GL_FLOAT: 184 clearVal = ctx->Color.ClearColor; 185 break; 186 default: 187 _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer"); 188 return; 189 } 190 191 for (i = 0; i < height; i++) { 192 rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL); 193 } 194} 195 196 197/** 198 * Clear color index buffer without masking. 199 */ 200static void 201clear_ci_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) 202{ 203 const GLint x = ctx->DrawBuffer->_Xmin; 204 const GLint y = ctx->DrawBuffer->_Ymin; 205 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 206 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 207 GLubyte clear8; 208 GLushort clear16; 209 GLuint clear32; 210 GLvoid *clearVal; 211 GLint i; 212 213 ASSERT(!ctx->Visual.rgbMode); 214 215 ASSERT(rb->PutMonoRow); 216 217 /* setup clear value */ 218 switch (rb->DataType) { 219 case GL_UNSIGNED_BYTE: 220 clear8 = (GLubyte) ctx->Color.ClearIndex; 221 clearVal = &clear8; 222 break; 223 case GL_UNSIGNED_SHORT: 224 clear16 = (GLushort) ctx->Color.ClearIndex; 225 clearVal = &clear16; 226 break; 227 case GL_UNSIGNED_INT: 228 clear32 = ctx->Color.ClearIndex; 229 clearVal = &clear32; 230 break; 231 default: 232 _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer"); 233 return; 234 } 235 236 for (i = 0; i < height; i++) 237 rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL); 238} 239 240 241/** 242 * Clear the front/back/left/right/aux color buffers. 243 * This function is usually only called if the device driver can't 244 * clear its own color buffers for some reason (such as with masking). 245 */ 246static void 247clear_color_buffers(GLcontext *ctx) 248{ 249 GLboolean masking; 250 GLuint buf; 251 252 if (ctx->Visual.rgbMode) { 253 if (ctx->Color.ColorMask[0] && 254 ctx->Color.ColorMask[1] && 255 ctx->Color.ColorMask[2] && 256 ctx->Color.ColorMask[3]) { 257 masking = GL_FALSE; 258 } 259 else { 260 masking = GL_TRUE; 261 } 262 } 263 else { 264 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; 265 const GLuint indexMask = (1 << _mesa_get_format_bits(rb->Format, GL_INDEX_BITS)) - 1; 266 if ((ctx->Color.IndexMask & indexMask) == indexMask) { 267 masking = GL_FALSE; 268 } 269 else { 270 masking = GL_TRUE; 271 } 272 } 273 274 for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) { 275 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf]; 276 if (ctx->Visual.rgbMode) { 277 if (masking) { 278 clear_rgba_buffer_with_masking(ctx, rb); 279 } 280 else { 281 clear_rgba_buffer(ctx, rb); 282 } 283 } 284 else { 285 if (masking) { 286 clear_ci_buffer_with_masking(ctx, rb); 287 } 288 else { 289 clear_ci_buffer(ctx, rb); 290 } 291 } 292 } 293} 294 295 296/** 297 * Called via the device driver's ctx->Driver.Clear() function if the 298 * device driver can't clear one or more of the buffers itself. 299 * \param buffers bitfield of BUFFER_BIT_* values indicating which 300 * renderbuffers are to be cleared. 301 * \param all if GL_TRUE, clear whole buffer, else clear specified region. 302 */ 303void 304_swrast_Clear(GLcontext *ctx, GLbitfield buffers) 305{ 306#ifdef DEBUG_FOO 307 { 308 const GLbitfield legalBits = 309 BUFFER_BIT_FRONT_LEFT | 310 BUFFER_BIT_FRONT_RIGHT | 311 BUFFER_BIT_BACK_LEFT | 312 BUFFER_BIT_BACK_RIGHT | 313 BUFFER_BIT_DEPTH | 314 BUFFER_BIT_STENCIL | 315 BUFFER_BIT_ACCUM | 316 BUFFER_BIT_AUX0; 317 assert((buffers & (~legalBits)) == 0); 318 } 319#endif 320 321 swrast_render_start(ctx); 322 323 /* do software clearing here */ 324 if (buffers) { 325 if ((buffers & BUFFER_BITS_COLOR) 326 && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) { 327 clear_color_buffers(ctx); 328 } 329 if (buffers & BUFFER_BIT_DEPTH) { 330 _swrast_clear_depth_buffer(ctx, ctx->DrawBuffer->_DepthBuffer); 331 } 332 if (buffers & BUFFER_BIT_ACCUM) { 333 _swrast_clear_accum_buffer(ctx, 334 ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); 335 } 336 if (buffers & BUFFER_BIT_STENCIL) { 337 _swrast_clear_stencil_buffer(ctx, ctx->DrawBuffer->_StencilBuffer); 338 } 339 } 340 341 swrast_render_finish(ctx); 342} 343