swrast: Rename blend_func->swrast_blend_func
[mesa.git] / src / mesa / swrast / s_clear.c
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 ctx->DrawBuffer->FlipY);
71 if (!map) {
72 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
73 return;
74 }
75
76 /* for 1, 2, 4-byte clearing */
77 #define SIMPLE_TYPE_CLEAR(TYPE) \
78 do { \
79 TYPE pixel, pixelMask; \
80 _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel); \
81 if (doMasking) { \
82 _mesa_pack_colormask(rb->Format, colorMask, &pixelMask); \
83 pixel &= pixelMask; \
84 pixelMask = ~pixelMask; \
85 } \
86 for (i = 0; i < height; i++) { \
87 TYPE *row = (TYPE *) map; \
88 if (doMasking) { \
89 for (j = 0; j < width; j++) { \
90 row[j] = (row[j] & pixelMask) | pixel; \
91 } \
92 } \
93 else { \
94 for (j = 0; j < width; j++) { \
95 row[j] = pixel; \
96 } \
97 } \
98 map += rowStride; \
99 } \
100 } while (0)
101
102
103 /* for 3, 6, 8, 12, 16-byte clearing */
104 #define MULTI_WORD_CLEAR(TYPE, N) \
105 do { \
106 TYPE pixel[N], pixelMask[N]; \
107 GLuint k; \
108 _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel); \
109 if (doMasking) { \
110 _mesa_pack_colormask(rb->Format, colorMask, pixelMask); \
111 for (k = 0; k < N; k++) { \
112 pixel[k] &= pixelMask[k]; \
113 pixelMask[k] = ~pixelMask[k]; \
114 } \
115 } \
116 for (i = 0; i < height; i++) { \
117 TYPE *row = (TYPE *) map; \
118 if (doMasking) { \
119 for (j = 0; j < width; j++) { \
120 for (k = 0; k < N; k++) { \
121 row[j * N + k] = \
122 (row[j * N + k] & pixelMask[k]) | pixel[k]; \
123 } \
124 } \
125 } \
126 else { \
127 for (j = 0; j < width; j++) { \
128 for (k = 0; k < N; k++) { \
129 row[j * N + k] = pixel[k]; \
130 } \
131 } \
132 } \
133 map += rowStride; \
134 } \
135 } while(0)
136
137 switch (pixelSize) {
138 case 1:
139 SIMPLE_TYPE_CLEAR(GLubyte);
140 break;
141 case 2:
142 SIMPLE_TYPE_CLEAR(GLushort);
143 break;
144 case 3:
145 MULTI_WORD_CLEAR(GLubyte, 3);
146 break;
147 case 4:
148 SIMPLE_TYPE_CLEAR(GLuint);
149 break;
150 case 6:
151 MULTI_WORD_CLEAR(GLushort, 3);
152 break;
153 case 8:
154 MULTI_WORD_CLEAR(GLuint, 2);
155 break;
156 case 12:
157 MULTI_WORD_CLEAR(GLuint, 3);
158 break;
159 case 16:
160 MULTI_WORD_CLEAR(GLuint, 4);
161 break;
162 default:
163 _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
164 }
165
166 /* unmap buffer */
167 ctx->Driver.UnmapRenderbuffer(ctx, rb);
168 }
169
170
171 /**
172 * Clear the front/back/left/right/aux color buffers.
173 * This function is usually only called if the device driver can't
174 * clear its own color buffers for some reason (such as with masking).
175 */
176 static void
177 clear_color_buffers(struct gl_context *ctx)
178 {
179 GLuint buf;
180
181 for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
182 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
183
184 /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
185 * the framebuffer can be complete with some attachments be missing. In
186 * this case the _ColorDrawBuffers pointer will be NULL.
187 */
188 if (rb == NULL)
189 continue;
190
191 const GLubyte colormask[4] = {
192 GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
193 GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
194 GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
195 GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
196 };
197 clear_rgba_buffer(ctx, rb, colormask);
198 }
199 }
200
201
202 /**
203 * Called via the device driver's ctx->Driver.Clear() function if the
204 * device driver can't clear one or more of the buffers itself.
205 * \param buffers bitfield of BUFFER_BIT_* values indicating which
206 * renderbuffers are to be cleared.
207 * \param all if GL_TRUE, clear whole buffer, else clear specified region.
208 */
209 void
210 _swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
211 {
212 const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL;
213
214 #ifdef DEBUG_FOO
215 {
216 const GLbitfield legalBits =
217 BUFFER_BIT_FRONT_LEFT |
218 BUFFER_BIT_FRONT_RIGHT |
219 BUFFER_BIT_BACK_LEFT |
220 BUFFER_BIT_BACK_RIGHT |
221 BUFFER_BIT_DEPTH |
222 BUFFER_BIT_STENCIL |
223 BUFFER_BIT_ACCUM |
224 BUFFER_BIT_AUX0;
225 assert((buffers & (~legalBits)) == 0);
226 }
227 #endif
228
229 if (!_mesa_check_conditional_render(ctx))
230 return; /* don't clear */
231
232 if (SWRAST_CONTEXT(ctx)->NewState)
233 _swrast_validate_derived(ctx);
234
235 if ((buffers & BUFFER_BITS_COLOR)
236 && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) {
237 clear_color_buffers(ctx);
238 }
239
240 if (buffers & BUFFER_BIT_ACCUM) {
241 _mesa_clear_accum_buffer(ctx);
242 }
243
244 if (buffers & BUFFER_DS) {
245 struct gl_renderbuffer *depthRb =
246 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
247 struct gl_renderbuffer *stencilRb =
248 ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
249
250 if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) {
251 /* clear depth and stencil together */
252 _swrast_clear_depth_stencil_buffer(ctx);
253 }
254 else {
255 /* clear depth, stencil separately */
256 if (buffers & BUFFER_BIT_DEPTH) {
257 _swrast_clear_depth_buffer(ctx);
258 }
259 if (buffers & BUFFER_BIT_STENCIL) {
260 _swrast_clear_stencil_buffer(ctx);
261 }
262 }
263 }
264 }