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