📄 radeon_accel.c
字号:
stop.flush = 0; i = 0; do { ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop, sizeof(drmRadeonCPStop)); } while (ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY); if (ret == 0) { return 0; } else if (errno != EBUSY) { return -errno; } stop.idle = 0; if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop, sizeof(drmRadeonCPStop))) { return -errno; } else { return 0; }}/* Get an indirect buffer for the CP 2D acceleration commands */drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); drmDMAReq dma; drmBufPtr buf = NULL; int indx = 0; int size = 0; int i = 0; int ret;#if 0 /* FIXME: pScrn->pScreen has not been initialized when this is first * called from RADEONSelectBuffer via RADEONDRICPInit. We could use * the screen index from pScrn, which is initialized, and then get * the screen from screenInfo.screens[index], but that is a hack. */ dma.context = DRIGetContext(pScrn->pScreen);#else /* This is the X server's context */ dma.context = 0x00000001;#endif 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 = &indx; dma.request_sizes = &size; dma.granted_count = 0; while (1) { do { ret = drmDMA(info->drmFD, &dma); if (ret && ret != -EBUSY) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: CP GetBuffer %d\n", __FUNCTION__, ret); } } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT)); if (ret == 0) { buf = &info->buffers->list[indx]; buf->used = 0; if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, " GetBuffer returning %d %p\n", buf->idx, buf->address); } return buf; } xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "GetBuffer timed out, resetting engine...\n"); RADEONEngineReset(pScrn); RADEONEngineRestore(pScrn); /* Always restart the engine when doing CP 2D acceleration */ RADEONCP_RESET(pScrn, info); RADEONCP_START(pScrn, info); }}/* Flush the indirect buffer to the kernel for submission to the card */void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard){ RADEONInfoPtr info = RADEONPTR(pScrn); drmBufPtr buffer = info->indirectBuffer; int start = info->indirectStart; drmRadeonIndirect indirect; if (!buffer) return; if (start == buffer->used && !discard) return; if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n", buffer->idx); } indirect.idx = buffer->idx; indirect.start = start; indirect.end = buffer->used; indirect.discard = discard; drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT, &indirect, sizeof(drmRadeonIndirect)); if (discard) { info->indirectBuffer = RADEONCPGetBuffer(pScrn); info->indirectStart = 0; } else { /* Start on a double word boundary */ info->indirectStart = buffer->used = (buffer->used + 7) & ~7; if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Starting at %d\n", info->indirectStart); } }}/* Flush and release the indirect buffer */void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); drmBufPtr buffer = info->indirectBuffer; int start = info->indirectStart; drmRadeonIndirect indirect; info->indirectBuffer = NULL; info->indirectStart = 0; if (!buffer) return; if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n", buffer->idx); } indirect.idx = buffer->idx; indirect.start = start; indirect.end = buffer->used; indirect.discard = 1; drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT, &indirect, sizeof(drmRadeonIndirect));}/** \brief Calculate HostDataBlit parameters from pointer and pitch * * This is a helper for the trivial HostDataBlit users that don't need to worry * about tiling etc. */voidRADEONHostDataParams(ScrnInfoPtr pScrn, CARD8 *dst, CARD32 pitch, int cpp, CARD32 *dstPitchOff, int *x, int *y){ RADEONInfoPtr info = RADEONPTR( pScrn ); CARD32 dstOffs = dst - info->FB + info->fbLocation; *dstPitchOff = pitch << 16 | (dstOffs & ~RADEON_BUFFER_ALIGN) >> 10; *y = ( dstOffs & RADEON_BUFFER_ALIGN ) / pitch; *x = ( ( dstOffs & RADEON_BUFFER_ALIGN ) - ( *y * pitch ) ) / cpp;}/* Set up a hostdata blit to transfer data from system memory to the * framebuffer. Returns the address where the data can be written to and sets * the dstPitch and hpass variables as required. */CARD8*RADEONHostDataBlit( ScrnInfoPtr pScrn, unsigned int cpp, unsigned int w, CARD32 dstPitchOff, CARD32 *bufPitch, int x, int *y, unsigned int *h, unsigned int *hpass){ RADEONInfoPtr info = RADEONPTR( pScrn ); CARD32 format, dwords; CARD8 *ret; RING_LOCALS; if ( *h == 0 ) { return NULL; } switch ( cpp ) { case 4: format = RADEON_GMC_DST_32BPP; *bufPitch = 4 * w; break; case 2: format = RADEON_GMC_DST_16BPP; *bufPitch = 2 * ((w + 1) & ~1); break; case 1: format = RADEON_GMC_DST_8BPP_CI; *bufPitch = (w + 3) & ~3; break; default: xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "%s: Unsupported cpp %d!\n", __func__, cpp ); return NULL; }#if X_BYTE_ORDER == X_BIG_ENDIAN /* Swap doesn't work on R300 and later, it's handled during the * copy to ind. buffer pass */ if (info->ChipFamily < CHIP_FAMILY_R300) { BEGIN_RING(2); if (cpp == 2) OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW); else if (cpp == 1) OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT); else OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); ADVANCE_RING(); }#endif /*RADEON_PURGE_CACHE(); RADEON_WAIT_UNTIL_IDLE();*/ *hpass = min( *h, ( ( RADEON_BUFFER_SIZE - 10 * 4 ) / *bufPitch ) ); dwords = *hpass * *bufPitch / 4; BEGIN_RING( dwords + 10 ); OUT_RING( CP_PACKET3( RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT, dwords + 10 - 2 ) ); OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_DST_CLIPPING | RADEON_GMC_BRUSH_NONE | format | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_S | RADEON_DP_SRC_SOURCE_HOST_DATA | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS ); OUT_RING( dstPitchOff ); OUT_RING( (*y << 16) | x ); OUT_RING( ((*y + *hpass) << 16) | (x + w) ); OUT_RING( 0xffffffff ); OUT_RING( 0xffffffff ); OUT_RING( *y << 16 | x ); OUT_RING( *hpass << 16 | (*bufPitch / cpp) ); OUT_RING( dwords ); ret = ( CARD8* )&__head[__count]; __count += dwords; ADVANCE_RING(); *y += *hpass; *h -= *hpass; return ret;}void RADEONCopySwap(CARD8 *dst, CARD8 *src, unsigned int size, int swap){ switch(swap) { case RADEON_HOST_DATA_SWAP_HDW: { unsigned int *d = (unsigned int *)dst; unsigned int *s = (unsigned int *)src; unsigned int nwords = size >> 2; for (; nwords > 0; --nwords, ++d, ++s) *d = ((*s & 0xffff) << 16) | ((*s >> 16) & 0xffff); return; } case RADEON_HOST_DATA_SWAP_32BIT: { unsigned int *d = (unsigned int *)dst; unsigned int *s = (unsigned int *)src; unsigned int nwords = size >> 2; for (; nwords > 0; --nwords, ++d, ++s)#ifdef __powerpc__ asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d));#else *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24);#endif return; } case RADEON_HOST_DATA_SWAP_16BIT: { unsigned short *d = (unsigned short *)dst; unsigned short *s = (unsigned short *)src; unsigned int nwords = size >> 1; for (; nwords > 0; --nwords, ++d, ++s)#ifdef __powerpc__ asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d));#else *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24);#endif return; } } if (src != dst) memmove(dst, src, size);}/* Copies a single pass worth of data for a hostdata blit set up by * RADEONHostDataBlit(). */voidRADEONHostDataBlitCopyPass( ScrnInfoPtr pScrn, unsigned int cpp, CARD8 *dst, CARD8 *src, unsigned int hpass, unsigned int dstPitch, unsigned int srcPitch){#if X_BYTE_ORDER == X_BIG_ENDIAN RADEONInfoPtr info = RADEONPTR( pScrn );#endif /* RADEONHostDataBlitCopy can return NULL ! */ if( (dst==NULL) || (src==NULL)) return; if ( dstPitch == srcPitch ) {#if X_BYTE_ORDER == X_BIG_ENDIAN if (info->ChipFamily >= CHIP_FAMILY_R300) { switch(cpp) { case 1: RADEONCopySwap(dst, src, hpass * dstPitch, RADEON_HOST_DATA_SWAP_32BIT); return; case 2: RADEONCopySwap(dst, src, hpass * dstPitch, RADEON_HOST_DATA_SWAP_HDW); return; } }#endif memcpy( dst, src, hpass * dstPitch ); } else { unsigned int minPitch = min( dstPitch, srcPitch ); while ( hpass-- ) {#if X_BYTE_ORDER == X_BIG_ENDIAN if (info->ChipFamily >= CHIP_FAMILY_R300) { switch(cpp) { case 1: RADEONCopySwap(dst, src, minPitch, RADEON_HOST_DATA_SWAP_32BIT); goto next; case 2: RADEONCopySwap(dst, src, minPitch, RADEON_HOST_DATA_SWAP_HDW); goto next; } }#endif memcpy( dst, src, minPitch );#if X_BYTE_ORDER == X_BIG_ENDIAN next:#endif src += srcPitch; dst += dstPitch; } }}#endifBool RADEONAccelInit(ScreenPtr pScreen){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn);#ifdef USE_EXA if (info->useEXA) {# ifdef XF86DRI if (info->directRenderingEnabled) { if (!RADEONDrawInitCP(pScreen)) return FALSE; } else# endif /* XF86DRI */ { if (!RADEONDrawInitMMIO(pScreen)) return FALSE; } }#endif /* USE_EXA */#ifdef USE_XAA if (!info->useEXA) { XAAInfoRecPtr a; if (!(a = info->accel = XAACreateInfoRec())) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAACreateInfoRec Error\n"); return FALSE; }#ifdef XF86DRI if (info->directRenderingEnabled) RADEONAccelInitCP(pScreen, a); else#endif /* XF86DRI */ RADEONAccelInitMMIO(pScreen, a); RADEONEngineInit(pScrn); if (!XAAInit(pScreen, a)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Error\n"); return FALSE; } }#endif /* USE_XAA */ return TRUE;}void RADEONInit3DEngine(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR (pScrn);#ifdef XF86DRI if (info->directRenderingEnabled) { RADEONSAREAPrivPtr pSAREAPriv; pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); RADEONInit3DEngineCP(pScrn); } else#endif RADEONInit3DEngineMMIO(pScrn); info->XInited3D = TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -