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