diff options
author | Alan Hourihane <[email protected]> | 2003-09-30 11:02:38 +0000 |
---|---|---|
committer | Alan Hourihane <[email protected]> | 2003-09-30 11:02:38 +0000 |
commit | 6bec5b30e1144fb530971b34087e86afd7162441 (patch) | |
tree | 11169cc8a3805f5941e59f39ced4db8dc3781090 /src/mesa/drivers/dri/i830/i830_ioctl.c | |
parent | 73b0420bba16b5dcfbb75b32bc519295f925041a (diff) |
add the i830 driver - no kernel driver yet
(build tested, but not physically tested)
Diffstat (limited to 'src/mesa/drivers/dri/i830/i830_ioctl.c')
-rw-r--r-- | src/mesa/drivers/dri/i830/i830_ioctl.c | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i830/i830_ioctl.c b/src/mesa/drivers/dri/i830/i830_ioctl.c new file mode 100644 index 00000000000..607b813e536 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_ioctl.c @@ -0,0 +1,841 @@ + +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_ioctl.c,v 1.5 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <[email protected]> + * Graeme Fisher <[email protected]> + * Abraham vd Merwe <[email protected]> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <[email protected]> + */ + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include "glheader.h" +#include "mtypes.h" +#include "macros.h" +#include "dd.h" +#include "swrast/swrast.h" + +#include "mm.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_ioctl.h" +#include "i830_state.h" +#include "i830_debug.h" + +#include "drm.h" + +static drmBufPtr i830_get_buffer_ioctl( i830ContextPtr imesa ) +{ + drmI830DMA dma; + drmBufPtr buf; + int retcode,i = 0; + while (1) { + retcode = drmCommandWriteRead(imesa->driFd, + DRM_I830_GETBUF, + &dma, + sizeof(drmI830DMA)); + if (dma.granted == 1 && retcode == 0) + break; + + if (++i > 1000) { + imesa->sarea->perf_boxes |= I830_BOX_WAIT; + retcode = drmCommandNone(imesa->driFd, DRM_I830_FLUSH); + i = 0; + } + } + + buf = &(imesa->i830Screen->bufs->list[dma.request_idx]); + buf->idx = dma.request_idx; + buf->used = 0; + buf->total = dma.request_size; + buf->address = (drmAddress)dma.virtual; + + return buf; +} + +static void i830ClearDrawQuad(i830ContextPtr imesa, float left, + float right, + float bottom, float top, GLubyte red, + GLubyte green, GLubyte blue, GLubyte alpha) +{ + GLuint *vb = i830AllocDmaLowLocked( imesa, 128 ); + i830Vertex tmp; + int i; + + /* PRIM3D_TRIFAN */ + + /* initial vertex, left bottom */ + tmp.v.x = left; + tmp.v.y = bottom; + tmp.v.z = 1.0; + tmp.v.w = 1.0; + tmp.v.color.red = red; + tmp.v.color.green = green; + tmp.v.color.blue = blue; + tmp.v.color.alpha = alpha; + tmp.v.specular.red = 0; + tmp.v.specular.green = 0; + tmp.v.specular.blue = 0; + tmp.v.specular.alpha = 0; + tmp.v.u0 = 0.0f; + tmp.v.v0 = 0.0f; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; + + /* right bottom */ + vb += 8; + tmp.v.x = right; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; + + /* right top */ + vb += 8; + tmp.v.y = top; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; + + /* left top */ + vb += 8; + tmp.v.x = left; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; +} + +static void i830ClearWithTris(GLcontext *ctx, GLbitfield mask, + GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + i830ScreenPrivate *i830Screen = imesa->i830Screen; + I830SAREAPtr sarea = imesa->sarea; + GLuint old_vertex_prim; + GLuint old_dirty; + int x0, y0, x1, y1; + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "Clearing with triangles\n"); + + old_dirty = imesa->dirty & ~I830_UPLOAD_CLIPRECTS; + /* Discard all the dirty flags except the cliprect one, reset later */ + imesa->dirty &= I830_UPLOAD_CLIPRECTS; + + if(!all) { + x0 = cx; + y0 = cy; + x1 = x0 + cw; + y1 = y0 + ch; + } else { + x0 = 0; + y0 = 0; + x1 = x0 + dPriv->w; + y1 = y0 + dPriv->h; + } + + /* Clip to Screen */ + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > i830Screen->width-1) x1 = i830Screen->width-1; + if (y1 > i830Screen->height-1) y1 = i830Screen->height-1; + + LOCK_HARDWARE(imesa); + memcpy(sarea->ContextState, + imesa->Init_Setup, + sizeof(imesa->Setup) ); + memcpy(sarea->BufferState, + imesa->BufferSetup, + sizeof(imesa->BufferSetup) ); + sarea->StippleState[I830_STPREG_ST1] = 0; + + old_vertex_prim = imesa->hw_primitive; + imesa->hw_primitive = PRIM3D_TRIFAN; + + if(mask & DD_FRONT_LEFT_BIT) { + GLuint tmp = sarea->ContextState[I830_CTXREG_ENABLES_2]; + + sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendStateWordsUsed[0] = 4; + + tmp &= ~(ENABLE_STENCIL_WRITE | ENABLE_DEPTH_WRITE); + tmp |= (DISABLE_STENCIL_WRITE | + DISABLE_DEPTH_WRITE | + (imesa->mask_red << WRITEMASK_RED_SHIFT) | + (imesa->mask_green << WRITEMASK_GREEN_SHIFT) | + (imesa->mask_blue << WRITEMASK_BLUE_SHIFT) | + (imesa->mask_alpha << WRITEMASK_ALPHA_SHIFT)); + sarea->ContextState[I830_CTXREG_ENABLES_2] = tmp; + + if(0) + fprintf(stderr, "fcdq : r_mask(%d) g_mask(%d) b_mask(%d) a_mask(%d)\n", + imesa->mask_red, imesa->mask_green, imesa->mask_blue, + imesa->mask_alpha); + + sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset; + + if(0) + fprintf(stderr, "fcdq : x0(%d) x1(%d) y0(%d) y1(%d)\n" + "r(0x%x) g(0x%x) b(0x%x) a(0x%x)\n", + x0, x1, y0, y1, imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + + i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1, + imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + i830FlushPrimsLocked( imesa ); + } + + if(mask & DD_BACK_LEFT_BIT) { + GLuint tmp = sarea->ContextState[I830_CTXREG_ENABLES_2]; + + sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendStateWordsUsed[0] = 4; + + tmp &= ~(ENABLE_STENCIL_WRITE | ENABLE_DEPTH_WRITE); + tmp |= (DISABLE_STENCIL_WRITE | + DISABLE_DEPTH_WRITE | + (imesa->mask_red << WRITEMASK_RED_SHIFT) | + (imesa->mask_green << WRITEMASK_GREEN_SHIFT) | + (imesa->mask_blue << WRITEMASK_BLUE_SHIFT) | + (imesa->mask_alpha << WRITEMASK_ALPHA_SHIFT)); + + if(0) + fprintf(stderr, "bcdq : r_mask(%d) g_mask(%d) b_mask(%d) a_mask(%d)\n", + imesa->mask_red, imesa->mask_green, imesa->mask_blue, + imesa->mask_alpha); + + sarea->ContextState[I830_CTXREG_ENABLES_2] = tmp; + + sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->backOffset; + + if(0) + fprintf(stderr, "bcdq : x0(%d) x1(%d) y0(%d) y1(%d)\n" + "r(0x%x) g(0x%x) b(0x%x) a(0x%x)\n", + x0, x1, y0, y1, imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + + i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1, + imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + i830FlushPrimsLocked( imesa ); + } + + if(mask & DD_STENCIL_BIT) { + GLuint s_mask = ctx->Stencil.WriteMask[0]; + + sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendStateWordsUsed[0] = 4; + + sarea->ContextState[I830_CTXREG_ENABLES_1] |= (ENABLE_STENCIL_TEST | + ENABLE_DEPTH_TEST); + + sarea->ContextState[I830_CTXREG_ENABLES_2] &= ~(ENABLE_STENCIL_WRITE | + ENABLE_DEPTH_WRITE | + ENABLE_COLOR_WRITE); + + sarea->ContextState[I830_CTXREG_ENABLES_2] |= + (ENABLE_STENCIL_WRITE | + DISABLE_DEPTH_WRITE | + (1 << WRITEMASK_RED_SHIFT) | + (1 << WRITEMASK_GREEN_SHIFT) | + (1 << WRITEMASK_BLUE_SHIFT) | + (1 << WRITEMASK_ALPHA_SHIFT) | + ENABLE_COLOR_WRITE); + + sarea->ContextState[I830_CTXREG_STATE4] &= + ~MODE4_ENABLE_STENCIL_WRITE_MASK; + + sarea->ContextState[I830_CTXREG_STATE4] |= + (ENABLE_STENCIL_WRITE_MASK | + STENCIL_WRITE_MASK(s_mask)); + + sarea->ContextState[I830_CTXREG_STENCILTST] &= + ~(STENCIL_OPS_MASK | + STENCIL_REF_VALUE_MASK | + ENABLE_STENCIL_TEST_FUNC_MASK); + + sarea->ContextState[I830_CTXREG_STENCILTST] |= + (ENABLE_STENCIL_PARMS | + ENABLE_STENCIL_REF_VALUE | + ENABLE_STENCIL_TEST_FUNC | + STENCIL_FAIL_OP(STENCILOP_REPLACE) | + STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) | + STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE) | + STENCIL_REF_VALUE((ctx->Stencil.Clear & 0xff)) | + STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS)); + + if(0) + fprintf(stderr, "Enables_1 (0x%x) Enables_2 (0x%x) StenTst (0x%x)\n" + "Modes_4 (0x%x)\n", + sarea->ContextState[I830_CTXREG_ENABLES_1], + sarea->ContextState[I830_CTXREG_ENABLES_2], + sarea->ContextState[I830_CTXREG_STENCILTST], + sarea->ContextState[I830_CTXREG_STATE4]); + + sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset; + + i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1, + 255, 255, 255, 255); + i830FlushPrimsLocked( imesa ); + } + + UNLOCK_HARDWARE(imesa); + imesa->dirty = old_dirty; + imesa->dirty |= (I830_UPLOAD_CTX | + I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + imesa->hw_primitive = old_vertex_prim; +} + +static void i830Clear(GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx1, GLint cy1, GLint cw, GLint ch) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); + drmI830Clear clear; + GLbitfield tri_mask = 0; + int i; + GLint cx, cy; + + /* flip top to bottom */ + cy = dPriv->h-cy1-ch; + cx = cx1 + imesa->drawX; + cy += imesa->drawY; + + if(0) fprintf(stderr, "\nClearColor : 0x%08x\n", imesa->ClearColor); + + clear.flags = 0; + clear.clear_color = imesa->ClearColor; + clear.clear_depth = 0; + clear.clear_colormask = 0; + clear.clear_depthmask = 0; + + I830_FIREVERTICES( imesa ); + + if (mask & DD_FRONT_LEFT_BIT) { + if(colorMask == ~0) { + clear.flags |= I830_FRONT; + } else { + tri_mask |= DD_FRONT_LEFT_BIT; + } + mask &= ~DD_FRONT_LEFT_BIT; + } + + if (mask & DD_BACK_LEFT_BIT) { + if(colorMask == ~0) { + clear.flags |= I830_BACK; + } else { + tri_mask |= DD_BACK_LEFT_BIT; + } + mask &= ~DD_BACK_LEFT_BIT; + } + + if (mask & DD_DEPTH_BIT) { + clear.flags |= I830_DEPTH; + clear.clear_depthmask = imesa->depth_clear_mask; + clear.clear_depth = (GLuint)(ctx->Depth.Clear * imesa->ClearDepth); + mask &= ~DD_DEPTH_BIT; + } + + if((mask & DD_STENCIL_BIT) && imesa->hw_stencil) { + if (ctx->Stencil.WriteMask[0] != 0xff) { + tri_mask |= DD_STENCIL_BIT; + } else { + clear.flags |= I830_DEPTH; + clear.clear_depthmask |= imesa->stencil_clear_mask; + clear.clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; + } + mask &= ~DD_STENCIL_BIT; + } + + /* First check for clears that need to happen with triangles */ + if(tri_mask) { + i830ClearWithTris(ctx, tri_mask, all, cx, cy, cw, ch); + } + + if (clear.flags) { + LOCK_HARDWARE( imesa ); + + for (i = 0 ; i < imesa->numClipRects ; ) + { + int nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, imesa->numClipRects); + XF86DRIClipRectRec *box = imesa->pClipRects; + drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes; + int n = 0; + + if (!all) { + for ( ; i < nr ; i++) { + GLint x = box[i].x1; + GLint y = box[i].y1; + GLint w = box[i].x2 - x; + GLint h = box[i].y2 - y; + + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + if (w <= 0) continue; + if (h <= 0) continue; + + b->x1 = x; + b->y1 = y; + b->x2 = x + w; + b->y2 = y + h; + b++; + n++; + } + } else { + for ( ; i < nr ; i++) { + *b++ = *(drm_clip_rect_t *)&box[i]; + n++; + } + } + + imesa->sarea->nbox = n; + drmCommandWrite(imesa->driFd, DRM_I830_CLEAR, + &clear, sizeof(drmI830Clear)); + } + + UNLOCK_HARDWARE( imesa ); + imesa->upload_cliprects = GL_TRUE; + } + + if (mask) + _swrast_Clear( ctx, mask, all, cx1, cy1, cw, ch ); +} + + + +/* + * Copy the back buffer to the front buffer. + */ +void i830CopyBuffer( const __DRIdrawablePrivate *dPriv ) +{ + i830ContextPtr imesa; + XF86DRIClipRectPtr pbox; + int nbox, i, tmp; + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + imesa = (i830ContextPtr) dPriv->driContextPriv->driverPrivate; + + I830_FIREVERTICES( imesa ); + LOCK_HARDWARE( imesa ); + + imesa->sarea->perf_boxes |= imesa->perf_boxes; + imesa->perf_boxes = 0; + + pbox = dPriv->pClipRects; + nbox = dPriv->numClipRects; + + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)imesa->sarea->boxes; + + imesa->sarea->nbox = nr - i; + + for ( ; i < nr ; i++) + *b++ = pbox[i]; + drmCommandNone(imesa->driFd, DRM_I830_SWAP); + } + + tmp = GET_ENQUEUE_AGE(imesa); + UNLOCK_HARDWARE( imesa ); + + /* multiarb will suck the life out of the server without this throttle: + */ + if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) { + i830WaitAge(imesa, imesa->lastSwap); + } + + imesa->lastSwap = tmp; + imesa->upload_cliprects = GL_TRUE; +} + +/* Flip the front & back buffes + */ +void i830PageFlip( const __DRIdrawablePrivate *dPriv ) +{ +#if 0 + i830ContextPtr imesa; + int tmp, ret; + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + imesa = (i830ContextPtr) dPriv->driContextPriv->driverPrivate; + + I830_FIREVERTICES( imesa ); + LOCK_HARDWARE( imesa ); + + imesa->sarea->perf_boxes |= imesa->perf_boxes; + imesa->perf_boxes = 0; + + if (dPriv->pClipRects) { + *(XF86DRIClipRectRec *)imesa->sarea->boxes = dPriv->pClipRects[0]; + imesa->sarea->nbox = 1; + } + + ret = drmCommandNone(imesa->driFd, DRM_I830_FLIP); + if (ret) { + fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); + UNLOCK_HARDWARE( imesa ); + exit(1); + } + + tmp = GET_ENQUEUE_AGE(imesa); + UNLOCK_HARDWARE( imesa ); + + /* multiarb will suck the life out of the server without this throttle: + */ + if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) { + i830WaitAge(imesa, imesa->lastSwap); + } + + i830SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer ); + imesa->upload_cliprects = GL_TRUE; + imesa->lastSwap = tmp; +#endif +} + +/* This waits for *everybody* to finish rendering -- overkill. + */ +void i830DmaFinish( i830ContextPtr imesa ) +{ + I830_FIREVERTICES( imesa ); + LOCK_HARDWARE_QUIESCENT( imesa ); + UNLOCK_HARDWARE( imesa ); +} + +void i830RegetLockQuiescent( i830ContextPtr imesa ) +{ + drmUnlock(imesa->driFd, imesa->hHWContext); + i830GetLock( imesa, DRM_LOCK_QUIESCENT ); +} + +void i830WaitAgeLocked( i830ContextPtr imesa, int age ) +{ + int i = 0; + while (++i < 5000) { + drmCommandNone(imesa->driFd, DRM_I830_GETAGE); + if (GET_DISPATCH_AGE(imesa) >= age) return; + imesa->sarea->perf_boxes |= I830_BOX_WAIT; + UNLOCK_HARDWARE( imesa ); + if (I830_DEBUG & DEBUG_SLEEP) fprintf(stderr, "."); + usleep(1); + LOCK_HARDWARE( imesa ); + } + /* If that didn't work, just do a flush: + */ + drmCommandNone(imesa->driFd, DRM_I830_FLUSH); +} + +void i830WaitAge( i830ContextPtr imesa, int age ) +{ + int i = 0; + if (GET_DISPATCH_AGE(imesa) >= age) return; + + while (1) { + drmCommandNone(imesa->driFd, DRM_I830_GETAGE); + if (GET_DISPATCH_AGE(imesa) >= age) return; + imesa->perf_boxes |= I830_BOX_WAIT; + + if (imesa->do_irqs) { + drmI830IrqEmit ie; + drmI830IrqWait iw; + int ret; + + ie.irq_seq = &iw.irq_seq; + + LOCK_HARDWARE( imesa ); + ret = drmCommandWriteRead( imesa->driFd, DRM_I830_IRQ_EMIT, &ie, sizeof(ie) ); + if ( ret ) { + fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret ); + exit(1); + } + UNLOCK_HARDWARE(imesa); + + ret = drmCommandWrite( imesa->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) ); + if ( ret ) { + fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret ); + exit(1); + } + } else { + if (++i > 5000) usleep(1); + } + } +} + +static void age_imesa( i830ContextPtr imesa, int age ) +{ + if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->base.timestamp = age; + if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->base.timestamp = age; +} + +void i830FlushPrimsLocked( i830ContextPtr imesa ) +{ + XF86DRIClipRectPtr pbox = (XF86DRIClipRectPtr)imesa->pClipRects; + int nbox = imesa->numClipRects; + drmBufPtr buffer = imesa->vertex_buffer; + I830SAREAPtr sarea = imesa->sarea; + drmI830Vertex vertex; + int i, nr; + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s dirty: %08x\n", __FUNCTION__, imesa->dirty); + + + vertex.idx = buffer->idx; + vertex.used = imesa->vertex_low; + vertex.discard = 0; + sarea->vertex_prim = imesa->hw_primitive; + + /* Reset imesa vars: + */ + imesa->vertex_buffer = 0; + imesa->vertex_addr = 0; + imesa->vertex_low = 0; + imesa->vertex_high = 0; + imesa->vertex_last_prim = 0; + + if (imesa->dirty) { + if (I830_DEBUG & DEBUG_SANITY) + i830EmitHwStateLockedDebug(imesa); + else + i830EmitHwStateLocked(imesa); + } + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr,"%s: Vertex idx %d used %d discard %d\n", + __FUNCTION__, vertex.idx, vertex.used, vertex.discard); + + if (!nbox) { + vertex.used = 0; + vertex.discard = 1; + if (drmCommandWrite (imesa->driFd, DRM_I830_VERTEX, + &vertex, sizeof(drmI830Vertex))) { + fprintf(stderr, "DRM_I830_VERTEX: %d\n", -errno); + UNLOCK_HARDWARE(imesa); + exit(1); + } + return; + } + + for (i = 0 ; i < nbox ; i = nr ) { + XF86DRIClipRectPtr b = sarea->boxes; + int j; + + nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, nbox); + sarea->nbox = nr - i; + + for ( j = i ; j < nr ; j++) { + b[j-i] = pbox[j]; + } + + /* Finished with the buffer? + */ + if (nr == nbox) + vertex.discard = 1; + + /* Do a bunch of sanity checks on the vertices sent to the hardware */ + if (I830_DEBUG & DEBUG_SANITY) { + i830VertexSanity(imesa, vertex); + + for ( j = 0 ; j < sarea->nbox ; j++) { + fprintf(stderr, "box %d/%d %d,%d %d,%d\n", + j, sarea->nbox, b[j].x1, b[j].y1, b[j].x2, b[j].y2); + } + } + + drmCommandWrite (imesa->driFd, DRM_I830_VERTEX, + &vertex, sizeof(drmI830Vertex)); + age_imesa(imesa, imesa->sarea->last_enqueue); + } + + imesa->dirty = 0; + imesa->upload_cliprects = GL_FALSE; +} + +void i830FlushPrimsGetBufferLocked( i830ContextPtr imesa ) +{ + if (imesa->vertex_buffer) + i830FlushPrimsLocked( imesa ); + imesa->vertex_buffer = i830_get_buffer_ioctl( imesa ); + imesa->vertex_addr = (char *)imesa->vertex_buffer->address; + + /* leave room for instruction header & footer: + */ + imesa->vertex_high = imesa->vertex_buffer->total - 4; + imesa->vertex_low = 4; + imesa->vertex_last_prim = imesa->vertex_low; +} + +void i830FlushPrimsGetBuffer( i830ContextPtr imesa ) +{ + LOCK_HARDWARE(imesa); + i830FlushPrimsGetBufferLocked( imesa ); + UNLOCK_HARDWARE(imesa); +} + + +void i830FlushPrims( i830ContextPtr imesa ) +{ + if (imesa->vertex_buffer) { + LOCK_HARDWARE( imesa ); + i830FlushPrimsLocked( imesa ); + UNLOCK_HARDWARE( imesa ); + } +} + +int i830_check_copy(int fd) +{ + return drmCommandNone(fd, DRM_I830_DOCOPY); +} + +static void i830DDFlush( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + I830_FIREVERTICES( imesa ); +} + +static void i830DDFinish( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + i830DmaFinish( imesa ); +} + +void i830DDInitIoctlFuncs( GLcontext *ctx ) +{ + ctx->Driver.Flush = i830DDFlush; + ctx->Driver.Clear = i830Clear; + ctx->Driver.Finish = i830DDFinish; +} + |