fixup vertex building code ..
[mesa.git] / src / mesa / swrast / s_buffers.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.0.1
4 *
5 * Copyright (C) 1999-2004 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
26 #include "glheader.h"
27 #include "colormac.h"
28 #include "macros.h"
29 #include "imports.h"
30
31 #include "s_accum.h"
32 #include "s_alphabuf.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
41 /*
42 * Clear the color buffer when glColorMask or glIndexMask is in effect.
43 */
44 static void
45 clear_color_buffer_with_masking( GLcontext *ctx )
46 {
47 SWcontext *swrast = SWRAST_CONTEXT(ctx);
48 const GLint x = ctx->DrawBuffer->_Xmin;
49 const GLint y = ctx->DrawBuffer->_Ymin;
50 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
51 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
52
53 if (ctx->Visual.rgbMode) {
54 /* RGBA mode */
55 GLchan clearColor[4];
56 GLint i;
57 CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
58 CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
59 CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
60 CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
61 for (i = 0; i < height; i++) {
62 GLchan rgba[MAX_WIDTH][4];
63 GLint j;
64 for (j = 0; j < width; j++) {
65 COPY_CHAN4(rgba[j], clearColor);
66 }
67 _swrast_mask_rgba_array( ctx, width, x, y + i, rgba );
68 (*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i,
69 (CONST GLchan (*)[4]) rgba, NULL );
70 }
71 }
72 else {
73 /* Color index mode */
74 GLuint span[MAX_WIDTH];
75 GLubyte mask[MAX_WIDTH];
76 GLint i, j;
77 MEMSET( mask, 1, width );
78 for (i=0;i<height;i++) {
79 for (j=0;j<width;j++) {
80 span[j] = ctx->Color.ClearIndex;
81 }
82 _swrast_mask_index_array( ctx, width, x, y + i, span );
83 (*swrast->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask );
84 }
85 }
86 }
87
88
89
90 /*
91 * Clear a color buffer without index/channel masking.
92 */
93 static void
94 clear_color_buffer(GLcontext *ctx)
95 {
96 SWcontext *swrast = SWRAST_CONTEXT(ctx);
97 const GLint x = ctx->DrawBuffer->_Xmin;
98 const GLint y = ctx->DrawBuffer->_Ymin;
99 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
100 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
101
102 if (ctx->Visual.rgbMode) {
103 /* RGBA mode */
104 GLchan clearColor[4];
105 GLint i;
106
107 CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
108 CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
109 CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
110 CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
111
112 ASSERT(*((GLuint *) &ctx->Color.ColorMask) == 0xffffffff);
113 ASSERT(swrast->Driver.WriteRGBASpan);
114
115 for (i = 0; i < height; i++) {
116 (*swrast->Driver.WriteMonoRGBASpan)( ctx, width, x, y + i,
117 clearColor, NULL );
118 }
119 }
120 else {
121 /* Color index mode */
122 GLint i;
123 ASSERT((ctx->Color.IndexMask & ((1 << ctx->Visual.indexBits) - 1))
124 == (GLuint) ((1 << ctx->Visual.indexBits) - 1));
125 ASSERT(swrast->Driver.WriteMonoCISpan);
126 for (i = 0; i < height; i++) {
127 (*swrast->Driver.WriteMonoCISpan)( ctx, width, x, y + i,
128 ctx->Color.ClearIndex, NULL);
129 }
130 }
131 }
132
133
134
135 /*
136 * Clear the front/back/left/right color buffers.
137 * This function is usually only called if we need to clear the
138 * buffers with masking.
139 */
140 static void
141 clear_color_buffers(GLcontext *ctx)
142 {
143 SWcontext *swrast = SWRAST_CONTEXT(ctx);
144 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
145 GLuint bufferBit;
146
147 /* loop over four possible dest color buffers */
148 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
149 if (bufferBit & ctx->Color._DrawDestMask) {
150 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
151
152 if (colorMask != 0xffffffff) {
153 clear_color_buffer_with_masking(ctx);
154 }
155 else {
156 clear_color_buffer(ctx);
157 }
158 }
159 }
160
161 /* restore default read/draw buffer */
162 _swrast_use_draw_buffer(ctx);
163 }
164
165
166
167 void
168 _swrast_Clear( GLcontext *ctx, GLbitfield mask,
169 GLboolean all,
170 GLint x, GLint y, GLint width, GLint height )
171 {
172 SWcontext *swrast = SWRAST_CONTEXT(ctx);
173 #ifdef DEBUG
174 {
175 GLbitfield legalBits = DD_FRONT_LEFT_BIT |
176 DD_FRONT_RIGHT_BIT |
177 DD_BACK_LEFT_BIT |
178 DD_BACK_RIGHT_BIT |
179 DD_DEPTH_BIT |
180 DD_STENCIL_BIT |
181 DD_ACCUM_BIT;
182 assert((mask & (~legalBits)) == 0);
183 }
184 #endif
185
186 RENDER_START(swrast,ctx);
187
188 /* do software clearing here */
189 if (mask) {
190 if (mask & ctx->Color._DrawDestMask) clear_color_buffers(ctx);
191 if (mask & GL_DEPTH_BUFFER_BIT) _swrast_clear_depth_buffer(ctx);
192 if (mask & GL_ACCUM_BUFFER_BIT) _swrast_clear_accum_buffer(ctx);
193 if (mask & GL_STENCIL_BUFFER_BIT) _swrast_clear_stencil_buffer(ctx);
194 }
195
196 /* clear software-based alpha buffer(s) */
197 if ( (mask & GL_COLOR_BUFFER_BIT)
198 && ctx->DrawBuffer->UseSoftwareAlphaBuffers
199 && ctx->Color.ColorMask[ACOMP]) {
200 _swrast_clear_alpha_buffers( ctx );
201 }
202
203 RENDER_FINISH(swrast,ctx);
204 }
205
206
207 void
208 _swrast_alloc_buffers( GLframebuffer *buffer )
209 {
210 /* Reallocate other buffers if needed. */
211 if (buffer->UseSoftwareDepthBuffer) {
212 _swrast_alloc_depth_buffer( buffer );
213 }
214 if (buffer->UseSoftwareStencilBuffer) {
215 _swrast_alloc_stencil_buffer( buffer );
216 }
217 if (buffer->UseSoftwareAccumBuffer) {
218 _swrast_alloc_accum_buffer( buffer );
219 }
220 if (buffer->UseSoftwareAlphaBuffers) {
221 _swrast_alloc_alpha_buffers( buffer );
222 }
223 }
224
225
226 /*
227 * Fallback for ctx->Driver.DrawBuffer()
228 */
229 void
230 _swrast_DrawBuffer( GLcontext *ctx, GLenum mode )
231 {
232 _swrast_use_draw_buffer(ctx);
233 }
234
235
236 /*
237 * Setup things so that we read/write spans from the user-designated
238 * read buffer (set via glReadPixels). We usually just have to call
239 * this for glReadPixels, glCopyPixels, etc.
240 */
241 void
242 _swrast_use_read_buffer( GLcontext *ctx )
243 {
244 SWcontext *swrast = SWRAST_CONTEXT(ctx);
245
246 /* Do this so the software-emulated alpha plane span functions work! */
247 swrast->CurrentBuffer = ctx->Pixel._ReadSrcMask;
248 /* Tell the device driver where to read/write spans */
249 (*swrast->Driver.SetBuffer)( ctx, ctx->ReadBuffer, swrast->CurrentBuffer );
250 }
251
252
253 /*
254 * Setup things so that we read/write spans from the default draw buffer.
255 * This is the usual mode that Mesa's software rasterizer operates in.
256 */
257 void
258 _swrast_use_draw_buffer( GLcontext *ctx )
259 {
260 SWcontext *swrast = SWRAST_CONTEXT(ctx);
261
262 /* The user can specify rendering to zero, one, two, or four color
263 * buffers simultaneously with glDrawBuffer()!
264 * We don't expect the span/point/line/triangle functions to deal with
265 * that mess so we'll iterate over the multiple buffers as needed.
266 * But usually we only render to one color buffer at a time.
267 * We set ctx->Color._DriverDrawBuffer to that buffer and tell the
268 * device driver to use that buffer.
269 * Look in s_span.c's multi_write_rgba_span() function to see how
270 * we loop over multiple color buffers when needed.
271 */
272
273 if (ctx->Color._DrawDestMask & FRONT_LEFT_BIT)
274 swrast->CurrentBuffer = FRONT_LEFT_BIT;
275 else if (ctx->Color._DrawDestMask & BACK_LEFT_BIT)
276 swrast->CurrentBuffer = BACK_LEFT_BIT;
277 else if (ctx->Color._DrawDestMask & FRONT_RIGHT_BIT)
278 swrast->CurrentBuffer = FRONT_RIGHT_BIT;
279 else if (ctx->Color._DrawDestMask & BACK_RIGHT_BIT)
280 swrast->CurrentBuffer = BACK_RIGHT_BIT;
281 else
282 /* glDrawBuffer(GL_NONE) */
283 swrast->CurrentBuffer = FRONT_LEFT_BIT; /* we always have this buffer */
284
285 (*swrast->Driver.SetBuffer)( ctx, ctx->DrawBuffer, swrast->CurrentBuffer );
286 }