cdb665fc18e4d812202b2b98240203cac0bf2eb8
[mesa.git] / src / mesa / swrast / s_buffers.c
1 /* $Id: s_buffers.c,v 1.16 2002/11/13 16:46:19 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #include "glheader.h"
29 #include "colormac.h"
30 #include "macros.h"
31 #include "imports.h"
32
33 #include "s_accum.h"
34 #include "s_alphabuf.h"
35 #include "s_context.h"
36 #include "s_depth.h"
37 #include "s_masking.h"
38 #include "s_stencil.h"
39
40
41
42
43 /*
44 * Clear the color buffer when glColorMask or glIndexMask is in effect.
45 */
46 static void
47 clear_color_buffer_with_masking( GLcontext *ctx )
48 {
49 SWcontext *swrast = SWRAST_CONTEXT(ctx);
50 const GLint x = ctx->DrawBuffer->_Xmin;
51 const GLint y = ctx->DrawBuffer->_Ymin;
52 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
53 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
54
55 if (ctx->Visual.rgbMode) {
56 /* RGBA mode */
57 GLchan clearColor[4];
58 GLint i;
59 CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
60 CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
61 CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
62 CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
63 for (i = 0; i < height; i++) {
64 GLchan rgba[MAX_WIDTH][4];
65 GLint j;
66 for (j = 0; j < width; j++) {
67 COPY_CHAN4(rgba[j], clearColor);
68 }
69 _mesa_mask_rgba_array( ctx, width, x, y + i, rgba );
70 (*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i,
71 (CONST GLchan (*)[4]) rgba, NULL );
72 }
73 }
74 else {
75 /* Color index mode */
76 GLuint span[MAX_WIDTH];
77 GLubyte mask[MAX_WIDTH];
78 GLint i, j;
79 MEMSET( mask, 1, width );
80 for (i=0;i<height;i++) {
81 for (j=0;j<width;j++) {
82 span[j] = ctx->Color.ClearIndex;
83 }
84 _mesa_mask_index_array( ctx, width, x, y + i, span );
85 (*swrast->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask );
86 }
87 }
88 }
89
90
91
92 /*
93 * Clear a color buffer without index/channel masking.
94 */
95 static void
96 clear_color_buffer(GLcontext *ctx)
97 {
98 SWcontext *swrast = SWRAST_CONTEXT(ctx);
99 const GLint x = ctx->DrawBuffer->_Xmin;
100 const GLint y = ctx->DrawBuffer->_Ymin;
101 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
102 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
103
104 if (ctx->Visual.rgbMode) {
105 /* RGBA mode */
106 GLchan clearColor[4];
107 GLint i;
108
109 CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
110 CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
111 CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
112 CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
113
114 ASSERT(*((GLuint *) &ctx->Color.ColorMask) == 0xffffffff);
115 ASSERT(swrast->Driver.WriteRGBASpan);
116
117 for (i = 0; i < height; i++) {
118 (*swrast->Driver.WriteMonoRGBASpan)( ctx, width, x, y + i,
119 clearColor, NULL );
120 }
121 }
122 else {
123 /* Color index mode */
124 GLint i;
125 ASSERT((ctx->Color.IndexMask & ((1 << ctx->Visual.indexBits) - 1))
126 == (GLuint) ((1 << ctx->Visual.indexBits) - 1));
127 ASSERT(swrast->Driver.WriteMonoCISpan);
128 for (i = 0; i < height; i++) {
129 (*swrast->Driver.WriteMonoCISpan)( ctx, width, x, y + i,
130 ctx->Color.ClearIndex, NULL);
131 }
132 }
133 }
134
135
136
137 /*
138 * Clear the front/back/left/right color buffers.
139 * This function is usually only called if we need to clear the
140 * buffers with masking.
141 */
142 static void
143 clear_color_buffers(GLcontext *ctx)
144 {
145 SWcontext *swrast = SWRAST_CONTEXT(ctx);
146 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
147 GLuint bufferBit;
148
149 /* loop over four possible dest color buffers */
150 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
151 if (bufferBit & ctx->Color._DrawDestMask) {
152 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
153
154 if (colorMask != 0xffffffff) {
155 clear_color_buffer_with_masking(ctx);
156 }
157 else {
158 clear_color_buffer(ctx);
159 }
160 }
161 }
162
163 /* restore default read/draw buffer */
164 _swrast_use_draw_buffer(ctx);
165 }
166
167
168
169 void
170 _swrast_Clear( GLcontext *ctx, GLbitfield mask,
171 GLboolean all,
172 GLint x, GLint y, GLint width, GLint height )
173 {
174 SWcontext *swrast = SWRAST_CONTEXT(ctx);
175 #ifdef DEBUG
176 {
177 GLbitfield legalBits = DD_FRONT_LEFT_BIT |
178 DD_FRONT_RIGHT_BIT |
179 DD_BACK_LEFT_BIT |
180 DD_BACK_RIGHT_BIT |
181 DD_DEPTH_BIT |
182 DD_STENCIL_BIT |
183 DD_ACCUM_BIT;
184 assert((mask & (~legalBits)) == 0);
185 }
186 #endif
187
188 RENDER_START(swrast,ctx);
189
190 /* do software clearing here */
191 if (mask) {
192 if (mask & ctx->Color._DrawDestMask) clear_color_buffers(ctx);
193 if (mask & GL_DEPTH_BUFFER_BIT) _mesa_clear_depth_buffer(ctx);
194 if (mask & GL_ACCUM_BUFFER_BIT) _mesa_clear_accum_buffer(ctx);
195 if (mask & GL_STENCIL_BUFFER_BIT) _mesa_clear_stencil_buffer(ctx);
196 }
197
198 /* clear software-based alpha buffer(s) */
199 if ( (mask & GL_COLOR_BUFFER_BIT)
200 && ctx->DrawBuffer->UseSoftwareAlphaBuffers
201 && ctx->Color.ColorMask[ACOMP]) {
202 _mesa_clear_alpha_buffers( ctx );
203 }
204
205 RENDER_FINISH(swrast,ctx);
206 }
207
208
209 void
210 _swrast_alloc_buffers( GLframebuffer *buffer )
211 {
212 /* Reallocate other buffers if needed. */
213 if (buffer->UseSoftwareDepthBuffer) {
214 _mesa_alloc_depth_buffer( buffer );
215 }
216 if (buffer->UseSoftwareStencilBuffer) {
217 _mesa_alloc_stencil_buffer( buffer );
218 }
219 if (buffer->UseSoftwareAccumBuffer) {
220 _mesa_alloc_accum_buffer( buffer );
221 }
222 if (buffer->UseSoftwareAlphaBuffers) {
223 _mesa_alloc_alpha_buffers( buffer );
224 }
225 }
226
227
228 /*
229 * Fallback for ctx->Driver.DrawBuffer()
230 */
231 void
232 _swrast_DrawBuffer( GLcontext *ctx, GLenum mode )
233 {
234 _swrast_use_draw_buffer(ctx);
235 }
236
237
238 /*
239 * Setup things so that we read/write spans from the user-designated
240 * read buffer (set via glReadPixels). We usually just have to call
241 * this for glReadPixels, glCopyPixels, etc.
242 */
243 void
244 _swrast_use_read_buffer( GLcontext *ctx )
245 {
246 SWcontext *swrast = SWRAST_CONTEXT(ctx);
247
248 /* Do this so the software-emulated alpha plane span functions work! */
249 swrast->CurrentBuffer = ctx->Pixel._ReadSrcMask;
250 /* Tell the device driver where to read/write spans */
251 (*swrast->Driver.SetBuffer)( ctx, ctx->ReadBuffer, swrast->CurrentBuffer );
252 }
253
254
255 /*
256 * Setup things so that we read/write spans from the default draw buffer.
257 * This is the usual mode that Mesa's software rasterizer operates in.
258 */
259 void
260 _swrast_use_draw_buffer( GLcontext *ctx )
261 {
262 SWcontext *swrast = SWRAST_CONTEXT(ctx);
263
264 /* The user can specify rendering to zero, one, two, or four color
265 * buffers simultaneously with glDrawBuffer()!
266 * We don't expect the span/point/line/triangle functions to deal with
267 * that mess so we'll iterate over the multiple buffers as needed.
268 * But usually we only render to one color buffer at a time.
269 * We set ctx->Color._DriverDrawBuffer to that buffer and tell the
270 * device driver to use that buffer.
271 * Look in s_span.c's multi_write_rgba_span() function to see how
272 * we loop over multiple color buffers when needed.
273 */
274
275 if (ctx->Color._DrawDestMask & FRONT_LEFT_BIT)
276 swrast->CurrentBuffer = FRONT_LEFT_BIT;
277 else if (ctx->Color._DrawDestMask & BACK_LEFT_BIT)
278 swrast->CurrentBuffer = BACK_LEFT_BIT;
279 else if (ctx->Color._DrawDestMask & FRONT_RIGHT_BIT)
280 swrast->CurrentBuffer = FRONT_RIGHT_BIT;
281 else if (ctx->Color._DrawDestMask & BACK_RIGHT_BIT)
282 swrast->CurrentBuffer = BACK_RIGHT_BIT;
283 else
284 /* glDrawBuffer(GL_NONE) */
285 swrast->CurrentBuffer = FRONT_LEFT_BIT; /* we always have this buffer */
286
287 (*swrast->Driver.SetBuffer)( ctx, ctx->DrawBuffer, swrast->CurrentBuffer );
288 }