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