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
134 #define WRITE_DEPTH_SPAN() \
136 r128WriteDepthSpanLocked( rmesa, n, \
142 #define WRITE_DEPTH_PIXELS() \
144 GLint ox[MAX_WIDTH]; \
145 GLint oy[MAX_WIDTH]; \
146 for ( i = 0 ; i < n ; i++ ) { \
147 ox[i] = x[i] + dPriv->x; \
148 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
150 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
153 #define READ_DEPTH_SPAN() \
155 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
156 r128scrn->spanOffset); \
159 r128ReadDepthSpanLocked( rmesa, n, \
162 r128WaitForIdleLocked( rmesa ); \
164 for ( i = 0 ; i < n ; i++ ) { \
169 #define READ_DEPTH_PIXELS() \
171 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
172 r128scrn->spanOffset); \
173 GLint i, remaining = n; \
175 while ( remaining > 0 ) { \
180 if ( remaining <= 128 ) { \
185 for ( i = 0 ; i < count ; i++ ) { \
186 ox[i] = x[i] + dPriv->x; \
187 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
190 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
191 r128WaitForIdleLocked( rmesa ); \
193 for ( i = 0 ; i < count ; i++ ) { \
199 remaining -= count; \
203 #define TAG(x) r128##x##_z16
204 #include "depthtmp.h"
207 /* 24-bit depth, 8-bit stencil buffer functions
209 #define WRITE_DEPTH_SPAN() \
213 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
214 r128scrn->spanOffset); \
215 r128ReadDepthSpanLocked( rmesa, n, \
218 r128WaitForIdleLocked( rmesa ); \
219 for ( i = 0 ; i < n ; i++ ) { \
220 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
222 r128WriteDepthSpanLocked( rmesa, n, \
228 #define WRITE_DEPTH_PIXELS() \
231 GLint ox[MAX_WIDTH]; \
232 GLint oy[MAX_WIDTH]; \
233 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
234 r128scrn->spanOffset); \
235 for ( i = 0 ; i < n ; i++ ) { \
236 ox[i] = x[i] + dPriv->x; \
237 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
239 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
240 r128WaitForIdleLocked( rmesa ); \
241 for ( i = 0 ; i < n ; i++ ) { \
242 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
244 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
247 #define READ_DEPTH_SPAN() \
249 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
250 r128scrn->spanOffset); \
253 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
254 r128ReadDepthSpanLocked( rmesa, n, \
257 r128WaitForIdleLocked( rmesa ); \
259 for ( i = 0 ; i < n ; i++ ) { \
260 depth[i] = buf[i] & 0x00ffffff; \
264 #define READ_DEPTH_PIXELS() \
266 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
267 r128scrn->spanOffset); \
268 GLint i, remaining = n; \
270 while ( remaining > 0 ) { \
275 if ( remaining <= 128 ) { \
280 for ( i = 0 ; i < count ; i++ ) { \
281 ox[i] = x[i] + dPriv->x; \
282 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
285 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
286 r128WaitForIdleLocked( rmesa ); \
288 for ( i = 0 ; i < count ; i++ ) { \
289 depth[i] = buf[i] & 0x00ffffff; \
294 remaining -= count; \
298 #define TAG(x) r128##x##_z24_s8
299 #include "depthtmp.h"
303 /* ================================================================
307 /* 24 bit depth, 8 bit stencil depthbuffer functions
309 #define WRITE_STENCIL_SPAN() \
313 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
314 r128scrn->spanOffset); \
315 r128ReadDepthSpanLocked( rmesa, n, \
318 r128WaitForIdleLocked( rmesa ); \
319 for ( i = 0 ; i < n ; i++ ) { \
320 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
322 r128WriteDepthSpanLocked( rmesa, n, \
328 #define WRITE_STENCIL_PIXELS() \
331 GLint ox[MAX_WIDTH]; \
332 GLint oy[MAX_WIDTH]; \
333 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
334 r128scrn->spanOffset); \
335 for ( i = 0 ; i < n ; i++ ) { \
336 ox[i] = x[i] + dPriv->x; \
337 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
339 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
340 r128WaitForIdleLocked( rmesa ); \
341 for ( i = 0 ; i < n ; i++ ) { \
342 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
344 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
347 #define READ_STENCIL_SPAN() \
349 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
350 r128scrn->spanOffset); \
353 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
354 r128ReadDepthSpanLocked( rmesa, n, \
357 r128WaitForIdleLocked( rmesa ); \
359 for ( i = 0 ; i < n ; i++ ) { \
360 stencil[i] = (buf[i] & 0xff000000) >> 24; \
364 #define READ_STENCIL_PIXELS() \
366 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
367 r128scrn->spanOffset); \
368 GLint i, remaining = n; \
370 while ( remaining > 0 ) { \
375 if ( remaining <= 128 ) { \
380 for ( i = 0 ; i < count ; i++ ) { \
381 ox[i] = x[i] + dPriv->x; \
382 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
385 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
386 r128WaitForIdleLocked( rmesa ); \
388 for ( i = 0 ; i < count ; i++ ) { \
389 stencil[i] = (buf[i] & 0xff000000) >> 24; \
394 remaining -= count; \
398 #define TAG(x) radeon##x##_z24_s8
399 #include "stenciltmp.h"
402 r128SpanRenderStart( GLcontext
*ctx
)
404 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
406 LOCK_HARDWARE(rmesa
);
407 r128WaitForIdleLocked( rmesa
);
411 r128SpanRenderFinish( GLcontext
*ctx
)
413 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
414 _swrast_flush( ctx
);
415 r128WaitForIdleLocked( rmesa
);
416 UNLOCK_HARDWARE( rmesa
);
419 void r128DDInitSpanFuncs( GLcontext
*ctx
)
421 struct swrast_device_driver
*swdd
= _swrast_GetDeviceDriverReference(ctx
);
422 swdd
->SpanRenderStart
= r128SpanRenderStart
;
423 swdd
->SpanRenderFinish
= r128SpanRenderFinish
;
428 * Plug in the Get/Put routines for the given driRenderbuffer.
431 r128SetSpanFunctions(driRenderbuffer
*drb
, const GLvisual
*vis
)
433 if (drb
->Base
.InternalFormat
== GL_RGBA
) {
434 if (vis
->redBits
== 5 && vis
->greenBits
== 6 && vis
->blueBits
== 5) {
435 r128InitPointers_RGB565(&drb
->Base
);
438 r128InitPointers_ARGB8888(&drb
->Base
);
441 else if (drb
->Base
.InternalFormat
== GL_DEPTH_COMPONENT16
) {
442 r128InitDepthPointers_z16(&drb
->Base
);
444 else if (drb
->Base
.InternalFormat
== GL_DEPTH_COMPONENT24
) {
445 r128InitDepthPointers_z24_s8(&drb
->Base
);
447 else if (drb
->Base
.InternalFormat
== GL_STENCIL_INDEX8_EXT
) {
448 radeonInitStencilPointers_z24_s8(&drb
->Base
);