s_clear.c revision 3464ebd5
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/condrender.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(struct gl_context *ctx, struct gl_renderbuffer *rb, 44 GLuint buf) 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 SWspan span; 51 GLint i; 52 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_CAST(span.array->rgba[i], clearColor, GLchan); 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, buf); 99 /* write masked row */ 100 rb->PutRow(ctx, rb, width, x, y + i, span.array->rgba, NULL); 101 } 102} 103 104 105/** 106 * Clear an rgba color buffer without channel masking. 107 */ 108static void 109clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint buf) 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 GLubyte clear8[4]; 116 GLushort clear16[4]; 117 GLvoid *clearVal; 118 GLint i; 119 120 ASSERT(ctx->Color.ColorMask[buf][0] && 121 ctx->Color.ColorMask[buf][1] && 122 ctx->Color.ColorMask[buf][2] && 123 ctx->Color.ColorMask[buf][3]); 124 125 ASSERT(rb->PutMonoRow); 126 127 switch (rb->DataType) { 128 case GL_UNSIGNED_BYTE: 129 UNCLAMPED_FLOAT_TO_UBYTE(clear8[0], ctx->Color.ClearColor[0]); 130 UNCLAMPED_FLOAT_TO_UBYTE(clear8[1], ctx->Color.ClearColor[1]); 131 UNCLAMPED_FLOAT_TO_UBYTE(clear8[2], ctx->Color.ClearColor[2]); 132 UNCLAMPED_FLOAT_TO_UBYTE(clear8[3], ctx->Color.ClearColor[3]); 133 clearVal = clear8; 134 break; 135 case GL_UNSIGNED_SHORT: 136 UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor[0]); 137 UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor[1]); 138 UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor[2]); 139 UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor[3]); 140 clearVal = clear16; 141 break; 142 case GL_FLOAT: 143 clearVal = ctx->Color.ClearColor; 144 break; 145 default: 146 _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer"); 147 return; 148 } 149 150 for (i = 0; i < height; i++) { 151 rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL); 152 } 153} 154 155 156/** 157 * Clear the front/back/left/right/aux color buffers. 158 * This function is usually only called if the device driver can't 159 * clear its own color buffers for some reason (such as with masking). 160 */ 161static void 162clear_color_buffers(struct gl_context *ctx) 163{ 164 GLuint buf; 165 166 for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) { 167 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf]; 168 169 /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported, 170 * the framebuffer can be complete with some attachments be missing. In 171 * this case the _ColorDrawBuffers pointer will be NULL. 172 */ 173 if (rb == NULL) 174 continue; 175 176 if (ctx->Color.ColorMask[buf][0] == 0 || 177 ctx->Color.ColorMask[buf][1] == 0 || 178 ctx->Color.ColorMask[buf][2] == 0 || 179 ctx->Color.ColorMask[buf][3] == 0) { 180 clear_rgba_buffer_with_masking(ctx, rb, buf); 181 } 182 else { 183 clear_rgba_buffer(ctx, rb, buf); 184 } 185 } 186} 187 188 189/** 190 * Called via the device driver's ctx->Driver.Clear() function if the 191 * device driver can't clear one or more of the buffers itself. 192 * \param buffers bitfield of BUFFER_BIT_* values indicating which 193 * renderbuffers are to be cleared. 194 * \param all if GL_TRUE, clear whole buffer, else clear specified region. 195 */ 196void 197_swrast_Clear(struct gl_context *ctx, GLbitfield buffers) 198{ 199#ifdef DEBUG_FOO 200 { 201 const GLbitfield legalBits = 202 BUFFER_BIT_FRONT_LEFT | 203 BUFFER_BIT_FRONT_RIGHT | 204 BUFFER_BIT_BACK_LEFT | 205 BUFFER_BIT_BACK_RIGHT | 206 BUFFER_BIT_DEPTH | 207 BUFFER_BIT_STENCIL | 208 BUFFER_BIT_ACCUM | 209 BUFFER_BIT_AUX0; 210 assert((buffers & (~legalBits)) == 0); 211 } 212#endif 213 214 if (!_mesa_check_conditional_render(ctx)) 215 return; /* don't clear */ 216 217 swrast_render_start(ctx); 218 219 /* do software clearing here */ 220 if (buffers) { 221 if ((buffers & BUFFER_BITS_COLOR) 222 && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) { 223 clear_color_buffers(ctx); 224 } 225 if (buffers & BUFFER_BIT_DEPTH) { 226 _swrast_clear_depth_buffer(ctx, ctx->DrawBuffer->_DepthBuffer); 227 } 228 if (buffers & BUFFER_BIT_ACCUM) { 229 _swrast_clear_accum_buffer(ctx, 230 ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); 231 } 232 if (buffers & BUFFER_BIT_STENCIL) { 233 _swrast_clear_stencil_buffer(ctx, ctx->DrawBuffer->_StencilBuffer); 234 } 235 } 236 237 swrast_render_finish(ctx); 238} 239