static void r200WaitForFrameCompletion( r200ContextPtr rmesa ) { drm_radeon_sarea_t *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 ); LOCK_HARDWARE( rmesa ); } } }
static void mgaWaitForFrameCompletion( mgaContextPtr mmesa ) { if ( mgaWaitFence( mmesa, mmesa->last_frame_fence, NULL ) == ENOSYS ) { unsigned wait = 0; GLuint last_frame; GLuint last_wrap; LOCK_HARDWARE( mmesa ); last_frame = mmesa->sarea->last_frame.head; last_wrap = mmesa->sarea->last_frame.wrap; /* The DMA routines in the kernel track a couple values in the SAREA * that we use here. The number of times that the primary DMA buffer * has "wrapped" around is tracked in last_wrap. In addition, the * wrap count and the buffer position at the end of the last frame are * stored in last_frame.wrap and last_frame.head. * * By comparing the wrap counts and the current DMA pointer value * (read directly from the hardware) to last_frame.head, we can * determine when the graphics processor has processed all of the * commands for the last frame. * * In this case "last frame" means the frame of the *previous* swap- * buffers call. This is done to prevent queuing a second buffer swap * before the previous swap is executed. */ while ( 1 ) { if ( last_wrap < mmesa->sarea->last_wrap || ( last_wrap == mmesa->sarea->last_wrap && last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset) ) ) { break; } if ( 0 ) { wait++; fprintf( stderr, " last: head=0x%06x wrap=%d\n", last_frame, last_wrap ); fprintf( stderr, " head: head=0x%06lx wrap=%d\n", (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset), mmesa->sarea->last_wrap ); } UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); UNLOCK_HARDWARE( mmesa ); DO_USLEEP( 1 ); LOCK_HARDWARE( mmesa ); } if ( wait ) fprintf( stderr, "\n" ); UNLOCK_HARDWARE( mmesa ); } }
void r200WaitForIdleLocked( r200ContextPtr rmesa ) { int ret; int i = 0; do { ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_CP_IDLE); if (ret) DO_USLEEP( 1 ); } while (ret && ++i < 100); if ( ret < 0 ) { UNLOCK_HARDWARE( rmesa ); fprintf( stderr, "Error: R200 timed out... exiting\n" ); exit( -1 ); } }
static void radeonKernelClear(GLcontext *ctx, GLuint flags) { r100ContextPtr rmesa = R100_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon); drm_radeon_sarea_t *sarea = rmesa->radeon.sarea; uint32_t clear; GLint ret, i; GLint cx, cy, cw, ch; radeonEmitState(&rmesa->radeon); LOCK_HARDWARE( &rmesa->radeon ); /* compute region after locking: */ cx = ctx->DrawBuffer->_Xmin; cy = ctx->DrawBuffer->_Ymin; cw = ctx->DrawBuffer->_Xmax - cx; ch = ctx->DrawBuffer->_Ymax - cy; /* Flip top to bottom */ cx += dPriv->x; cy = dPriv->y + dPriv->h - cy - ch; /* Throttle the number of clear ioctls we do. */ while ( 1 ) { int ret; drm_radeon_getparam_t gp; gp.param = RADEON_PARAM_LAST_CLEAR; gp.value = (int *)&clear; ret = drmCommandWriteRead( rmesa->radeon.dri.fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); if ( ret ) { fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret ); exit(1); } if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) { break; } if ( rmesa->radeon.do_usleeps ) { UNLOCK_HARDWARE( &rmesa->radeon ); DO_USLEEP( 1 ); LOCK_HARDWARE( &rmesa->radeon ); } } /* Send current state to the hardware */ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ ); for ( i = 0 ; i < dPriv->numClipRects ; ) { GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects ); drm_clip_rect_t *box = dPriv->pClipRects; drm_clip_rect_t *b = rmesa->radeon.sarea->boxes; drm_radeon_clear_t clear; drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; GLint n = 0; if (cw != dPriv->w || ch != dPriv->h) { /* clear subregion */ 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 { /* clear whole buffer */ for ( ; i < nr ; i++ ) { *b++ = box[i]; n++; } } rmesa->radeon.sarea->nbox = n; clear.flags = flags; clear.clear_color = rmesa->radeon.state.color.clear; clear.clear_depth = rmesa->radeon.state.depth.clear; clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; clear.depth_mask = rmesa->radeon.state.stencil.clear; clear.depth_boxes = depth_boxes; n--; b = rmesa->radeon.sarea->boxes; for ( ; n >= 0 ; n-- ) { depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1; depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1; depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2; depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2; depth_boxes[n].f[CLEAR_DEPTH] = (float)rmesa->radeon.state.depth.clear; } ret = drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_CLEAR, &clear, sizeof(drm_radeon_clear_t)); if ( ret ) { UNLOCK_HARDWARE( &rmesa->radeon ); fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret ); exit( 1 ); } } UNLOCK_HARDWARE( &rmesa->radeon ); }
/* ================================================================ * 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; } r200Flush( ctx ); 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 ) { flags |= RADEON_DEPTH; mask &= ~DD_DEPTH_BIT; } if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) { flags |= RADEON_STENCIL; mask &= ~DD_STENCIL_BIT; } if ( mask ) { if (R200_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask); _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); } if ( !flags ) return; if (rmesa->using_hyperz) { flags |= RADEON_USE_COMP_ZBUF; /* if (rmesa->r200Screen->chipset & R200_CHIPSET_REAL_R200) flags |= RADEON_USE_HIERZ; */ if (!(rmesa->state.stencil.hwBuffer) || ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) && ((rmesa->state.stencil.clear & R200_STENCIL_WRITE_MASK) == R200_STENCIL_WRITE_MASK))) { flags |= RADEON_CLEAR_FASTZ; } } /* 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 ) { drm_radeon_getparam_t 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 ); LOCK_HARDWARE( rmesa ); } } /* Send current state to the hardware */ r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); for ( i = 0 ; i < dPriv->numClipRects ; ) { GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects ); drm_clip_rect_t *box = dPriv->pClipRects; drm_clip_rect_t *b = rmesa->sarea->boxes; drm_radeon_clear_t clear; drm_radeon_clear_rect_t 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 = rmesa->state.depth.clear; /* needed for hyperz */ 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[CLEAR_X1] = (float)b[n].x1; depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1; depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2; depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2; depth_boxes[n].f[CLEAR_DEPTH] = ctx->Depth.Clear; } ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR, &clear, sizeof(clear)); if ( ret ) { UNLOCK_HARDWARE( rmesa ); fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret ); exit( 1 ); } } UNLOCK_HARDWARE( rmesa ); rmesa->hw.all_dirty = GL_TRUE; }
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 ); 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; }