Changed a number of context fields from GLchan to GLfloat (such as ClearColor).
[mesa.git] / src / mesa / swrast / s_alphabuf.c
1 /* $Id: s_alphabuf.c,v 1.12 2002/10/04 19:10:12 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.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 /*
29 * Software alpha planes. Many frame buffers don't have alpha bits so
30 * we simulate them in software.
31 */
32
33
34 #include "glheader.h"
35 #include "context.h"
36 #include "mem.h"
37
38 #include "s_alphabuf.h"
39
40
41 /*
42 * Allocate a new front and back alpha buffer.
43 */
44 void
45 _mesa_alloc_alpha_buffers( GLframebuffer *buffer )
46 {
47 const GLint bytes = buffer->Width * buffer->Height * sizeof(GLchan);
48
49 ASSERT(buffer->UseSoftwareAlphaBuffers);
50
51 if (buffer->FrontLeftAlpha) {
52 MESA_PBUFFER_FREE( buffer->FrontLeftAlpha );
53 }
54 buffer->FrontLeftAlpha = MESA_PBUFFER_ALLOC( bytes );
55 if (!buffer->FrontLeftAlpha) {
56 /* out of memory */
57 _mesa_error( NULL, GL_OUT_OF_MEMORY,
58 "Couldn't allocate front-left alpha buffer" );
59 }
60
61 if (buffer->Visual.doubleBufferMode) {
62 if (buffer->BackLeftAlpha) {
63 MESA_PBUFFER_FREE( buffer->BackLeftAlpha );
64 }
65 buffer->BackLeftAlpha = MESA_PBUFFER_ALLOC( bytes );
66 if (!buffer->BackLeftAlpha) {
67 /* out of memory */
68 _mesa_error( NULL, GL_OUT_OF_MEMORY,
69 "Couldn't allocate back-left alpha buffer" );
70 }
71 }
72
73 if (buffer->Visual.stereoMode) {
74 if (buffer->FrontRightAlpha) {
75 MESA_PBUFFER_FREE( buffer->FrontRightAlpha );
76 }
77 buffer->FrontRightAlpha = MESA_PBUFFER_ALLOC( bytes );
78 if (!buffer->FrontRightAlpha) {
79 /* out of memory */
80 _mesa_error( NULL, GL_OUT_OF_MEMORY,
81 "Couldn't allocate front-right alpha buffer" );
82 }
83
84 if (buffer->Visual.doubleBufferMode) {
85 if (buffer->BackRightAlpha) {
86 MESA_PBUFFER_FREE( buffer->BackRightAlpha );
87 }
88 buffer->BackRightAlpha = MESA_PBUFFER_ALLOC( bytes );
89 if (!buffer->BackRightAlpha) {
90 /* out of memory */
91 _mesa_error( NULL, GL_OUT_OF_MEMORY,
92 "Couldn't allocate back-right alpha buffer" );
93 }
94 }
95 }
96 }
97
98
99 /*
100 * Clear all the alpha buffers
101 */
102 void
103 _mesa_clear_alpha_buffers( GLcontext *ctx )
104 {
105 const GLchan aclear = ctx->Color.ClearColor[3];
106 GLuint bufferBit;
107
108 ASSERT(ctx->DrawBuffer->UseSoftwareAlphaBuffers);
109 ASSERT(ctx->Color.ColorMask[ACOMP]);
110
111 /* loop over four possible alpha buffers */
112 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
113 if (bufferBit & ctx->Color._DrawDestMask) {
114 GLchan *buffer;
115 if (bufferBit == FRONT_LEFT_BIT) {
116 buffer = (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
117 }
118 else if (bufferBit == FRONT_RIGHT_BIT) {
119 buffer = (GLchan *) ctx->DrawBuffer->FrontRightAlpha;
120 }
121 else if (bufferBit == BACK_LEFT_BIT) {
122 buffer = (GLchan *) ctx->DrawBuffer->BackLeftAlpha;
123 }
124 else {
125 buffer = (GLchan *) ctx->DrawBuffer->BackRightAlpha;
126 }
127
128 if (ctx->Scissor.Enabled) {
129 /* clear scissor region */
130 GLint j;
131 GLint rowLen = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
132 GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
133 GLint width = ctx->DrawBuffer->Width;
134 GLchan *aptr = buffer
135 + ctx->DrawBuffer->_Ymin * ctx->DrawBuffer->Width
136 + ctx->DrawBuffer->_Xmin;
137 for (j = 0; j < rows; j++) {
138 #if CHAN_BITS == 8
139 MEMSET( aptr, aclear, rowLen );
140 #elif CHAN_BITS == 16
141 MEMSET16( aptr, aclear, rowLen );
142 #else
143 GLint i;
144 for (i = 0; i < rowLen; i++) {
145 aptr[i] = aclear;
146 }
147 #endif
148 aptr += width;
149 }
150 }
151 else {
152 /* clear whole buffer */
153 GLuint pixels = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
154 #if CHAN_BITS == 8
155 MEMSET(buffer, aclear, pixels);
156 #elif CHAN_BITS == 16
157 MEMSET16(buffer, aclear, pixels);
158 #else
159 GLuint i;
160 for (i = 0; i < pixels; i++) {
161 buffer[i] = aclear;
162 }
163 #endif
164 }
165 }
166 }
167 }
168
169
170
171 static INLINE
172 GLchan *get_alpha_buffer( GLcontext *ctx )
173 {
174 switch (ctx->Color._DriverDrawBuffer) {
175 case GL_FRONT_LEFT:
176 return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
177 break;
178 case GL_BACK_LEFT:
179 return (GLchan *) ctx->DrawBuffer->BackLeftAlpha;
180 break;
181 case GL_FRONT_RIGHT:
182 return (GLchan *) ctx->DrawBuffer->FrontRightAlpha;
183 break;
184 case GL_BACK_RIGHT:
185 return (GLchan *) ctx->DrawBuffer->BackRightAlpha;
186 break;
187 default:
188 _mesa_problem(ctx, "Bad DriverDrawBuffer in _mesa_write_alpha_span()");
189 return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha; /* aribitrary */
190 }
191 }
192
193
194 void
195 _mesa_write_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
196 CONST GLchan rgba[][4], const GLubyte mask[] )
197 {
198 GLchan *buffer, *aptr;
199 GLuint i;
200
201 buffer = get_alpha_buffer(ctx);
202 aptr = buffer + y * ctx->DrawBuffer->Width + x;
203
204 if (mask) {
205 for (i=0;i<n;i++) {
206 if (mask[i]) {
207 *aptr = rgba[i][ACOMP];
208 }
209 aptr++;
210 }
211 }
212 else {
213 for (i=0;i<n;i++) {
214 *aptr++ = rgba[i][ACOMP];
215 }
216 }
217 }
218
219
220 void
221 _mesa_write_mono_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
222 GLchan alpha, const GLubyte mask[] )
223 {
224 GLchan *buffer, *aptr;
225 GLuint i;
226
227 buffer = get_alpha_buffer(ctx);
228 aptr = buffer + y * ctx->DrawBuffer->Width + x;
229
230 if (mask) {
231 for (i=0;i<n;i++) {
232 if (mask[i]) {
233 *aptr = alpha;
234 }
235 aptr++;
236 }
237 }
238 else {
239 for (i=0;i<n;i++) {
240 *aptr++ = alpha;
241 }
242 }
243 }
244
245
246 void
247 _mesa_write_alpha_pixels( GLcontext *ctx,
248 GLuint n, const GLint x[], const GLint y[],
249 CONST GLchan rgba[][4], const GLubyte mask[] )
250 {
251 GLchan *buffer;
252 GLuint i;
253
254 buffer = get_alpha_buffer(ctx);
255
256 if (mask) {
257 for (i=0;i<n;i++) {
258 if (mask[i]) {
259 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
260 *aptr = rgba[i][ACOMP];
261 }
262 }
263 }
264 else {
265 for (i=0;i<n;i++) {
266 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
267 *aptr = rgba[i][ACOMP];
268 }
269 }
270 }
271
272
273 void
274 _mesa_write_mono_alpha_pixels( GLcontext *ctx,
275 GLuint n, const GLint x[], const GLint y[],
276 GLchan alpha, const GLubyte mask[] )
277 {
278 GLchan *buffer;
279 GLuint i;
280
281 buffer = get_alpha_buffer(ctx);
282
283 if (mask) {
284 for (i=0;i<n;i++) {
285 if (mask[i]) {
286 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
287 *aptr = alpha;
288 }
289 }
290 }
291 else {
292 for (i=0;i<n;i++) {
293 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
294 *aptr = alpha;
295 }
296 }
297 }
298
299
300
301 void
302 _mesa_read_alpha_span( GLcontext *ctx,
303 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
304 {
305 const GLchan *buffer, *aptr;
306 GLuint i;
307
308 buffer = get_alpha_buffer(ctx);
309 aptr = buffer + y * ctx->DrawBuffer->Width + x;
310
311 for (i = 0; i < n; i++)
312 rgba[i][ACOMP] = *aptr++;
313 }
314
315
316 void
317 _mesa_read_alpha_pixels( GLcontext *ctx,
318 GLuint n, const GLint x[], const GLint y[],
319 GLchan rgba[][4], const GLubyte mask[] )
320 {
321 const GLchan *buffer;
322 GLuint i;
323
324 buffer = get_alpha_buffer(ctx);
325
326 for (i = 0; i < n; i++) {
327 if (mask[i]) {
328 const GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
329 rgba[i][ACOMP] = *aptr;
330 }
331 }
332 }