1 /* $Id: s_alphabuf.c,v 1.14 2002/10/18 17:02:01 kschultz 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.
38 #include "s_context.h"
39 #include "s_alphabuf.h"
43 * Allocate a new front and back alpha buffer.
46 _mesa_alloc_alpha_buffers( GLframebuffer
*buffer
)
48 const GLint bytes
= buffer
->Width
* buffer
->Height
* sizeof(GLchan
);
50 ASSERT(buffer
->UseSoftwareAlphaBuffers
);
52 if (buffer
->FrontLeftAlpha
) {
53 MESA_PBUFFER_FREE( buffer
->FrontLeftAlpha
);
55 buffer
->FrontLeftAlpha
= MESA_PBUFFER_ALLOC( bytes
);
56 if (!buffer
->FrontLeftAlpha
) {
58 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
59 "Couldn't allocate front-left alpha buffer" );
62 if (buffer
->Visual
.doubleBufferMode
) {
63 if (buffer
->BackLeftAlpha
) {
64 MESA_PBUFFER_FREE( buffer
->BackLeftAlpha
);
66 buffer
->BackLeftAlpha
= MESA_PBUFFER_ALLOC( bytes
);
67 if (!buffer
->BackLeftAlpha
) {
69 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
70 "Couldn't allocate back-left alpha buffer" );
74 if (buffer
->Visual
.stereoMode
) {
75 if (buffer
->FrontRightAlpha
) {
76 MESA_PBUFFER_FREE( buffer
->FrontRightAlpha
);
78 buffer
->FrontRightAlpha
= MESA_PBUFFER_ALLOC( bytes
);
79 if (!buffer
->FrontRightAlpha
) {
81 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
82 "Couldn't allocate front-right alpha buffer" );
85 if (buffer
->Visual
.doubleBufferMode
) {
86 if (buffer
->BackRightAlpha
) {
87 MESA_PBUFFER_FREE( buffer
->BackRightAlpha
);
89 buffer
->BackRightAlpha
= MESA_PBUFFER_ALLOC( bytes
);
90 if (!buffer
->BackRightAlpha
) {
92 _mesa_error( NULL
, GL_OUT_OF_MEMORY
,
93 "Couldn't allocate back-right alpha buffer" );
101 * Clear all the alpha buffers
104 _mesa_clear_alpha_buffers( GLcontext
*ctx
)
106 const GLchan aclear
= (GLchan
) ctx
->Color
.ClearColor
[3];
109 ASSERT(ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
);
110 ASSERT(ctx
->Color
.ColorMask
[ACOMP
]);
112 /* loop over four possible alpha buffers */
113 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
114 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
116 if (bufferBit
== FRONT_LEFT_BIT
) {
117 buffer
= (GLchan
*) ctx
->DrawBuffer
->FrontLeftAlpha
;
119 else if (bufferBit
== FRONT_RIGHT_BIT
) {
120 buffer
= (GLchan
*) ctx
->DrawBuffer
->FrontRightAlpha
;
122 else if (bufferBit
== BACK_LEFT_BIT
) {
123 buffer
= (GLchan
*) ctx
->DrawBuffer
->BackLeftAlpha
;
126 buffer
= (GLchan
*) ctx
->DrawBuffer
->BackRightAlpha
;
129 if (ctx
->Scissor
.Enabled
) {
130 /* clear scissor region */
132 GLint rowLen
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
133 GLint rows
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
134 GLint width
= ctx
->DrawBuffer
->Width
;
135 GLchan
*aptr
= buffer
136 + ctx
->DrawBuffer
->_Ymin
* ctx
->DrawBuffer
->Width
137 + ctx
->DrawBuffer
->_Xmin
;
138 for (j
= 0; j
< rows
; j
++) {
140 MEMSET( aptr
, aclear
, rowLen
);
141 #elif CHAN_BITS == 16
142 MEMSET16( aptr
, aclear
, rowLen
);
145 for (i
= 0; i
< rowLen
; i
++) {
153 /* clear whole buffer */
154 GLuint pixels
= ctx
->DrawBuffer
->Width
* ctx
->DrawBuffer
->Height
;
156 MEMSET(buffer
, aclear
, pixels
);
157 #elif CHAN_BITS == 16
158 MEMSET16(buffer
, aclear
, pixels
);
161 for (i
= 0; i
< pixels
; i
++) {
173 GLchan
*get_alpha_buffer( GLcontext
*ctx
)
175 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
177 switch (swrast
->CurrentBuffer
) {
179 return (GLchan
*) ctx
->DrawBuffer
->FrontLeftAlpha
;
182 return (GLchan
*) ctx
->DrawBuffer
->BackLeftAlpha
;
184 case FRONT_RIGHT_BIT
:
185 return (GLchan
*) ctx
->DrawBuffer
->FrontRightAlpha
;
188 return (GLchan
*) ctx
->DrawBuffer
->BackRightAlpha
;
191 _mesa_problem(ctx
, "Bad CurrentBuffer in get_alpha_buffer()");
192 return (GLchan
*) ctx
->DrawBuffer
->FrontLeftAlpha
;
198 _mesa_write_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
199 CONST GLchan rgba
[][4], const GLubyte mask
[] )
201 GLchan
*buffer
, *aptr
;
204 buffer
= get_alpha_buffer(ctx
);
205 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
210 *aptr
= rgba
[i
][ACOMP
];
217 *aptr
++ = rgba
[i
][ACOMP
];
224 _mesa_write_mono_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
225 GLchan alpha
, const GLubyte mask
[] )
227 GLchan
*buffer
, *aptr
;
230 buffer
= get_alpha_buffer(ctx
);
231 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
250 _mesa_write_alpha_pixels( GLcontext
*ctx
,
251 GLuint n
, const GLint x
[], const GLint y
[],
252 CONST GLchan rgba
[][4], const GLubyte mask
[] )
257 buffer
= get_alpha_buffer(ctx
);
262 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
263 *aptr
= rgba
[i
][ACOMP
];
269 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
270 *aptr
= rgba
[i
][ACOMP
];
277 _mesa_write_mono_alpha_pixels( GLcontext
*ctx
,
278 GLuint n
, const GLint x
[], const GLint y
[],
279 GLchan alpha
, const GLubyte mask
[] )
284 buffer
= get_alpha_buffer(ctx
);
289 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
296 GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
305 _mesa_read_alpha_span( GLcontext
*ctx
,
306 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
308 const GLchan
*buffer
, *aptr
;
311 buffer
= get_alpha_buffer(ctx
);
312 aptr
= buffer
+ y
* ctx
->DrawBuffer
->Width
+ x
;
314 for (i
= 0; i
< n
; i
++)
315 rgba
[i
][ACOMP
] = *aptr
++;
320 _mesa_read_alpha_pixels( GLcontext
*ctx
,
321 GLuint n
, const GLint x
[], const GLint y
[],
322 GLchan rgba
[][4], const GLubyte mask
[] )
324 const GLchan
*buffer
;
327 buffer
= get_alpha_buffer(ctx
);
329 for (i
= 0; i
< n
; i
++) {
331 const GLchan
*aptr
= buffer
+ y
[i
] * ctx
->DrawBuffer
->Width
+ x
[i
];
332 rgba
[i
][ACOMP
] = *aptr
;