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-03-23 15:49:40.377692493 -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" @@ -69,7 +72,7 @@ #include "atipcirename.h" -#define R128_DEBUG 0 /* Turn off debugging output */ +#define R128_DEBUG 1 /* Turn off debugging output */ #define R128_IDLE_RETRY 32 /* Fall out of idle loops after this count */ #define R128_TIMEOUT 2000000 /* Fall out of wait loops after this count */ #define R128_MMIOSIZE 0x4000 @@ -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); \ @@ -277,6 +282,11 @@ XAAInfoRecPtr accel; Bool accelOn; + + ExaDriverPtr ExaDriver; + XF86ModReqInfo exaReq; + Bool useEXA; + xf86CursorInfoPtr cursor; unsigned long cursor_start; unsigned long cursor_end; @@ -470,6 +480,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); 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-03-23 17:59:59.705282864 -0700 @@ -1866,8 +1866,26 @@ R128InfoPtr info = R128PTR(pScrn); XAAInfoRecPtr a; - if (!xf86LoadSubModule(pScrn, "xaa")) - return FALSE; + if (info->useEXA) { + int errmaj = 0, errmin = 0; + + info->exaReq.majorversion = 2; + info->exaReq.minorversion = 0; + + 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 */ + info->ExaDriver = exaDriverAlloc(); + if (!info->ExaDriver) 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-03-24 11:10:11.756023827 -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 @@ -1419,7 +1420,9 @@ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; R128InfoPtr info = R128PTR(pScrn); R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); - + + if (info->useEXA) return; + if (info->allowPageFlip) { /* Duplicate the frontbuffer to the backbuffer */ (*info->accel->SetupForScreenToScreenCopy)(pScrn, @@ -1471,6 +1474,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-03-24 21:37:08.291086661 -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,26 @@ } } +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; + } +} + /* Called at the start of each server generation. */ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) @@ -2192,8 +2214,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)); @@ -2245,8 +2282,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) { @@ -2318,6 +2353,22 @@ /* must be after RGB order fixed */ fbPictureInit (pScreen, 0, 0); + + /* Acceleration setup */ + 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; + } /* Memory manager setup */ #ifdef R128DRI @@ -2387,7 +2438,7 @@ info->textureOffset = 0; info->textureSize = 0; } - + total = info->FbMapSize - info->textureSize; scanlines = total / width_bytes; if (scanlines > 8191) scanlines = 8191; @@ -2402,50 +2453,91 @@ 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); + } } - 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"); + 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 +2547,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; @@ -2501,51 +2614,39 @@ drawable caches beyond this region. */ 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); + } + } } else { - xf86DrvMsg(scrnIndex, X_ERROR, - "Acceleration initialization failed\n"); - xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); - info->accelOn = FALSE; + info->ExaDriver->offScreenBase = width_bytes * pScrn->virtualY; + info->ExaDriver->memorySize = info->FbMapSize; + R128VerboseInitEXA(scrnIndex, pScreen); } - } else { - xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); - info->accelOn = FALSE; } /* DGA setup */ @@ -2897,16 +2998,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 +3884,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 +4384,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-03-25 23:15:39.357265479 -0700 @@ -0,0 +1,842 @@ +/* Based on work by Eric Anholt in 2004 and Joseph Garvin in 2006. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "r128.h" +#include "exa.h" + +#include "r128_reg.h" + +#include "xf86.h" + +static int widths[2] = {1,1}; +static int heights[2] = {1,1}; +static Bool is_transform[2]; +static PictTransform *transform[2]; + +struct blendinfo { + Bool dst_alpha; + Bool src_alpha; + CARD32 blendctl; +}; + +static struct blendinfo 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 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 */ +}; + +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 { \ + 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 +R128GetDatatypePict(CARD32 format, CARD32 *type) +{ + switch (format) { + case PICT_a1r5g5b5: + case PICT_x1r5g5b5: + *type = R128_DATATYPE_ARGB1555; + return TRUE; + case PICT_r5g6b5: + *type = R128_DATATYPE_RGB565; + return TRUE; + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + *type = R128_DATATYPE_ARGB8888; + return TRUE; + default: + return FALSE; + } + +} + +static Bool +R128CheckCompositeTexture(PicturePtr pPict) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + + ScreenPtr pScreen = pPict->pDrawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (w > (1 << 10) || h > (1 << 10)) { + R128TRACE(("Picture w/h too large (%dx%d)\n", w, h)); + return FALSE; + } + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) { + R128TRACE(("NPOT repeat unsupported (%dx%d)\n", w, h)); + return FALSE; + } + + switch (pPict->format) { + case PICT_a8: + case PICT_a1r5g5b5: + case PICT_a4r4g4b4: + case PICT_r5g6b5: + case PICT_a8r8g8b8: + break; + default: + R128TRACE(("Unsupported picture format 0x%x\n", pPict->format)); + return FALSE; + } + + return TRUE; +} + +static Bool +R128TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit, CARD32 *txsize, CARD32 *tex_cntl_c) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int bytepp, shift, l2w, l2h, l2p; + int pitch; + + ScreenPtr pScreen = pPix->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + pitch = pPix->devKind; + if ((pitch & (pitch - 1)) != 0) { + R128TRACE(("NPOT pitch 0x%x unsupported\n", pitch)); + return FALSE; + } + + switch (pPict->format) { + case PICT_a8: + /* DATATYPE_RGB8 appears to expand the value into the alpha + * channel like we want. We then blank out the R,G,B channels + * as necessary using the combiners. + */ + *tex_cntl_c = R128_DATATYPE_RGB8; + break; + case PICT_a1r5g5b5: + *tex_cntl_c = R128_DATATYPE_ARGB1555; + break; + case PICT_a4r4g4b4: + *tex_cntl_c = R128_DATATYPE_ARGB4444; + break; + case PICT_r5g6b5: + *tex_cntl_c = R128_DATATYPE_RGB565; + break; + case PICT_a8r8g8b8: + *tex_cntl_c = R128_DATATYPE_ARGB8888; + break; + default: + 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; + + 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; +} + +/* 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); + unsigned char *R128MMIO = info->MMIO; + unsigned long pxPitch = exaGetPixmapPitch(pPixmap); + unsigned long pxOffset = exaGetPixmapOffset(pPixmap); + int bpp = pPixmap->drawable.bitsPerPixel; + CARD32 regValue; + + regValue = ((pxPitch / bpp) << 21) | (pxOffset >> 5); + + + R128WaitForFifo(pScrn, 5); + OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl + | R128_GMC_BRUSH_SOLID_COLOR + | R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP[alu].pattern)); + OUTREG(R128_DP_BRUSH_FRGD_CLR, fg); + OUTREG(R128_DP_WRITE_MASK, planemask); + OUTREG(R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT + | R128_DST_Y_TOP_TO_BOTTOM)); + OUTREG(R128_DST_PITCH_OFFSET, regValue); + 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)); +} + +static void +R128DoneSolid(PixmapPtr pPixmap) +{ +} + +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); + unsigned char *R128MMIO = info->MMIO; + + unsigned long srcpxPitch = exaGetPixmapPitch(pSrcPixmap); + unsigned long srcpxOffset = exaGetPixmapOffset(pSrcPixmap); + int srcbpp = pSrcPixmap->drawable.bitsPerPixel; + CARD32 srcRegValue; + + unsigned long dstpxPitch = exaGetPixmapPitch(pDstPixmap); + unsigned long dstpxOffset = exaGetPixmapOffset(pDstPixmap); + int dstbpp = pDstPixmap->drawable.bitsPerPixel; + CARD32 dstRegValue; + + dstRegValue = ((dstpxPitch / dstbpp) << 21) | (dstpxOffset >> 5); + srcRegValue = ((srcpxPitch / srcbpp) << 21) | (srcpxOffset >> 5); + + info->xdir = xdir; + info->ydir = ydir; + R128WaitForFifo(pScrn, 5); + OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl + | R128_GMC_BRUSH_SOLID_COLOR + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP[alu].rop + | R128_DP_SRC_SOURCE_MEMORY)); + OUTREG(R128_DP_WRITE_MASK, planemask); + OUTREG(R128_DP_CNTL, ((xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) + | (ydir >= 0 + ? R128_DST_Y_TOP_TO_BOTTOM + : 0))); + OUTREG(R128_DST_PITCH_OFFSET, dstRegValue); + OUTREG(R128_SRC_PITCH_OFFSET, srcRegValue); + + 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); +} + +static void +R128DoneCopy(PixmapPtr pPixmap) +{ +} + +static void +R128Sync(ScreenPtr pScreen, int marker) +{ + R128WaitForIdle(xf86Screens[pScreen->myNum]); +} + +#ifdef R128DRI +static Bool +R128CCEPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + unsigned long pxPitch = exaGetPixmapPitch(pPixmap); + unsigned long pxOffset = exaGetPixmapOffset(pPixmap); + int bpp = pPixmap->drawable.bitsPerPixel; + CARD32 regValue; + RING_LOCALS; + + regValue = ((pxPitch / bpp) << 21) | (pxOffset >> 5); + + R128CCE_REFRESH( pScrn, info ); + + BEGIN_RING( 10 ); + + OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, + (info->dp_gui_master_cntl + | R128_GMC_BRUSH_SOLID_COLOR + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP[alu].pattern) ); + + OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, fg ); + OUT_RING_REG( R128_DP_WRITE_MASK, planemask ); + OUT_RING_REG( R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT | + R128_DST_Y_TOP_TO_BOTTOM)); + + OUT_RING_REG(R128_DST_PITCH_OFFSET, regValue); + + ADVANCE_RING(); + + return TRUE; +} + +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); + unsigned char *R128MMIO = info->MMIO; + 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(); +} + + +static void +R128CCEDoneSolid(PixmapPtr pPixmap) +{ +} + +static Bool +R128CCEPrepareCopy(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); + + unsigned long srcpxPitch = exaGetPixmapPitch(pSrcPixmap); + unsigned long srcpxOffset = exaGetPixmapOffset(pSrcPixmap); + int srcbpp = pSrcPixmap->drawable.bitsPerPixel; + CARD32 srcRegValue; + + unsigned long dstpxPitch = exaGetPixmapPitch(pDstPixmap); + unsigned long dstpxOffset = exaGetPixmapOffset(pDstPixmap); + int dstbpp = pDstPixmap->drawable.bitsPerPixel; + CARD32 dstRegValue; + + RING_LOCALS; + + dstRegValue = ((dstpxPitch / dstbpp) << 21) | (dstpxOffset >> 5); + srcRegValue = ((srcpxPitch / srcbpp) << 21) | (srcpxOffset >> 5); + + R128CCE_REFRESH( pScrn, info ); + + info->xdir = xdir; + info->ydir = ydir; + + BEGIN_RING( 10 ); + + OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, + (info->dp_gui_master_cntl + | R128_GMC_BRUSH_NONE + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP[alu].rop + | R128_DP_SRC_SOURCE_MEMORY) ); + + OUT_RING_REG( R128_DP_WRITE_MASK, planemask ); + OUT_RING_REG( R128_DP_CNTL, + ((xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) | + (ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0)) ); + + OUT_RING_REG(R128_DST_PITCH_OFFSET, dstRegValue); + OUT_RING_REG(R128_SRC_PITCH_OFFSET, srcRegValue); + + ADVANCE_RING(); + + return TRUE; +} + +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(); +} + +static void +R128CCEDoneCopy(PixmapPtr pPixmap) +{ +} + +static Bool +R128CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) +{ + CARD32 dstDatatype; + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (op >= sizeof(R128BlendOp) / sizeof(R128BlendOp[0])) { + R128TRACE(("Unsupported op 0x%x\n", op)); + 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 (!R128GetDatatypePict(pDstPicture->format, &dstDatatype)) { + R128TRACE(("Unsupported dest format 0x%x\n", pDstPicture->format)); + return FALSE; + } + if (pMaskPicture != NULL && pMaskPicture->componentAlpha && R128BlendOp[op].src_alpha) { + R128TRACE(("Component alpha not supported with source alpha blending.\n")); + return FALSE; + } + + if (!R128CheckCompositeTexture(pSrcPicture)) + return FALSE; + if (pMaskPicture != NULL && !R128CheckCompositeTexture(pMaskPicture)) + return FALSE; + + return TRUE; +} + +static Bool +R128PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + CARD32 txsize = 0, prim_tex_cntl_c, sec_tex_cntl_c = 0, dstDatatype; + CARD32 dst_pitch_offset, color_factor, in_color_factor, alpha_comb, blend_cntl; + RING_LOCALS; + + unsigned long dst_pitch; + unsigned long dst_offset; + CARD32 regValue; + ScreenPtr pScreen = pDst->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + int bpp = pDst->drawable.bitsPerPixel; + int i; + + dst_pitch = exaGetPixmapPitch(pDst); + dst_offset = exaGetPixmapOffset(pDst); + regValue = ((dst_pitch / bpp) << 21) | (dst_offset >> 5); + + if (pDstPicture->format == PICT_a8) + dstDatatype = R128_DATATYPE_Y8; + else + R128GetDatatypePict(pDstPicture->format, &dstDatatype); + + if (!R128TextureSetup(pSrcPicture, pSrc, 0, &txsize, &prim_tex_cntl_c)) + return FALSE; + if (pMask != NULL && !R128TextureSetup(pMaskPicture, pMask, 1, &txsize, &sec_tex_cntl_c)) + return FALSE; + else if (pMask == NULL) + is_transform[1] = FALSE; + + 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, regValue); + 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 +R128Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h) +{ + int srcXend, srcYend, maskXend, maskYend; + PictVector v; + RING_LOCALS; + + ScreenPtr pScreen = pDst->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + 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_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); + + ADVANCE_RING(); +} + +static void +R128DoneComposite(PixmapPtr pPixmap) +{ +} + +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); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocating EXA driver...\n"); + + + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EXA driver allocated...\n"); + + info->ExaDriver->exa_major = 2; + info->ExaDriver->exa_minor = 0; + + info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS; + info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset; + + /* Pitch alignment is in sets of 32 pixels, and we need to cover 32bpp, so it's 128 bytes */ + info->ExaDriver->pixmapPitchAlign = 128; + + /* Taken from radeon driver */ + info->ExaDriver->pixmapOffsetAlign = 4096; + info->ExaDriver->maxX = 2048; + info->ExaDriver->maxY = 2048; + + info->ExaDriver->PrepareAccess = NULL; + + 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; + + info->ExaDriver->CheckComposite = R128CheckComposite; + info->ExaDriver->PrepareComposite = R128PrepareComposite; + info->ExaDriver->Composite = R128Composite; + info->ExaDriver->DoneComposite = R128DoneComposite; + + 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; + + info->ExaDriver->CheckComposite = NULL; + info->ExaDriver->PrepareComposite = NULL; + info->ExaDriver->Composite = NULL; + info->ExaDriver->DoneComposite = NULL; + + 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"); + + return (exaDriverInit(pScreen, info->ExaDriver)); +} 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;