2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * Software alpha planes. Many frame buffers don't have alpha bits so
28 * we simulate them in software.
37 #include "s_context.h"
38 #include "s_alphabuf.h"
42 * Allocate a new front and back alpha buffer.
45 _swrast_alloc_alpha_buffers( GLframebuffer
*buffer
)
47 const GLint bytes
= buffer
->Width
* buffer
->Height
* sizeof(GLchan
);
49 ASSERT(buffer
->UseSoftwareAlphaBuffers
);
51 if (buffer
->FrontLeftAlpha
) {
52 MESA_PBUFFER_FREE( buffer
->FrontLeftAlpha
);
54 buffer
->FrontLeftAlpha
= (GLchan
*) MESA_PBUFFER_ALLOC( bytes
);
55 if (!buffer
->FrontLeftAlpha
) {
57 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
58 "Couldn't allocate front-left alpha buffer" );
61 if (buffer
->Visual
.doubleBufferMode
) {
62 if (buffer
->BackLeftAlpha
) {
63 MESA_PBUFFER_FREE( buffer
->BackLeftAlpha
);
65 buffer
->BackLeftAlpha
= (GLchan
*) MESA_PBUFFER_ALLOC( bytes
);
66 if (!buffer
->BackLeftAlpha
) {
68 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
69 "Couldn't allocate back-left alpha buffer" );
73 if (buffer
->Visual
.stereoMode
) {
74 if (buffer
->FrontRightAlpha
) {
75 MESA_PBUFFER_FREE( buffer
->FrontRightAlpha
);
77 buffer
->FrontRightAlpha
= (GLchan
*) MESA_PBUFFER_ALLOC( bytes
);
78 if (!buffer
->FrontRightAlpha
) {
80 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
81 "Couldn't allocate front-right alpha buffer" );
84 if (buffer
->Visual
.doubleBufferMode
) {
85 if (buffer
->BackRightAlpha
) {
86 MESA_PBUFFER_FREE( buffer
->BackRightAlpha
);
88 buffer
->BackRightAlpha
= (GLchan
*) MESA_PBUFFER_ALLOC( bytes
);
89 if (!buffer
->BackRightAlpha
) {
91 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
92 "Couldn't allocate back-right alpha buffer" );
100 * Clear all the alpha buffers
103 _swrast_clear_alpha_buffers( GLcontext
*ctx
)
108 CLAMPED_FLOAT_TO_CHAN(aclear
, ctx
->Color
.ClearColor
[3]);
110 ASSERT(ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
);
111 ASSERT(ctx
->Color
.ColorMask
[ACOMP
]);
113 /* loop over four possible alpha buffers */
114 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
115 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
117 if (bufferBit
== FRONT_LEFT_BIT
) {
118 buffer
= ctx
->DrawBuffer
->FrontLeftAlpha
;
120 else if (bufferBit
== FRONT_RIGHT_BIT
) {
121 buffer
= ctx
->DrawBuffer
->FrontRightAlpha
;
123 else if (bufferBit
== BACK_LEFT_BIT
) {
124 buffer
= ctx
->DrawBuffer
->BackLeftAlpha
;
127 buffer
= ctx
->DrawBuffer
->BackRightAlpha
;
130 if (ctx
->Scissor
.Enabled
) {
131 /* clear scissor region */
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
++) {
141 MEMSET( aptr
, aclear
, rowLen
);
142 #elif CHAN_BITS == 16
143 MEMSET16( aptr
, aclear
, rowLen
);
146 for (i
= 0; i
< rowLen
; i
++) {
154 /* clear whole buffer */
155 GLuint pixels
= ctx
->DrawBuffer
->Width
* ctx
->DrawBuffer
->Height
;
157 MEMSET(buffer
, aclear
, pixels
);
158 #elif CHAN_BITS == 16
159 MEMSET16(buffer
, aclear
, pixels
);
162 for (i
= 0; i
< pixels
; i
++) {
174 GLchan
*get_alpha_buffer( GLcontext
*ctx
)
176 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
178 switch (swrast
->CurrentBuffer
) {
180 return ctx
->DrawBuffer
->FrontLeftAlpha
;
183 return ctx
->DrawBuffer
->BackLeftAlpha
;
185 case FRONT_RIGHT_BIT
:
186 return ctx
->DrawBuffer
->FrontRightAlpha
;
189 return ctx
->DrawBuffer
->BackRightAlpha
;
192 _mesa_problem(ctx
, "Bad CurrentBuffer in get_alpha_buffer()");
193 return (GLchan
*) ctx
->DrawBuffer
->FrontLeftAlpha
;
199 _swrast_write_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
200 CONST GLchan rgba
[][4], const GLubyte mask
[] )
202 GLchan
*buffer
, *aptr
;
205 buffer
= get_alpha_buffer(ctx
);
206 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
211 *aptr
= rgba
[i
][ACOMP
];
218 *aptr
++ = rgba
[i
][ACOMP
];
225 _swrast_write_mono_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
226 GLchan alpha
, const GLubyte mask
[] )
228 GLchan
*buffer
, *aptr
;
231 buffer
= get_alpha_buffer(ctx
);
232 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
251 _swrast_write_alpha_pixels( GLcontext
*ctx
,
252 GLuint n
, const GLint x
[], const GLint y
[],
253 CONST GLchan rgba
[][4], const GLubyte mask
[] )
258 buffer
= get_alpha_buffer(ctx
);
263 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
264 *aptr
= rgba
[i
][ACOMP
];
270 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
271 *aptr
= rgba
[i
][ACOMP
];
278 _swrast_write_mono_alpha_pixels( GLcontext
*ctx
,
279 GLuint n
, const GLint x
[], const GLint y
[],
280 GLchan alpha
, const GLubyte mask
[] )
285 buffer
= get_alpha_buffer(ctx
);
290 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
297 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
306 _swrast_read_alpha_span( GLcontext
*ctx
,
307 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
309 const GLchan
*buffer
, *aptr
;
312 buffer
= get_alpha_buffer(ctx
);
313 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
315 for (i
= 0; i
< n
; i
++)
316 rgba
[i
][ACOMP
] = *aptr
++;
321 _swrast_read_alpha_pixels( GLcontext
*ctx
,
322 GLuint n
, const GLint x
[], const GLint y
[],
323 GLchan rgba
[][4], const GLubyte mask
[] )
325 const GLchan
*buffer
;
328 buffer
= get_alpha_buffer(ctx
);
330 for (i
= 0; i
< n
; i
++) {
332 const GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
333 rgba
[i
][ACOMP
] = *aptr
;