diff options
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/i810/i810ioctl.c')
-rw-r--r-- | xc/lib/GL/mesa/src/drv/i810/i810ioctl.c | 436 |
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; +} |