1 /* $Id: s_alphabuf.c,v 1.5 2001/03/03 20:33:30 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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_alphabuf.h"
43 #define ALPHA_DRAW_ADDR(X,Y) \
44 (ctx->DrawBuffer->Alpha + (Y) * ctx->DrawBuffer->Width + (X))
46 #define ALPHA_READ_ADDR(X,Y) \
47 (ctx->ReadBuffer->Alpha + (Y) * ctx->ReadBuffer->Width + (X))
52 * Allocate new front/back/left/right alpha buffers.
53 * Input: ctx - the context
57 alloc_alpha_buffers( GLcontext
*ctx
, GLframebuffer
*buf
)
59 GLint bytes
= buf
->Width
* buf
->Height
* sizeof(GLchan
);
61 ASSERT(ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
);
63 if (buf
->FrontLeftAlpha
) {
64 FREE( buf
->FrontLeftAlpha
);
66 buf
->FrontLeftAlpha
= (GLchan
*) MALLOC( bytes
);
67 if (!buf
->FrontLeftAlpha
) {
69 _mesa_error( ctx
, GL_OUT_OF_MEMORY
,
70 "Couldn't allocate front-left alpha buffer" );
73 if (ctx
->Visual
.doubleBufferMode
) {
74 if (buf
->BackLeftAlpha
) {
75 FREE( buf
->BackLeftAlpha
);
77 buf
->BackLeftAlpha
= (GLchan
*) MALLOC( bytes
);
78 if (!buf
->BackLeftAlpha
) {
80 _mesa_error( ctx
, GL_OUT_OF_MEMORY
,
81 "Couldn't allocate back-left alpha buffer" );
85 if (ctx
->Visual
.stereoMode
) {
86 if (buf
->FrontRightAlpha
) {
87 FREE( buf
->FrontRightAlpha
);
89 buf
->FrontRightAlpha
= (GLchan
*) MALLOC( bytes
);
90 if (!buf
->FrontRightAlpha
) {
92 _mesa_error( ctx
, GL_OUT_OF_MEMORY
,
93 "Couldn't allocate front-right alpha buffer" );
96 if (ctx
->Visual
.doubleBufferMode
) {
97 if (buf
->BackRightAlpha
) {
98 FREE( buf
->BackRightAlpha
);
100 buf
->BackRightAlpha
= (GLchan
*) MALLOC( bytes
);
101 if (!buf
->BackRightAlpha
) {
103 _mesa_error( ctx
, GL_OUT_OF_MEMORY
,
104 "Couldn't allocate back-right alpha buffer" );
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
;
121 * Allocate a new front and back alpha buffer.
124 _mesa_alloc_alpha_buffers( GLcontext
*ctx
)
126 alloc_alpha_buffers( ctx
, ctx
->DrawBuffer
);
127 if (ctx
->ReadBuffer
!= ctx
->DrawBuffer
) {
128 alloc_alpha_buffers( ctx
, ctx
->ReadBuffer
);
134 * Clear all the alpha buffers
137 _mesa_clear_alpha_buffers( GLcontext
*ctx
)
139 const GLchan aclear
= ctx
->Color
.ClearColor
[3];
142 ASSERT(ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
);
143 ASSERT(ctx
->Color
.ColorMask
[ACOMP
]);
145 /* loop over four possible alpha buffers */
146 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
147 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
149 if (bufferBit
== FRONT_LEFT_BIT
) {
150 buffer
= ctx
->DrawBuffer
->FrontLeftAlpha
;
152 else if (bufferBit
== FRONT_RIGHT_BIT
) {
153 buffer
= ctx
->DrawBuffer
->FrontRightAlpha
;
155 else if (bufferBit
== BACK_LEFT_BIT
) {
156 buffer
= ctx
->DrawBuffer
->BackLeftAlpha
;
159 buffer
= ctx
->DrawBuffer
->BackRightAlpha
;
162 if (ctx
->Scissor
.Enabled
) {
163 /* clear scissor region */
165 GLint rowLen
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
+ 1;
166 GLint rows
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
+ 1;
167 GLchan
*aptr
= buffer
168 + ctx
->DrawBuffer
->_Ymin
* ctx
->DrawBuffer
->Width
169 + ctx
->DrawBuffer
->_Xmin
;
170 for (j
= 0; j
< rows
; j
++) {
172 MEMSET( aptr
, aclear
, rowLen
);
173 #elif CHAN_BITS == 16
174 MEMSET16( aptr
, aclear
, rowLen
);
176 #error unexpected CHAN_BITS value
182 /* clear whole buffer */
183 GLuint bytes
= ctx
->DrawBuffer
->Width
* ctx
->DrawBuffer
->Height
;
184 MEMSET( buffer
, aclear
, bytes
);
193 _mesa_write_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
194 CONST GLchan rgba
[][4], const GLubyte mask
[] )
196 GLchan
*aptr
= ALPHA_DRAW_ADDR( x
, y
);
202 *aptr
= rgba
[i
][ACOMP
];
209 *aptr
++ = rgba
[i
][ACOMP
];
216 _mesa_write_mono_alpha_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
217 GLchan alpha
, const GLubyte mask
[] )
219 GLchan
*aptr
= ALPHA_DRAW_ADDR( x
, y
);
239 _mesa_write_alpha_pixels( GLcontext
*ctx
,
240 GLuint n
, const GLint x
[], const GLint y
[],
241 CONST GLchan rgba
[][4], const GLubyte mask
[] )
248 GLchan
*aptr
= ALPHA_DRAW_ADDR( x
[i
], y
[i
] );
249 *aptr
= rgba
[i
][ACOMP
];
255 GLchan
*aptr
= ALPHA_DRAW_ADDR( x
[i
], y
[i
] );
256 *aptr
= rgba
[i
][ACOMP
];
263 _mesa_write_mono_alpha_pixels( GLcontext
*ctx
,
264 GLuint n
, const GLint x
[], const GLint y
[],
265 GLchan alpha
, const GLubyte mask
[] )
272 GLchan
*aptr
= ALPHA_DRAW_ADDR( x
[i
], y
[i
] );
279 GLchan
*aptr
= ALPHA_DRAW_ADDR( x
[i
], y
[i
] );
288 _mesa_read_alpha_span( GLcontext
*ctx
,
289 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
291 GLchan
*aptr
= ALPHA_READ_ADDR( x
, y
);
294 rgba
[i
][ACOMP
] = *aptr
++;
300 _mesa_read_alpha_pixels( GLcontext
*ctx
,
301 GLuint n
, const GLint x
[], const GLint y
[],
302 GLchan rgba
[][4], const GLubyte mask
[] )
307 GLchan
*aptr
= ALPHA_READ_ADDR( x
[i
], y
[i
] );
308 rgba
[i
][ACOMP
] = *aptr
;