assorted changes for supporting GLfloat color channels (not done)
[mesa.git] / src / mesa / swrast / s_alphabuf.c
1 /* $Id: s_alphabuf.c,v 1.8 2001/07/13 20:07:37 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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
43 #define ALPHA_DRAW_ADDR(X,Y) \
44 (ctx->DrawBuffer->Alpha + (Y) * ctx->DrawBuffer->Width + (X))
45
46 #define ALPHA_READ_ADDR(X,Y) \
47 (ctx->ReadBuffer->Alpha + (Y) * ctx->ReadBuffer->Width + (X))
48
49
50
51 /*
52 * Allocate new front/back/left/right alpha buffers.
53 * Input: ctx - the context
54 *
55 */
56 static void
57 alloc_alpha_buffers( GLcontext *ctx, GLframebuffer *buf )
58 {
59 GLint bytes = buf->Width * buf->Height * sizeof(GLchan);
60
61 ASSERT(ctx->DrawBuffer->UseSoftwareAlphaBuffers);
62
63 if (buf->FrontLeftAlpha) {
64 FREE( buf->FrontLeftAlpha );
65 }
66 buf->FrontLeftAlpha = (GLchan *) MALLOC( bytes );
67 if (!buf->FrontLeftAlpha) {
68 /* out of memory */
69 _mesa_error( ctx, GL_OUT_OF_MEMORY,
70 "Couldn't allocate front-left alpha buffer" );
71 }
72
73 if (ctx->Visual.doubleBufferMode) {
74 if (buf->BackLeftAlpha) {
75 FREE( buf->BackLeftAlpha );
76 }
77 buf->BackLeftAlpha = (GLchan *) MALLOC( bytes );
78 if (!buf->BackLeftAlpha) {
79 /* out of memory */
80 _mesa_error( ctx, GL_OUT_OF_MEMORY,
81 "Couldn't allocate back-left alpha buffer" );
82 }
83 }
84
85 if (ctx->Visual.stereoMode) {
86 if (buf->FrontRightAlpha) {
87 FREE( buf->FrontRightAlpha );
88 }
89 buf->FrontRightAlpha = (GLchan *) MALLOC( bytes );
90 if (!buf->FrontRightAlpha) {
91 /* out of memory */
92 _mesa_error( ctx, GL_OUT_OF_MEMORY,
93 "Couldn't allocate front-right alpha buffer" );
94 }
95
96 if (ctx->Visual.doubleBufferMode) {
97 if (buf->BackRightAlpha) {
98 FREE( buf->BackRightAlpha );
99 }
100 buf->BackRightAlpha = (GLchan *) MALLOC( bytes );
101 if (!buf->BackRightAlpha) {
102 /* out of memory */
103 _mesa_error( ctx, GL_OUT_OF_MEMORY,
104 "Couldn't allocate back-right alpha buffer" );
105 }
106 }
107 }
108
109 if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT)
110 buf->Alpha = buf->FrontLeftAlpha;
111 else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT)
112 buf->Alpha = buf->BackLeftAlpha;
113 else if (ctx->Color.DriverDrawBuffer == GL_FRONT_RIGHT)
114 buf->Alpha = buf->FrontRightAlpha;
115 else if (ctx->Color.DriverDrawBuffer == GL_BACK_RIGHT)
116 buf->Alpha = buf->BackRightAlpha;
117 }
118
119
120 /*
121 * Allocate a new front and back alpha buffer.
122 */
123 void
124 _mesa_alloc_alpha_buffers( GLcontext *ctx )
125 {
126 alloc_alpha_buffers( ctx, ctx->DrawBuffer );
127 if (ctx->ReadBuffer != ctx->DrawBuffer) {
128 alloc_alpha_buffers( ctx, ctx->ReadBuffer );
129 }
130 }
131
132
133 /*
134 * Clear all the alpha buffers
135 */
136 void
137 _mesa_clear_alpha_buffers( GLcontext *ctx )
138 {
139 const GLchan aclear = ctx->Color.ClearColor[3];
140 GLuint bufferBit;
141
142 ASSERT(ctx->DrawBuffer->UseSoftwareAlphaBuffers);
143 ASSERT(ctx->Color.ColorMask[ACOMP]);
144
145 /* loop over four possible alpha buffers */
146 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
147 if (bufferBit & ctx->Color.DrawDestMask) {
148 GLchan *buffer;
149 if (bufferBit == FRONT_LEFT_BIT) {
150 buffer = ctx->DrawBuffer->FrontLeftAlpha;
151 }
152 else if (bufferBit == FRONT_RIGHT_BIT) {
153 buffer = ctx->DrawBuffer->FrontRightAlpha;
154 }
155 else if (bufferBit == BACK_LEFT_BIT) {
156 buffer = ctx->DrawBuffer->BackLeftAlpha;
157 }
158 else {
159 buffer = ctx->DrawBuffer->BackRightAlpha;
160 }
161
162 if (ctx->Scissor.Enabled) {
163 /* clear scissor region */
164 GLint j;
165 GLint rowLen = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
166 GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
167 GLint width = ctx->DrawBuffer->Width;
168 GLchan *aptr = buffer
169 + ctx->DrawBuffer->_Ymin * ctx->DrawBuffer->Width
170 + ctx->DrawBuffer->_Xmin;
171 for (j = 0; j < rows; j++) {
172 #if CHAN_BITS == 8
173 MEMSET( aptr, aclear, rowLen );
174 #elif CHAN_BITS == 16
175 MEMSET16( aptr, aclear, rowLen );
176 #else
177 GLint i;
178 for (i = 0; i < rowLen; i++) {
179 aptr[i] = aclear;
180 }
181 #endif
182 aptr += width;
183 }
184 }
185 else {
186 /* clear whole buffer */
187 GLuint pixels = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
188 #if CHAN_BITS == 8
189 MEMSET(buffer, aclear, pixels);
190 #elif CHAN_BITS == 16
191 MEMSET16(buffer, aclear, pixels);
192 #else
193 GLuint i;
194 for (i = 0; i < pixels; i++) {
195 buffer[i] = aclear;
196 }
197 #endif
198 }
199 }
200 }
201 }
202
203
204
205 void
206 _mesa_write_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
207 CONST GLchan rgba[][4], const GLubyte mask[] )
208 {
209 GLchan *aptr = ALPHA_DRAW_ADDR( x, y );
210 GLuint i;
211
212 if (mask) {
213 for (i=0;i<n;i++) {
214 if (mask[i]) {
215 *aptr = rgba[i][ACOMP];
216 }
217 aptr++;
218 }
219 }
220 else {
221 for (i=0;i<n;i++) {
222 *aptr++ = rgba[i][ACOMP];
223 }
224 }
225 }
226
227
228 void
229 _mesa_write_mono_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
230 GLchan alpha, const GLubyte mask[] )
231 {
232 GLchan *aptr = ALPHA_DRAW_ADDR( x, y );
233 GLuint i;
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 _mesa_write_alpha_pixels( GLcontext *ctx,
253 GLuint n, const GLint x[], const GLint y[],
254 CONST GLchan rgba[][4], const GLubyte mask[] )
255 {
256 GLuint i;
257
258 if (mask) {
259 for (i=0;i<n;i++) {
260 if (mask[i]) {
261 GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] );
262 *aptr = rgba[i][ACOMP];
263 }
264 }
265 }
266 else {
267 for (i=0;i<n;i++) {
268 GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] );
269 *aptr = rgba[i][ACOMP];
270 }
271 }
272 }
273
274
275 void
276 _mesa_write_mono_alpha_pixels( GLcontext *ctx,
277 GLuint n, const GLint x[], const GLint y[],
278 GLchan alpha, const GLubyte mask[] )
279 {
280 GLuint i;
281
282 if (mask) {
283 for (i=0;i<n;i++) {
284 if (mask[i]) {
285 GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] );
286 *aptr = alpha;
287 }
288 }
289 }
290 else {
291 for (i=0;i<n;i++) {
292 GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] );
293 *aptr = alpha;
294 }
295 }
296 }
297
298
299
300 void
301 _mesa_read_alpha_span( GLcontext *ctx,
302 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
303 {
304 GLchan *aptr = ALPHA_READ_ADDR( x, y );
305 GLuint i;
306 for (i=0;i<n;i++) {
307 rgba[i][ACOMP] = *aptr++;
308 }
309 }
310
311
312 void
313 _mesa_read_alpha_pixels( GLcontext *ctx,
314 GLuint n, const GLint x[], const GLint y[],
315 GLchan rgba[][4], const GLubyte mask[] )
316 {
317 GLuint i;
318 for (i=0;i<n;i++) {
319 if (mask[i]) {
320 GLchan *aptr = ALPHA_READ_ADDR( x[i], y[i] );
321 rgba[i][ACOMP] = *aptr;
322 }
323 }
324 }