1 /* $Id: s_buffers.c,v 1.16 2002/11/13 16:46:19 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
34 #include "s_alphabuf.h"
35 #include "s_context.h"
37 #include "s_masking.h"
38 #include "s_stencil.h"
44 * Clear the color buffer when glColorMask or glIndexMask is in effect.
47 clear_color_buffer_with_masking( GLcontext
*ctx
)
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
;
55 if (ctx
->Visual
.rgbMode
) {
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];
66 for (j
= 0; j
< width
; j
++) {
67 COPY_CHAN4(rgba
[j
], clearColor
);
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
);
75 /* Color index mode */
76 GLuint span
[MAX_WIDTH
];
77 GLubyte mask
[MAX_WIDTH
];
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
;
84 _mesa_mask_index_array( ctx
, width
, x
, y
+ i
, span
);
85 (*swrast
->Driver
.WriteCI32Span
)( ctx
, width
, x
, y
+ i
, span
, mask
);
93 * Clear a color buffer without index/channel masking.
96 clear_color_buffer(GLcontext
*ctx
)
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
;
104 if (ctx
->Visual
.rgbMode
) {
106 GLchan clearColor
[4];
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]);
114 ASSERT(*((GLuint
*) &ctx
->Color
.ColorMask
) == 0xffffffff);
115 ASSERT(swrast
->Driver
.WriteRGBASpan
);
117 for (i
= 0; i
< height
; i
++) {
118 (*swrast
->Driver
.WriteMonoRGBASpan
)( ctx
, width
, x
, y
+ i
,
123 /* Color index mode */
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
);
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.
143 clear_color_buffers(GLcontext
*ctx
)
145 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
146 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
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
);
154 if (colorMask
!= 0xffffffff) {
155 clear_color_buffer_with_masking(ctx
);
158 clear_color_buffer(ctx
);
163 /* restore default read/draw buffer */
164 _swrast_use_draw_buffer(ctx
);
170 _swrast_Clear( GLcontext
*ctx
, GLbitfield mask
,
172 GLint x
, GLint y
, GLint width
, GLint height
)
174 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
177 GLbitfield legalBits
= DD_FRONT_LEFT_BIT
|
184 assert((mask
& (~legalBits
)) == 0);
188 RENDER_START(swrast
,ctx
);
190 /* do software clearing here */
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
);
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
);
205 RENDER_FINISH(swrast
,ctx
);
210 _swrast_alloc_buffers( GLframebuffer
*buffer
)
212 /* Reallocate other buffers if needed. */
213 if (buffer
->UseSoftwareDepthBuffer
) {
214 _mesa_alloc_depth_buffer( buffer
);
216 if (buffer
->UseSoftwareStencilBuffer
) {
217 _mesa_alloc_stencil_buffer( buffer
);
219 if (buffer
->UseSoftwareAccumBuffer
) {
220 _mesa_alloc_accum_buffer( buffer
);
222 if (buffer
->UseSoftwareAlphaBuffers
) {
223 _mesa_alloc_alpha_buffers( buffer
);
229 * Fallback for ctx->Driver.DrawBuffer()
232 _swrast_DrawBuffer( GLcontext
*ctx
, GLenum mode
)
234 _swrast_use_draw_buffer(ctx
);
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.
244 _swrast_use_read_buffer( GLcontext
*ctx
)
246 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
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
);
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.
260 _swrast_use_draw_buffer( GLcontext
*ctx
)
262 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
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.
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
;
284 /* glDrawBuffer(GL_NONE) */
285 swrast
->CurrentBuffer
= FRONT_LEFT_BIT
; /* we always have this buffer */
287 (*swrast
->Driver
.SetBuffer
)( ctx
, ctx
->DrawBuffer
, swrast
->CurrentBuffer
);