📄 via_ioctl.c
字号:
viaWaitBreadcrumb( vmesa, vmesa->lastDma ); if (light) return; while(!viaCheckIdle(vmesa)) ; via_release_pending_textures(vmesa);}/* Wait for command stream to be processed *and* the next vblank to * occur. Equivalent to calling WAIT_IDLE() and then WaitVBlank, * except that WAIT_IDLE() will spin the CPU polling, while this is * IRQ driven. */static void viaWaitIdleVBlank( __DRIdrawablePrivate *dPriv, struct via_context *vmesa, GLuint value ){ GLboolean missed_target; __DRIscreenPrivate *psp = dPriv->driScreenPriv; VIA_FLUSH_DMA(vmesa); if (!value) return; do { if (value < vmesa->lastBreadcrumbRead || vmesa->thrashing) viaSwapOutWork(vmesa); driWaitForVBlank( dPriv, & missed_target ); if ( missed_target ) { vmesa->swap_missed_count++; (*psp->systemTime->getUST)( &vmesa->swap_missed_ust ); } } while (!viaCheckBreadcrumb(vmesa, value)); vmesa->thrashing = 0; /* reset flag on swap */ vmesa->swap_count++; via_release_pending_textures( vmesa );}static void viaDoPageFlipLocked(struct via_context *vmesa, GLuint offset){ RING_VARS; if (VIA_DEBUG & DEBUG_2D) fprintf(stderr, "%s %x\n", __FUNCTION__, offset); if (!vmesa->nDoneFirstFlip) { vmesa->nDoneFirstFlip = GL_TRUE; BEGIN_RING(4); OUT_RING(HALCYON_HEADER2); OUT_RING(0x00fe0000); OUT_RING(0x0000000e); OUT_RING(0x0000000e); ADVANCE_RING(); } BEGIN_RING(4); OUT_RING( HALCYON_HEADER2 ); OUT_RING( 0x00fe0000 ); OUT_RING((HC_SubA_HFBBasL << 24) | (offset & 0xFFFFF8) | 0x2); OUT_RING((HC_SubA_HFBDrawFirst << 24) | ((offset & 0xFF000000) >> 24) | 0x0100); ADVANCE_RING(); vmesa->pfCurrentOffset = vmesa->sarea->pfCurrentOffset = offset; viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* often redundant */}void viaResetPageFlippingLocked(struct via_context *vmesa){ if (VIA_DEBUG & DEBUG_2D) fprintf(stderr, "%s\n", __FUNCTION__); viaDoPageFlipLocked( vmesa, 0 ); if (vmesa->front.offset != 0) { struct via_renderbuffer buffer_tmp; memcpy(&buffer_tmp, &vmesa->back, sizeof(struct via_renderbuffer)); memcpy(&vmesa->back, &vmesa->front, sizeof(struct via_renderbuffer)); memcpy(&vmesa->front, &buffer_tmp, sizeof(struct via_renderbuffer)); } assert(vmesa->front.offset == 0); vmesa->doPageFlip = vmesa->allowPageFlip = 0;}/* * Copy the back buffer to the front buffer. */void viaCopyBuffer(__DRIdrawablePrivate *dPriv){ struct via_context *vmesa = (struct via_context *)dPriv->driContextPriv->driverPrivate; __DRIscreenPrivate *psp = dPriv->driScreenPriv; if (VIA_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s: lastSwap[1] %d lastSwap[0] %d lastWrite %d lastRead %d\n", __FUNCTION__, vmesa->lastSwap[1], vmesa->lastSwap[0], vmesa->lastBreadcrumbWrite, vmesa->lastBreadcrumbRead); VIA_FLUSH_DMA(vmesa); if (dPriv->vblFlags == VBLANK_FLAG_SYNC && vmesa->lastBreadcrumbWrite > 1) viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite-1); else viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[1]); LOCK_HARDWARE(vmesa); /* Catch and cleanup situation where we were pageflipping but have * stopped. */ if (dPriv->numClipRects && vmesa->sarea->pfCurrentOffset != 0) { viaResetPageFlippingLocked(vmesa); UNLOCK_HARDWARE(vmesa); return; } viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects); vmesa->lastSwap[1] = vmesa->lastSwap[0]; vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite; viaEmitBreadcrumbLocked(vmesa); UNLOCK_HARDWARE(vmesa); (*psp->systemTime->getUST)( &vmesa->swap_ust );}void viaPageFlip(__DRIdrawablePrivate *dPriv){ struct via_context *vmesa = (struct via_context *)dPriv->driContextPriv->driverPrivate; struct via_renderbuffer buffer_tmp; __DRIscreenPrivate *psp = dPriv->driScreenPriv; VIA_FLUSH_DMA(vmesa); if (dPriv->vblFlags == VBLANK_FLAG_SYNC && vmesa->lastBreadcrumbWrite > 1) viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite - 1); else viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[0]); LOCK_HARDWARE(vmesa); viaDoPageFlipLocked(vmesa, vmesa->back.offset); vmesa->lastSwap[1] = vmesa->lastSwap[0]; vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite; viaEmitBreadcrumbLocked(vmesa); UNLOCK_HARDWARE(vmesa); (*psp->systemTime->getUST)( &vmesa->swap_ust ); /* KW: FIXME: When buffers are freed, could free frontbuffer by * accident: */ memcpy(&buffer_tmp, &vmesa->back, sizeof(struct via_renderbuffer)); memcpy(&vmesa->back, &vmesa->front, sizeof(struct via_renderbuffer)); memcpy(&vmesa->front, &buffer_tmp, sizeof(struct via_renderbuffer));}#define VIA_CMDBUF_MAX_LAG 50000static int fire_buffer(struct via_context *vmesa){ drm_via_cmdbuffer_t bufI; int ret; bufI.buf = (char *)vmesa->dma; bufI.size = vmesa->dmaLow; if (vmesa->useAgp) { drm_via_cmdbuf_size_t bSiz; /* Do the CMDBUF_SIZE ioctl: */ bSiz.func = VIA_CMDBUF_LAG; bSiz.wait = 1; bSiz.size = VIA_CMDBUF_MAX_LAG; do { ret = drmCommandWriteRead(vmesa->driFd, DRM_VIA_CMDBUF_SIZE, &bSiz, sizeof(bSiz)); } while (ret == -EAGAIN); if (ret) { UNLOCK_HARDWARE(vmesa); fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n", __FUNCTION__, ret); abort(); return ret; } /* Actually fire the buffer: */ do { ret = drmCommandWrite(vmesa->driFd, DRM_VIA_CMDBUFFER, &bufI, sizeof(bufI)); } while (ret == -EAGAIN); if (ret) { UNLOCK_HARDWARE(vmesa); fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n", __FUNCTION__, ret); abort(); /* If this fails, the original code fell back to the PCI path. */ } else return 0; /* Fall through to PCI handling?!? */ viaWaitIdleLocked(vmesa, GL_FALSE); } ret = drmCommandWrite(vmesa->driFd, DRM_VIA_PCICMD, &bufI, sizeof(bufI)); if (ret) { UNLOCK_HARDWARE(vmesa); dump_dma(vmesa); fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret); abort(); } return ret;}/* Inserts the surface addresss and active cliprects one at a time * into the head of the DMA buffer being flushed. Fires the buffer * for each cliprect. */static void via_emit_cliprect(struct via_context *vmesa, drm_clip_rect_t *b) { struct via_renderbuffer *buffer = vmesa->drawBuffer; GLuint *vb = (GLuint *)(vmesa->dma + vmesa->dmaCliprectAddr); GLuint format = (vmesa->viaScreen->bitsPerPixel == 0x20 ? HC_HDBFM_ARGB8888 : HC_HDBFM_RGB565); GLuint pitch = buffer->pitch; GLuint offset = buffer->offset; if (0) fprintf(stderr, "emit cliprect for box %d,%d %d,%d\n", b->x1, b->y1, b->x2, b->y2); vb[0] = HC_HEADER2; vb[1] = (HC_ParaType_NotTex << 16); if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) { vb[2] = (HC_SubA_HClipTB << 24) | 0x0; vb[3] = (HC_SubA_HClipLR << 24) | 0x0; } else { vb[2] = (HC_SubA_HClipTB << 24) | (b->y1 << 12) | b->y2; vb[3] = (HC_SubA_HClipLR << 24) | (b->x1 << 12) | b->x2; } vb[4] = (HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF); vb[5] = (HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000) >> 24); vb[6] = (HC_SubA_HSPXYOS << 24); vb[7] = (HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch;}static int intersect_rect(drm_clip_rect_t *out, drm_clip_rect_t *a, drm_clip_rect_t *b){ *out = *a; if (0) fprintf(stderr, "intersect %d,%d %d,%d and %d,%d %d,%d\n", a->x1, a->y1, a->x2, a->y2, b->x1, b->y1, b->x2, b->y2); if (b->x1 > out->x1) out->x1 = b->x1; if (b->x2 < out->x2) out->x2 = b->x2; if (out->x1 >= out->x2) return 0; if (b->y1 > out->y1) out->y1 = b->y1; if (b->y2 < out->y2) out->y2 = b->y2; if (out->y1 >= out->y2) return 0; return 1;}void viaFlushDmaLocked(struct via_context *vmesa, GLuint flags){ int i; RING_VARS; if (VIA_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) fprintf(stderr, "%s\n", __FUNCTION__); if (*(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|vmesa->hHWContext) && *(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|DRM_LOCK_CONT|vmesa->hHWContext)) { fprintf(stderr, "%s called without lock held\n", __FUNCTION__); abort(); } if (vmesa->dmaLow == 0) { return; } assert(vmesa->dmaLastPrim == 0); /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER: */ if (vmesa->dmaLow > VIA_DMA_HIGHWATER + 8) { fprintf(stderr, "buffer overflow in Flush Prims = %d\n",vmesa->dmaLow); abort(); } switch (vmesa->dmaLow & 0x1F) { case 8: BEGIN_RING_NOCHECK( 6 ); OUT_RING( HC_HEADER2 ); OUT_RING( (HC_ParaType_NotTex << 16) ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); ADVANCE_RING(); break; case 16: BEGIN_RING_NOCHECK( 4 ); OUT_RING( HC_HEADER2 ); OUT_RING( (HC_ParaType_NotTex << 16) ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); ADVANCE_RING(); break; case 24: BEGIN_RING_NOCHECK( 10 ); OUT_RING( HC_HEADER2 ); OUT_RING( (HC_ParaType_NotTex << 16) ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); OUT_RING( HC_DUMMY ); ADVANCE_RING(); break; case 0: break; default: if (VIA_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s: unaligned value for vmesa->dmaLow: %x\n", __FUNCTION__, vmesa->dmaLow); } vmesa->lastDma = vmesa->lastBreadcrumbWrite; if (VIA_DEBUG & DEBUG_DMA) dump_dma( vmesa ); if (flags & VIA_NO_CLIPRECTS) { if (0) fprintf(stderr, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__); assert(vmesa->dmaCliprectAddr == ~0); fire_buffer( vmesa ); } else if (vmesa->dmaCliprectAddr == ~0) { /* Contains only state. Could just dump the packet? */ if (0) fprintf(stderr, "%s: no dmaCliprectAddr\n", __FUNCTION__); if (0) fire_buffer( vmesa ); } else if (vmesa->numClipRects) { drm_clip_rect_t *pbox = vmesa->pClipRects; __DRIdrawablePrivate *dPriv = vmesa->driDrawable; struct via_renderbuffer *const vrb = (struct via_renderbuffer *) dPriv->driverPrivate; for (i = 0; i < vmesa->numClipRects; i++) { drm_clip_rect_t b; b.x1 = pbox[i].x1; b.x2 = pbox[i].x2; b.y1 = pbox[i].y1; b.y2 = pbox[i].y2; if (vmesa->scissor && !intersect_rect(&b, &b, &vmesa->scissorRect)) continue; via_emit_cliprect(vmesa, &b); if (fire_buffer(vmesa) != 0) { dump_dma( vmesa ); goto done; } } } else { if (0) fprintf(stderr, "%s: no cliprects\n", __FUNCTION__); UNLOCK_HARDWARE(vmesa); sched_yield(); LOCK_HARDWARE(vmesa); } done: /* Reset vmesa vars: */ vmesa->dmaLow = 0; vmesa->dmaCliprectAddr = ~0; vmesa->newEmitState = ~0;}void viaWrapPrimitive( struct via_context *vmesa ){ GLenum renderPrimitive = vmesa->renderPrimitive; GLenum hwPrimitive = vmesa->hwPrimitive; if (VIA_DEBUG & DEBUG_PRIMS) fprintf(stderr, "%s\n", __FUNCTION__); if (vmesa->dmaLastPrim) viaFinishPrimitive( vmesa ); viaFlushDma(vmesa); if (renderPrimitive != GL_POLYGON + 1) viaRasterPrimitive( vmesa->glCtx, renderPrimitive, hwPrimitive );}void viaFlushDma(struct via_context *vmesa){ if (vmesa->dmaLow) { assert(!vmesa->dmaLastPrim); LOCK_HARDWARE(vmesa); viaFlushDmaLocked(vmesa, 0); UNLOCK_HARDWARE(vmesa); }}static void viaFlush(GLcontext *ctx){ struct via_context *vmesa = VIA_CONTEXT(ctx); VIA_FLUSH_DMA(vmesa);}static void viaFinish(GLcontext *ctx){ struct via_context *vmesa = VIA_CONTEXT(ctx); VIA_FLUSH_DMA(vmesa); viaWaitIdle(vmesa, GL_FALSE);}static void viaClearStencil(GLcontext *ctx, int s){ return;}void viaInitIoctlFuncs(GLcontext *ctx){ ctx->Driver.Flush = viaFlush; ctx->Driver.Clear = viaClear; ctx->Driver.Finish = viaFinish; ctx->Driver.ClearStencil = viaClearStencil;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -