Michel DÃnzer wrote:

fixed a copy & paste error in the non-core drm version, and it actually auto-refreshes the screen when switching between a tiled and untiled resolution...


Nice.

What happened to Stephane's surface allocator, BTW? If you just whack
the surface registers directly from the X server, it becomes hard if not
impossible to introduce such an allocator, at least for the surfaces
touched directly by the X server...

Ok, I'm late, but here it is.
Also attached is the small patch for the ddx.

It is supposed to be used with the drmCommand interface, btw :
drmRadeonSurfaceAlloc drmalloc_front;
drmalloc_front.lower=(info->frontOffset) &~0x3ff ;
drmalloc_front.size=bufferSize -1 ;
drmalloc_front.flags=pitch | RADEON_SURF_TILE_COLOR_MACRO;
drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, &drmalloc_front,sizeof(drmalloc_front));


Stephane

Index: shared/radeon.h
===================================================================
RCS file: /cvs/dri/drm/shared/radeon.h,v
retrieving revision 1.34
diff -u -r1.34 radeon.h
--- shared/radeon.h     8 Dec 2004 16:43:00 -0000       1.34
+++ shared/radeon.h     20 Jan 2005 01:43:05 -0000
@@ -84,6 +84,8 @@
  *       (No 3D support yet - just microcode loading).
  * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
  *     - Add hyperz support, add hyperz flags to clear ioctl.
+ * 1.14- Add support for color tiling
+ *     - Add R100/R200 surface allocation/free support
  */
 #define DRIVER_IOCTLS                                                       \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
@@ -112,5 +114,7 @@
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)]   = { radeon_cp_setparam, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SURF_FREE)]  = { radeon_surface_free ,1, 0 }, \
 
 #endif
Index: shared/radeon_cp.c
===================================================================
RCS file: /cvs/dri/drm/shared/radeon_cp.c,v
retrieving revision 1.46
diff -u -r1.46 radeon_cp.c
--- shared/radeon_cp.c  8 Dec 2004 16:43:00 -0000       1.46
+++ shared/radeon_cp.c  20 Jan 2005 01:43:05 -0000
@@ -1267,6 +1267,7 @@
 
 static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 {
+       int i;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG( "\n" );
 
@@ -1520,6 +1521,11 @@
 
        dev_priv->last_buf = 0;
 
+       for(i=0;i<RADEON_MAX_SURFACES;i++)
+               dev_priv->surfaces[i].refcount = 0;
+       for(i=0;i<2*RADEON_MAX_SURFACES;i++)
+               dev_priv->virt_surfaces[i].filp = 0;
+
        radeon_do_engine_reset( dev );
 
        return 0;
Index: shared/radeon_drm.h
===================================================================
RCS file: /cvs/dri/drm/shared/radeon_drm.h,v
retrieving revision 1.25
diff -u -r1.25 radeon_drm.h
--- shared/radeon_drm.h 8 Dec 2004 16:43:00 -0000       1.25
+++ shared/radeon_drm.h 20 Jan 2005 01:43:06 -0000
@@ -231,6 +231,8 @@
 #define RADEON_MAX_TEXTURE_LEVELS      12
 #define RADEON_MAX_TEXTURE_UNITS       3
 
+#define RADEON_MAX_SURFACES            8
+
 /* Blits have strict offset rules.  All blit offset must be aligned on
  * a 1K-byte boundary.
  */
@@ -403,6 +405,8 @@
 #define DRM_RADEON_IRQ_WAIT   0x17
 #define DRM_RADEON_CP_RESUME  0x18
 #define DRM_RADEON_SETPARAM   0x19
+#define DRM_RADEON_SURF_ALLOC 0x1a
+#define DRM_RADEON_SURF_FREE  0x1b
 
 #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + 
DRM_RADEON_CP_INIT, drm_radeon_init_t)
 #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + 
DRM_RADEON_CP_START)
@@ -429,6 +433,8 @@
 #define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( DRM_COMMAND_BASE + 
DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t)
 #define DRM_IOCTL_RADEON_CP_RESUME  DRM_IO(  DRM_COMMAND_BASE + 
DRM_RADEON_CP_RESUME)
 #define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW( DRM_COMMAND_BASE + 
DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
+#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW(DRM_COMMAND_BASE + 
DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
+#define DRM_IOCTL_RADEON_SURF_FREE  DRM_IOW( DRM_COMMAND_BASE + 
DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
 
 typedef struct drm_radeon_init {
        enum {
@@ -630,5 +636,19 @@
 
 #define RADEON_SETPARAM_FB_LOCATION    1 /* determined framebuffer location */
 
+/* 1.14: Clients can allocate/free a surface
+ */
+
+typedef struct drm_radeon_surface_alloc {
+       unsigned int lower;
+       unsigned int size;
+       unsigned int flags;
+} drm_radeon_surface_alloc_t;
+
+typedef struct drm_radeon_surface_free {
+       unsigned int lower;
+} drm_radeon_surface_free_t;
+
+
 
 #endif
Index: shared/radeon_drv.h
===================================================================
RCS file: /cvs/dri/drm/shared/radeon_drv.h,v
retrieving revision 1.38
diff -u -r1.38 radeon_drv.h
--- shared/radeon_drv.h 8 Dec 2004 16:43:00 -0000       1.38
+++ shared/radeon_drv.h 20 Jan 2005 01:43:06 -0000
@@ -112,6 +112,21 @@
        DRMFILE filp;           /* 0: free, -1: heap, other: real files */
 };
 
+struct radeon_surface {
+       int refcount;
+       u32 lower;
+       u32 upper;
+       u32 flags;
+};
+
+struct radeon_virt_surface {
+       int surface_index;
+       u32 lower;
+       u32 upper;
+       u32 flags;
+       DRMFILE filp;
+};
+
 typedef struct drm_radeon_private {
 
        drm_radeon_ring_buffer_t ring;
@@ -192,6 +207,10 @@
 
        /* starting from here on, data is preserved accross an open */
        uint32_t flags;         /* see radeon_chip_flags */
+       
+       struct radeon_surface surfaces[RADEON_MAX_SURFACES];
+       struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES];
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
        struct radeon_i2c_chan  i2c[4];
 #endif
@@ -240,6 +259,8 @@
 extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
 extern void radeon_mem_takedown( struct mem_block **heap );
 extern void radeon_mem_release( DRMFILE filp, struct mem_block *heap );
+extern int radeon_surface_alloc( DRM_IOCTL_ARGS );
+extern int radeon_surface_free( DRM_IOCTL_ARGS );
 
                                /* radeon_irq.c */
 extern int radeon_irq_emit( DRM_IOCTL_ARGS );
@@ -511,6 +532,7 @@
 #      define RADEON_SURF_TILE_MODE_32BIT_Z    (2 << 16)
 #      define RADEON_SURF_TILE_MODE_16BIT_Z    (3 << 16)
 #define RADEON_SURFACE0_LOWER_BOUND    0x0b04
+#      define RADEON_SURF_ADDRESS_FIXED_MASK   (0x03ff << 0)
 #define RADEON_SURFACE0_UPPER_BOUND    0x0b08
 #define RADEON_SURFACE1_INFO           0x0b1c
 #define RADEON_SURFACE1_LOWER_BOUND    0x0b14
Index: shared/radeon_state.c
===================================================================
RCS file: /cvs/dri/drm/shared/radeon_state.c,v
retrieving revision 1.40
diff -u -r1.40 radeon_state.c
--- shared/radeon_state.c       8 Dec 2004 16:43:00 -0000       1.40
+++ shared/radeon_state.c       20 Jan 2005 01:43:08 -0000
@@ -1706,11 +1706,199 @@
        ADVANCE_RING();
 }
 
+static void radeon_apply_surface_regs(int surf_index, drm_radeon_private_t 
*dev_priv)
+{
+       if (!dev_priv->mmio)
+               return;
+       
+       radeon_do_wait_for_idle(dev_priv);
+       
+       RADEON_WRITE( RADEON_SURFACE0_INFO+16*surf_index, 
dev_priv->surfaces[surf_index].flags );
+       RADEON_WRITE( RADEON_SURFACE0_LOWER_BOUND+16*surf_index, 
dev_priv->surfaces[surf_index].lower );
+       RADEON_WRITE( RADEON_SURFACE0_UPPER_BOUND+16*surf_index, 
dev_priv->surfaces[surf_index].upper );
+}
+
+/* Allocates a virtual surface
+ * doesn't always allocate a real surface, will stretch an existing 
+ * surface when possible.
+ *
+ * Note that refcount can be at most 2, since during a free refcount=3
+ * might mean we have to allocate a new surface which might not always
+ * be available.
+ * For example : we allocate three contigous surfaces ABC. If B is 
+ * freed, we suddenly need two surfaces to store A and C, which might
+ * not always be available.
+ */
+static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t 
*dev_priv, DRMFILE filp)
+{
+       struct radeon_virt_surface *s;
+       int i;
+       int virt_surface_index;
+       uint32_t new_upper;
+       
+       new_upper=new->lower + new->size;
+       
+       /* sanity check */
+       if ((new->lower >= new_upper)||(new->flags==0)||
+               
((new_upper&RADEON_SURF_ADDRESS_FIXED_MASK)!=RADEON_SURF_ADDRESS_FIXED_MASK)||
+               ((new->lower&RADEON_SURF_ADDRESS_FIXED_MASK)!=0))
+               return -1;
+
+       /* make sure there is no overlap with existing surfaces */
+       for(i=0;i<RADEON_MAX_SURFACES;i++) {
+               if ((dev_priv->surfaces[i].refcount!=0) &&
+               (( (new->lower>=dev_priv->surfaces[i].lower) && 
(new->lower<dev_priv->surfaces[i].upper) ) ||
+                ( (new_upper>dev_priv->surfaces[i].lower) && 
(new_upper<=dev_priv->surfaces[i].upper) ) ||
+                ( (new->lower<dev_priv->surfaces[i].lower) && 
(new_upper>dev_priv->surfaces[i].upper) )) )
+                       return -1;
+       }
+
+       /* find a virtual surface */
+       for(i=0;i<2*RADEON_MAX_SURFACES;i++)
+               if (dev_priv->virt_surfaces[i].filp==0)
+                       break;
+       if (i==2*RADEON_MAX_SURFACES)
+               return -1;
+       virt_surface_index=i;
+
+       /* try to reuse an existing surface */
+       for(i=0;i<RADEON_MAX_SURFACES;i++) {
+               /* extend before */
+               if ((dev_priv->surfaces[i].refcount==1) &&
+                 (new->flags==dev_priv->surfaces[i].flags) &&
+                 (new_upper+1==dev_priv->surfaces[i].lower)) {
+                       s=&(dev_priv->virt_surfaces[virt_surface_index]);
+                       s->surface_index=i;
+                       s->lower=new->lower;
+                       s->upper=new_upper;
+                       s->flags=new->flags;
+                       s->filp=filp;
+                       dev_priv->surfaces[i].refcount++;
+                       dev_priv->surfaces[i].lower=s->lower;
+                       radeon_apply_surface_regs(s->surface_index, dev_priv);
+                       return virt_surface_index;
+               }
+               
+               /* extend after */
+               if ((dev_priv->surfaces[i].refcount==1) &&
+                 (new->flags==dev_priv->surfaces[i].flags) &&
+                 (new->lower==dev_priv->surfaces[i].upper+1)) {
+                       s=&(dev_priv->virt_surfaces[virt_surface_index]);
+                       s->surface_index=i;
+                       s->lower=new->lower;
+                       s->upper=new_upper;
+                       s->flags=new->flags;
+                       s->filp=filp;
+                       dev_priv->surfaces[i].refcount++;
+                       dev_priv->surfaces[i].upper=s->upper;
+                       radeon_apply_surface_regs(s->surface_index, dev_priv);
+                       return virt_surface_index;
+               }
+       }
+
+       /* okay, we need a new one */
+       for(i=0;i<RADEON_MAX_SURFACES;i++) {
+               if (dev_priv->surfaces[i].refcount==0) {
+                       s=&(dev_priv->virt_surfaces[virt_surface_index]);
+                       s->surface_index=i;
+                       s->lower=new->lower;
+                       s->upper=new_upper;
+                       s->flags=new->flags;
+                       s->filp=filp;
+                       dev_priv->surfaces[i].refcount=1;
+                       dev_priv->surfaces[i].lower=s->lower;
+                       dev_priv->surfaces[i].upper=s->upper;
+                       dev_priv->surfaces[i].flags=s->flags;
+                       radeon_apply_surface_regs(s->surface_index, dev_priv);
+                       return virt_surface_index;
+               }
+       }
+
+       /* we didn't find anything */
+       return -1;
+}
+
+static int free_surface(DRMFILE filp, drm_radeon_private_t *dev_priv, int 
lower)
+{
+       struct radeon_virt_surface *s;
+       int i;
+       /* find the virtual surface */
+       for(i=0;i<2*RADEON_MAX_SURFACES;i++) {
+               s=&(dev_priv->virt_surfaces[i]);
+               if (s->filp) {
+                       if ((lower==s->lower) && (filp==s->filp)) {
+                               if 
(dev_priv->surfaces[s->surface_index].lower==s->lower)
+                                       
dev_priv->surfaces[s->surface_index].lower=s->upper;
+
+                               if 
(dev_priv->surfaces[s->surface_index].upper==s->upper)
+                                       
dev_priv->surfaces[s->surface_index].upper=s->lower;
+                               
+                               dev_priv->surfaces[s->surface_index].refcount--;
+                               if 
(dev_priv->surfaces[s->surface_index].refcount==0)
+                                       
dev_priv->surfaces[s->surface_index].flags=0;
+                               s->filp=0;
+                               radeon_apply_surface_regs(s->surface_index, 
dev_priv);
+                               return 0;
+                       }
+               }
+       }
+       return 1;
+}
+
+static void radeon_surfaces_release(DRMFILE filp, drm_radeon_private_t 
*dev_priv)
+{
+       int i;
+       for(i=0;i<2*RADEON_MAX_SURFACES;i++)
+       {
+               if (dev_priv->virt_surfaces[i].filp==filp)
+                       
free_surface(filp,dev_priv,dev_priv->virt_surfaces[i].lower);
+       }
+}
 
 /* ================================================================
  * IOCTL functions
  */
 
+int radeon_surface_alloc( DRM_IOCTL_ARGS )
+{
+       DRM_DEVICE;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_surface_alloc_t alloc;
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_surface_alloc_t __user 
*)data,
+                                 sizeof(alloc) );
+
+       if (alloc_surface(&alloc,dev_priv,filp)==-1)
+               return DRM_ERR(EINVAL);
+       else
+               return 0;
+}
+
+int radeon_surface_free( DRM_IOCTL_ARGS )
+{
+       DRM_DEVICE;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_surface_free_t memfree;
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t __user *)data,
+                                 sizeof(memfree) );
+
+       if (free_surface(filp,dev_priv,memfree.lower))
+               return DRM_ERR(EINVAL);
+       else
+               return 0;
+}
+
 int radeon_cp_clear( DRM_IOCTL_ARGS )
 {
        DRM_DEVICE;
@@ -2724,6 +2912,7 @@
 /* When a client dies:
  *    - Check for and clean up flipped page state
  *    - Free any alloced GART memory.
+ *    - Free any alloced radeon surfaces.
  *
  * DRM infrastructure takes care of reclaiming dma buffers.
  */
@@ -2736,6 +2925,7 @@
                }                                               
                radeon_mem_release( filp, dev_priv->gart_heap ); 
                radeon_mem_release( filp, dev_priv->fb_heap );  
+               radeon_surfaces_release( filp, dev_priv );
        }                               
 }
 
Index: radeon_common.h
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v
retrieving revision 1.4
diff -u -r1.4 radeon_common.h
--- radeon_common.h     12 Dec 2004 16:05:35 -0000      1.4
+++ radeon_common.h     20 Jan 2005 01:59:57 -0000
@@ -74,6 +74,8 @@
 #define DRM_RADEON_IRQ_WAIT               0x17
 #define DRM_RADEON_CP_RESUME              0x18
 #define DRM_RADEON_SETPARAM               0x19
+#define DRM_RADEON_SURF_ALLOC             0x1a
+#define DRM_RADEON_SURF_FREE              0x1b
 #define DRM_RADEON_MAX_DRM_COMMAND_INDEX  0x39
 
 
@@ -470,6 +472,22 @@
 } drmRadeonSetParam;
 
 #define RADEON_SETPARAM_FB_LOCATION     1
+#define RADEON_SETPARAM_SWITCH_TILING   2
+#define RADEON_SETPARAM_CRT1_USESAREA   3
+
+/* 1.14: Clients can allocate/free a surface
+ */
+
+typedef struct drm_radeon_surface_alloc {
+       unsigned int lower;
+       unsigned int size;
+       unsigned int flags;
+} drmRadeonSurfaceAlloc;
+
+typedef struct drm_radeon_surface_free {
+       unsigned int lower;
+} drmRadeonSurfaceFree;
+
 
 
 #endif
Index: radeon_reg.h
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v
retrieving revision 1.13
diff -u -r1.13 radeon_reg.h
--- radeon_reg.h        12 Dec 2004 02:00:48 -0000      1.13
+++ radeon_reg.h        20 Jan 2005 01:59:59 -0000
@@ -1280,6 +1280,7 @@
 #       define RADEON_NONSURF_AP1_SWP_32BPP (1 << 23)
 #define RADEON_SURFACE0_INFO                0x0b0c
 #define RADEON_SURFACE0_LOWER_BOUND         0x0b04
+#      define RADEON_SURF_ADDRESS_FIXED_MASK   (0x03ff << 0)
 #define RADEON_SURFACE0_UPPER_BOUND         0x0b08
 #define RADEON_SURFACE1_INFO                0x0b1c
 #define RADEON_SURFACE1_LOWER_BOUND         0x0b14

Reply via email to