📄 r200_ioctl.c
字号:
} UNLOCK_HARDWARE( rmesa ); if (!rect) { rmesa->hw.all_dirty = GL_TRUE; rmesa->swap_count++; (*psp->systemTime->getUST)( & ust ); if ( missed_target ) { rmesa->swap_missed_count++; rmesa->swap_missed_ust = ust - rmesa->swap_ust; } rmesa->swap_ust = ust; sched_yield(); }}void r200PageFlip( __DRIdrawablePrivate *dPriv ){ r200ContextPtr rmesa; GLint ret; GLboolean missed_target; __DRIscreenPrivate *psp = dPriv->driScreenPriv; 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 (!dPriv->numClipRects) { UNLOCK_HARDWARE( rmesa ); usleep( 10000 ); /* throttle invisible client 10ms */ return; } /* Need to do this for the perf box placement: */ { drm_clip_rect_t *box = dPriv->pClipRects; drm_clip_rect_t *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 ); UNLOCK_HARDWARE( rmesa ); driWaitForVBlank( dPriv, & missed_target ); if ( missed_target ) { rmesa->swap_missed_count++; (void) (*psp->systemTime->getUST)( & rmesa->swap_missed_ust ); } LOCK_HARDWARE( rmesa ); ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP ); UNLOCK_HARDWARE( rmesa ); if ( ret ) { fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret ); exit( 1 ); } rmesa->swap_count++; (void) (*psp->systemTime->getUST)( & rmesa->swap_ust );#if 000 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->r200Screen->fbLocation; rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; if (rmesa->sarea->tiling_enabled) { rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE; }#else /* Get ready for drawing next frame. Update the renderbuffers' * flippedOffset/Pitch fields so we draw into the right place. */ driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer, rmesa->sarea->pfCurrentPage); r200UpdateDrawBuffer(rmesa->glCtx);#endif}/* ================================================================ * Buffer clear */static void r200Clear( GLcontext *ctx, GLbitfield mask ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; GLuint flags = 0; GLuint color_mask = 0; GLint ret, i; GLint cx, cy, cw, ch; if ( R200_DEBUG & DEBUG_IOCTL ) { fprintf( stderr, "r200Clear\n"); } { LOCK_HARDWARE( rmesa ); UNLOCK_HARDWARE( rmesa ); if ( dPriv->numClipRects == 0 ) return; } r200Flush( ctx ); if ( mask & BUFFER_BIT_FRONT_LEFT ) { flags |= RADEON_FRONT; color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; mask &= ~BUFFER_BIT_FRONT_LEFT; } if ( mask & BUFFER_BIT_BACK_LEFT ) { flags |= RADEON_BACK; color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; mask &= ~BUFFER_BIT_BACK_LEFT; } if ( mask & BUFFER_BIT_DEPTH ) { flags |= RADEON_DEPTH; mask &= ~BUFFER_BIT_DEPTH; } if ( (mask & BUFFER_BIT_STENCIL) && rmesa->state.stencil.hwBuffer ) { flags |= RADEON_STENCIL; mask &= ~BUFFER_BIT_STENCIL; } if ( mask ) { if (R200_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask); _swrast_Clear( ctx, mask ); } if ( !flags ) return; if (rmesa->using_hyperz) { flags |= RADEON_USE_COMP_ZBUF;/* if (rmesa->r200Screen->chip_family == CHIP_FAMILY_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; } } LOCK_HARDWARE( rmesa ); /* 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 ) { 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 (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 window */ 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 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 r200WaitForIdle( r200ContextPtr rmesa ){ LOCK_HARDWARE(rmesa); r200WaitForIdleLocked( rmesa ); UNLOCK_HARDWARE(rmesa);}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 ); 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 AllocateMemoryMESA allocates only GART 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 *r200AllocateMemoryMESA(__DRIscreen *screen, GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority){ GET_CURRENT_CONTEXT(ctx); r200ContextPtr rmesa; int region_offset; drm_radeon_mem_alloc_t 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->gartTextures.map) return NULL; if (getenv("R200_NO_ALLOC")) return NULL; alloc.region = RADEON_MEM_REGION_GART; 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->gartTextures.map; return (void *)(region_start + region_offset); }}/* Called via glXFreeMemoryMESA() */void r200FreeMemoryMESA(__DRIscreen *screen, GLvoid *pointer){ GET_CURRENT_CONTEXT(ctx); r200ContextPtr rmesa; ptrdiff_t region_offset; drm_radeon_mem_free_t memfree; int ret; if (R200_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s %p\n", __FUNCTION__, pointer); if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || !rmesa->r200Screen->gartTextures.map) { fprintf(stderr, "%s: no context\n", __FUNCTION__); return; } region_offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map; if (region_offset < 0 || region_offset > rmesa->r200Screen->gartTextures.size) { fprintf(stderr, "offset %d outside range 0..%d\n", region_offset, rmesa->r200Screen->gartTextures.size); return; } memfree.region = RADEON_MEM_REGION_GART; 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 glXGetMemoryOffsetMESA() */GLuint r200GetMemoryOffsetMESA(__DRIscreen *screen, 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 (!r200IsGartMemory( rmesa, pointer, 0 )) return ~0; card_offset = r200GartOffsetFromVirtual( rmesa, pointer ); return card_offset - rmesa->r200Screen->gart_base;}GLboolean r200IsGartMemory( r200ContextPtr rmesa, const GLvoid *pointer, GLint size ){ ptrdiff_t offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map; int valid = (size >= 0 && offset >= 0 && offset + size < rmesa->r200Screen->gartTextures.size); if (R200_DEBUG & DEBUG_IOCTL) fprintf(stderr, "r200IsGartMemory( %p ) : %d\n", pointer, valid ); return valid;}GLuint r200GartOffsetFromVirtual( r200ContextPtr rmesa, const GLvoid *pointer ){ ptrdiff_t offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map; if (offset < 0 || offset > rmesa->r200Screen->gartTextures.size) return ~0; else return rmesa->r200Screen->gart_texture_offset + offset;}void r200InitIoctlFuncs( struct dd_function_table *functions ){ functions->Clear = r200Clear; functions->Finish = r200Finish; functions->Flush = r200Flush;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -