dri fb works using renderbuffers now in RGBA mode
[mesa.git] / src / mesa / swrast / s_buffers.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
4 *
5 * Copyright (C) 1999-2005 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 #include "mtypes.h"
31 #include "fbobject.h"
32
33 #include "s_accum.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 is in effect.
42 */
43 static void
44 clear_rgba_buffer_with_masking(GLcontext *ctx, struct gl_renderbuffer *rb)
45 {
46 SWcontext *swrast = SWRAST_CONTEXT(ctx);
47 const GLint x = ctx->DrawBuffer->_Xmin;
48 const GLint y = ctx->DrawBuffer->_Ymin;
49 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
50 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
51 GLchan clearColor[4];
52 GLint i;
53
54 ASSERT(ctx->Visual.rgbMode);
55
56 CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
57 CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
58 CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
59 CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
60
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, rb, width, x, y + i, rgba );
68 #if NEW_RENDERBUFFER
69 if (rb->PutRow) {
70 rb->PutRow(ctx, rb, width, x, y + i, rgba, NULL);
71 }
72 #endif
73 #if OLD_RENDERBUFFER
74 else {
75 swrast->Driver.WriteRGBASpan(ctx, rb, width, x, y + i,
76 (CONST GLchan (*)[4]) rgba, NULL);
77 }
78 #endif
79 }
80 }
81
82
83 /**
84 * Clear color index buffer with masking.
85 */
86 static void
87 clear_ci_buffer_with_masking(GLcontext *ctx, struct gl_renderbuffer *rb)
88 {
89 const GLint x = ctx->DrawBuffer->_Xmin;
90 const GLint y = ctx->DrawBuffer->_Ymin;
91 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
92 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
93 GLuint span[MAX_WIDTH];
94 GLubyte mask[MAX_WIDTH];
95 GLint i, j;
96
97 ASSERT(!ctx->Visual.rgbMode);
98
99 MEMSET( mask, 1, width );
100 for (i = 0; i < height;i++) {
101 for (j = 0; j < width;j++) {
102 span[j] = ctx->Color.ClearIndex;
103 }
104 _swrast_mask_ci_array(ctx, rb, width, x, y + i, span);
105 ASSERT(rb->PutRow);
106 ASSERT(rb->DataType == GL_UNSIGNED_INT);
107 rb->PutRow(ctx, rb, width, x, y + i, span, mask);
108 }
109 }
110
111
112 /**
113 * Clear an rgba color buffer without channel masking.
114 */
115 static void
116 clear_rgba_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
117 {
118 SWcontext *swrast = SWRAST_CONTEXT(ctx);
119 const GLint x = ctx->DrawBuffer->_Xmin;
120 const GLint y = ctx->DrawBuffer->_Ymin;
121 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
122 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
123 GLint i;
124
125 ASSERT(ctx->Visual.rgbMode);
126
127 ASSERT(ctx->Color.ColorMask[0] &&
128 ctx->Color.ColorMask[1] &&
129 ctx->Color.ColorMask[2] &&
130 ctx->Color.ColorMask[3]);
131
132 #if NEW_RENDERBUFFER
133 if (rb->PutMonoRow) { /* XXX assert this */
134 GLubyte clear8[4];
135 GLushort clear16[4];
136 GLvoid *clearVal;
137 switch (rb->DataType) {
138 case GL_UNSIGNED_BYTE:
139 clear8[0] = FLOAT_TO_UBYTE(ctx->Color.ClearColor[0]);
140 clear8[1] = FLOAT_TO_UBYTE(ctx->Color.ClearColor[1]);
141 clear8[2] = FLOAT_TO_UBYTE(ctx->Color.ClearColor[2]);
142 clear8[3] = FLOAT_TO_UBYTE(ctx->Color.ClearColor[3]);
143 clearVal = clear8;
144 break;
145 case GL_UNSIGNED_SHORT:
146 clear16[0] = FLOAT_TO_USHORT(ctx->Color.ClearColor[0]);
147 clear16[1] = FLOAT_TO_USHORT(ctx->Color.ClearColor[1]);
148 clear16[2] = FLOAT_TO_USHORT(ctx->Color.ClearColor[2]);
149 clear16[3] = FLOAT_TO_USHORT(ctx->Color.ClearColor[3]);
150 clearVal = clear16;
151 break;
152 case GL_FLOAT:
153 clearVal = ctx->Color.ClearColor;
154 break;
155 default:
156 _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer");
157 return;
158 }
159 for (i = 0; i < height; i++) {
160 rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL);
161 }
162 }
163 #endif
164 #if OLD_RENDERBUFFER
165 else {
166 GLchan clearColor[4];
167 CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
168 CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
169 CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
170 CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
171 ASSERT(swrast->Driver.WriteRGBASpan);
172 for (i = 0; i < height; i++) {
173 swrast->Driver.WriteMonoRGBASpan(ctx, rb, width, x, y + i,
174 clearColor, NULL );
175 }
176 }
177 #endif
178 }
179
180
181 /**
182 * Clear color index buffer without masking.
183 */
184 static void
185 clear_ci_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
186 {
187 const GLint x = ctx->DrawBuffer->_Xmin;
188 const GLint y = ctx->DrawBuffer->_Ymin;
189 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
190 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
191
192 ASSERT(!ctx->Visual.rgbMode);
193
194 ASSERT((ctx->Color.IndexMask & ((1 << ctx->Visual.indexBits) - 1))
195 == (GLuint) ((1 << ctx->Visual.indexBits) - 1));
196
197 #if NEW_RENDERBUFFER
198 if (rb->PutMonoRow) { /* XXX assert this */
199 GLubyte clear8;
200 GLushort clear16;
201 GLuint clear32;
202 GLvoid *clearVal;
203 GLint i;
204 switch (rb->DataType) {
205 case GL_UNSIGNED_BYTE:
206 clear8 = (GLubyte) ctx->Color.ClearIndex;
207 clearVal = &clear8;
208 break;
209 case GL_UNSIGNED_SHORT:
210 clear16 = (GLushort) ctx->Color.ClearIndex;
211 clearVal = &clear16;
212 break;
213 case GL_UNSIGNED_INT:
214 clear32 = ctx->Color.ClearIndex;
215 clearVal = &clear32;
216 break;
217 default:
218 _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer");
219 return;
220 }
221 for (i = 0; i < height; i++)
222 rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL);
223 }
224 #endif
225 }
226
227
228 /**
229 * Clear the front/back/left/right/aux color buffers.
230 * This function is usually only called if the device driver can't
231 * clear its own color buffers for some reason (such as with masking).
232 */
233 static void
234 clear_color_buffers(GLcontext *ctx)
235 {
236 SWcontext *swrast = SWRAST_CONTEXT(ctx);
237 GLboolean masking;
238 GLuint i;
239
240 if (ctx->Visual.rgbMode) {
241 if (ctx->Color.ColorMask[0] &&
242 ctx->Color.ColorMask[1] &&
243 ctx->Color.ColorMask[2] &&
244 ctx->Color.ColorMask[3]) {
245 masking = GL_FALSE;
246 }
247 else {
248 masking = GL_TRUE;
249 }
250 }
251 else {
252 const GLuint indexBits = (1 << ctx->Visual.indexBits) - 1;
253 if ((ctx->Color.IndexMask & indexBits) == indexBits) {
254 masking = GL_FALSE;
255 }
256 else {
257 masking = GL_TRUE;
258 }
259 }
260
261 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers[0]; i++) {
262 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][i];
263 #if OLD_RENDERBUFFER /* this is obsolete code */
264 if (swrast->Driver.SetBuffer)
265 swrast->Driver.SetBuffer(ctx, ctx->DrawBuffer,
266 ctx->DrawBuffer->_ColorDrawBit[0][i]);
267 #endif
268
269 if (ctx->Visual.rgbMode) {
270 if (masking) {
271 clear_rgba_buffer_with_masking(ctx, rb);
272 }
273 else {
274 clear_rgba_buffer(ctx, rb);
275 }
276 }
277 else {
278 if (masking) {
279 clear_ci_buffer_with_masking(ctx, rb);
280 }
281 else {
282 clear_ci_buffer(ctx, rb);
283 }
284 }
285 }
286
287 /* restore default read/draw buffer */
288 _swrast_use_draw_buffer(ctx);
289 }
290
291
292 /**
293 * Called via the device driver's ctx->Driver.Clear() function if the
294 * device driver can't clear one or more of the buffers itself.
295 * \param mask bitwise-OR of DD_*_BIT flags.
296 * \param all if GL_TRUE, clear whole buffer, else clear specified region.
297 */
298 void
299 _swrast_Clear(GLcontext *ctx, GLbitfield mask,
300 GLboolean all, GLint x, GLint y, GLint width, GLint height)
301 {
302 SWcontext *swrast = SWRAST_CONTEXT(ctx);
303
304 (void) all; (void) x; (void) y; (void) width; (void) height;
305
306 #ifdef DEBUG_FOO
307 {
308 const GLbitfield legalBits =
309 BUFFER_BIT_FRONT_LEFT |
310 BUFFER_BIT_FRONT_RIGHT |
311 BUFFER_BIT_BACK_LEFT |
312 BUFFER_BIT_BACK_RIGHT |
313 BUFFER_BIT_DEPTH |
314 BUFFER_BIT_STENCIL |
315 BUFFER_BIT_ACCUM |
316 BUFFER_BIT_AUX0 |
317 BUFFER_BIT_AUX1 |
318 BUFFER_BIT_AUX2 |
319 BUFFER_BIT_AUX3;
320 assert((mask & (~legalBits)) == 0);
321 }
322 #endif
323
324 RENDER_START(swrast,ctx);
325
326 /* do software clearing here */
327 if (mask) {
328 if (mask & ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
329 clear_color_buffers(ctx);
330 }
331 if (mask & BUFFER_BIT_DEPTH) {
332 struct gl_renderbuffer *rb
333 = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
334 _swrast_clear_depth_buffer(ctx, rb);
335 }
336 if (mask & BUFFER_BIT_ACCUM) {
337 struct gl_renderbuffer *rb
338 = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
339 _swrast_clear_accum_buffer(ctx, rb);
340 }
341 if (mask & BUFFER_BIT_STENCIL) {
342 struct gl_renderbuffer *rb
343 = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
344 _swrast_clear_stencil_buffer(ctx, rb);
345 }
346 }
347
348 RENDER_FINISH(swrast,ctx);
349 }
350
351
352 /*
353 * Fallback for ctx->Driver.DrawBuffer()
354 */
355 void
356 _swrast_DrawBuffer( GLcontext *ctx, GLenum mode )
357 {
358 (void) mode;
359 _swrast_use_draw_buffer(ctx);
360 }
361
362
363 /*
364 * Fallback for ctx->Driver.DrawBuffers()
365 */
366 void
367 _swrast_DrawBuffers( GLcontext *ctx, GLsizei n, const GLenum *buffers )
368 {
369 _swrast_use_draw_buffer(ctx);
370 }
371
372
373 /*
374 * Setup things so that we read/write spans from the user-designated
375 * read buffer (set via glReadPixels). We usually just have to call
376 * this for glReadPixels, glCopyPixels, etc.
377 */
378 void
379 _swrast_use_read_buffer( GLcontext *ctx )
380 {
381 SWcontext *swrast = SWRAST_CONTEXT(ctx);
382
383 /* Do this so the software-emulated alpha plane span functions work! */
384 swrast->CurrentBufferBit = ctx->ReadBuffer->_ColorReadBufferMask;
385 /* Tell the device driver where to read/write spans */
386 swrast->Driver.SetBuffer(ctx, ctx->ReadBuffer, swrast->CurrentBufferBit);
387 }
388
389
390 /*
391 * Setup things so that we read/write spans from the default draw buffer.
392 * This is the usual mode that Mesa's software rasterizer operates in.
393 */
394 void
395 _swrast_use_draw_buffer( GLcontext *ctx )
396 {
397 SWcontext *swrast = SWRAST_CONTEXT(ctx);
398
399 /* The user can specify rendering to zero, one, two, or four color
400 * buffers simultaneously with glDrawBuffer()!
401 * We don't expect the span/point/line/triangle functions to deal with
402 * that mess so we'll iterate over the multiple buffers as needed.
403 * But usually we only render to one color buffer at a time.
404 * We set ctx->Color._DriverDrawBuffer to that buffer and tell the
405 * device driver to use that buffer.
406 * Look in s_span.c's multi_write_rgba_span() function to see how
407 * we loop over multiple color buffers when needed.
408 */
409
410 if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_FRONT_LEFT)
411 swrast->CurrentBufferBit = BUFFER_BIT_FRONT_LEFT;
412 else if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_BACK_LEFT)
413 swrast->CurrentBufferBit = BUFFER_BIT_BACK_LEFT;
414 else if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_FRONT_RIGHT)
415 swrast->CurrentBufferBit = BUFFER_BIT_FRONT_RIGHT;
416 else if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_BACK_RIGHT)
417 swrast->CurrentBufferBit = BUFFER_BIT_BACK_RIGHT;
418 else if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_AUX0)
419 swrast->CurrentBufferBit = BUFFER_BIT_AUX0;
420 else if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_AUX1)
421 swrast->CurrentBufferBit = BUFFER_BIT_AUX1;
422 else if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_AUX2)
423 swrast->CurrentBufferBit = BUFFER_BIT_AUX2;
424 else if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_AUX3)
425 swrast->CurrentBufferBit = BUFFER_BIT_AUX3;
426 else
427 /* glDrawBuffer(GL_NONE) */
428 swrast->CurrentBufferBit = BUFFER_BIT_FRONT_LEFT; /* we always have this buffer */
429
430 if (swrast->Driver.SetBuffer)
431 swrast->Driver.SetBuffer(ctx, ctx->DrawBuffer, swrast->CurrentBufferBit);
432 }