summaryrefslogtreecommitdiff
path: root/xc/lib/GL/mesa/src/drv/i810/i810ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/i810/i810ioctl.c')
-rw-r--r--xc/lib/GL/mesa/src/drv/i810/i810ioctl.c436
1 files changed, 436 insertions, 0 deletions
diff --git a/xc/lib/GL/mesa/src/drv/i810/i810ioctl.c b/xc/lib/GL/mesa/src/drv/i810/i810ioctl.c
new file mode 100644
index 000000000..93e2f4492
--- /dev/null
+++ b/xc/lib/GL/mesa/src/drv/i810/i810ioctl.c
@@ -0,0 +1,436 @@
+#include <stdio.h>
+
+
+#include "types.h"
+#include "pb.h"
+#include "dd.h"
+
+#include "mm.h"
+#include "i810context.h"
+#include "i810log.h"
+#include "i810ioctl.h"
+
+#include "drm.h"
+#include <sys/ioctl.h>
+
+static int _tot_used, _tot_size;
+
+void i810FlushGeneralLocked( i810ContextPtr imesa )
+{
+ int retcode;
+ drm_i810_general_t dma;
+ drmBufPtr buf = imesa->dma_buffer;
+
+ if (!buf) {
+ fprintf(stderr, "i810FlushGeneralLocked: no buffer\n");
+ return;
+ }
+
+ _tot_used += buf->used;
+ _tot_size += buf->total;
+
+ dma.idx = buf->idx;
+ dma.used = buf->used;
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "DRM_IOCTL_I810_DMA idx %d used %d\n",
+ dma.idx, dma.used);
+
+ if ((retcode = ioctl(imesa->driFd, DRM_IOCTL_I810_DMA, &dma))) {
+ printf("send dma retcode = %d\n", retcode);
+ exit(1);
+ }
+
+ imesa->dma_buffer = 0;
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "finished general dma put\n");
+}
+
+static drmBufPtr i810_get_buffer_ioctl( i810ContextPtr imesa )
+{
+ int idx = 0;
+ int size = 0;
+ drmDMAReq dma;
+ int retcode;
+ drmBufPtr buf;
+ int cnt = 0;
+
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "Getting dma buffer\n");
+
+ dma.context = imesa->hHWContext;
+ dma.send_count = 0;
+ dma.send_list = NULL;
+ dma.send_sizes = NULL;
+ dma.flags = 0;
+ dma.request_count = 1;
+ dma.request_size = I810_DMA_BUF_SZ;
+ dma.request_list = &idx;
+ dma.request_sizes = &size;
+ dma.granted_count = 0;
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "drmDMA (get) ctx %d count %d size 0x%x\n",
+ dma.context, dma.request_count,
+ dma.request_size);
+
+ while (1) {
+ retcode = drmDMA(imesa->driFd, &dma);
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "retcode %d sz %d idx %d count %d\n",
+ retcode,
+ dma.request_sizes[0],
+ dma.request_list[0],
+ dma.granted_count);
+
+ if (retcode == 0 &&
+ dma.request_list[0] &&
+ dma.request_sizes[0] &&
+ dma.granted_count)
+ break;
+
+ if (++cnt > 1000) {
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) {
+ fprintf(stderr, "\n\nflush retcode %d idx %d sz %d count %d\n",
+ retcode, dma.request_list[0],
+ dma.request_sizes[0], dma.granted_count);
+
+ fprintf(stderr, "used %d size %d (ratio %.3f)\n",
+ _tot_used, _tot_size, (float)_tot_size / (float)_tot_used);
+ }
+
+ ioctl(imesa->driFd, DRM_IOCTL_I810_FLUSH);
+ }
+ }
+
+
+
+ buf = &(imesa->i810Screen->bufs->list[idx]);
+ buf->used = 0;
+
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr,
+ "drmDMA (get) returns size[0] 0x%x idx[0] %d\n"
+ "dma_buffer now: buf idx: %d size: %d used: %d\n",
+ dma.request_sizes[0], dma.request_list[0],
+ buf->idx, buf->total,
+ buf->used);
+
+ return buf;
+}
+
+
+
+void i810GetGeneralDmaBufferLocked( i810ContextPtr imesa )
+{
+ if (imesa->dma_buffer) {
+ fprintf(stderr, "i810GetGeneralDmaBufferLocked - dma_buffer not zero\n");
+ exit(1);
+ }
+
+ imesa->dma_buffer = i810_get_buffer_ioctl( imesa );
+}
+
+
+
+/* This waits for *everybody* to finish rendering -- overkill.
+ */
+void i810DmaFinish( i810ContextPtr imesa )
+{
+ FLUSH_BATCH( imesa );
+
+ if (imesa->sarea->last_quiescent != imesa->sarea->last_enqueue) {
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "i810DmaFinish\n");
+
+ LOCK_HARDWARE( imesa );
+ i810RegetLockQuiescent( imesa );
+ UNLOCK_HARDWARE( imesa );
+ imesa->sarea->last_quiescent = imesa->sarea->last_enqueue;
+ }
+}
+
+
+void i810RegetLockQuiescent( i810ContextPtr imesa )
+{
+ if (imesa->sarea->last_quiescent != imesa->sarea->last_enqueue) {
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "i810RegetLockQuiescent\n");
+
+ drmUnlock(imesa->driFd, imesa->hHWContext);
+ i810GetLock( imesa, DRM_LOCK_QUIESCENT );
+ imesa->sarea->last_quiescent = imesa->sarea->last_enqueue;
+ }
+}
+
+void i810WaitAgeLocked( i810ContextPtr imesa, int age )
+{
+ int i = 0;
+
+ if (0) fprintf(stderr, "waitagelocked\n");
+
+ while (++i < 500000 && GET_DISPATCH_AGE(imesa) < age) {
+ ioctl(imesa->driFd, DRM_IOCTL_I810_GETAGE);
+ }
+
+ if (GET_DISPATCH_AGE(imesa) < age) {
+ if (0)
+ fprintf(stderr, "wait locked %d %d\n", age, GET_DISPATCH_AGE(imesa));
+ ioctl(imesa->driFd, DRM_IOCTL_I810_FLUSH);
+ }
+}
+
+
+void i810WaitAge( i810ContextPtr imesa, int age )
+{
+ int i = 0;
+
+ while (++i < 500000 && GET_DISPATCH_AGE(imesa) < age) {
+ ioctl(imesa->driFd, DRM_IOCTL_I810_GETAGE);
+ }
+
+ if (GET_DISPATCH_AGE(imesa) >= age)
+ return;
+
+ i = 0;
+ while (++i < 1000 && GET_DISPATCH_AGE(imesa) < age) {
+ ioctl(imesa->driFd, DRM_IOCTL_I810_GETAGE);
+ usleep(1000);
+ }
+
+ /* To be effective at letting other clients at the hardware,
+ * particularly the X server which regularly needs quiescence to
+ * touch the framebuffer, we really need to sleep *beyond* the
+ * point where our last buffer clears the hardware.
+ */
+ if (imesa->any_contend) {
+ usleep(3000);
+ }
+
+ imesa->any_contend = 0;
+
+ if (GET_DISPATCH_AGE(imesa) < age) {
+ LOCK_HARDWARE(imesa);
+ if (GET_DISPATCH_AGE(imesa) < age)
+ ioctl(imesa->driFd, DRM_IOCTL_I810_FLUSH);
+ UNLOCK_HARDWARE(imesa);
+ }
+}
+
+
+
+void i810FlushVertices( i810ContextPtr imesa )
+{
+ if (!imesa->vertex_dma_buffer) return;
+
+ LOCK_HARDWARE( imesa );
+ i810FlushVerticesLocked( imesa );
+ UNLOCK_HARDWARE( imesa );
+}
+
+
+static int intersect_rect( drm_clip_rect_t *out,
+ drm_clip_rect_t *a,
+ drm_clip_rect_t *b )
+{
+ *out = *a;
+ if (b->x1 > out->x1) out->x1 = b->x1;
+ if (b->y1 > out->y1) out->y1 = b->y1;
+ if (b->x2 < out->x2) out->x2 = b->x2;
+ if (b->y2 < out->y2) out->y2 = b->y2;
+ if (out->x1 >= out->x2) return 0;
+ if (out->y1 >= out->y2) return 0;
+ return 1;
+}
+
+
+static void age_imesa( i810ContextPtr imesa, int age )
+{
+ if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->age = age;
+ if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->age = age;
+}
+
+void i810FlushVerticesLocked( i810ContextPtr imesa )
+{
+ drm_clip_rect_t *pbox = (drm_clip_rect_t *)imesa->pClipRects;
+ int nbox = imesa->numClipRects;
+ drmBufPtr buffer = imesa->vertex_dma_buffer;
+ drm_i810_vertex_t vertex;
+ int i;
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "i810FlushVerticesLocked, buf %p\n", buffer);
+
+ if (!buffer)
+ return;
+
+ if (imesa->dirty & ~I810_EMIT_CLIPRECT)
+ i810EmitHwStateLocked( imesa );
+
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "i810FlushVerticesLocked, used %d\n",
+ buffer->used);
+
+ _tot_used += buffer->used;
+ _tot_size += buffer->total;
+
+ imesa->vertex_dma_buffer = 0;
+
+ vertex.idx = buffer->idx;
+ vertex.used = buffer->used;
+ vertex.discard = 0;
+
+ if (!nbox)
+ vertex.used = 0;
+
+ if (nbox > I810_NR_SAREA_CLIPRECTS)
+ imesa->dirty |= I810_EMIT_CLIPRECT;
+
+ if (!vertex.used || !(imesa->dirty & I810_EMIT_CLIPRECT))
+ {
+ if (nbox == 1)
+ imesa->sarea->nbox = 0;
+ else
+ imesa->sarea->nbox = nbox;
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "DRM_IOCTL_I810_VERTEX CASE1 nbox %d used %d\n",
+ nbox, vertex.used);
+
+ vertex.discard = 1;
+ ioctl(imesa->driFd, DRM_IOCTL_I810_VERTEX, &vertex);
+ age_imesa(imesa, imesa->sarea->last_enqueue);
+ }
+ else
+ {
+ for (i = 0 ; i < nbox ; )
+ {
+ int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, nbox);
+ drm_clip_rect_t *b = imesa->sarea->boxes;
+
+ if (imesa->scissor) {
+ imesa->sarea->nbox = 0;
+
+ for ( ; i < nr ; i++) {
+ b->x1 = pbox[i].x1 - imesa->drawX;
+ b->y1 = pbox[i].y1 - imesa->drawY;
+ b->x2 = pbox[i].x2 - imesa->drawX;
+ b->y2 = pbox[i].y2 - imesa->drawY;
+
+ if (intersect_rect(b, b, &imesa->scissor_rect)) {
+ imesa->sarea->nbox++;
+ b++;
+ }
+ }
+
+ /* Culled?
+ */
+ if (!imesa->sarea->nbox) {
+ if (nr < nbox) continue;
+ vertex.used = 0;
+ }
+ } else {
+ imesa->sarea->nbox = nr - i;
+ for ( ; i < nr ; i++, b++) {
+ b->x1 = pbox[i].x1 - imesa->drawX;
+ b->y1 = pbox[i].y1 - imesa->drawY;
+ b->x2 = pbox[i].x2 - imesa->drawX;
+ b->y2 = pbox[i].y2 - imesa->drawY;
+ }
+ }
+
+ /* Finished with the buffer?
+ */
+ if (nr == nbox)
+ vertex.discard = 1;
+
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "DRM_IOCTL_I810_VERTEX nbox %d used %d\n",
+ nbox, vertex.used);
+
+ ioctl(imesa->driFd, DRM_IOCTL_I810_VERTEX, &vertex);
+ age_imesa(imesa, imesa->sarea->last_enqueue);
+ }
+ }
+
+ imesa->dirty = 0;
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "finished i810FlushVerticesLocked\n");
+}
+
+
+GLuint *i810AllocDwords( i810ContextPtr imesa, int dwords )
+{
+ GLuint orig_dwords = dwords;
+ GLuint *start;
+
+ dwords++;
+ dwords&=~1;
+
+ if (!imesa->vertex_dma_buffer)
+ {
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "i810AllocPrimitiveVerts -- get buf\n");
+ LOCK_HARDWARE(imesa);
+ imesa->vertex_dma_buffer = i810_get_buffer_ioctl( imesa );
+ UNLOCK_HARDWARE(imesa);
+ }
+ else if (imesa->vertex_dma_buffer->used + dwords * 4 >
+ imesa->vertex_dma_buffer->total)
+ {
+ if (I810_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "i810AllocPrimitiveVerts -- flush\n");
+ i810FlushVertices( imesa );
+ LOCK_HARDWARE(imesa);
+ imesa->vertex_dma_buffer = i810_get_buffer_ioctl( imesa );
+ UNLOCK_HARDWARE(imesa);
+ }
+
+ if (0)
+ fprintf(stderr, "i810AllocPrimitiveVerts %d, buf %d, used %d\n",
+ dwords, imesa->vertex_dma_buffer->idx,
+ imesa->vertex_dma_buffer->used);
+
+
+ start = (GLuint *)((char *)imesa->vertex_dma_buffer->address +
+ imesa->vertex_dma_buffer->used);
+
+ imesa->vertex_dma_buffer->used += dwords * 4;
+
+ if (orig_dwords & 1)
+ *start++ = 0;
+
+ return start;
+}
+
+
+
+
+
+
+static void i810DDFlush( GLcontext *ctx )
+{
+ i810ContextPtr imesa = I810_CONTEXT( ctx );
+ FLUSH_BATCH( imesa );
+}
+
+
+static void i810DDFinish( GLcontext *ctx )
+{
+ i810ContextPtr imesa = I810_CONTEXT( ctx );
+ i810DmaFinish( imesa );
+}
+
+
+void i810DDInitIoctlFuncs( GLcontext *ctx )
+{
+ ctx->Driver.Flush = i810DDFlush;
+ ctx->Driver.Finish = i810DDFinish;
+}