remove unused413 stuff, glDrawBuffersARB uses that slot now
[mesa.git] / src / mesa / swrast / s_buffers.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
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_auxbuffer.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 or glIndexMask is in effect.
42 * We'll have specified which color buffer to clear by previously
43 * calling Driver.SetBuffer().
44 */
45 static void
46 clear_color_buffer_with_masking( GLcontext *ctx )
47 {
48 SWcontext *swrast = SWRAST_CONTEXT(ctx);
49 const GLint x = ctx->DrawBuffer->_Xmin;
50 const GLint y = ctx->DrawBuffer->_Ymin;
51 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
52 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
53
54 if (ctx->Visual.rgbMode) {
55 /* RGBA mode */
56 GLchan clearColor[4];
57 GLint i;
58 CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
59 CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
60 CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
61 CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
62 for (i = 0; i < height; i++) {
63 GLchan rgba[MAX_WIDTH][4];
64 GLint j;
65 for (j = 0; j < width; j++) {
66 COPY_CHAN4(rgba[j], clearColor);
67 }
68 _swrast_mask_rgba_array( ctx, width, x, y + i, rgba );
69 (*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i,
70 (CONST GLchan (*)[4]) rgba, NULL );
71 }
72 }
73 else {
74 /* Color index mode */
75 GLuint span[MAX_WIDTH];
76 GLubyte mask[MAX_WIDTH];
77 GLint i, j;
78 MEMSET( mask, 1, width );
79 for (i=0;i<height;i++) {
80 for (j=0;j<width;j++) {
81 span[j] = ctx->Color.ClearIndex;
82 }
83 _swrast_mask_index_array( ctx, width, x, y + i, span );
84 (*swrast->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask );
85 }
86 }
87 }
88
89
90 /**
91 * Clear a color buffer without index/channel masking.
92 * We'll have specified which color buffer to clear by previously
93 * calling Driver.SetBuffer().
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 * Clear the front/back/left/right/aux color buffers.
138 * This function is usually only called if the device driver can't
139 * clear its own color buffers for some reason (such as with masking).
140 */
141 static void
142 clear_color_buffers(GLcontext *ctx)
143 {
144 SWcontext *swrast = SWRAST_CONTEXT(ctx);
145 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
146 GLuint bufferBit;
147
148 /* loop over four possible dest color buffers */
149 for (bufferBit = 1; bufferBit <= DD_AUX3_BIT; bufferBit <<= 1) {
150 if (bufferBit & ctx->Color._DrawDestMask[0]) {
151 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
152
153 if (colorMask != 0xffffffff) {
154 clear_color_buffer_with_masking(ctx);
155 }
156 else {
157 clear_color_buffer(ctx);
158 }
159 }
160 }
161
162 /* restore default read/draw buffer */
163 _swrast_use_draw_buffer(ctx);
164 }
165
166
167 /**
168 * Called via the device driver's ctx->Driver.Clear() function if the
169 * device driver can't clear one or more of the buffers itself.
170 * \param mask bitwise-OR of DD_*_BIT flags.
171 * \param all if GL_TRUE, clear whole buffer, else clear specified region.
172 */
173 void
174 _swrast_Clear( GLcontext *ctx, GLbitfield mask,
175 GLboolean all,
176 GLint x, GLint y, GLint width, GLint height )
177 {
178 SWcontext *swrast = SWRAST_CONTEXT(ctx);
179 (void) all; (void) x; (void) y; (void) width; (void) height;
180 #ifdef DEBUG
181 {
182 const GLbitfield legalBits =
183 DD_FRONT_LEFT_BIT |
184 DD_FRONT_RIGHT_BIT |
185 DD_BACK_LEFT_BIT |
186 DD_BACK_RIGHT_BIT |
187 DD_DEPTH_BIT |
188 DD_STENCIL_BIT |
189 DD_ACCUM_BIT |
190 DD_AUX0_BIT |
191 DD_AUX1_BIT |
192 DD_AUX2_BIT |
193 DD_AUX3_BIT;
194 assert((mask & (~legalBits)) == 0);
195 }
196 #endif
197
198 RENDER_START(swrast,ctx);
199
200 /* do software clearing here */
201 if (mask) {
202 if (mask & ctx->Color._DrawDestMask[0]) {
203 clear_color_buffers(ctx);
204 /* clear software-based alpha buffer(s) */
205 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers
206 && ctx->Color.ColorMask[ACOMP]) {
207 _swrast_clear_alpha_buffers( ctx );
208 }
209 }
210 if (mask & DD_DEPTH_BIT) {
211 _swrast_clear_depth_buffer(ctx);
212 }
213 if (mask & DD_ACCUM_BIT) {
214 _swrast_clear_accum_buffer(ctx);
215 }
216 if (mask & DD_STENCIL_BIT) {
217 _swrast_clear_stencil_buffer(ctx);
218 }
219 }
220
221 RENDER_FINISH(swrast,ctx);
222 }
223
224
225 /**
226 * Typically called via ctx->Driver.ResizeBuffers().
227 * Reallocate all software-based depth/stencil/accum/etc buffers
228 * to match current window dimensions.
229 */
230 void
231 _swrast_alloc_buffers( GLframebuffer *buffer )
232 {
233 /* Reallocate other buffers if needed. */
234 if (buffer->UseSoftwareDepthBuffer) {
235 _swrast_alloc_depth_buffer( buffer );
236 }
237 if (buffer->UseSoftwareStencilBuffer) {
238 _swrast_alloc_stencil_buffer( buffer );
239 }
240 if (buffer->UseSoftwareAccumBuffer) {
241 _swrast_alloc_accum_buffer( buffer );
242 }
243 if (buffer->UseSoftwareAlphaBuffers) {
244 _swrast_alloc_alpha_buffers( buffer );
245 }
246 if (buffer->UseSoftwareAuxBuffers) {
247 _swrast_alloc_aux_buffers( buffer );
248 }
249 }
250
251
252 /*
253 * Fallback for ctx->Driver.DrawBuffer()
254 */
255 void
256 _swrast_DrawBuffer( GLcontext *ctx, GLenum mode )
257 {
258 (void) mode;
259 _swrast_use_draw_buffer(ctx);
260 }
261
262
263 /*
264 * Fallback for ctx->Driver.DrawBuffers()
265 */
266 void
267 _swrast_DrawBuffers( GLcontext *ctx, GLsizei n, const GLenum *buffers )
268 {
269 _swrast_use_draw_buffer(ctx);
270 }
271
272
273 /*
274 * Setup things so that we read/write spans from the user-designated
275 * read buffer (set via glReadPixels). We usually just have to call
276 * this for glReadPixels, glCopyPixels, etc.
277 */
278 void
279 _swrast_use_read_buffer( GLcontext *ctx )
280 {
281 SWcontext *swrast = SWRAST_CONTEXT(ctx);
282
283 /* Do this so the software-emulated alpha plane span functions work! */
284 swrast->CurrentBufferBit = ctx->Pixel._ReadSrcMask;
285 /* Tell the device driver where to read/write spans */
286 swrast->Driver.SetBuffer(ctx, ctx->ReadBuffer, swrast->CurrentBufferBit);
287 }
288
289
290 /*
291 * Setup things so that we read/write spans from the default draw buffer.
292 * This is the usual mode that Mesa's software rasterizer operates in.
293 */
294 void
295 _swrast_use_draw_buffer( GLcontext *ctx )
296 {
297 SWcontext *swrast = SWRAST_CONTEXT(ctx);
298
299 /* The user can specify rendering to zero, one, two, or four color
300 * buffers simultaneously with glDrawBuffer()!
301 * We don't expect the span/point/line/triangle functions to deal with
302 * that mess so we'll iterate over the multiple buffers as needed.
303 * But usually we only render to one color buffer at a time.
304 * We set ctx->Color._DriverDrawBuffer to that buffer and tell the
305 * device driver to use that buffer.
306 * Look in s_span.c's multi_write_rgba_span() function to see how
307 * we loop over multiple color buffers when needed.
308 */
309
310 if (ctx->Color._DrawDestMask[0] & DD_FRONT_LEFT_BIT)
311 swrast->CurrentBufferBit = DD_FRONT_LEFT_BIT;
312 else if (ctx->Color._DrawDestMask[0] & DD_BACK_LEFT_BIT)
313 swrast->CurrentBufferBit = DD_BACK_LEFT_BIT;
314 else if (ctx->Color._DrawDestMask[0] & DD_FRONT_RIGHT_BIT)
315 swrast->CurrentBufferBit = DD_FRONT_RIGHT_BIT;
316 else if (ctx->Color._DrawDestMask[0] & DD_BACK_RIGHT_BIT)
317 swrast->CurrentBufferBit = DD_BACK_RIGHT_BIT;
318 else if (ctx->Color._DrawDestMask[0] & DD_AUX0_BIT)
319 swrast->CurrentBufferBit = DD_AUX0_BIT;
320 else if (ctx->Color._DrawDestMask[0] & DD_AUX1_BIT)
321 swrast->CurrentBufferBit = DD_AUX1_BIT;
322 else if (ctx->Color._DrawDestMask[0] & DD_AUX2_BIT)
323 swrast->CurrentBufferBit = DD_AUX2_BIT;
324 else if (ctx->Color._DrawDestMask[0] & DD_AUX3_BIT)
325 swrast->CurrentBufferBit = DD_AUX3_BIT;
326 else
327 /* glDrawBuffer(GL_NONE) */
328 swrast->CurrentBufferBit = DD_FRONT_LEFT_BIT; /* we always have this buffer */
329
330 swrast->Driver.SetBuffer(ctx, ctx->DrawBuffer, swrast->CurrentBufferBit);
331 }