-/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.c,v 1.8 2002/10/30 12:51:39 alanh Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
#define HAVE_HW_DEPTH_SPANS 1
#define HAVE_HW_DEPTH_PIXELS 1
+#define HAVE_HW_STENCIL_SPANS 1
+#define HAVE_HW_STENCIL_PIXELS 1
#define LOCAL_VARS \
r128ContextPtr rmesa = R128_CONTEXT(ctx); \
- r128ScreenPtr r128scrn = rmesa->r128Screen; \
__DRIscreenPrivate *sPriv = rmesa->driScreen; \
__DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
- GLuint pitch = r128scrn->frontPitch * r128scrn->cpp; \
+ driRenderbuffer *drb = (driRenderbuffer *) rb; \
GLuint height = dPriv->h; \
- char *buf = (char *)(sPriv->pFB + \
- rmesa->drawOffset + \
- (dPriv->x * r128scrn->cpp) + \
- (dPriv->y * pitch)); \
- char *read_buf = (char *)(sPriv->pFB + \
- rmesa->readOffset + \
- (dPriv->x * r128scrn->cpp) + \
- (dPriv->y * pitch)); \
GLuint p; \
- (void) read_buf; (void) buf; (void) p
+ (void) p;
#define LOCAL_DEPTH_VARS \
r128ContextPtr rmesa = R128_CONTEXT(ctx); \
#define TAG(x) r128##x##_RGB565
#define TAG2(x,y) r128##x##_RGB565##y
+#define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
+ + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
#include "spantmp2.h"
#define TAG(x) r128##x##_ARGB8888
#define TAG2(x,y) r128##x##_ARGB8888##y
+#define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
+ + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
#include "spantmp2.h"
+/* Idling in the depth/stencil span functions:
+ * For writes, the kernel reads from the given user-space buffer at dispatch
+ * time, and then writes to the depth buffer asynchronously.
+ * For reads, the kernel reads from the depth buffer and writes to the span
+ * temporary asynchronously.
+ * So, if we're going to read from the span temporary, we need to idle before
+ * doing so. But we don't need to idle after write, because the CPU won't
+ * be accessing the destination, only the accelerator (through 3d rendering or
+ * depth span reads)
+ * However, due to interactions from pixel cache between 2d (what we do with
+ * depth) and 3d (all other parts of the system), we idle at the begin and end
+ * of a set of span operations, which should cover the pix cache issue.
+ * Except, we still have major issues, as shown by no_rast=true glxgears, or
+ * stencilwrap.
+ */
/* ================================================================
* Depth buffer
*/
+/* These functions require locking */
+#undef HW_LOCK
+#undef HW_UNLOCK
+#define HW_LOCK() LOCK_HARDWARE(R128_CONTEXT(ctx));
+#define HW_UNLOCK() UNLOCK_HARDWARE(R128_CONTEXT(ctx));
+
/* 16-bit depth buffer functions
*/
#define WRITE_DEPTH_SPAN() \
+do { \
r128WriteDepthSpanLocked( rmesa, n, \
x + dPriv->x, \
y + dPriv->y, \
- depth, mask );
+ depth, mask ); \
+} while (0)
#define WRITE_DEPTH_PIXELS() \
do { \
} \
} while (0)
-#define TAG(x) r128##x##_16
+#define TAG(x) r128##x##_z16
#include "depthtmp.h"
/* 24-bit depth, 8-bit stencil buffer functions
*/
#define WRITE_DEPTH_SPAN() \
+do { \
+ GLuint buf[n]; \
+ GLint i; \
+ GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ r128ReadDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y ); \
+ r128WaitForIdleLocked( rmesa ); \
+ for ( i = 0 ; i < n ; i++ ) { \
+ buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
+ } \
r128WriteDepthSpanLocked( rmesa, n, \
x + dPriv->x, \
y + dPriv->y, \
- depth, mask );
+ buf, mask ); \
+} while (0)
#define WRITE_DEPTH_PIXELS() \
do { \
+ GLuint buf[n]; \
GLint ox[MAX_WIDTH]; \
GLint oy[MAX_WIDTH]; \
+ GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
for ( i = 0 ; i < n ; i++ ) { \
ox[i] = x[i] + dPriv->x; \
oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
} \
- r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
+ r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
+ r128WaitForIdleLocked( rmesa ); \
+ for ( i = 0 ; i < n ; i++ ) { \
+ buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
+ } \
+ r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
} while (0)
#define READ_DEPTH_SPAN() \
r128scrn->spanOffset); \
GLint i; \
\
+ /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
r128ReadDepthSpanLocked( rmesa, n, \
x + dPriv->x, \
y + dPriv->y ); \
} \
} while (0)
-#define TAG(x) r128##x##_24_8
+#define TAG(x) r128##x##_z24_s8
#include "depthtmp.h"
* Stencil buffer
*/
-/* FIXME: Add support for hardware stencil buffers.
+/* 24 bit depth, 8 bit stencil depthbuffer functions
*/
+#define WRITE_STENCIL_SPAN() \
+do { \
+ GLuint buf[n]; \
+ GLint i; \
+ GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ r128ReadDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y ); \
+ r128WaitForIdleLocked( rmesa ); \
+ for ( i = 0 ; i < n ; i++ ) { \
+ buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
+ } \
+ r128WriteDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y, \
+ buf, mask ); \
+} while (0)
-/*
- * This function is called to specify which buffer to read and write
- * for software rasterization (swrast) fallbacks. This doesn't necessarily
- * correspond to glDrawBuffer() or glReadBuffer() calls.
- */
-static void r128DDSetBuffer( GLcontext *ctx,
- GLframebuffer *colorBuffer,
- GLuint bufferBit )
-{
- r128ContextPtr rmesa = R128_CONTEXT(ctx);
+#define WRITE_STENCIL_PIXELS() \
+do { \
+ GLuint buf[n]; \
+ GLint ox[MAX_WIDTH]; \
+ GLint oy[MAX_WIDTH]; \
+ GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ for ( i = 0 ; i < n ; i++ ) { \
+ ox[i] = x[i] + dPriv->x; \
+ oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
+ } \
+ r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
+ r128WaitForIdleLocked( rmesa ); \
+ for ( i = 0 ; i < n ; i++ ) { \
+ buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
+ } \
+ r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
+} while (0)
- switch ( bufferBit ) {
- case BUFFER_BIT_FRONT_LEFT:
- if ( rmesa->sarea->pfCurrentPage == 1 ) {
- rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
- rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
- } else {
- rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
- rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
- }
- break;
- case BUFFER_BIT_BACK_LEFT:
- if ( rmesa->sarea->pfCurrentPage == 1 ) {
- rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
- rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
- } else {
- rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
- rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
- }
- break;
- default:
- break;
- }
-}
+#define READ_STENCIL_SPAN() \
+do { \
+ GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ GLint i; \
+ \
+ /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
+ r128ReadDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y ); \
+ r128WaitForIdleLocked( rmesa ); \
+ \
+ for ( i = 0 ; i < n ; i++ ) { \
+ stencil[i] = (buf[i] & 0xff000000) >> 24; \
+ } \
+} while (0)
+
+#define READ_STENCIL_PIXELS() \
+do { \
+ GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ GLint i, remaining = n; \
+ \
+ while ( remaining > 0 ) { \
+ GLint ox[128]; \
+ GLint oy[128]; \
+ GLint count; \
+ \
+ if ( remaining <= 128 ) { \
+ count = remaining; \
+ } else { \
+ count = 128; \
+ } \
+ for ( i = 0 ; i < count ; i++ ) { \
+ ox[i] = x[i] + dPriv->x; \
+ oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
+ } \
+ \
+ r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
+ r128WaitForIdleLocked( rmesa ); \
+ \
+ for ( i = 0 ; i < count ; i++ ) { \
+ stencil[i] = (buf[i] & 0xff000000) >> 24; \
+ } \
+ stencil += count; \
+ x += count; \
+ y += count; \
+ remaining -= count; \
+ } \
+} while (0)
+
+#define TAG(x) radeon##x##_z24_s8
+#include "stenciltmp.h"
-void r128SpanRenderStart( GLcontext *ctx )
+static void
+r128SpanRenderStart( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
FLUSH_BATCH(rmesa);
r128WaitForIdleLocked( rmesa );
}
-void r128SpanRenderFinish( GLcontext *ctx )
+static void
+r128SpanRenderFinish( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
_swrast_flush( ctx );
+ r128WaitForIdleLocked( rmesa );
UNLOCK_HARDWARE( rmesa );
}
void r128DDInitSpanFuncs( GLcontext *ctx )
{
- r128ContextPtr rmesa = R128_CONTEXT(ctx);
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
-
- swdd->SetBuffer = r128DDSetBuffer;
swdd->SpanRenderStart = r128SpanRenderStart;
swdd->SpanRenderFinish = r128SpanRenderFinish;
}
}
}
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
- drb->Base.GetRow = r128ReadDepthSpan_16;
- drb->Base.GetValues = r128ReadDepthPixels_16;
- drb->Base.PutRow = r128WriteDepthSpan_16;
- drb->Base.PutMonoRow = r128WriteMonoDepthSpan_16;
- drb->Base.PutValues = r128WriteDepthPixels_16;
- drb->Base.PutMonoValues = NULL;
+ r128InitDepthPointers_z16(&drb->Base);
}
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
- drb->Base.GetRow = r128ReadDepthSpan_24_8;
- drb->Base.GetValues = r128ReadDepthPixels_24_8;
- drb->Base.PutRow = r128WriteDepthSpan_24_8;
- drb->Base.PutMonoRow = r128WriteMonoDepthSpan_24_8;
- drb->Base.PutValues = r128WriteDepthPixels_24_8;
- drb->Base.PutMonoValues = NULL;
+ r128InitDepthPointers_z24_s8(&drb->Base);
}
else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
- drb->Base.GetRow = NULL;
- drb->Base.GetValues = NULL;
- drb->Base.PutRow = NULL;
- drb->Base.PutMonoRow = NULL;
- drb->Base.PutValues = NULL;
- drb->Base.PutMonoValues = NULL;
+ radeonInitStencilPointers_z24_s8(&drb->Base);
}
}