diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2000-02-11 01:11:13 +0000 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2000-02-11 01:11:13 +0000 |
commit | 6a54cedbf1eacf6fee9ff0a8286829a4e62de699 (patch) | |
tree | 5727201d9facfa23087f2c45341b947e91fba448 | |
parent | c0a9edafb3ecf1045f6f0b7ddc5df9b059c2289c (diff) |
multictx with arbitary number of cliprects
-rw-r--r-- | linux-core/mga_drv.c | 5 | ||||
-rw-r--r-- | linux/mga_clear.c | 90 | ||||
-rw-r--r-- | linux/mga_dma.c | 31 | ||||
-rw-r--r-- | linux/mga_dma.h | 4 | ||||
-rw-r--r-- | linux/mga_drm_public.h | 19 | ||||
-rw-r--r-- | linux/mga_drv.c | 5 | ||||
-rw-r--r-- | linux/mga_drv.h | 2 | ||||
-rw-r--r-- | linux/mga_state.c | 4 |
8 files changed, 104 insertions, 56 deletions
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c index 25f06580..a4bb6ea8 100644 --- a/linux-core/mga_drv.c +++ b/linux-core/mga_drv.c @@ -105,9 +105,10 @@ static drm_ioctl_desc_t mga_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 1 }, }; #define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls) diff --git a/linux/mga_clear.c b/linux/mga_clear.c index e52ef743..40f331ce 100644 --- a/linux/mga_clear.c +++ b/linux/mga_clear.c @@ -104,8 +104,6 @@ int mgaSwapBuffers(drm_device_t *dev, drm_mga_swap_t *args) buf_priv->dma_type = MGA_DMA_DISCARD; } - - /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX; @@ -192,6 +190,48 @@ static int mgaIload(drm_device_t *dev, drm_mga_iload_t *args) } +static int mgaDmaVertex(drm_device_t *dev, drm_mga_vertex_t *args) +{ + drm_device_dma_t *dma = dev->dma; + drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; + drm_mga_buf_priv_t *buf_priv; + drm_buf_t *buf; + drm_dma_t d; + + + buf = dma->buflist[ args->idx ]; + + printk("mgaDmaVertex idx %d used %d\n", args->idx, buf->used); + + buf_priv = buf->dev_private; + buf_priv->dma_type = MGA_DMA_VERTEX; + buf_priv->vertex_real_idx = args->real_idx; + buf->used = args->real_used; + + if (!mgaCopyAndVerifyState(dev_priv, buf_priv, ~0)) + buf_priv->dma_type = MGA_DMA_DISCARD; + + d.context = DRM_KERNEL_CONTEXT; + d.send_count = 1; + d.send_indices = &buf->idx; + d.send_sizes = &buf->used; + d.flags = 0; + d.request_count = 0; + d.request_size = 0; + d.request_indices = NULL; + d.request_sizes = NULL; + d.granted_count = 0; + + atomic_inc(&dev_priv->pending_bufs); + if((drm_dma_enqueue(dev, &d)) != 0) + atomic_dec(&dev_priv->pending_bufs); + mga_dma_schedule(dev, 1); + return 0; +} + + + + int mga_clear_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -241,6 +281,23 @@ int mga_iload(struct inode *inode, struct file *filp, return retcode; } +int mga_vertex(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_mga_vertex_t vertex; + int retcode = 0; + + copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex), + -EFAULT); + + retcode = mgaDmaVertex(dev, &vertex); + + return retcode; + +} + int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) @@ -261,42 +318,21 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, d.context = DRM_KERNEL_CONTEXT; d.flags &= ~_DRM_DMA_WHILE_LOCKED; - /* Maybe multiple buffers is useful for iload... - * But this ioctl is only for *despatching* vertex data... + /* Please don't send us buffers. */ - if (d.send_count < 0 || d.send_count > 1) { - DRM_ERROR("Process %d trying to send %d buffers (max 1)\n", + if (d.send_count != 0) { + DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", current->pid, d.send_count); return -EINVAL; } - - /* But it *is* used to request buffers for all types of dma: + /* We'll send you buffers. */ if (d.request_count < 0 || d.request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", current->pid, d.request_count, dma->buf_count); return -EINVAL; } - - if (d.send_count) { - int idx = d.send_indices[0]; - drm_mga_buf_priv_t *buf_priv = dma->buflist[ idx ]->dev_private; - drm_mga_private_t *dev_priv = dev->dev_private; - - buf_priv->dma_type = MGA_DMA_VERTEX; - - /* Snapshot the relevent bits of the sarea... - */ - if (!mgaCopyAndVerifyState( dev_priv, buf_priv, ~0 )) - dma->buflist[ idx ]->used = 0; - - atomic_inc(&dev_priv->pending_bufs); - retcode = drm_dma_enqueue(dev, &d); - if(retcode != 0) - atomic_dec(&dev_priv->pending_bufs); - mga_dma_schedule(dev, 1); - } d.granted_count = 0; diff --git a/linux/mga_dma.c b/linux/mga_dma.c index 40d77cb2..b3ee658a 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -316,7 +316,6 @@ static void __mga_iload_small(drm_device_t *dev, { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; -/* drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; */ unsigned long address = (unsigned long)buf->bus_address; int length = buf->used; int y1 = buf_priv->boxes[0].y1; @@ -356,11 +355,6 @@ static void __mga_iload_small(drm_device_t *dev, PRIMOUTREG(MGAREG_SOFTRAP, 0); PRIMADVANCE(dev_priv); -#if 0 - /* For now we need to set this in the ioctl */ - sarea_priv->dirty |= MGASAREA_NEW_CONTEXT; -#endif - MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -371,7 +365,6 @@ static void __mga_iload_xy(drm_device_t *dev, { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; -/* drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; */ unsigned long address = (unsigned long)buf->bus_address; int length = buf->used; int y1 = buf_priv->boxes[0].y1; @@ -429,10 +422,6 @@ static void __mga_iload_xy(drm_device_t *dev, PRIMOUTREG(MGAREG_DMAPAD, 0); PRIMOUTREG(MGAREG_SOFTRAP, 0); PRIMADVANCE(dev_priv); -#if 0 - /* For now we need to set this in the ioctl */ - sarea_priv->dirty |= MGASAREA_NEW_CONTEXT; -#endif MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); @@ -460,10 +449,12 @@ static void mga_dma_dispatch_iload(drm_device_t *dev, drm_buf_t *buf) static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) { + drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; - unsigned long address = (unsigned long)buf->bus_address; - int length = buf->used; + drm_buf_t *real_buf = dev->dma->buflist[ buf_priv->vertex_real_idx ]; + unsigned long address = (unsigned long)real_buf->bus_address; + int length = buf->used; /* this is correct */ int use_agp = PDEA_pagpxfer_enable; int i, count; PRIMLOCALS; @@ -476,7 +467,6 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) mgaEmitState( dev_priv, buf_priv ); - printk("dispatch vertex addr 0x%lx, length 0x%x nbox %d\n", address, length, buf_priv->nbox); @@ -490,15 +480,16 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) PRIMOUTREG( MGAREG_SECADDRESS, ((__u32)address) | TT_VERTEX); PRIMOUTREG( MGAREG_SECEND, (((__u32)(address + length)) | use_agp)); + PRIMADVANCE( dev_priv ); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_SOFTRAP, 0); - PRIMADVANCE(dev_priv); } - PRIMGETPTR( dev_priv ); + PRIMGETPTR(dev_priv); + PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_SOFTRAP, 0); + PRIMADVANCE( dev_priv ); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); diff --git a/linux/mga_dma.h b/linux/mga_dma.h index c9507d3d..6f183724 100644 --- a/linux/mga_dma.h +++ b/linux/mga_dma.h @@ -20,12 +20,14 @@ typedef struct { unsigned short clear_zval; unsigned int clear_flags; + unsigned int vertex_real_idx; + unsigned int nbox; xf86drmClipRectRec boxes[MGA_NR_SAREA_CLIPRECTS]; } drm_mga_buf_priv_t; -#define MGA_DMA_GENERAL 0 +#define MGA_DMA_GENERAL 0 /* not used */ #define MGA_DMA_VERTEX 1 #define MGA_DMA_SETUP 2 #define MGA_DMA_ILOAD 3 diff --git a/linux/mga_drm_public.h b/linux/mga_drm_public.h index 16b6cc28..cded9314 100644 --- a/linux/mga_drm_public.h +++ b/linux/mga_drm_public.h @@ -154,7 +154,7 @@ typedef struct _xf86drmClipRectRec { #define MGA_UPLOAD_TEX0IMAGE 0x10 #define MGA_UPLOAD_TEX1IMAGE 0x20 #define MGA_UPLOAD_2D 0x40 -#define MGA_REQUIRE_QUIESCENT 0x80 +#define MGA_REQUIRE_QUIESCENT 0x80 /* handled client-side */ #define MGA_UPLOAD_CLIPRECTS 0x100 @@ -209,7 +209,6 @@ typedef struct { typedef struct { int idx; - int flags; /* not actually used? */ } drm_mga_swap_t; typedef struct { @@ -221,8 +220,24 @@ typedef struct { } drm_mga_iload_t; +/* These may be placeholders if we have more cliprects than + * MGA_NR_SAREA_CLIPRECTS. In that case, idx != real_idx; idx is + * the number of a bogus buffer, real_idx is the real buffer to be + * rendered multiple times. + * + * This is a hack to work around the 'generalized gamma driver' + * known as the drm. + */ +typedef struct { + int idx; /* buffer to queue and free on completion */ + int real_idx; /* buffer to execute */ + int real_used; /* buf->used in for real buffer */ +} drm_mga_vertex_t; + + #define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t) #define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t) #define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x42, drm_mga_clear_t) #define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t) #endif diff --git a/linux/mga_drv.c b/linux/mga_drv.c index 25f06580..a4bb6ea8 100644 --- a/linux/mga_drv.c +++ b/linux/mga_drv.c @@ -105,9 +105,10 @@ static drm_ioctl_desc_t mga_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 1 }, }; #define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls) diff --git a/linux/mga_drv.h b/linux/mga_drv.h index c713d70d..ebbcab55 100644 --- a/linux/mga_drv.h +++ b/linux/mga_drv.h @@ -122,6 +122,8 @@ extern int mga_swap_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int mga_iload(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int mga_vertex(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /* mga_context.c */ extern int mga_resctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/linux/mga_state.c b/linux/mga_state.c index f27e3e10..2bf83347 100644 --- a/linux/mga_state.c +++ b/linux/mga_state.c @@ -57,8 +57,8 @@ void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box ) } PRIMOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) ); - PRIMOUTREG( MGAREG_YTOP, box->y1 * dev_priv->stride ); - PRIMOUTREG( MGAREG_YBOT, box->y2 * dev_priv->stride ); + PRIMOUTREG( MGAREG_YTOP, box->y1 * dev_priv->stride/2 ); + PRIMOUTREG( MGAREG_YBOT, box->y2 * dev_priv->stride/2 ); PRIMOUTREG( MGAREG_DMAPAD, 0 ); PRIMADVANCE( dev_priv ); |