diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index d14c112e..db0641c4 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -68,7 +68,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, #include "drm_agpsupport.h" diff --git a/linux/drm.h b/linux/drm.h index b0bf91c4..b0819995 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -491,6 +491,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) /* Gamma specific ioctls */ #define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t) diff --git a/linux/radeon_cp.c b/linux/radeon_cp.c index 3bb1e78d..2f262516 100644 --- a/linux/radeon_cp.c +++ b/linux/radeon_cp.c @@ -964,9 +964,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) radeon_cp_load_microcode( dev_priv ); radeon_cp_init_ring_buffer( dev, dev_priv ); -#if ROTATE_BUFS dev_priv->last_buf = 0; -#endif dev->dev_private = (void *)dev_priv; @@ -1206,56 +1204,15 @@ int radeon_fullscreen( struct inode *inode, struct file *filp, /* ================================================================ * Freelist management */ -#define RADEON_BUFFER_USED 0xffffffff -#define RADEON_BUFFER_FREE 0 -#if 0 -static int radeon_freelist_init( drm_device_t *dev ) -{ - drm_device_dma_t *dma = dev->dma; - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; - drm_radeon_freelist_t *entry; - int i; - - dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t), - DRM_MEM_DRIVER ); - if ( dev_priv->head == NULL ) - return -ENOMEM; - - memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) ); - dev_priv->head->age = RADEON_BUFFER_USED; - - for ( i = 0 ; i < dma->buf_count ; i++ ) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - - entry = DRM(alloc)( sizeof(drm_radeon_freelist_t), - DRM_MEM_DRIVER ); - if ( !entry ) return -ENOMEM; - - entry->age = RADEON_BUFFER_FREE; - entry->buf = buf; - entry->prev = dev_priv->head; - entry->next = dev_priv->head->next; - if ( !entry->next ) - dev_priv->tail = entry; - - buf_priv->discard = 0; - buf_priv->dispatched = 0; - buf_priv->list_entry = entry; - - dev_priv->head->next = entry; - - if ( dev_priv->head->next ) - dev_priv->head->next->prev = entry; - } - - return 0; - -} -#endif +/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through + * bufs until freelist code is used. Note this hides a problem with + * the scratch register * (used to keep track of last buffer + * completed) being written to before * the last buffer has actually + * completed rendering. + * + * KW: It's also a good way to find free buffers quickly. + */ drm_buf_t *radeon_freelist_get( drm_device_t *dev ) { @@ -1264,57 +1221,24 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev ) drm_radeon_buf_priv_t *buf_priv; drm_buf_t *buf; int i, t; -#if ROTATE_BUFS int start; -#endif - /* FIXME: Optimize -- use freelist code */ - - for ( i = 0 ; i < dma->buf_count ; i++ ) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - if ( buf->pid == 0 ) { - DRM_DEBUG( " ret buf=%d last=%d pid=0\n", - buf->idx, dev_priv->last_buf ); - return buf; - } - DRM_DEBUG( " skipping buf=%d pid=%d\n", - buf->idx, buf->pid ); - } - -#if ROTATE_BUFS if ( ++dev_priv->last_buf >= dma->buf_count ) dev_priv->last_buf = 0; + start = dev_priv->last_buf; -#endif + for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { -#if 0 - /* FIXME: Disable this for now */ - u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH]; -#else u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG ); -#endif -#if ROTATE_BUFS for ( i = start ; i < dma->buf_count ; i++ ) { -#else - for ( i = 0 ; i < dma->buf_count ; i++ ) { -#endif buf = dma->buflist[i]; buf_priv = buf->dev_private; - if ( buf->pending && buf_priv->age <= done_age ) { - /* The buffer has been processed, so it - * can now be used. - */ + if ( buf->pid == 0 || (buf->pending && + buf_priv->age <= done_age) ) { buf->pending = 0; - DRM_DEBUG( " ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age ); return buf; } - DRM_DEBUG( " skipping buf=%d age=%d done=%d\n", - buf->idx, buf_priv->age, - done_age ); -#if ROTATE_BUFS start = 0; -#endif } udelay( 1 ); } @@ -1326,14 +1250,10 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev ) void radeon_freelist_reset( drm_device_t *dev ) { drm_device_dma_t *dma = dev->dma; -#if ROTATE_BUFS drm_radeon_private_t *dev_priv = dev->dev_private; -#endif int i; -#if ROTATE_BUFS dev_priv->last_buf = 0; -#endif for ( i = 0 ; i < dma->buf_count ; i++ ) { drm_buf_t *buf = dma->buflist[i]; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; diff --git a/linux/radeon_drm.h b/linux/radeon_drm.h index 382f49fb..7cfd7f92 100644 --- a/linux/radeon_drm.h +++ b/linux/radeon_drm.h @@ -98,8 +98,10 @@ #define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ #define RADEON_CMD_SCALARS 2 /* emit scalar data */ #define RADEON_CMD_VECTORS 3 /* emit vector data */ -#define RADEON_CMD_PRIMITIVE 4 /* emit a primitive from current dma buf */ -#define RADEON_CMD_DMA_DISCARD 5 /* discard current dma buf */ +#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ +#define RADEON_CMD_PACKET3 5 /* emit hw packet */ +#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ + typedef union { int i; @@ -115,9 +117,6 @@ typedef union { struct { char cmd_type, offset, stride, count; } vectors; - struct { - char cmd_type, buf_idx, pad0, pad1; - } primitive; struct { char cmd_type, buf_idx, pad0, pad1; } dma; @@ -145,7 +144,6 @@ typedef union { /* Byte offsets for indirect buffer data */ #define RADEON_INDEX_PRIM_OFFSET 20 -#define RADEON_HOSTDATA_BLIT_OFFSET 32 #define RADEON_SCRATCH_REG_OFFSET 32 @@ -253,13 +251,6 @@ typedef struct { unsigned int vc_format; /* vertex format */ } drm_radeon_prim_t; -typedef struct { - unsigned int start; - unsigned int finish; - unsigned int prim; - unsigned int numverts; /* overloaded as offset/64 for elt prims */ - unsigned int vc_format; /* vertex format */ -} drm_radeon_tcl_prim_t; typedef struct { drm_radeon_context_regs_t context; @@ -437,4 +428,15 @@ typedef struct drm_radeon_indirect { int discard; } drm_radeon_indirect_t; + +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_AGP_BUFFER_OFFSET 0x1 + +typedef struct drm_radeon_getparam { + int param; + int *value; +} drm_radeon_getparam_t; + #endif diff --git a/linux/radeon_drv.c b/linux/radeon_drv.c index d14c112e..db0641c4 100644 --- a/linux/radeon_drv.c +++ b/linux/radeon_drv.c @@ -68,7 +68,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, #include "drm_agpsupport.h" diff --git a/linux/radeon_drv.h b/linux/radeon_drv.h index ea87c738..df5c47f2 100644 --- a/linux/radeon_drv.h +++ b/linux/radeon_drv.h @@ -71,14 +71,7 @@ typedef struct drm_radeon_private { drm_radeon_freelist_t *head; drm_radeon_freelist_t *tail; -/* FIXME: ROTATE_BUFS is a hask to cycle through bufs until freelist - code is used. Note this hides a problem with the scratch register - (used to keep track of last buffer completed) being written to before - the last buffer has actually completed rendering. */ -#define ROTATE_BUFS 1 -#if ROTATE_BUFS int last_buf; -#endif volatile u32 *scratch; int usec_timeout; @@ -120,10 +113,6 @@ typedef struct drm_radeon_private { typedef struct drm_radeon_buf_priv { u32 age; - int prim; - int discard; - int dispatched; - drm_radeon_freelist_t *list_entry; } drm_radeon_buf_priv_t; /* radeon_cp.c */ @@ -180,6 +169,8 @@ extern int radeon_cp_vertex2( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int radeon_cp_cmdbuf( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int radeon_cp_getparam( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); @@ -467,8 +458,10 @@ extern int radeon_cp_cmdbuf( struct inode *inode, struct file *filp, #define RADEON_CP_PACKET3 0xC0000000 # define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300 # define RADEON_WAIT_FOR_IDLE 0x00002600 +# define RADEON_3D_DRAW_VBUF 0x00002800 # define RADEON_3D_DRAW_IMMD 0x00002900 -# define RADEON_3D_CLEAR_ZMASK 0x00003200 +# define RADEON_3D_DRAW_INDX 0x00002A00 +# define RADEON_3D_LOAD_VBPNTR 0x00002F00 # define RADEON_CNTL_HOSTDATA_BLT 0x00009400 # define RADEON_CNTL_PAINT_MULTI 0x00009A00 # define RADEON_CNTL_BITBLT_MULTI 0x00009B00 diff --git a/linux/radeon_state.c b/linux/radeon_state.c index 1e71a7e5..78854cab 100644 --- a/linux/radeon_state.c +++ b/linux/radeon_state.c @@ -610,6 +610,40 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) ADVANCE_RING(); } +static int bad_prim_vertex_nr( int primitive, int nr ) +{ + switch (primitive & RADEON_PRIM_TYPE_MASK) { + case RADEON_PRIM_TYPE_NONE: + case RADEON_PRIM_TYPE_POINT: + return nr < 1; + case RADEON_PRIM_TYPE_LINE: + return (nr & 1) || nr == 0; + case RADEON_PRIM_TYPE_LINE_STRIP: + return nr < 2; + case RADEON_PRIM_TYPE_TRI_LIST: + case RADEON_PRIM_TYPE_3VRT_POINT_LIST: + case RADEON_PRIM_TYPE_3VRT_LINE_LIST: + case RADEON_PRIM_TYPE_RECT_LIST: + return nr % 3 || nr == 0; + case RADEON_PRIM_TYPE_TRI_FAN: + case RADEON_PRIM_TYPE_TRI_STRIP: + return nr < 3; + default: + return 1; + } +} + + + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim; + unsigned int numverts; + unsigned int offset; + unsigned int vc_format; +} drm_radeon_tcl_prim_t; + static void radeon_cp_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf, drm_radeon_tcl_prim_t *prim, @@ -618,7 +652,6 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev, { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; drm_clip_rect_t box; int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start; int numverts = (int)prim->numverts; @@ -634,52 +667,12 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev, prim->finish, prim->numverts); - switch (prim->prim & RADEON_PRIM_TYPE_MASK) { - case RADEON_PRIM_TYPE_NONE: - case RADEON_PRIM_TYPE_POINT: - if (prim->numverts < 1) { - DRM_ERROR( "Bad nr verts for line %d\n", - prim->numverts); - return; - } - break; - case RADEON_PRIM_TYPE_LINE: - if ((prim->numverts & 1) || prim->numverts == 0) { - DRM_ERROR( "Bad nr verts for line %d\n", - prim->numverts); - return; - } - break; - case RADEON_PRIM_TYPE_LINE_STRIP: - if (prim->numverts < 2) { - DRM_ERROR( "Bad nr verts for line_strip %d\n", - prim->numverts); - return; - } - break; - case RADEON_PRIM_TYPE_TRI_LIST: - case RADEON_PRIM_TYPE_3VRT_POINT_LIST: - case RADEON_PRIM_TYPE_3VRT_LINE_LIST: - case RADEON_PRIM_TYPE_RECT_LIST: - if (prim->numverts % 3 || prim->numverts == 0) { - DRM_ERROR( "Bad nr verts for tri %d\n", - prim->numverts); - return; - } - break; - case RADEON_PRIM_TYPE_TRI_FAN: - case RADEON_PRIM_TYPE_TRI_STRIP: - if (prim->numverts < 3) { - DRM_ERROR( "Bad nr verts for strip/fan %d\n", - prim->numverts); - return; - } - break; - default: - DRM_ERROR( "buffer prim %x start %x\n", - prim->prim, prim->start ); + if (bad_prim_vertex_nr( prim->prim, prim->numverts )) { + DRM_ERROR( "bad prim %x numverts %d\n", + prim->prim, prim->numverts ); return; - } + } + do { /* Emit the next cliprect */ @@ -706,19 +699,17 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev, i++; } while ( i < nbox ); - - buf_priv->dispatched = 1; - dev_priv->sarea_priv->last_dispatch++; } + static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf ) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; - buf_priv->age = dev_priv->sarea_priv->last_dispatch; + buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING( 2 ); @@ -727,8 +718,6 @@ static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf ) buf->pending = 1; buf->used = 0; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; } static void radeon_cp_dispatch_indirect( drm_device_t *dev, @@ -736,7 +725,6 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, int start, int end ) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end ); @@ -757,8 +745,6 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, data[dwords++] = RADEON_CP_PACKET2; } - buf_priv->dispatched = 1; - /* Fire off the indirect buffer */ BEGIN_RING( 3 ); @@ -768,8 +754,6 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, ADVANCE_RING(); } - - dev_priv->sarea_priv->last_dispatch++; } @@ -780,67 +764,29 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, int nbox ) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv = elt_buf->dev_private; drm_clip_rect_t box; - int offset = dev_priv->agp_buffers_offset + prim->numverts * 64; + int offset = dev_priv->agp_buffers_offset + prim->offset; u32 *data; int dwords; int i = 0; int start = prim->start + RADEON_INDEX_PRIM_OFFSET; int count = (prim->finish - start) / sizeof(u16); - DRM_DEBUG("%s: hwprim 0x%x vfmt 0x%x %d..%d offset: %x\n", + DRM_DEBUG("%s: hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", __FUNCTION__, prim->prim, prim->vc_format, prim->start, prim->finish, - prim->numverts * 64); + prim->offset, + prim->numverts); - switch (prim->prim & RADEON_PRIM_TYPE_MASK) { - case RADEON_PRIM_TYPE_NONE: - case RADEON_PRIM_TYPE_POINT: - if (count < 1) { - DRM_ERROR( "Bad nr verts for line %d\n", - count); - return; - } - break; - case RADEON_PRIM_TYPE_LINE: - if ((count & 1) || count == 0) { - DRM_ERROR( "Bad nr verts for line %d\n", - count); - return; - } - break; - case RADEON_PRIM_TYPE_LINE_STRIP: - if (count < 2) { - DRM_ERROR( "Bad nr verts for line_strip %d\n", - count); - return; - } - break; - case RADEON_PRIM_TYPE_TRI_LIST: - case RADEON_PRIM_TYPE_3VRT_POINT_LIST: - case RADEON_PRIM_TYPE_3VRT_LINE_LIST: - case RADEON_PRIM_TYPE_RECT_LIST: - if (count % 3 || count == 0) { - DRM_ERROR( "Bad nr verts for tri %d\n", count); - return; - } - break; - case RADEON_PRIM_TYPE_TRI_FAN: - case RADEON_PRIM_TYPE_TRI_STRIP: - if (count < 3) { - DRM_ERROR( "Bad nr verts for strip/fan %d\n", count); - return; - } - break; - default: - DRM_ERROR( "buffer prim %x start %x\n", - prim->prim, prim->start ); + if (bad_prim_vertex_nr( prim->prim, count )) { + DRM_ERROR( "bad prim %x count %d\n", + prim->prim, count ); return; - } + } + if ( start >= prim->finish || (prim->start & 0x7) ) { @@ -855,7 +801,7 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); data[1] = offset; - data[2] = RADEON_MAX_VB_VERTS; + data[2] = prim->numverts; data[3] = prim->vc_format; data[4] = (prim->prim | RADEON_PRIM_WALK_IND | @@ -878,9 +824,6 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, i++; } while ( i < nbox ); - - buf_priv->dispatched = 1; - dev_priv->sarea_priv->last_dispatch++; } #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32)) @@ -891,7 +834,6 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, { drm_radeon_private_t *dev_priv = dev->dev_private; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; u32 format; u32 *buffer; u8 *data; @@ -909,8 +851,6 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, tex->offset >> 10, tex->pitch, tex->format, image->x, image->y, image->width, image->height ); - buf_priv = buf->dev_private; - /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll * use a shift instead. @@ -1036,7 +976,6 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, buf->pid = current->pid; buf->used = (dwords + 8) * sizeof(u32); - buf_priv->discard = 1; radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); radeon_cp_discard_buffer( dev, buf ); @@ -1160,7 +1099,6 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp, drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_vertex_t vertex; drm_radeon_tcl_prim_t prim; @@ -1194,7 +1132,6 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp, VB_AGE_TEST_WITH_RETURN( dev_priv ); buf = dma->buflist[vertex.idx]; - buf_priv = buf->dev_private; if ( buf->pid != current->pid ) { DRM_ERROR( "process %d using buffer owned by %d\n", @@ -1250,7 +1187,6 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_indices_t elts; drm_radeon_tcl_prim_t prim; int count; @@ -1285,7 +1221,6 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, VB_AGE_TEST_WITH_RETURN( dev_priv ); buf = dma->buflist[elts.idx]; - buf_priv = buf->dev_private; if ( buf->pid != current->pid ) { DRM_ERROR( "process %d using buffer owned by %d\n", @@ -1329,7 +1264,8 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, prim.start = elts.start; prim.finish = elts.end; prim.prim = elts.prim; - prim.numverts = 0; /* offset from start of dma buffers */ + prim.offset = 0; /* offset from start of dma buffers */ + prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ prim.vc_format = dev_priv->sarea_priv->vc_format; radeon_cp_dispatch_indices( dev, buf, &prim, @@ -1405,7 +1341,6 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_indirect_t indirect; RING_LOCALS; @@ -1431,7 +1366,6 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp, } 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", @@ -1453,7 +1387,6 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp, VB_AGE_TEST_WITH_RETURN( dev_priv ); buf->used = indirect.end; - buf_priv->discard = indirect.discard; /* Wait for the 3D stream to idle before the indirect buffer * containing 2D acceleration commands is processed. @@ -1486,7 +1419,6 @@ int radeon_cp_vertex2( struct inode *inode, struct file *filp, drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_vertex2_t vertex; int i; unsigned char laststate; @@ -1515,7 +1447,6 @@ int radeon_cp_vertex2( struct inode *inode, struct file *filp, VB_AGE_TEST_WITH_RETURN( dev_priv ); buf = dma->buflist[vertex.idx]; - buf_priv = buf->dev_private; if ( buf->pid != current->pid ) { DRM_ERROR( "process %d using buffer owned by %d\n", @@ -1527,6 +1458,9 @@ int radeon_cp_vertex2( struct inode *inode, struct file *filp, DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); return -EINVAL; } + + if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) + return -EINVAL; for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) { drm_radeon_prim_t prim; @@ -1551,14 +1485,19 @@ int radeon_cp_vertex2( struct inode *inode, struct file *filp, tclprim.start = prim.start; tclprim.finish = prim.finish; tclprim.prim = prim.prim; - tclprim.numverts = prim.numverts; tclprim.vc_format = prim.vc_format; if ( prim.prim & RADEON_PRIM_WALK_IND ) { + tclprim.offset = prim.numverts * 64; + tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ + radeon_cp_dispatch_indices( dev, buf, &tclprim, sarea_priv->boxes, sarea_priv->nbox); } else { + tclprim.numverts = prim.numverts; + tclprim.offset = 0; /* not used */ + radeon_cp_dispatch_vertex( dev, buf, &tclprim, sarea_priv->boxes, sarea_priv->nbox); @@ -1656,35 +1595,88 @@ static inline int radeon_emit_vectors( return 0; } -static int radeon_emit_primitive( - drm_device_t *dev, - drm_buf_t *buf, - drm_radeon_cmd_buffer_t *cmdbuf ) + +static int radeon_emit_packet3( drm_device_t *dev, + drm_radeon_cmd_buffer_t *cmdbuf ) { - drm_radeon_tcl_prim_t prim; + drm_radeon_private_t *dev_priv = dev->dev_private; + int cmdsz, tmp; + int *cmd = (int *)cmdbuf->buf; + int j; + RING_LOCALS; - if (cmdbuf->bufsz < sizeof(prim)) + DRM_DEBUG("%s\n", __FUNCTION__); + + if (__get_user( tmp, &cmd[0])) return -EFAULT; - if (__copy_from_user(&prim, cmdbuf->buf, sizeof(prim))) - return -EFAULT; - + cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); - if ( prim.prim & RADEON_PRIM_WALK_IND ) { - radeon_cp_dispatch_indices( dev, buf, &prim, - cmdbuf->boxes, - cmdbuf->nbox); - } else { - radeon_cp_dispatch_vertex( dev, buf, &prim, - cmdbuf->boxes, - cmdbuf->nbox); + if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || + cmdsz * 4 > cmdbuf->bufsz) + return -EINVAL; + + + BEGIN_RING( cmdsz ); + for (j = 0 ; j < cmdsz ; j++) { + if (__get_user( tmp, &cmd[j] )) + return -EFAULT; +/* printk( "pk3 %d: %x\n", j, tmp); */ + OUT_RING( tmp ); } + ADVANCE_RING(); - if (cmdbuf->nbox == 1) + cmdbuf->buf += cmdsz * 4; + cmdbuf->bufsz -= cmdsz * 4; + return 0; +} + + +static int radeon_emit_packet3_cliprect( drm_device_t *dev, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_clip_rect_t box; + int cmdsz, tmp; + int *cmd = (int *)cmdbuf->buf; + drm_clip_rect_t *boxes = cmdbuf->boxes; + int i = 0, j; + RING_LOCALS; + + DRM_DEBUG("%s\n", __FUNCTION__); + + if (__get_user( tmp, &cmd[0])) + return -EFAULT; + + cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); + + if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || + cmdsz * 4 > cmdbuf->bufsz) + return -EINVAL; + + do { + if ( i < cmdbuf->nbox ) { + if (__copy_from_user( &box, &boxes[i], sizeof(box) )) + return -EFAULT; + radeon_emit_clip_rect( dev_priv, &box ); + } + + BEGIN_RING( cmdsz ); + for (j = 0 ; j < cmdsz ; j++) { + if (__get_user( tmp, &cmd[j] )) + return -EFAULT; +/* printk( "pk3_clip %d: %x\n", j, tmp); */ + OUT_RING( tmp ); + } + ADVANCE_RING(); + + } while ( ++i < cmdbuf->nbox ); + + if (cmdbuf->nbox == 1) cmdbuf->nbox = 0; - cmdbuf->buf += sizeof(prim); - cmdbuf->bufsz -= sizeof(prim); + cmdbuf->buf += cmdsz * 4; + cmdbuf->bufsz -= cmdsz * 4; return 0; } @@ -1759,26 +1751,6 @@ int radeon_cp_cmdbuf( struct inode *inode, struct file *filp, } break; - case RADEON_CMD_PRIMITIVE: - idx = header.dma.buf_idx; - if ( idx < 0 || idx >= dma->buf_count ) { - DRM_ERROR( "buffer index %d (of %d max)\n", - idx, dma->buf_count - 1 ); - return -EINVAL; - } - - buf = dma->buflist[idx]; - if ( buf->pid != current->pid || buf->pending ) { - DRM_ERROR( "bad buffer\n" ); - return -EINVAL; - } - - if (radeon_emit_primitive( dev, buf, &cmdbuf )) { - DRM_ERROR("radeon_emit_primitive failed\n"); - return -EINVAL; - } - break; - case RADEON_CMD_DMA_DISCARD: idx = header.dma.buf_idx; if ( idx < 0 || idx >= dma->buf_count ) { @@ -1796,6 +1768,20 @@ int radeon_cp_cmdbuf( struct inode *inode, struct file *filp, radeon_cp_discard_buffer( dev, buf ); break; + case RADEON_CMD_PACKET3: + if (radeon_emit_packet3( dev, &cmdbuf )) { + DRM_ERROR("radeon_emit_packet3 failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_PACKET3_CLIP: + if (radeon_emit_packet3_cliprect( dev, &cmdbuf )) { + DRM_ERROR("radeon_emit_packet3_clip failed\n"); + return -EINVAL; + } + break; + default: DRM_ERROR("bad cmd_type %d at %p\n", header.header.cmd_type, @@ -1810,6 +1796,46 @@ int radeon_cp_cmdbuf( struct inode *inode, struct file *filp, +int radeon_cp_getparam( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if ( copy_from_user( ¶m, (drm_radeon_getparam_t *)arg, + sizeof(param) ) ) { + DRM_ERROR("copy_from_user\n"); + return -EFAULT; + } + + DRM_DEBUG( __FUNCTION__": pid=%d\n", current->pid ); + + switch( param.param ) { + case RADEON_PARAM_AGP_BUFFER_OFFSET: + value = dev_priv->agp_buffers_offset; + break; + default: + return -EINVAL; + } + + if ( copy_to_user( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + + return 0; +} + + + diff --git a/shared-core/drm.h b/shared-core/drm.h index b0bf91c4..b0819995 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -491,6 +491,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) /* Gamma specific ioctls */ #define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t) diff --git a/shared/drm.h b/shared/drm.h index b0bf91c4..b0819995 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -491,6 +491,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) /* Gamma specific ioctls */ #define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t)