Implemented support for software-based AUX color buffers.
[mesa.git] / src / mesa / drivers / dri / r128 / r128_span.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.c,v 1.8 2002/10/30 12:51:39 alanh Exp $ */
2 /**************************************************************************
3
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
5 Cedar Park, Texas.
6 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 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Gareth Hughes <gareth@valinux.com>
32 * Keith Whitwell <keith@tungstengraphics.com>
33 * Kevin E. Martin <martin@valinux.com>
34 *
35 */
36
37 #include "r128_context.h"
38 #include "r128_ioctl.h"
39 #include "r128_state.h"
40 #include "r128_span.h"
41 #include "r128_tex.h"
42
43 #include "swrast/swrast.h"
44
45 #define DBG 0
46
47 #define HAVE_HW_DEPTH_SPANS 1
48 #define HAVE_HW_DEPTH_PIXELS 1
49
50 #define LOCAL_VARS \
51 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
52 r128ScreenPtr r128scrn = rmesa->r128Screen; \
53 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
54 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
55 GLuint pitch = r128scrn->frontPitch * r128scrn->cpp; \
56 GLuint height = dPriv->h; \
57 char *buf = (char *)(sPriv->pFB + \
58 rmesa->drawOffset + \
59 (dPriv->x * r128scrn->cpp) + \
60 (dPriv->y * pitch)); \
61 char *read_buf = (char *)(sPriv->pFB + \
62 rmesa->readOffset + \
63 (dPriv->x * r128scrn->cpp) + \
64 (dPriv->y * pitch)); \
65 GLuint p; \
66 (void) read_buf; (void) buf; (void) p
67
68 #define LOCAL_DEPTH_VARS \
69 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
70 r128ScreenPtr r128scrn = rmesa->r128Screen; \
71 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
72 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
73 GLuint height = dPriv->h; \
74 (void) r128scrn; (void) sPriv; (void) height
75
76 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
77
78
79 #define CLIPPIXEL( _x, _y ) \
80 ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
81
82
83 #define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
84 if ( _y < miny || _y >= maxy ) { \
85 _n1 = 0, _x1 = x; \
86 } else { \
87 _n1 = _n; \
88 _x1 = _x; \
89 if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
90 if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
91 }
92
93 #define Y_FLIP( _y ) (height - _y - 1)
94
95
96 #define HW_LOCK() \
97 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
98 FLUSH_BATCH( rmesa ); \
99 LOCK_HARDWARE( rmesa ); \
100 r128WaitForIdleLocked( rmesa );
101
102 #define HW_CLIPLOOP() \
103 do { \
104 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
105 int _nc = dPriv->numClipRects; \
106 \
107 while ( _nc-- ) { \
108 int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
109 int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
110 int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
111 int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
112
113 #define HW_ENDCLIPLOOP() \
114 } \
115 } while (0)
116
117 #define HW_UNLOCK() \
118 UNLOCK_HARDWARE( rmesa )
119
120
121
122 /* ================================================================
123 * Color buffer
124 */
125
126 /* 16 bit, RGB565 color spanline and pixel functions
127 */
128 #undef INIT_MONO_PIXEL
129 #define INIT_MONO_PIXEL(p, color) \
130 p = R128PACKCOLOR565( color[0], color[1], color[2] )
131
132 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
133 *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \
134 (((int)g & 0xfc) << 3) | \
135 (((int)b & 0xf8) >> 3))
136
137 #define WRITE_PIXEL( _x, _y, p ) \
138 *(GLushort *)(buf + _x*2 + _y*pitch) = p
139
140 #define READ_RGBA( rgba, _x, _y ) \
141 do { \
142 GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
143 rgba[0] = (p >> 8) & 0xf8; \
144 rgba[1] = (p >> 3) & 0xfc; \
145 rgba[2] = (p << 3) & 0xf8; \
146 rgba[3] = 0xff; \
147 if ( rgba[0] & 0x08 ) rgba[0] |= 0x07; \
148 if ( rgba[1] & 0x04 ) rgba[1] |= 0x03; \
149 if ( rgba[2] & 0x08 ) rgba[2] |= 0x07; \
150 } while (0)
151
152 #define TAG(x) r128##x##_RGB565
153 #include "spantmp.h"
154
155 #define READ_DEPTH(d, _x, _y) \
156 d = *(GLushort *)(buf + _x*2 + _y*pitch)
157
158 /* 32 bit, ARGB8888 color spanline and pixel functions
159 */
160 #undef INIT_MONO_PIXEL
161 #define INIT_MONO_PIXEL(p, color) \
162 p = R128PACKCOLOR8888( color[0], color[1], color[2], color[3] )
163
164 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
165 *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
166 (g << 8) | \
167 (r << 16) | \
168 (a << 24) )
169
170 #define WRITE_PIXEL( _x, _y, p ) \
171 *(GLuint *)(buf + _x*4 + _y*pitch) = p
172
173 #define READ_RGBA( rgba, _x, _y ) \
174 do { \
175 GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \
176 rgba[0] = (p >> 16) & 0xff; \
177 rgba[1] = (p >> 8) & 0xff; \
178 rgba[2] = (p >> 0) & 0xff; \
179 rgba[3] = 0xff;/*(p >> 24) & 0xff;*/ \
180 } while (0)
181
182 #define TAG(x) r128##x##_ARGB8888
183 #include "spantmp.h"
184
185
186 /* 24 bit, RGB888 color spanline and pixel functions */
187 #undef INIT_MONO_PIXEL
188 #define INIT_MONO_PIXEL(p, color) \
189 p = R128PACKCOLOR888( color[0], color[1], color[2] )
190
191 #define WRITE_RGBA(_x, _y, r, g, b, a) \
192 *(GLuint *)(buf + _x*3 + _y*pitch) = ((r << 16) | \
193 (g << 8) | \
194 (b << 0))
195
196 #define WRITE_PIXEL(_x, _y, p) \
197 *(GLuint *)(buf + _x*3 + _y*pitch) = p
198
199 #define READ_RGBA(rgba, _x, _y) \
200 do { \
201 GLuint p = *(GLuint *)(read_buf + _x*3 + _y*pitch); \
202 rgba[0] = (p >> 16) & 0xff; \
203 rgba[1] = (p >> 8) & 0xff; \
204 rgba[2] = (p >> 0) & 0xff; \
205 rgba[3] = 0xff; \
206 } while (0)
207
208 /* ================================================================
209 * Depth buffer
210 */
211
212 /* 16-bit depth buffer functions
213 */
214 #define WRITE_DEPTH_SPAN() \
215 r128WriteDepthSpanLocked( rmesa, n, \
216 x + dPriv->x, \
217 y + dPriv->y, \
218 depth, mask );
219
220 #define WRITE_DEPTH_PIXELS() \
221 do { \
222 GLint ox[MAX_WIDTH]; \
223 GLint oy[MAX_WIDTH]; \
224 for ( i = 0 ; i < n ; i++ ) { \
225 ox[i] = x[i] + dPriv->x; \
226 } \
227 for ( i = 0 ; i < n ; i++ ) { \
228 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
229 } \
230 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
231 } while (0)
232
233 #define READ_DEPTH_SPAN() \
234 do { \
235 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
236 r128scrn->spanOffset); \
237 GLint i; \
238 \
239 r128ReadDepthSpanLocked( rmesa, n, \
240 x + dPriv->x, \
241 y + dPriv->y ); \
242 r128WaitForIdleLocked( rmesa ); \
243 \
244 for ( i = 0 ; i < n ; i++ ) { \
245 depth[i] = buf[i]; \
246 } \
247 } while (0)
248
249 #define READ_DEPTH_PIXELS() \
250 do { \
251 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
252 r128scrn->spanOffset); \
253 GLint i, remaining = n; \
254 \
255 while ( remaining > 0 ) { \
256 GLint ox[MAX_WIDTH]; \
257 GLint oy[MAX_WIDTH]; \
258 GLint count; \
259 \
260 if ( remaining <= 128 ) { \
261 count = remaining; \
262 } else { \
263 count = 128; \
264 } \
265 for ( i = 0 ; i < count ; i++ ) { \
266 ox[i] = x[i] + dPriv->x; \
267 } \
268 for ( i = 0 ; i < count ; i++ ) { \
269 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
270 } \
271 \
272 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
273 r128WaitForIdleLocked( rmesa ); \
274 \
275 for ( i = 0 ; i < count ; i++ ) { \
276 depth[i] = buf[i]; \
277 } \
278 depth += count; \
279 x += count; \
280 y += count; \
281 remaining -= count; \
282 } \
283 } while (0)
284
285 #define TAG(x) r128##x##_16
286 #include "depthtmp.h"
287
288
289 /* 24-bit depth, 8-bit stencil buffer functions
290 */
291 #define WRITE_DEPTH_SPAN() \
292 r128WriteDepthSpanLocked( rmesa, n, \
293 x + dPriv->x, \
294 y + dPriv->y, \
295 depth, mask );
296
297 #define WRITE_DEPTH_PIXELS() \
298 do { \
299 GLint ox[MAX_WIDTH]; \
300 GLint oy[MAX_WIDTH]; \
301 for ( i = 0 ; i < n ; i++ ) { \
302 ox[i] = x[i] + dPriv->x; \
303 } \
304 for ( i = 0 ; i < n ; i++ ) { \
305 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
306 } \
307 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
308 } while (0)
309
310 #define READ_DEPTH_SPAN() \
311 do { \
312 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
313 r128scrn->spanOffset); \
314 GLint i; \
315 \
316 r128ReadDepthSpanLocked( rmesa, n, \
317 x + dPriv->x, \
318 y + dPriv->y ); \
319 r128WaitForIdleLocked( rmesa ); \
320 \
321 for ( i = 0 ; i < n ; i++ ) { \
322 depth[i] = buf[i] & 0x00ffffff; \
323 } \
324 } while (0)
325
326 #define READ_DEPTH_PIXELS() \
327 do { \
328 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
329 r128scrn->spanOffset); \
330 GLint i, remaining = n; \
331 \
332 while ( remaining > 0 ) { \
333 GLint ox[MAX_WIDTH]; \
334 GLint oy[MAX_WIDTH]; \
335 GLint count; \
336 \
337 if ( remaining <= 128 ) { \
338 count = remaining; \
339 } else { \
340 count = 128; \
341 } \
342 for ( i = 0 ; i < count ; i++ ) { \
343 ox[i] = x[i] + dPriv->x; \
344 } \
345 for ( i = 0 ; i < count ; i++ ) { \
346 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
347 } \
348 \
349 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
350 r128WaitForIdleLocked( rmesa ); \
351 \
352 for ( i = 0 ; i < count ; i++ ) { \
353 depth[i] = buf[i] & 0x00ffffff; \
354 } \
355 depth += count; \
356 x += count; \
357 y += count; \
358 remaining -= count; \
359 } \
360 } while (0)
361
362 #define TAG(x) r128##x##_24_8
363 #include "depthtmp.h"
364
365
366
367 /* ================================================================
368 * Stencil buffer
369 */
370
371 /* FIXME: Add support for hardware stencil buffers.
372 */
373
374
375 /* 32 bit depthbuffer functions */
376 #define WRITE_DEPTH(_x, _y, d) \
377 *(GLuint *)(buf + _x*4 + _y*pitch) = d
378
379
380
381 /*
382 * This function is called to specify which buffer to read and write
383 * for software rasterization (swrast) fallbacks. This doesn't necessarily
384 * correspond to glDrawBuffer() or glReadBuffer() calls.
385 */
386 static void r128DDSetBuffer( GLcontext *ctx,
387 GLframebuffer *colorBuffer,
388 GLuint bufferBit )
389 {
390 r128ContextPtr rmesa = R128_CONTEXT(ctx);
391
392 switch ( bufferBit ) {
393 case DD_FRONT_LEFT_BIT:
394 if ( rmesa->sarea->pfCurrentPage == 1 ) {
395 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
396 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
397 } else {
398 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
399 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
400 }
401 break;
402 case DD_BACK_LEFT_BIT:
403 if ( rmesa->sarea->pfCurrentPage == 1 ) {
404 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
405 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
406 } else {
407 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
408 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
409 }
410 break;
411 default:
412 break;
413 }
414 }
415
416
417 void r128DDInitSpanFuncs( GLcontext *ctx )
418 {
419 r128ContextPtr rmesa = R128_CONTEXT(ctx);
420 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
421
422 swdd->SetBuffer = r128DDSetBuffer;
423
424 switch ( rmesa->r128Screen->cpp ) {
425 case 2:
426 swdd->WriteRGBASpan = r128WriteRGBASpan_RGB565;
427 swdd->WriteRGBSpan = r128WriteRGBSpan_RGB565;
428 swdd->WriteMonoRGBASpan = r128WriteMonoRGBASpan_RGB565;
429 swdd->WriteRGBAPixels = r128WriteRGBAPixels_RGB565;
430 swdd->WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_RGB565;
431 swdd->ReadRGBASpan = r128ReadRGBASpan_RGB565;
432 swdd->ReadRGBAPixels = r128ReadRGBAPixels_RGB565;
433 break;
434
435 case 4:
436 swdd->WriteRGBASpan = r128WriteRGBASpan_ARGB8888;
437 swdd->WriteRGBSpan = r128WriteRGBSpan_ARGB8888;
438 swdd->WriteMonoRGBASpan = r128WriteMonoRGBASpan_ARGB8888;
439 swdd->WriteRGBAPixels = r128WriteRGBAPixels_ARGB8888;
440 swdd->WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_ARGB8888;
441 swdd->ReadRGBASpan = r128ReadRGBASpan_ARGB8888;
442 swdd->ReadRGBAPixels = r128ReadRGBAPixels_ARGB8888;
443 break;
444
445 default:
446 break;
447 }
448
449 switch ( rmesa->glCtx->Visual.depthBits ) {
450 case 16:
451 swdd->ReadDepthSpan = r128ReadDepthSpan_16;
452 swdd->WriteDepthSpan = r128WriteDepthSpan_16;
453 swdd->ReadDepthPixels = r128ReadDepthPixels_16;
454 swdd->WriteDepthPixels = r128WriteDepthPixels_16;
455 break;
456
457 case 24:
458 swdd->ReadDepthSpan = r128ReadDepthSpan_24_8;
459 swdd->WriteDepthSpan = r128WriteDepthSpan_24_8;
460 swdd->ReadDepthPixels = r128ReadDepthPixels_24_8;
461 swdd->WriteDepthPixels = r128WriteDepthPixels_24_8;
462 break;
463
464 default:
465 break;
466 }
467
468 swdd->WriteCI8Span = NULL;
469 swdd->WriteCI32Span = NULL;
470 swdd->WriteMonoCISpan = NULL;
471 swdd->WriteCI32Pixels = NULL;
472 swdd->WriteMonoCIPixels = NULL;
473 swdd->ReadCI32Span = NULL;
474 swdd->ReadCI32Pixels = NULL;
475 }