s/BlendEquatioRGB/BlendEquationRGB/
[mesa.git] / src / mesa / swrast / s_alphabuf.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
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 /*
27 * Software alpha planes. Many frame buffers don't have alpha bits so
28 * we simulate them in software.
29 */
30
31
32 #include "glheader.h"
33 #include "colormac.h"
34 #include "context.h"
35 #include "imports.h"
36
37 #include "s_context.h"
38 #include "s_alphabuf.h"
39
40
41 /*
42 * Allocate a new front and back alpha buffer.
43 */
44 void
45 _swrast_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 = (GLchan *) 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 = (GLchan *) 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 = (GLchan *) 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 = (GLchan *) 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 _swrast_clear_alpha_buffers( GLcontext *ctx )
104 {
105 GLchan aclear;
106 GLuint bufferBit;
107
108 CLAMPED_FLOAT_TO_CHAN(aclear, ctx->Color.ClearColor[3]);
109
110 ASSERT(ctx->DrawBuffer->UseSoftwareAlphaBuffers);
111 ASSERT(ctx->Color.ColorMask[ACOMP]);
112
113 /* loop over four possible alpha buffers */
114 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
115 if (bufferBit & ctx->Color._DrawDestMask) {
116 GLchan *buffer;
117 if (bufferBit == FRONT_LEFT_BIT) {
118 buffer = ctx->DrawBuffer->FrontLeftAlpha;
119 }
120 else if (bufferBit == FRONT_RIGHT_BIT) {
121 buffer = ctx->DrawBuffer->FrontRightAlpha;
122 }
123 else if (bufferBit == BACK_LEFT_BIT) {
124 buffer = ctx->DrawBuffer->BackLeftAlpha;
125 }
126 else {
127 buffer = ctx->DrawBuffer->BackRightAlpha;
128 }
129
130 if (ctx->Scissor.Enabled) {
131 /* clear scissor region */
132 GLint j;
133 GLint rowLen = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
134 GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
135 GLint width = ctx->DrawBuffer->Width;
136 GLchan *aptr = buffer
137 + ctx->DrawBuffer->_Ymin * ctx->DrawBuffer->Width
138 + ctx->DrawBuffer->_Xmin;
139 for (j = 0; j < rows; j++) {
140 #if CHAN_BITS == 8
141 MEMSET( aptr, aclear, rowLen );
142 #elif CHAN_BITS == 16
143 MEMSET16( aptr, aclear, rowLen );
144 #else
145 GLint i;
146 for (i = 0; i < rowLen; i++) {
147 aptr[i] = aclear;
148 }
149 #endif
150 aptr += width;
151 }
152 }
153 else {
154 /* clear whole buffer */
155 GLuint pixels = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
156 #if CHAN_BITS == 8
157 MEMSET(buffer, aclear, pixels);
158 #elif CHAN_BITS == 16
159 MEMSET16(buffer, aclear, pixels);
160 #else
161 GLuint i;
162 for (i = 0; i < pixels; i++) {
163 buffer[i] = aclear;
164 }
165 #endif
166 }
167 }
168 }
169 }
170
171
172
173 static INLINE
174 GLchan *get_alpha_buffer( GLcontext *ctx )
175 {
176 SWcontext *swrast = SWRAST_CONTEXT(ctx);
177
178 switch (swrast->CurrentBuffer) {
179 case FRONT_LEFT_BIT:
180 return ctx->DrawBuffer->FrontLeftAlpha;
181 break;
182 case BACK_LEFT_BIT:
183 return ctx->DrawBuffer->BackLeftAlpha;
184 break;
185 case FRONT_RIGHT_BIT:
186 return ctx->DrawBuffer->FrontRightAlpha;
187 break;
188 case BACK_RIGHT_BIT:
189 return ctx->DrawBuffer->BackRightAlpha;
190 break;
191 default:
192 _mesa_problem(ctx, "Bad CurrentBuffer in get_alpha_buffer()");
193 return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
194 }
195 }
196
197
198 void
199 _swrast_write_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
200 CONST GLchan rgba[][4], const GLubyte mask[] )
201 {
202 GLchan *buffer, *aptr;
203 GLuint i;
204
205 buffer = get_alpha_buffer(ctx);
206 aptr = buffer + y * ctx->DrawBuffer->Width + x;
207
208 if (mask) {
209 for (i=0;i<n;i++) {
210 if (mask[i]) {
211 *aptr = rgba[i][ACOMP];
212 }
213 aptr++;
214 }
215 }
216 else {
217 for (i=0;i<n;i++) {
218 *aptr++ = rgba[i][ACOMP];
219 }
220 }
221 }
222
223
224 void
225 _swrast_write_mono_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
226 GLchan alpha, const GLubyte mask[] )
227 {
228 GLchan *buffer, *aptr;
229 GLuint i;
230
231 buffer = get_alpha_buffer(ctx);
232 aptr = buffer + y * ctx->DrawBuffer->Width + x;
233
234 if (mask) {
235 for (i=0;i<n;i++) {
236 if (mask[i]) {
237 *aptr = alpha;
238 }
239 aptr++;
240 }
241 }
242 else {
243 for (i=0;i<n;i++) {
244 *aptr++ = alpha;
245 }
246 }
247 }
248
249
250 void
251 _swrast_write_alpha_pixels( GLcontext *ctx,
252 GLuint n, const GLint x[], const GLint y[],
253 CONST GLchan rgba[][4], const GLubyte mask[] )
254 {
255 GLchan *buffer;
256 GLuint i;
257
258 buffer = get_alpha_buffer(ctx);
259
260 if (mask) {
261 for (i=0;i<n;i++) {
262 if (mask[i]) {
263 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
264 *aptr = rgba[i][ACOMP];
265 }
266 }
267 }
268 else {
269 for (i=0;i<n;i++) {
270 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
271 *aptr = rgba[i][ACOMP];
272 }
273 }
274 }
275
276
277 void
278 _swrast_write_mono_alpha_pixels( GLcontext *ctx,
279 GLuint n, const GLint x[], const GLint y[],
280 GLchan alpha, const GLubyte mask[] )
281 {
282 GLchan *buffer;
283 GLuint i;
284
285 buffer = get_alpha_buffer(ctx);
286
287 if (mask) {
288 for (i=0;i<n;i++) {
289 if (mask[i]) {
290 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
291 *aptr = alpha;
292 }
293 }
294 }
295 else {
296 for (i=0;i<n;i++) {
297 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
298 *aptr = alpha;
299 }
300 }
301 }
302
303
304
305 void
306 _swrast_read_alpha_span( GLcontext *ctx,
307 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
308 {
309 const GLchan *buffer, *aptr;
310 GLuint i;
311
312 buffer = get_alpha_buffer(ctx);
313 aptr = buffer + y * ctx->DrawBuffer->Width + x;
314
315 for (i = 0; i < n; i++)
316 rgba[i][ACOMP] = *aptr++;
317 }
318
319
320 void
321 _swrast_read_alpha_pixels( GLcontext *ctx,
322 GLuint n, const GLint x[], const GLint y[],
323 GLchan rgba[][4], const GLubyte mask[] )
324 {
325 const GLchan *buffer;
326 GLuint i;
327
328 buffer = get_alpha_buffer(ctx);
329
330 for (i = 0; i < n; i++) {
331 if (mask[i]) {
332 const GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
333 rgba[i][ACOMP] = *aptr;
334 }
335 }
336 }