diff options
-rw-r--r-- | man/siliconmotion.man | 11 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/smi.h | 14 | ||||
-rw-r--r-- | src/smi_accel.c | 817 | ||||
-rw-r--r-- | src/smi_dga.c | 24 | ||||
-rw-r--r-- | src/smi_driver.c | 94 | ||||
-rw-r--r-- | src/smi_exa.c | 446 | ||||
-rw-r--r-- | src/smi_video.c | 200 | ||||
-rw-r--r-- | src/smi_video.h | 15 | ||||
-rw-r--r-- | src/smi_xaa.c | 844 |
10 files changed, 1545 insertions, 922 deletions
diff --git a/man/siliconmotion.man b/man/siliconmotion.man index 381ed52..fa8f030 100644 --- a/man/siliconmotion.man +++ b/man/siliconmotion.man @@ -178,6 +178,17 @@ This will increase performance, especially for small fills/blits, because the driver does not have to poll the ViRGE before sending it commands to make sure it is ready. It should work on most recent PCI chipsets. Default: off. +.TP +.BI "Option \*qAccelMethod\*q \*q" "string" \*q +Chooses between available acceleration architectures. Valid options are +.B XAA +and +.B EXA. +XAA is the traditional acceleration architecture and support for it is very +stable. EXA is a newer acceleration architecture with better performance for +the Render and Composite extensions, but the rendering code for it is newer and +possibly unstable. The default is +.B XAA. .PP The following additional diff --git a/src/Makefile.am b/src/Makefile.am index b122d08..869f852 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,6 +31,8 @@ siliconmotion_drv_ladir = @moduledir@/drivers siliconmotion_drv_la_SOURCES = \ regsmi.h \ smi_accel.c \ + smi_xaa.c \ + smi_exa.c \ smi_dac.c \ smi_dga.c \ smi_driver.c \ @@ -49,6 +49,7 @@ authorization from the XFree86 Project and Silicon Motion. #include "fb.h" #include "xaa.h" +#include "exa.h" #include "xf86cmap.h" #include "xf86i2c.h" @@ -179,7 +180,13 @@ typedef struct CloseScreenProcPtr CloseScreen; /* Pointer used to save wrapped CloseScreen function */ - XAAInfoRecPtr AccelInfoRec; /* XAA info Rec */ + XAAInfoRecPtr XAAInfoRec; /* XAA info Rec */ + + /* EXA */ + ExaDriverPtr EXADriverPtr; + Bool useEXA; /* enable exa acceleration */ + int depth; /* Pixmap color depth in bytes */ + pciVideoPtr PciInfo; /* PCI info vars */ PCITAG PciTag; int Chipset; /* Chip info, set using PCI @@ -334,10 +341,13 @@ void SMI_CommonCalcClock(int scrnIndex, long freq, int min_m, int min_n1, Bool SMI_I2CInit(ScrnInfoPtr pScrn); /* smi_accel.c */ -Bool SMI_AccelInit(ScreenPtr pScrn); +Bool SMI_XAAInit(ScreenPtr pScrn); +Bool SMI_EXAInit(ScreenPtr pScrn); void SMI_AccelSync(ScrnInfoPtr pScrn); void SMI_GEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file); void SMI_EngineReset(ScrnInfoPtr); +void SMI_SetClippingRectangle(ScrnInfoPtr, int, int, int, int); +void SMI_DisableClipping(ScrnInfoPtr); /* smi_hwcurs.c */ Bool SMI_HWCursorInit(ScreenPtr pScrn); diff --git a/src/smi_accel.c b/src/smi_accel.c index 48075f4..40c530a 100644 --- a/src/smi_accel.c +++ b/src/smi_accel.c @@ -34,200 +34,6 @@ authorization from the XFree86 Project and silicon Motion. #include "smi.h" -#include "miline.h" -#include "xaalocal.h" -#include "xaarop.h" -#include "servermd.h" - - -static void SMI_SetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int, - unsigned int, int); -static void SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int, - int, int); -static void SMI_SetupForSolidFill(ScrnInfoPtr, int, int, unsigned); -static void SMI_SubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int); -static void SMI_SubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int); -static void SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int, - unsigned int); -static void SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int, - int, int); -static void SMI_SetupForMono8x8PatternFill(ScrnInfoPtr, int, int, int, int, int, - unsigned int); -static void SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr, int, int, int, - int, int, int); -static void SMI_SetupForColor8x8PatternFill(ScrnInfoPtr, int, int, int, - unsigned int, int); -static void SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr, int, int, int, - int, int, int); -#if SMI_USE_IMAGE_WRITES -static void SMI_SetupForImageWrite(ScrnInfoPtr, int, unsigned int, int, int, - int); -static void SMI_SubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int); -#endif -static void SMI_SetClippingRectangle(ScrnInfoPtr, int, int, int, int); -static void SMI_DisableClipping(ScrnInfoPtr); -/* #671 */ -static void SMI_ValidatePolylines(GCPtr, unsigned long, DrawablePtr); -static void SMI_Polylines(DrawablePtr, GCPtr, int, int, DDXPointPtr); - -Bool -SMI_AccelInit(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoPtr; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SMIPtr pSmi = SMIPTR(pScrn); - /*BoxRec AvailFBArea;*/ - Bool ret; - /*int numLines, maxLines;*/ - - ENTER_PROC("SMI_AccelInit"); - - pSmi->AccelInfoRec = infoPtr = XAACreateInfoRec(); - if (infoPtr == NULL) { - LEAVE_PROC("SMI_AccelInit"); - return FALSE; - } - - infoPtr->Flags = PIXMAP_CACHE - | LINEAR_FRAMEBUFFER - | OFFSCREEN_PIXMAPS; - - infoPtr->Sync = SMI_AccelSync; - - /* Screen to screen copies */ - infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK - | ONLY_TWO_BITBLT_DIRECTIONS; - infoPtr->SetupForScreenToScreenCopy = SMI_SetupForScreenToScreenCopy; - infoPtr->SubsequentScreenToScreenCopy = SMI_SubsequentScreenToScreenCopy; - if (pScrn->bitsPerPixel == 24) { - infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY; - } - if ((pSmi->Chipset == SMI_LYNX3D) && (pScrn->bitsPerPixel == 8)) { - infoPtr->ScreenToScreenCopyFlags |= GXCOPY_ONLY; - } - - /* Solid Fills */ - infoPtr->SolidFillFlags = NO_PLANEMASK; - infoPtr->SetupForSolidFill = SMI_SetupForSolidFill; - infoPtr->SubsequentSolidFillRect = SMI_SubsequentSolidFillRect; - - /* Solid Lines */ - infoPtr->SolidLineFlags = NO_PLANEMASK; - infoPtr->SetupForSolidLine = SMI_SetupForSolidFill; - infoPtr->SubsequentSolidHorVertLine = SMI_SubsequentSolidHorVertLine; - - /* Color Expansion Fills */ - infoPtr->CPUToScreenColorExpandFillFlags = ROP_NEEDS_SOURCE - | NO_PLANEMASK - | BIT_ORDER_IN_BYTE_MSBFIRST - | LEFT_EDGE_CLIPPING - | CPU_TRANSFER_PAD_DWORD - | SCANLINE_PAD_DWORD; - infoPtr->ColorExpandBase = pSmi->DataPortBase; - infoPtr->ColorExpandRange = pSmi->DataPortSize; - infoPtr->SetupForCPUToScreenColorExpandFill = - SMI_SetupForCPUToScreenColorExpandFill; - infoPtr->SubsequentCPUToScreenColorExpandFill = - SMI_SubsequentCPUToScreenColorExpandFill; - - /* 8x8 Mono Pattern Fills */ - infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK - | HARDWARE_PATTERN_PROGRAMMED_BITS - | HARDWARE_PATTERN_SCREEN_ORIGIN - | BIT_ORDER_IN_BYTE_MSBFIRST; - infoPtr->SetupForMono8x8PatternFill = SMI_SetupForMono8x8PatternFill; - infoPtr->SubsequentMono8x8PatternFillRect = - SMI_SubsequentMono8x8PatternFillRect; - - /* 8x8 Color Pattern Fills */ - if (!SMI_LYNX3D_SERIES(pSmi->Chipset) || (pScrn->bitsPerPixel != 24)) { - infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK - | HARDWARE_PATTERN_SCREEN_ORIGIN; - infoPtr->SetupForColor8x8PatternFill = - SMI_SetupForColor8x8PatternFill; - infoPtr->SubsequentColor8x8PatternFillRect = - SMI_SubsequentColor8x8PatternFillRect; - } - -#if SMI_USE_IMAGE_WRITES - /* Image Writes */ - infoPtr->ImageWriteFlags = ROP_NEEDS_SOURCE - | NO_PLANEMASK - | CPU_TRANSFER_PAD_DWORD - | SCANLINE_PAD_DWORD; - infoPtr->ImageWriteBase = pSmi->DataPortBase; - infoPtr->ImageWriteRange = pSmi->DataPortSize; - infoPtr->SetupForImageWrite = SMI_SetupForImageWrite; - infoPtr->SubsequentImageWriteRect = SMI_SubsequentImageWriteRect; -#endif - - /* Clipping */ - infoPtr->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY - | HARDWARE_CLIP_MONO_8x8_FILL - | HARDWARE_CLIP_COLOR_8x8_FILL - | HARDWARE_CLIP_SOLID_FILL - | HARDWARE_CLIP_SOLID_LINE - | HARDWARE_CLIP_DASHED_LINE; - infoPtr->SetClippingRectangle = SMI_SetClippingRectangle; - infoPtr->DisableClipping = SMI_DisableClipping; - - /* Pixmap Cache */ - if (pScrn->bitsPerPixel == 24) { - infoPtr->CachePixelGranularity = 16; - } else { - infoPtr->CachePixelGranularity = 128 / pScrn->bitsPerPixel; - } - - /* Offscreen Pixmaps */ - infoPtr->maxOffPixWidth = 4096; - infoPtr->maxOffPixHeight = 4096; - if (pScrn->bitsPerPixel == 24) { - infoPtr->maxOffPixWidth = 4096 / 3; - - if (pSmi->Chipset == SMI_LYNX) { - infoPtr->maxOffPixHeight = 4096 / 3; - } - } - - SMI_EngineReset(pScrn); - - - /* CZ 18.06.2001: moved to smi_driver.c before the NoAccel question - to have offscreen framebuffer in NoAccel mode */ -#if 0 - maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp); - if (pSmi->rotate) { - numLines = maxLines; - } else { -#if SMI_USE_VIDEO - numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp * pSmi->height) - * 25 / 100 + pSmi->width * pSmi->Bpp - 1) - / (pSmi->width * pSmi->Bpp); - numLines += pSmi->height; -#else - numLines = maxLines; -#endif - } - - AvailFBArea.x1 = 0; - AvailFBArea.y1 = 0; - AvailFBArea.x2 = pSmi->width; - AvailFBArea.y2 = numLines; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FrameBuffer Box: %d,%d - %d,%d\n", - AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2); - xf86InitFBManager(pScreen, &AvailFBArea); -#endif - - ret = XAAInit(pScreen, infoPtr); - if (ret && pSmi->shadowFB) /* #671 */ { - pSmi->ValidatePolylines = infoPtr->ValidatePolylines; - infoPtr->ValidatePolylines = SMI_ValidatePolylines; - } - - LEAVE_PROC("SMI_AccelInit"); - return ret; -} - void SMI_GEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file) { @@ -326,477 +132,10 @@ SMI_EngineReset(ScrnInfoPtr pScrn) } /******************************************************************************/ -/* Screen to Screen Copies */ -/******************************************************************************/ - -static void -SMI_SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, - unsigned int planemask, int trans) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SetupForScreenToScreenCopy"); - DEBUG((VERBLEV, "xdir=%d ydir=%d rop=%02X trans=%08X\n", xdir, ydir, - rop, trans)); - - pSmi->AccelCmd = XAAGetCopyROP(rop) - | SMI_BITBLT - | SMI_START_ENGINE; - - if ((xdir == -1) || (ydir == -1)) { - pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT; - } - - if (trans != -1) { - pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; - WaitQueue(1); - WRITE_DPR(pSmi, 0x20, trans); - } - - if (pSmi->ClipTurnedOn) { - WaitQueue(1); - WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); - pSmi->ClipTurnedOn = FALSE; - } - - LEAVE_PROC("SMI_SetupForScreenToScreenCopy"); -} - -static void -SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, - int y2, int w, int h) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SubsequentScreenToScreenCopy"); - DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n", x1, y1, x2, y2, w, h)); - - if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { - x1 += w - 1; - y1 += h - 1; - x2 += w - 1; - y2 += h - 1; - } - - if (pScrn->bitsPerPixel == 24) { - x1 *= 3; - x2 *= 3; - w *= 3; - - if (pSmi->Chipset == SMI_LYNX) { - y1 *= 3; - y2 *= 3; - } - - if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { - x1 += 2; - x2 += 2; - } - } - - WaitQueue(4); - WRITE_DPR(pSmi, 0x00, (x1 << 16) + (y1 & 0xFFFF)); - WRITE_DPR(pSmi, 0x04, (x2 << 16) + (y2 & 0xFFFF)); - WRITE_DPR(pSmi, 0x08, (w << 16) + (h & 0xFFFF)); - WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); - - LEAVE_PROC("SMI_SubsequentScreenToScreenCopy"); -} - -/******************************************************************************/ -/* Solid Fills */ -/******************************************************************************/ - -static void -SMI_SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, - unsigned int planemask) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SetupForSolidFill"); - DEBUG((VERBLEV, "color=%08X rop=%02X\n", color, rop)); - - pSmi->AccelCmd = XAAGetPatternROP(rop) - | SMI_BITBLT - | SMI_START_ENGINE; - - if (pSmi->ClipTurnedOn) { - WaitQueue(4); - WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); - pSmi->ClipTurnedOn = FALSE; - } else { - WaitQueue(3); - } - WRITE_DPR(pSmi, 0x14, color); - WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF); - WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF); - - LEAVE_PROC("SMI_SetupForSolidFill"); -} - -void -SMI_SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SubsequentSolidFillRect"); - DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); - - if (pScrn->bitsPerPixel == 24) { - x *= 3; - w *= 3; - - if (pSmi->Chipset == SMI_LYNX) { - y *= 3; - } - } - - WaitQueue(3); - WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); - WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); - WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); - - LEAVE_PROC("SMI_SubsequentSolidFillRect"); -} - -/******************************************************************************/ -/* Solid Lines */ -/******************************************************************************/ - -static void -SMI_SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, - int dir) -{ - SMIPtr pSmi = SMIPTR(pScrn); - int w, h; - - ENTER_PROC("SMI_SubsequentSolidHorVertLine"); - DEBUG((VERBLEV, "x=%d y=%d len=%d dir=%d\n", x, y, len, dir)); - - if (dir == DEGREES_0) { - w = len; - h = 1; - } else { - w = 1; - h = len; - } - - if (pScrn->bitsPerPixel == 24) { - x *= 3; - w *= 3; - - if (pSmi->Chipset == SMI_LYNX) { - y *= 3; - } - } - - WaitQueue(3); - WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); - WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); - WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); - - LEAVE_PROC("SMI_SubsequentSolidHorVertLine"); -} - -/******************************************************************************/ -/* Color Expansion Fills */ -/******************************************************************************/ - -static void -SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, - int rop, unsigned int planemask) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SetupForCPUToScreenColorExpandFill"); - DEBUG((VERBLEV, "fg=%08X bg=%08X rop=%02X\n", fg, bg, rop)); - - pSmi->AccelCmd = XAAGetCopyROP(rop) - | SMI_HOSTBLT_WRITE - | SMI_SRC_MONOCHROME - | SMI_START_ENGINE; - - if (bg == -1) { - pSmi->AccelCmd |= SMI_TRANSPARENT_SRC; - - WaitQueue(3); - WRITE_DPR(pSmi, 0x14, fg); - WRITE_DPR(pSmi, 0x18, ~fg); - WRITE_DPR(pSmi, 0x20, fg); - } else { - WaitQueue(2); - WRITE_DPR(pSmi, 0x14, fg); - WRITE_DPR(pSmi, 0x18, bg); - } - - LEAVE_PROC("SMI_SetupForCPUToScreenColorExpandFill"); -} - -void -SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y, int w, - int h, int skipleft) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SubsequentCPUToScreenColorExpandFill"); - DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft)); - - if (pScrn->bitsPerPixel == 24) { - x *= 3; - w *= 3; - skipleft *= 3; - - if (pSmi->Chipset == SMI_LYNX) { - y *= 3; - } - } - - if (skipleft) { - WaitQueue(5); - WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) - | (x + skipleft) | 0x2000); - pSmi->ClipTurnedOn = TRUE; - } else { - if (pSmi->ClipTurnedOn) { - WaitQueue(5); - WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); - pSmi->ClipTurnedOn = FALSE; - } else { - WaitQueue(4); - } - } - WRITE_DPR(pSmi, 0x00, 0); - WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); - WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); - WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); - - LEAVE_PROC("SMI_SubsequentCPUToScreenColorExpandFill"); -} - -/******************************************************************************/ -/* 8x8 Mono Pattern Fills */ -/******************************************************************************/ - -static void -SMI_SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg, - int bg, int rop, unsigned int planemask) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SetupForMono8x8PatternFill"); - DEBUG((VERBLEV, "patx=%08X paty=%08X fg=%08X bg=%08X rop=%02X\n", patx, - paty, fg, bg, rop)); - - pSmi->AccelCmd = XAAGetPatternROP(rop) - | SMI_BITBLT - | SMI_START_ENGINE; - - if (pSmi->ClipTurnedOn) { - WaitQueue(1); - WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); - pSmi->ClipTurnedOn = FALSE; - } - - if (bg == -1) { - WaitQueue(5); - WRITE_DPR(pSmi, 0x14, fg); - WRITE_DPR(pSmi, 0x18, ~fg); - WRITE_DPR(pSmi, 0x20, fg); - WRITE_DPR(pSmi, 0x34, patx); - WRITE_DPR(pSmi, 0x38, paty); - } else { - WaitQueue(4); - WRITE_DPR(pSmi, 0x14, fg); - WRITE_DPR(pSmi, 0x18, bg); - WRITE_DPR(pSmi, 0x34, patx); - WRITE_DPR(pSmi, 0x38, paty); - } - - LEAVE_PROC("SMI_SetupForMono8x8PatternFill"); -} - -static void -SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty, - int x, int y, int w, int h) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SubsequentMono8x8PatternFillRect"); - DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); - - if (pScrn->bitsPerPixel == 24) { - x *= 3; - w *= 3; - if (pSmi->Chipset == SMI_LYNX) { - y *= 3; - } - } - - WaitQueue(3); - WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); - WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); - WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); - - LEAVE_PROC("SMI_SubsequentMono8x8PatternFillRect"); -} - -/******************************************************************************/ -/* 8x8 Color Pattern Fills */ -/******************************************************************************/ - -static void -SMI_SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int rop, - unsigned int planemask, int trans_color) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SetupForColor8x8PatternFill"); - DEBUG((VERBLEV, "patx=%d paty=%d rop=%02X trans_color=%08X\n", patx, paty, - rop, trans_color)); - - pSmi->AccelCmd = XAAGetPatternROP(rop) - | SMI_BITBLT - | SMI_COLOR_PATTERN - | SMI_START_ENGINE; - - if (pScrn->bitsPerPixel <= 16) { - /* PDR#950 */ - CARD8* pattern = pSmi->FBBase + (patx + paty * pSmi->Stride) * pSmi->Bpp; - - WaitIdleEmpty(); - WRITE_DPR(pSmi, 0x0C, SMI_BITBLT | SMI_COLOR_PATTERN); - memcpy(pSmi->DataPortBase, pattern, 8 * pSmi->Bpp * 8); - } else { - if (pScrn->bitsPerPixel == 24) { - patx *= 3; - - if (pSmi->Chipset == SMI_LYNX) { - paty *= 3; - } - } - - WaitQueue(1); - WRITE_DPR(pSmi, 0x00, (patx << 16) | (paty & 0xFFFF)); - } - - if (trans_color == -1) { - pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; - - WaitQueue(1); - WRITE_DPR(pSmi, 0x20, trans_color); - } - - if (pSmi->ClipTurnedOn) { - WaitQueue(1); - WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); - pSmi->ClipTurnedOn = FALSE; - } - - LEAVE_PROC("SMI_SetupForColor8x8PatternFill"); -} - -static void -SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty, - int x, int y, int w, int h) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SubsequentColor8x8PatternFillRect"); - DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); - - if (pScrn->bitsPerPixel == 24) { - x *= 3; - w *= 3; - - if (pSmi->Chipset == SMI_LYNX) { - y *= 3; - } - } - - WaitQueue(3); - WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); - WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); /* PDR#950 */ - WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); - - LEAVE_PROC("SMI_SubsequentColor8x8PatternFillRect"); -} - -#if SMI_USE_IMAGE_WRITES -/******************************************************************************/ -/* Image Writes */ -/******************************************************************************/ - -static void -SMI_SetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask, - int trans_color, int bpp, int depth) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SetupForImageWrite"); - DEBUG((VERBLEV, "rop=%02X trans_color=%08X bpp=%d depth=%d\n", rop, - trans_color, bpp, depth)); - - pSmi->AccelCmd = XAAGetCopyROP(rop) - | SMI_HOSTBLT_WRITE - | SMI_START_ENGINE; - - if (trans_color != -1) { - pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; - - WaitQueue(1); - WRITE_DPR(pSmi, 0x20, trans_color); - } - - LEAVE_PROC("SMI_SetupForImageWrite"); -} - -static void -SMI_SubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, - int skipleft) -{ - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_SubsequentImageWriteRect"); - DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft)); - - if (pScrn->bitsPerPixel == 24) { - x *= 3; - w *= 3; - skipleft *= 3; - - if (pSmi->Chipset == SMI_LYNX) { - y *= 3; - } - } - - if (skipleft) { - WaitQueue(5); - WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) | - (x + skipleft) | 0x2000); - pSmi->ClipTurnedOn = TRUE; - } else { - if (pSmi->ClipTurnedOn) { - WaitQueue(5); - WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); - pSmi->ClipTurnedOn = FALSE; - } else { - WaitQueue(4); - } - } - WRITE_DPR(pSmi, 0x00, 0); - WRITE_DPR(pSmi, 0x04, (x << 16) | (y * 0xFFFF)); - WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); - WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); - - LEAVE_PROC("SMI_SubsequentImageWriteRect"); -} -#endif - -/******************************************************************************/ /* Clipping */ /******************************************************************************/ -static void +void SMI_SetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right, int bottom) { @@ -835,7 +174,7 @@ SMI_SetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right, LEAVE_PROC("SMI_SetClippingRectangle"); } -static void +void SMI_DisableClipping(ScrnInfoPtr pScrn) { SMIPtr pSmi = SMIPTR(pScrn); @@ -862,155 +201,3 @@ SMI_DisableClipping(ScrnInfoPtr pScrn) LEAVE_PROC("SMI_DisableClipping"); } -/******************************************************************************/ -/* Polylines #671 */ -/******************************************************************************/ - -/* - -In order to speed up the "logout" screen in rotated modes, we need to intercept -the Polylines function. Normally, the polylines are drawn and the shadowFB is -then sending a request of the bounding rectangle of those poylines. This should -be okay, if it weren't for the fact that the Gnome logout screen is drawing -polylines in rectangles and this asks for a rotation of the entire rectangle. -This is very slow. - -To circumvent this slowness, we intercept the ValidatePolylines function and -override the default "Fallback" Polylines with our own Polylines function. Our -Polylines function first draws the polylines through the original Fallback -function and then rotates the lines, line by line. We then set a flag and -return control to the shadowFB which will try to rotate the bounding rectangle. -However, the flag has been set and the RefreshArea function does nothing but -clear the flag so the next Refresh that comes in shoiuld be handled correctly. - -All this code improves the speed quite a bit. - -*/ - -#define IS_VISIBLE(pWin) \ -( \ - pScrn->vtSema \ - && (((WindowPtr) pWin)->visibility != VisibilityFullyObscured) \ -) - -#define TRIM_BOX(box, pGC) \ -{ \ - BoxPtr extents = &pGC->pCompositeClip->extents; \ - if (box.x1 < extents->x1) box.x1 = extents->x1; \ - if (box.y1 < extents->y1) box.y1 = extents->y1; \ - if (box.x2 > extents->x2) box.x2 = extents->x2; \ - if (box.y2 > extents->y2) box.y2 = extents->y2; \ -} - -#define TRANSLATE_BOX(box, pDraw) \ -{ \ - box.x1 += pDraw->x; \ - box.y1 += pDraw->y; \ - box.x2 += pDraw->x; \ - box.y2 += pDraw->y; \ -} - -#define BOX_NOT_EMPTY(box) \ - ((box.x2 > box.x1) && (box.y2 > box.y1)) - -static void -SMI_ValidatePolylines(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - SMIPtr pSmi = SMIPTR(infoRec->pScrn); - - ENTER_PROC("SMI_ValidatePolylines"); - - pSmi->ValidatePolylines(pGC, changes, pDraw); - if (pGC->ops->Polylines == XAAGetFallbackOps()->Polylines) { - /* Override the Polylines function with our own Polylines function. */ - pGC->ops->Polylines = SMI_Polylines; - } - - LEAVE_PROC("SMI_ValidatePolylines"); -} - -static void -SMI_Polylines(DrawablePtr pDraw, GCPtr pGC, int mode, int npt, - DDXPointPtr pptInit) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - ScrnInfoPtr pScrn = infoRec->pScrn; - SMIPtr pSmi = SMIPTR(pScrn); - - ENTER_PROC("SMI_Polylines"); - - /* Call the original Polylines function. */ - pGC->ops->Polylines = XAAGetFallbackOps()->Polylines; - (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); - pGC->ops->Polylines = SMI_Polylines; - - if (IS_VISIBLE(pDraw) && npt) { - /* Allocate a temporary buffer for all segments of the polyline. */ - BoxPtr pBox = xnfcalloc(sizeof(BoxRec), npt); - int extra = pGC->lineWidth >> 1, box; - - if (npt > 1) { - /* Adjust the extra space required per polyline segment. */ - if (pGC->joinStyle == JoinMiter) { - extra = 6 * pGC->lineWidth; - } else if (pGC->capStyle == CapProjecting) { - extra = pGC->lineWidth; - } - } - - for (box = 0; --npt;) { - /* Setup the bounding box for one polyline segment. */ - pBox[box].x1 = pptInit->x; - pBox[box].y1 = pptInit->y; - pptInit++; - pBox[box].x2 = pptInit->x; - pBox[box].y2 = pptInit->y; - if (mode == CoordModePrevious) { - pBox[box].x2 += pBox[box].x1; - pBox[box].y2 += pBox[box].y1; - } - - /* Sort coordinates. */ - if (pBox[box].x1 > pBox[box].x2) { - int tmp = pBox[box].x1; - pBox[box].x1 = pBox[box].x2; - pBox[box].x2 = tmp; - } - if (pBox[box].y1 > pBox[box].y2) { - int tmp = pBox[box].y1; - pBox[box].y1 = pBox[box].y2; - pBox[box].y2 = tmp; - } - - /* Add extra space required for each polyline segment. */ - pBox[box].x1 -= extra; - pBox[box].y1 -= extra; - pBox[box].x2 += extra + 1; - pBox[box].y2 += extra + 1; - - /* See if we need to draw this polyline segment. */ - TRANSLATE_BOX(pBox[box], pDraw); - TRIM_BOX(pBox[box], pGC); - if (BOX_NOT_EMPTY(pBox[box])) { - box++; - } - } - - if (box) { - /* Refresh all polyline segments now. */ - if (pSmi->Chipset == SMI_COUGAR3DR) { - SMI_RefreshArea730(pScrn, box, pBox); - } else { - SMI_RefreshArea(pScrn, box, pBox); - } - } - - /* Free the temporary buffer. */ - xfree(pBox); - } - - pSmi->polyLines = TRUE; - LEAVE_PROC("SMI_Polylines"); -} - diff --git a/src/smi_dga.c b/src/smi_dga.c index 71d0922..504b700 100644 --- a/src/smi_dga.c +++ b/src/smi_dga.c @@ -216,10 +216,10 @@ SMI_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color) ENTER_PROC("SMI_FillRect"); - if (pSmi->AccelInfoRec) { - (*pSmi->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); - (*pSmi->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); - SET_SYNC_FLAG(pSmi->AccelInfoRec); + if (pSmi->XAAInfoRec) { + (*pSmi->XAAInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); + (*pSmi->XAAInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + SET_SYNC_FLAG(pSmi->XAAInfoRec); } LEAVE_PROC("SMI_FillRect"); @@ -233,13 +233,13 @@ SMI_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx, ENTER_PROC("SMI_BlitRect"); - if (pSmi->AccelInfoRec) { + if (pSmi->XAAInfoRec) { int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; int ydir = (srcy < dsty) ? -1 : 1; - (*pSmi->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1); - (*pSmi->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h); - SET_SYNC_FLAG(pSmi->AccelInfoRec); + (*pSmi->XAAInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1); + (*pSmi->XAAInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h); + SET_SYNC_FLAG(pSmi->XAAInfoRec); } LEAVE_PROC("SMI_BlitRect"); @@ -253,13 +253,13 @@ SMI_BlitTransRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx, ENTER_PROC("SMI_BlitTraneRect"); - if (pSmi->AccelInfoRec) { + if (pSmi->XAAInfoRec) { int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; int ydir = (srcy < dsty) ? -1 : 1; - (*pSmi->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, color); - (*pSmi->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h); - SET_SYNC_FLAG(pSmi->AccelInfoRec); + (*pSmi->XAAInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, color); + (*pSmi->XAAInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h); + SET_SYNC_FLAG(pSmi->XAAInfoRec); } LEAVE_PROC("SMI_BlitTraneRect"); diff --git a/src/smi_driver.c b/src/smi_driver.c index 255bd5c..5f14264 100644 --- a/src/smi_driver.c +++ b/src/smi_driver.c @@ -164,6 +164,7 @@ typedef enum OPTION_USEBIOS, OPTION_ZOOMONLCD, OPTION_DUALHEAD, + OPTION_ACCELMETHOD, NUMBER_OF_OPTIONS } SMIOpts; @@ -189,6 +190,7 @@ static const OptionInfoRec SMIOptions[] = { OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ZOOMONLCD, "ZoomOnLCD", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DUALHEAD, "Dualhead", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -232,6 +234,19 @@ static const char *xaaSymbols[] = NULL }; +static const char *exaSymbols[] = +{ + "exaDriverAlloc", + "exaDriverInit", + "exaDriverFini", + "exaOffscreenAlloc", + "exaOffscreenFree", + "exaGetPixmapPitch", + "exaGetPixmapOffset", + "exaGetPixmapSize", + NULL +}; + static const char *ramdacSymbols[] = { "xf86CreateCursorInfoRec", @@ -341,7 +356,7 @@ siliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin) * Tell the loader about symbols from other modules that this module * might refer to. */ - LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, ramdacSymbols, + LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, exaSymbols, ramdacSymbols, ddcSymbols, i2cSymbols, int10Symbols, vbeSymbols, shadowSymbols, NULL); @@ -1083,15 +1098,52 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + if (!pSmi->NoAccel) { + from = X_DEFAULT; + char *strptr; + + if ((strptr = (char *)xf86GetOptValString(pSmi->Options, OPTION_ACCELMETHOD))) { + if (!xf86NameCmp(strptr,"XAA")) { + from = X_CONFIG; + pSmi->useEXA = FALSE; + } else if(!xf86NameCmp(strptr,"EXA")) { + from = X_CONFIG; + pSmi->useEXA = TRUE; + } + } + + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", + pSmi->useEXA ? "EXA" : "XAA"); + } + xf86LoaderReqSymLists(fbSymbols, NULL); - /* Load XAA if needed */ - if (!pSmi->NoAccel || pSmi->hwcursor) { - if (!xf86LoadSubModule(pScrn, "xaa")) { - SMI_FreeRec(pScrn); - LEAVE_PROC("SMI_PreInit"); - return FALSE; + + /* Load XAA or EXA if needed */ + if (!pSmi->NoAccel) { + if (!pSmi->useEXA) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + SMI_FreeRec(pScrn); + LEAVE_PROC("SMI_PreInit"); + return FALSE; + } + xf86LoaderReqSymLists(xaaSymbols, NULL); + } else { + XF86ModReqInfo req; + int errmaj, errmin; + + memset(&req, 0, sizeof(XF86ModReqInfo)); + req.majorversion = 2; + req.minorversion = 0; + + if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, + &req, &errmaj, &errmin)) { + LoaderErrorMsg(NULL, "exa", errmaj, errmin); + SMI_FreeRec(pScrn); + LEAVE_PROC("SMI_PreInit"); + return FALSE; + } + xf86LoaderReqSymLists(exaSymbols, NULL); } - xf86LoaderReqSymLists(xaaSymbols, NULL); } /* Load ramdac if needed */ @@ -2016,7 +2068,7 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* CZ 18.06.2001: moved here from smi_accel.c to have offscreen framebuffer in NoAccel mode */ - { + if (!pSmi->useEXA) { int numLines, maxLines; BoxRec AvailFBArea; @@ -2051,16 +2103,24 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* Initialize acceleration layer */ if (!pSmi->NoAccel) { - if (!SMI_AccelInit(pScreen)) { - LEAVE_PROC("SMI_ScreenInit"); - return FALSE; + if (!pSmi->useEXA) { + if (!SMI_XAAInit(pScreen)) { + LEAVE_PROC("SMI_ScreenInit"); + return FALSE; + } + } else { + if (!SMI_EXAInit(pScreen)) { + LEAVE_PROC("SMI_ScreenInit"); + return FALSE; + } } } miInitializeBackingStore(pScreen); /* hardware cursor needs to wrap this layer */ - SMI_DGAInit(pScreen); + if(!pSmi->NoAccel && !pSmi->useEXA) + SMI_DGAInit(pScreen); /* Initialise cursor functions */ miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); @@ -2725,8 +2785,12 @@ SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen) SMI_UnmapMem(pScrn); } - if (pSmi->AccelInfoRec != NULL) { - XAADestroyInfoRec(pSmi->AccelInfoRec); + if (pSmi->XAAInfoRec != NULL) { + XAADestroyInfoRec(pSmi->XAAInfoRec); + } + if (pSmi->EXADriverPtr) { + exaDriverFini(pScreen); + pSmi->EXADriverPtr = NULL; } if (pSmi->CursorInfoRec != NULL) { xf86DestroyCursorInfoRec(pSmi->CursorInfoRec); diff --git a/src/smi_exa.c b/src/smi_exa.c new file mode 100644 index 0000000..0718709 --- /dev/null +++ b/src/smi_exa.c @@ -0,0 +1,446 @@ +/* +Copyright (C) 2006 Dennis De Winter 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, 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 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, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +XFREE86 PROJECT 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 "smi.h" + + +static void +SMI_EXASync(ScreenPtr pScreen, int marker); + +static Bool +SMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, + int xdir, int ydir, int alu, Pixel planemask); + +static void +SMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height); + +static void +SMI_DoneCopy(PixmapPtr pDstPixmap); + +static Bool +SMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg); + +static void +SMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2); + +static void +SMI_DoneSolid(PixmapPtr pPixmap); + +Bool +SMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch); + +Bool +SMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch); + +Bool +SMI_EXAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_EXAInit"); + + if (!(pSmi->EXADriverPtr = exaDriverAlloc())) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate EXADriverRec.\n"); + LEAVE_PROC("SMI_EXAInit"); + return FALSE; + } + + pSmi->EXADriverPtr->exa_major = 2; + pSmi->EXADriverPtr->exa_minor = 0; + + SMI_EngineReset(pScrn); + + /* Memory Manager */ + pSmi->EXADriverPtr->memoryBase = pSmi->FBBase + pSmi->FBOffset; + pSmi->EXADriverPtr->memorySize = pSmi->FBReserved - 1024; + pSmi->EXADriverPtr->offScreenBase = pSmi->width * pSmi->height * pSmi->Bpp + 1024; + + /* Flags */ + pSmi->EXADriverPtr->flags = EXA_TWO_BITBLT_DIRECTIONS; + if (pSmi->EXADriverPtr->memorySize > pSmi->EXADriverPtr->offScreenBase) { + pSmi->EXADriverPtr->flags |= EXA_OFFSCREEN_PIXMAPS; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EXA offscreen memory manager enabled.\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Not enough video RAM for EXA offscreen memory manager.\n"); + } + + /* Offscreen Pixmaps */ + if (pScrn->bitsPerPixel == 24) { + pSmi->EXADriverPtr->maxX = 4096 / 3; + + if (pSmi->Chipset == SMI_LYNX) { + pSmi->EXADriverPtr->maxY = 4096 / 3; + } + } else { + pSmi->EXADriverPtr->maxX = 4096; + pSmi->EXADriverPtr->maxY = 4096; + } + + pSmi->EXADriverPtr->pixmapPitchAlign = 16; + pSmi->EXADriverPtr->pixmapOffsetAlign = 16; + + /* Sync */ + pSmi->EXADriverPtr->WaitMarker = SMI_EXASync; + + /* Copy */ + pSmi->EXADriverPtr->PrepareCopy = SMI_PrepareCopy; + pSmi->EXADriverPtr->Copy = SMI_Copy; + pSmi->EXADriverPtr->DoneCopy = SMI_DoneCopy; + + /* Solid */ + pSmi->EXADriverPtr->PrepareSolid = SMI_PrepareSolid; + pSmi->EXADriverPtr->Solid = SMI_Solid; + pSmi->EXADriverPtr->DoneSolid = SMI_DoneSolid; + + /* DFS & UTS */ + pSmi->EXADriverPtr->UploadToScreen = SMI_UploadToScreen; + pSmi->EXADriverPtr->DownloadFromScreen = SMI_DownloadFromScreen; + + if(!exaDriverInit(pScreen, pSmi->EXADriverPtr)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "exaDriverInit failed.\n"); + LEAVE_PROC("SMI_EXAInit"); + return FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration enabled.\n"); + LEAVE_PROC("SMI_EXAInit"); + return TRUE; + } +} + +static void +SMI_EXASync(ScreenPtr pScreen, int marker) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SMIPtr pSmi = SMIPTR(xf86Screens[pScreen->myNum]); + + ENTER_PROC("SMI_EXASync"); + + WaitIdleEmpty(); + + LEAVE_PROC("SMI_EXASync"); +} + +/* ----------------------------------------------------- EXA Copy ---------------------------------------------- */ + +CARD8 SMI_BltRop[16] = /* table stolen from KAA */ +{ + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0x88, /* src AND dst */ + /* GXandReverse */ 0x44, /* src AND NOT dst */ + /* GXcopy */ 0xCC, /* src */ + /* GXandInverted*/ 0x22, /* NOT src AND dst */ + /* GXnoop */ 0xAA, /* dst */ + /* GXxor */ 0x66, /* src XOR dst */ + /* GXor */ 0xEE, /* src OR dst */ + /* GXnor */ 0x11, /* NOT src AND NOT dst */ + /* GXequiv */ 0x99, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xDD, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x33, /* NOT src */ + /* GXorInverted */ 0xBB, /* NOT src OR dst */ + /* GXnand */ 0x77, /* NOT src OR NOT dst */ + /* GXset */ 0xFF, /* 1 */ +}; + +static Bool +SMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, + int alu, Pixel planemask) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_PrepareCopy"); + DEBUG((VERBLEV, "xdir=%d ydir=%d alu=%02X", xdir, ydir, alu)); + + /* calculate pitch in pixel unit */ + int src_pitch = exaGetPixmapPitch(pSrcPixmap) / pSmi->Bpp; + int dst_pitch = exaGetPixmapPitch(pDstPixmap) / pSmi->Bpp; + /* calculate offset in 8 byte (64 bit) unit */ + int src_offset = exaGetPixmapOffset(pSrcPixmap) / 8; + int dst_offset = exaGetPixmapOffset(pDstPixmap) / 8; + + pSmi->AccelCmd = SMI_BltRop[alu] + | SMI_BITBLT + | SMI_START_ENGINE; + + if (ydir < 0 || (ydir == 0 && xdir < 0)) { + pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT; + } + + WaitQueue(1); + /* Destination and Source Window Widths */ + WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF)); + + if (pScrn->bitsPerPixel == 24) { + /* Bit Mask not supported in 24 bit mode */ + pSmi->depth = pSrcPixmap->drawable.depth; + if (!EXA_PM_IS_SOLID(pSmi, planemask)) { + LEAVE_PROC("SMI_PrepareCopy"); + return FALSE; + } + + src_pitch *= 3; + dst_pitch *= 3; + WaitQueue(3); + } else { + WaitQueue(4); + /* Bit Mask (planemask) */ + WRITE_DPR(pSmi, 0x28, planemask); + } + /* Destination and Source Row Pitch */ + WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF)); + /* Destination and Source Base Address (offset) */ + WRITE_DPR(pSmi, 0x40, src_offset); + WRITE_DPR(pSmi, 0x44, dst_offset); + + LEAVE_PROC("SMI_PrepareCopy"); + return TRUE; +} + +static void +SMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, + int dstY, int width, int height) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_Copy"); + DEBUG((VERBLEV, "srcX=%d srcY=%d dstX=%d dstY=%d width=%d height=%d\n", + srcX, srcY, dstX, dstY, width, height)); + + if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { + srcX += width - 1; + srcY += height - 1; + dstX += width - 1; + dstY += height - 1; + } + + if (pScrn->bitsPerPixel == 24) { + srcX *= 3; + dstX *= 3; + width *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + srcY *= 3; + dstY *= 3; + } + + if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { + srcX += 2; + dstX += 2; + } + } + + WaitQueue(4); + WRITE_DPR(pSmi, 0x00, (srcX << 16) + (srcY & 0xFFFF)); + WRITE_DPR(pSmi, 0x04, (dstX << 16) + (dstY & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (width << 16) + (height & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_Copy"); +} + +static void +SMI_DoneCopy(PixmapPtr pDstPixmap) +{ + ENTER_PROC("SMI_DoneCopy"); + + LEAVE_PROC("SMI_DoneCopy"); +} + +/* ----------------------------------------------------- EXA Solid --------------------------------------------- */ + +CARD8 SMI_SolidRop[16] = /* table stolen from KAA */ +{ + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0xA0, /* src AND dst */ + /* GXandReverse */ 0x50, /* src AND NOT dst */ + /* GXcopy */ 0xF0, /* src */ + /* GXandInverted*/ 0x0A, /* NOT src AND dst */ + /* GXnoop */ 0xAA, /* dst */ + /* GXxor */ 0x5A, /* src XOR dst */ + /* GXor */ 0xFA, /* src OR dst */ + /* GXnor */ 0x05, /* NOT src AND NOT dst */ + /* GXequiv */ 0xA5, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xF5, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x0F, /* NOT src */ + /* GXorInverted */ 0xAF, /* NOT src OR dst */ + /* GXnand */ 0x5F, /* NOT src OR NOT dst */ + /* GXset */ 0xFF, /* 1 */ +}; + +static Bool +SMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_PrepareSolid"); + DEBUG((VERBLEV, "alu=%02X\n", alu)); + + /* calculate pitch in pixel unit */ + int pitch = exaGetPixmapPitch(pPixmap) / pSmi->Bpp; + /* calculate offset in 8 byte (64 bit) unit */ + int offset = exaGetPixmapOffset(pPixmap) / 8; + + pSmi->AccelCmd = SMI_SolidRop[alu] + | SMI_BITBLT + | SMI_START_ENGINE; + + WaitQueue(1); + /* Destination Window Width */ + WRITE_DPR(pSmi, 0x3C, (pitch << 16)); + + if (pScrn->bitsPerPixel == 24) { + /* Bit Mask not supported in 24 bit mode */ + pSmi->depth = pPixmap->drawable.depth; + if (!EXA_PM_IS_SOLID(pSmi, planemask)) { + LEAVE_PROC("SMI_PrepareSolid"); + return FALSE; + } + + pitch *= 3; + WaitQueue(5); + } else { + WaitQueue(6); + /* Bit Mask (planemask) */ + WRITE_DPR(pSmi, 0x28, planemask); + } + /* Destination Row Pitch */ + WRITE_DPR(pSmi, 0x12, pitch); + /* Destination Base Address (offset) */ + WRITE_DPR(pSmi, 0x44, offset); + /* Foreground Color */ + WRITE_DPR(pSmi, 0x14, fg); + /* Mono Pattern High and Low */ + WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF); + WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF); + + LEAVE_PROC("SMI_PrepareSolid"); + return TRUE; +} + +static void +SMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_Solid"); + DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d\n", x1, y1, x2, y2)); + + int w = (x2 - x1); + int h = (y2 - y1); + + if (pScrn->bitsPerPixel == 24) { + x1 *= 3; + w *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + y1 *= 3; + } + } + + WaitQueue(3); + WRITE_DPR(pSmi, 0x04, (x1 << 16) | (y1 & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_Solid"); +} + +static void +SMI_DoneSolid(PixmapPtr pPixmap) +{ + ENTER_PROC("SMI_DoneSolid"); + + LEAVE_PROC("SMI_DoneSolid"); +} + +/* --------------------------------------- EXA DFS & UTS ---------------------------------------- */ + +Bool +SMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_DownloadFromScreen"); + DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d dst=%d dst_pitch=%d\n", + x, y, w, h, dst, dst_pitch)); + + unsigned char *src = pSrc->devPrivate.ptr; + int src_pitch = exaGetPixmapPitch(pSrc); + + exaWaitSync(pSrc->drawable.pScreen); + + src += (y * src_pitch) + (x * pSmi->Bpp); + w *= pSmi->Bpp; + + while (h--) { + memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + + return TRUE; + LEAVE_PROC("SMI_DownloadFromScreen"); +} + +Bool +SMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, + char *src, int src_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_UploadToScreen"); + DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d src=%d src_pitch=%d\n", + x, y, w, h, src, src_pitch)); + + char *dst = pDst->devPrivate.ptr; + int dst_pitch = exaGetPixmapPitch(pDst); + + exaWaitSync(pDst->drawable.pScreen); + + dst += (y * dst_pitch) + (x * pSmi->Bpp); + w *= pSmi->Bpp; + + while (h--) { + memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + + return TRUE; + LEAVE_PROC("SMI_UploadToScreen"); +} + diff --git a/src/smi_video.c b/src/smi_video.c index db19ffd..8ea1114 100644 --- a/src/smi_video.c +++ b/src/smi_video.c @@ -136,8 +136,10 @@ static void SMI_WaitForSync(ScrnInfoPtr pScrn); SMI_I2CDataPtr i2cData);*/ static void SMI_InitOffscreenImages(ScreenPtr pScreen); -static FBAreaPtr SMI_AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, - int numLines); +static void SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area); +static CARD32 SMI_AllocateMemory(ScrnInfoPtr pScrn, void **mem_struct, int size); +static void SMI_FreeMemory(ScrnInfoPtr pScrn, void *mem_struct); + static int SMI_AllocSurface(ScrnInfoPtr pScrn, int id, unsigned short width, unsigned short height, @@ -1035,7 +1037,7 @@ SMI_PutVideo( BoxRec dstBox; INT32 x1, y1, x2, y2; int norm; - int areaHeight, width, height, fbPitch; + int size, width, height, fbPitch; int top, left; ENTER_PROC("SMI_PutVideo"); @@ -1200,11 +1202,11 @@ SMI_PutVideo( } do { - areaHeight = (vid_pitch * height + fbPitch - 1) / fbPitch; - DEBUG((VERBLEV, "SMI_AllocateMemory: vid_pitch=%d height=%d fbPitch=%d areaHeight=%d\n", - vid_pitch, height, fbPitch, areaHeight)); - pPort->area = SMI_AllocateMemory(pScrn, pPort->area, areaHeight); - if (pPort->area == NULL) { + size = vid_pitch * height; + DEBUG((VERBLEV, "SMI_AllocateMemory: vid_pitch=%d height=%d size=%d\n", + vid_pitch, height, size)); + pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size); + if (pPort->video_offset == 0) { if ((cpr00 & 0x000C0000) == 0) { /* height -> 1/2 height */ yscale = (128 * vid_h / drw_h) & 0xFF; @@ -1234,14 +1236,14 @@ SMI_PutVideo( } } } - } while (pPort->area == NULL); + } while (pPort->video_offset == 0); DEBUG((VERBLEV, "xscale==%d yscale=%d width=%d height=%d\n", xscale, yscale, width, height)); /* aaa whats this ----------------------v ? vid_address = (pPort->area->box.y1 * fbPitch) + ((y1 >> 16) * vid_pitch);*/ - vid_address = (pPort->area->box.y1 * fbPitch); + vid_address = pPort->video_offset; DEBUG((VERBLEV, "test RegionsEqual\n")); #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) @@ -1359,9 +1361,9 @@ SMI_StopVideo( /* #864 OUT_SEQ(pSmi, 0x21, IN_SEQ(pSmi, 0x21) | 0x04); */ #endif } - if (pPort->area != NULL) { - xf86FreeOffscreenArea(pPort->area); - pPort->area = NULL; + if (pPort->video_memory != NULL) { + SMI_FreeMemory(pScrn, pPort->video_memory); + pPort->video_memory = NULL; } pPort->videoStatus = 0; /* pPort->i2cDevice = 0;aaa*/ @@ -1375,7 +1377,6 @@ SMI_StopVideo( LEAVE_PROC("SMI_StopVideo"); } - static int SMI_SetPortAttribute( ScrnInfoPtr pScrn, @@ -1518,7 +1519,7 @@ SMI_PutImage( SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; INT32 x1, y1, x2, y2; int bpp = 0; - int fbPitch, srcPitch, srcPitch2 = 0, dstPitch, areaHeight; + int srcPitch, srcPitch2 = 0, dstPitch, size; BoxRec dstBox; CARD32 offset, offset2 = 0, offset3 = 0, tmp; int left, top, nPixels, nLines; @@ -1546,11 +1547,6 @@ SMI_PutImage( dstBox.x2 -= pScrn->frameX0; dstBox.y2 -= pScrn->frameY0; - if (pSmi->Bpp == 3) { - fbPitch = pSmi->Stride; - } else { - fbPitch = pSmi->Stride * pSmi->Bpp; - } switch (id) { case FOURCC_YV12: @@ -1587,9 +1583,9 @@ SMI_PutImage( break; } - areaHeight = ((dstPitch * height) + fbPitch - 1) / fbPitch; - pPort->area = SMI_AllocateMemory(pScrn, pPort->area, areaHeight); - if (pPort->area == NULL) { + size = dstPitch * height; + pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size); + if (pPort->video_offset == 0) { LEAVE_PROC("SMI_PutImage"); return BadAlloc; } @@ -1599,7 +1595,7 @@ SMI_PutImage( nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left; left *= bpp; - offset = (pPort->area->box.y1 * fbPitch) + (top * dstPitch); + offset = pPort->video_offset + (top * dstPitch); dstStart = pSmi->FBBase + offset + left; switch(id) { @@ -2042,8 +2038,8 @@ SMI_BlockHandler( } } else { if (pPort->freeTime < currentTime.milliseconds) { - xf86FreeOffscreenArea(pPort->area); - pPort->area = NULL; + SMI_FreeMemory(pScrn, pPort->video_memory); + pPort->video_memory = NULL; } pPort->videoStatus = 0; } @@ -2151,55 +2147,118 @@ SMI_InitOffscreenImages( LEAVE_PROC("SMI_InitOffscreenImages"); } -static FBAreaPtr +static void +SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr; + + ENTER_PROC("SMI_VideoSave"); + + if (pPort->video_memory == area) + pPort->video_memory = NULL; + + LEAVE_PROC("SMI_VideoSave"); +} + +static CARD32 SMI_AllocateMemory( ScrnInfoPtr pScrn, - FBAreaPtr area, - int numLines + void **mem_struct, + int size ) { ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + SMIPtr pSmi = SMIPTR(pScrn); + int offset = 0; ENTER_PROC("SMI_AllocateMemory"); - if (area != NULL) { - if ((area->box.y2 - area->box.y1) >= numLines) { - LEAVE_PROC("SMI_AllocateMemory (area->box.y2 - area->box.y1) >= numLines ok"); - return area; - } + if (pSmi->useEXA) { + ExaOffscreenArea *area = *mem_struct; + + if (area != NULL) { + if (area->size >= size) + return area->offset; - if (xf86ResizeOffscreenArea(area, pScrn->displayWidth, numLines)) { - LEAVE_PROC("SMI_AllocateMemory xf86ResizeOffscreenArea ok"); - return area; + exaOffscreenFree(pScrn->pScreen, area); } - xf86FreeOffscreenArea(area); - } + area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SMI_VideoSave, NULL); + + *mem_struct = area; + if (area == NULL) + return 0; + offset = area->offset; + } else { + FBLinearPtr linear = *mem_struct; + + /* XAA allocates in units of pixels at the screen bpp, + * so adjust size appropriately. + */ + size = (size + pSmi->Bpp - 1) / pSmi->Bpp; + + if (linear) { + if (linear->size >= size) + return linear->offset * pSmi->Bpp; + + if (xf86ResizeOffscreenLinear(linear, size)) + return linear->offset * pSmi->Bpp; - area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, numLines, 0, - NULL, NULL, NULL); + xf86FreeOffscreenLinear(linear); + } + + linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, NULL, NULL); + *mem_struct = linear; + + if (!linear) { + int max_size; - if (area == NULL) { - int maxW, maxH; + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, PRIORITY_EXTREME); + if (max_size < size) + return 0; + + xf86PurgeUnlockedOffscreenAreas(pScreen); - xf86QueryLargestOffscreenArea(pScreen, &maxW, &maxH, 0, - FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME); + linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, NULL, NULL); + *mem_struct = linear; - DEBUG((VERBLEV, "QueryLargestOffscreenArea maxW=%d maxH=%d displayWidth=%d numlines=%d\n", - maxW, maxH, pScrn->displayWidth, numLines)); - if ((maxW < pScrn->displayWidth) || (maxH < numLines)) { - LEAVE_PROC("SMI_AllocateMemory (maxW < pScrn->displayWidth) || (maxH < numLines)"); - return NULL; + if (!linear) + return 0; } - xf86PurgeUnlockedOffscreenAreas(pScreen); - area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, numLines, - 0, NULL, NULL, NULL); + DEBUG((VERBLEV, "offset = %p\n", offset)); } DEBUG((VERBLEV, "area = %p\n", area)); LEAVE_PROC("SMI_AllocateMemory"); - return area; + return offset; +} + +static void +SMI_FreeMemory( + ScrnInfoPtr pScrn, + void *mem_struct +) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_FreeMemory"); + + if (pSmi->useEXA) { + ExaOffscreenArea *area = mem_struct; + + if (area != NULL) + exaOffscreenFree(pScrn->pScreen, area); + } else { + FBLinearPtr linear = mem_struct; + + if (linear != NULL) + xf86FreeOffscreenLinear(linear); + } + + LEAVE_PROC("SMI_FreeMemory"); } static int @@ -2212,9 +2271,9 @@ SMI_AllocSurface( ) { SMIPtr pSmi = SMIPTR(pScrn); - int numLines, pitch, fbPitch, bpp; + int pitch, bpp, offset, size; + void *surface_memory = NULL; SMI_OffscreenPtr ptrOffscreen; - FBAreaPtr area; ENTER_PROC("SMI_AllocSurface"); @@ -2223,13 +2282,6 @@ SMI_AllocSurface( return BadAlloc; } - if (pSmi->Bpp == 3) { - fbPitch = pSmi->Stride; - } else { - fbPitch = pSmi->Stride * pSmi->Bpp; - } - - width = (width + 1) & ~1; switch (id) { case FOURCC_YV12: case FOURCC_I420: @@ -2248,26 +2300,27 @@ SMI_AllocSurface( LEAVE_PROC("SMI_AllocSurface"); return BadAlloc; } - pitch = (width * bpp + 15) & ~15; - numLines = ((height * pitch) + fbPitch - 1) / fbPitch; + width = (width + 1) & ~1; + pitch = (width * bpp + 15) & ~15; + size = pitch * height; - area = SMI_AllocateMemory(pScrn, NULL, numLines); - if (area == NULL) { + offset = SMI_AllocateMemory(pScrn, &surface_memory, size); + if (offset == 0) { LEAVE_PROC("SMI_AllocSurface"); return BadAlloc; } surface->pitches = xalloc(sizeof(int)); if (surface->pitches == NULL) { - xf86FreeOffscreenArea(area); + SMI_FreeMemory(pScrn, surface_memory); LEAVE_PROC("SMI_AllocSurface"); return BadAlloc; } surface->offsets = xalloc(sizeof(int)); if (surface->offsets == NULL) { xfree(surface->pitches); - xf86FreeOffscreenArea(area); + SMI_FreeMemory(pScrn, surface_memory); LEAVE_PROC("SMI_AllocSurface"); return BadAlloc; } @@ -2276,7 +2329,7 @@ SMI_AllocSurface( if (ptrOffscreen == NULL) { xfree(surface->offsets); xfree(surface->pitches); - xf86FreeOffscreenArea(area); + SMI_FreeMemory(pScrn, surface_memory); LEAVE_PROC("SMI_AllocSurface"); return BadAlloc; } @@ -2286,10 +2339,10 @@ SMI_AllocSurface( surface->width = width; surface->height = height; surface->pitches[0] = pitch; - surface->offsets[0] = area->box.y1 * fbPitch; + surface->offsets[0] = offset; surface->devPrivate.ptr = (pointer) ptrOffscreen; - ptrOffscreen->area = area; + ptrOffscreen->surface_memory = surface_memory; ptrOffscreen->isOn = FALSE; LEAVE_PROC("SMI_AllocSurface"); @@ -2301,6 +2354,7 @@ SMI_FreeSurface( XF86SurfacePtr surface ) { + ScrnInfoPtr pScrn = surface->pScrn; SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; ENTER_PROC("SMI_FreeSurface"); @@ -2309,7 +2363,7 @@ SMI_FreeSurface( SMI_StopSurface(surface); } - xf86FreeOffscreenArea(ptrOffscreen->area); + SMI_FreeMemory(pScrn, ptrOffscreen->surface_memory); xfree(surface->pitches); xfree(surface->offsets); xfree(surface->devPrivate.ptr); diff --git a/src/smi_video.h b/src/smi_video.h index ff15dc7..13c0ace 100644 --- a/src/smi_video.h +++ b/src/smi_video.h @@ -69,26 +69,31 @@ authorization from the XFree86 Project and silicon Motion. typedef struct { - FBAreaPtr area; RegionRec clip; /* Attributes */ CARD32 Attribute[N_ATTRS]; - CARD32 videoStatus; - Time offTime; - Time freeTime; + CARD32 videoStatus; + Time offTime; + Time freeTime; I2CDevRec I2CDev; + /* Memory */ + int size; + void *video_memory; + int video_offset; + /* Encodings */ XF86VideoEncodingPtr enc; int *input; int *norm; int *channel; int nenc,cenc; + } SMI_PortRec, *SMI_PortPtr; typedef struct { - FBAreaPtr area; + void *surface_memory; Bool isOn; } SMI_OffscreenRec, *SMI_OffscreenPtr; diff --git a/src/smi_xaa.c b/src/smi_xaa.c new file mode 100644 index 0000000..190b62e --- /dev/null +++ b/src/smi_xaa.c @@ -0,0 +1,844 @@ +/* +Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. +Copyright (C) 2000 Silicon Motion, Inc. 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, 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 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, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +XFREE86 PROJECT 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. + +Except as contained in this notice, the names of the XFree86 Project and +Silicon Motion shall not be used in advertising or otherwise to promote the +sale, use or other dealings in this Software without prior written +authorization from the XFree86 Project and silicon Motion. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "smi.h" + +#include "miline.h" +#include "xaalocal.h" +#include "xaarop.h" +#include "servermd.h" + +static void SMI_SetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int, + unsigned int, int); +static void SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int, + int, int); +static void SMI_SetupForSolidFill(ScrnInfoPtr, int, int, unsigned); +static void SMI_SubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int); +static void SMI_SubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int); +static void SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int, + unsigned int); +static void SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int, + int, int); +static void SMI_SetupForMono8x8PatternFill(ScrnInfoPtr, int, int, int, int, int, + unsigned int); +static void SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr, int, int, int, + int, int, int); +static void SMI_SetupForColor8x8PatternFill(ScrnInfoPtr, int, int, int, + unsigned int, int); +static void SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr, int, int, int, + int, int, int); +#if SMI_USE_IMAGE_WRITES +static void SMI_SetupForImageWrite(ScrnInfoPtr, int, unsigned int, int, int, + int); +static void SMI_SubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int); +#endif +/* #671 */ +static void SMI_ValidatePolylines(GCPtr, unsigned long, DrawablePtr); +static void SMI_Polylines(DrawablePtr, GCPtr, int, int, DDXPointPtr); + + +Bool +SMI_XAAInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SMIPtr pSmi = SMIPTR(pScrn); + /*BoxRec AvailFBArea;*/ + Bool ret; + /*int numLines, maxLines;*/ + + ENTER_PROC("SMI_XAAInit"); + + pSmi->XAAInfoRec = infoPtr = XAACreateInfoRec(); + if (infoPtr == NULL) { + LEAVE_PROC("SMI_AccelInit"); + return FALSE; + } + + infoPtr->Flags = PIXMAP_CACHE + | LINEAR_FRAMEBUFFER + | OFFSCREEN_PIXMAPS; + + infoPtr->Sync = SMI_AccelSync; + + /* Screen to screen copies */ + infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK + | ONLY_TWO_BITBLT_DIRECTIONS; + infoPtr->SetupForScreenToScreenCopy = SMI_SetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = SMI_SubsequentScreenToScreenCopy; + if (pScrn->bitsPerPixel == 24) { + infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY; + } + if ((pSmi->Chipset == SMI_LYNX3D) && (pScrn->bitsPerPixel == 8)) { + infoPtr->ScreenToScreenCopyFlags |= GXCOPY_ONLY; + } + + /* Solid Fills */ + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = SMI_SetupForSolidFill; + infoPtr->SubsequentSolidFillRect = SMI_SubsequentSolidFillRect; + + /* Solid Lines */ + infoPtr->SolidLineFlags = NO_PLANEMASK; + infoPtr->SetupForSolidLine = SMI_SetupForSolidFill; + infoPtr->SubsequentSolidHorVertLine = SMI_SubsequentSolidHorVertLine; + + /* Color Expansion Fills */ + infoPtr->CPUToScreenColorExpandFillFlags = ROP_NEEDS_SOURCE + | NO_PLANEMASK + | BIT_ORDER_IN_BYTE_MSBFIRST + | LEFT_EDGE_CLIPPING + | CPU_TRANSFER_PAD_DWORD + | SCANLINE_PAD_DWORD; + infoPtr->ColorExpandBase = pSmi->DataPortBase; + infoPtr->ColorExpandRange = pSmi->DataPortSize; + infoPtr->SetupForCPUToScreenColorExpandFill = + SMI_SetupForCPUToScreenColorExpandFill; + infoPtr->SubsequentCPUToScreenColorExpandFill = + SMI_SubsequentCPUToScreenColorExpandFill; + + /* 8x8 Mono Pattern Fills */ + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK + | HARDWARE_PATTERN_PROGRAMMED_BITS + | HARDWARE_PATTERN_SCREEN_ORIGIN + | BIT_ORDER_IN_BYTE_MSBFIRST; + infoPtr->SetupForMono8x8PatternFill = SMI_SetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + SMI_SubsequentMono8x8PatternFillRect; + + /* 8x8 Color Pattern Fills */ + if (!SMI_LYNX3D_SERIES(pSmi->Chipset) || (pScrn->bitsPerPixel != 24)) { + infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK + | HARDWARE_PATTERN_SCREEN_ORIGIN; + infoPtr->SetupForColor8x8PatternFill = + SMI_SetupForColor8x8PatternFill; + infoPtr->SubsequentColor8x8PatternFillRect = + SMI_SubsequentColor8x8PatternFillRect; + } + +#if SMI_USE_IMAGE_WRITES + /* Image Writes */ + infoPtr->ImageWriteFlags = ROP_NEEDS_SOURCE + | NO_PLANEMASK + | CPU_TRANSFER_PAD_DWORD + | SCANLINE_PAD_DWORD; + infoPtr->ImageWriteBase = pSmi->DataPortBase; + infoPtr->ImageWriteRange = pSmi->DataPortSize; + infoPtr->SetupForImageWrite = SMI_SetupForImageWrite; + infoPtr->SubsequentImageWriteRect = SMI_SubsequentImageWriteRect; +#endif + + /* Clipping */ + infoPtr->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY + | HARDWARE_CLIP_MONO_8x8_FILL + | HARDWARE_CLIP_COLOR_8x8_FILL + | HARDWARE_CLIP_SOLID_FILL + | HARDWARE_CLIP_SOLID_LINE + | HARDWARE_CLIP_DASHED_LINE; + infoPtr->SetClippingRectangle = SMI_SetClippingRectangle; + infoPtr->DisableClipping = SMI_DisableClipping; + + /* Pixmap Cache */ + if (pScrn->bitsPerPixel == 24) { + infoPtr->CachePixelGranularity = 16; + } else { + infoPtr->CachePixelGranularity = 128 / pScrn->bitsPerPixel; + } + + /* Offscreen Pixmaps */ + infoPtr->maxOffPixWidth = 4096; + infoPtr->maxOffPixHeight = 4096; + if (pScrn->bitsPerPixel == 24) { + infoPtr->maxOffPixWidth = 4096 / 3; + + if (pSmi->Chipset == SMI_LYNX) { + infoPtr->maxOffPixHeight = 4096 / 3; + } + } + + SMI_EngineReset(pScrn); + + + /* CZ 18.06.2001: moved to smi_driver.c before the NoAccel question + to have offscreen framebuffer in NoAccel mode */ +#if 0 + maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp); + if (pSmi->rotate) { + numLines = maxLines; + } else { +#if SMI_USE_VIDEO + numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp * pSmi->height) + * 25 / 100 + pSmi->width * pSmi->Bpp - 1) + / (pSmi->width * pSmi->Bpp); + numLines += pSmi->height; +#else + numLines = maxLines; +#endif + } + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pSmi->width; + AvailFBArea.y2 = numLines; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FrameBuffer Box: %d,%d - %d,%d\n", + AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2); + xf86InitFBManager(pScreen, &AvailFBArea); +#endif + + ret = XAAInit(pScreen, infoPtr); + if (ret && pSmi->shadowFB) /* #671 */ { + pSmi->ValidatePolylines = infoPtr->ValidatePolylines; + infoPtr->ValidatePolylines = SMI_ValidatePolylines; + } + + LEAVE_PROC("SMI_XAAInit"); + return ret; +} + +/******************************************************************************/ +/* Screen to Screen Copies */ +/******************************************************************************/ + +static void +SMI_SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned int planemask, int trans) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SetupForScreenToScreenCopy"); + DEBUG((VERBLEV, "xdir=%d ydir=%d rop=%02X trans=%08X\n", xdir, ydir, + rop, trans)); + + pSmi->AccelCmd = XAAGetCopyROP(rop) + | SMI_BITBLT + | SMI_START_ENGINE; + + if ((xdir == -1) || (ydir == -1)) { + pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT; + } + + if (trans != -1) { + pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; + WaitQueue(1); + WRITE_DPR(pSmi, 0x20, trans); + } + + if (pSmi->ClipTurnedOn) { + WaitQueue(1); + WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); + pSmi->ClipTurnedOn = FALSE; + } + + LEAVE_PROC("SMI_SetupForScreenToScreenCopy"); +} + +static void +SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, + int y2, int w, int h) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SubsequentScreenToScreenCopy"); + DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n", x1, y1, x2, y2, w, h)); + + if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { + x1 += w - 1; + y1 += h - 1; + x2 += w - 1; + y2 += h - 1; + } + + if (pScrn->bitsPerPixel == 24) { + x1 *= 3; + x2 *= 3; + w *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + y1 *= 3; + y2 *= 3; + } + + if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { + x1 += 2; + x2 += 2; + } + } + + WaitQueue(4); + WRITE_DPR(pSmi, 0x00, (x1 << 16) + (y1 & 0xFFFF)); + WRITE_DPR(pSmi, 0x04, (x2 << 16) + (y2 & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) + (h & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_SubsequentScreenToScreenCopy"); +} + +/******************************************************************************/ +/* Solid Fills */ +/******************************************************************************/ + +static void +SMI_SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SetupForSolidFill"); + DEBUG((VERBLEV, "color=%08X rop=%02X\n", color, rop)); + + pSmi->AccelCmd = XAAGetPatternROP(rop) + | SMI_BITBLT + | SMI_START_ENGINE; + + if (pSmi->ClipTurnedOn) { + WaitQueue(4); + WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); + pSmi->ClipTurnedOn = FALSE; + } else { + WaitQueue(3); + } + WRITE_DPR(pSmi, 0x14, color); + WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF); + WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF); + + LEAVE_PROC("SMI_SetupForSolidFill"); +} + +void +SMI_SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SubsequentSolidFillRect"); + DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); + + if (pScrn->bitsPerPixel == 24) { + x *= 3; + w *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + y *= 3; + } + } + + WaitQueue(3); + WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_SubsequentSolidFillRect"); +} + +/******************************************************************************/ +/* Solid Lines */ +/******************************************************************************/ + +static void +SMI_SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, + int dir) +{ + SMIPtr pSmi = SMIPTR(pScrn); + int w, h; + + ENTER_PROC("SMI_SubsequentSolidHorVertLine"); + DEBUG((VERBLEV, "x=%d y=%d len=%d dir=%d\n", x, y, len, dir)); + + if (dir == DEGREES_0) { + w = len; + h = 1; + } else { + w = 1; + h = len; + } + + if (pScrn->bitsPerPixel == 24) { + x *= 3; + w *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + y *= 3; + } + } + + WaitQueue(3); + WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_SubsequentSolidHorVertLine"); +} + +/******************************************************************************/ +/* Color Expansion Fills */ +/******************************************************************************/ + +static void +SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SetupForCPUToScreenColorExpandFill"); + DEBUG((VERBLEV, "fg=%08X bg=%08X rop=%02X\n", fg, bg, rop)); + + pSmi->AccelCmd = XAAGetCopyROP(rop) + | SMI_HOSTBLT_WRITE + | SMI_SRC_MONOCHROME + | SMI_START_ENGINE; + + if (bg == -1) { + pSmi->AccelCmd |= SMI_TRANSPARENT_SRC; + + WaitQueue(3); + WRITE_DPR(pSmi, 0x14, fg); + WRITE_DPR(pSmi, 0x18, ~fg); + WRITE_DPR(pSmi, 0x20, fg); + } else { + WaitQueue(2); + WRITE_DPR(pSmi, 0x14, fg); + WRITE_DPR(pSmi, 0x18, bg); + } + + LEAVE_PROC("SMI_SetupForCPUToScreenColorExpandFill"); +} + +void +SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y, int w, + int h, int skipleft) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SubsequentCPUToScreenColorExpandFill"); + DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft)); + + if (pScrn->bitsPerPixel == 24) { + x *= 3; + w *= 3; + skipleft *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + y *= 3; + } + } + + if (skipleft) { + WaitQueue(5); + WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) + | (x + skipleft) | 0x2000); + pSmi->ClipTurnedOn = TRUE; + } else { + if (pSmi->ClipTurnedOn) { + WaitQueue(5); + WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); + pSmi->ClipTurnedOn = FALSE; + } else { + WaitQueue(4); + } + } + WRITE_DPR(pSmi, 0x00, 0); + WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_SubsequentCPUToScreenColorExpandFill"); +} + +/******************************************************************************/ +/* 8x8 Mono Pattern Fills */ +/******************************************************************************/ + +static void +SMI_SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg, + int bg, int rop, unsigned int planemask) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SetupForMono8x8PatternFill"); + DEBUG((VERBLEV, "patx=%08X paty=%08X fg=%08X bg=%08X rop=%02X\n", patx, + paty, fg, bg, rop)); + + pSmi->AccelCmd = XAAGetPatternROP(rop) + | SMI_BITBLT + | SMI_START_ENGINE; + + if (pSmi->ClipTurnedOn) { + WaitQueue(1); + WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); + pSmi->ClipTurnedOn = FALSE; + } + + if (bg == -1) { + WaitQueue(5); + WRITE_DPR(pSmi, 0x14, fg); + WRITE_DPR(pSmi, 0x18, ~fg); + WRITE_DPR(pSmi, 0x20, fg); + WRITE_DPR(pSmi, 0x34, patx); + WRITE_DPR(pSmi, 0x38, paty); + } else { + WaitQueue(4); + WRITE_DPR(pSmi, 0x14, fg); + WRITE_DPR(pSmi, 0x18, bg); + WRITE_DPR(pSmi, 0x34, patx); + WRITE_DPR(pSmi, 0x38, paty); + } + + LEAVE_PROC("SMI_SetupForMono8x8PatternFill"); +} + +static void +SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty, + int x, int y, int w, int h) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SubsequentMono8x8PatternFillRect"); + DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); + + if (pScrn->bitsPerPixel == 24) { + x *= 3; + w *= 3; + if (pSmi->Chipset == SMI_LYNX) { + y *= 3; + } + } + + WaitQueue(3); + WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_SubsequentMono8x8PatternFillRect"); +} + +/******************************************************************************/ +/* 8x8 Color Pattern Fills */ +/******************************************************************************/ + +static void +SMI_SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int rop, + unsigned int planemask, int trans_color) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SetupForColor8x8PatternFill"); + DEBUG((VERBLEV, "patx=%d paty=%d rop=%02X trans_color=%08X\n", patx, paty, + rop, trans_color)); + + pSmi->AccelCmd = XAAGetPatternROP(rop) + | SMI_BITBLT + | SMI_COLOR_PATTERN + | SMI_START_ENGINE; + + if (pScrn->bitsPerPixel <= 16) { + /* PDR#950 */ + CARD8* pattern = pSmi->FBBase + (patx + paty * pSmi->Stride) * pSmi->Bpp; + + WaitIdleEmpty(); + WRITE_DPR(pSmi, 0x0C, SMI_BITBLT | SMI_COLOR_PATTERN); + memcpy(pSmi->DataPortBase, pattern, 8 * pSmi->Bpp * 8); + } else { + if (pScrn->bitsPerPixel == 24) { + patx *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + paty *= 3; + } + } + + WaitQueue(1); + WRITE_DPR(pSmi, 0x00, (patx << 16) | (paty & 0xFFFF)); + } + + if (trans_color == -1) { + pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; + + WaitQueue(1); + WRITE_DPR(pSmi, 0x20, trans_color); + } + + if (pSmi->ClipTurnedOn) { + WaitQueue(1); + WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); + pSmi->ClipTurnedOn = FALSE; + } + + LEAVE_PROC("SMI_SetupForColor8x8PatternFill"); +} + +static void +SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty, + int x, int y, int w, int h) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SubsequentColor8x8PatternFillRect"); + DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); + + if (pScrn->bitsPerPixel == 24) { + x *= 3; + w *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + y *= 3; + } + } + + WaitQueue(3); + WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); /* PDR#950 */ + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_SubsequentColor8x8PatternFillRect"); +} + +#if SMI_USE_IMAGE_WRITES +/******************************************************************************/ +/* Image Writes */ +/******************************************************************************/ + +static void +SMI_SetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask, + int trans_color, int bpp, int depth) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SetupForImageWrite"); + DEBUG((VERBLEV, "rop=%02X trans_color=%08X bpp=%d depth=%d\n", rop, + trans_color, bpp, depth)); + + pSmi->AccelCmd = XAAGetCopyROP(rop) + | SMI_HOSTBLT_WRITE + | SMI_START_ENGINE; + + if (trans_color != -1) { + pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; + + WaitQueue(1); + WRITE_DPR(pSmi, 0x20, trans_color); + } + + LEAVE_PROC("SMI_SetupForImageWrite"); +} + +static void +SMI_SubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft) +{ + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_SubsequentImageWriteRect"); + DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft)); + + if (pScrn->bitsPerPixel == 24) { + x *= 3; + w *= 3; + skipleft *= 3; + + if (pSmi->Chipset == SMI_LYNX) { + y *= 3; + } + } + + if (skipleft) { + WaitQueue(5); + WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) | + (x + skipleft) | 0x2000); + pSmi->ClipTurnedOn = TRUE; + } else { + if (pSmi->ClipTurnedOn) { + WaitQueue(5); + WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); + pSmi->ClipTurnedOn = FALSE; + } else { + WaitQueue(4); + } + } + WRITE_DPR(pSmi, 0x00, 0); + WRITE_DPR(pSmi, 0x04, (x << 16) | (y * 0xFFFF)); + WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); + WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); + + LEAVE_PROC("SMI_SubsequentImageWriteRect"); +} +#endif + +/******************************************************************************/ +/* Polylines #671 */ +/******************************************************************************/ + +/* + +In order to speed up the "logout" screen in rotated modes, we need to intercept +the Polylines function. Normally, the polylines are drawn and the shadowFB is +then sending a request of the bounding rectangle of those poylines. This should +be okay, if it weren't for the fact that the Gnome logout screen is drawing +polylines in rectangles and this asks for a rotation of the entire rectangle. +This is very slow. + +To circumvent this slowness, we intercept the ValidatePolylines function and +override the default "Fallback" Polylines with our own Polylines function. Our +Polylines function first draws the polylines through the original Fallback +function and then rotates the lines, line by line. We then set a flag and +return control to the shadowFB which will try to rotate the bounding rectangle. +However, the flag has been set and the RefreshArea function does nothing but +clear the flag so the next Refresh that comes in shoiuld be handled correctly. + +All this code improves the speed quite a bit. + +*/ + +#define IS_VISIBLE(pWin) \ +( \ + pScrn->vtSema \ + && (((WindowPtr) pWin)->visibility != VisibilityFullyObscured) \ +) + +#define TRIM_BOX(box, pGC) \ +{ \ + BoxPtr extents = &pGC->pCompositeClip->extents; \ + if (box.x1 < extents->x1) box.x1 = extents->x1; \ + if (box.y1 < extents->y1) box.y1 = extents->y1; \ + if (box.x2 > extents->x2) box.x2 = extents->x2; \ + if (box.y2 > extents->y2) box.y2 = extents->y2; \ +} + +#define TRANSLATE_BOX(box, pDraw) \ +{ \ + box.x1 += pDraw->x; \ + box.y1 += pDraw->y; \ + box.x2 += pDraw->x; \ + box.y2 += pDraw->y; \ +} + +#define BOX_NOT_EMPTY(box) \ + ((box.x2 > box.x1) && (box.y2 > box.y1)) + +static void +SMI_ValidatePolylines(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + SMIPtr pSmi = SMIPTR(infoRec->pScrn); + + ENTER_PROC("SMI_ValidatePolylines"); + + pSmi->ValidatePolylines(pGC, changes, pDraw); + if (pGC->ops->Polylines == XAAGetFallbackOps()->Polylines) { + /* Override the Polylines function with our own Polylines function. */ + pGC->ops->Polylines = SMI_Polylines; + } + + LEAVE_PROC("SMI_ValidatePolylines"); +} + +static void +SMI_Polylines(DrawablePtr pDraw, GCPtr pGC, int mode, int npt, + DDXPointPtr pptInit) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + ScrnInfoPtr pScrn = infoRec->pScrn; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER_PROC("SMI_Polylines"); + + /* Call the original Polylines function. */ + pGC->ops->Polylines = XAAGetFallbackOps()->Polylines; + (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); + pGC->ops->Polylines = SMI_Polylines; + + if (IS_VISIBLE(pDraw) && npt) { + /* Allocate a temporary buffer for all segments of the polyline. */ + BoxPtr pBox = xnfcalloc(sizeof(BoxRec), npt); + int extra = pGC->lineWidth >> 1, box; + + if (npt > 1) { + /* Adjust the extra space required per polyline segment. */ + if (pGC->joinStyle == JoinMiter) { + extra = 6 * pGC->lineWidth; + } else if (pGC->capStyle == CapProjecting) { + extra = pGC->lineWidth; + } + } + + for (box = 0; --npt;) { + /* Setup the bounding box for one polyline segment. */ + pBox[box].x1 = pptInit->x; + pBox[box].y1 = pptInit->y; + pptInit++; + pBox[box].x2 = pptInit->x; + pBox[box].y2 = pptInit->y; + if (mode == CoordModePrevious) { + pBox[box].x2 += pBox[box].x1; + pBox[box].y2 += pBox[box].y1; + } + + /* Sort coordinates. */ + if (pBox[box].x1 > pBox[box].x2) { + int tmp = pBox[box].x1; + pBox[box].x1 = pBox[box].x2; + pBox[box].x2 = tmp; + } + if (pBox[box].y1 > pBox[box].y2) { + int tmp = pBox[box].y1; + pBox[box].y1 = pBox[box].y2; + pBox[box].y2 = tmp; + } + + /* Add extra space required for each polyline segment. */ + pBox[box].x1 -= extra; + pBox[box].y1 -= extra; + pBox[box].x2 += extra + 1; + pBox[box].y2 += extra + 1; + + /* See if we need to draw this polyline segment. */ + TRANSLATE_BOX(pBox[box], pDraw); + TRIM_BOX(pBox[box], pGC); + if (BOX_NOT_EMPTY(pBox[box])) { + box++; + } + } + + if (box) { + /* Refresh all polyline segments now. */ + if (pSmi->Chipset == SMI_COUGAR3DR) { + SMI_RefreshArea730(pScrn, box, pBox); + } else { + SMI_RefreshArea(pScrn, box, pBox); + } + } + + /* Free the temporary buffer. */ + xfree(pBox); + } + + pSmi->polyLines = TRUE; + LEAVE_PROC("SMI_Polylines"); +} + |