Removed all RCS / CVS tags (Id, Header, Date, etc.) from everything.
[mesa.git] / src / mesa / swrast / s_alphabuf.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 5.0.1
5 *
6 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /*
28 * Software alpha planes. Many frame buffers don't have alpha bits so
29 * we simulate them in software.
30 */
31
32
33 #include "glheader.h"
34 #include "colormac.h"
35 #include "context.h"
36 #include "imports.h"
37
38 #include "s_context.h"
39 #include "s_alphabuf.h"
40
41
42 /*
43 * Allocate a new front and back alpha buffer.
44 */
45 void
46 _swrast_alloc_alpha_buffers( GLframebuffer *buffer )
47 {
48 const GLint bytes = buffer->Width * buffer->Height * sizeof(GLchan);
49
50 ASSERT(buffer->UseSoftwareAlphaBuffers);
51
52 if (buffer->FrontLeftAlpha) {
53 MESA_PBUFFER_FREE( buffer->FrontLeftAlpha );
54 }
55 buffer->FrontLeftAlpha = MESA_PBUFFER_ALLOC( bytes );
56 if (!buffer->FrontLeftAlpha) {
57 /* out of memory */
58 _mesa_error( NULL, GL_OUT_OF_MEMORY,
59 "Couldn't allocate front-left alpha buffer" );
60 }
61
62 if (buffer->Visual.doubleBufferMode) {
63 if (buffer->BackLeftAlpha) {
64 MESA_PBUFFER_FREE( buffer->BackLeftAlpha );
65 }
66 buffer->BackLeftAlpha = MESA_PBUFFER_ALLOC( bytes );
67 if (!buffer->BackLeftAlpha) {
68 /* out of memory */
69 _mesa_error( NULL, GL_OUT_OF_MEMORY,
70 "Couldn't allocate back-left alpha buffer" );
71 }
72 }
73
74 if (buffer->Visual.stereoMode) {
75 if (buffer->FrontRightAlpha) {
76 MESA_PBUFFER_FREE( buffer->FrontRightAlpha );
77 }
78 buffer->FrontRightAlpha = MESA_PBUFFER_ALLOC( bytes );
79 if (!buffer->FrontRightAlpha) {
80 /* out of memory */
81 _mesa_error( NULL, GL_OUT_OF_MEMORY,
82 "Couldn't allocate front-right alpha buffer" );
83 }
84
85 if (buffer->Visual.doubleBufferMode) {
86 if (buffer->BackRightAlpha) {
87 MESA_PBUFFER_FREE( buffer->BackRightAlpha );
88 }
89 buffer->BackRightAlpha = MESA_PBUFFER_ALLOC( bytes );
90 if (!buffer->BackRightAlpha) {
91 /* out of memory */
92 _mesa_error( NULL, GL_OUT_OF_MEMORY,
93 "Couldn't allocate back-right alpha buffer" );
94 }
95 }
96 }
97 }
98
99
100 /*
101 * Clear all the alpha buffers
102 */
103 void
104 _swrast_clear_alpha_buffers( GLcontext *ctx )
105 {
106 GLchan aclear;
107 GLuint bufferBit;
108
109 CLAMPED_FLOAT_TO_CHAN(aclear, ctx->Color.ClearColor[3]);
110
111 ASSERT(ctx->DrawBuffer->UseSoftwareAlphaBuffers);
112 ASSERT(ctx->Color.ColorMask[ACOMP]);
113
114 /* loop over four possible alpha buffers */
115 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
116 if (bufferBit & ctx->Color._DrawDestMask) {
117 GLchan *buffer;
118 if (bufferBit == FRONT_LEFT_BIT) {
119 buffer = (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
120 }
121 else if (bufferBit == FRONT_RIGHT_BIT) {
122 buffer = (GLchan *) ctx->DrawBuffer->FrontRightAlpha;
123 }
124 else if (bufferBit == BACK_LEFT_BIT) {
125 buffer = (GLchan *) ctx->DrawBuffer->BackLeftAlpha;
126 }
127 else {
128 buffer = (GLchan *) ctx->DrawBuffer->BackRightAlpha;
129 }
130
131 if (ctx->Scissor.Enabled) {
132 /* clear scissor region */
133 GLint j;
134 GLint rowLen = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
135 GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
136 GLint width = ctx->DrawBuffer->Width;
137 GLchan *aptr = buffer
138 + ctx->DrawBuffer->_Ymin * ctx->DrawBuffer->Width
139 + ctx->DrawBuffer->_Xmin;
140 for (j = 0; j < rows; j++) {
141 #if CHAN_BITS == 8
142 MEMSET( aptr, aclear, rowLen );
143 #elif CHAN_BITS == 16
144 MEMSET16( aptr, aclear, rowLen );
145 #else
146 GLint i;
147 for (i = 0; i < rowLen; i++) {
148 aptr[i] = aclear;
149 }
150 #endif
151 aptr += width;
152 }
153 }
154 else {
155 /* clear whole buffer */
156 GLuint pixels = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
157 #if CHAN_BITS == 8
158 MEMSET(buffer, aclear, pixels);
159 #elif CHAN_BITS == 16
160 MEMSET16(buffer, aclear, pixels);
161 #else
162 GLuint i;
163 for (i = 0; i < pixels; i++) {
164 buffer[i] = aclear;
165 }
166 #endif
167 }
168 }
169 }
170 }
171
172
173
174 static INLINE
175 GLchan *get_alpha_buffer( GLcontext *ctx )
176 {
177 SWcontext *swrast = SWRAST_CONTEXT(ctx);
178
179 switch (swrast->CurrentBuffer) {
180 case FRONT_LEFT_BIT:
181 return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
182 break;
183 case BACK_LEFT_BIT:
184 return (GLchan *) ctx->DrawBuffer->BackLeftAlpha;
185 break;
186 case FRONT_RIGHT_BIT:
187 return (GLchan *) ctx->DrawBuffer->FrontRightAlpha;
188 break;
189 case BACK_RIGHT_BIT:
190 return (GLchan *) ctx->DrawBuffer->BackRightAlpha;
191 break;
192 default:
193 _mesa_problem(ctx, "Bad CurrentBuffer in get_alpha_buffer()");
194 return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
195 }
196 }
197
198
199 void
200 _swrast_write_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
201 CONST GLchan rgba[][4], const GLubyte mask[] )
202 {
203 GLchan *buffer, *aptr;
204 GLuint i;
205
206 buffer = get_alpha_buffer(ctx);
207 aptr = buffer + y * ctx->DrawBuffer->Width + x;
208
209 if (mask) {
210 for (i=0;i<n;i++) {
211 if (mask[i]) {
212 *aptr = rgba[i][ACOMP];
213 }
214 aptr++;
215 }
216 }
217 else {
218 for (i=0;i<n;i++) {
219 *aptr++ = rgba[i][ACOMP];
220 }
221 }
222 }
223
224
225 void
226 _swrast_write_mono_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
227 GLchan alpha, const GLubyte mask[] )
228 {
229 GLchan *buffer, *aptr;
230 GLuint i;
231
232 buffer = get_alpha_buffer(ctx);
233 aptr = buffer + y * ctx->DrawBuffer->Width + x;
234
235 if (mask) {
236 for (i=0;i<n;i++) {
237 if (mask[i]) {
238 *aptr = alpha;
239 }
240 aptr++;
241 }
242 }
243 else {
244 for (i=0;i<n;i++) {
245 *aptr++ = alpha;
246 }
247 }
248 }
249
250
251 void
252 _swrast_write_alpha_pixels( GLcontext *ctx,
253 GLuint n, const GLint x[], const GLint y[],
254 CONST GLchan rgba[][4], const GLubyte mask[] )
255 {
256 GLchan *buffer;
257 GLuint i;
258
259 buffer = get_alpha_buffer(ctx);
260
261 if (mask) {
262 for (i=0;i<n;i++) {
263 if (mask[i]) {
264 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
265 *aptr = rgba[i][ACOMP];
266 }
267 }
268 }
269 else {
270 for (i=0;i<n;i++) {
271 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
272 *aptr = rgba[i][ACOMP];
273 }
274 }
275 }
276
277
278 void
279 _swrast_write_mono_alpha_pixels( GLcontext *ctx,
280 GLuint n, const GLint x[], const GLint y[],
281 GLchan alpha, const GLubyte mask[] )
282 {
283 GLchan *buffer;
284 GLuint i;
285
286 buffer = get_alpha_buffer(ctx);
287
288 if (mask) {
289 for (i=0;i<n;i++) {
290 if (mask[i]) {
291 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
292 *aptr = alpha;
293 }
294 }
295 }
296 else {
297 for (i=0;i<n;i++) {
298 GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
299 *aptr = alpha;
300 }
301 }
302 }
303
304
305
306 void
307 _swrast_read_alpha_span( GLcontext *ctx,
308 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
309 {
310 const GLchan *buffer, *aptr;
311 GLuint i;
312
313 buffer = get_alpha_buffer(ctx);
314 aptr = buffer + y * ctx->DrawBuffer->Width + x;
315
316 for (i = 0; i < n; i++)
317 rgba[i][ACOMP] = *aptr++;
318 }
319
320
321 void
322 _swrast_read_alpha_pixels( GLcontext *ctx,
323 GLuint n, const GLint x[], const GLint y[],
324 GLchan rgba[][4], const GLubyte mask[] )
325 {
326 const GLchan *buffer;
327 GLuint i;
328
329 buffer = get_alpha_buffer(ctx);
330
331 for (i = 0; i < n; i++) {
332 if (mask[i]) {
333 const GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
334 rgba[i][ACOMP] = *aptr;
335 }
336 }
337 }