> > to the Rage128's CCE engine. Although it only accelerates SolidFill and
> > ScreenToScreenCopies it should help a lot.
> 
> Hmm, maybe it's easy for someone who doesn't touch the dri code for the
> first time, but not for me.  I've tried, the code builds and doesn't
> crash, but doesn't work.  Can someone have a look at it please?

Uhm, well, with r128_cce_indirect not implemented yet in th kernel it
can't work.  New version + kernel patch, working this time.

  Gerd

diff -ur /suse/kraxel/r128/ati.orig/r128.h 
xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h
--- /suse/kraxel/r128/ati.orig/r128.h   Thu Sep 13 18:19:17 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h   Mon Sep 17 11:40:23 2001
@@ -295,7 +295,6 @@
     int               CCEFifoSize;      /* Size of the CCE command FIFO */
     Bool              CCESecure;        /* CCE security enabled */
     int               CCEusecTimeout;   /* CCE timeout in usecs */
-    Bool              CCE2D;            /* CCE is used for X server 2D prims */
 
                                /* CCE ring buffer data */
     unsigned long     ringStart;        /* Offset into AGP space */
@@ -327,6 +326,10 @@
     unsigned char     *agpTex;          /* Map */
     int               log2AGPTexGran;
 
+                               /* CCE 2D accleration */
+    drmBufPtr         indirectBuffer;
+    int               indirectStart;
+
                                /* DRI screen private data */
     int               fbX;
     int               fbY;
@@ -351,6 +354,10 @@
     CARD32            sc_right;
     CARD32            sc_top;
     CARD32            sc_bottom;
+
+    CARD32            re_top_left;
+    CARD32            re_width_height;
+
     CARD32            aux_sc_cntl;
 #endif
 
@@ -396,7 +403,6 @@
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,                           \
                   "%s: CCE start %d\n", __FUNCTION__, _ret);           \
     }                                                                  \
-    info->CCEInUse = TRUE;                                             \
 } while (0)
 
 #define R128CCE_STOP(pScrn, info)                                      \
@@ -406,7 +412,6 @@
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,                           \
                   "%s: CCE stop %d\n", __FUNCTION__, _ret);            \
     }                                                                  \
-    info->CCEInUse = FALSE;                                            \
 } while (0)
 
 #define R128CCE_RESET(pScrn, info)                                     \
@@ -419,29 +424,100 @@
                       "%s: CCE reset %d\n", __FUNCTION__, _ret);       \
        }                                                               \
     }                                                                  \
-    info->CCEInUse = FALSE;                                            \
 } while (0)
 
-#define R128CCE_TO_MMIO(pScrn, info)                                   \
+#endif
+
+extern drmBufPtr   R128CCEGetBuffer(ScrnInfoPtr pScrn);
+extern void        R128CCEFlushIndirect(ScrnInfoPtr pScrn);
+extern void        R128CCEReleaseIndirect(ScrnInfoPtr pScrn);
+extern void        R128CCEWaitForIdle(ScrnInfoPtr pScrn);
+
+
+#define CP_PACKET0( reg, n )                                           \
+       (R128_CCE_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET1( reg0, reg1 )                                       \
+       (R128_CCE_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CP_PACKET2()                                                   \
+       (R128_CCE_PACKET2)
+#define CP_PACKET3( pkt, n )                                           \
+       (R128_CCE_PACKET3 | (pkt) | ((n) << 16))
+
+
+#define R128_VERBOSE   0
+
+#define RING_LOCALS    CARD32 *__head; int __count;
+#define RING_THRESHOLD 256
+
+#define R128CCE_REFRESH(pScrn, info)                                   \
 do {                                                                   \
-    if (info->CCEInUse) {                                              \
-       R128CCE_STOP(pScrn, info);                                      \
-                                                                       \
-       R128WaitForFifo(pScrn, 5);                                      \
-       OUTREG(R128_SC_LEFT,     info->sc_left);                        \
-       OUTREG(R128_SC_RIGHT,    info->sc_right);                       \
-       OUTREG(R128_SC_TOP,      info->sc_top);                         \
-       OUTREG(R128_SC_BOTTOM,   info->sc_bottom);                      \
-       OUTREG(R128_AUX_SC_CNTL, info->aux_sc_cntl);                    \
-    }                                                                  \
+   if ( R128_VERBOSE ) {                                               \
+      xf86DrvMsg( pScrn->scrnIndex, X_INFO, "REFRESH( %d ) in %s\n",   \
+                 !info->CCEInUse , __FUNCTION__ );                     \
+   }                                                                   \
+   if ( !info->CCEInUse ) {                                            \
+      R128CCEWaitForIdle(pScrn);                                               \
+      BEGIN_RING( 6 );                                                 \
+      OUT_RING_REG( R128_RE_TOP_LEFT,     info->re_top_left );         \
+      OUT_RING_REG( R128_RE_WIDTH_HEIGHT, info->re_width_height );     \
+      OUT_RING_REG( R128_AUX_SC_CNTL,     info->aux_sc_cntl );         \
+      ADVANCE_RING();                                                  \
+      info->CCEInUse = TRUE;                                           \
+   }                                                                   \
+} while (0)
+
+#define BEGIN_RING( n ) do {                                           \
+   if ( R128_VERBOSE ) {                                               \
+      xf86DrvMsg( pScrn->scrnIndex, X_INFO,                            \
+                 "BEGIN_RING( %d ) in %s\n", n, __FUNCTION__ );        \
+   }                                                                   \
+   if ( !info->indirectBuffer ) {                                      \
+      info->indirectBuffer = R128CCEGetBuffer( pScrn );                \
+      info->indirectStart = 0;                                         \
+   } else if ( info->indirectBuffer->used - info->indirectStart +      \
+              (n) * (int)sizeof(CARD32) > RING_THRESHOLD ) {           \
+      R128CCEFlushIndirect( pScrn );                                   \
+   }                                                                   \
+   __head = (pointer)((char *)info->indirectBuffer->address +          \
+                      info->indirectBuffer->used);                     \
+   __count = 0;                                                                \
+} while (0)
+
+#define ADVANCE_RING() do {                                            \
+   if ( R128_VERBOSE ) {                                               \
+      xf86DrvMsg( pScrn->scrnIndex, X_INFO,                            \
+                 "ADVANCE_RING() used: %d+%d=%d/%d\n",                 \
+                 info->indirectBuffer->used - info->indirectStart,     \
+                 __count * sizeof(CARD32),                             \
+                 info->indirectBuffer->used - info->indirectStart +    \
+                 __count * sizeof(CARD32),                             \
+                 RING_THRESHOLD );                                     \
+   }                                                                   \
+   info->indirectBuffer->used += __count * (int)sizeof(CARD32);                \
+} while (0)
+
+#define OUT_RING( x ) do {                                             \
+   if ( R128_VERBOSE ) {                                               \
+      xf86DrvMsg( pScrn->scrnIndex, X_INFO,                            \
+                 "   OUT_RING( 0x%08x )\n", (unsigned int)(x) );       \
+   }                                                                   \
+   __head[__count++] = (x);                                            \
 } while (0)
 
-#define R128MMIO_TO_CCE(pScrn, info)                                   \
+#define OUT_RING_REG( reg, val )                                       \
 do {                                                                   \
-    if (!info->CCEInUse) {                                             \
-       R128CCE_START(pScrn, info);                                     \
-    }                                                                  \
+   OUT_RING( CP_PACKET0( reg, 0 ) );                                   \
+   OUT_RING( val );                                                    \
+} while (0)
+
+#define FLUSH_RING()                                                   \
+do {                                                                   \
+   if ( R128_VERBOSE )                                                 \
+      xf86DrvMsg( pScrn->scrnIndex, X_INFO,                            \
+                 "FLUSH_RING in %s\n", __FUNCTION__ );                 \
+   if ( info->indirectBuffer ) {                                       \
+      R128CCEFlushIndirect( pScrn );                                   \
+   }                                                                   \
 } while (0)
-#endif
 
 #endif
diff -ur /suse/kraxel/r128/ati.orig/r128_accel.c 
xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c
--- /suse/kraxel/r128/ati.orig/r128_accel.c     Thu Aug  9 21:14:12 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c     Mon Sep 17 11:37:51 
+2001
@@ -82,6 +82,7 @@
                                /* Driver data structures */
 #include "r128.h"
 #include "r128_reg.h"
+#include "r128_sarea.h"
 #ifdef XF86DRI
 #define _XF86DRI_SERVER_
 #include "r128_dri.h"
@@ -179,7 +180,7 @@
        R128EngineReset(pScrn);
 #ifdef XF86DRI
        R128CCE_RESET(pScrn, info);
-       if (info->CCE2D) {
+       if (info->directRenderingEnabled) {
            R128CCE_START(pScrn, info);
        }
 #endif
@@ -213,7 +214,7 @@
        R128EngineReset(pScrn);
 #ifdef XF86DRI
        R128CCE_RESET(pScrn, info);
-       if (info->CCE2D) {
+       if (info->directRenderingEnabled) {
            R128CCE_START(pScrn, info);
        }
 #endif
@@ -224,12 +225,14 @@
 /* Wait until the CCE is completely idle: the FIFO has drained and the
  * CCE is idle.
  */
-static void R128CCEWaitForIdle(ScrnInfoPtr pScrn)
+void R128CCEWaitForIdle(ScrnInfoPtr pScrn)
 {
     R128InfoPtr info = R128PTR(pScrn);
     int         ret;
     int         i    = 0;
 
+    FLUSH_RING();
+
     for (;;) {
        do {
            ret = drmR128WaitForIdleCCE(info->drmFD);
@@ -259,10 +262,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128WaitForFifo(pScrn, 4);
     OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
                                     | R128_GMC_BRUSH_SOLID_COLOR
@@ -284,10 +283,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128WaitForFifo(pScrn, 2);
     OUTREG(R128_DST_Y_X,          (y << 16) | x);
     OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | h);
@@ -300,10 +295,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128WaitForFifo(pScrn, 3);
     OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
                                     | R128_GMC_BRUSH_SOLID_COLOR
@@ -336,10 +327,6 @@
     unsigned char *R128MMIO = info->MMIO;
     int           flags     = 0;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     if (octant & YMAJOR)         flags |= R128_DST_Y_MAJOR;
     if (!(octant & XDECREASING)) flags |= R128_DST_X_DIR_LEFT_TO_RIGHT;
     if (!(octant & YDECREASING)) flags |= R128_DST_Y_DIR_TOP_TO_BOTTOM;
@@ -366,10 +353,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128WaitForFifo(pScrn, 1);
     OUTREG(R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT
                          | R128_DST_Y_TOP_TO_BOTTOM));
@@ -404,10 +387,6 @@
     unsigned char *R128MMIO = info->MMIO;
     CARD32        pat       = *(CARD32 *)(pointer)pattern;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
 # define PAT_SHIFT(pat,n) pat << n
 #else
@@ -445,10 +424,6 @@
     unsigned char *R128MMIO = info->MMIO;
     int           flags     = 0;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     if (octant & YMAJOR)         flags |= R128_DST_Y_MAJOR;
     if (!(octant & XDECREASING)) flags |= R128_DST_X_DIR_LEFT_TO_RIGHT;
     if (!(octant & YDECREASING)) flags |= R128_DST_Y_DIR_TOP_TO_BOTTOM;
@@ -486,10 +461,6 @@
     int           origdxL   = dxL;
     int           origdxR   = dxR;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128TRACE(("Trap %d %d; L %d %d %d %d; R %d %d %d %d\n",
               y, h,
               left, dxL, dyL, eL,
@@ -540,10 +511,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     info->xdir = xdir;
     info->ydir = ydir;
     R128WaitForFifo(pScrn, 3);
@@ -577,10 +544,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     if (info->xdir < 0) xa += w - 1, xb += w - 1;
     if (info->ydir < 0) ya += h - 1, yb += h - 1;
 
@@ -610,10 +573,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128WaitForFifo(pScrn, 6);
     OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
                                     | (bg == -1
@@ -637,10 +596,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128WaitForFifo(pScrn, 3);
     OUTREG(R128_BRUSH_Y_X,        (patterny << 8) | patternx);
     OUTREG(R128_DST_Y_X,          (y << 16) | x);
@@ -660,10 +615,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128TRACE(("Color8x8 %d %d %d\n", trans_color, patx, paty));
 
     R128WaitForFifo(pScrn, 2);
@@ -692,10 +643,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128TRACE(("Color8x8 %d,%d %d,%d %d %d\n", patx, paty, x, y, w, h));
     R128WaitForFifo(pScrn, 3);
     OUTREG(R128_SRC_Y_X, (paty << 16) | patx);
@@ -756,10 +703,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     R128WaitForFifo(pScrn, 4);
     OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
                                     | R128_GMC_DST_CLIPPING
@@ -787,10 +730,6 @@
     int x1clip = x+skipleft;
     int x2clip = x+w;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     info->scanline_h      = h;
     info->scanline_words  = (w + 31) >> 5;
 
@@ -837,10 +776,6 @@
     int             left      = info->scanline_words;
     volatile CARD32 *d;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     if (info->scanline_direct) return;
     --info->scanline_h;
     while (left) {
@@ -887,10 +822,6 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     info->scanline_bpp = bpp;
 
     R128WaitForFifo(pScrn, 2);
@@ -927,10 +858,6 @@
 
     int shift = 0; /* 32bpp */
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     if (pScrn->bitsPerPixel == 8) shift = 3;
     else if (pScrn->bitsPerPixel == 16) shift = 1;
 
@@ -979,10 +906,6 @@
     int             left      = info->scanline_words;
     volatile CARD32 *d;
 
-#ifdef XF86DRI
-    R128CCE_TO_MMIO(pScrn, info);
-#endif
-
     if (info->scanline_direct) return;
     --info->scanline_h;
     while (left) {
@@ -1075,18 +998,269 @@
     OUTREGP(R128_DP_DATATYPE, 0, ~R128_HOST_BIG_ENDIAN_EN);
 #endif
 
+#ifdef XF86DRI
+    info->sc_left         = 0x00000000;
+    info->sc_right        = R128_DEFAULT_SC_RIGHT_MAX;
+    info->sc_top          = 0x00000000;
+    info->sc_bottom       = R128_DEFAULT_SC_BOTTOM_MAX;
+
+    info->re_top_left     = 0x00000000;
+    info->re_width_height = ((0x7ff << R128_RE_WIDTH_SHIFT) |
+                            (0x7ff << R128_RE_HEIGHT_SHIFT));
+
+    info->aux_sc_cntl     = 0x00000000;
+#endif
+
     R128WaitForIdle(pScrn);
 }
 
 #ifdef XF86DRI
-    /* FIXME: When direct rendering is enabled, we should use the CCE to
-       draw 2D commands */
-static void R128CCEAccelInit(XAAInfoRecPtr a)
+
+/* Setup for XAA SolidFill. */
+static void R128CCESetupForSolidFill(ScrnInfoPtr pScrn,
+                                    int color, int rop,
+                                    unsigned int planemask)
+{
+    R128InfoPtr   info = R128PTR(pScrn);
+    RING_LOCALS;
+
+    R128CCE_REFRESH( pScrn, info );
+
+    BEGIN_RING( 8 );
+
+    OUT_RING_REG( R128_DP_GUI_MASTER_CNTL,
+                 (info->dp_gui_master_cntl
+                  | R128_GMC_BRUSH_SOLID_COLOR
+                  | R128_GMC_SRC_DATATYPE_COLOR
+                  | R128_ROP[rop].pattern) );
+
+    OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR,  color );
+    OUT_RING_REG( R128_DP_WRITE_MASK,     planemask );
+    OUT_RING_REG( R128_DP_CNTL,                   (R128_DST_X_LEFT_TO_RIGHT |
+                                           R128_DST_Y_TOP_TO_BOTTOM));
+    ADVANCE_RING();
+}
+
+/* Subsequent XAA SolidFillRect.
+
+   Tests: xtest CH06/fllrctngl, xterm
+*/
+static void R128CCESubsequentSolidFillRect(ScrnInfoPtr pScrn,
+                                          int x, int y, int w, int h)
 {
-    a->Flags                            = 0;
+    R128InfoPtr   info = R128PTR(pScrn);
+    RING_LOCALS;
+
+    R128CCE_REFRESH( pScrn, info );
+
+    BEGIN_RING( 4 );
+
+    OUT_RING_REG( R128_DST_Y_X,          (y << 16) | x );
+    OUT_RING_REG( R128_DST_WIDTH_HEIGHT, (w << 16) | h );
+
+    ADVANCE_RING();
+}
+
+/* Setup for XAA screen-to-screen copy.
+
+   Tests: xtest CH06/fllrctngl (also tests transparency).
+*/
+static void R128CCESetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
+                                              int xdir, int ydir, int rop,
+                                              unsigned int planemask,
+                                              int trans_color)
+{
+    R128InfoPtr   info = R128PTR(pScrn);
+    RING_LOCALS;
+
+    R128CCE_REFRESH( pScrn, info );
+
+    info->xdir = xdir;
+    info->ydir = ydir;
+
+    BEGIN_RING( 6 );
+
+    OUT_RING_REG( R128_DP_GUI_MASTER_CNTL,
+                 (info->dp_gui_master_cntl
+                  | R128_GMC_BRUSH_NONE
+                  | R128_GMC_SRC_DATATYPE_COLOR
+                  | R128_ROP[rop].rop
+                  | R128_DP_SRC_SOURCE_MEMORY) );
+
+    OUT_RING_REG( R128_DP_WRITE_MASK, planemask );
+    OUT_RING_REG( R128_DP_CNTL,
+                 ((xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) |
+                  (ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0)) );
+
+    ADVANCE_RING();
+
+    if ((trans_color != -1) || (info->XAAForceTransBlit == TRUE)) {
+       BEGIN_RING( 6 );
+
+       OUT_RING_REG( R128_CLR_CMP_CLR_SRC, trans_color );
+       OUT_RING_REG( R128_CLR_CMP_MASK,    R128_CLR_CMP_MSK );
+       OUT_RING_REG( R128_CLR_CMP_CNTL,    (R128_SRC_CMP_NEQ_COLOR |
+                                            R128_CLR_CMP_SRC_SOURCE) );
+
+       ADVANCE_RING();
+    }
+}
+
+/* Subsequent XAA screen-to-screen copy. */
+static void R128CCESubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
+                                                int xa, int ya,
+                                                int xb, int yb,
+                                                int w, int h)
+{
+    R128InfoPtr   info = R128PTR(pScrn);
+    RING_LOCALS;
+
+    R128CCE_REFRESH( pScrn, info );
+
+    if (info->xdir < 0) xa += w - 1, xb += w - 1;
+    if (info->ydir < 0) ya += h - 1, yb += h - 1;
+
+    BEGIN_RING( 6 );
+
+    OUT_RING_REG( R128_SRC_Y_X,          (ya << 16) | xa );
+    OUT_RING_REG( R128_DST_Y_X,          (yb << 16) | xb );
+    OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (h << 16) | w );
+
+    ADVANCE_RING();
+}
+
+/* Get an indirect buffer for the CP 2D acceleration commands.
+ */
+drmBufPtr R128CCEGetBuffer( ScrnInfoPtr pScrn )
+{
+    R128InfoPtr   info = R128PTR(pScrn);
+    drmDMAReq dma;
+    drmBufPtr buf = NULL;
+    int indx = 0;
+    int size = 0;
+    int ret, i = 0;
+
+#if 0
+    /* FIXME: pScrn->pScreen has not been initialized when this is first
+       called from RADEONSelectBuffer via RADEONDRICPInit.  We could use
+       the screen index from pScrn, which is initialized, and then get
+       the screen from screenInfo.screens[index], but that is a hack. */
+    dma.context = DRIGetContext(pScrn->pScreen);
+#else
+    dma.context = 0x00000001; /* This is the X server's context */
+#endif
+    dma.send_count = 0;
+    dma.send_list = NULL;
+    dma.send_sizes = NULL;
+    dma.flags = 0;
+    dma.request_count = 1;
+    dma.request_size = R128_BUFFER_SIZE;
+    dma.request_list = &indx;
+    dma.request_sizes = &size;
+    dma.granted_count = 0;
+
+    while ( 1 ) {
+       do {
+           ret = drmDMA( info->drmFD, &dma );
+           if ( ret && ret != -EBUSY ) {
+               xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
+                           "%s: CCE GetBuffer %d\n", __FUNCTION__, ret );
+           }
+       } while ( ( ret == -EBUSY ) && ( i++ < R128_TIMEOUT ) );
+
+       if ( ret == 0 ) {
+           buf = &info->buffers->list[indx];
+           buf->used = 0;
+           if ( R128_VERBOSE ) {
+               xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+                           "   GetBuffer returning %d\n", buf->idx );
+           }
+           return buf;
+       }
+
+       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
+                   "GetBuffer timed out, resetting engine...\n");
+       R128EngineReset( pScrn );
+       /* R128EngineRestore( pScrn ); FIXME ??? */
+
+       /* Always restart the engine when doing CP 2D acceleration */
+       R128CCE_RESET( pScrn, info );
+       R128CCE_START( pScrn, info );
+    }
+}
+
+/* Flush the indirect buffer to the kernel for submission to the card.
+ */
+void R128CCEFlushIndirect( ScrnInfoPtr pScrn )
+{
+    R128InfoPtr   info = R128PTR(pScrn);
+    drmBufPtr buffer = info->indirectBuffer;
+    int start = info->indirectStart;
+    int discard;
+
+    if ( !buffer )
+       return;
+
+    if ( start == buffer->used )
+       return;
+
+    discard = ( buffer->used + RING_THRESHOLD > buffer->total );
+
+    drmR128FlushIndirectBuffer( info->drmFD, buffer->idx,
+                               start, buffer->used, discard );
+
+    if ( discard ) {
+       info->indirectBuffer = R128CCEGetBuffer( pScrn );
+       info->indirectStart = 0;
+    } else {
+       info->indirectStart = buffer->used;
+    }
+}
+
+/* Flush and release the indirect buffer.
+ */
+void R128CCEReleaseIndirect( ScrnInfoPtr pScrn )
+{
+    R128InfoPtr   info = R128PTR(pScrn);
+    drmBufPtr buffer = info->indirectBuffer;
+    int start = info->indirectStart;
+
+    info->indirectBuffer = NULL;
+    info->indirectStart = 0;
+
+    if ( !buffer )
+       return;
+
+    drmR128FlushIndirectBuffer( info->drmFD, buffer->idx,
+                               start, buffer->used, 1 );
+}
+
+static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a)
+{
+    a->Flags                            = (PIXMAP_CACHE
+                                          | OFFSCREEN_PIXMAPS
+                                          | LINEAR_FRAMEBUFFER);
 
                                /* Sync */
     a->Sync                             = R128CCEWaitForIdle;
+
+    /* Solid Filled Rectangle */
+    a->PolyFillRectSolidFlags           = 0;
+    a->SetupForSolidFill                = R128CCESetupForSolidFill;
+    a->SubsequentSolidFillRect          = R128CCESubsequentSolidFillRect;
+    
+                               /* Screen-to-screen Copy */
+                               /* Transparency uses the wrong colors for
+                                  24 bpp mode -- the transparent part is
+                                  correct, but the opaque color is wrong.
+                                  This can be seen with netscape's I-bar
+                                  cursor when editing in the URL location
+                                  box. */
+    a->ScreenToScreenCopyFlags          = ((pScrn->bitsPerPixel == 24)
+                                          ? NO_TRANSPARENCY
+                                          : 0);
+    a->SetupForScreenToScreenCopy       = R128CCESetupForScreenToScreenCopy;
+    a->SubsequentScreenToScreenCopy     = R128CCESubsequentScreenToScreenCopy;
 }
 #endif
 
@@ -1189,7 +1363,8 @@
 #ifdef XF86DRI
     /* FIXME: When direct rendering is enabled, we should use the CCE to
        draw 2D commands */
-    if (info->CCE2D) R128CCEAccelInit(a);
+    if (info->directRenderingEnabled)
+       R128CCEAccelInit(pScrn, a);
     else
 #endif
        R128MMIOAccelInit(pScrn, a);
diff -ur /suse/kraxel/r128/ati.orig/r128_dri.c 
xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c
--- /suse/kraxel/r128/ati.orig/r128_dri.c       Sat Aug 18 19:25:51 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c       Mon Sep 17 10:29:04 
+2001
@@ -294,7 +294,7 @@
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
 
-    if (!info->CCE2D) {
+    if (!info->directRenderingEnabled) {
        if (!info->CCEInUse) {
            /* Save all hardware scissors */
            info->sc_left     = INREG(R128_SC_LEFT);
@@ -303,8 +303,6 @@
            info->sc_bottom   = INREG(R128_SC_BOTTOM);
            info->aux_sc_cntl = INREG(R128_SC_BOTTOM);
        }
-
-       R128MMIO_TO_CCE(pScrn, info);
     }
 }
 
@@ -338,7 +336,8 @@
     int         depth;
 
     /* FIXME: Use accel when CCE 2D code is written */
-    if (info->CCE2D) return;
+    if (info->directRenderingEnabled)
+       return;
 
     /* FIXME: This should be based on the __GLXvisualConfig info */
     switch (pScrn->bitsPerPixel) {
@@ -399,7 +398,8 @@
        that request them */
 
     /* FIXME: Use accel when CCE 2D code is written */
-    if (info->CCE2D) return;
+    if (info->directRenderingEnabled)
+       return;
 }
 
 /* Initialize the AGP state.  Request memory for use in AGP space, and
@@ -852,7 +852,7 @@
     case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64;  break;
     }
 
-    if (info->CCE2D) {
+    if (info->directRenderingEnabled) {
                                /* Make sure the CCE is on for the X server */
        R128CCE_START(pScrn, info);
     } else {
@@ -1122,7 +1122,7 @@
     R128InfoPtr info = R128PTR(pScrn);
 
                                /* Stop the CCE if it is still in use */
-    if (info->CCE2D) {
+    if (info->directRenderingEnabled) {
        R128CCE_STOP(pScrn, info);
     }
 
diff -ur /suse/kraxel/r128/ati.orig/r128_driver.c 
xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c
--- /suse/kraxel/r128/ati.orig/r128_driver.c    Thu Sep 13 10:16:29 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c    Sun Sep 16 19:17:37 
+2001
@@ -133,7 +133,6 @@
   OPTION_AGP_SIZE,
   OPTION_RING_SIZE,
   OPTION_BUFFER_SIZE,
-  OPTION_USE_CCE_2D,
 #endif
 #if USE_CRT_ONLY
   /* FIXME: Disable CRTOnly until it is tested */
@@ -162,7 +161,6 @@
   { OPTION_AGP_SIZE,     "AGPSize",          OPTV_INTEGER, {0}, FALSE },
   { OPTION_RING_SIZE,    "RingSize",         OPTV_INTEGER, {0}, FALSE },
   { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
-  { OPTION_USE_CCE_2D,   "UseCCEfor2D",      OPTV_BOOLEAN, {0}, FALSE },
 #endif
   { OPTION_DISPLAY,      "Display",          OPTV_STRING,  {0}, FALSE },
   { OPTION_PANEL_WIDTH,  "PanelWidth",       OPTV_INTEGER, {0}, FALSE },
@@ -278,12 +276,14 @@
     "drmGetVersion",
     "drmMap",
     "drmMapBufs",
+    "drmDMA",
     "drmR128CleanupCCE",
     "drmR128InitCCE",
     "drmR128ResetCCE",
     "drmR128StartCCE",
     "drmR128StopCCE",
     "drmR128WaitForIdleCCE",
+    "drmR128FlushIndirectBuffer",
     "drmScatterGatherAlloc",
     "drmScatterGatherFree",
     "drmUnmap",
@@ -1219,13 +1219,6 @@
        info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
     } else {
        info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
-    }
-
-    if (xf86ReturnOptValBool(info->Options, OPTION_USE_CCE_2D, FALSE)) {
-       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using CCE for 2D\n");
-       info->CCE2D = TRUE;
-    } else {
-       info->CCE2D = FALSE;
     }
 
     if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) {
diff -ur /suse/kraxel/r128/ati.orig/r128_reg.h 
xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h
--- /suse/kraxel/r128/ati.orig/r128_reg.h       Tue Apr 10 18:07:59 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h       Mon Sep 17 10:02:23 
+2001
@@ -1484,4 +1484,12 @@
 #define R128_CCE_VC_CNTL_PRIM_WALK_RING          0x00000030
 #define R128_CCE_VC_CNTL_NUM_SHIFT               16
 
+/* hmm copyed blindly (no specs) from radeon.h ... */
+#define R128_RE_TOP_LEFT                  0x26c0
+#       define R128_RE_LEFT_SHIFT         0
+#       define R128_RE_TOP_SHIFT          16
+#define R128_RE_WIDTH_HEIGHT              0x1c44
+#       define R128_RE_WIDTH_SHIFT        0
+#       define R128_RE_HEIGHT_SHIFT       16
+
 #endif
diff -ur vanilla-2.4.10-pre9/drivers/char/drm/r128_state.c 
2.4.10-pre9/drivers/char/drm/r128_state.c
--- vanilla-2.4.10-pre9/drivers/char/drm/r128_state.c   Wed Aug  8 18:42:15 2001
+++ 2.4.10-pre9/drivers/char/drm/r128_state.c   Mon Sep 17 11:24:42 2001
@@ -1519,10 +1519,75 @@
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
+       drm_buf_t *buf;
+       drm_r128_buf_priv_t *buf_priv;
+       drm_r128_indirect_t indirect;
+#if 0
+       RING_LOCALS;
+#endif
 
        LOCK_TEST_WITH_RETURN( dev );
 
-       /* Indirect buffer firing is not supported at this time.
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+               return -EINVAL;
+       }
+
+       if ( copy_from_user( &indirect, (drm_r128_indirect_t *)arg,
+                            sizeof(indirect) ) )
+               return -EFAULT;
+
+       DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+                  indirect.idx, indirect.start,
+                  indirect.end, indirect.discard );
+
+       if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+               DRM_ERROR( "buffer index %d (of %d max)\n",
+                          indirect.idx, dma->buf_count - 1 );
+               return -EINVAL;
+       }
+
+       buf = dma->buflist[indirect.idx];
+       buf_priv = buf->dev_private;
+
+       if ( buf->pid != current->pid ) {
+               DRM_ERROR( "process %d using buffer owned by %d\n",
+                          current->pid, buf->pid );
+               return -EINVAL;
+       }
+       if ( buf->pending ) {
+               DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
+               return -EINVAL;
+       }
+
+       if ( indirect.start < buf->used ) {
+               DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+                          indirect.start, buf->used );
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+       buf->used = indirect.end;
+       buf_priv->discard = indirect.discard;
+
+#if 0
+       /* Wait for the 3D stream to idle before the indirect buffer
+        * containing 2D acceleration commands is processed.
         */
-       return -EINVAL;
+       BEGIN_RING( 2 );
+       RADEON_WAIT_UNTIL_3D_IDLE();
+       ADVANCE_RING();
+#endif
+
+       /* Dispatch the indirect buffer full of commands from the
+        * X server.  This is insecure and is thus only available to
+        * privileged clients.
+        */
+       r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+
+       return 0;
 }

Reply via email to