diff -ruN xf86-video-r128-master.orig/src/Makefile.am xf86-video-r128-master/src/Makefile.am --- xf86-video-r128-master.orig/src/Makefile.am 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/Makefile.am 2012-03-23 15:45:45.857398809 -0700 @@ -36,7 +36,7 @@ r128_drv_la_LDFLAGS = -module -avoid-version r128_drv_ladir = @moduledir@/drivers r128_drv_la_SOURCES = \ - r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \ + r128_accel.c r128_cursor.c r128_dga.c r128_driver.c r128_exa.c \ r128_video.c r128_misc.c r128_probe.c $(R128_DRI_SRCS) EXTRA_DIST = \ diff -ruN xf86-video-r128-master.orig/src/r128.h xf86-video-r128-master/src/r128.h --- xf86-video-r128-master.orig/src/r128.h 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/r128.h 2012-04-12 12:45:34.828284953 -0700 @@ -43,6 +43,9 @@ /* PCI support */ #include "xf86Pci.h" + /* EXA support */ +#include "exa.h" + /* XAA and Cursor Support */ #include "xaa.h" #include "xf86Cursor.h" @@ -77,6 +80,8 @@ #define R128_VBIOS_SIZE 0x00010000 #if R128_DEBUG +#include "r128_version.h" + #define R128TRACE(x) \ do { \ ErrorF("(**) %s(%d): ", R128_NAME, pScrn->scrnIndex); \ @@ -227,6 +232,20 @@ MT_STV } R128MonitorType; +struct r128_2d_state { + Bool in_use; + uint32_t dst_pitch_offset; + uint32_t src_pitch_offset; + uint32_t dp_gui_master_cntl; + uint32_t dp_cntl; + uint32_t dp_write_mask; + uint32_t dp_brush_frgd_clr; + uint32_t dp_brush_bkgd_clr; + uint32_t dp_src_frgd_clr; + uint32_t dp_src_bkgd_clr; + uint32_t default_sc_bottom_right; +}; + typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; @@ -277,6 +296,12 @@ XAAInfoRecPtr accel; Bool accelOn; + + Bool useEXA; + ExaDriverPtr ExaDriver; + XF86ModReqInfo exaReq; + struct r128_2d_state state_2d; + xf86CursorInfoPtr cursor; unsigned long cursor_start; unsigned long cursor_end; @@ -470,6 +495,7 @@ extern void R128WaitForVerticalSync(ScrnInfoPtr pScrn); extern Bool R128AccelInit(ScreenPtr pScreen); +extern Bool R128ExaInit(ScreenPtr pScreen); extern void R128EngineInit(ScrnInfoPtr pScrn); extern Bool R128CursorInit(ScreenPtr pScreen); extern Bool R128DGAInit(ScreenPtr pScreen); @@ -521,6 +547,11 @@ extern void R128CCEWaitForIdle(ScrnInfoPtr pScrn); extern int R128CCEStop(ScrnInfoPtr pScrn); +extern Bool R128GetDatatypeBpp(int bpp, uint32_t *type); +extern Bool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset); +extern void R128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, + uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask); + #define CCE_PACKET0( reg, n ) \ (R128_CCE_PACKET0 | ((n) << 16) | ((reg) >> 2)) diff -ruN xf86-video-r128-master.orig/src/r128_accel.c xf86-video-r128-master/src/r128_accel.c --- xf86-video-r128-master.orig/src/r128_accel.c 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/r128_accel.c 2012-04-12 11:57:12.763405375 -0700 @@ -1045,6 +1045,42 @@ OUTREG(R128_SC_BOTTOM_RIGHT, (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX)); +#ifdef RENDER + if (info->useEXA) { + R128TRACE(("Preparing for compositing\n")); + R128WaitForFifo(pScrn, 6); + OUTREG(R128_SCALE_3D_CNTL, + R128_SCALE_3D_TEXMAP_SHADE | + R128_SCALE_PIX_REPLICATE | + R128_TEX_CACHE_SPLIT | + R128_TEX_MAP_ALPHA_IN_TEXTURE | + R128_TEX_CACHE_LINE_SIZE_4QW); + OUTREG(R128_SETUP_CNTL, + R128_COLOR_SOLID_COLOR | + R128_PRIM_TYPE_TRI | + R128_TEXTURE_ST_MULT_W | + R128_STARTING_VERTEX_1 | + R128_ENDING_VERTEX_3 | + R128_SUB_PIX_4BITS); + OUTREG(R128_PM4_VC_FPU_SETUP, + R128_FRONT_DIR_CCW | + R128_BACKFACE_CULL | + R128_FRONTFACE_SOLID | + R128_FPU_COLOR_SOLID | + R128_FPU_SUB_PIX_4BITS | + R128_FPU_MODE_3D | + R128_TRAP_BITS_DISABLE | + R128_XFACTOR_2 | + R128_YFACTOR_2 | + R128_FLAT_SHADE_VERTEX_OGL | + R128_FPU_ROUND_TRUNCATE | + R128_WM_SEL_8DW); + OUTREG(R128_PLANE_3D_MASK_C, 0xffffffff); + OUTREG(R128_CONSTANT_COLOR_C, 0xff000000); + OUTREG(R128_WINDOW_XY_OFFSET, 0x00000000); + } +#endif + info->dp_gui_master_cntl = ((info->datatype << R128_GMC_DST_DATATYPE_SHIFT) | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS); @@ -1866,8 +1902,30 @@ R128InfoPtr info = R128PTR(pScrn); XAAInfoRecPtr a; - if (!xf86LoadSubModule(pScrn, "xaa")) - return FALSE; + if (info->useEXA) { + int errmaj = 0, errmin = 0; + + info->exaReq.majorversion = EXA_VERSION_MAJOR; + info->exaReq.minorversion = EXA_VERSION_MINOR; + + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Loading EXA module...\n"); + if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &info->exaReq, &errmaj, &errmin)) { + LoaderErrorMsg(NULL, "exa", errmaj, errmin); + return FALSE; + } + + /* Don't init EXA here because it'll be taken care of in mm init */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating EXA driver...\n"); + info->ExaDriver = exaDriverAlloc(); + if (!info->ExaDriver) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Could not allocate EXA driver...\n"); + info->accel = FALSE; + } + + return TRUE; + } else { + if (!xf86LoadSubModule(pScrn, "xaa")) return FALSE; + } if (!(a = info->accel = XAACreateInfoRec())) return FALSE; diff -ruN xf86-video-r128-master.orig/src/r128_cursor.c xf86-video-r128-master/src/r128_cursor.c --- xf86-video-r128-master.orig/src/r128_cursor.c 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/r128_cursor.c 2012-03-23 16:26:27.248487743 -0700 @@ -54,6 +54,9 @@ /* X and server generic header files */ #include "xf86.h" + /* Because for EXA we need to use a different allocator */ +#include "exa.h" + #if X_BYTE_ORDER == X_BIG_ENDIAN #define P_SWAP32( a , b ) \ ((char *)a)[0] = ((char *)b)[3]; \ @@ -253,10 +256,15 @@ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; R128InfoPtr info = R128PTR(pScrn); xf86CursorInfoPtr cursor; - FBAreaPtr fbarea; + FBAreaPtr fbarea = NULL; + ExaOffscreenArea* osArea = NULL; int width; int height; int size; + int cpp = info->CurrentLayout.pixel_bytes; + int width_bytes = (pScrn->displayWidth * + info->CurrentLayout.pixel_bytes); + int x1, x2, y1, y2; if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE; @@ -284,24 +292,37 @@ size = (cursor->MaxWidth/4) * cursor->MaxHeight; width = pScrn->displayWidth; height = (size*2 + 1023) / pScrn->displayWidth; - fbarea = xf86AllocateOffscreenArea(pScreen, - width, - height, - 16, - NULL, - NULL, - NULL); + + if(!info->useEXA) { + fbarea = xf86AllocateOffscreenArea(pScreen, width, height, + 16, NULL, NULL, NULL); + + if (fbarea) { + x1 = fbarea->box.x1; + x2 = fbarea->box.x2; + y1 = fbarea->box.y1; + y2 = fbarea->box.y2; + } + } else { + osArea = exaOffscreenAlloc(pScreen, width * height, 16, + TRUE, NULL, NULL); + + if (osArea) { + x1 = osArea->offset % width_bytes; + x2 = (osArea->offset + osArea->size) % width_bytes; + y1 = osArea->offset / width_bytes; + y2 = (osArea->offset + osArea->size) / width_bytes; + } + } - if (!fbarea) { + if ((!info->useEXA && !fbarea) || (info->useEXA && !osArea)) { info->cursor_start = 0; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Hardware cursor disabled" " due to insufficient offscreen memory\n"); } else { - info->cursor_start = R128_ALIGN((fbarea->box.x1 - + width * fbarea->box.y1) - * info->CurrentLayout.pixel_bytes, 16); - info->cursor_end = info->cursor_start + size; + info->cursor_start = x1 * cpp + y1 * pScrn->virtualX * cpp; + info->cursor_end = x2 * cpp + y2 * pScrn->virtualX * cpp; } R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n", diff -ruN xf86-video-r128-master.orig/src/r128_dri.c xf86-video-r128-master/src/r128_dri.c --- xf86-video-r128-master.orig/src/r128_dri.c 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/r128_dri.c 2012-04-11 20:28:05.047089779 -0700 @@ -305,6 +305,7 @@ R128InfoPtr info = R128PTR(pScrn); if (info->accel) info->accel->NeedToSync = TRUE; + if (info->ExaDriver) exaMarkSync(pScreen); } /* Called when the X server goes to sleep to allow the X server's @@ -1389,6 +1390,7 @@ R128InfoPtr info = R128PTR(pScrn); int i; R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + PixmapPtr pPix = pScrn->pScreen->GetScreenPixmap(pScrn->pScreen); /* Don't want to do this when no 3d is active and pages are * right-way-round @@ -1396,20 +1398,35 @@ if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) return; - (*info->accel->SetupForScreenToScreenCopy)(pScrn, + if (!info->useEXA) { + (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, (CARD32)(-1), -1); + } else { + CARD32 src_pitch_offset, dst_pitch_offset, datatype; + + R128GetPixmapOffsetPitch(pPix, &src_pitch_offset); + dst_pitch_offset = src_pitch_offset + (info->backOffset >> 5); + R128GetDatatypeBpp(pScrn->bitsPerPixel, &datatype); + info->xdir = info->ydir = 1; + + R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, GXcopy, ~0); + } for (i = 0 ; i < num ; i++, pbox++) { int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1); int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1); if (xa <= xb && ya <= yb) { - (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, + if (!info->useEXA) { + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, xa + info->backX, ya + info->backY, xb - xa + 1, yb - ya + 1); + } else { + (*info->ExaDriver->Copy)(pPix, xa, ya, xa, ya, xb - xa + 1, yb - ya + 1); + } } } } @@ -1419,20 +1436,34 @@ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; R128InfoPtr info = R128PTR(pScrn); R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); - + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); + if (info->allowPageFlip) { /* Duplicate the frontbuffer to the backbuffer */ - (*info->accel->SetupForScreenToScreenCopy)(pScrn, + if (!info->useEXA) { + (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, (CARD32)(-1), -1); - (*info->accel->SubsequentScreenToScreenCopy)(pScrn, + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, 0, 0, info->backX, info->backY, pScrn->virtualX, pScrn->virtualY); + } else { + CARD32 src_pitch_offset, dst_pitch_offset, datatype; + + R128GetPixmapOffsetPitch(pPix, &src_pitch_offset); + dst_pitch_offset = src_pitch_offset + (info->backOffset >> 5); + R128GetDatatypeBpp(pScrn->bitsPerPixel, &datatype); + info->xdir = info->ydir = 1; + + R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, GXcopy, ~0); + + (*info->ExaDriver->Copy)(pPix, 0, 0, 0, 0, pScrn->virtualX, pScrn->virtualY); + } pSAREAPriv->pfAllowPageFlip = 1; } @@ -1471,6 +1502,8 @@ if (info->cursor_start) xf86ForceHWCursor(pScreen, TRUE); + + if (info->ExaDriver) exaMarkSync(pScreen); } static void R128DRITransitionTo2d(ScreenPtr pScreen) diff -ruN xf86-video-r128-master.orig/src/r128_driver.c xf86-video-r128-master/src/r128_driver.c --- xf86-video-r128-master.orig/src/r128_driver.c 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/r128_driver.c 2012-04-10 17:23:47.297678912 -0700 @@ -156,7 +156,8 @@ OPTION_FBDEV, OPTION_VIDEO_KEY, OPTION_SHOW_CACHE, - OPTION_VGA_ACCESS + OPTION_VGA_ACCESS, + OPTION_ACCELMETHOD } R128Opts; static const OptionInfoRec R128Options[] = { @@ -184,6 +185,7 @@ { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, { OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VGA_ACCESS, "VGAAccess", OPTV_BOOLEAN, {0}, TRUE }, + { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -2185,6 +2187,47 @@ } } +Bool R128VerboseInitEXA(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + xf86DrvMsg(scrnIndex, X_INFO, "Going to init EXA...\n"); + + if (R128EXAInit(pScreen)) { + xf86DrvMsg(scrnIndex, X_INFO, "EXA Acceleration enabled\n"); + info->accelOn = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_ERROR, + "EXA Acceleration initialization failed\n"); + xf86DrvMsg(scrnIndex, X_INFO, "EXA Acceleration disabled\n"); + info->accelOn = FALSE; + + return FALSE; + } +} + +void R128VerboseInitAccel(Bool noAccel, int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + if (!noAccel) { + if (R128AccelInit(pScreen)) { + xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); + info->accelOn = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_ERROR, + "Acceleration initialization failed\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); + info->accelOn = FALSE; + } + } else { + xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); + info->accelOn = FALSE; + } +} + /* Called at the start of each server generation. */ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) @@ -2192,8 +2235,23 @@ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; R128InfoPtr info = R128PTR(pScrn); BoxRec MemBox; - int y2; + int width_bytes = (pScrn->displayWidth * + info->CurrentLayout.pixel_bytes); + int x1, x2, y1, y2; Bool noAccel; + ExaOffscreenArea* osArea; + char *optstr; + + info->useEXA = FALSE; + + optstr = (char *)xf86GetOptValString(info->Options, OPTION_ACCELMETHOD); + if (optstr != NULL) { + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"AccelMethod option found\n"); + if (xf86NameCmp(optstr, "EXA") == 0) { + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"AccelMethod is set to EXA, turning EXA on\n"); + info->useEXA = TRUE; + } + } R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset)); @@ -2221,7 +2279,7 @@ } else { if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; } - + R128SaveScreen(pScreen, SCREEN_SAVER_ON); pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); @@ -2245,8 +2303,6 @@ /* FIXME: When we move to dynamic allocation of back and depth buffers, we will want to revisit the following check for 3 times the virtual size of the screen below. */ - int width_bytes = (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes); int maxy = info->FbMapSize / width_bytes; if (noAccel) { @@ -2323,8 +2379,6 @@ #ifdef R128DRI if (info->directRenderingEnabled) { FBAreaPtr fbarea; - int width_bytes = (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes); int cpp = info->CurrentLayout.pixel_bytes; int bufferSize = pScrn->virtualY * width_bytes; int l, total; @@ -2387,7 +2441,7 @@ info->textureOffset = 0; info->textureSize = 0; } - + total = info->FbMapSize - info->textureSize; scanlines = total / width_bytes; if (scanlines > 8191) scanlines = 8191; @@ -2402,50 +2456,95 @@ MemBox.x2 = pScrn->displayWidth; MemBox.y2 = scanlines; - if (!xf86InitFBManager(pScreen, &MemBox)) { - xf86DrvMsg(scrnIndex, X_ERROR, - "Memory manager initialization to (%d,%d) (%d,%d) failed\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - return FALSE; - } else { - int width, height; - - xf86DrvMsg(scrnIndex, X_INFO, - "Memory manager initialized to (%d,%d) (%d,%d)\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - if ((fbarea = xf86AllocateOffscreenArea(pScreen, - pScrn->displayWidth, - 2, 0, NULL, NULL, NULL))) { - xf86DrvMsg(scrnIndex, X_INFO, - "Reserved area from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); + if (!info->useEXA) { + if (!xf86InitFBManager(pScreen, &MemBox)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Memory manager initialization to (%d,%d) (%d,%d) failed\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + return FALSE; } else { - xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); + int width, height; + + xf86DrvMsg(scrnIndex, X_INFO, + "Memory manager initialized to (%d,%d) (%d,%d)\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, + 2, 0, NULL, NULL, NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved area from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); + } + if (xf86QueryLargestOffscreenArea(pScreen, &width, + &height, 0, 0, 0)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + } + + R128VerboseInitAccel(noAccel, scrnIndex, pScreen); } - if (xf86QueryLargestOffscreenArea(pScreen, &width, - &height, 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Filling in EXA memory info\n"); + + R128VerboseInitAccel(noAccel, scrnIndex, pScreen); + info->ExaDriver->offScreenBase = pScrn->virtualY * width_bytes; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Filled in offs\n"); + + /* Don't give EXA the true full memory size, because the + textureSize sized chunk on the end is handled by DRI */ + info->ExaDriver->memorySize = total; + + R128VerboseInitEXA(scrnIndex, pScreen); + } + + /* Allocate the shared back buffer */ + if(!info->useEXA) { + fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->virtualX, + pScrn->virtualY, + 32, NULL, NULL, NULL); + + if (fbarea) { + x1 = fbarea->box.x1; + x2 = fbarea->box.x2; + y1 = fbarea->box.y1; + y2 = fbarea->box.y2; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Actually trying an EXA allocation...\n"); + osArea = exaOffscreenAlloc(pScreen, + pScrn->virtualX * pScrn->virtualY, + 32, TRUE, NULL, NULL); + + if (osArea) { + x1 = osArea->offset % width_bytes; + x2 = (osArea->offset + osArea->size) % width_bytes; + y1 = osArea->offset / width_bytes; + y2 = (osArea->offset + osArea->size) / width_bytes; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Went swimmingly...\n"); } } + + if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) { + /* info->backOffset = y1 * width_bytes + x1 * cpp; */ + info->backOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16); + info->backX = info->backOffset % width_bytes; + info->backY = info->backOffset / width_bytes; + info->backPitch = pScrn->displayWidth; - /* Allocate the shared back buffer */ - if ((fbarea = xf86AllocateOffscreenArea(pScreen, - pScrn->virtualX, - pScrn->virtualY, - 32, NULL, NULL, NULL))) { xf86DrvMsg(scrnIndex, X_INFO, - "Reserved back buffer from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); - - info->backX = fbarea->box.x1; - info->backY = fbarea->box.y1; - info->backOffset = (fbarea->box.y1 * width_bytes + - fbarea->box.x1 * cpp); - info->backPitch = pScrn->displayWidth; + "Reserved back buffer from (%d,%d) to (%d,%d) offset: %x\n", + x1, y1, + x2, y2, info->backOffset); } else { xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n"); info->backX = -1; @@ -2455,25 +2554,46 @@ } /* Allocate the shared depth buffer */ - if ((fbarea = xf86AllocateOffscreenArea(pScreen, - pScrn->virtualX, - pScrn->virtualY + 1, - 32, NULL, NULL, NULL))) { - xf86DrvMsg(scrnIndex, X_INFO, - "Reserved depth buffer from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); - - info->depthX = fbarea->box.x1; - info->depthY = fbarea->box.y1; - info->depthOffset = (fbarea->box.y1 * width_bytes + - fbarea->box.x1 * cpp); + if(!info->useEXA) { + fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->virtualX, + pScrn->virtualY + 1, + 32, NULL, NULL, NULL); + if (fbarea) { + x1 = fbarea->box.x1; + x2 = fbarea->box.x2; + y1 = fbarea->box.y1; + y2 = fbarea->box.y2; + } + } else { + osArea = exaOffscreenAlloc(pScreen, + pScrn->virtualX * (pScrn->virtualY+1), + 32, TRUE, NULL, NULL); + + if (osArea) { + x1 = osArea->offset % width_bytes; + x2 = (osArea->offset + osArea->size) % width_bytes; + y1 = osArea->offset / width_bytes; + y2 = (osArea->offset + osArea->size) / width_bytes; + } + } + + if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) { + /* info->depthOffset = y1 * width_bytes + x1 * cpp; */ + info->depthOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16); + info->depthX = info->depthOffset % width_bytes; + info->depthY = info->depthOffset / width_bytes; info->depthPitch = pScrn->displayWidth; - info->spanOffset = ((fbarea->box.y2 - 1) * width_bytes + - fbarea->box.x1 * cpp); + info->spanOffset = (y2 - 1) * width_bytes + x1 * cpp; + + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved depth buffer from (%d,%d) to (%d,%d) offset: %x\n", + x1, y1, + x2, y2, info->depthOffset); + xf86DrvMsg(scrnIndex, X_INFO, "Reserved depth span from (%d,%d) offset 0x%x\n", - fbarea->box.x1, fbarea->box.y2 - 1, info->spanOffset); + x1, y2 - 1, info->spanOffset); } else { xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n"); info->depthX = -1; @@ -2502,50 +2622,48 @@ if (y2 > 8191) y2 = 8191; MemBox.y2 = y2; - if (!xf86InitFBManager(pScreen, &MemBox)) { - xf86DrvMsg(scrnIndex, X_ERROR, - "Memory manager initialization to (%d,%d) (%d,%d) failed\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - return FALSE; - } else { - int width, height; - FBAreaPtr fbarea; - - xf86DrvMsg(scrnIndex, X_INFO, - "Memory manager initialized to (%d,%d) (%d,%d)\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, - 2, 0, NULL, NULL, NULL))) { - xf86DrvMsg(scrnIndex, X_INFO, - "Reserved area from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); + if (!info->useEXA) { + if (!xf86InitFBManager(pScreen, &MemBox)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Memory manager initialization to (%d,%d) (%d,%d) failed\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + return FALSE; } else { - xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); - } - if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, - 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); - } - } - } + int width, height; + FBAreaPtr fbarea; - /* Acceleration setup */ - if (!noAccel) { - if (R128AccelInit(pScreen)) { - xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); - info->accelOn = TRUE; + xf86DrvMsg(scrnIndex, X_INFO, + "Memory manager initialized to (%d,%d) (%d,%d)\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 2, 0, NULL, NULL, NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved area from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); + } + if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + } + + R128VerboseInitAccel(noAccel, scrnIndex, pScreen); + } } else { - xf86DrvMsg(scrnIndex, X_ERROR, - "Acceleration initialization failed\n"); - xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); - info->accelOn = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Filling in EXA memory info\n"); + + R128VerboseInitAccel(noAccel, scrnIndex, pScreen); + info->ExaDriver->offScreenBase = width_bytes * pScrn->virtualY; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Filled in offs\n"); + + info->ExaDriver->memorySize = info->FbMapSize; + R128VerboseInitEXA(scrnIndex, pScreen); } - } else { - xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); - info->accelOn = FALSE; } /* DGA setup */ @@ -2897,16 +3015,6 @@ | R128_P2PLL_ATOMIC_UPDATE_EN | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); - R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", - restore->p2pll_ref_div, - restore->p2pll_div_0, - restore->htotal_cntl2, - INPLL(pScrn, RADEON_P2PLL_CNTL))); - R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", - restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, - restore->p2pll_div_0 & RADEON_P2PLL_FB3_DIV_MASK, - (restore->p2pll_div_0 & RADEON_P2PLL_POST3_DIV_MASK) >>16)); - usleep(5000); /* Let the clock to lock */ OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, @@ -3793,12 +3901,6 @@ pll->reference_freq); save->post_div_2 = post_div->divider; - R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", - save->dot_clock_freq_2, - save->pll_output_freq_2, - save->feedback_div_2, - save->post_div_2)); - save->p2pll_ref_div = pll->reference_div; save->p2pll_div_0 = (save->feedback_div_2 | (post_div->bitvalue<<16)); save->htotal_cntl2 = 0; @@ -4299,8 +4401,15 @@ R128UnmapMem(pScrn); } - if (info->accel) XAADestroyInfoRec(info->accel); - info->accel = NULL; + if (info->accel) { + if (info->useEXA) { + exaDriverFini(pScreen); + free(info->ExaDriver); + } else { + XAADestroyInfoRec(info->accel); + } + info->accel = NULL; + } if (info->scratch_save) free(info->scratch_save); info->scratch_save = NULL; diff -ruN xf86-video-r128-master.orig/src/r128_exa.c xf86-video-r128-master/src/r128_exa.c --- xf86-video-r128-master.orig/src/r128_exa.c 1969-12-31 16:00:00.000000000 -0800 +++ xf86-video-r128-master/src/r128_exa.c 2012-04-12 13:38:22.133933258 -0700 @@ -0,0 +1,1158 @@ +/* Based on work by Eric Anholt in 2004 and Joseph Garvin in 2006. + * Put together by Connor Behan in 2012. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "r128.h" +#include "exa.h" + +#include "r128_reg.h" + +#include "xf86.h" + +static struct { + int rop; + int pattern; +} R128_ROP[] = { + { R128_ROP3_ZERO, R128_ROP3_ZERO }, /* GXclear */ + { R128_ROP3_DSa, R128_ROP3_DPa }, /* Gxand */ + { R128_ROP3_SDna, R128_ROP3_PDna }, /* GXandReverse */ + { R128_ROP3_S, R128_ROP3_P }, /* GXcopy */ + { R128_ROP3_DSna, R128_ROP3_DPna }, /* GXandInverted */ + { R128_ROP3_D, R128_ROP3_D }, /* GXnoop */ + { R128_ROP3_DSx, R128_ROP3_DPx }, /* GXxor */ + { R128_ROP3_DSo, R128_ROP3_DPo }, /* GXor */ + { R128_ROP3_DSon, R128_ROP3_DPon }, /* GXnor */ + { R128_ROP3_DSxn, R128_ROP3_PDxn }, /* GXequiv */ + { R128_ROP3_Dn, R128_ROP3_Dn }, /* GXinvert */ + { R128_ROP3_SDno, R128_ROP3_PDno }, /* GXorReverse */ + { R128_ROP3_Sn, R128_ROP3_Pn }, /* GXcopyInverted */ + { R128_ROP3_DSno, R128_ROP3_DPno }, /* GXorInverted */ + { R128_ROP3_DSan, R128_ROP3_DPan }, /* GXnand */ + { R128_ROP3_ONE, R128_ROP3_ONE } /* GXset */ +}; + +#ifdef RENDER +static struct { + Bool dst_alpha; + Bool src_alpha; + CARD32 blendctl; +} R128BlendOp[] = { + /* Clear */ + {0, 0, R128_SBLEND_ZERO | R128_DBLEND_ZERO}, + /* Src */ + {0, 0, R128_SBLEND_ONE | R128_DBLEND_ZERO}, + /* Dst */ + {0, 0, R128_SBLEND_ZERO | R128_DBLEND_ONE}, + /* Over */ + {0, 1, R128_SBLEND_ONE | R128_DBLEND_INV_SRC_ALPHA}, + /* OverReverse */ + {1, 0, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_ONE}, + /* In */ + {1, 0, R128_SBLEND_DST_ALPHA | R128_DBLEND_ZERO}, + /* InReverse */ + {0, 1, R128_SBLEND_ZERO | R128_DBLEND_SRC_ALPHA}, + /* Out */ + {1, 0, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_ZERO}, + /* OutReverse */ + {0, 1, R128_SBLEND_ZERO | R128_DBLEND_INV_SRC_ALPHA}, + /* Atop */ + {1, 1, R128_SBLEND_DST_ALPHA | R128_DBLEND_INV_SRC_ALPHA}, + /* AtopReverse */ + {1, 1, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_SRC_ALPHA}, + /* Xor */ + {1, 1, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_INV_SRC_ALPHA}, + /* Add */ + {0, 0, R128_SBLEND_ONE | R128_DBLEND_ONE}, +}; + +static int widths[2] = {1,1}; +static int heights[2] = {1,1}; +static Bool is_transform[2]; +static PictTransform *transform[2]; + +typedef union { float f; CARD32 i; } fi_type; + +/* If it was okay to not be paranoid about a simple cast, I guess they wouldn't have made this. */ +static inline CARD32 +R128FloatAsInt(float val) +{ + fi_type fi; + + fi.f = val; + return fi.i; +} + +#define VTX_RING_COUNT 8 + +#define VTX_OUT(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY) \ +do { \ + OUTREG(0, R128FloatAsInt(_dstX)); \ + OUTREG(0, R128FloatAsInt(((float)(_dstY)) + 0.125)); \ + OUTREG(0, R128FloatAsInt(0.0)); \ + OUTREG(0, R128FloatAsInt(1.0)); \ + OUTREG(0, R128FloatAsInt((((float)(_srcX)) + 0.5) / (widths[0]))); \ + OUTREG(0, R128FloatAsInt((((float)(_srcY)) + 0.5) / (heights[0]))); \ + OUTREG(0, R128FloatAsInt((((float)(_maskX)) + 0.5) / (widths[1]))); \ + OUTREG(0, R128FloatAsInt((((float)(_maskY)) + 0.5) / (heights[1])));\ +} while (0) + +#define VTX_CCE_OUT(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY) \ +do { \ + OUT_RING(R128FloatAsInt(_dstX)); \ + OUT_RING(R128FloatAsInt(((float)(_dstY)) + 0.125)); \ + OUT_RING(R128FloatAsInt(0.0)); \ + OUT_RING(R128FloatAsInt(1.0)); \ + OUT_RING(R128FloatAsInt((((float)(_srcX)) + 0.5) / (widths[0]))); \ + OUT_RING(R128FloatAsInt((((float)(_srcY)) + 0.5) / (heights[0]))); \ + OUT_RING(R128FloatAsInt((((float)(_maskX)) + 0.5) / (widths[1]))); \ + OUT_RING(R128FloatAsInt((((float)(_maskY)) + 0.5) / (heights[1]))); \ +} while (0) + +static Bool +R128TransformAffineOrScaled(PictTransformPtr t) +{ + if (t == NULL) return TRUE; + + /* the shaders don't handle scaling either */ + return t->matrix[2][0] == 0 && t->matrix[2][1] == 0 && t->matrix[2][2] == IntToxFixed(1); +} + +/* Sometimes one list is supported, sometimes the other list is */ +static Bool +R128GetDatatypePict1(uint32_t format, uint32_t *type) +{ + switch(format) { + case PICT_r5g6b5: + *type = R128_DATATYPE_RGB565; + return TRUE; + case PICT_a1r5g5b5: + case PICT_x1r5g5b5: + *type = R128_DATATYPE_ARGB1555; + return TRUE; + case PICT_x8r8g8b8: + *type = R128_DATATYPE_ARGB8888; + return TRUE; + default: + return FALSE; + } +} + +static Bool +R128GetDatatypePict2(uint32_t format, uint32_t *type) +{ + switch(format) { + case PICT_r5g6b5: + *type = R128_DATATYPE_RGB565; + return TRUE; + case PICT_a1r5g5b5: + *type = R128_DATATYPE_ARGB1555; + return TRUE; + case PICT_a4r4g4b4: + *type = R128_DATATYPE_ARGB4444; + return TRUE; + default: + return FALSE; + } +} +#endif + +/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we + * require src and dest datatypes to be equal. + */ +Bool R128GetDatatypeBpp(int bpp, uint32_t *type) +{ + switch (bpp) { + case 8: + *type = R128_DATATYPE_CI8; + return TRUE; + case 16: + *type = R128_DATATYPE_RGB565; + return TRUE; + case 24: + *type = R128_DATATYPE_CI8; + return TRUE; + case 32: + *type = R128_DATATYPE_ARGB8888; + return TRUE; + default: + return FALSE; + } +} + +static Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, + unsigned int offset, unsigned int pitch) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) { + R128TRACE(("Bad pitch 0x%08x\n", pitch)); + return FALSE; + } + + if (offset % info->ExaDriver->pixmapOffsetAlign != 0) { + R128TRACE(("Bad offset 0x%08x\n", offset)); + return FALSE; + } + + *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5); + + return TRUE; +} + +Bool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) +{ + uint32_t pitch, offset; + int bpp; + + bpp = pPix->drawable.bitsPerPixel; + if (bpp == 24) + bpp = 8; + + offset = exaGetPixmapOffset(pPix); + pitch = exaGetPixmapPitch(pPix); + + return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); +} + +static void Emit2DState(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + int has_src = info->state_2d.src_pitch_offset; + unsigned char *R128MMIO = info->MMIO; + + R128WaitForFifo(pScrn, (has_src ? 10 : 9)); + + OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right); + OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl); + OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr); + OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr); + OUTREG(R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr); + OUTREG(R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr); + OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask); + OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl); + + OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); + if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset); +} + +static void EmitCCE2DState(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + int has_src = info->state_2d.src_pitch_offset; + RING_LOCALS; + + R128CCE_REFRESH( pScrn, info ); + + BEGIN_RING( (has_src ? 20 : 18) ); + + OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right ); + OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl ); + OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr ); + OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr ); + OUT_RING_REG( R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr ); + OUT_RING_REG( R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr ); + OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask ); + OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl ); + + OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset ); + if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset ); + + ADVANCE_RING(); +} + +/* EXA Callbacks */ + +static Bool +R128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + int bpp = pPixmap->drawable.bitsPerPixel; + uint32_t datatype, dst_pitch_offset; + + if (!R128GetDatatypeBpp(bpp, &datatype)) { + R128TRACE(("R128GetDatatypeBpp failed\n")); + return FALSE; + } + if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) { + R128TRACE(("R128GetPixmapOffsetPitch failed\n")); + return FALSE; + } + if (info->state_2d.in_use) return FALSE; + + info->state_2d.in_use = TRUE; + info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX); + info->state_2d.dp_brush_bkgd_clr = 0x00000000; + info->state_2d.dp_src_frgd_clr = 0xffffffff; + info->state_2d.dp_src_bkgd_clr = 0x00000000; + info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + (datatype >> 8) | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP[alu].pattern | + R128_GMC_CLR_CMP_CNTL_DIS); + info->state_2d.dp_brush_frgd_clr = fg; + info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM); + info->state_2d.dp_write_mask = planemask; + info->state_2d.dst_pitch_offset = dst_pitch_offset; + info->state_2d.src_pitch_offset = 0; + +#ifdef R128DRI + if (info->directRenderingEnabled) { + EmitCCE2DState(pScrn); + } else +#endif + { + Emit2DState(pScrn); + } + return TRUE; +} + +static void +R128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + R128WaitForFifo(pScrn, 2); + OUTREG(R128_DST_Y_X, (y1 << 16) | x1); + OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1)); +} + +#define R128DoneSolid R128Done + +void +R128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, + uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask) +{ + R128InfoPtr info = R128PTR(pScrn); + + info->state_2d.in_use = TRUE; + info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_SRC_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_NONE | + (datatype >> 8) | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP[alu].rop | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_CLR_CMP_CNTL_DIS); + info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) | + (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0)); + info->state_2d.dp_brush_frgd_clr = 0xffffffff; + info->state_2d.dp_brush_bkgd_clr = 0x00000000; + info->state_2d.dp_src_frgd_clr = 0xffffffff; + info->state_2d.dp_src_bkgd_clr = 0x00000000; + info->state_2d.dp_write_mask = planemask; + info->state_2d.dst_pitch_offset = dst_pitch_offset; + info->state_2d.src_pitch_offset = src_pitch_offset; + info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX); + +#ifdef R128DRI + if (info->directRenderingEnabled) { + EmitCCE2DState(pScrn); + } else +#endif + { + Emit2DState(pScrn); + } +} + +static Bool +R128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask) +{ + ScreenPtr pScreen = pSrcPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + int bpp = pDstPixmap->drawable.bitsPerPixel; + uint32_t datatype, src_pitch_offset, dst_pitch_offset; + + if (!R128GetDatatypeBpp(bpp, &datatype)) { + R128TRACE(("R128GetDatatypeBpp failed\n")); + return FALSE; + } + if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) { + R128TRACE(("R128GetPixmapOffsetPitch source failed\n")); + return FALSE; + } + if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) { + R128TRACE(("R128GetPixmapOffsetPitch dest failed\n")); + return FALSE; + } + if (info->state_2d.in_use) return FALSE; + + info->xdir = xdir; + info->ydir = ydir; + + R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask); + + return TRUE; +} + +static void +R128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) +{ + ScreenPtr pScreen = pDstPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + if (info->xdir < 0) srcX += width - 1, dstX += width - 1; + if (info->ydir < 0) srcY += height - 1, dstY += height - 1; + + R128WaitForFifo(pScrn, 3); + OUTREG(R128_SRC_Y_X, (srcY << 16) | srcX); + OUTREG(R128_DST_Y_X, (dstY << 16) | dstX); + OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width); +} + +#define R128DoneCopy R128Done + +#ifdef RENDER +static Bool +R128CheckCompositeTexture(PicturePtr pPict, PicturePtr pDstPict, int op) +{ + ScreenPtr pScreen = pPict->pDrawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone; + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + uint32_t tmp1; + + if (!R128GetDatatypePict2(pDstPict->format, &tmp1)) return FALSE; + + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) { + R128TRACE(("NPOT repeat unsupported (%dx%d)\n", w, h)); + return FALSE; + } + if (pPict->filter != PictFilterNearest && pPict->filter != PictFilterBilinear) { + R128TRACE(("Unsupported filter 0x%x\n", pPict->filter)); + return FALSE; + } + + /* The radeon driver has a long explanation about this part that I don't really understand */ + if (pPict->transform != 0 && repeatType == RepeatNone && PICT_FORMAT_A(pPict->format) == 0) { + if (!(((op == PictOpSrc) || (op == PictOpClear)) && (PICT_FORMAT_A(pDstPict->format) == 0))) { + R128TRACE(("REPEAT_NONE unsupported for transformed xRGB source\n")); + return FALSE; + } + } + if (!R128TransformAffineOrScaled(pPict->transform)) { + R128TRACE(("Non-affine transforms not supported\n")); + return FALSE; + } + + return TRUE; +} + +static Bool +R128CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) +{ + ScreenPtr pScreen = pSrcPicture->pDrawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + uint32_t tmp1; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(R128BlendOp) / sizeof(R128BlendOp[0])) { + R128TRACE(("Unsupported Composite op 0x%x\n", op)); + return FALSE; + } + if (!pSrcPicture->pDrawable) { + R128TRACE(("Solid or gradient pictures not supported yet\n")); + return FALSE; + } + + if (pDstPicture->format == PICT_a8) { + if (R128BlendOp[op].src_alpha || R128BlendOp[op].dst_alpha || pMaskPicture != NULL) { + R128TRACE(("Alpha blending unsupported with A8 dst?\n")); + return FALSE; + } + } else { + if (!R128GetDatatypePict1(pDstPicture->format, &tmp1)) return FALSE; + } + + if (pMaskPicture) { + if (!pMaskPicture->pDrawable) { + R128TRACE(("Solid or gradient pictures not supported yet\n")); + return FALSE; + } + if (pMaskPicture->componentAlpha && R128BlendOp[op].src_alpha) { + R128TRACE(("Component alpha not supported with source alpha blending\n")); + return FALSE; + } + + if (!R128CheckCompositeTexture(pMaskPicture, pDstPicture, op)) return FALSE; + } + + if (!R128CheckCompositeTexture(pSrcPicture, pDstPicture, op)) return FALSE; + + return TRUE; +} + +static Bool +R128TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit, uint32_t *txsize, uint32_t *tex_cntl_c) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int bytepp, shift, l2w, l2h, l2p, pitch; + + pitch = pPix->devKind; + if ((pitch & (pitch - 1)) != 0) { + R128TRACE(("NPOT pitch 0x%x unsupported\n", pitch)); + return FALSE; + } + + if (!R128GetDatatypePict2(pPict->format, tex_cntl_c)) return FALSE; + + bytepp = PICT_FORMAT_BPP(pPict->format) / 8; + + *tex_cntl_c |= R128_MIP_MAP_DISABLE; + + if (pPict->filter == PictFilterBilinear) { + *tex_cntl_c |= R128_MIN_BLEND_LINEAR | R128_MAG_BLEND_LINEAR; + } else if (pPict->filter == PictFilterNearest) { + *tex_cntl_c |= R128_MIN_BLEND_NEAREST | R128_MAG_BLEND_NEAREST; + } else { + R128TRACE(("Bad filter 0x%x\n", pPict->filter)); + return FALSE; + } + + if (unit == 0) + shift = 0; + else { + shift = 16; + *tex_cntl_c |= R128_SEC_SELECT_SEC_ST; + } + + /* R128MinBits returns -1 for value of 0 */ + l2w = R128MinBits(w - 1) + 1; + l2h = R128MinBits(h - 1) + 1; + l2p = R128MinBits(pPix->devKind / bytepp); + + if (pPict->repeat && w == 1 && h == 1) + l2p = 0; + else if (pPict->repeat && l2p != l2w) { + R128TRACE(("Repeat not supported for pitch != width\n")); + return FALSE; + } + l2w = l2p; + + widths[unit] = 1 << l2w; + heights[unit] = 1 << l2h; + *txsize |= l2p << (R128_TEX_PITCH_SHIFT + shift); + *txsize |= ((l2w > l2h) ? l2w : l2h) << (R128_TEX_SIZE_SHIFT + shift); + *txsize |= l2h << (R128_TEX_HEIGHT_SHIFT + shift); + + if (pPict->transform != 0) { + is_transform[unit] = TRUE; + transform[unit] = pPict->transform; + } else { + is_transform[unit] = FALSE; + } + + return TRUE; +} + +static Bool +R128PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + ScreenPtr pScreen = pSrc->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + uint32_t txsize = 0, prim_tex_cntl_c, sec_tex_cntl_c = 0, dstDatatype; + uint32_t dst_pitch_offset, color_factor, in_color_factor, alpha_comb; + uint32_t blend_cntl; + int i; + + if (pDstPicture->format == PICT_a8) { + if (R128BlendOp[op].dst_alpha) { + R128TRACE(("Can't dst alpha blend A8\n")); + return FALSE; + } + dstDatatype = R128_DATATYPE_Y8; + } else { + if (!R128GetDatatypePict1(pDstPicture->format, &dstDatatype)) return FALSE; + } + + if (!R128TextureSetup(pSrcPicture, pSrc, 0, &txsize, &prim_tex_cntl_c)) return FALSE; + + if (pMask != NULL) { + if (!R128TextureSetup(pMaskPicture, pMask, 1, &txsize, &sec_tex_cntl_c)) return FALSE; + } else { + is_transform[1] = FALSE; + } + + if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) return FALSE; + + info->state_2d.in_use = TRUE; + blend_cntl = R128BlendOp[op].blendctl; + if (PICT_FORMAT_A(pDstPicture->format) == 0 && R128BlendOp[op].dst_alpha) { + if ((blend_cntl & R128_SBLEND_MASK) == R128_SBLEND_DST_ALPHA) + blend_cntl = (blend_cntl & ~R128_SBLEND_MASK) | R128_SBLEND_ONE; + else if ((blend_cntl & R128_SBLEND_MASK) == R128_SBLEND_INV_DST_ALPHA) + blend_cntl = (blend_cntl & ~R128_SBLEND_MASK) | R128_SBLEND_ZERO; + } + + R128WaitForFifo(pScrn, 21); + + OUTREG(R128_SCALE_3D_CNTL, + R128_SCALE_3D_TEXMAP_SHADE | + R128_SCALE_PIX_REPLICATE | + R128_TEX_CACHE_SPLIT | + R128_TEX_MAP_ALPHA_IN_TEXTURE | + R128_TEX_CACHE_LINE_SIZE_4QW); + OUTREG(R128_DST_PITCH_OFFSET, dst_pitch_offset); + OUTREG(R128_DP_GUI_MASTER_CNTL, + R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + (dstDatatype >> 8) | + R128_GMC_SRC_DATATYPE_COLOR | + (R128_ROP[3].rop << 16) | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_3D_FCN_EN | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS | + R128_GMC_WR_MSK_DIS); + OUTREG(R128_MISC_3D_STATE_CNTL_REG, + R128_MISC_SCALE_3D_TEXMAP_SHADE | + R128_MISC_SCALE_PIX_REPLICATE | + R128_ALPHA_COMB_ADD_CLAMP | + blend_cntl); + OUTREG(R128_TEX_CNTL_C, + R128_TEXMAP_ENABLE | + ((pMask != NULL) ? R128_SEC_TEXMAP_ENABLE : 0) | + R128_ALPHA_ENABLE | + R128_TEX_CACHE_FLUSH); + OUTREG(R128_PC_GUI_CTLSTAT, R128_PC_FLUSH_GUI); + + /* IN operator: Without a mask, only the first texture unit is enabled. + * With a mask, we put the source in the first unit and have it pass + * through as input to the 2nd. The 2nd unit takes the incoming source + * pixel and modulates it with either the alpha or each of the channels + * in the mask, depending on componentAlpha. + */ + OUTREG(0, CCE_PACKET0(R128_PRIM_TEX_CNTL_C, 13)); + OUTREG(0, prim_tex_cntl_c); + + /* If this is the only stage and the dest is a8, route the alpha result + * to the color (red channel, in particular), too. Otherwise, be sure + * to zero out color channels of an a8 source. + */ + if (pMaskPicture == NULL && pDstPicture->format == PICT_a8) + color_factor = R128_COLOR_FACTOR_ALPHA; + else if (pSrcPicture->format == PICT_a8) + color_factor = R128_COLOR_FACTOR_CONST_COLOR; + else + color_factor = R128_COLOR_FACTOR_TEX; + + if (PICT_FORMAT_A(pSrcPicture->format) == 0) + alpha_comb = R128_COMB_ALPHA_COPY_INP; + else + alpha_comb = R128_COMB_ALPHA_DIS; + + OUTREG(0, R128_COMB_COPY | + color_factor | + R128_INPUT_FACTOR_INT_COLOR | + alpha_comb | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_CONST_ALPHA); + OUTREG(0, txsize); + /* We could save some output by only writing the offset register that + * will actually be used. On the other hand, this is easy. + */ + for (i = 0; i <= 10; i++) + OUTREG(0, ((CARD8 *)pSrc->devPrivate.ptr - info->ExaDriver->memoryBase)); + + if (pMask != NULL) { + R128WaitForFifo(pScrn, 14); + + OUTREG(0, CCE_PACKET0(R128_SEC_TEX_CNTL_C, 12)); + OUTREG(0, sec_tex_cntl_c); + + if (pDstPicture->format == PICT_a8) { + color_factor = R128_COLOR_FACTOR_ALPHA; + in_color_factor = R128_INPUT_FACTOR_PREV_ALPHA; + } else if (pMaskPicture->componentAlpha) { + color_factor = R128_COLOR_FACTOR_TEX; + in_color_factor = R128_INPUT_FACTOR_PREV_COLOR; + } else { + color_factor = R128_COLOR_FACTOR_ALPHA; + in_color_factor = R128_INPUT_FACTOR_PREV_COLOR; + } + + OUTREG(0, R128_COMB_MODULATE | + color_factor | + in_color_factor | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + for (i = 0; i <= 10; i++) + OUTREG(0, ((CARD8 *)pMask->devPrivate.ptr - info->ExaDriver->memoryBase)); + } + + return TRUE; +} + +static void +R128Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + int srcXend, srcYend, maskXend, maskYend; + PictVector v; + + srcXend = srcX + w; + srcYend = srcY + h; + maskXend = maskX + w; + maskYend = maskY + h; + if (is_transform[0]) { + v.vector[0] = IntToxFixed(srcX); + v.vector[1] = IntToxFixed(srcY); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[0], &v); + srcX = xFixedToInt(v.vector[0]); + srcY = xFixedToInt(v.vector[1]); + v.vector[0] = IntToxFixed(srcXend); + v.vector[1] = IntToxFixed(srcYend); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[0], &v); + srcXend = xFixedToInt(v.vector[0]); + srcYend = xFixedToInt(v.vector[1]); + } + if (is_transform[1]) { + v.vector[0] = IntToxFixed(maskX); + v.vector[1] = IntToxFixed(maskY); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[1], &v); + maskX = xFixedToInt(v.vector[0]); + maskY = xFixedToInt(v.vector[1]); + v.vector[0] = IntToxFixed(maskXend); + v.vector[1] = IntToxFixed(maskYend); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[1], &v); + maskXend = xFixedToInt(v.vector[0]); + maskYend = xFixedToInt(v.vector[1]); + } + + R128WaitForFifo(pScrn, 3 + 4 * VTX_RING_COUNT); + + OUTREG(0, CCE_PACKET3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 2 + 4 * VTX_RING_COUNT - 1)); + OUTREG(0, R128_CCE_VC_FRMT_RHW | + R128_CCE_VC_FRMT_S_T | + R128_CCE_VC_FRMT_S2_T2); + OUTREG(0, R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (4 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + VTX_OUT(dstX, dstY, srcX, srcY, maskX, maskY); + VTX_OUT(dstX, dstY + h, srcX, srcYend, maskX, maskYend); + VTX_OUT(dstX + w, dstY + h, srcXend, srcYend, maskXend, maskYend); + VTX_OUT(dstX + w, dstY, srcXend, srcY, maskXend, maskY); +} + +#define R128DoneComposite R128Done +#endif + +static void +R128Sync(ScreenPtr pScreen, int marker) +{ + R128WaitForIdle(xf86Screens[pScreen->myNum]); +} + +static void +R128Done(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + info->state_2d.in_use = FALSE; +} + +#ifdef R128DRI + +#define R128CCEPrepareSolid R128PrepareSolid + +static void +R128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + RING_LOCALS; + + R128CCE_REFRESH( pScrn, info ); + + BEGIN_RING( 4 ); + + OUT_RING_REG( R128_DST_Y_X, (y1 << 16) | x1 ); + OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) ); + + ADVANCE_RING(); +} + +#define R128CCEDoneSolid R128Done + +#define R128CCEPrepareCopy R128PrepareCopy + +static void +R128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, + int width, int height) +{ + ScreenPtr pScreen = pDstPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + RING_LOCALS; + + R128CCE_REFRESH( pScrn, info ); + + if (info->xdir < 0) srcX += width - 1, dstX += width - 1; + if (info->ydir < 0) srcY += height - 1, dstY += height - 1; + + BEGIN_RING( 6 ); + + OUT_RING_REG( R128_SRC_Y_X, (srcY << 16) | srcX ); + OUT_RING_REG( R128_DST_Y_X, (dstY << 16) | dstX ); + OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width ); + + ADVANCE_RING(); +} + +#define R128CCEDoneCopy R128Done + +#ifdef RENDER +#define R128CCECheckComposite R128CheckComposite + +static Bool +R128CCEPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + ScreenPtr pScreen = pSrc->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + RING_LOCALS; + + uint32_t txsize = 0, prim_tex_cntl_c, sec_tex_cntl_c = 0, dstDatatype; + uint32_t dst_pitch_offset, color_factor, in_color_factor, alpha_comb; + uint32_t blend_cntl; + int i; + + if (pDstPicture->format == PICT_a8) { + if (R128BlendOp[op].dst_alpha) { + R128TRACE(("Can't dst alpha blend A8\n")); + return FALSE; + } + dstDatatype = R128_DATATYPE_Y8; + } else { + if (!R128GetDatatypePict1(pDstPicture->format, &dstDatatype)) return FALSE; + } + + if (!R128TextureSetup(pSrcPicture, pSrc, 0, &txsize, &prim_tex_cntl_c)) return FALSE; + + if (pMask != NULL) { + if (!R128TextureSetup(pMaskPicture, pMask, 1, &txsize, &sec_tex_cntl_c)) return FALSE; + } else { + is_transform[1] = FALSE; + } + + if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) return FALSE; + + info->state_2d.in_use = TRUE; + blend_cntl = R128BlendOp[op].blendctl; + if (PICT_FORMAT_A(pDstPicture->format) == 0 && R128BlendOp[op].dst_alpha) { + if ((blend_cntl & R128_SBLEND_MASK) == R128_SBLEND_DST_ALPHA) + blend_cntl = (blend_cntl & ~R128_SBLEND_MASK) | R128_SBLEND_ONE; + else if ((blend_cntl & R128_SBLEND_MASK) == R128_SBLEND_INV_DST_ALPHA) + blend_cntl = (blend_cntl & ~R128_SBLEND_MASK) | R128_SBLEND_ZERO; + } + + R128CCE_REFRESH( pScrn, info ); + BEGIN_RING( 12 ); + + OUT_RING_REG(R128_SCALE_3D_CNTL, + R128_SCALE_3D_TEXMAP_SHADE | + R128_SCALE_PIX_REPLICATE | + R128_TEX_CACHE_SPLIT | + R128_TEX_MAP_ALPHA_IN_TEXTURE | + R128_TEX_CACHE_LINE_SIZE_4QW); + OUT_RING_REG(R128_DST_PITCH_OFFSET, dst_pitch_offset); + OUT_RING_REG(R128_DP_GUI_MASTER_CNTL, + R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + (dstDatatype >> 8) | + R128_GMC_SRC_DATATYPE_COLOR | + (R128_ROP[3].rop << 16) | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_3D_FCN_EN | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS | + R128_GMC_WR_MSK_DIS); + OUT_RING_REG(R128_MISC_3D_STATE_CNTL_REG, + R128_MISC_SCALE_3D_TEXMAP_SHADE | + R128_MISC_SCALE_PIX_REPLICATE | + R128_ALPHA_COMB_ADD_CLAMP | + blend_cntl); + OUT_RING_REG(R128_TEX_CNTL_C, + R128_TEXMAP_ENABLE | + ((pMask != NULL) ? R128_SEC_TEXMAP_ENABLE : 0) | + R128_ALPHA_ENABLE | + R128_TEX_CACHE_FLUSH); + OUT_RING_REG(R128_PC_GUI_CTLSTAT, R128_PC_FLUSH_GUI); + ADVANCE_RING(); + + /* IN operator: Without a mask, only the first texture unit is enabled. + * With a mask, we put the source in the first unit and have it pass + * through as input to the 2nd. The 2nd unit takes the incoming source + * pixel and modulates it with either the alpha or each of the channels + * in the mask, depending on componentAlpha. + */ + BEGIN_RING( 15 ); + /* R128_REG_PRIM_TEX_CNTL_C, + * R128_REG_PRIM_TEXTURE_COMBINE_CNTL_C, + * R128_REG_TEX_SIZE_PITCH_C, + * R128_REG_PRIM_TEX_0_OFFSET_C - R128_REG_PRIM_TEX_10_OFFSET_C + */ + OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C, 13)); + OUT_RING(prim_tex_cntl_c); + + /* If this is the only stage and the dest is a8, route the alpha result + * to the color (red channel, in particular), too. Otherwise, be sure + * to zero out color channels of an a8 source. + */ + if (pMaskPicture == NULL && pDstPicture->format == PICT_a8) + color_factor = R128_COLOR_FACTOR_ALPHA; + else if (pSrcPicture->format == PICT_a8) + color_factor = R128_COLOR_FACTOR_CONST_COLOR; + else + color_factor = R128_COLOR_FACTOR_TEX; + + if (PICT_FORMAT_A(pSrcPicture->format) == 0) + alpha_comb = R128_COMB_ALPHA_COPY_INP; + else + alpha_comb = R128_COMB_ALPHA_DIS; + + OUT_RING(R128_COMB_COPY | + color_factor | + R128_INPUT_FACTOR_INT_COLOR | + alpha_comb | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_CONST_ALPHA); + OUT_RING(txsize); + /* We could save some output by only writing the offset register that + * will actually be used. On the other hand, this is easy. + */ + for (i = 0; i <= 10; i++) + OUT_RING(((CARD8 *)pSrc->devPrivate.ptr - info->ExaDriver->memoryBase)); + ADVANCE_RING(); + + if (pMask != NULL) { + BEGIN_RING( 14 ); + /* R128_REG_SEC_TEX_CNTL_C, + * R128_REG_SEC_TEXTURE_COMBINE_CNTL_C, + * R128_REG_SEC_TEX_0_OFFSET_C - R128_REG_SEC_TEX_10_OFFSET_C + */ + + OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 12)); + OUT_RING(sec_tex_cntl_c); + + if (pDstPicture->format == PICT_a8) { + color_factor = R128_COLOR_FACTOR_ALPHA; + in_color_factor = R128_INPUT_FACTOR_PREV_ALPHA; + } else if (pMaskPicture->componentAlpha) { + color_factor = R128_COLOR_FACTOR_TEX; + in_color_factor = R128_INPUT_FACTOR_PREV_COLOR; + } else { + color_factor = R128_COLOR_FACTOR_ALPHA; + in_color_factor = R128_INPUT_FACTOR_PREV_COLOR; + } + + OUT_RING(R128_COMB_MODULATE | + color_factor | + in_color_factor | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + for (i = 0; i <= 10; i++) + OUT_RING(((CARD8 *)pMask->devPrivate.ptr - info->ExaDriver->memoryBase)); + + ADVANCE_RING(); + } + + return TRUE; +} + +static void +R128CCEComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + RING_LOCALS; + + int srcXend, srcYend, maskXend, maskYend; + PictVector v; + + srcXend = srcX + w; + srcYend = srcY + h; + maskXend = maskX + w; + maskYend = maskY + h; + if (is_transform[0]) { + v.vector[0] = IntToxFixed(srcX); + v.vector[1] = IntToxFixed(srcY); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[0], &v); + srcX = xFixedToInt(v.vector[0]); + srcY = xFixedToInt(v.vector[1]); + v.vector[0] = IntToxFixed(srcXend); + v.vector[1] = IntToxFixed(srcYend); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[0], &v); + srcXend = xFixedToInt(v.vector[0]); + srcYend = xFixedToInt(v.vector[1]); + } + if (is_transform[1]) { + v.vector[0] = IntToxFixed(maskX); + v.vector[1] = IntToxFixed(maskY); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[1], &v); + maskX = xFixedToInt(v.vector[0]); + maskY = xFixedToInt(v.vector[1]); + v.vector[0] = IntToxFixed(maskXend); + v.vector[1] = IntToxFixed(maskYend); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[1], &v); + maskXend = xFixedToInt(v.vector[0]); + maskYend = xFixedToInt(v.vector[1]); + } + + R128CCE_REFRESH( pScrn, info ); + BEGIN_RING( 3 + 4 * VTX_RING_COUNT ); + + OUT_RING(CCE_PACKET3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 2 + 4 * VTX_RING_COUNT - 1)); + OUT_RING(R128_CCE_VC_FRMT_RHW | + R128_CCE_VC_FRMT_S_T | + R128_CCE_VC_FRMT_S2_T2); + OUT_RING(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (4 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + VTX_CCE_OUT(dstX, dstY, srcX, srcY, maskX, maskY); + VTX_CCE_OUT(dstX, dstY + h, srcX, srcYend, maskX, maskYend); + VTX_CCE_OUT(dstX + w, dstY + h, srcXend, srcYend, maskXend, maskYend); + VTX_CCE_OUT(dstX + w, dstY, srcXend, srcY, maskXend, maskY); + + ADVANCE_RING(); +} + +#define R128CCEDoneComposite R128Done +#endif + +static void +R128CCESync(ScreenPtr pScreen, int marker) +{ + R128CCEWaitForIdle(xf86Screens[pScreen->myNum]); +} +#endif + +Bool +R128EXAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + info->ExaDriver->exa_major = EXA_VERSION_MAJOR; + info->ExaDriver->exa_minor = EXA_VERSION_MINOR; + + info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset; + info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT; + +#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3) + info->ExaDriver->maxPitchBytes = 16320; +#endif + /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */ + info->ExaDriver->pixmapPitchAlign = 32; + info->ExaDriver->pixmapOffsetAlign = 32; + info->ExaDriver->maxX = 2048; + info->ExaDriver->maxY = 2048; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Setting up EXA callbacks\n"); + +#ifdef R128DRI + if (info->directRenderingEnabled) { + info->ExaDriver->PrepareSolid = R128CCEPrepareSolid; + info->ExaDriver->Solid = R128CCESolid; + info->ExaDriver->DoneSolid = R128CCEDoneSolid; + + info->ExaDriver->PrepareCopy = R128CCEPrepareCopy; + info->ExaDriver->Copy = R128CCECopy; + info->ExaDriver->DoneCopy = R128CCEDoneCopy; + +#ifdef RENDER + info->ExaDriver->CheckComposite = R128CCECheckComposite; + info->ExaDriver->PrepareComposite = R128CCEPrepareComposite; + info->ExaDriver->Composite = R128CCEComposite; + info->ExaDriver->DoneComposite = R128CCEDoneComposite; +#endif + + info->ExaDriver->WaitMarker = R128CCESync; + } else +#endif + { + info->ExaDriver->PrepareSolid = R128PrepareSolid; + info->ExaDriver->Solid = R128Solid; + info->ExaDriver->DoneSolid = R128DoneSolid; + + info->ExaDriver->PrepareCopy = R128PrepareCopy; + info->ExaDriver->Copy = R128Copy; + info->ExaDriver->DoneCopy = R128DoneCopy; + +#ifdef RENDER + info->ExaDriver->CheckComposite = R128CheckComposite; + info->ExaDriver->PrepareComposite = R128PrepareComposite; + info->ExaDriver->Composite = R128Composite; + info->ExaDriver->DoneComposite = R128DoneComposite; +#endif + + info->ExaDriver->WaitMarker = R128Sync; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initalizing 2D acceleration engine...\n"); + + R128EngineInit(pScrn); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initializing EXA driver...\n"); + + if (!exaDriverInit(pScreen, info->ExaDriver)) { + free(info->ExaDriver); + return FALSE; + } + exaMarkSync(pScreen); + + return TRUE; +} diff -ruN xf86-video-r128-master.orig/src/r128_reg.h xf86-video-r128-master/src/r128_reg.h --- xf86-video-r128-master.orig/src/r128_reg.h 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/r128_reg.h 2012-03-25 23:12:05.100618676 -0700 @@ -1522,6 +1522,33 @@ #define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 #define R128_CCE_VC_CNTL_NUM_SHIFT 16 +# define R128_SBLEND_ZERO (0 << 16) +# define R128_SBLEND_ONE (1 << 16) +# define R128_SBLEND_SRCCOLOR (2 << 16) +# define R128_SBLEND_INVSRCCOLOR (3 << 16) +# define R128_SBLEND_SRC_ALPHA (4 << 16) +# define R128_SBLEND_INV_SRC_ALPHA (5 << 16) +# define R128_SBLEND_DST_ALPHA (6 << 16) +# define R128_SBLEND_INV_DST_ALPHA (7 << 16) +# define R128_SBLEND_DSTCOLOR (8 << 16) +# define R128_SBLEND_INVDSTCOLOR (9 << 16) +# define R128_SBLEND_SRC_ALPHASAT (10 << 16) +# define R128_SBLEND_BOTHSRC_ALPHA (11 << 16) +# define R128_SBLEND_BOTHINV_SRC_ALPHA (12 << 16) +# define R128_SBLEND_MASK (15 << 16) +# define R128_DBLEND_ZERO (0 << 20) +# define R128_DBLEND_ONE (1 << 20) +# define R128_DBLEND_SRCCOLOR (2 << 20) +# define R128_DBLEND_INVSRCCOLOR (3 << 20) +# define R128_DBLEND_SRC_ALPHA (4 << 20) +# define R128_DBLEND_INV_SRC_ALPHA (5 << 20) +# define R128_DBLEND_DST_ALPHA (6 << 20) +# define R128_DBLEND_INV_DST_ALPHA (7 << 20) +# define R128_DBLEND_DSTCOLOR (8 << 20) +# define R128_DBLEND_INVDSTCOLOR (9 << 20) +# define R128_DBLEND_SRC_ALPHASAT (10 << 20) +# define R128_DBLEND_MASK (15 << 20) + /* hmm copyed blindly (no specs) from radeon.h ... */ #define R128_RE_TOP_LEFT 0x26c0 # define R128_RE_LEFT_SHIFT 0 diff -ruN xf86-video-r128-master.orig/src/r128_video.c xf86-video-r128-master/src/r128_video.c --- xf86-video-r128-master.orig/src/r128_video.c 2012-01-03 20:24:36.000000000 -0800 +++ xf86-video-r128-master/src/r128_video.c 2012-03-24 16:10:44.311559065 -0700 @@ -56,7 +56,8 @@ int saturation; Bool doubleBuffer; unsigned char currentBuffer; - FBLinearPtr linear; + void* BufferHandle; + int videoOffset; RegionRec clip; CARD32 colorKey; CARD32 videoStatus; @@ -270,9 +271,13 @@ if(pPriv->videoStatus & CLIENT_VIDEO_ON) { OUTREG(R128_OV0_SCALE_CNTL, 0); } - if(pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; + if(pPriv->BufferHandle) { + if (!info->useEXA) { + xf86FreeOffscreenLinear((FBLinearPtr) pPriv->BufferHandle); + } else { + exaOffscreenFree(pScrn->pScreen, (ExaOffscreenArea *) pPriv->BufferHandle); + } + pPriv->BufferHandle = NULL; } pPriv->videoStatus = 0; } else { @@ -564,45 +569,75 @@ } -static FBLinearPtr +static CARD32 R128AllocateMemory( ScrnInfoPtr pScrn, - FBLinearPtr linear, + void **mem_struct, int size ){ - ScreenPtr pScreen; - FBLinearPtr new_linear; + R128InfoPtr info = R128PTR(pScrn); + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];; + int offset = 0; - if(linear) { - if(linear->size >= size) - return linear; + if(!info->useEXA) { + FBLinearPtr linear = *mem_struct; + int cpp = info->CurrentLayout.pixel_bytes; + + /* XAA allocates in units of pixels at the screen bpp, so adjust size appropriately. */ + size = (size + cpp - 1) / cpp; + + if(linear) { + if(linear->size >= size) + return linear->offset * cpp; - if(xf86ResizeOffscreenLinear(linear, size)) - return linear; + if(xf86ResizeOffscreenLinear(linear, size)) + return linear->offset * cpp; - xf86FreeOffscreenLinear(linear); - } + xf86FreeOffscreenLinear(linear); + } - pScreen = screenInfo.screens[pScrn->scrnIndex]; - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, + linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); + *mem_struct = linear; - if(!new_linear) { - int max_size; + if(!linear) { + int max_size; - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME); - if(max_size < size) - return NULL; + if(max_size < size) + return NULL; - xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, + xf86PurgeUnlockedOffscreenAreas(pScreen); + linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); + + if(!linear) return 0; + } + + offset = linear->offset * cpp; + } else { + /* EXA support based on mga driver */ + ExaOffscreenArea *area = *mem_struct; + + if(area) { + if(area->size >= size) + return area->offset; + + exaOffscreenFree(pScrn->pScreen, area); + } + + area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, NULL, NULL); + *mem_struct = area; + + if(!area) return 0; + + offset = area->offset; } - return new_linear; + return offset; } static void @@ -841,7 +876,7 @@ srcPitch = (width + 3) & ~3; srcPitch2 = ((width >> 1) + 3) & ~3; dstPitch = (width + 31) & ~31; /* of luma */ - new_size = ((dstPitch * (height + (height >> 1))) + bpp - 1) / bpp; + new_size = dstPitch * (height + (height >> 1)); s1offset = 0; s2offset = srcPitch * height; s3offset = (srcPitch2 * (height >> 1)) + s2offset; @@ -852,14 +887,14 @@ srcPitch = width << 1; srcPitch2 = 0; dstPitch = ((width << 1) + 15) & ~15; - new_size = ((dstPitch * height) + bpp - 1) / bpp; + new_size = dstPitch * height; s1offset = 0; s2offset = 0; s3offset = 0; break; } - if(!(pPriv->linear = R128AllocateMemory(pScrn, pPriv->linear, + if(!(pPriv->videoOffset = R128AllocateMemory(pScrn, &(pPriv->BufferHandle), pPriv->doubleBuffer ? (new_size << 1) : new_size))) { return BadAlloc; @@ -872,9 +907,9 @@ left = (xa >> 16) & ~1; npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; - offset = pPriv->linear->offset * bpp; + offset = pPriv->videoOffset; if(pPriv->doubleBuffer) - offset += pPriv->currentBuffer * new_size * bpp; + offset += pPriv->currentBuffer * new_size; switch(id) { case FOURCC_YV12: @@ -1015,9 +1050,13 @@ } } else { /* FREE_TIMER */ if(pPriv->freeTime < now) { - if(pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; + if(pPriv->BufferHandle) { + if (!info->useEXA) { + xf86FreeOffscreenLinear((FBLinearPtr) pPriv->BufferHandle); + } else { + exaOffscreenAreaFree(pScrn->pScreen, (ExaOffscreenArea *) pPriv->BufferHandle); + } + pPriv->BufferHandle = NULL; } pPriv->videoStatus = 0; info->VideoTimerCallback = NULL;