[MESA]
[reactos.git] / reactos / dll / opengl / mesa / 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/accum.h"
27 #include "main/format_pack.h"
28 #include "main/macros.h"
29 #include "main/imports.h"
30 #include "main/mtypes.h"
31
32 #include "s_context.h"
33 #include "s_depth.h"
34 #include "s_stencil.h"
35
36
37
38 /**
39 * Clear an rgba color buffer with masking if needed.
40 */
41 static void
42 clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
43 const GLubyte colorMask[4])
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 const GLuint pixelSize = _mesa_get_format_bytes(rb->Format);
50 const GLboolean doMasking = (colorMask[0] == 0 ||
51 colorMask[1] == 0 ||
52 colorMask[2] == 0 ||
53 colorMask[3] == 0);
54 const GLfloat (*clearColor)[4] =
55 (const GLfloat (*)[4]) ctx->Color.ClearColor.f;
56 GLbitfield mapMode = GL_MAP_WRITE_BIT;
57 GLubyte *map;
58 GLint rowStride;
59 GLint i, j;
60
61 if (doMasking) {
62 /* we'll need to read buffer values too */
63 mapMode |= GL_MAP_READ_BIT;
64 }
65
66 /* map dest buffer */
67 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
68 mapMode, &map, &rowStride);
69 if (!map) {
70 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
71 return;
72 }
73
74 /* for 1, 2, 4-byte clearing */
75 #define SIMPLE_TYPE_CLEAR(TYPE) \
76 do { \
77 TYPE pixel, pixelMask; \
78 _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel); \
79 if (doMasking) { \
80 _mesa_pack_colormask(rb->Format, colorMask, &pixelMask); \
81 pixel &= pixelMask; \
82 pixelMask = ~pixelMask; \
83 } \
84 for (i = 0; i < height; i++) { \
85 TYPE *row = (TYPE *) map; \
86 if (doMasking) { \
87 for (j = 0; j < width; j++) { \
88 row[j] = (row[j] & pixelMask) | pixel; \
89 } \
90 } \
91 else { \
92 for (j = 0; j < width; j++) { \
93 row[j] = pixel; \
94 } \
95 } \
96 map += rowStride; \
97 } \
98 } while (0)
99
100
101 /* for 3, 6, 8, 12, 16-byte clearing */
102 #define MULTI_WORD_CLEAR(TYPE, N) \
103 do { \
104 TYPE pixel[N], pixelMask[N]; \
105 GLuint k; \
106 _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel); \
107 if (doMasking) { \
108 _mesa_pack_colormask(rb->Format, colorMask, pixelMask); \
109 for (k = 0; k < N; k++) { \
110 pixel[k] &= pixelMask[k]; \
111 pixelMask[k] = ~pixelMask[k]; \
112 } \
113 } \
114 for (i = 0; i < height; i++) { \
115 TYPE *row = (TYPE *) map; \
116 if (doMasking) { \
117 for (j = 0; j < width; j++) { \
118 for (k = 0; k < N; k++) { \
119 row[j * N + k] = \
120 (row[j * N + k] & pixelMask[k]) | pixel[k]; \
121 } \
122 } \
123 } \
124 else { \
125 for (j = 0; j < width; j++) { \
126 for (k = 0; k < N; k++) { \
127 row[j * N + k] = pixel[k]; \
128 } \
129 } \
130 } \
131 map += rowStride; \
132 } \
133 } while(0)
134
135 switch (pixelSize) {
136 case 1:
137 SIMPLE_TYPE_CLEAR(GLubyte);
138 break;
139 case 2:
140 SIMPLE_TYPE_CLEAR(GLushort);
141 break;
142 case 3:
143 MULTI_WORD_CLEAR(GLubyte, 3);
144 break;
145 case 4:
146 SIMPLE_TYPE_CLEAR(GLuint);
147 break;
148 case 6:
149 MULTI_WORD_CLEAR(GLushort, 3);
150 break;
151 case 8:
152 MULTI_WORD_CLEAR(GLuint, 2);
153 break;
154 case 12:
155 MULTI_WORD_CLEAR(GLuint, 3);
156 break;
157 case 16:
158 MULTI_WORD_CLEAR(GLuint, 4);
159 break;
160 default:
161 _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
162 }
163
164 /* unmap buffer */
165 ctx->Driver.UnmapRenderbuffer(ctx, rb);
166 }
167
168
169 /**
170 * Clear the front/back/left/right/aux color buffers.
171 * This function is usually only called if the device driver can't
172 * clear its own color buffers for some reason (such as with masking).
173 */
174 static void
175 clear_color_buffers(struct gl_context *ctx)
176 {
177 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffer;
178
179 clear_rgba_buffer(ctx, rb, ctx->Color.ColorMask);
180 }
181
182
183 /**
184 * Called via the device driver's ctx->Driver.Clear() function if the
185 * device driver can't clear one or more of the buffers itself.
186 * \param buffers bitfield of BUFFER_BIT_* values indicating which
187 * renderbuffers are to be cleared.
188 * \param all if GL_TRUE, clear whole buffer, else clear specified region.
189 */
190 void
191 _swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
192 {
193 #ifdef DEBUG_FOO
194 {
195 const GLbitfield legalBits =
196 BUFFER_BIT_FRONT_LEFT |
197 BUFFER_BIT_FRONT_RIGHT |
198 BUFFER_BIT_BACK_LEFT |
199 BUFFER_BIT_BACK_RIGHT |
200 BUFFER_BIT_DEPTH |
201 BUFFER_BIT_STENCIL |
202 BUFFER_BIT_ACCUM |
203 BUFFER_BIT_AUX0;
204 assert((buffers & (~legalBits)) == 0);
205 }
206 #endif
207
208 if (SWRAST_CONTEXT(ctx)->NewState)
209 _swrast_validate_derived(ctx);
210
211 if (buffers & BUFFER_BITS_COLOR) {
212 clear_color_buffers(ctx);
213 }
214
215 if (buffers & BUFFER_BIT_ACCUM) {
216 _mesa_clear_accum_buffer(ctx);
217 }
218
219 if (buffers & BUFFER_BIT_DEPTH) {
220 _swrast_clear_depth_buffer(ctx);
221 }
222 if (buffers & BUFFER_BIT_STENCIL) {
223 _swrast_clear_stencil_buffer(ctx);
224 }
225 }