1 /* $Id: s_alphabuf.c,v 1.16 2002/11/26 02:58:43 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
29 * Software alpha planes. Many frame buffers don't have alpha bits so
30 * we simulate them in software.
39 #include "s_context.h"
40 #include "s_alphabuf.h"
44 * Allocate a new front and back alpha buffer.
47 _mesa_alloc_alpha_buffers( GLframebuffer
*buffer
)
49 const GLint bytes
= buffer
->Width
* buffer
->Height
* sizeof(GLchan
);
51 ASSERT(buffer
->UseSoftwareAlphaBuffers
);
53 if (buffer
->FrontLeftAlpha
) {
54 MESA_PBUFFER_FREE( buffer
->FrontLeftAlpha
);
56 buffer
->FrontLeftAlpha
= MESA_PBUFFER_ALLOC( bytes
);
57 if (!buffer
->FrontLeftAlpha
) {
59 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
60 "Couldn't allocate front-left alpha buffer" );
63 if (buffer
->Visual
.doubleBufferMode
) {
64 if (buffer
->BackLeftAlpha
) {
65 MESA_PBUFFER_FREE( buffer
->BackLeftAlpha
);
67 buffer
->BackLeftAlpha
= MESA_PBUFFER_ALLOC( bytes
);
68 if (!buffer
->BackLeftAlpha
) {
70 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
71 "Couldn't allocate back-left alpha buffer" );
75 if (buffer
->Visual
.stereoMode
) {
76 if (buffer
->FrontRightAlpha
) {
77 MESA_PBUFFER_FREE( buffer
->FrontRightAlpha
);
79 buffer
->FrontRightAlpha
= MESA_PBUFFER_ALLOC( bytes
);
80 if (!buffer
->FrontRightAlpha
) {
82 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
83 "Couldn't allocate front-right alpha buffer" );
86 if (buffer
->Visual
.doubleBufferMode
) {
87 if (buffer
->BackRightAlpha
) {
88 MESA_PBUFFER_FREE( buffer
->BackRightAlpha
);
90 buffer
->BackRightAlpha
= MESA_PBUFFER_ALLOC( bytes
);
91 if (!buffer
->BackRightAlpha
) {
93 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
94 "Couldn't allocate back-right alpha buffer" );
102 * Clear all the alpha buffers
105 _mesa_clear_alpha_buffers( GLcontext
*ctx
)
110 CLAMPED_FLOAT_TO_CHAN(aclear
, ctx
->Color
.ClearColor
[3]);
112 ASSERT(ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
);
113 ASSERT(ctx
->Color
.ColorMask
[ACOMP
]);
115 /* loop over four possible alpha buffers */
116 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
117 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
119 if (bufferBit
== FRONT_LEFT_BIT
) {
120 buffer
= (GLchan
*) ctx
->DrawBuffer
->FrontLeftAlpha
;
122 else if (bufferBit
== FRONT_RIGHT_BIT
) {
123 buffer
= (GLchan
*) ctx
->DrawBuffer
->FrontRightAlpha
;
125 else if (bufferBit
== BACK_LEFT_BIT
) {
126 buffer
= (GLchan
*) ctx
->DrawBuffer
->BackLeftAlpha
;
129 buffer
= (GLchan
*) ctx
->DrawBuffer
->BackRightAlpha
;
132 if (ctx
->Scissor
.Enabled
) {
133 /* clear scissor region */
135 GLint rowLen
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
136 GLint rows
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
137 GLint width
= ctx
->DrawBuffer
->Width
;
138 GLchan
*aptr
= buffer
139 + ctx
->DrawBuffer
->_Ymin
* ctx
->DrawBuffer
->Width
140 + ctx
->DrawBuffer
->_Xmin
;
141 for (j
= 0; j
< rows
; j
++) {
143 MEMSET( aptr
, aclear
, rowLen
);
144 #elif CHAN_BITS == 16
145 MEMSET16( aptr
, aclear
, rowLen
);
148 for (i
= 0; i
< rowLen
; i
++) {
156 /* clear whole buffer */
157 GLuint pixels
= ctx
->DrawBuffer
->Width
* ctx
->DrawBuffer
->Height
;
159 MEMSET(buffer
, aclear
, pixels
);
160 #elif CHAN_BITS == 16
161 MEMSET16(buffer
, aclear
, pixels
);
164 for (i
= 0; i
< pixels
; i
++) {
176 GLchan
*get_alpha_buffer( GLcontext
*ctx
)
178 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
180 switch (swrast
->CurrentBuffer
) {
182 return (GLchan
*) ctx
->DrawBuffer
->FrontLeftAlpha
;
185 return (GLchan
*) ctx
->DrawBuffer
->BackLeftAlpha
;
187 case FRONT_RIGHT_BIT
:
188 return (GLchan
*) ctx
->DrawBuffer
->FrontRightAlpha
;
191 return (GLchan
*) ctx
->DrawBuffer
->BackRightAlpha
;
194 _mesa_problem(ctx
, "Bad CurrentBuffer in get_alpha_buffer()");
195 return (GLchan
*) ctx
->DrawBuffer
->FrontLeftAlpha
;
201 _mesa_write_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
202 CONST GLchan rgba
[][4], const GLubyte mask
[] )
204 GLchan
*buffer
, *aptr
;
207 buffer
= get_alpha_buffer(ctx
);
208 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
213 *aptr
= rgba
[i
][ACOMP
];
220 *aptr
++ = rgba
[i
][ACOMP
];
227 _mesa_write_mono_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
228 GLchan alpha
, const GLubyte mask
[] )
230 GLchan
*buffer
, *aptr
;
233 buffer
= get_alpha_buffer(ctx
);
234 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
253 _mesa_write_alpha_pixels( GLcontext
*ctx
,
254 GLuint n
, const GLint x
[], const GLint y
[],
255 CONST GLchan rgba
[][4], const GLubyte mask
[] )
260 buffer
= get_alpha_buffer(ctx
);
265 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
266 *aptr
= rgba
[i
][ACOMP
];
272 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
273 *aptr
= rgba
[i
][ACOMP
];
280 _mesa_write_mono_alpha_pixels( GLcontext
*ctx
,
281 GLuint n
, const GLint x
[], const GLint y
[],
282 GLchan alpha
, const GLubyte mask
[] )
287 buffer
= get_alpha_buffer(ctx
);
292 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
299 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
308 _mesa_read_alpha_span( GLcontext
*ctx
,
309 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
311 const GLchan
*buffer
, *aptr
;
314 buffer
= get_alpha_buffer(ctx
);
315 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
317 for (i
= 0; i
< n
; i
++)
318 rgba
[i
][ACOMP
] = *aptr
++;
323 _mesa_read_alpha_pixels( GLcontext
*ctx
,
324 GLuint n
, const GLint x
[], const GLint y
[],
325 GLchan rgba
[][4], const GLubyte mask
[] )
327 const GLchan
*buffer
;
330 buffer
= get_alpha_buffer(ctx
);
332 for (i
= 0; i
< n
; i
++) {
334 const GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
335 rgba
[i
][ACOMP
] = *aptr
;