summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2000-02-11 01:11:13 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2000-02-11 01:11:13 +0000
commit6a54cedbf1eacf6fee9ff0a8286829a4e62de699 (patch)
tree5727201d9facfa23087f2c45341b947e91fba448
parentc0a9edafb3ecf1045f6f0b7ddc5df9b059c2289c (diff)
multictx with arbitary number of cliprects
-rw-r--r--linux-core/mga_drv.c5
-rw-r--r--linux/mga_clear.c90
-rw-r--r--linux/mga_dma.c31
-rw-r--r--linux/mga_dma.h4
-rw-r--r--linux/mga_drm_public.h19
-rw-r--r--linux/mga_drv.c5
-rw-r--r--linux/mga_drv.h2
-rw-r--r--linux/mga_state.c4
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 );