radeon_accelfuncs.c [plain text]
#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
#error Cannot define both MMIO and CP acceleration!
#endif
#if !defined(UNIXCPP) || defined(ANSICPP)
#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
#else
#define FUNC_NAME_CAT(prefix,suffix) prefixsuffix
#endif
#ifdef ACCEL_MMIO
#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
#else
#ifdef ACCEL_CP
#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
#else
#error No accel type defined!
#endif
#endif
void
FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
int i = 0;
#ifdef ACCEL_CP
if (info->CPStarted) {
int ret;
FLUSH_RING();
for (;;) {
do {
ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE);
if (ret && ret != -EBUSY) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"%s: CP idle %d\n", __FUNCTION__, ret);
}
} while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT));
if (ret == 0) return;
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Idle timed out, resetting engine...\n");
RADEONEngineReset(pScrn);
RADEONEngineRestore(pScrn);
RADEONCP_RESET(pScrn, info);
RADEONCP_START(pScrn, info);
}
}
#endif
RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n",
INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
INREG(RADEON_RBBM_STATUS)));
RADEONWaitForFifoFunction(pScrn, 64);
for (;;) {
for (i = 0; i < RADEON_TIMEOUT; i++) {
if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) {
RADEONEngineFlush(pScrn);
return;
}
}
RADEONTRACE(("Idle timed out: %d entries, stat=0x%08x\n",
INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
INREG(RADEON_RBBM_STATUS)));
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Idle timed out, resetting engine...\n");
RADEONEngineReset(pScrn);
RADEONEngineRestore(pScrn);
#ifdef XF86DRI
if (info->directRenderingEnabled) {
RADEONCP_RESET(pScrn, info);
RADEONCP_START(pScrn, info);
}
#endif
}
}
static void
FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
#ifdef ACCEL_MMIO
CARD32 pitch64;
pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6;
OUTREG(RADEON_DEFAULT_OFFSET, (((INREG(RADEON_DISPLAY_BASE_ADDR) + pScrn->fbOffset) >> 10) |
(pitch64 << 22)));
RADEONWaitForIdleMMIO(pScrn);
#else
RADEONWaitForFifo(pScrn, 1);
OUTREG(RADEON_DEFAULT_OFFSET, info->frontPitchOffset);
RADEONWaitForIdleMMIO(pScrn);
#if 0
RADEONMMIO_TO_CP(pScrn, info);
#endif
#endif
}
static void
FUNC_NAME(RADEONSetupForSolidFill)(ScrnInfoPtr pScrn,
int color,
int rop,
unsigned int planemask)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP[rop].pattern);
BEGIN_ACCEL(4);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, color);
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT
| RADEON_DST_Y_TOP_TO_BOTTOM));
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSubsequentSolidFillRect)(ScrnInfoPtr pScrn,
int x, int y,
int w, int h)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
BEGIN_ACCEL(2);
OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSetupForSolidLine)(ScrnInfoPtr pScrn,
int color,
int rop,
unsigned int planemask)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP[rop].pattern);
if (info->ChipFamily >= CHIP_FAMILY_RV200) {
BEGIN_ACCEL(1);
OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT,
0x55 << RADEON_BRES_CNTL_SHIFT);
}
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, color);
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSubsequentSolidHorVertLine)(ScrnInfoPtr pScrn,
int x, int y,
int len,
int dir)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
int w = 1;
int h = 1;
ACCEL_PREAMBLE();
if (dir == DEGREES_0) w = len;
else h = len;
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT
| RADEON_DST_Y_TOP_TO_BOTTOM));
OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSubsequentSolidTwoPointLine)(ScrnInfoPtr pScrn,
int xa, int ya,
int xb, int yb,
int flags)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
if (!(flags & OMIT_LAST))
FUNC_NAME(RADEONSubsequentSolidHorVertLine)(pScrn,
xb, yb, 1,
DEGREES_0);
BEGIN_ACCEL(2);
OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa);
OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSetupForDashedLine)(ScrnInfoPtr pScrn,
int fg,
int bg,
int rop,
unsigned int planemask,
int length,
unsigned char *pattern)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
CARD32 pat = *(CARD32 *)(pointer)pattern;
ACCEL_PREAMBLE();
info->dashLen = length;
info->dashPattern = pat;
#if X_BYTE_ORDER == X_BIG_ENDIAN
# define PAT_SHIFT(pat, shift) (pat >> shift)
#else
# define PAT_SHIFT(pat, shift) (pat << shift)
#endif
switch (length) {
case 2: pat |= PAT_SHIFT(pat, 2);
case 4: pat |= PAT_SHIFT(pat, 4);
case 8: pat |= PAT_SHIFT(pat, 8);
case 16: pat |= PAT_SHIFT(pat, 16);
}
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| (bg == -1
? RADEON_GMC_BRUSH_32x1_MONO_FG_LA
: RADEON_GMC_BRUSH_32x1_MONO_FG_BG)
| RADEON_ROP[rop].pattern
| RADEON_GMC_BYTE_LSB_TO_MSB);
info->dash_fg = fg;
info->dash_bg = bg;
BEGIN_ACCEL((bg == -1) ? 4 : 5);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
if (bg != -1)
OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, bg);
OUT_ACCEL_REG(RADEON_BRUSH_DATA0, pat);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONDashedLastPel)(ScrnInfoPtr pScrn,
int x, int y,
int fg)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
CARD32 dp_gui_master_cntl = info->dp_gui_master_cntl_clip;
ACCEL_PREAMBLE();
dp_gui_master_cntl &= ~RADEON_GMC_BRUSH_DATATYPE_MASK;
dp_gui_master_cntl |= RADEON_GMC_BRUSH_SOLID_COLOR;
dp_gui_master_cntl &= ~RADEON_GMC_SRC_DATATYPE_MASK;
dp_gui_master_cntl |= RADEON_GMC_SRC_DATATYPE_COLOR;
BEGIN_ACCEL(7);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, dp_gui_master_cntl);
OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT
| RADEON_DST_Y_TOP_TO_BOTTOM));
OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (1 << 16) | 1);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, info->dash_fg);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSubsequentDashedTwoPointLine)(ScrnInfoPtr pScrn,
int xa, int ya,
int xb, int yb,
int flags,
int phase)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
if (!(flags & OMIT_LAST)) {
int deltax = abs(xa - xb);
int deltay = abs(ya - yb);
int shift;
if (deltax > deltay) shift = deltax;
else shift = deltay;
shift += phase;
shift %= info->dashLen;
if ((info->dashPattern >> shift) & 1)
FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->dash_fg);
else if (info->dash_bg != -1)
FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->dash_bg);
}
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa);
OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT, phase);
OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSetTransparency)(ScrnInfoPtr pScrn,
int trans_color)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
if ((trans_color != -1) || (info->XAAForceTransBlit == TRUE)) {
ACCEL_PREAMBLE();
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_CLR_CMP_CLR_SRC, trans_color);
OUT_ACCEL_REG(RADEON_CLR_CMP_MASK, RADEON_CLR_CMP_MSK);
OUT_ACCEL_REG(RADEON_CLR_CMP_CNTL, (RADEON_SRC_CMP_EQ_COLOR
| RADEON_CLR_CMP_SRC_SOURCE));
FINISH_ACCEL();
}
}
static void
FUNC_NAME(RADEONSetupForScreenToScreenCopy)(ScrnInfoPtr pScrn,
int xdir, int ydir,
int rop,
unsigned int planemask,
int trans_color)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
info->xdir = xdir;
info->ydir = ydir;
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| RADEON_GMC_BRUSH_NONE
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP[rop].rop
| RADEON_DP_SRC_SOURCE_MEMORY);
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
OUT_ACCEL_REG(RADEON_DP_CNTL,
((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
(ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
FINISH_ACCEL();
info->trans_color = trans_color;
FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
}
static void
FUNC_NAME(RADEONSubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn,
int xa, int ya,
int xb, int yb,
int w, int h)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
if (info->xdir < 0) xa += w - 1, xb += w - 1;
if (info->ydir < 0) ya += h - 1, yb += h - 1;
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_SRC_Y_X, (ya << 16) | xa);
OUT_ACCEL_REG(RADEON_DST_Y_X, (yb << 16) | xb);
OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSetupForMono8x8PatternFill)(ScrnInfoPtr pScrn,
int patternx,
int patterny,
int fg,
int bg,
int rop,
unsigned int planemask)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
#if X_BYTE_ORDER == X_BIG_ENDIAN
unsigned char pattern[8];
#endif
ACCEL_PREAMBLE();
#if X_BYTE_ORDER == X_BIG_ENDIAN
pattern[0] = (patternx & 0x000000ff);
pattern[1] = (patternx & 0x0000ff00) >> 8;
pattern[2] = (patternx & 0x00ff0000) >> 16;
pattern[3] = (patternx & 0xff000000) >> 24;
pattern[4] = (patterny & 0x000000ff);
pattern[5] = (patterny & 0x0000ff00) >> 8;
pattern[6] = (patterny & 0x00ff0000) >> 16;
pattern[7] = (patterny & 0xff000000) >> 24;
#endif
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| (bg == -1
? RADEON_GMC_BRUSH_8X8_MONO_FG_LA
: RADEON_GMC_BRUSH_8X8_MONO_FG_BG)
| RADEON_ROP[rop].pattern
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
| RADEON_GMC_BYTE_MSB_TO_LSB
#endif
);
BEGIN_ACCEL((bg == -1) ? 5 : 6);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
if (bg != -1)
OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, bg);
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
OUT_ACCEL_REG(RADEON_BRUSH_DATA0, patternx);
OUT_ACCEL_REG(RADEON_BRUSH_DATA1, patterny);
#else
OUT_ACCEL_REG(RADEON_BRUSH_DATA0, *(CARD32 *)(pointer)&pattern[0]);
OUT_ACCEL_REG(RADEON_BRUSH_DATA1, *(CARD32 *)(pointer)&pattern[4]);
#endif
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn,
int patternx,
int patterny,
int x, int y,
int w, int h)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (patterny << 8) | patternx);
OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
FINISH_ACCEL();
}
#if 0
static void
FUNC_NAME(RADEONSetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,
int patx, int paty,
int rop,
unsigned int planemask,
int trans_color)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| RADEON_GMC_BRUSH_8x8_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP[rop].pattern
| RADEON_DP_SRC_SOURCE_MEMORY);
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
OUT_ACCEL_REG(RADEON_SRC_Y_X, (paty << 16) | patx);
FINISH_ACCEL();
info->trans_color = trans_color;
FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
}
static void
FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn,
int patx, int paty,
int x, int y,
int w, int h)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (paty << 16) | patx);
OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
FINISH_ACCEL();
}
#endif
#ifdef ACCEL_CP
#define CP_BUFSIZE (info->indirectBuffer->total/4-9)
static void
RADEONCPScanlinePacket(ScrnInfoPtr pScrn, int bufno)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
int chunk_words = info->scanline_hpass * info->scanline_words;
ACCEL_PREAMBLE();
if (RADEON_VERBOSE) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"CPScanline Packet h=%d hpass=%d chunkwords=%d\n",
info->scanline_h, info->scanline_hpass, chunk_words);
}
BEGIN_RING(chunk_words+9);
OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT,chunk_words+9-2));
OUT_RING(info->dp_gui_master_cntl_clip);
OUT_RING((info->scanline_y << 16) |
(info->scanline_x1clip & 0xffff));
OUT_RING(((info->scanline_y+info->scanline_hpass) << 16) |
(info->scanline_x2clip & 0xffff));
OUT_RING(info->scanline_fg);
OUT_RING(info->scanline_bg);
OUT_RING((info->scanline_y << 16) |
(info->scanline_x & 0xffff));
OUT_RING((info->scanline_hpass << 16) |
(info->scanline_w & 0xffff));
OUT_RING(chunk_words);
info->scratch_buffer[bufno] = (unsigned char *)&__head[__count];
__count += chunk_words;
FINISH_ACCEL();
info->scanline_y += info->scanline_hpass;
info->scanline_h -= info->scanline_hpass;
}
#endif
static void
FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn,
int fg,
int bg,
int rop,
unsigned int
planemask)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| RADEON_GMC_DST_CLIPPING
| RADEON_GMC_BRUSH_NONE
| (bg == -1
? RADEON_GMC_SRC_DATATYPE_MONO_FG_LA
: RADEON_GMC_SRC_DATATYPE_MONO_FG_BG)
| RADEON_ROP[rop].rop
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
| RADEON_GMC_BYTE_LSB_TO_MSB
#else
| RADEON_GMC_BYTE_MSB_TO_LSB
#endif
| RADEON_DP_SRC_SOURCE_HOST_DATA);
#ifdef ACCEL_MMIO
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
BEGIN_ACCEL(4);
#else
BEGIN_ACCEL(5);
OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE);
#endif
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR, fg);
OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR, bg);
#else
info->scanline_fg = fg;
info->scanline_bg = bg;
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
BEGIN_ACCEL(1);
#else
BEGIN_ACCEL(2);
OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT);
#endif
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
#endif
FINISH_ACCEL();
}
static void
FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr
pScrn,
int x, int y,
int w, int h,
int skipleft)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
#ifdef ACCEL_MMIO
ACCEL_PREAMBLE();
info->scanline_h = h;
info->scanline_words = (w + 31) >> 5;
#ifdef __alpha__
if (0)
#else
if ((info->scanline_words * h) <= 9)
#endif
{
info->scratch_buffer[0] =
(unsigned char *)(ADDRREG(RADEON_HOST_DATA_LAST)
- (info->scanline_words - 1));
info->scanline_direct = 1;
} else {
info->scratch_buffer[0] = info->scratch_save;
info->scanline_direct = 0;
}
BEGIN_ACCEL(4 + (info->scanline_direct ?
(info->scanline_words * h) : 0));
OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft)
& 0xffff));
OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff));
OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | (x & 0xffff));
OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | ((w + 31) & ~31));
FINISH_ACCEL();
#else
info->scanline_x = x;
info->scanline_y = y;
info->scanline_w = (w + 31) & ~31;
info->scanline_h = h;
info->scanline_x1clip = x + skipleft;
info->scanline_x2clip = x + w;
info->scanline_words = info->scanline_w / 32;
info->scanline_hpass = min(h,(CP_BUFSIZE/info->scanline_words));
RADEONCPScanlinePacket(pScrn, 0);
#endif
}
static void
FUNC_NAME(RADEONSubsequentScanline)(ScrnInfoPtr pScrn,
int bufno)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
#ifdef ACCEL_MMIO
CARD32 *p = (pointer)info->scratch_buffer[bufno];
int i;
int left = info->scanline_words;
volatile CARD32 *d;
ACCEL_PREAMBLE();
if (info->scanline_direct) return;
--info->scanline_h;
while (left) {
write_mem_barrier();
if (left <= 8) {
if (info->scanline_h == 0) {
BEGIN_ACCEL(left);
for (d = ADDRREG(RADEON_HOST_DATA_LAST) - (left - 1); left; --left)
*d++ = *p++;
return;
} else {
BEGIN_ACCEL(left);
for (d = ADDRREG(RADEON_HOST_DATA7) - (left - 1); left; --left)
*d++ = *p++;
}
} else {
BEGIN_ACCEL(8);
for (d = ADDRREG(RADEON_HOST_DATA0), i = 0; i < 8; i++)
*d++ = *p++;
left -= 8;
}
}
FINISH_ACCEL();
#else
if (--info->scanline_hpass) {
info->scratch_buffer[bufno] += 4 * info->scanline_words;
} else if (info->scanline_h) {
info->scanline_hpass =
min(info->scanline_h,(CP_BUFSIZE/info->scanline_words));
RADEONCPScanlinePacket(pScrn, bufno);
}
#endif
}
static void
FUNC_NAME(RADEONSetupForScanlineImageWrite)(ScrnInfoPtr pScrn,
int rop,
unsigned int planemask,
int trans_color,
int bpp,
int depth)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
info->scanline_bpp = bpp;
info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
| RADEON_GMC_DST_CLIPPING
| RADEON_GMC_BRUSH_NONE
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP[rop].rop
| RADEON_GMC_BYTE_MSB_TO_LSB
| RADEON_DP_SRC_SOURCE_HOST_DATA);
#ifdef ACCEL_MMIO
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
BEGIN_ACCEL(2);
#else
BEGIN_ACCEL(3);
if (bpp == 16)
OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_16BIT);
else if (bpp == 32)
OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT);
else
OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE);
#endif
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
#else
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
BEGIN_ACCEL(1);
#else
BEGIN_ACCEL(2);
if (bpp == 16)
OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW);
else
OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE);
#endif
#endif
OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
FINISH_ACCEL();
info->trans_color = trans_color;
FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
}
static void
FUNC_NAME(RADEONSubsequentScanlineImageWriteRect)(ScrnInfoPtr pScrn,
int x, int y,
int w, int h,
int skipleft)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
#ifdef ACCEL_MMIO
int shift = 0;
ACCEL_PREAMBLE();
if (pScrn->bitsPerPixel == 8) shift = 3;
else if (pScrn->bitsPerPixel == 16) shift = 1;
info->scanline_h = h;
info->scanline_words = (w * info->scanline_bpp + 31) >> 5;
#ifdef __alpha__
if (0)
#else
if ((info->scanline_words * h) <= 9)
#endif
{
info->scratch_buffer[0]
= (unsigned char *)(ADDRREG(RADEON_HOST_DATA_LAST)
- (info->scanline_words - 1));
info->scanline_direct = 1;
} else {
info->scratch_buffer[0] = info->scratch_save;
info->scanline_direct = 0;
}
BEGIN_ACCEL(4 + (info->scanline_direct ?
(info->scanline_words * h) : 0));
OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft)
& 0xffff));
OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff));
OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | (x & 0xffff));
OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | ((w + shift) &
~shift));
FINISH_ACCEL();
#else
int pad = 0;
if (pScrn->bitsPerPixel == 8) pad = 3;
else if (pScrn->bitsPerPixel == 16) pad = 1;
info->scanline_x = x;
info->scanline_y = y;
info->scanline_w = (w + pad) & ~pad;
info->scanline_h = h;
info->scanline_x1clip = x + skipleft;
info->scanline_x2clip = x + w;
info->scanline_words = (w * info->scanline_bpp + 31) / 32;
info->scanline_hpass = min(h,(CP_BUFSIZE/info->scanline_words));
RADEONCPScanlinePacket(pScrn, 0);
#endif
}
static void
FUNC_NAME(RADEONSetClippingRectangle)(ScrnInfoPtr pScrn,
int xa, int ya,
int xb, int yb)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned long tmp1 = 0;
unsigned long tmp2 = 0;
ACCEL_PREAMBLE();
if (xa < 0) {
tmp1 = (-xa) & 0x3fff;
tmp1 |= RADEON_SC_SIGN_MASK_LO;
} else {
tmp1 = xa;
}
if (ya < 0) {
tmp1 |= (((-ya) & 0x3fff) << 16);
tmp1 |= RADEON_SC_SIGN_MASK_HI;
} else {
tmp1 |= (ya << 16);
}
xb++; yb++;
if (xb < 0) {
tmp2 = (-xb) & 0x3fff;
tmp2 |= RADEON_SC_SIGN_MASK_LO;
} else {
tmp2 = xb;
}
if (yb < 0) {
tmp2 |= (((-yb) & 0x3fff) << 16);
tmp2 |= RADEON_SC_SIGN_MASK_HI;
} else {
tmp2 |= (yb << 16);
}
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl_clip
| RADEON_GMC_DST_CLIPPING));
OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, tmp1);
OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, tmp2);
FINISH_ACCEL();
FUNC_NAME(RADEONSetTransparency)(pScrn, info->trans_color);
}
static void
FUNC_NAME(RADEONDisableClipping)(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
BEGIN_ACCEL(3);
OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, 0);
OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX |
RADEON_DEFAULT_SC_BOTTOM_MAX));
FINISH_ACCEL();
FUNC_NAME(RADEONSetTransparency)(pScrn, info->trans_color);
}
#ifdef ACCEL_CP
void
RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ACCEL_PREAMBLE();
switch (buffer) {
case RADEON_BACK:
info->dst_pitch_offset = info->backPitchOffset;
break;
case RADEON_DEPTH:
info->dst_pitch_offset = info->depthPitchOffset;
break;
default:
case RADEON_FRONT:
info->dst_pitch_offset = info->frontPitchOffset;
break;
}
BEGIN_ACCEL(1);
OUT_ACCEL_REG(RADEON_DEFAULT_OFFSET, info->dst_pitch_offset);
FINISH_ACCEL();
}
#endif
static void
FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
a->Flags = (PIXMAP_CACHE
| OFFSCREEN_PIXMAPS
| LINEAR_FRAMEBUFFER);
a->Sync = FUNC_NAME(RADEONWaitForIdle);
a->PolyFillRectSolidFlags = 0;
a->SetupForSolidFill
= FUNC_NAME(RADEONSetupForSolidFill);
a->SubsequentSolidFillRect
= FUNC_NAME(RADEONSubsequentSolidFillRect);
a->ScreenToScreenCopyFlags = 0;
a->SetupForScreenToScreenCopy
= FUNC_NAME(RADEONSetupForScreenToScreenCopy);
a->SubsequentScreenToScreenCopy
= FUNC_NAME(RADEONSubsequentScreenToScreenCopy);
a->SetupForMono8x8PatternFill
= FUNC_NAME(RADEONSetupForMono8x8PatternFill);
a->SubsequentMono8x8PatternFillRect
= FUNC_NAME(RADEONSubsequentMono8x8PatternFillRect);
a->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS
| HARDWARE_PATTERN_PROGRAMMED_ORIGIN
| HARDWARE_PATTERN_SCREEN_ORIGIN);
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
if (info->ChipFamily >= CHIP_FAMILY_RV200)
a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_MSBFIRST;
else
a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_LSBFIRST;
#else
a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_LSBFIRST;
#endif
a->ScanlineCPUToScreenColorExpandFillFlags
= (LEFT_EDGE_CLIPPING
| ROP_NEEDS_SOURCE
| LEFT_EDGE_CLIPPING_NEGATIVE_X);
a->NumScanlineColorExpandBuffers = 1;
a->ScanlineColorExpandBuffers = info->scratch_buffer;
info->scratch_save
= xalloc(((pScrn->virtualX+31)/32*4)
+ (pScrn->virtualX * info->CurrentLayout.pixel_bytes));
info->scratch_buffer[0] = info->scratch_save;
a->SetupForScanlineCPUToScreenColorExpandFill
= FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill);
a->SubsequentScanlineCPUToScreenColorExpandFill
= FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill);
a->SubsequentColorExpandScanline = FUNC_NAME(RADEONSubsequentScanline);
a->SetupForSolidLine
= FUNC_NAME(RADEONSetupForSolidLine);
a->SubsequentSolidHorVertLine
= FUNC_NAME(RADEONSubsequentSolidHorVertLine);
#ifdef XFree86LOADER
if (info->xaaReq.minorversion >= 1) {
#endif
a->SolidLineFlags = LINE_LIMIT_COORDS;
a->SolidLineLimits.x1 = 0;
a->SolidLineLimits.y1 = 0;
a->SolidLineLimits.x2 = pScrn->virtualX-1;
a->SolidLineLimits.y2 = pScrn->virtualY-1;
miSetZeroLineBias(pScreen, (OCTANT5 | OCTANT6 | OCTANT7 | OCTANT8));
a->SubsequentSolidTwoPointLine
= FUNC_NAME(RADEONSubsequentSolidTwoPointLine);
if (info->ChipFamily < CHIP_FAMILY_RV200) {
a->SetupForDashedLine
= FUNC_NAME(RADEONSetupForDashedLine);
a->SubsequentDashedTwoPointLine
= FUNC_NAME(RADEONSubsequentDashedTwoPointLine);
a->DashPatternMaxLength = 32;
a->DashedLineFlags = (LINE_PATTERN_LSBFIRST_LSBJUSTIFIED
| LINE_PATTERN_POWER_OF_2_ONLY
| LINE_LIMIT_COORDS
| ROP_NEEDS_SOURCE);
a->DashedLineLimits.x1 = 0;
a->DashedLineLimits.y1 = 0;
a->DashedLineLimits.x2 = pScrn->virtualX-1;
a->DashedLineLimits.y2 = pScrn->virtualY-1;
}
#ifdef XFree86LOADER
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"libxaa too old, can't accelerate TwoPoint lines\n");
}
#endif
a->SetClippingRectangle
= FUNC_NAME(RADEONSetClippingRectangle);
a->DisableClipping
= FUNC_NAME(RADEONDisableClipping);
a->ClippingFlags
= (HARDWARE_CLIP_SOLID_LINE
| HARDWARE_CLIP_DASHED_LINE
| HARDWARE_CLIP_MONO_8x8_FILL
| HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY);
if (xf86IsEntityShared(info->pEnt->index)) {
if (xf86GetNumEntityInstances(info->pEnt->index) > 1)
a->RestoreAccelState = FUNC_NAME(RADEONRestoreAccelState);
}
a->NumScanlineImageWriteBuffers = 1;
a->ScanlineImageWriteBuffers = info->scratch_buffer;
a->SetupForScanlineImageWrite
= FUNC_NAME(RADEONSetupForScanlineImageWrite);
a->SubsequentScanlineImageWriteRect
= FUNC_NAME(RADEONSubsequentScanlineImageWriteRect);
a->SubsequentImageWriteScanline = FUNC_NAME(RADEONSubsequentScanline);
a->ScanlineImageWriteFlags = (CPU_TRANSFER_PAD_DWORD
#ifdef ACCEL_MMIO
| NO_GXCOPY
#endif
| ROP_NEEDS_SOURCE
| SCANLINE_PAD_DWORD
| LEFT_EDGE_CLIPPING
| LEFT_EDGE_CLIPPING_NEGATIVE_X);
#if 0
a->SetupForColor8x8PatternFill
= FUNC_NAME(RADEONSetupForColor8x8PatternFill);
a->SubsequentColor8x8PatternFillRect
= FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect);
a->Color8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_ORIGIN
| HARDWARE_PATTERN_SCREEN_ORIGIN
| BIT_ORDER_IN_BYTE_LSBFIRST);
#endif
}
#undef FUNC_NAME