1 /**************************************************************************
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
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 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Gareth Hughes <gareth@valinux.com>
31 * Keith Whitwell <keith@tungstengraphics.com>
32 * Kevin E. Martin <martin@valinux.com>
36 #include "r128_context.h"
37 #include "r128_ioctl.h"
38 #include "r128_state.h"
39 #include "r128_span.h"
42 #include "swrast/swrast.h"
46 #define HAVE_HW_DEPTH_SPANS 1
47 #define HAVE_HW_DEPTH_PIXELS 1
48 #define HAVE_HW_STENCIL_SPANS 1
49 #define HAVE_HW_STENCIL_PIXELS 1
52 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
53 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
54 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
55 driRenderbuffer *drb = (driRenderbuffer *) rb; \
56 GLuint height = dPriv->h; \
60 #define LOCAL_DEPTH_VARS \
61 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
62 r128ScreenPtr r128scrn = rmesa->r128Screen; \
63 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
64 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
65 GLuint height = dPriv->h; \
66 (void) r128scrn; (void) sPriv; (void) height
68 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
70 #define Y_FLIP( _y ) (height - _y - 1)
78 /* ================================================================
82 /* 16 bit, RGB565 color spanline and pixel functions
84 #define SPANTMP_PIXEL_FMT GL_RGB
85 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
87 #define TAG(x) r128##x##_RGB565
88 #define TAG2(x,y) r128##x##_RGB565##y
89 #define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
90 + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
94 /* 32 bit, ARGB8888 color spanline and pixel functions
96 #define SPANTMP_PIXEL_FMT GL_BGRA
97 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
99 #define TAG(x) r128##x##_ARGB8888
100 #define TAG2(x,y) r128##x##_ARGB8888##y
101 #define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
102 + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
103 #include "spantmp2.h"
105 /* Idling in the depth/stencil span functions:
106 * For writes, the kernel reads from the given user-space buffer at dispatch
107 * time, and then writes to the depth buffer asynchronously.
108 * For reads, the kernel reads from the depth buffer and writes to the span
109 * temporary asynchronously.
110 * So, if we're going to read from the span temporary, we need to idle before
111 * doing so. But we don't need to idle after write, because the CPU won't
112 * be accessing the destination, only the accelerator (through 3d rendering or
114 * However, due to interactions from pixel cache between 2d (what we do with
115 * depth) and 3d (all other parts of the system), we idle at the begin and end
116 * of a set of span operations, which should cover the pix cache issue.
117 * Except, we still have major issues, as shown by no_rast=true glxgears, or
121 /* ================================================================
125 /* These functions require locking */
128 #define HW_LOCK() LOCK_HARDWARE(R128_CONTEXT(ctx));
129 #define HW_UNLOCK() UNLOCK_HARDWARE(R128_CONTEXT(ctx));
131 /* 16-bit depth buffer functions
133 #define VALUE_TYPE GLushort
135 #define WRITE_DEPTH_SPAN() \
137 r128WriteDepthSpanLocked( rmesa, n, \
143 #define WRITE_DEPTH_PIXELS() \
145 GLint ox[MAX_WIDTH]; \
146 GLint oy[MAX_WIDTH]; \
147 for ( i = 0 ; i < n ; i++ ) { \
148 ox[i] = x[i] + dPriv->x; \
149 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
151 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
154 #define READ_DEPTH_SPAN() \
156 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
157 r128scrn->spanOffset); \
160 r128ReadDepthSpanLocked( rmesa, n, \
163 r128WaitForIdleLocked( rmesa ); \
165 for ( i = 0 ; i < n ; i++ ) { \
170 #define READ_DEPTH_PIXELS() \
172 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
173 r128scrn->spanOffset); \
174 GLint i, remaining = n; \
176 while ( remaining > 0 ) { \
181 if ( remaining <= 128 ) { \
186 for ( i = 0 ; i < count ; i++ ) { \
187 ox[i] = x[i] + dPriv->x; \
188 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
191 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
192 r128WaitForIdleLocked( rmesa ); \
194 for ( i = 0 ; i < count ; i++ ) { \
200 remaining -= count; \
204 #define TAG(x) r128##x##_z16
205 #include "depthtmp.h"
208 /* 24-bit depth, 8-bit stencil buffer functions
210 #define VALUE_TYPE GLuint
212 #define WRITE_DEPTH_SPAN() \
216 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
217 r128scrn->spanOffset); \
218 r128ReadDepthSpanLocked( rmesa, n, \
221 r128WaitForIdleLocked( rmesa ); \
222 for ( i = 0 ; i < n ; i++ ) { \
223 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
225 r128WriteDepthSpanLocked( rmesa, n, \
231 #define WRITE_DEPTH_PIXELS() \
234 GLint ox[MAX_WIDTH]; \
235 GLint oy[MAX_WIDTH]; \
236 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
237 r128scrn->spanOffset); \
238 for ( i = 0 ; i < n ; i++ ) { \
239 ox[i] = x[i] + dPriv->x; \
240 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
242 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
243 r128WaitForIdleLocked( rmesa ); \
244 for ( i = 0 ; i < n ; i++ ) { \
245 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
247 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
250 #define READ_DEPTH_SPAN() \
252 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
253 r128scrn->spanOffset); \
256 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
257 r128ReadDepthSpanLocked( rmesa, n, \
260 r128WaitForIdleLocked( rmesa ); \
262 for ( i = 0 ; i < n ; i++ ) { \
263 depth[i] = buf[i] & 0x00ffffff; \
267 #define READ_DEPTH_PIXELS() \
269 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
270 r128scrn->spanOffset); \
271 GLint i, remaining = n; \
273 while ( remaining > 0 ) { \
278 if ( remaining <= 128 ) { \
283 for ( i = 0 ; i < count ; i++ ) { \
284 ox[i] = x[i] + dPriv->x; \
285 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
288 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
289 r128WaitForIdleLocked( rmesa ); \
291 for ( i = 0 ; i < count ; i++ ) { \
292 depth[i] = buf[i] & 0x00ffffff; \
297 remaining -= count; \
301 #define TAG(x) r128##x##_z24_s8
302 #include "depthtmp.h"
306 /* ================================================================
310 /* 24 bit depth, 8 bit stencil depthbuffer functions
312 #define WRITE_STENCIL_SPAN() \
316 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
317 r128scrn->spanOffset); \
318 r128ReadDepthSpanLocked( rmesa, n, \
321 r128WaitForIdleLocked( rmesa ); \
322 for ( i = 0 ; i < n ; i++ ) { \
323 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
325 r128WriteDepthSpanLocked( rmesa, n, \
331 #define WRITE_STENCIL_PIXELS() \
334 GLint ox[MAX_WIDTH]; \
335 GLint oy[MAX_WIDTH]; \
336 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
337 r128scrn->spanOffset); \
338 for ( i = 0 ; i < n ; i++ ) { \
339 ox[i] = x[i] + dPriv->x; \
340 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
342 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
343 r128WaitForIdleLocked( rmesa ); \
344 for ( i = 0 ; i < n ; i++ ) { \
345 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
347 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
350 #define READ_STENCIL_SPAN() \
352 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
353 r128scrn->spanOffset); \
356 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
357 r128ReadDepthSpanLocked( rmesa, n, \
360 r128WaitForIdleLocked( rmesa ); \
362 for ( i = 0 ; i < n ; i++ ) { \
363 stencil[i] = (buf[i] & 0xff000000) >> 24; \
367 #define READ_STENCIL_PIXELS() \
369 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
370 r128scrn->spanOffset); \
371 GLint i, remaining = n; \
373 while ( remaining > 0 ) { \
378 if ( remaining <= 128 ) { \
383 for ( i = 0 ; i < count ; i++ ) { \
384 ox[i] = x[i] + dPriv->x; \
385 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
388 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
389 r128WaitForIdleLocked( rmesa ); \
391 for ( i = 0 ; i < count ; i++ ) { \
392 stencil[i] = (buf[i] & 0xff000000) >> 24; \
397 remaining -= count; \
401 #define TAG(x) radeon##x##_z24_s8
402 #include "stenciltmp.h"
405 r128SpanRenderStart( GLcontext
*ctx
)
407 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
409 LOCK_HARDWARE(rmesa
);
410 r128WaitForIdleLocked( rmesa
);
414 r128SpanRenderFinish( GLcontext
*ctx
)
416 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
417 _swrast_flush( ctx
);
418 r128WaitForIdleLocked( rmesa
);
419 UNLOCK_HARDWARE( rmesa
);
422 void r128DDInitSpanFuncs( GLcontext
*ctx
)
424 struct swrast_device_driver
*swdd
= _swrast_GetDeviceDriverReference(ctx
);
425 swdd
->SpanRenderStart
= r128SpanRenderStart
;
426 swdd
->SpanRenderFinish
= r128SpanRenderFinish
;
431 * Plug in the Get/Put routines for the given driRenderbuffer.
434 r128SetSpanFunctions(driRenderbuffer
*drb
, const GLvisual
*vis
)
436 if (drb
->Base
.Format
== MESA_FORMAT_RGB565
) {
437 r128InitPointers_RGB565(&drb
->Base
);
439 else if (drb
->Base
.Format
== MESA_FORMAT_ARGB8888
) {
440 r128InitPointers_ARGB8888(&drb
->Base
);
442 else if (drb
->Base
.Format
== MESA_FORMAT_Z16
) {
443 r128InitDepthPointers_z16(&drb
->Base
);
445 else if (drb
->Base
.Format
== MESA_FORMAT_S8_Z24
) {
446 r128InitDepthPointers_z24_s8(&drb
->Base
);
448 else if (drb
->Base
.Format
== MESA_FORMAT_S8
) {
449 radeonInitStencilPointers_z24_s8(&drb
->Base
);