diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/i830.h | 25 | ||||
-rw-r--r-- | src/i830_3d.c | 10 | ||||
-rw-r--r-- | src/i830_accel.c | 647 | ||||
-rw-r--r-- | src/i830_dga.c | 4 | ||||
-rw-r--r-- | src/i830_dri.c | 6 | ||||
-rw-r--r-- | src/i830_driver.c | 174 | ||||
-rw-r--r-- | src/i830_exa.c | 594 | ||||
-rw-r--r-- | src/i830_exa_render.c | 512 | ||||
-rw-r--r-- | src/i830_memory.c | 28 | ||||
-rw-r--r-- | src/i830_reg.h | 117 | ||||
-rw-r--r-- | src/i830_rotate.c | 33 | ||||
-rw-r--r-- | src/i830_video.c | 2 | ||||
-rw-r--r-- | src/i830_xaa.c | 712 | ||||
-rw-r--r-- | src/i915_3d.c | 4 | ||||
-rw-r--r-- | src/i915_3d.h | 27 | ||||
-rw-r--r-- | src/i915_exa_render.c | 501 | ||||
-rw-r--r-- | src/i915_reg.h | 12 |
18 files changed, 2715 insertions, 701 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 63370ab9..e58350c9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ SUBDIRS = xvmc # -avoid-version prevents gratuitous .0.0.0 version numbers on the end # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA i810_drv_la_LTLIBRARIES = i810_drv.la i810_drv_la_LDFLAGS = -module -avoid-version @@ -64,7 +64,11 @@ i810_drv_la_SOURCES = \ i915_3d.c \ i915_3d.h \ i915_reg.h \ - i915_video.c + i915_video.c \ + i830_exa.c \ + i830_xaa.c \ + i830_exa_render.c \ + i915_exa_render.c if DRI i810_drv_la_SOURCES += \ @@ -70,6 +70,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830_dri.h" #endif +#ifdef I830_USE_EXA +#include "exa.h" +Bool I830EXAInit(ScreenPtr pScreen); +#endif + +#ifdef I830_USE_XAA +Bool I830XAAInit(ScreenPtr pScreen); +#endif + #include "common.h" #define NEED_REPLIES /* ? */ @@ -232,7 +241,9 @@ typedef struct _I830Rec { I830MemRange FrontBuffer2; I830MemRange Scratch; I830MemRange Scratch2; - +#ifdef I830_USE_EXA + I830MemRange Offscreen; +#endif /* Regions allocated either from the above pools, or from agpgart. */ I830MemRange *CursorMem; I830MemRange *CursorMemARGB; @@ -332,13 +343,22 @@ typedef struct _I830Rec { I830RegRec SavedReg; I830RegRec ModeReg; + Bool useEXA; Bool noAccel; Bool SWCursor; Bool cursorOn; +#ifdef I830_USE_XAA XAAInfoRecPtr AccelInfoRec; +#endif xf86CursorInfoPtr CursorInfoRec; CloseScreenProcPtr CloseScreen; +#ifdef I830_USE_EXA + unsigned int copy_src_pitch; + unsigned int copy_src_off; + ExaDriverPtr EXADriverPtr; +#endif + I830WriteIndexedByteFunc writeControl; I830ReadIndexedByteFunc readControl; I830WriteByteFunc writeStandard; @@ -531,6 +551,9 @@ extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode); extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode); extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); +extern void i830MarkSync(ScrnInfoPtr pScrn); +extern void i830WaitSync(ScrnInfoPtr pScrn); + /* i830_memory.c */ Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); diff --git a/src/i830_3d.c b/src/i830_3d.c index debad7c9..563dcef7 100644 --- a/src/i830_3d.c +++ b/src/i830_3d.c @@ -34,13 +34,11 @@ #include "i830_reg.h" -#define CMD_3D (0x3<<29) - void I830EmitInvarientState( ScrnInfoPtr pScrn ) { I830Ptr pI830 = I830PTR(pScrn); - BEGIN_LP_RING(38); + BEGIN_LP_RING(40); OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(0)); OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(1)); @@ -99,6 +97,12 @@ void I830EmitInvarientState( ScrnInfoPtr pScrn ) OUT_RING(_3DSTATE_MAP_COORD_TRANSFORM); OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3)); + OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD); + OUT_RING(TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) | + TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) | + TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | + TEXBIND_SET0(TEXCOORDSRC_VTXSET_0)); + OUT_RING(_3DSTATE_RASTER_RULES_CMD | ENABLE_POINT_RASTER_RULE | OGL_POINT_RASTER_RULE | diff --git a/src/i830_accel.c b/src/i830_accel.c index b029968e..6ad62d1f 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -7,10 +7,6 @@ #include "config.h" #endif -#ifndef DO_SCANLINE_IMAGE_WRITE -#define DO_SCANLINE_IMAGE_WRITE 0 -#endif - /************************************************************************** Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. @@ -111,7 +107,12 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]); } #endif +#ifdef I830_USE_XAA pI830->AccelInfoRec = NULL; /* Stops recursive behavior */ +#endif +#ifdef I830_USE_EXA + pI830->EXADriverPtr = NULL; +#endif FatalError("lockup\n"); } @@ -219,47 +220,9 @@ I830RefreshRing(ScrnInfoPtr pScrn) pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); if (pI830->LpRing->space < 0) pI830->LpRing->space += pI830->LpRing->mem.Size; - - if (pI830->AccelInfoRec) - pI830->AccelInfoRec->NeedToSync = TRUE; + i830MarkSync(pScrn); } -/* I830 Accel Functions */ - -static void I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, - int pattx, int patty, - int fg, int bg, int rop, - unsigned int planemask); -static void I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, - int pattx, int patty, - int x, int y, int w, int h); - -static void I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, - int fg, int bg, - int rop, - unsigned int mask); - -static void I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr - pScrn, int x, - int y, int w, - int h, - int skipleft); - -static void I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); - -#if DO_SCANLINE_IMAGE_WRITE -static void I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, - int trans_color, int bpp, - int depth); -static void I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, - int x, int y, int w, int h, - int skipleft); -static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno); -#endif -static void I830RestoreAccelState(ScrnInfoPtr pScrn); - - /* The following function sets up the supported acceleration. Call it * from the FbInit() function in the SVGA driver, or before ScreenInit * in a monolithic server. @@ -267,597 +230,15 @@ static void I830RestoreAccelState(ScrnInfoPtr pScrn); Bool I830AccelInit(ScreenPtr pScreen) { - XAAInfoRecPtr infoPtr; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - int i; - int width = 0; - int nr_buffers = 0; - unsigned char *ptr = NULL; - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830AccelInit\n"); - - pI830->AccelInfoRec = infoPtr = XAACreateInfoRec(); - if (!infoPtr) - return FALSE; - - pI830->bufferOffset = 0; - infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE; - - /* Use the same sync function as the I830. - */ - infoPtr->Sync = I830Sync; +#ifdef I830_USE_EXA + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); - /* Everything else is different enough to justify different functions */ - { - infoPtr->SolidFillFlags = NO_PLANEMASK; - infoPtr->SetupForSolidFill = I830SetupForSolidFill; - infoPtr->SubsequentSolidFillRect = I830SubsequentSolidFillRect; - } - - { - infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY); - - infoPtr->SetupForScreenToScreenCopy = I830SetupForScreenToScreenCopy; - infoPtr->SubsequentScreenToScreenCopy = - I830SubsequentScreenToScreenCopy; - } - - { - infoPtr->SetupForMono8x8PatternFill = I830SetupForMono8x8PatternFill; - infoPtr->SubsequentMono8x8PatternFillRect = - I830SubsequentMono8x8PatternFillRect; - - infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS | - HARDWARE_PATTERN_SCREEN_ORIGIN | - HARDWARE_PATTERN_PROGRAMMED_ORIGIN | - BIT_ORDER_IN_BYTE_MSBFIRST | - NO_PLANEMASK); - - } - - /* On the primary screen */ - if (pI830->init == 0) { - if (pI830->Scratch.Size != 0) { - width = ((pScrn->displayWidth + 31) & ~31) / 8; - nr_buffers = pI830->Scratch.Size / width; - ptr = pI830->FbBase + pI830->Scratch.Start; - } - } else { - /* On the secondary screen */ - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - if (pI8301->Scratch2.Size != 0) { - width = ((pScrn->displayWidth + 31) & ~31) / 8; - nr_buffers = pI8301->Scratch2.Size / width; - /* We have to use the primary screen's FbBase, as that's where - * we allocated Scratch2, so we get the correct pointer */ - ptr = pI8301->FbBase + pI8301->Scratch2.Start; - } - } - - if (nr_buffers) { - pI830->NumScanlineColorExpandBuffers = nr_buffers; - pI830->ScanlineColorExpandBuffers = (unsigned char **) - xnfcalloc(nr_buffers, sizeof(unsigned char *)); - - for (i = 0; i < nr_buffers; i++, ptr += width) - pI830->ScanlineColorExpandBuffers[i] = ptr; - - infoPtr->ScanlineCPUToScreenColorExpandFillFlags = - (NO_PLANEMASK | ROP_NEEDS_SOURCE | BIT_ORDER_IN_BYTE_MSBFIRST); - - infoPtr->ScanlineColorExpandBuffers = (unsigned char **) - xnfcalloc(1, sizeof(unsigned char *)); - infoPtr->NumScanlineColorExpandBuffers = 1; - - infoPtr->ScanlineColorExpandBuffers[0] = - pI830->ScanlineColorExpandBuffers[0]; - pI830->nextColorExpandBuf = 0; - - infoPtr->SetupForScanlineCPUToScreenColorExpandFill = - I830SetupForScanlineCPUToScreenColorExpandFill; - - infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = - I830SubsequentScanlineCPUToScreenColorExpandFill; - - infoPtr->SubsequentColorExpandScanline = - I830SubsequentColorExpandScanline; - -#if DO_SCANLINE_IMAGE_WRITE - infoPtr->NumScanlineImageWriteBuffers = 1; - infoPtr->ScanlineImageWriteBuffers = infoPtr->ScanlineColorExpandBuffers; - infoPtr->SetupForScanlineImageWrite = I830SetupForScanlineImageWrite; - infoPtr->SubsequentScanlineImageWriteRect = - I830SubsequentScanlineImageWriteRect; - infoPtr->SubsequentImageWriteScanline = I830SubsequentImageWriteScanline; - infoPtr->ScanlineImageWriteFlags = NO_GXCOPY | - NO_PLANEMASK | - ROP_NEEDS_SOURCE | - SCANLINE_PAD_DWORD; -#endif - } - - { - Bool shared_accel = FALSE; - int i; - - for(i = 0; i < pScrn->numEntities; i++) { - if(xf86IsEntityShared(pScrn->entityList[i])) - shared_accel = TRUE; - } - if(shared_accel == TRUE) - infoPtr->RestoreAccelState = I830RestoreAccelState; - } - - I830SelectBuffer(pScrn, I830_SELECT_FRONT); - - return XAAInit(pScreen, infoPtr); -} - -#ifdef XF86DRI -static unsigned int -CheckTiling(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned int tiled = 0; - - /* Check tiling */ - if (IS_I965G(pI830)) { - if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR) - tiled = 1; - if (pI830->bufferOffset == pI830->RotatedMem.Start && pI830->rotated_tiled == FENCE_XMAJOR) - tiled = 1; - if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR) - tiled = 1; - /* not really supported as it's always YMajor tiled */ - if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR) - tiled = 1; - } - - return tiled; -} -#else -#define CheckTiling(pScrn) 0 + if (pI830->useEXA) + return I830EXAInit(pScreen); #endif - -void -I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, - unsigned int planemask) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n", - color, rop, planemask); - - pI830->BR[13] = ((XAAGetPatternROP(rop) << 16) | - (pScrn->displayWidth * pI830->cpp)); - - pI830->BR[16] = color; - - switch (pScrn->bitsPerPixel) { - case 8: - break; - case 16: - pI830->BR[13] |= (1 << 24); - break; - case 32: - pI830->BR[13] |= ((1 << 25) | (1 << 24)); - break; - } -} - -void -I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h); - - { - BEGIN_LP_RING(6); - - if (pScrn->bitsPerPixel == 32) { - OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA | - COLOR_BLT_WRITE_RGB); - } else { - OUT_RING(COLOR_BLT_CMD); - } - OUT_RING(pI830->BR[13]); - OUT_RING((h << 16) | (w * pI830->cpp)); - OUT_RING(pI830->bufferOffset + (y * pScrn->displayWidth + x) * - pI830->cpp); - OUT_RING(pI830->BR[16]); - OUT_RING(0); - - ADVANCE_LP_RING(); - } - - if (IS_I965G(pI830)) - I830EmitFlush(pScrn); -} - -void -I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, - unsigned int planemask, int transparency_color) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SetupForScreenToScreenCopy %d %d %x %x %d\n", - xdir, ydir, rop, planemask, transparency_color); - - pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); - pI830->BR[13] |= XAAGetCopyROP(rop) << 16; - - switch (pScrn->bitsPerPixel) { - case 8: - break; - case 16: - pI830->BR[13] |= (1 << 24); - break; - case 32: - pI830->BR[13] |= ((1 << 25) | (1 << 24)); - break; - } - -} - -void -I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1, - int dst_x1, int dst_y1, int w, int h) -{ - I830Ptr pI830 = I830PTR(pScrn); - int dst_x2, dst_y2; - unsigned int tiled = CheckTiling(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n", - src_x1, src_y1, dst_x1, dst_y1, w, h); - - dst_x2 = dst_x1 + w; - dst_y2 = dst_y1 + h; - - if (tiled) - pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | - (pI830->BR[13] & 0xFFFF0000); - - { - BEGIN_LP_RING(8); - - if (pScrn->bitsPerPixel == 32) { - OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB | tiled << 15 | tiled << 11); - } else { - OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 15 | tiled << 11); - } - OUT_RING(pI830->BR[13]); - OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff)); - OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff)); - OUT_RING(pI830->bufferOffset); - OUT_RING((src_y1 << 16) | (src_x1 & 0xffff)); - OUT_RING(pI830->BR[13] & 0xFFFF); - OUT_RING(pI830->bufferOffset); - - ADVANCE_LP_RING(); - } - - if (IS_I965G(pI830)) - I830EmitFlush(pScrn); -} - -static void -I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty, - int fg, int bg, int rop, - unsigned int planemask) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SetupForMono8x8PatternFill\n"); - - pI830->BR[16] = pattx; - pI830->BR[17] = patty; - pI830->BR[18] = bg; - pI830->BR[19] = fg; - - pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); /* In bytes */ - pI830->BR[13] |= XAAGetPatternROP(rop) << 16; - if (bg == -1) - pI830->BR[13] |= (1 << 28); - - switch (pScrn->bitsPerPixel) { - case 8: - break; - case 16: - pI830->BR[13] |= (1 << 24); - break; - case 32: - pI830->BR[13] |= ((1 << 25) | (1 << 24)); - break; - } - -} - -static void -I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty, - int x, int y, int w, int h) -{ - I830Ptr pI830 = I830PTR(pScrn); - int x1, x2, y1, y2; - unsigned int tiled = CheckTiling(pScrn); - - x1 = x; - x2 = x + w; - y1 = y; - y2 = y + h; - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SubsequentMono8x8PatternFillRect\n"); - - if (tiled) - pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | - (pI830->BR[13] & 0xFFFF0000); - - { - BEGIN_LP_RING(10); - - if (pScrn->bitsPerPixel == 32) { - OUT_RING(XY_MONO_PAT_BLT_CMD | XY_MONO_PAT_BLT_WRITE_ALPHA | - XY_MONO_PAT_BLT_WRITE_RGB | - tiled << 11 | - ((patty << 8) & XY_MONO_PAT_VERT_SEED) | - ((pattx << 12) & XY_MONO_PAT_HORT_SEED)); - } else { - OUT_RING(XY_MONO_PAT_BLT_CMD | - tiled << 11 | - ((patty << 8) & XY_MONO_PAT_VERT_SEED) | - ((pattx << 12) & XY_MONO_PAT_HORT_SEED)); - } - OUT_RING(pI830->BR[13]); - OUT_RING((y1 << 16) | x1); - OUT_RING((y2 << 16) | x2); - OUT_RING(pI830->bufferOffset); - OUT_RING(pI830->BR[18]); /* bg */ - OUT_RING(pI830->BR[19]); /* fg */ - OUT_RING(pI830->BR[16]); /* pattern data */ - OUT_RING(pI830->BR[17]); - OUT_RING(0); - ADVANCE_LP_RING(); - } - - if (IS_I965G(pI830)) - I830EmitFlush(pScrn); -} - -static void -I830GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - XAAInfoRecPtr infoPtr = pI830->AccelInfoRec; - - if (pI830->nextColorExpandBuf == pI830->NumScanlineColorExpandBuffers) - I830Sync(pScrn); - - infoPtr->ScanlineColorExpandBuffers[0] = - pI830->ScanlineColorExpandBuffers[pI830->nextColorExpandBuf]; - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("using color expand buffer %d\n", pI830->nextColorExpandBuf); - - pI830->nextColorExpandBuf++; -} - -static void -I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n", - fg, bg, rop, planemask); - - /* Fill out register values */ - pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); - pI830->BR[13] |= XAAGetCopyROP(rop) << 16; - if (bg == -1) - pI830->BR[13] |= (1 << 29); - - switch (pScrn->bitsPerPixel) { - case 8: - break; - case 16: - pI830->BR[13] |= (1 << 24); - break; - case 32: - pI830->BR[13] |= ((1 << 25) | (1 << 24)); - break; - } - - pI830->BR[18] = bg; - pI830->BR[19] = fg; - - I830GetNextScanlineColorExpandBuffer(pScrn); -} - -static void -I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, - int x, int y, - int w, int h, int skipleft) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SubsequentScanlineCPUToScreenColorExpandFill " - "%d,%d %dx%x %d\n", x, y, w, h, skipleft); - - /* Fill out register values */ - pI830->BR[9] = (pI830->bufferOffset + - (y * pScrn->displayWidth + x) * pI830->cpp); - pI830->BR[11] = ((1 << 16) | w); -} - -static void -I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned int tiled = CheckTiling(pScrn); - - if (pI830->init == 0) { - pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - - pI830->FbBase); - } else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - - /* We have to use the primary screen's FbBase, as that's where - * we allocated Scratch2, so we get the correct pointer */ - pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - - pI8301->FbBase); - } - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n", - bufno, pI830->BR[12]); - - if (tiled) - pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | - (pI830->BR[13] & 0xFFFF0000); - - { - BEGIN_LP_RING(8); - - if (pScrn->bitsPerPixel == 32) { - OUT_RING(XY_MONO_SRC_BLT_CMD | XY_MONO_SRC_BLT_WRITE_ALPHA | - tiled << 11 | - XY_MONO_SRC_BLT_WRITE_RGB); - } else { - OUT_RING(XY_MONO_SRC_BLT_CMD | tiled << 11); - } - OUT_RING(pI830->BR[13]); - OUT_RING(0); /* x1 = 0, y1 = 0 */ - OUT_RING(pI830->BR[11]); /* x2 = w, y2 = 1 */ - OUT_RING(pI830->BR[9]); /* dst addr */ - OUT_RING(pI830->BR[12]); /* src addr */ - OUT_RING(pI830->BR[18]); /* bg */ - OUT_RING(pI830->BR[19]); /* fg */ - - ADVANCE_LP_RING(); - } - - /* Advance to next scanline. - */ - pI830->BR[9] += pScrn->displayWidth * pI830->cpp; - I830GetNextScanlineColorExpandBuffer(pScrn); - - if (IS_I965G(pI830)) - I830EmitFlush(pScrn); -} - -#if DO_SCANLINE_IMAGE_WRITE -static void -I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int trans_color, - int bpp, int depth) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SetupForScanlineImageWrite %x %x\n", rop, planemask); - - /* Fill out register values */ - pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); - pI830->BR[13] |= XAAGetCopyROP(rop) << 16; - - switch (pScrn->bitsPerPixel) { - case 8: - break; - case 16: - pI830->BR[13] |= (1 << 24); - break; - case 32: - pI830->BR[13] |= ((1 << 25) | (1 << 24)); - break; - } - - I830GetNextScanlineColorExpandBuffer(pScrn); -} - -static void -I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, int y, - int w, int h, int skipleft) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SubsequentScanlineImageWriteRect " - "%d,%d %dx%x %d\n", x, y, w, h, skipleft); - - /* Fill out register values */ - pI830->BR[9] = (pI830->bufferOffset + - (y * pScrn->displayWidth + x) * pI830->cpp); - pI830->BR[11] = ((1 << 16) | w); -} - -static void -I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned int tiled = CheckTiling(pScrn); - - if (pI830->init == 0) { - pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - - pI830->FbBase); - } else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - - /* We have to use the primary screen's FbBase, as that's where - * we allocated Scratch2, so we get the correct pointer */ - pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - - pI8301->FbBase); - } - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - ErrorF("I830SubsequentImageWriteScanline %d (addr %x)\n", - bufno, pI830->BR[12]); - - { - BEGIN_LP_RING(8); - - if (pScrn->bitsPerPixel == 32) { - OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - tiled << 11 | - XY_SRC_COPY_BLT_WRITE_RGB); - } else { - OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 11); - } - OUT_RING(pI830->BR[13]); - OUT_RING(0); /* x1 = 0, y1 = 0 */ - OUT_RING(pI830->BR[11]); /* x2 = w, y2 = 1 */ - OUT_RING(pI830->BR[9]); /* dst addr */ - OUT_RING(0); /* source origin (0,0) */ - OUT_RING(pI830->BR[11] & 0xffff); /* source pitch */ - OUT_RING(pI830->BR[12]); /* src addr */ - - ADVANCE_LP_RING(); - } - - /* Advance to next scanline. - */ - pI830->BR[9] += pScrn->displayWidth * pI830->cpp; - I830GetNextScanlineColorExpandBuffer(pScrn); -} -#endif - -/* Support for multiscreen */ -static void -I830RestoreAccelState(ScrnInfoPtr pScrn) -{ -#if 0 - /* might be needed, but everything is on a ring, so I don't think so */ - I830Sync(pScrn); +#ifdef I830_USE_XAA + return I830XAAInit(pScreen); #endif + return FALSE; } diff --git a/src/i830_dga.c b/src/i830_dga.c index bd45d61d..c78063e1 100644 --- a/src/i830_dga.c +++ b/src/i830_dga.c @@ -264,6 +264,7 @@ static void I830_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color) { +#ifdef I830_USE_XAA I830Ptr pI830 = I830PTR(pScrn); MARKER(); @@ -273,6 +274,7 @@ I830_FillRect(ScrnInfoPtr pScrn, (*pI830->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); SET_SYNC_FLAG(pI830->AccelInfoRec); } +#endif } static void @@ -304,6 +306,7 @@ static void I830_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx, int dsty) { +#ifdef I830_USE_XAA I830Ptr pI830 = I830PTR(pScrn); MARKER(); @@ -318,6 +321,7 @@ I830_BlitRect(ScrnInfoPtr pScrn, dstx, dsty, w, h); SET_SYNC_FLAG(pI830->AccelInfoRec); } +#endif } #if 0 diff --git a/src/i830_dri.c b/src/i830_dri.c index c9b52c48..8a52750f 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1019,7 +1019,6 @@ I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) { ScreenPtr pScreen = pWin->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); BoxPtr pbox = REGION_RECTS(prgn); int nbox = REGION_NUM_RECTS(prgn); @@ -1057,7 +1056,7 @@ I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) } I830SelectBuffer(pScrn, I830_SELECT_FRONT); - pI830->AccelInfoRec->NeedToSync = TRUE; + i830MarkSync(pScrn); } /* This routine is a modified form of XAADoBitBlt with the calls to @@ -1220,8 +1219,7 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } - - pI830->AccelInfoRec->NeedToSync = TRUE; + i830MarkSync(pScrn); } /* Use callbacks from dri.c to support pageflipping mode for a single diff --git a/src/i830_driver.c b/src/i830_driver.c index c0d96725..10a329c9 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -199,6 +199,18 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dri.h" #endif +#ifdef I830_USE_EXA +const char *I830exaSymbols[] = { + "exaGetVersion", + "exaDriverInit", + "exaDriverFini", + "exaOffscreenAlloc", + "exaOffscreenFree", + "exaWaitSync", + NULL +}; +#endif + #define BIT(x) (1 << (x)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define NB_OF(x) (sizeof (x) / sizeof (*x)) @@ -245,6 +257,9 @@ static PciChipsets I830BIOSPciChipsets[] = { */ typedef enum { +#if defined(I830_USE_XAA) && defined(I830_USE_EXA) + OPTION_ACCELMETHOD, +#endif OPTION_NOACCEL, OPTION_SW_CURSOR, OPTION_CACHE_LINES, @@ -272,6 +287,9 @@ typedef enum { } I830Opts; static OptionInfoRec I830BIOSOptions[] = { +#if defined(I830_USE_XAA) && defined(I830_USE_EXA) + {OPTION_ACCELMETHOD, "AccelMethod", OPTV_ANYSTR, {0}, FALSE}, +#endif {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE}, @@ -4202,6 +4220,42 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) { pI830->noAccel = TRUE; } + + /* + * The ugliness below: + * If either XAA or EXA (exclusive) is compiled in, default to it. + * + * If both are compiled in, and the user didn't specify noAccel, use the + * config option AccelMethod to determine which to use, defaulting to XAA + * if none is specified, or if the string was unrecognized. + * + * All this *could* go away if we removed XAA support from this driver, + * for example. :) + */ + if (!pI830->noAccel) { +#if (defined(I830_USE_EXA) && defined(I830_USE_XAA)) || !defined(I830_USE_EXA) + pI830->useEXA = FALSE; +#else + pI830->useEXA = TRUE; +#endif +#if defined(I830_USE_XAA) && defined(I830_USE_EXA) + int from = X_DEFAULT; + if ((s = (char *)xf86GetOptValString(pI830->Options, + OPTION_ACCELMETHOD))) { + if (!xf86NameCmp(s, "EXA")) { + from = X_CONFIG; + pI830->useEXA = TRUE; + } + else if (!xf86NameCmp(s, "XAA")) { + from = X_CONFIG; + pI830->useEXA = FALSE; + } + } +#endif + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n", + pI830->useEXA ? "EXA" : "XAA"); + } + if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) { pI830->SWCursor = TRUE; } @@ -5482,14 +5536,33 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86LoaderReqSymLists(I810fbSymbols, NULL); - if (!pI830->noAccel) { +#ifdef I830_USE_XAA + if (!pI830->noAccel && !pI830->useEXA) { if (!xf86LoadSubModule(pScrn, "xaa")) { PreInitCleanup(pScrn); return FALSE; } xf86LoaderReqSymLists(I810xaaSymbols, NULL); } +#endif + +#ifdef I830_USE_EXA + if (!pI830->noAccel && pI830->useEXA) { + XF86ModReqInfo req; + int errmaj, errmin; + memset(&req, 0, sizeof(req)); + req.majorversion = 2; + req.minorversion = 0; + if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, + &errmaj, &errmin)) { + LoaderErrorMsg(NULL, "exa", errmaj, errmin); + PreInitCleanup(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(I830exaSymbols, NULL); + } +#endif if (!pI830->SWCursor) { if (!xf86LoadSubModule(pScrn, "ramdac")) { PreInitCleanup(pScrn); @@ -5647,16 +5720,25 @@ ResetState(ScrnInfoPtr pScrn, Bool flush) for (i = 0; i < FENCE_NR; i++) OUTREG(FENCE + i * 4, 0); } - /* Flush the ring buffer (if enabled), then disable it. */ - if (pI830->AccelInfoRec != NULL && flush) { - temp = INREG(LP_RING + RING_LEN); - if (temp & 1) { - I830RefreshRing(pScrn); - I830Sync(pScrn); - DO_RING_IDLE(); - } - } + /* God this is ugly */ +#define flush_ring() do { \ + temp = INREG(LP_RING + RING_LEN); \ + if (temp & 1) { \ + I830RefreshRing(pScrn); \ + I830Sync(pScrn); \ + DO_RING_IDLE(); \ + } \ + } while(0) +#ifdef I830_USE_XAA + if (!pI830->useEXA && flush && pI830->AccelInfoRec) + flush_ring(); +#endif +#ifdef I830_USE_XAA + if (pI830->useEXA && flush && pI830->EXADriverPtr) + flush_ring(); +#endif + OUTREG(LP_RING + RING_LEN, 0); OUTREG(LP_RING + RING_HEAD, 0); OUTREG(LP_RING + RING_TAIL, 0); @@ -7509,10 +7591,7 @@ I830AdjustFrame(int scrnIndex, int x, int y, int flags) x, pI830->xoffset, y, pI830->yoffset); /* Sync the engine before adjust frame */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } + i830WaitSync(pScrn); if (pI830->MergedFB) { I830AdjustFrameMerged(scrnIndex, x, y, flags); @@ -7678,8 +7757,11 @@ I830BIOSLeaveVT(int scrnIndex, int flags) RestoreBIOSMemSize(pScrn); if (I830IsPrimary(pScrn)) I830UnbindAGPMemory(pScrn); - if (pI830->AccelInfoRec) + +#ifdef I830_USE_XAA + if (!pI830->useEXA && pI830->AccelInfoRec) pI830->AccelInfoRec->NeedToSync = FALSE; +#endif /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */ if (I830IsPrimary(pScrn)) { @@ -8133,10 +8215,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) #endif /* Sync the engine before mode switch */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } + i830WaitSync(pScrn); /* Check if our currentmode is about to change. We do this so if we * are rotating, we don't need to call the mode setup again. @@ -8304,7 +8383,9 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); +#ifdef I830_USE_XAA XAAInfoRecPtr infoPtr = pI830->AccelInfoRec; +#endif pI830->closing = TRUE; #ifdef XF86DRI @@ -8330,14 +8411,21 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) xfree(pI830->ScanlineColorExpandBuffers); pI830->ScanlineColorExpandBuffers = 0; } - +#ifdef I830_USE_XAA if (infoPtr) { if (infoPtr->ScanlineColorExpandBuffers) xfree(infoPtr->ScanlineColorExpandBuffers); XAADestroyInfoRec(infoPtr); pI830->AccelInfoRec = NULL; } - +#endif +#ifdef I830_USE_EXA + if (pI830->useEXA && pI830->EXADriverPtr) { + exaDriverFini(pScreen); + xfree(pI830->EXADriverPtr); + pI830->EXADriverPtr = NULL; + } +#endif if (pI830->CursorInfoRec) { xf86DestroyCursorInfoRec(pI830->CursorInfoRec); pI830->CursorInfoRec = 0; @@ -8509,12 +8597,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hotkey switch to 0x%lx.\n", (unsigned long) temp); - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - if (xf86IsEntityShared(pScrn->entityList[0])) - pI8302->AccelInfoRec->NeedToSync = FALSE; - } + i830WaitSync(pScrn); GetAttachableDisplayDeviceList(pScrn); @@ -8791,6 +8874,43 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) } void +i830WaitSync(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + +#ifdef I830_USE_XAA + if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec + && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } +#endif +#ifdef I830_USE_EXA + if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) { + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + exaWaitSync(pScreen); + } +#endif +} + +void +i830MarkSync(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + +#ifdef I830_USE_XAA + if (!pI830->useEXA && pI830->AccelInfoRec) + pI830->AccelInfoRec->NeedToSync = FALSE; +#endif +#ifdef I830_USE_EXA + if (pI830->useEXA && pI830->EXADriverPtr) { + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + exaMarkSync(pScreen); + } +#endif +} + +void I830InitpScrn(ScrnInfoPtr pScrn) { pScrn->PreInit = I830BIOSPreInit; diff --git a/src/i830_exa.c b/src/i830_exa.c new file mode 100644 index 00000000..bb75b24a --- /dev/null +++ b/src/i830_exa.c @@ -0,0 +1,594 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. +Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org> + Based on code from i830_xaa.c. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86_ansic.h" +#include "xf86.h" +#include "xaarop.h" +#include "i830.h" +#include "i810_reg.h" +#include "i830_reg.h" + +#ifdef I830DEBUG +#define DEBUG_I830FALLBACK 1 +#endif + +#ifdef DEBUG_I830FALLBACK +#define I830FALLBACK(s, arg...) \ +do { \ + DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \ + return FALSE; \ +} while(0) +#else +#define I830FALLBACK(s, arg...) \ +do { \ + return FALSE; \ +} while(0) +#endif + +float scale_units[2][2]; + +const int I830CopyROP[16] = +{ + ROP_0, /* GXclear */ + ROP_DSa, /* GXand */ + ROP_SDna, /* GXandReverse */ + ROP_S, /* GXcopy */ + ROP_DSna, /* GXandInverted */ + ROP_D, /* GXnoop */ + ROP_DSx, /* GXxor */ + ROP_DSo, /* GXor */ + ROP_DSon, /* GXnor */ + ROP_DSxn, /* GXequiv */ + ROP_Dn, /* GXinvert*/ + ROP_SDno, /* GXorReverse */ + ROP_Sn, /* GXcopyInverted */ + ROP_DSno, /* GXorInverted */ + ROP_DSan, /* GXnand */ + ROP_1 /* GXset */ +}; + +const int I830PatternROP[16] = +{ + ROP_0, + ROP_DPa, + ROP_PDna, + ROP_P, + ROP_DPna, + ROP_D, + ROP_DPx, + ROP_DPo, + ROP_DPon, + ROP_PDxn, + ROP_Dn, + ROP_PDno, + ROP_Pn, + ROP_DPno, + ROP_DPan, + ROP_1 +}; + +/* move to common.h */ +union intfloat { + float f; + unsigned int ui; +}; + +#define OUT_RING_F(x) do { \ + union intfloat tmp; \ + tmp.f = (float)(x); \ + OUT_RING(tmp.ui); \ +} while(0) + +Bool is_transform[2]; +PictTransform *transform[2]; + +Bool i830UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, + char *src, int src_pitch); +Bool i830DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch); + +extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr); +extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, + PixmapPtr, PixmapPtr, PixmapPtr); +extern Bool I915EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr); +extern Bool I915EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, + PixmapPtr, PixmapPtr, PixmapPtr); + +/** + * I830EXASync - wait for a command to finish + * @pScreen: current screen + * @marker: marker command to wait for + * + * Wait for the command specified by @marker to finish, then return. + */ +static void +I830EXASync(ScreenPtr pScreen, int marker) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + +#ifdef XF86DRI + /* VT switching tries to do this. */ + if (!pI830->LockHeld && pI830->directRenderingEnabled) + return; +#endif + + if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) + return; + + /* Send a flush instruction and then wait till the ring is empty. + * This is stronger than waiting for the blitter to finish as it also + * flushes the internal graphics caches. + */ + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(MI_NOOP); /* pad to quadword */ + ADVANCE_LP_RING(); + } + + I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0); + + pI830->LpRing->space = pI830->LpRing->mem.Size - 8; + pI830->nextColorExpandBuf = 0; +} + +/** + * I830EXAPrepareSolid - prepare for a Solid operation, if possible + * + * TODO: + * - support planemask using FILL_MONO_SRC_BLT_CMD? + */ +static Bool +I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + unsigned long offset, pitch; + + if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask)) + I830FALLBACK("planemask is not solid"); + + offset = exaGetPixmapOffset(pPixmap); + pitch = exaGetPixmapPitch(pPixmap); + + if ( offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0) + I830FALLBACK("pixmap offset not aligned"); + if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0) + I830FALLBACK("pixmap pitch not aligned"); + + pI830->BR[13] = pitch; + pI830->BR[13] |= I830PatternROP[alu] << 16; + + pI830->BR[16] = fg; + + /* + * Depth: 00 - 8 bit, 01 - 16 bit, 10 - 24 bit, 11 - 32 bit + */ + switch (pScrn->bitsPerPixel) { + case 8: + pI830->BR[13] |= ((0 << 25) | (0 << 24)); + break; + case 16: + pI830->BR[13] |= ((0 << 25) | (1 << 24)); + break; + case 32: + pI830->BR[13] |= ((1 << 25) | (1 << 24)); + break; + } + return TRUE; +} + +static void +I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int h, w; + unsigned long offset; + + /* pixmap's offset and pitch is aligned, + otherwise it falls back in PrepareSolid */ + offset = exaGetPixmapOffset(pPixmap) + y1 * exaGetPixmapPitch(pPixmap) + + x1 * (pPixmap->drawable.bitsPerPixel / 8); + + h = y2 - y1; + w = x2 - x1; + + { + BEGIN_LP_RING(6); + + if (pScrn->bitsPerPixel == 32) + OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA | + COLOR_BLT_WRITE_RGB); + else + OUT_RING(COLOR_BLT_CMD); + + OUT_RING(pI830->BR[13]); + OUT_RING((h << 16) | (w * (pPixmap->drawable.bitsPerPixel/8))); + OUT_RING(offset); + OUT_RING(pI830->BR[16]); + OUT_RING(0); + + ADVANCE_LP_RING(); + } +} + +static void +I830EXADoneSolid(PixmapPtr pPixmap) +{ + return; +} + +/** + * TODO: + * - support planemask using FULL_BLT_CMD? + */ +static Bool +I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, + int ydir, int alu, Pixel planemask) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + + if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask)) + I830FALLBACK("planemask is not solid"); + + pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap); + pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap); + + pI830->BR[13] = exaGetPixmapPitch(pDstPixmap); + pI830->BR[13] |= I830CopyROP[alu] << 16; + + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + pI830->BR[13] |= (1 << 24); + break; + case 32: + pI830->BR[13] |= ((1 << 25) | (1 << 24)); + break; + } + return TRUE; +} + +static void +I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1, + int dst_y1, int w, int h) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int dst_x2, dst_y2; + unsigned int src_off, dst_off; + + dst_x2 = dst_x1 + w; + dst_y2 = dst_y1 + h; + + src_off = pI830->copy_src_off; + dst_off = exaGetPixmapOffset(pDstPixmap); + + { + BEGIN_LP_RING(8); + + if (pScrn->bitsPerPixel == 32) + OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + else + OUT_RING(XY_SRC_COPY_BLT_CMD); + + OUT_RING(pI830->BR[13]); + OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff)); + OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff)); + OUT_RING(dst_off); + OUT_RING((src_y1 << 16) | (src_x1 & 0xffff)); + OUT_RING(pI830->copy_src_pitch); + OUT_RING(src_off); + + ADVANCE_LP_RING(); + } +} + +static void +I830EXADoneCopy(PixmapPtr pDstPixmap) +{ + return; +} + +static Bool +I830EXAUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, + char *src, int src_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int dst_pitch = exaGetPixmapPitch(pDst); + int dst_offset = exaGetPixmapOffset(pDst); + unsigned char *dst; + + I830Sync(pScrn); + +#ifdef I830DEBUG + ErrorF("Up->Screen: dst offset 0x%x, dst pitch %d, x %d, y %d, src %p, src pitch %d\n", + dst_offset, dst_pitch, x, y, src, src_pitch); +#endif + dst = pI830->FbBase + dst_offset + y*dst_pitch + + x* (pDst->drawable.bitsPerPixel/8); + w *= pDst->drawable.bitsPerPixel/8; + while(h--) { + memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + + return TRUE; +} + +static Bool +I830EXADownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int src_pitch = exaGetPixmapPitch(pSrc); + int src_offset = exaGetPixmapOffset(pSrc); + unsigned char *src = pI830->FbBase + src_offset + y*src_pitch + + x*(pSrc->drawable.bitsPerPixel/8); + + I830Sync(pScrn); + +#ifdef I830DEBUG + ErrorF("Screen->Mem: src offset 0x%x, src %p, src pitch %d, x %d, y %d, dst %p, dst_pitch %d\n", + src_offset, src, src_pitch, x, y, dst, dst_pitch); +#endif + w *= pSrc->drawable.bitsPerPixel/8; + while(h--) { + memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + + return TRUE; +} + +static void +IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int w, int h) +{ + /* should be same like I830Composite */ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int srcXend, srcYend, maskXend, maskYend; + PictVector v; + int pMask = 1; + + DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t" + "dstX %d, dstY %d\n\twidth %d, height %d\n\t" + "src_scale_x %f, src_scale_y %f, " + "mask_scale_x %f, mask_scale_y %f\n", + srcX, srcY, maskX, maskY, dstX, dstY, w, h, + scale_units[0][0], scale_units[0][1], + scale_units[1][0], scale_units[1][1]); + + if (scale_units[1][0] == -1 || scale_units[1][1] == -1) { + ErrorF("mask is null\n"); + pMask = 0; + } + + 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]); + } + DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t" + "maskX %d, maskY %d, maskXend %d, maskYend %d\n\t" + "dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend, + maskX, maskY, maskXend, maskYend, dstX, dstY); + + { + int vertex_count; + + if (pMask) + vertex_count = 4*6; + else + vertex_count = 4*4; + + BEGIN_LP_RING(6+vertex_count); + + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + + OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (vertex_count-1)); + + OUT_RING_F(dstX); + OUT_RING_F(dstY); + OUT_RING_F(srcX / scale_units[0][0]); + OUT_RING_F(srcY / scale_units[0][1]); + if (pMask) { + OUT_RING_F(maskX / scale_units[1][0]); + OUT_RING_F(maskY / scale_units[1][1]); + } + + OUT_RING_F(dstX); + OUT_RING_F(dstY + h); + OUT_RING_F(srcX / scale_units[0][0]); + OUT_RING_F(srcYend / scale_units[0][1]); + if (pMask) { + OUT_RING_F(maskX / scale_units[1][0]); + OUT_RING_F(maskYend / scale_units[1][1]); + } + + OUT_RING_F(dstX + w); + OUT_RING_F(dstY + h); + OUT_RING_F(srcXend / scale_units[0][0]); + OUT_RING_F(srcYend / scale_units[0][1]); + if (pMask) { + OUT_RING_F(maskXend / scale_units[1][0]); + OUT_RING_F(maskYend / scale_units[1][1]); + } + + OUT_RING_F(dstX + w); + OUT_RING_F(dstY); + OUT_RING_F(srcXend / scale_units[0][0]); + OUT_RING_F(srcY / scale_units[0][1]); + if (pMask) { + OUT_RING_F(maskXend / scale_units[1][0]); + OUT_RING_F(maskY / scale_units[1][1]); + } + ADVANCE_LP_RING(); + } +#ifdef I830DEBUG + ErrorF("sync after 3dprimitive"); + I830Sync(pScrn); +#endif + +} + +static void +IntelEXADoneComposite(PixmapPtr pDst) +{ + return; +} +/* + * TODO: + * - Dual head? + */ +Bool +I830EXAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + + pI830->EXADriverPtr = exaDriverAlloc(); + if (pI830->EXADriverPtr == NULL) { + pI830->noAccel = TRUE; + return FALSE; + } + memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr)); + + pI830->bufferOffset = 0; + pI830->EXADriverPtr->exa_major = 2; + pI830->EXADriverPtr->exa_minor = 0; + pI830->EXADriverPtr->memoryBase = pI830->FbBase; + pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start; + pI830->EXADriverPtr->memorySize = pI830->Offscreen.End; + + DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n", + pI830->EXADriverPtr->memoryBase, + pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize, + pI830->EXADriverPtr->offScreenBase, + pI830->EXADriverPtr->memorySize); + + if(pI830->EXADriverPtr->memorySize > + pI830->EXADriverPtr->offScreenBase) + pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS; + else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for " + "offscreen memory manager. Xv disabled\n"); + /* disable Xv here... */ + } + + pI830->EXADriverPtr->pixmapOffsetAlign = 256; + pI830->EXADriverPtr->pixmapPitchAlign = 64; + pI830->EXADriverPtr->maxX = 4095; + pI830->EXADriverPtr->maxY = 4095; + + /* Sync */ + pI830->EXADriverPtr->WaitMarker = I830EXASync; + + /* Solid fill */ + pI830->EXADriverPtr->PrepareSolid = I830EXAPrepareSolid; + pI830->EXADriverPtr->Solid = I830EXASolid; + pI830->EXADriverPtr->DoneSolid = I830EXADoneSolid; + + /* Copy */ + pI830->EXADriverPtr->PrepareCopy = I830EXAPrepareCopy; + pI830->EXADriverPtr->Copy = I830EXACopy; + pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy; + + /* Composite */ + if (IS_I9XX(pI830)) { + pI830->EXADriverPtr->CheckComposite = I915EXACheckComposite; + pI830->EXADriverPtr->PrepareComposite = I915EXAPrepareComposite; + pI830->EXADriverPtr->Composite = IntelEXAComposite; + pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite; + } else if (IS_I865G(pI830) || IS_I855(pI830) || IS_845G(pI830) || IS_I830(pI830)) { + pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite; + pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite; + pI830->EXADriverPtr->Composite = IntelEXAComposite; + pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite; + } + + /* Upload, download to/from Screen, experimental!! */ + pI830->EXADriverPtr->UploadToScreen = I830EXAUploadToScreen; + pI830->EXADriverPtr->DownloadFromScreen = I830EXADownloadFromScreen; + + if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) { + xfree(pI830->EXADriverPtr); + pI830->noAccel = TRUE; + return FALSE; + } + + I830SelectBuffer(pScrn, I830_SELECT_FRONT); + + return TRUE; +} diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c new file mode 100644 index 00000000..86e11d21 --- /dev/null +++ b/src/i830_exa_render.c @@ -0,0 +1,512 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Wang Zhenyu <zhenyu.z.wang@intel.com> + * Eric Anholt <eric@anholt.net> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i830.h" +#include "i830_reg.h" + +#ifdef I830DEBUG +#define DEBUG_I830FALLBACK 1 +#endif + +#ifdef DEBUG_I830FALLBACK +#define I830FALLBACK(s, arg...) \ +do { \ + DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \ + return FALSE; \ +} while(0) +#else +#define I830FALLBACK(s, arg...) \ +do { \ + return FALSE; \ +} while(0) +#endif + +extern float scale_units[2][2]; +extern Bool is_transform[2]; +extern PictTransform *transform[2]; + +struct blendinfo { + Bool dst_alpha; + Bool src_alpha; + CARD32 src_blend; + CARD32 dst_blend; +}; + +struct formatinfo { + int fmt; + CARD32 card_fmt; +}; + +extern Bool +I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture); + +extern Bool +I830EXAPrepareComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); + + +#define TB0C_LAST_STAGE (1 << 31) +#define TB0C_RESULT_SCALE_1X (0 << 29) +#define TB0C_RESULT_SCALE_2X (1 << 29) +#define TB0C_RESULT_SCALE_4X (2 << 29) +#define TB0C_OP_MODULE (3 << 25) +#define TB0C_OUTPUT_WRITE_CURRENT (0 << 24) +#define TB0C_OUTPUT_WRITE_ACCUM (1 << 24) +#define TB0C_ARG3_REPLICATE_ALPHA (1<<23) +#define TB0C_ARG3_INVERT (1<<22) +#define TB0C_ARG3_SEL_XXX +#define TB0C_ARG2_REPLICATE_ALPHA (1<<17) +#define TB0C_ARG2_INVERT (1<<16) +#define TB0C_ARG2_SEL_ONE (0 << 12) +#define TB0C_ARG2_SEL_FACTOR (1 << 12) +#define TB0C_ARG2_SEL_TEXEL0 (6 << 12) +#define TB0C_ARG2_SEL_TEXEL1 (7 << 12) +#define TB0C_ARG2_SEL_TEXEL2 (8 << 12) +#define TB0C_ARG2_SEL_TEXEL3 (9 << 12) +#define TB0C_ARG1_REPLICATE_ALPHA (1<<11) +#define TB0C_ARG1_INVERT (1<<10) +#define TB0C_ARG1_SEL_TEXEL0 (6 << 6) +#define TB0C_ARG1_SEL_TEXEL1 (7 << 6) +#define TB0C_ARG1_SEL_TEXEL2 (8 << 6) +#define TB0C_ARG1_SEL_TEXEL3 (9 << 6) +#define TB0C_ARG0_REPLICATE_ALPHA (1<<5) +#define TB0C_ARG0_SEL_XXX + +#define TB0A_CTR_STAGE_ENABLE (1<<31) +#define TB0A_RESULT_SCALE_1X (0 << 29) +#define TB0A_RESULT_SCALE_2X (1 << 29) +#define TB0A_RESULT_SCALE_4X (2 << 29) +#define TB0A_OP_MODULE (3 << 25) +#define TB0A_OUTPUT_WRITE_CURRENT (0<<24) +#define TB0A_OUTPUT_WRITE_ACCUM (1<<24) +#define TB0A_CTR_STAGE_SEL_BITS_XXX +#define TB0A_ARG3_SEL_XXX +#define TB0A_ARG3_INVERT (1<<17) +#define TB0A_ARG2_INVERT (1<<16) +#define TB0A_ARG2_SEL_ONE (0 << 12) +#define TB0A_ARG2_SEL_TEXEL0 (6 << 12) +#define TB0A_ARG2_SEL_TEXEL1 (7 << 12) +#define TB0A_ARG2_SEL_TEXEL2 (8 << 12) +#define TB0A_ARG2_SEL_TEXEL3 (9 << 12) +#define TB0A_ARG1_INVERT (1<<10) +#define TB0A_ARG1_SEL_TEXEL0 (6 << 6) +#define TB0A_ARG1_SEL_TEXEL1 (7 << 6) +#define TB0A_ARG1_SEL_TEXEL2 (8 << 6) +#define TB0A_ARG1_SEL_TEXEL3 (9 << 6) + +static struct blendinfo I830BlendOp[] = { + /* Clear */ + {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO}, + /* Src */ + {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO}, + /* Dst */ + {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE}, + /* Over */ + {0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA}, + /* OverReverse */ + {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE}, + /* In */ + {1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO}, + /* InReverse */ + {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA}, + /* Out */ + {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO}, + /* OutReverse */ + {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA}, + /* Atop */ + {1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, + /* AtopReverse */ + {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA}, + /* Xor */ + {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, + /* Add */ + {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE}, +}; + + +static struct formatinfo I830TexFormats[] = { + {PICT_a8r8g8b8, MT_32BIT_ARGB8888 }, + {PICT_x8r8g8b8, MT_32BIT_ARGB8888 }, + {PICT_a8b8g8r8, MT_32BIT_ABGR8888 }, + {PICT_x8b8g8r8, MT_32BIT_ABGR8888 }, + {PICT_r5g6b5, MT_16BIT_RGB565 }, + {PICT_a1r5g5b5, MT_16BIT_ARGB1555 }, + {PICT_x1r5g5b5, MT_16BIT_ARGB1555 }, + {PICT_a8, MT_8BIT_I8 }, +}; + +static Bool I830GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format) +{ + /* XXX: color buffer format for i830 */ + switch (pDstPicture->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + *dst_format = COLR_BUF_ARGB8888; + break; + case PICT_r5g6b5: + *dst_format = COLR_BUF_RGB565; + break; + case PICT_a1r5g5b5: + case PICT_x1r5g5b5: + *dst_format = COLR_BUF_ARGB1555; + break; + case PICT_a8: + *dst_format = COLR_BUF_8BIT; + break; + case PICT_a4r4g4b4: + case PICT_x4r4g4b4: + *dst_format = COLR_BUF_ARGB4444; + break; + default: + I830FALLBACK("Unsupported dest format 0x%x\n", + (int)pDstPicture->format); + } + + return TRUE; +} + + +static CARD32 I830GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format) +{ + CARD32 sblend, dblend; + + sblend = I830BlendOp[op].src_blend; + dblend = I830BlendOp[op].dst_blend; + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (PICT_FORMAT_A(dst_format) == 0 && I830BlendOp[op].dst_alpha) { + if (sblend == BLENDFACTOR_DST_ALPHA) + sblend = BLENDFACTOR_ONE; + else if (sblend == BLENDFACTOR_INV_DST_ALPHA) + sblend = BLENDFACTOR_ZERO; + } + + /* If the source alpha is being used, then we should only be in a case where + * the source blend factor is 0, and the source blend value is the mask + * channels multiplied by the source picture's alpha. + */ + if (pMask && pMask->componentAlpha && I830BlendOp[op].src_alpha) { + if (dblend == BLENDFACTOR_SRC_ALPHA) { + dblend = BLENDFACTOR_SRC_COLR; + } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) { + dblend = BLENDFACTOR_INV_SRC_COLR; + } + } + + return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | + (dblend << S8_DST_BLEND_FACTOR_SHIFT); +} + +static Bool I830CheckCompositeTexture(PicturePtr pPict, int unit) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + + if ((w > 0x7ff) || (h > 0x7ff)) + I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h); + + for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) + { + if (I830TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(I830TexFormats) / sizeof(I830TexFormats[0])) + I830FALLBACK("Unsupported picture format 0x%x\n", + (int)pPict->format); + + /* FIXME: fix repeat support */ + if (pPict->repeat) + I830FALLBACK("repeat unsupport now\n"); + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) + I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter); + + return TRUE; +} + +static Bool +I830TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit) +{ + + ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 format, offset, pitch, filter; + int w, h, i; + CARD32 wrap_mode = TEXCOORDMODE_CLAMP; + + offset = exaGetPixmapOffset(pPix); + pitch = exaGetPixmapPitch(pPix); + w = pPict->pDrawable->width; + h = pPict->pDrawable->height; + scale_units[unit][0] = pPix->drawable.width; + scale_units[unit][1] = pPix->drawable.height; + + for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) { + if (I830TexFormats[i].fmt == pPict->format) + break; + } + if ( i == sizeof(I830TexFormats)/ sizeof(I830TexFormats[0]) ) + I830FALLBACK("unknown texture format\n"); + format = I830TexFormats[i].card_fmt; + + if (pPict->repeat) + wrap_mode = TEXCOORDMODE_WRAP; /* XXX: correct ? */ + + switch (pPict->filter) { + case PictFilterNearest: + filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) | + (FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT)); + break; + case PictFilterBilinear: + filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) | + (FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT)); + break; + default: + filter = 0; + I830FALLBACK("Bad filter 0x%x\n", pPict->filter); + } + + { + if (pPix->drawable.bitsPerPixel == 8) + format |= MAP_SURFACE_8BIT; + else if (pPix->drawable.bitsPerPixel == 16) + format |= MAP_SURFACE_16BIT; + else + format |= MAP_SURFACE_32BIT; + + BEGIN_LP_RING(6); + OUT_RING(_3DSTATE_MAP_INFO_CMD); + OUT_RING(format | TEXMAP_INDEX(unit) | MAP_FORMAT_2D); + OUT_RING(((pPix->drawable.height - 1) << 16) | + (pPix->drawable.width - 1)); /* height, width */ + OUT_RING(offset); /* map address */ + OUT_RING(((pitch / 4) - 1) << 2); /* map pitch */ + OUT_RING(0); + ADVANCE_LP_RING(); + } + + { + BEGIN_LP_RING(2); + /* coord sets */ + OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | + ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | + TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | + TEXCOORD_ADDR_V_MODE(wrap_mode) | + ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode)); + OUT_RING(MI_NOOP); + + /* XXX: filter seems hang engine...*/ +#if 0 + OUT_RING(I830_STATE3D_MAP_FILTER | FILTER_MAP_INDEX(unit) | ENABLE_KEYS| DISABLE_COLOR_KEY | DISABLE_CHROMA_KEY | DISABLE_KILL_PIXEL |ENABLE_MIP_MODE_FILTER | MIPFILTER_NONE | filter); + OUT_RING(0); +#endif + + /* max & min mip level ? or base mip level? */ + + ADVANCE_LP_RING(); + } + + /* XXX */ + if (pPict->transform != 0) { + is_transform[unit] = TRUE; + transform[unit] = pPict->transform; + } else { + is_transform[unit] = FALSE; + } + +#ifdef I830DEBUG + ErrorF("try to sync to show any errors..."); + I830Sync(pScrn); +#endif + + return TRUE; +} + +Bool +I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + CARD32 tmp1; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(I830BlendOp) / sizeof(I830BlendOp[0])) + I830FALLBACK("Unsupported Composite op 0x%x\n", op); + + if (pMaskPicture != NULL && pMaskPicture->componentAlpha) { + /* Check if it's component alpha that relies on a source alpha and on + * the source value. We can only get one of those into the single + * source value that we get to blend with. + */ + if (I830BlendOp[op].src_alpha && + (I830BlendOp[op].src_blend != BLENDFACTOR_ZERO)) + I830FALLBACK("Component alpha not supported with source " + "alpha and source value blending.\n"); + } + + if (!I830CheckCompositeTexture(pSrcPicture, 0)) + I830FALLBACK("Check Src picture texture\n"); + if (pMaskPicture != NULL && !I830CheckCompositeTexture(pMaskPicture, 1)) + I830FALLBACK("Check Mask picture texture\n"); + + if (!I830GetDestFormat(pDstPicture, &tmp1)) + I830FALLBACK("Get Color buffer format\n"); + + return TRUE; +} + +Bool +I830EXAPrepareComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ +/* XXX: setup texture map from pixmap, vertex format, blend cntl */ + ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 dst_format, dst_offset, dst_pitch; + + I830GetDestFormat(pDstPicture, &dst_format); + dst_offset = exaGetPixmapOffset(pDst); + dst_pitch = exaGetPixmapPitch(pDst); + + if (!I830TextureSetup(pSrcPicture, pSrc, 0)) + I830FALLBACK("fail to setup src texture\n"); + if (pMask != NULL) { + if (!I830TextureSetup(pMaskPicture, pMask, 1)) + I830FALLBACK("fail to setup mask texture\n"); + } else { + is_transform[1] = FALSE; + scale_units[1][0] = -1; + scale_units[1][1] = -1; + } + + { + + CARD32 cblend, ablend, blendctl, vf2; + + BEGIN_LP_RING(22+6); + + /*color buffer*/ + OUT_RING(_3DSTATE_BUF_INFO_CMD); + OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch)); + OUT_RING(BUF_3D_ADDR(dst_offset)); + OUT_RING(MI_NOOP); + + OUT_RING(_3DSTATE_DST_BUF_VARS_CMD); + OUT_RING(dst_format); + + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(MI_NOOP); /* pad to quadword */ + /* defaults */ + OUT_RING(_3DSTATE_DFLT_Z_CMD); + OUT_RING(0); + + OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD); + OUT_RING(0); + + OUT_RING(_3DSTATE_DFLT_SPEC_CMD); + OUT_RING(0); + + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0); + OUT_RING((1 << S3_POINT_WIDTH_SHIFT) | (2 << S3_LINE_WIDTH_SHIFT) | + S3_CULLMODE_NONE | S3_VERTEXHAS_XY); + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0); + if (pMask) + vf2 = 2 << 12; /* 2 texture coord sets */ + else + vf2 = 1 << 12; + vf2 |= (TEXCOORDFMT_2D << 16); + if (pMask) + vf2 |= (TEXCOORDFMT_2D << 18); + else + vf2 |= (TEXCOORDFMT_1D << 18); + + vf2 |= (TEXCOORDFMT_1D << 20); + vf2 |= (TEXCOORDFMT_1D << 22); + vf2 |= (TEXCOORDFMT_1D << 24); + vf2 |= (TEXCOORDFMT_1D << 26); + vf2 |= (TEXCOORDFMT_1D << 28); + vf2 |= (TEXCOORDFMT_1D << 30); + OUT_RING(vf2); + + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(MI_NOOP); /* pad to quadword */ + /* For (src In mask) operation */ + /* IN operator: Multiply src by mask components or mask alpha.*/ + /* TEXBLENDOP_MODULE: arg1*arg2 */ + cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE | + TB0C_OUTPUT_WRITE_CURRENT; + ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | + TB0A_OUTPUT_WRITE_CURRENT; + + cblend |= TB0C_ARG1_SEL_TEXEL0; + ablend |= TB0A_ARG1_SEL_TEXEL0; + if (pMask) { + if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8) + cblend |= TB0C_ARG2_SEL_TEXEL1; + else + cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA); + ablend |= TB0A_ARG2_SEL_TEXEL1; + } else { + cblend |= TB0C_ARG2_SEL_ONE; + ablend |= TB0A_ARG2_SEL_ONE; + } + + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_BLEND_STAGE(0)|1); + OUT_RING(cblend); + OUT_RING(ablend); + OUT_RING(0); + + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(MI_NOOP); /* pad to quadword */ + + blendctl = I830GetBlendCntl(op, pMaskPicture, pDstPicture->format); + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0); + OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |(blendctl<<4) | + S8_ENABLE_COLOR_BUFFER_WRITE); + ADVANCE_LP_RING(); + } + +#ifdef I830DEBUG + Error("try to sync to show any errors..."); + I830Sync(pScrn); +#endif + + return TRUE; +} + diff --git a/src/i830_memory.c b/src/i830_memory.c index f270a51e..88dc5acb 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -878,6 +878,34 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) } return FALSE; } +#ifdef I830_USE_EXA + size = lineSize * pScrn->virtualY; + size = ROUND_TO_PAGE(size); + + if (tileable) { + align = KB(512); + alignflags = ALIGN_BOTH_ENDS; + } else { + align = KB(64); + alignflags = 0; + } + + alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), + &(pI830->StolenPool), size, align, + flags | alignflags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "offscreen memory. Not enough VRAM?\n"); + } + return FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate " + "offscreen memory at 0x%lx, size %ld KB\n", + pI830->Offscreen.Start, pI830->Offscreen.Size/1024); + } +#endif } else { long lineSize; long extra = 0; diff --git a/src/i830_reg.h b/src/i830_reg.h index be12e760..f9c1df9f 100644 --- a/src/i830_reg.h +++ b/src/i830_reg.h @@ -31,6 +31,23 @@ #define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value) +#define CMD_3D (0x3<<29) + +#define PRIM3D_INLINE (CMD_3D | (0x1f<<24)) +#define PRIM3D_TRILIST (0x0<<18) +#define PRIM3D_TRISTRIP (0x1<<18) +#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) +#define PRIM3D_TRIFAN (0x3<<18) +#define PRIM3D_POLY (0x4<<18) +#define PRIM3D_LINELIST (0x5<<18) +#define PRIM3D_LINESTRIP (0x6<<18) +#define PRIM3D_RECTLIST (0x7<<18) +#define PRIM3D_POINTLIST (0x8<<18) +#define PRIM3D_DIB (0x9<<18) +#define PRIM3D_CLEAR_RECT (0xa<<18) +#define PRIM3D_ZONE_INIT (0xd<<18) +#define PRIM3D_MASK (0x1f<<18) + #define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24)) #define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16) #define AA_LINE_ECAAR_WIDTH_0_5 0 @@ -85,6 +102,8 @@ #define COLR_BUF_RGB555 (1<<8) #define COLR_BUF_RGB565 (2<<8) #define COLR_BUF_ARGB8888 (3<<8) +#define COLR_BUF_ARGB4444 (8<<8) +#define COLR_BUF_ARGB1555 (9<<8) #define DEPTH_IS_Z 0 #define DEPTH_IS_W (1<<6) #define DEPTH_FRMT_16_FIXED 0 @@ -202,6 +221,22 @@ #define ENABLE_DST_ABLEND_FACTOR (1<<5) #define DST_ABLEND_FACT(x) (x) +#define BLENDFACTOR_ZERO 0x01 +#define BLENDFACTOR_ONE 0x02 +#define BLENDFACTOR_SRC_COLR 0x03 +#define BLENDFACTOR_INV_SRC_COLR 0x04 +#define BLENDFACTOR_SRC_ALPHA 0x05 +#define BLENDFACTOR_INV_SRC_ALPHA 0x06 +#define BLENDFACTOR_DST_ALPHA 0x07 +#define BLENDFACTOR_INV_DST_ALPHA 0x08 +#define BLENDFACTOR_DST_COLR 0x09 +#define BLENDFACTOR_INV_DST_COLR 0x0a +#define BLENDFACTOR_SRC_ALPHA_SATURATE 0x0b +#define BLENDFACTOR_CONST_COLOR 0x0c +#define BLENDFACTOR_INV_CONST_COLOR 0x0d +#define BLENDFACTOR_CONST_ALPHA 0x0e +#define BLENDFACTOR_INV_CONST_ALPHA 0x0f +#define BLENDFACTOR_MASK 0x0f /* _3DSTATE_MAP_BLEND_ARG, p152 */ #define _3DSTATE_MAP_BLEND_ARG_CMD(stage) (CMD_3D|(0x0e<<24)|((stage)<<20)) @@ -301,6 +336,7 @@ /* _3DSTATE_MAP_COORD_SETS, p164 */ #define _3DSTATE_MAP_COORD_SET_CMD (CMD_3D|(0x1c<<24)|(0x01<<19)) +#define TEXCOORD_SET(n) ((n)<<16) #define ENABLE_TEXCOORD_PARAMS (1<<15) #define TEXCOORDS_ARE_NORMAL (1<<14) #define TEXCOORDS_ARE_IN_TEXELUNITS 0 @@ -329,6 +365,13 @@ #define CUBE_NEGZ_ENABLE (1<<1) #define CUBE_POSZ_ENABLE (1<<0) +#define _3DSTATE_MAP_INFO_CMD (CMD_3D|(0x1d<<24)|(0x0<<16)|3) +#define TEXMAP_INDEX(x) ((x)<<28) +#define MAP_SURFACE_8BIT (1<<24) +#define MAP_SURFACE_16BIT (2<<24) +#define MAP_SURFACE_32BIT (3<<24) +#define MAP_FORMAT_2D (0) +#define MAP_FORMAT_3D_CUBE (1<<11) /* _3DSTATE_MODES_1, p190 */ #define _3DSTATE_MODES_1_CMD (CMD_3D|(0x08<<24)) @@ -523,14 +566,57 @@ /* Stipple command, carried over from the i810, apparently: */ -#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) +#define _3DSTATE_STIPPLE (CMD_3D|(0x1d<<24)|(0x83<<16)) #define ST1_ENABLE (1<<16) #define ST1_MASK (0xffff) - - -#define _3DSTATE_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16)) -#define LOAD_TEXTURE_MAP0 (1<<11) +#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 (CMD_3D|(0x1d<<24)|(0x04<<16)) +#define I1_LOAD_S(n) (1<<((n)+4)) +#define S3_POINT_WIDTH_SHIFT 23 +#define S3_LINE_WIDTH_SHIFT 19 +#define S3_ALPHA_SHADE_MODE_SHIFT 18 +#define S3_FOG_SHADE_MODE_SHIFT 17 +#define S3_SPEC_SHADE_MODE_SHIFT 16 +#define S3_COLOR_SHADE_MODE_SHIFT 15 +#define S3_CULL_MODE_SHIFT 13 +#define S3_CULLMODE_BOTH (0) +#define S3_CULLMODE_NONE (1<<13) +#define S3_CULLMODE_CW (2<<13) +#define S3_CULLMODE_CCW (3<<13) +#define S3_POINT_WIDTH_PRESENT (1<<12) +#define S3_SPEC_FOG_PRESENT (1<<11) +#define S3_DIFFUSE_PRESENT (1<<10) +#define S3_DEPTH_OFFSET_PRESENT (1<<9) +#define S3_POSITION_SHIFT 6 +#define S3_VERTEXHAS_XYZ (1<<6) +#define S3_VERTEXHAS_XYZW (2<<6) +#define S3_VERTEXHAS_XY (3<<6) +#define S3_VERTEXHAS_XYW (4<<6) +#define S3_ENABLE_SPEC_ADD (1<<5) +#define S3_ENABLE_FOG (1<<4) +#define S3_ENABLE_LOCAL_DEPTH_BIAS (1<<3) +#define S3_ENABLE_SPRITE_POINT (1<<1) +#define S3_ENABLE_ANTIALIASING 1 +#define S8_ENABLE_ALPHA_TEST (1<<31) +#define S8_ALPHA_TEST_FUNC_SHIFT 28 +#define S8_ALPHA_REFVALUE_SHIFT 20 +#define S8_ENABLE_DEPTH_TEST (1<<19) +#define S8_DEPTH_TEST_FUNC_SHIFT 16 +#define S8_ENABLE_COLOR_BLEND (1<<15) +#define S8_COLOR_BLEND_FUNC_SHIFT 12 +#define S8_BLENDFUNC_ADD (0) +#define S8_BLENDFUNC_SUB (1<<12) +#define S8_BLENDFUNC_RVRSE_SUB (2<<12) +#define S8_BLENDFUNC_MIN (3<<12) +#define S8_BLENDFUNC_MAX (4<<12) +#define S8_SRC_BLEND_FACTOR_SHIFT 8 +#define S8_DST_BLEND_FACTOR_SHIFT 4 +#define S8_ENABLE_DEPTH_BUFFER_WRITE (1<<3) +#define S8_ENABLE_COLOR_BUFFER_WRITE (1<<2) + +#define _3DSTATE_LOAD_STATE_IMMEDIATE_2 (CMD_3D|(0x1d<<24)|(0x03<<16)) +#define LOAD_TEXTURE_MAP(x) (1<<((x)+11)) +#define LOAD_TEXTURE_BLEND_STAGE(x) (1<<((x)+7)) #define LOAD_GLOBAL_COLOR_FACTOR (1<<6) #define TM0S0_ADDRESS_MASK 0xfffffffc @@ -591,6 +677,8 @@ #define TM0S2_CUBE_FACE_ENA_SHIFT 15 #define TM0S2_CUBE_FACE_ENA_MASK (1<<15) #define TM0S2_MAP_FORMAT (1<<14) +#define TM0S2_MAP_2D (0<<14) +#define TM0S2_MAP_3D_CUBE (1<<14) #define TM0S2_VERTICAL_LINE_STRIDE (1<<13) #define TM0S2_VERITCAL_LINE_STRIDE_OFF (1<<12) #define TM0S2_OUTPUT_CHAN_SHIFT 10 @@ -634,4 +722,23 @@ #define FLUSH_MAP_CACHE (1<<0) +#define _3DSTATE_MAP_FILTER_CMD (CMD_3D|(0x1c<<24)|(0x02<<19)) +#define FILTER_TEXMAP_INDEX(x) ((x) << 16) +#define MAG_MODE_FILTER_ENABLE (1 << 5) +#define MIN_MODE_FILTER_ENABLE (1 << 2) +#define MAG_MAPFILTER_NEAREST (0 << 3) +#define MAG_MAPFILTER_LINEAR (1 << 3) +#define MAG_MAPFILTER_ANISOTROPIC (2 << 3) +#define MIN_MAPFILTER_NEAREST (0) +#define MIN_MAPFILTER_LINEAR (1) +#define MIN_MAPFILTER_ANISOTROPIC (2) +#define ENABLE_KEYS (1<<15) +#define DISABLE_COLOR_KEY 0 +#define DISABLE_CHROMA_KEY 0 +#define DISABLE_KILL_PIXEL 0 +#define ENABLE_MIP_MODE_FILTER (1 << 9) +#define MIPFILTER_NONE 0 +#define MIPFILTER_NEAREST 1 +#define MIPFILTER_LINEAR 3 + #endif diff --git a/src/i830_rotate.c b/src/i830_rotate.c index 020d7e61..76effa29 100644 --- a/src/i830_rotate.c +++ b/src/i830_rotate.c @@ -1016,21 +1016,26 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) } } - /* Don't allow pixmap cache or offscreen pixmaps when rotated */ - /* XAA needs some serious fixing for this to happen */ - if (pI830->rotation == RR_Rotate_0) { - pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE; - pI830->AccelInfoRec->UsingPixmapCache = TRUE; - /* funny as it seems this will enable XAA's createpixmap */ - pI830->AccelInfoRec->maxOffPixWidth = 0; - pI830->AccelInfoRec->maxOffPixHeight = 0; - } else { - pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER; - pI830->AccelInfoRec->UsingPixmapCache = FALSE; - /* funny as it seems this will disable XAA's createpixmap */ - pI830->AccelInfoRec->maxOffPixWidth = 1; - pI830->AccelInfoRec->maxOffPixHeight = 1; +#ifdef I830_USE_XAA + if (pI830->AccelInfoRec != NULL) { + /* Don't allow pixmap cache or offscreen pixmaps when rotated */ + /* XAA needs some serious fixing for this to happen */ + if (pI830->rotation == RR_Rotate_0) { + pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | + PIXMAP_CACHE; + pI830->AccelInfoRec->UsingPixmapCache = TRUE; + /* funny as it seems this will enable XAA's createpixmap */ + pI830->AccelInfoRec->maxOffPixWidth = 0; + pI830->AccelInfoRec->maxOffPixHeight = 0; + } else { + pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER; + pI830->AccelInfoRec->UsingPixmapCache = FALSE; + /* funny as it seems this will disable XAA's createpixmap */ + pI830->AccelInfoRec->maxOffPixWidth = 1; + pI830->AccelInfoRec->maxOffPixHeight = 1; + } } +#endif return TRUE; diff --git a/src/i830_video.c b/src/i830_video.c index 7f6eb80d..1c5bf4eb 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -2922,8 +2922,6 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) ScreenPtr pScreen; FBLinearPtr new_linear = NULL; - DPRINTF(PFX, "I830AllocateMemory\n"); - if (linear) { if (linear->size >= size) return linear; diff --git a/src/i830_xaa.c b/src/i830_xaa.c new file mode 100644 index 00000000..6948be08 --- /dev/null +++ b/src/i830_xaa.c @@ -0,0 +1,712 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86_ansic.h" +#include "xf86.h" +#include "xaarop.h" +#include "i830.h" +#include "i810_reg.h" + +#ifndef DO_SCANLINE_IMAGE_WRITE +#define DO_SCANLINE_IMAGE_WRITE 0 +#endif + +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Reformatted with GNU indent (2.2.8), using the following options: + * + * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78 + * -lp -npcs -psl -sob -ss -br -ce -sc -hnl + * + * This provides a good match with the original i810 code and preferred + * XFree86 formatting conventions. + * + * When editing this driver, please follow the existing formatting, and edit + * with <TAB> characters expanded at 8-column intervals. + */ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +/* I830 Accel Functions */ +static void I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int pattx, int patty, + int fg, int bg, int rop, + unsigned int planemask); +static void I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int pattx, int patty, + int x, int y, int w, int h); + +static void I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int mask); + +static void I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr + pScrn, int x, + int y, int w, + int h, + int skipleft); + +static void I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); + +#if DO_SCANLINE_IMAGE_WRITE +static void I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int trans_color, int bpp, + int depth); +static void I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft); +static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno); +#endif +static void I830RestoreAccelState(ScrnInfoPtr pScrn); + +#ifdef I830_USE_EXA +extern const int I830PatternROP[16]; +extern const int I830CopyROP[16]; +#endif + +Bool +I830XAAInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int i; + int width = 0; + int nr_buffers = 0; + unsigned char *ptr = NULL; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830XAAInit\n"); + + pI830->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if (!infoPtr) + return FALSE; + + pI830->bufferOffset = 0; + infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE; + + /* Use the same sync function as the I830. + */ + infoPtr->Sync = I830Sync; + + /* Everything else is different enough to justify different functions */ + { + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = I830SetupForSolidFill; + infoPtr->SubsequentSolidFillRect = I830SubsequentSolidFillRect; + } + + { + infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY); + + infoPtr->SetupForScreenToScreenCopy = I830SetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = + I830SubsequentScreenToScreenCopy; + } + + { + infoPtr->SetupForMono8x8PatternFill = I830SetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + I830SubsequentMono8x8PatternFillRect; + + infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS | + HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_ORIGIN| + BIT_ORDER_IN_BYTE_MSBFIRST | + NO_PLANEMASK); + + } + + /* On the primary screen */ + if (pI830->init == 0) { + if (pI830->Scratch.Size != 0) { + width = ((pScrn->displayWidth + 31) & ~31) / 8; + nr_buffers = pI830->Scratch.Size / width; + ptr = pI830->FbBase + pI830->Scratch.Start; + } + } else { + /* On the secondary screen */ + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + if (pI8301->Scratch2.Size != 0) { + width = ((pScrn->displayWidth + 31) & ~31) / 8; + nr_buffers = pI8301->Scratch2.Size / width; + /* We have to use the primary screen's FbBase, as that's where + * we allocated Scratch2, so we get the correct pointer */ + ptr = pI8301->FbBase + pI8301->Scratch2.Start; + } + } + + if (nr_buffers) { + pI830->NumScanlineColorExpandBuffers = nr_buffers; + pI830->ScanlineColorExpandBuffers = (unsigned char **) + xnfcalloc(nr_buffers, sizeof(unsigned char *)); + + for (i = 0; i < nr_buffers; i++, ptr += width) + pI830->ScanlineColorExpandBuffers[i] = ptr; + + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = + (NO_PLANEMASK | ROP_NEEDS_SOURCE | BIT_ORDER_IN_BYTE_MSBFIRST); + + infoPtr->ScanlineColorExpandBuffers = (unsigned char **) + xnfcalloc(1, sizeof(unsigned char *)); + infoPtr->NumScanlineColorExpandBuffers = 1; + + infoPtr->ScanlineColorExpandBuffers[0] = + pI830->ScanlineColorExpandBuffers[0]; + pI830->nextColorExpandBuf = 0; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + I830SetupForScanlineCPUToScreenColorExpandFill; + + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + I830SubsequentScanlineCPUToScreenColorExpandFill; + + infoPtr->SubsequentColorExpandScanline = + I830SubsequentColorExpandScanline; + +#if DO_SCANLINE_IMAGE_WRITE + infoPtr->NumScanlineImageWriteBuffers = 1; + infoPtr->ScanlineImageWriteBuffers = + infoPtr->ScanlineColorExpandBuffers; + infoPtr->SetupForScanlineImageWrite = I830SetupForScanlineImageWrite; + infoPtr->SubsequentScanlineImageWriteRect = + I830SubsequentScanlineImageWriteRect; + infoPtr->SubsequentImageWriteScanline = + I830SubsequentImageWriteScanline; + infoPtr->ScanlineImageWriteFlags = NO_GXCOPY | + NO_PLANEMASK | + ROP_NEEDS_SOURCE | + SCANLINE_PAD_DWORD; +#endif + } + + { + Bool shared_accel = FALSE; + int i; + + for(i = 0; i < pScrn->numEntities; i++) { + if(xf86IsEntityShared(pScrn->entityList[i])) + shared_accel = TRUE; + } + if(shared_accel == TRUE) + infoPtr->RestoreAccelState = I830RestoreAccelState; + } + + I830SelectBuffer(pScrn, I830_SELECT_FRONT); + + return XAAInit(pScreen, infoPtr); +} + +#ifdef XF86DRI +static unsigned int +CheckTiling(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned int tiled = 0; + + /* Check tiling */ + if (IS_I965G(pI830)) { + if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR) + tiled = 1; + if (pI830->bufferOffset == pI830->RotatedMem.Start && pI830->rotated_tiled == FENCE_XMAJOR) + tiled = 1; + if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR) + tiled = 1; + /* not really supported as it's always YMajor tiled */ + if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR) + tiled = 1; + } + + return tiled; +} +#else +#define CheckTiling(pScrn) 0 +#endif + +void +I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n", + color, rop, planemask); + +#ifdef I830_USE_EXA + /* This function gets used by I830DRIInitBuffers(), and we might not have + * XAAGetPatternROP() available. So just use the ROPs from our EXA code + * if available. + */ + pI830->BR[13] = ((I830PatternROP[rop] << 16) | + (pScrn->displayWidth * pI830->cpp)); +#else + pI830->BR[13] = ((XAAGetPatternROP(rop) << 16) | + (pScrn->displayWidth * pI830->cpp)); +#endif + + pI830->BR[16] = color; + + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + pI830->BR[13] |= (1 << 24); + break; + case 32: + pI830->BR[13] |= ((1 << 25) | (1 << 24)); + break; + } +} + +void +I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h); + + { + BEGIN_LP_RING(6); + + if (pScrn->bitsPerPixel == 32) { + OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA | + COLOR_BLT_WRITE_RGB); + } else { + OUT_RING(COLOR_BLT_CMD); + } + OUT_RING(pI830->BR[13]); + OUT_RING((h << 16) | (w * pI830->cpp)); + OUT_RING(pI830->bufferOffset + (y * pScrn->displayWidth + x) * + pI830->cpp); + OUT_RING(pI830->BR[16]); + OUT_RING(0); + + ADVANCE_LP_RING(); + } + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); +} + +void +I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SetupForScreenToScreenCopy %d %d %x %x %d\n", + xdir, ydir, rop, planemask, transparency_color); + + pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); +#ifdef I830_USE_EXA + /* This function gets used by I830DRIInitBuffers(), and we might not have + * XAAGetCopyROP() available. So just use the ROPs from our EXA code + * if available. + */ + pI830->BR[13] |= I830CopyROP[rop] << 16; +#else + pI830->BR[13] |= XAAGetCopyROP(rop) << 16; +#endif + + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + pI830->BR[13] |= (1 << 24); + break; + case 32: + pI830->BR[13] |= ((1 << 25) | (1 << 24)); + break; + } + +} + +void +I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1, + int dst_x1, int dst_y1, int w, int h) +{ + I830Ptr pI830 = I830PTR(pScrn); + int dst_x2, dst_y2; + unsigned int tiled = CheckTiling(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n", + src_x1, src_y1, dst_x1, dst_y1, w, h); + + dst_x2 = dst_x1 + w; + dst_y2 = dst_y1 + h; + + if (tiled) + pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | + (pI830->BR[13] & 0xFFFF0000); + + { + BEGIN_LP_RING(8); + + if (pScrn->bitsPerPixel == 32) { + OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB | tiled << 15 | tiled << 11); + } else { + OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 15 | tiled << 11); + } + OUT_RING(pI830->BR[13]); + OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff)); + OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff)); + OUT_RING(pI830->bufferOffset); + OUT_RING((src_y1 << 16) | (src_x1 & 0xffff)); + OUT_RING(pI830->BR[13] & 0xFFFF); + OUT_RING(pI830->bufferOffset); + + ADVANCE_LP_RING(); + } + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); +} + +static void +I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty, + int fg, int bg, int rop, + unsigned int planemask) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SetupForMono8x8PatternFill\n"); + + pI830->BR[16] = pattx; + pI830->BR[17] = patty; + pI830->BR[18] = bg; + pI830->BR[19] = fg; + + pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); /* In bytes */ + pI830->BR[13] |= XAAGetPatternROP(rop) << 16; + if (bg == -1) + pI830->BR[13] |= (1 << 28); + + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + pI830->BR[13] |= (1 << 24); + break; + case 32: + pI830->BR[13] |= ((1 << 25) | (1 << 24)); + break; + } + +} + +static void +I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty, + int x, int y, int w, int h) +{ + I830Ptr pI830 = I830PTR(pScrn); + int x1, x2, y1, y2; + unsigned int tiled = CheckTiling(pScrn); + + x1 = x; + x2 = x + w; + y1 = y; + y2 = y + h; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SubsequentMono8x8PatternFillRect\n"); + + if (tiled) + pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | + (pI830->BR[13] & 0xFFFF0000); + + { + BEGIN_LP_RING(10); + + if (pScrn->bitsPerPixel == 32) { + OUT_RING(XY_MONO_PAT_BLT_CMD | XY_MONO_PAT_BLT_WRITE_ALPHA | + XY_MONO_PAT_BLT_WRITE_RGB | tiled << 11 | + ((patty << 8) & XY_MONO_PAT_VERT_SEED) | + ((pattx << 12) & XY_MONO_PAT_HORT_SEED)); + } else { + OUT_RING(XY_MONO_PAT_BLT_CMD | tiled << 11 | + ((patty << 8) & XY_MONO_PAT_VERT_SEED) | + ((pattx << 12) & XY_MONO_PAT_HORT_SEED)); + } + OUT_RING(pI830->BR[13]); + OUT_RING((y1 << 16) | x1); + OUT_RING((y2 << 16) | x2); + OUT_RING(pI830->bufferOffset); + OUT_RING(pI830->BR[18]); /* bg */ + OUT_RING(pI830->BR[19]); /* fg */ + OUT_RING(pI830->BR[16]); /* pattern data */ + OUT_RING(pI830->BR[17]); + OUT_RING(0); + ADVANCE_LP_RING(); + } + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); +} + +static void +I830GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + XAAInfoRecPtr infoPtr = pI830->AccelInfoRec; + + if (pI830->nextColorExpandBuf == pI830->NumScanlineColorExpandBuffers) + I830Sync(pScrn); + + infoPtr->ScanlineColorExpandBuffers[0] = + pI830->ScanlineColorExpandBuffers[pI830->nextColorExpandBuf]; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("using color expand buffer %d\n", pI830->nextColorExpandBuf); + + pI830->nextColorExpandBuf++; +} + +static void +I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n", + fg, bg, rop, planemask); + + /* Fill out register values */ + pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); + pI830->BR[13] |= XAAGetCopyROP(rop) << 16; + if (bg == -1) + pI830->BR[13] |= (1 << 29); + + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + pI830->BR[13] |= (1 << 24); + break; + case 32: + pI830->BR[13] |= ((1 << 25) | (1 << 24)); + break; + } + + pI830->BR[18] = bg; + pI830->BR[19] = fg; + + I830GetNextScanlineColorExpandBuffer(pScrn); +} + +static void +I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, + int w, int h, int skipleft) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SubsequentScanlineCPUToScreenColorExpandFill " + "%d,%d %dx%x %d\n", x, y, w, h, skipleft); + + /* Fill out register values */ + pI830->BR[9] = (pI830->bufferOffset + + (y * pScrn->displayWidth + x) * pI830->cpp); + pI830->BR[11] = ((1 << 16) | w); +} + +static void +I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned int tiled = CheckTiling(pScrn); + + if (pI830->init == 0) { + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI830->FbBase); + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + + /* We have to use the primary screen's FbBase, as that's where + * we allocated Scratch2, so we get the correct pointer */ + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI8301->FbBase); + } + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n", + bufno, pI830->BR[12]); + + if (tiled) + pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | + (pI830->BR[13] & 0xFFFF0000); + + { + BEGIN_LP_RING(8); + + if (pScrn->bitsPerPixel == 32) { + OUT_RING(XY_MONO_SRC_BLT_CMD | XY_MONO_SRC_BLT_WRITE_ALPHA | + tiled << 11 | XY_MONO_SRC_BLT_WRITE_RGB); + } else { + OUT_RING(XY_MONO_SRC_BLT_CMD | tiled << 11); + } + OUT_RING(pI830->BR[13]); + OUT_RING(0); /* x1 = 0, y1 = 0 */ + OUT_RING(pI830->BR[11]); /* x2 = w, y2 = 1 */ + OUT_RING(pI830->BR[9]); /* dst addr */ + OUT_RING(pI830->BR[12]); /* src addr */ + OUT_RING(pI830->BR[18]); /* bg */ + OUT_RING(pI830->BR[19]); /* fg */ + + ADVANCE_LP_RING(); + } + + /* Advance to next scanline. + */ + pI830->BR[9] += pScrn->displayWidth * pI830->cpp; + I830GetNextScanlineColorExpandBuffer(pScrn); + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); +} + +#if DO_SCANLINE_IMAGE_WRITE +static void +I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int trans_color, + int bpp, int depth) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SetupForScanlineImageWrite %x %x\n", rop, planemask); + + /* Fill out register values */ + pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); + pI830->BR[13] |= XAAGetCopyROP(rop) << 16; + + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + pI830->BR[13] |= (1 << 24); + break; + case 32: + pI830->BR[13] |= ((1 << 25) | (1 << 24)); + break; + } + + I830GetNextScanlineColorExpandBuffer(pScrn); +} + +static void +I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, int y, + int w, int h, int skipleft) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SubsequentScanlineImageWriteRect " + "%d,%d %dx%x %d\n", x, y, w, h, skipleft); + + /* Fill out register values */ + pI830->BR[9] = (pI830->bufferOffset + + (y * pScrn->displayWidth + x) * pI830->cpp); + pI830->BR[11] = ((1 << 16) | w); +} + +static void +I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned int tiled = CheckTiling(pScrn); + + if (pI830->init == 0) { + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI830->FbBase); + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + + /* We have to use the primary screen's FbBase, as that's where + * we allocated Scratch2, so we get the correct pointer */ + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI8301->FbBase); + } + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I830SubsequentImageWriteScanline %d (addr %x)\n", + bufno, pI830->BR[12]); + + { + BEGIN_LP_RING(8); + + if (pScrn->bitsPerPixel == 32) { + OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + tiled << 11 | XY_SRC_COPY_BLT_WRITE_RGB); + } else { + OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 11); + } + OUT_RING(pI830->BR[13]); + OUT_RING(0); /* x1 = 0, y1 = 0 */ + OUT_RING(pI830->BR[11]); /* x2 = w, y2 = 1 */ + OUT_RING(pI830->BR[9]); /* dst addr */ + OUT_RING(0); /* source origin (0,0) */ + OUT_RING(pI830->BR[11] & 0xffff); /* source pitch */ + OUT_RING(pI830->BR[12]); /* src addr */ + + ADVANCE_LP_RING(); + } + + /* Advance to next scanline. + */ + pI830->BR[9] += pScrn->displayWidth * pI830->cpp; + I830GetNextScanlineColorExpandBuffer(pScrn); +} +#endif /* DO_SCANLINE_IMAGE_WRITE */ +/* Support for multiscreen */ + +static void +I830RestoreAccelState(ScrnInfoPtr pScrn) +{ +#if 0 + /* might be needed, but everything is on a ring, so I don't think so */ + I830Sync(pScrn); +#endif +} + diff --git a/src/i915_3d.c b/src/i915_3d.c index b1f30ef2..e70bb24a 100644 --- a/src/i915_3d.c +++ b/src/i915_3d.c @@ -78,9 +78,7 @@ void I915EmitInvarientState( ScrnInfoPtr pScrn ) /* Need to initialize this to zero. */ - OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(3) | - (1)); + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0); OUT_RING(0); /* XXX: Use this */ diff --git a/src/i915_3d.h b/src/i915_3d.h index fc4ca603..10902186 100644 --- a/src/i915_3d.h +++ b/src/i915_3d.h @@ -33,7 +33,7 @@ #define MASK_Y 0x2 #define MASK_Z 0x4 #define MASK_W 0x8 -#define MASK_XYZ (MASK_X | MASK_Y | MASK_W) +#define MASK_XYZ (MASK_X | MASK_Y | MASK_Z) #define MASK_XYZW (MASK_XYZ | MASK_W) #define MASK_SATURATE 0x10 @@ -350,8 +350,16 @@ _i915_fs_arith(int cmd, int dest_reg, return op; } +/** Move operand0 to dest_reg */ +#define i915_fs_mov(dest_reg, operand0) \ +do { \ + FS_OUT(i915_fs_arith(MOV, dest_reg, operand0, \ + i915_fs_operand_none(), \ + i915_fs_operand_none())); \ +} while (0) + /** - * Move the values in operand0 to the dest reg with the masking/saturation + * Move the value in operand0 to the dest reg with the masking/saturation * specified. */ #define i915_fs_mov_masked(dest_reg, dest_mask, operand0) \ @@ -375,6 +383,13 @@ do { \ i915_fs_operand_none())); \ } while (0) +/** Add operand0 and operand1 and put the result in dest_reg */ +#define i915_fs_mul(dest_reg, operand0, operand1) \ +do { \ + FS_OUT(i915_fs_arith(MUL, dest_reg, operand0, operand1, \ + i915_fs_operand_none())); \ +} while (0) + /** * Perform a 3-component dot-product of operand0 and operand1 and put the * resulting scalar in the channels of dest_reg specified by the dest_mask. @@ -383,7 +398,7 @@ do { \ do { \ struct i915_fs_op op; \ \ - op = i915_fs_arith(DP3, dest_reg, operand0, i915_fs_operand_none(), \ + op = i915_fs_arith(DP3, dest_reg, operand0, operand1, \ i915_fs_operand_none()); \ op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \ op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \ @@ -421,11 +436,13 @@ do { \ #define FS_END() \ do { \ - int _i; \ - BEGIN_LP_RING(_cur_shader_commands * 3 + 1); \ + int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1; \ + BEGIN_LP_RING(_cur_shader_commands * 3 + 1 + _pad); \ OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM | \ (_cur_shader_commands * 3 - 1)); \ for (_i = 0; _i < _cur_shader_commands * 3; _i++) \ OUT_RING(_shader_buf[_i]); \ + if (_pad != 0) \ + OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ } while (0); diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c new file mode 100644 index 00000000..90240b82 --- /dev/null +++ b/src/i915_exa_render.c @@ -0,0 +1,501 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Wang Zhenyu <zhenyu.z.wang@intel.com> + * Eric Anholt <eric@anholt.net> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i830.h" +#include "i915_reg.h" +#include "i915_3d.h" + +#ifdef I830DEBUG +#define DEBUG_I830FALLBACK 1 +#endif + +#ifdef DEBUG_I830FALLBACK +#define I830FALLBACK(s, arg...) \ +do { \ + DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \ + return FALSE; \ +} while(0) +#else +#define I830FALLBACK(s, arg...) \ +do { \ + return FALSE; \ +} while(0) +#endif + +extern float scale_units[2][2]; +extern Bool is_transform[2]; +extern PictTransform *transform[2]; +static CARD32 mapstate[6]; +static CARD32 samplerstate[6]; + +struct formatinfo { + int fmt; + CARD32 card_fmt; +}; + +struct blendinfo { + Bool dst_alpha; + Bool src_alpha; + CARD32 src_blend; + CARD32 dst_blend; +}; + +extern Bool +I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture); + +extern Bool +I915EXAPrepareComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); + +static struct blendinfo I915BlendOp[] = { + /* Clear */ + {0, 0, BLENDFACT_ZERO, BLENDFACT_ZERO}, + /* Src */ + {0, 0, BLENDFACT_ONE, BLENDFACT_ZERO}, + /* Dst */ + {0, 0, BLENDFACT_ZERO, BLENDFACT_ONE}, + /* Over */ + {0, 1, BLENDFACT_ONE, BLENDFACT_INV_SRC_ALPHA}, + /* OverReverse */ + {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE}, + /* In */ + {1, 0, BLENDFACT_DST_ALPHA, BLENDFACT_ZERO}, + /* InReverse */ + {0, 1, BLENDFACT_ZERO, BLENDFACT_SRC_ALPHA}, + /* Out */ + {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO}, + /* OutReverse */ + {0, 1, BLENDFACT_ZERO, BLENDFACT_INV_SRC_ALPHA}, + /* Atop */ + {1, 1, BLENDFACT_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA}, + /* AtopReverse */ + {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA}, + /* Xor */ + {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA}, + /* Add */ + {0, 0, BLENDFACT_ONE, BLENDFACT_ONE}, +}; + +static struct formatinfo I915TexFormats[] = { + {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 }, + {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 }, + {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 }, + {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 }, + {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565 }, + {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 }, + {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 }, + {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8 }, +}; + +static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format) +{ + CARD32 sblend, dblend; + + sblend = I915BlendOp[op].src_blend; + dblend = I915BlendOp[op].dst_blend; + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (PICT_FORMAT_A(dst_format) == 0 && I915BlendOp[op].dst_alpha) { + if (sblend == BLENDFACT_DST_ALPHA) + sblend = BLENDFACT_ONE; + else if (sblend == BLENDFACT_INV_DST_ALPHA) + sblend = BLENDFACT_ZERO; + } + + /* If the source alpha is being used, then we should only be in a case where + * the source blend factor is 0, and the source blend value is the mask + * channels multiplied by the source picture's alpha. + */ + if (pMask && pMask->componentAlpha && I915BlendOp[op].src_alpha) { + if (dblend == BLENDFACT_SRC_ALPHA) { + dblend = BLENDFACT_SRC_COLR; + } else if (dblend == BLENDFACT_INV_SRC_ALPHA) { + dblend = BLENDFACT_INV_SRC_COLR; + } + } + + return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) | + (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT); +} + +static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format) +{ + switch (pDstPicture->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + *dst_format = COLR_BUF_ARGB8888; + break; + case PICT_r5g6b5: + *dst_format = COLR_BUF_RGB565; + break; + case PICT_a1r5g5b5: + case PICT_x1r5g5b5: + *dst_format = COLR_BUF_ARGB1555; + break; + /* COLR_BUF_8BIT is special for YUV surfaces. While we may end up being + * able to use it depending on how the hardware implements it, disable it + * for now while we don't know what exactly it does (what channel does it + * read from? + */ + /* + case PICT_a8: + *dst_format = COLR_BUF_8BIT; + break; + */ + case PICT_a4r4g4b4: + case PICT_x4r4g4b4: + *dst_format = COLR_BUF_ARGB4444; + break; + default: + I830FALLBACK("Unsupported dest format 0x%x\n", + (int)pDstPicture->format); + } + + return TRUE; +} + +static Bool I915CheckCompositeTexture(PicturePtr pPict, int unit) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + + if ((w > 0x7ff) || (h > 0x7ff)) + I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h); + + for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) + { + if (I915TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(I915TexFormats) / sizeof(I915TexFormats[0])) + I830FALLBACK("Unsupported picture format 0x%x\n", + (int)pPict->format); + + if (pPict->repeat && pPict->repeatType != RepeatNormal) + I830FALLBACK("extended repeat (%d) not supported\n", + pPict->repeatType); + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) + I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter); + + return TRUE; +} + +Bool +I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + CARD32 tmp1; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0])) + I830FALLBACK("Unsupported Composite op 0x%x\n", op); + if (pMaskPicture != NULL && pMaskPicture->componentAlpha) { + /* Check if it's component alpha that relies on a source alpha and on + * the source value. We can only get one of those into the single + * source value that we get to blend with. + */ + if (I915BlendOp[op].src_alpha && + (I915BlendOp[op].src_blend != BLENDFACT_ZERO)) + I830FALLBACK("Component alpha not supported with source " + "alpha and source value blending.\n"); + } + + if (!I915CheckCompositeTexture(pSrcPicture, 0)) + I830FALLBACK("Check Src picture texture\n"); + if (pMaskPicture != NULL && !I915CheckCompositeTexture(pMaskPicture, 1)) + I830FALLBACK("Check Mask picture texture\n"); + + if (!I915GetDestFormat(pDstPicture, &tmp1)) + I830FALLBACK("Get Color buffer format\n"); + + return TRUE; +} + +static Bool +I915TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit) +{ + ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 format, offset, pitch, filter; + int w, h, i; + CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER; + + offset = exaGetPixmapOffset(pPix); + pitch = exaGetPixmapPitch(pPix); + w = pPict->pDrawable->width; + h = pPict->pDrawable->height; + scale_units[unit][0] = pPix->drawable.width; + scale_units[unit][1] = pPix->drawable.height; + + for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) { + if (I915TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0])) + I830FALLBACK("unknown texture format\n"); + format = I915TexFormats[i].card_fmt; + + if (pPict->repeat) + wrap_mode = TEXCOORDMODE_WRAP; + + switch (pPict->filter) { + case PictFilterNearest: + filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | + (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT); + break; + case PictFilterBilinear: + filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | + (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT); + break; + default: + filter = 0; + I830FALLBACK("Bad filter 0x%x\n", pPict->filter); + } + + mapstate[unit * 3 + 0] = offset; + mapstate[unit * 3 + 1] = format | + ((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) | + ((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT); + if (!pI830->disableTiling) + samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS; + mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT; + + samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT); + samplerstate[unit * 3 + 0] |= filter; + samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS; + samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT; + samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT; + samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT; + samplerstate[unit * 3 + 2] = 0x00000000; /* border color */ + + if (pPict->transform != 0) { + is_transform[unit] = TRUE; + transform[unit] = pPict->transform; + } else { + is_transform[unit] = FALSE; + } + +#ifdef I830DEBUG + ErrorF("try to sync to show any errors..."); + I830Sync(pScrn); +#endif + + return TRUE; +} + +Bool +I915EXAPrepareComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 dst_format, dst_offset, dst_pitch; + CARD32 blendctl; + + ErrorF("i915 prepareComposite\n"); + + I915GetDestFormat(pDstPicture, &dst_format); + dst_offset = exaGetPixmapOffset(pDst); + dst_pitch = exaGetPixmapPitch(pDst); + scale_units[2][0] = pDst->drawable.width; + scale_units[2][1] = pDst->drawable.height; + FS_LOCALS(20); + + if (!I915TextureSetup(pSrcPicture, pSrc, 0)) + I830FALLBACK("fail to setup src texture\n"); + if (pMask != NULL) { + if (!I915TextureSetup(pMaskPicture, pMask, 1)) + I830FALLBACK("fail to setup mask texture\n"); + } else { + is_transform[1] = FALSE; + scale_units[1][0] = -1; + scale_units[1][1] = -1; + } + + if (pMask == NULL) { + BEGIN_LP_RING(10); + OUT_RING(_3DSTATE_MAP_STATE | 3); + OUT_RING(0x00000001); /* map 0 */ + OUT_RING(mapstate[0]); + OUT_RING(mapstate[1]); + OUT_RING(mapstate[2]); + + OUT_RING(_3DSTATE_SAMPLER_STATE | 3); + OUT_RING(0x00000001); /* sampler 0 */ + OUT_RING(samplerstate[0]); + OUT_RING(samplerstate[1]); + OUT_RING(samplerstate[2]); + ADVANCE_LP_RING(); + } else { + BEGIN_LP_RING(16); + OUT_RING(_3DSTATE_MAP_STATE | 6); + OUT_RING(0x00000003); /* map 0,1 */ + OUT_RING(mapstate[0]); + OUT_RING(mapstate[1]); + OUT_RING(mapstate[2]); + OUT_RING(mapstate[3]); + OUT_RING(mapstate[4]); + OUT_RING(mapstate[5]); + + OUT_RING(_3DSTATE_SAMPLER_STATE | 6); + OUT_RING(0x00000003); /* sampler 0,1 */ + OUT_RING(samplerstate[0]); + OUT_RING(samplerstate[1]); + OUT_RING(samplerstate[2]); + OUT_RING(samplerstate[3]); + OUT_RING(samplerstate[4]); + OUT_RING(samplerstate[5]); + ADVANCE_LP_RING(); + } + { + CARD32 ss2; + + BEGIN_LP_RING(26); + /* color buffer + * XXX: Need to add USE_FENCE if we ever tile the X Server's pixmaps or + * visible screen. + */ + OUT_RING(_3DSTATE_BUF_INFO_CMD); + OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch)); + OUT_RING(BUF_3D_ADDR(dst_offset)); + OUT_RING(MI_NOOP); + + OUT_RING(_3DSTATE_DST_BUF_VARS_CMD); + OUT_RING(dst_format); + + /* XXX: defaults */ + OUT_RING(_3DSTATE_DFLT_Z_CMD); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_DFLT_SPEC_CMD); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | + I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4); + ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D); + if (pMask) + ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D); + else + ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT); + OUT_RING(ss2); + OUT_RING(0x00000000); /* Disable texture coordinate wrap-shortest */ + OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE | + S4_CULLMODE_NONE| S4_VFMT_XY); + blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format); + OUT_RING(0x00000000); /* Disable stencil buffer */ + OUT_RING(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | + (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl); + + /* issue a flush */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(MI_NOOP); + + /* draw rect is unconditional */ + OUT_RING(_3DSTATE_DRAW_RECT_CMD); + OUT_RING(0x00000000); + OUT_RING(0x00000000); /* ymin, xmin*/ + OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) | + DRAW_XMAX(pDst->drawable.width - 1)); + OUT_RING(0x00000000); /* yorig, xorig (relate to color buffer?)*/ + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } + + FS_BEGIN(); + + /* Declare the registers necessary for our program. I don't think the + * S then T ordering is necessary. + */ + i915_fs_dcl(FS_S0); + if (pMask) + i915_fs_dcl(FS_S1); + i915_fs_dcl(FS_T0); + if (pMask) + i915_fs_dcl(FS_T1); + + /* Load the pSrcPicture texel */ + i915_fs_texld(FS_R0, FS_S0, FS_T0); + /* If the texture lacks an alpha channel, force the alpha to 1. */ + if (PICT_FORMAT_A(pSrcPicture->format) == 0) + i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one()); + + if (!pMask) { + /* No mask, so move to output color */ + i915_fs_mov(FS_OC, i915_fs_operand_reg(FS_R0)); + } else { + /* Load the pMaskPicture texel */ + i915_fs_texld(FS_R1, FS_S1, FS_T1); + /* If the texture lacks an alpha channel, force the alpha to 1. */ + if (PICT_FORMAT_A(pMaskPicture->format) == 0) + i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one()); + + /* If component alpha is set in the mask, then we need to provide + * the source alpha component (channelwise multiplication) as the + * output color. If it isn't set, then we need to provide the + * source value component, which is the multipliction of the source + * by the mask alpha. + */ + if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8) { + i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0), + i915_fs_operand_reg(FS_R1)); + } else { + i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0), + i915_fs_operand(FS_R1, W, W, W, W)); + } + } + FS_END(); + +#ifdef I830DEBUG + ErrorF("try to sync to show any errors..."); + I830Sync(pScrn); +#endif + + return TRUE; +} diff --git a/src/i915_reg.h b/src/i915_reg.h index 6d4f8fc0..6751de60 100644 --- a/src/i915_reg.h +++ b/src/i915_reg.h @@ -161,6 +161,9 @@ #define COLR_BUF_RGB555 (1<<8) #define COLR_BUF_RGB565 (2<<8) #define COLR_BUF_ARGB8888 (3<<8) +#define COLR_BUF_ARGB4444 (8<<8) +#define COLR_BUF_ARGB1555 (9<<8) +#define COLR_BUF_ARGB2AAA (0xa<<8) #define DEPTH_FRMT_16_FIXED 0 #define DEPTH_FRMT_16_FLOAT (1<<2) #define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2) @@ -685,7 +688,9 @@ -/* p207 */ +/* p207. + * The DWORD count is 3 times the number of bits set in MS1_MAPMASK_MASK + */ #define _3DSTATE_MAP_STATE (CMD_3D|(0x1d<<24)|(0x0<<16)) #define MS1_MAPMASK_SHIFT 0 @@ -752,6 +757,7 @@ #define MS3_TILED_SURFACE (1<<1) #define MS3_TILE_WALK (1<<0) +/* The pitch is the pitch measured in DWORDS, minus 1 */ #define MS4_PITCH_SHIFT 21 #define MS4_CUBE_FACE_ENA_NEGX (1<<20) #define MS4_CUBE_FACE_ENA_POSX (1<<19) @@ -768,7 +774,9 @@ #define MS4_VOLUME_DEPTH_SHIFT 0 #define MS4_VOLUME_DEPTH_MASK (0xff<<0) -/* p244 */ +/* p244. + * The DWORD count is 3 times the number of bits set in SS1_MAPMASK_MASK. + */ #define _3DSTATE_SAMPLER_STATE (CMD_3D|(0x1d<<24)|(0x1<<16)) #define SS1_MAPMASK_SHIFT 0 |