summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/smi.h14
-rw-r--r--src/smi_accel.c817
-rw-r--r--src/smi_dga.c24
-rw-r--r--src/smi_driver.c94
-rw-r--r--src/smi_exa.c446
-rw-r--r--src/smi_video.c200
-rw-r--r--src/smi_video.h15
-rw-r--r--src/smi_xaa.c844
9 files changed, 1534 insertions, 922 deletions
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 \
diff --git a/src/smi.h b/src/smi.h
index f20900a..ba44a03 100644
--- a/src/smi.h
+++ b/src/smi.h
@@ -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");
+}
+