| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934 |
- /* $XFree86$ */
- /*
- Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
- The Weather Channel (TM) funded Tungsten Graphics to develop the
- initial release of the Radeon 8500 driver under the XFree86 license.
- This notice must be preserved.
-
- 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 the rights to use, copy, modify, merge, publish,
- distribute, sublicense, 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 NONINFRINGEMENT.
- IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS 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.
- */
-
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
- #include "glheader.h"
- #include "imports.h"
- #include "macros.h"
- #include "context.h"
- #include "swrast/swrast.h"
-
- #include "r200_context.h"
- #include "r200_state.h"
- #include "r200_ioctl.h"
- #include "r200_tcl.h"
- #include "r200_sanity.h"
- #include "radeon_reg.h"
-
- #include <unistd.h> /* for usleep() */
- #include <errno.h>
-
-
- #define R200_TIMEOUT 512
- #define R200_IDLE_RETRY 16
-
-
- static void do_usleep( int nr, const char *caller )
- {
- //if (1) fprintf(stderr, "usleep %d in %s\n", nr, caller );
- if (1) usleep( nr );
- }
-
- static void r200WaitForIdle( r200ContextPtr rmesa );
-
-
- int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller )
- {
- int ret, i;
- drmRadeonCmdBuffer cmd;
-
- if (R200_DEBUG & DEBUG_IOCTL) {
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (0 & R200_DEBUG & DEBUG_VERBOSE)
- for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
- fprintf(stderr, "%d: %x\n", i/4,
- *(int *)(&rmesa->store.cmd_buf[i]));
- }
-
- if (R200_DEBUG & DEBUG_DMA)
- fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
- rmesa->dma.nr_released_bufs);
-
-
- if (R200_DEBUG & DEBUG_SANITY) {
- if (rmesa->state.scissor.enabled)
- ret = r200SanityCmdBuffer( rmesa,
- rmesa->state.scissor.numClipRects,
- rmesa->state.scissor.pClipRects);
- else
- ret = r200SanityCmdBuffer( rmesa,
- rmesa->numClipRects,
- rmesa->pClipRects);
- if (ret) {
- fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
- goto out;
- }
- }
-
-
- if (R200_DEBUG & DEBUG_MEMORY) {
- if (!r200ValidateTexObjs( rmesa )) {
- fprintf(stderr, " -- tex memory is inconsistent - expect mangled textures\n");
- }
- }
-
-
- cmd.bufsz = rmesa->store.cmd_used;
- cmd.buf = rmesa->store.cmd_buf;
-
- if (rmesa->state.scissor.enabled) {
- cmd.nbox = rmesa->state.scissor.numClipRects;
- cmd.boxes = (drmClipRect *)rmesa->state.scissor.pClipRects;
- } else {
- cmd.nbox = rmesa->numClipRects;
- cmd.boxes = (drmClipRect *)rmesa->pClipRects;
- }
-
- ret = drmCommandWrite( rmesa->dri.fd,
- DRM_RADEON_CMDBUF,
- &cmd, sizeof(cmd) );
-
- if (ret)
- fprintf(stderr, "drmCommandWrite: %d\n", ret);
-
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__);
- r200WaitForIdleLocked( rmesa );
- }
-
-
- out:
- rmesa->store.primnr = 0;
- rmesa->store.statenr = 0;
- rmesa->store.cmd_used = 0;
- rmesa->dma.nr_released_bufs = 0;
- /* rmesa->lost_context = 0; */
- rmesa->lost_context = 1;
- return ret;
- }
-
-
- /* Note: does not emit any commands to avoid recursion on
- * r200AllocCmdBuf.
- */
- void r200FlushCmdBuf( r200ContextPtr rmesa, const char *caller )
- {
- int ret;
-
- LOCK_HARDWARE( rmesa );
-
- ret = r200FlushCmdBufLocked( rmesa, caller );
-
- UNLOCK_HARDWARE( rmesa );
-
- if (ret) {
- fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret);
- exit(ret);
- }
- }
-
-
- /* =============================================================
- * Hardware vertex buffer handling
- */
-
-
- void r200RefillCurrentDmaRegion( r200ContextPtr rmesa )
- {
- struct r200_dma_buffer *dmabuf;
- int fd = rmesa->dri.fd;
- int index = 0;
- int size = 0;
- drmDMAReq dma;
- int ret;
-
- if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->dma.flush) {
- rmesa->dma.flush( rmesa );
- }
-
- if (rmesa->dma.current.buf)
- r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
-
- if (rmesa->dma.nr_released_bufs > 4)
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
-
- dma.context = rmesa->dri.hwContext;
- dma.send_count = 0;
- dma.send_list = NULL;
- dma.send_sizes = NULL;
- dma.flags = 0;
- dma.request_count = 1;
- dma.request_size = RADEON_BUFFER_SIZE;
- dma.request_list = &index;
- dma.request_sizes = &size;
- dma.granted_count = 0;
-
- LOCK_HARDWARE(rmesa); /* no need to validate */
-
- while (1) {
- ret = drmDMA( fd, &dma );
- if (ret == 0)
- break;
-
- if (rmesa->dma.nr_released_bufs) {
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
- }
-
- if (rmesa->do_usleeps) {
- UNLOCK_HARDWARE( rmesa );
- do_usleep(1, __FUNCTION__);
- LOCK_HARDWARE( rmesa );
- }
- }
-
- UNLOCK_HARDWARE(rmesa);
-
- if (R200_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Allocated buffer %d\n", index);
-
- dmabuf = CALLOC_STRUCT( r200_dma_buffer );
- dmabuf->buf = &rmesa->r200Screen->buffers->list[index];
- dmabuf->refcount = 1;
-
- rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = dmabuf->buf->address;
- rmesa->dma.current.end = dmabuf->buf->total;
- rmesa->dma.current.start = 0;
- rmesa->dma.current.ptr = 0;
- }
-
- void r200ReleaseDmaRegion( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- const char *caller )
- {
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (--region->buf->refcount == 0) {
- drmRadeonCmdHeader *cmd;
-
- if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
- fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
- region->buf->buf->idx);
-
- cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, sizeof(*cmd),
- __FUNCTION__ );
- cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
- cmd->dma.buf_idx = region->buf->buf->idx;
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
- }
-
- region->buf = 0;
- region->start = 0;
- }
-
- /* Allocates a region from rmesa->dma.current. If there isn't enough
- * space in current, grab a new buffer (and discard what was left of current)
- */
- void r200AllocDmaRegion( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- int bytes,
- int alignment )
- {
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (region->buf)
- r200ReleaseDmaRegion( rmesa, region, __FUNCTION__ );
-
- alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
- r200RefillCurrentDmaRegion( rmesa );
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
-
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
- }
-
- void r200AllocDmaRegionVerts( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- int numverts,
- int vertsize,
- int alignment )
- {
- r200AllocDmaRegion( rmesa, region, vertsize * numverts, alignment );
- }
-
- /* ================================================================
- * SwapBuffers with client-side throttling
- */
-
- static GLuint r200GetLastFrame(r200ContextPtr rmesa)
- {
- drmRadeonGetParam gp;
- int ret;
- GLuint frame;
-
- gp.param = RADEON_PARAM_LAST_FRAME;
- gp.value = (int *)&frame;
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp) );
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-
- return frame;
- }
-
- static void r200EmitIrqLocked( r200ContextPtr rmesa )
- {
- drmRadeonIrqEmit ie;
- int ret;
-
- ie.irq_seq = &rmesa->iw.irq_seq;
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT,
- &ie, sizeof(ie) );
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
- exit(1);
- }
- }
-
-
- static void r200WaitIrq( r200ContextPtr rmesa )
- {
- int ret;
-
- do {
- ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
- &rmesa->iw, sizeof(rmesa->iw) );
- } while (ret && (errno == EINTR || errno == EAGAIN));
-
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
- exit(1);
- }
- }
-
-
- static void r200WaitForFrameCompletion( r200ContextPtr rmesa )
- {
- RADEONSAREAPrivPtr sarea = rmesa->sarea;
-
- if (rmesa->do_irqs) {
- if (r200GetLastFrame(rmesa) < sarea->last_frame) {
- if (!rmesa->irqsEmitted) {
- while (r200GetLastFrame (rmesa) < sarea->last_frame)
- ;
- }
- else {
- UNLOCK_HARDWARE( rmesa );
- r200WaitIrq( rmesa );
- LOCK_HARDWARE( rmesa );
- }
- rmesa->irqsEmitted = 10;
- }
-
- if (rmesa->irqsEmitted) {
- r200EmitIrqLocked( rmesa );
- rmesa->irqsEmitted--;
- }
- }
- else {
- while (r200GetLastFrame (rmesa) < sarea->last_frame) {
- UNLOCK_HARDWARE( rmesa );
- if (rmesa->do_usleeps)
- do_usleep(1, __FUNCTION__);
- LOCK_HARDWARE( rmesa );
- }
- }
- }
-
-
-
- /* Copy the back color buffer to the front color buffer.
- */
- void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
- {
- r200ContextPtr rmesa;
- GLint nbox, i, ret;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
-
- if ( R200_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx );
- }
-
- R200_FIREVERTICES( rmesa );
-
- LOCK_HARDWARE( rmesa );
-
-
- /* Throttle the frame rate -- only allow one pending swap buffers
- * request at a time.
- */
- r200WaitForFrameCompletion( rmesa );
-
- r200WaitForVBlank( rmesa );
-
- nbox = rmesa->dri.drawable->numClipRects; /* must be in locked region */
-
- for ( i = 0 ; i < nbox ; ) {
- GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
- XF86DRIClipRectPtr box = rmesa->dri.drawable->pClipRects;
- XF86DRIClipRectPtr b = rmesa->sarea->boxes;
- GLint n = 0;
-
- for ( ; i < nr ; i++ ) {
- *b++ = box[i];
- n++;
- }
- rmesa->sarea->nbox = n;
-
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
-
- if ( ret ) {
- fprintf( stderr, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret );
- UNLOCK_HARDWARE( rmesa );
- exit( 1 );
- }
- }
-
- UNLOCK_HARDWARE( rmesa );
- rmesa->lost_context = 1;
- }
-
- void r200PageFlip( const __DRIdrawablePrivate *dPriv )
- {
- r200ContextPtr rmesa;
- GLint ret;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
-
- if ( R200_DEBUG & DEBUG_IOCTL ) {
- fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
- rmesa->sarea->pfCurrentPage);
- }
-
- R200_FIREVERTICES( rmesa );
- LOCK_HARDWARE( rmesa );
-
- if (!rmesa->dri.drawable->numClipRects) {
- UNLOCK_HARDWARE( rmesa );
- usleep( 10000 ); /* throttle invisible client 10ms */
- return;
- }
-
- /* Need to do this for the perf box placement:
- */
- {
- XF86DRIClipRectPtr box = rmesa->dri.drawable->pClipRects;
- XF86DRIClipRectPtr b = rmesa->sarea->boxes;
- b[0] = box[0];
- rmesa->sarea->nbox = 1;
- }
-
- /* Throttle the frame rate -- only allow a few pending swap buffers
- * request at a time.
- */
- r200WaitForFrameCompletion( rmesa );
-
- r200WaitForVBlank( rmesa );
-
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP );
-
- UNLOCK_HARDWARE( rmesa );
-
- if ( ret ) {
- fprintf( stderr, "DRM_R200_FLIP: return = %d\n", ret );
- exit( 1 );
- }
-
- if ( rmesa->sarea->pfCurrentPage == 1 ) {
- rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
- rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
- } else {
- rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
- rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
- }
-
- R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
- }
-
-
- /* ================================================================
- * Buffer clear
- */
- static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
- GLint cx, GLint cy, GLint cw, GLint ch )
- {
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
- GLuint flags = 0;
- GLuint color_mask = 0;
- GLint ret, i;
-
- if ( R200_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
- __FUNCTION__, all, cx, cy, cw, ch );
- }
-
- {
- LOCK_HARDWARE( rmesa );
- UNLOCK_HARDWARE( rmesa );
- if ( dPriv->numClipRects == 0 )
- return;
- }
-
- r200EmitState( rmesa );
-
- /* Need to cope with lostcontext here as kernel relies on
- * some residual state:
- */
- R200_FIREVERTICES( rmesa );
-
- if ( mask & DD_FRONT_LEFT_BIT ) {
- flags |= RADEON_FRONT;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~DD_FRONT_LEFT_BIT;
- }
-
- if ( mask & DD_BACK_LEFT_BIT ) {
- flags |= RADEON_BACK;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~DD_BACK_LEFT_BIT;
- }
-
- if ( mask & DD_DEPTH_BIT ) {
- if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */
- mask &= ~DD_DEPTH_BIT;
- }
-
- if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) {
- flags |= RADEON_STENCIL;
- mask &= ~DD_STENCIL_BIT;
- }
-
- if ( mask )
- _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
-
- if ( !flags )
- return;
-
- /* Flip top to bottom */
- cx += dPriv->x;
- cy = dPriv->y + dPriv->h - cy - ch;
-
- LOCK_HARDWARE( rmesa );
-
- /* Throttle the number of clear ioctls we do.
- */
- while ( 1 ) {
- drmRadeonGetParam gp;
- int ret;
- int clear;
-
- gp.param = RADEON_PARAM_LAST_CLEAR;
- gp.value = (int *)&clear;
- ret = drmCommandWriteRead( rmesa->dri.fd,
- DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
-
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-
- /* Clear throttling needs more thought.
- */
- if ( rmesa->sarea->last_clear - clear <= 25 ) {
- break;
- }
-
- if (rmesa->do_usleeps) {
- UNLOCK_HARDWARE( rmesa );
- do_usleep(1, __FUNCTION__);
- LOCK_HARDWARE( rmesa );
- }
- }
-
-
- for ( i = 0 ; i < dPriv->numClipRects ; ) {
- GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
- XF86DRIClipRectPtr box = dPriv->pClipRects;
- XF86DRIClipRectPtr b = rmesa->sarea->boxes;
- drmRadeonClearType clear;
- drmRadeonClearRect depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
- GLint 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++ = box[i];
- n++;
- }
- }
-
- rmesa->sarea->nbox = n;
-
- clear.flags = flags;
- clear.clear_color = rmesa->state.color.clear;
- clear.clear_depth = 0; /* not used */
- clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- clear.depth_mask = rmesa->state.stencil.clear;
- clear.depth_boxes = depth_boxes;
-
- n--;
- b = rmesa->sarea->boxes;
- for ( ; n >= 0 ; n-- ) {
- depth_boxes[n].f[RADEON_CLEAR_X1] = (float)b[n].x1;
- depth_boxes[n].f[RADEON_CLEAR_Y1] = (float)b[n].y1;
- depth_boxes[n].f[RADEON_CLEAR_X2] = (float)b[n].x2;
- depth_boxes[n].f[RADEON_CLEAR_Y2] = (float)b[n].y2;
- depth_boxes[n].f[RADEON_CLEAR_DEPTH] = ctx->Depth.Clear;
- }
-
- ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
- &clear, sizeof(drmRadeonClearType));
-
-
- if ( ret ) {
- UNLOCK_HARDWARE( rmesa );
- fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
- exit( 1 );
- }
- }
-
- UNLOCK_HARDWARE( rmesa );
- rmesa->lost_context = 1;
- }
-
-
- void r200WaitForIdleLocked( r200ContextPtr rmesa )
- {
- int ret;
- int i = 0;
-
- do {
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_CP_IDLE);
- if (ret)
- do_usleep( 1, __FUNCTION__ );
- } while (ret && ++i < 100);
-
- if ( ret < 0 ) {
- UNLOCK_HARDWARE( rmesa );
- fprintf( stderr, "Error: R200 timed out... exiting\n" );
- exit( -1 );
- }
- }
-
- static void r200WaitForIdle( r200ContextPtr rmesa )
- {
- LOCK_HARDWARE(rmesa);
- r200WaitForIdleLocked( rmesa );
- UNLOCK_HARDWARE(rmesa);
- }
-
-
- void r200WaitForVBlank( r200ContextPtr rmesa )
- {
- #if 0
- drmVBlank vbl;
- int ret;
-
- if ( !rmesa->r200Screen->irq )
- return;
-
- if ( getenv("LIBGL_SYNC_REFRESH") ) {
- /* Wait for until the next vertical blank */
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.sequence = 1;
- } else if ( getenv("LIBGL_THROTTLE_REFRESH") ) {
- /* Wait for at least one vertical blank since the last call */
- vbl.request.type = DRM_VBLANK_ABSOLUTE;
- vbl.request.sequence = rmesa->vbl_seq + 1;
- } else {
- return;
- }
-
- UNLOCK_HARDWARE( rmesa );
-
- if ((ret = drmWaitVBlank( rmesa->dri.fd, &vbl ))) {
- fprintf(stderr, "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
- " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
- " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
- exit(1);
- } else if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s: drmWaitVBlank returned %d\n", __FUNCTION__, ret);
-
- rmesa->vbl_seq = vbl.reply.sequence;
-
- LOCK_HARDWARE( rmesa );
- #endif
- }
-
- void r200Flush( GLcontext *ctx )
- {
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
-
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (!is_empty_list(&rmesa->hw.dirty))
- r200EmitState( rmesa );
-
- if (rmesa->store.cmd_used)
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
- }
-
- /* Make sure all commands have been sent to the hardware and have
- * completed processing.
- */
- void r200Finish( GLcontext *ctx )
- {
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- r200Flush( ctx );
-
- if (rmesa->do_irqs) {
- LOCK_HARDWARE( rmesa );
- r200EmitIrqLocked( rmesa );
- UNLOCK_HARDWARE( rmesa );
- r200WaitIrq( rmesa );
- }
- else
- r200WaitForIdle( rmesa );
- }
-
-
- /* This version of AllocateMemoryNV allocates only agp memory, and
- * only does so after the point at which the driver has been
- * initialized.
- *
- * Theoretically a valid context isn't required. However, in this
- * implementation, it is, as I'm using the hardware lock to protect
- * the kernel data structures, and the current context to get the
- * device fd.
- */
- void *r200AllocateMemoryNV(GLsizei size, GLfloat readfreq,
- GLfloat writefreq, GLfloat priority)
- {
- GET_CURRENT_CONTEXT(ctx);
- r200ContextPtr rmesa;
- int region_offset;
- drmRadeonMemAlloc alloc;
- int ret;
-
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
- writefreq, priority);
-
- if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || rmesa->r200Screen->IsPCI )
- return NULL;
-
- if (getenv("R200_NO_ALLOC"))
- return NULL;
-
- if (rmesa->dri.drmMinor < 6)
- return NULL;
-
- alloc.region = RADEON_MEM_REGION_AGP;
- alloc.alignment = 0;
- alloc.size = size;
- alloc.region_offset = ®ion_offset;
-
- ret = drmCommandWriteRead( rmesa->r200Screen->driScreen->fd,
- DRM_RADEON_ALLOC,
- &alloc, sizeof(alloc));
-
- if (ret) {
- fprintf(stderr, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__, ret);
- return NULL;
- }
-
- {
- char *region_start = (char *)rmesa->r200Screen->agpTextures.map;
- return (void *)(region_start + region_offset);
- }
- }
-
-
- /* Called via glXFreeMemoryNV() */
- void r200FreeMemoryNV(GLvoid *pointer)
- {
- GET_CURRENT_CONTEXT(ctx);
- r200ContextPtr rmesa;
- int region_offset;
- drmRadeonMemFree memfree;
- int ret;
-
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
-
- if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || rmesa->r200Screen->IsPCI ) {
- fprintf(stderr, "%s: no context\n", __FUNCTION__);
- return;
- }
-
- if (rmesa->dri.drmMinor < 6)
- return;
-
- region_offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map;
-
- if (region_offset < 0 ||
- region_offset > rmesa->r200Screen->agpTextures.size) {
- fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
- rmesa->r200Screen->agpTextures.size);
- return;
- }
-
- memfree.region = RADEON_MEM_REGION_AGP;
- memfree.region_offset = region_offset;
-
- ret = drmCommandWrite( rmesa->r200Screen->driScreen->fd,
- DRM_RADEON_FREE,
- &memfree, sizeof(memfree));
-
- if (ret)
- fprintf(stderr, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__, ret);
- }
-
- /* Called via glXGetAGPOffsetMESA() */
- GLuint r200GetAGPOffset(const GLvoid *pointer)
- {
- GET_CURRENT_CONTEXT(ctx);
- r200ContextPtr rmesa;
- GLuint card_offset;
-
- if (!ctx || !(rmesa = R200_CONTEXT(ctx)) ) {
- fprintf(stderr, "%s: no context\n", __FUNCTION__);
- return ~0;
- }
-
- if (!r200IsAgpMemory( rmesa, pointer, 0 ))
- return ~0;
-
- if (rmesa->dri.drmMinor < 6)
- return ~0;
-
- card_offset = r200AgpOffsetFromVirtual( rmesa, pointer );
-
- return card_offset - rmesa->r200Screen->agp_base;
- }
-
-
- GLboolean r200IsAgpMemory( r200ContextPtr rmesa, const GLvoid *pointer,
- GLint size )
- {
- int offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map;
- int valid = (size >= 0 &&
- offset >= 0 &&
- offset + size < rmesa->r200Screen->agpTextures.size);
-
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "r200IsAgpMemory( %p ) : %d\n", pointer, valid );
-
- return valid;
- }
-
-
- GLuint r200AgpOffsetFromVirtual( r200ContextPtr rmesa, const GLvoid *pointer )
- {
- int offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map;
-
- if (offset < 0 || offset > rmesa->r200Screen->agpTextures.size)
- return ~0;
- else
- return rmesa->r200Screen->agp_texture_offset + offset;
- }
-
-
-
- void r200InitIoctlFuncs( GLcontext *ctx )
- {
- ctx->Driver.Clear = r200Clear;
- ctx->Driver.Finish = r200Finish;
- ctx->Driver.Flush = r200Flush;
- }
|