diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | man/i810.man | 22 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/common.h | 77 | ||||
-rw-r--r-- | src/i810.h | 4 | ||||
-rw-r--r-- | src/i810_dri.c | 2 | ||||
-rw-r--r-- | src/i810_driver.c | 10 | ||||
-rw-r--r-- | src/i830.h | 49 | ||||
-rw-r--r-- | src/i830_common.h | 29 | ||||
-rw-r--r-- | src/i830_cursor.c | 153 | ||||
-rw-r--r-- | src/i830_dga.c | 116 | ||||
-rw-r--r-- | src/i830_dri.c | 371 | ||||
-rw-r--r-- | src/i830_dri.h | 10 | ||||
-rw-r--r-- | src/i830_driver.c | 1159 | ||||
-rw-r--r-- | src/i830_memory.c | 542 | ||||
-rw-r--r-- | src/i830_modes.c | 2 | ||||
-rw-r--r-- | src/i830_randr.c | 356 | ||||
-rw-r--r-- | src/i830_rotate.c | 1181 | ||||
-rw-r--r-- | src/i830_shadow.c | 253 | ||||
-rw-r--r-- | src/i830_video.c | 869 |
20 files changed, 4038 insertions, 1172 deletions
diff --git a/configure.ac b/configure.ac index e50b3d18..665b76a7 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.57) AC_INIT([xf86-video-i810], - 1.4.1.3, + 1.5.0.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-video-i810) diff --git a/man/i810.man b/man/i810.man index 8c432eff..099e1f8a 100644 --- a/man/i810.man +++ b/man/i810.man @@ -192,16 +192,18 @@ the machine has booted, but unfortunately it doesn't always work and is extremely dependent upon the Video BIOS. Default: disabled .TP -.BI "Option \*qRotate\*q \*qCW\*q" -.TP -.BI "Option \*qRotate\*q \*qCCW\*q" -Rotate the desktop 90 degrees clockwise or counterclockwise. This option -forces the ShadowFB option on, and disables acceleration. -Default: no rotation. -.TP -.BI "Option \*qShadowFB\*q \*q" boolean \*q -Enable or disable use of the shadow framebuffer layer. This option -disables acceleration. Default: off. +.BI "Option \*qRotate\*q \*q90\*q" +Rotate the desktop 90 degrees counterclockwise. Other valid options are +0, 90, 180 and 270 degrees. The RandR extension is used for rotation +functionality. So this option allows the Xserver to start with a rotated +mode of operation. +Default: 0 degrees. +.TP +.BI "Option \*qLinearAlloc\*q \*q" integer \*q +Allows more memory for the offscreen allocator. This usually helps in +situations where HDTV movies are required to play but not enough offscreen +memory is usually available. Set this to 6144 for upto 1920x1080 HDTV support. +Default 0KB (off). .SH "SEE ALSO" __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) diff --git a/src/Makefile.am b/src/Makefile.am index fa695928..c64c2036 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,7 +53,8 @@ i810_drv_la_SOURCES = \ i830_memory.c \ i830_modes.c \ i830_video.c \ - i830_shadow.c + i830_rotate.c \ + i830_randr.c if DRI i810_drv_la_SOURCES += \ diff --git a/src/common.h b/src/common.h index 85a24ab3..bb89dd25 100644 --- a/src/common.h +++ b/src/common.h @@ -119,29 +119,21 @@ extern void I830DPRINTF_stub(const char *filename, int line, ErrorF( "OUT_RING %lx: %x, (mask %x)\n", \ (unsigned long)(outring), (unsigned int)(n), ringmask); \ *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ + outring += 4; ringused += 4; \ outring &= ringmask; \ } while (0) -#if 1 #define ADVANCE_LP_RING() do { \ + if (ringused > needed) \ + ErrorF("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ", \ + __FUNCTION__, ringused, needed); \ RecPtr->LpRing->tail = outring; \ + RecPtr->LpRing->space -= ringused; \ if (outring & 0x07) \ ErrorF("ADVANCE_LP_RING: " \ "outring (0x%x) isn't on a QWord boundary", outring); \ OUTREG(LP_RING + RING_TAIL, outring); \ } while (0) -#else -#define ADVANCE_LP_RING() { \ - RecPtr->LpRing->tail = outring; \ - if (outring & 0x07) \ - ErrorF("ADVANCE_LP_RING: " \ - "outring (0x%x) isn't on a QWord boundary", outring); \ - ErrorF("head is %d, tail is %d [%d]\n", INREG(LP_RING + RING_HEAD), INREG(LP_RING + RING_TAIL), outring); \ - OUTREG(LP_RING + RING_TAIL, outring); \ - ErrorF("head is %d, tail is %d [%d]\n", INREG(LP_RING + RING_HEAD), INREG(LP_RING + RING_TAIL), outring); \ -} -#endif /* * XXX Note: the head/tail masks are different for 810 and i830. @@ -158,54 +150,9 @@ extern void I830DPRINTF_stub(const char *filename, int line, } while (_head != _tail); \ } while( 0) -/* - * This is for debugging a potential problem writing the tail pointer - * close to the end of the ring buffer. - */ -#ifndef AVOID_TAIL_END -#define AVOID_TAIL_END 0 -#endif -#ifndef AVOID_SIZE -#define AVOID_SIZE 64 -#endif - -#if AVOID_TAIL_END - -#define BEGIN_LP_RING(n) \ - unsigned int outring, ringmask; \ - volatile unsigned char *virt; \ - int needed; \ - if ((n) & 1) \ - ErrorF("BEGIN_LP_RING called with odd argument: %d\n", n); \ - if ((n) > 2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC)) \ - DO_RING_IDLE(); \ - needed = (n) * 4; \ - if ((RecPtr->LpRing->tail > RecPtr->LpRing->tail_mask - AVOID_SIZE) || \ - (RecPtr->LpRing->tail + needed) > \ - RecPtr->LpRing->tail_mask - AVOID_SIZE) { \ - needed += RecPtr->LpRing->tail_mask + 1 - RecPtr->LpRing->tail; \ - ErrorF("BEGIN_LP_RING: skipping last 64 bytes of " \ - "ring (%d vs %d)\n", needed, (n) * 4); \ - } \ - if (RecPtr->LpRing->space < needed) \ - WaitRingFunc(pScrn, needed, 0); \ - RecPtr->LpRing->space -= needed; \ - outring = RecPtr->LpRing->tail; \ - ringmask = RecPtr->LpRing->tail_mask; \ - virt = RecPtr->LpRing->virtual_start; \ - while (needed > (n) * 4) { \ - ErrorF("BEGIN_LP_RING: putting MI_NOOP at 0x%x (remaining %d)\n", \ - outring, needed - (n) * 4); \ - OUT_RING(MI_NOOP); \ - needed -= 4; \ - } \ - if (I810_DEBUG & DEBUG_VERBOSE_RING) \ - ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME); - -#else /* AVOID_TAIL_END */ #define BEGIN_LP_RING(n) \ - unsigned int outring, ringmask; \ + unsigned int outring, ringmask, ringused = 0; \ volatile unsigned char *virt; \ int needed; \ if ((n) & 1) \ @@ -215,14 +162,12 @@ extern void I830DPRINTF_stub(const char *filename, int line, needed = (n) * 4; \ if (RecPtr->LpRing->space < needed) \ WaitRingFunc(pScrn, needed, 0); \ - RecPtr->LpRing->space -= needed; \ outring = RecPtr->LpRing->tail; \ ringmask = RecPtr->LpRing->tail_mask; \ virt = RecPtr->LpRing->virtual_start; \ if (I810_DEBUG & DEBUG_VERBOSE_RING) \ ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME); -#endif /* AVOID_TAIL_END */ /* Memory mapped register access macros */ @@ -322,6 +267,11 @@ extern int I810_DEBUG; #define PCI_CHIP_I945_G_BRIDGE 0x2770 #endif +#ifndef PCI_CHIP_I945_GM +#define PCI_CHIP_I945_GM 0x27A2 +#define PCI_CHIP_I945_GM_BRIDGE 0x27A0 +#endif + #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_E) @@ -332,11 +282,14 @@ extern int I810_DEBUG; #define IS_I852(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME)) #define IS_I855(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME)) #define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G) + #define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G || pI810->PciInfo->chipType == PCI_CHIP_E7221_G) #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM) #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G) +#define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM) +#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810)) -#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810)) +#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810)) #define GTT_PAGE_SIZE KB(4) #define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y)) @@ -66,8 +66,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define I810_NAME "I810" #define I810_DRIVER_NAME "i810" #define I810_MAJOR_VERSION 1 -#define I810_MINOR_VERSION 4 -#define I810_PATCHLEVEL 1 +#define I810_MINOR_VERSION 5 +#define I810_PATCHLEVEL 0 /* HWMC Surfaces */ diff --git a/src/i810_dri.c b/src/i810_dri.c index f9b95bdc..82fb0594 100644 --- a/src/i810_dri.c +++ b/src/i810_dri.c @@ -356,7 +356,7 @@ I810DRIScreenInit(ScreenPtr pScreen) pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL; - pDRIInfo->frameBufferPhysicalAddress = pI810->LinearAddr; + pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr; pDRIInfo->frameBufferSize = (((pScrn->displayWidth * pScrn->virtualY * pI810->cpp) + 4096 - 1) / 4096) * 4096; diff --git a/src/i810_driver.c b/src/i810_driver.c index bfa1dae9..54395a78 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -136,6 +136,7 @@ static SymTabRec I810Chipsets[] = { {PCI_CHIP_E7221_G, "E7221 (i915)"}, {PCI_CHIP_I915_GM, "915GM"}, {PCI_CHIP_I945_G, "945G"}, + {PCI_CHIP_I945_GM, "945GM"}, {-1, NULL} }; @@ -154,6 +155,7 @@ static PciChipsets I810PciChipsets[] = { {PCI_CHIP_E7221_G, PCI_CHIP_E7221_G, RES_SHARED_VGA}, {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA}, {PCI_CHIP_I945_G, PCI_CHIP_I945_G, RES_SHARED_VGA}, + {PCI_CHIP_I945_GM, PCI_CHIP_I945_GM, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED } }; @@ -299,6 +301,7 @@ const char *I810drmSymbols[] = { "drmGetInterruptFromBusID", "drmGetLibVersion", "drmGetVersion", + "drmRmMap", NULL }; @@ -306,6 +309,7 @@ const char *I810drmSymbols[] = { const char *I810driSymbols[] = { "DRICloseScreen", "DRICreateInfoRec", + "DRIGetContext", "DRIDestroyInfoRec", "DRIFinishScreenInit", "DRIGetSAREAPrivate", @@ -317,16 +321,17 @@ const char *I810driSymbols[] = { "DRICreatePCIBusID", NULL }; +#endif const char *I810shadowSymbols[] = { "shadowInit", "shadowSetup", "shadowAdd", + "shadowRemove", + "shadowUpdateRotatePacked", NULL }; -#endif - #ifndef I810_DEBUG int I810_DEBUG = (0 /* | DEBUG_ALWAYS_SYNC */ @@ -569,6 +574,7 @@ I810Probe(DriverPtr drv, int flags) case PCI_CHIP_E7221_G: case PCI_CHIP_I915_GM: case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: xf86SetEntitySharable(usedChips[i]); /* Allocate an entity private if necessary */ @@ -58,6 +58,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86int10.h" #include "vbe.h" #include "vgaHW.h" +#include "randrstr.h" #ifdef XF86DRI #include "xf86drm.h" @@ -168,6 +169,8 @@ typedef struct _I830Rec { int fixedPipe; + DisplayModePtr currentMode; + Bool Clone; int CloneRefresh; int CloneHDisplay; @@ -214,14 +217,25 @@ typedef struct _I830Rec { #ifdef I830_XV /* For Xvideo */ I830MemRange *OverlayMem; + I830MemRange LinearMem; #endif + unsigned int LinearAlloc; + + I830MemRange RotatedMem; + I830MemRange RotatedMem2; + Rotation rotation; + int InitialRotation; + int displayWidth; + void (*PointerMoved)(int, int, int); + CreateScreenResourcesProcPtr CreateScreenResources; + int *used3D; #ifdef XF86DRI I830MemRange BackBuffer; I830MemRange DepthBuffer; I830MemRange TexMem; - I830MemRange ContextMem; int TexGranularity; + I830MemRange ContextMem; int drmMinor; Bool have3DWindows; #endif @@ -234,6 +248,7 @@ typedef struct _I830Rec { Bool CursorNeedsPhysical; Bool CursorIsARGB; + CursorPtr pCurs; int MonType1; int MonType2; @@ -303,13 +318,6 @@ typedef struct _I830Rec { /* Broken-out options. */ OptionInfoPtr Options; - int rotate; - Bool shadowFB; - - /* Support for shadowFB and rotation. */ - unsigned char *shadowPtr; - int shadowPitch; - void (*PointerMoved)(int, int, int); /* Stolen memory support */ Bool StolenOnly; @@ -335,8 +343,9 @@ typedef struct _I830Rec { Bool checkDevices; int monitorSwitch; int operatingDevices; + int toggleDevices; int savedDevices; - int lastDevice1, lastDevice2; + int lastDevice0, lastDevice1, lastDevice2; /* These are indexed by the display types */ Bool displayAttached[NumDisplayTypes]; @@ -399,15 +408,27 @@ extern void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode); extern void I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode); #endif +extern Bool I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, const int flags); +extern Bool I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, const int flags); #ifdef XF86DRI extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags); +extern Bool I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags); +extern Bool I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags); +extern Bool I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags); extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn); extern Bool I830DRIScreenInit(ScreenPtr pScreen); +extern Bool I830CheckDRIAvailable(ScrnInfoPtr pScrn); extern Bool I830DRIDoMappings(ScreenPtr pScreen); extern Bool I830DRIResume(ScreenPtr pScreen); extern void I830DRICloseScreen(ScreenPtr pScreen); extern Bool I830DRIFinishScreenInit(ScreenPtr pScreen); +extern Bool I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea); +extern void I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea); +extern Bool I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea); +extern void I830DRIUnlock(ScrnInfoPtr pScrn); +extern Bool I830DRILock(ScrnInfoPtr pScrn); #endif + extern Bool I830AccelInit(ScreenPtr pScreen); extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, @@ -432,11 +453,13 @@ extern Bool I830UnbindGARTMemory(ScrnInfoPtr pScrn); extern unsigned long I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags); +extern void I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range); extern void I830PrintAllRegisters(I830RegPtr i830Reg); extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg); extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer); +extern Bool I830IsPrimary(ScrnInfoPtr pScrn); extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe); @@ -445,12 +468,8 @@ extern void I830UnsetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe); extern void I830PrintModes(ScrnInfoPtr pScrn); extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh); extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode); -extern void I830PointerMoved(int index, int x, int y); -extern void I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); -extern void I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox); -extern void I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox); -extern void I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox); -extern void I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode); +extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); /* * 12288 is set as the maximum, chosen because it is enough for diff --git a/src/i830_common.h b/src/i830_common.h index a0a00ff4..41b5cc3c 100644 --- a/src/i830_common.h +++ b/src/i830_common.h @@ -51,6 +51,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define DRM_I830_FREE 0x09 #define DRM_I830_INIT_HEAP 0x0a #define DRM_I830_CMDBUFFER 0x0b +#define DRM_I830_DESTROY_HEAP 0x0c typedef struct { enum { @@ -87,6 +88,30 @@ typedef struct { int pf_active; int pf_current_page; /* which buffer is being displayed? */ int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; } drmI830Sarea; /* Flags for perf_boxes @@ -164,5 +189,9 @@ typedef struct { int start; } drmI830MemInitHeap; +typedef struct { + int region; +} drmI830MemDestroyHeap; + #endif /* _I830_DRM_H_ */ diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 24114192..dfed8cda 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -86,12 +86,14 @@ I830InitHWCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830InitHWCursor\n"); /* Initialise the HW cursor registers, leaving the cursor hidden. */ - if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) { + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL | MCURSOR_PIPE_SELECT); temp |= CURSOR_MODE_DISABLE; temp |= (pI830->pipe << 28); + if(pI830->CursorIsARGB) + temp |= MCURSOR_GAMMA_ENABLE; /* Need to set control, then address. */ OUTREG(CURSOR_A_CONTROL, temp); if (pI830->CursorIsARGB) @@ -139,8 +141,8 @@ I830CursorInit(ScreenPtr pScreen) if (!infoPtr) return FALSE; - infoPtr->MaxWidth = 64; - infoPtr->MaxHeight = 64; + infoPtr->MaxWidth = I810_CURSOR_X; + infoPtr->MaxHeight = I810_CURSOR_Y; infoPtr->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | HARDWARE_CURSOR_INVERT_MASK | @@ -155,6 +157,8 @@ I830CursorInit(ScreenPtr pScreen) infoPtr->ShowCursor = I830ShowCursor; infoPtr->UseHWCursor = I830UseHWCursor; + pI830->pCurs = NULL; + #ifdef ARGB_CURSOR pI830->CursorIsARGB = FALSE; @@ -179,6 +183,8 @@ I830UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); + pI830->pCurs = pCurs; + DPRINTF(PFX, "I830UseHWCursor\n"); if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) return FALSE; @@ -198,6 +204,52 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) #ifdef ARGB_CURSOR pI830->CursorIsARGB = FALSE; #endif + + memset(pcurs, 0, 64 * 64 / 4); + +#define GetBit(image, x, y)\ + ((int)((*(image + ((x) / 8) + ((y) * (128/8))) &\ + (1 << ( 7 -((x) % 8) ))) ? 1 : 0)) + +#define SetBit(image, x, y)\ + (*(image + (x) / 8 + (y) * (128/8)) |=\ + (int) (1 << (7-((x) % 8)))) + + switch (pI830->rotation) { + case RR_Rotate_90: + for (y = 0; y < 64; y++) { + for (x = 0; x < 64; x++) { + if (GetBit(src, 64 - y - 1, x)) + SetBit(pcurs, x, y); + if (GetBit(src, 128 - y - 1, x)) + SetBit(pcurs, x + 64, y); + } + } + + return; + case RR_Rotate_180: + for (y = 0; y < 64; y++) { + for (x = 0; x < 64; x++) { + if (GetBit(src, 64 - x - 1, 64 - y - 1)) + SetBit(pcurs, x, y); + if (GetBit(src, 128 - x - 1, 64 - y - 1)) + SetBit(pcurs, x + 64, y); + } + } + + return; + case RR_Rotate_270: + for (y = 0; y < 64; y++) { + for (x = 0; x < 64; x++) { + if (GetBit(src, y, 64 - x - 1)) + SetBit(pcurs, x, y); + if (GetBit(src, y + 64, 64 - x - 1)) + SetBit(pcurs, x + 64, y); + } + } + + return; + } for (y = 0; y < 64; y++) { for (x = 0; x < 64 / 4; x++) { @@ -215,6 +267,9 @@ static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, "I830UseHWCursorARGB\n"); + + pI830->pCurs = pCurs; + if (pScrn->bitsPerPixel == 8) return FALSE; @@ -239,13 +294,52 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) if (!image) return; /* XXX can't happen */ -#ifdef ARGB_CURSOR pI830->CursorIsARGB = TRUE; -#endif w = pCurs->bits->width; h = pCurs->bits->height; + switch (pI830->rotation) { + case RR_Rotate_90: + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) + dst[(y) + ((64 - x - 1) * 64)] = *image++; + for(; x < 64; x++) + dst[(y) + ((64 - x - 1) * 64)] = 0; + } + for(; y < 64; y++) { + for(x = 0; x < 64; x++) + dst[(y) + ((64 - x - 1) * 64)] = 0; + } + return; + + case RR_Rotate_180: + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) + dst[(64 - x - 1) + ((64 - y - 1) * 64)] = *image++; + for(; x < 64; x++) + dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0; + } + for(; y < 64; y++) { + for(x = 0; x < 64; x++) + dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0; + } + return; + + case RR_Rotate_270: + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) + dst[(64 - y - 1) + (x * 64)] = *image++; + for(; x < 64; x++) + dst[(64 - y - 1) + (x * 64)] = 0; + } + for(; y < 64; y++) { + for(x = 0; x < 64; x++) + dst[(64 - y - 1) + (x * 64)] = 0; + } + return; + } + for(y = 0; y < h; y++) { for(x = 0; x < w; x++) *dst++ = *image++; @@ -267,7 +361,49 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) CARD32 temp = 0; static Bool outsideViewport = FALSE; Bool hide = FALSE, show = FALSE; + int oldx = x, oldy = y; + int hotspotx = 0, hotspoty = 0; + + oldx += pScrn->frameX0; /* undo what xf86HWCurs did */ + oldy += pScrn->frameY0; + + switch (pI830->rotation) { + case RR_Rotate_0: + x = oldx; + y = oldy; + break; + case RR_Rotate_90: + x = oldy; + y = pScrn->pScreen->width - oldx; + hotspoty = I810_CURSOR_X; + break; + case RR_Rotate_180: + x = pScrn->pScreen->width - oldx; + y = pScrn->pScreen->height - oldy; + hotspotx = I810_CURSOR_X; + hotspoty = I810_CURSOR_Y; + break; + case RR_Rotate_270: + x = pScrn->pScreen->height - oldy; + y = oldx; + hotspotx = I810_CURSOR_Y; + break; + } + + x -= hotspotx; + y -= hotspoty; + /* Now, readjust */ + x -= pScrn->frameX0; + y -= pScrn->frameY0; + + /* Clamp the cursor position to the visible screen area */ + if (x >= pScrn->currentMode->HDisplay) x = pScrn->currentMode->HDisplay - 1; + if (y >= pScrn->currentMode->VDisplay) y = pScrn->currentMode->VDisplay - 1; + if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1; + if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1; + +#if 0 /* * There is a screen display problem when the cursor position is set * wholely outside of the viewport. We trap that here, turning the @@ -283,6 +419,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) show = TRUE; outsideViewport = FALSE; } +#endif if (x < 0) { temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); @@ -308,7 +445,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) } /* have to upload the base for the new position */ - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + if (IS_I9XX(pI830)) { if (pI830->CursorIsARGB) OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); else @@ -339,7 +476,7 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); pI830->cursorOn = TRUE; - if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) { + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); if (pI830->CursorIsARGB) @@ -387,7 +524,7 @@ I830HideCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) { + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); temp &= ~CURSOR_MODE; temp |= CURSOR_MODE_DISABLE; diff --git a/src/i830_dga.c b/src/i830_dga.c index e1991db4..e5bcfc72 100644 --- a/src/i830_dga.c +++ b/src/i830_dga.c @@ -54,6 +54,7 @@ static Bool I830_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, int *, int *, int *); +static void I830_CloseFramebuffer(ScrnInfoPtr pScrn); static Bool I830_SetMode(ScrnInfoPtr, DGAModePtr); static void I830_Sync(ScrnInfoPtr); static int I830_GetViewport(ScrnInfoPtr); @@ -69,7 +70,7 @@ static void I830_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, static DGAFunctionRec I830DGAFuncs = { I830_OpenFramebuffer, - NULL, + I830_CloseFramebuffer, I830_SetMode, I830_SetViewport, I830_GetViewport, @@ -131,11 +132,22 @@ I830DGAInit(ScreenPtr pScreen) currentMode->yViewportStep = 1; currentMode->viewportFlags = DGA_FLIP_RETRACE; currentMode->offset = 0; - currentMode->address = pI830->FbBase + pScrn->fbOffset; + if (I830IsPrimary(pScrn)) { + currentMode->address = pI830->FbBase + pI830->FrontBuffer.Start; + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + currentMode->address = pI830->FbBase + pI8301->FrontBuffer2.Start; + } - currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L; - currentMode->imageWidth = pI830->FbMemBox.x2; - currentMode->imageHeight = pI830->FbMemBox.y2; + currentMode->bytesPerScanline = ((pI830->displayWidth * Bpp) + 3) & ~3L; + if (I830IsPrimary(pScrn)) { + currentMode->imageWidth = pI830->FbMemBox.x2; + currentMode->imageHeight = pI830->FbMemBox.y2; + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + currentMode->imageWidth = pI8301->FbMemBox2.x2; + currentMode->imageHeight = pI8301->FbMemBox2.y2; + } currentMode->pixmapWidth = currentMode->imageWidth; currentMode->pixmapHeight = currentMode->imageHeight; currentMode->maxViewportX = currentMode->imageWidth - @@ -168,6 +180,7 @@ I830_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) if (!pMode) { /* restore the original mode */ DPRINTF(PFX, "Restoring original mode (from DGA mode)\n"); if (pI830->DGAactive) { + I830_CloseFramebuffer(pScrn); pScrn->currentMode = I830SavedDGAModes[index]; pScrn->SwitchMode(index, pScrn->currentMode, 0); pScrn->AdjustFrame(index, 0, 0, 0); @@ -178,6 +191,15 @@ I830_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) DPRINTF(PFX, "Setting DGA mode\n"); I830SavedDGAModes[index] = pScrn->currentMode; pI830->DGAactive = TRUE; + if (I830IsPrimary(pScrn)) { + pScrn->fbOffset = pI830->FrontBuffer.Start; + } + else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pScrn->fbOffset = pI8301->FrontBuffer2.Start; + } + pScrn->displayWidth = pI830->displayWidth; + I830SelectBuffer(pScrn, I830_SELECT_FRONT); } pScrn->SwitchMode(index, pMode->mode, 0); @@ -284,13 +306,19 @@ I830_OpenFramebuffer(ScrnInfoPtr pScrn, MARKER(); *name = NULL; /* no special device */ - *mem = (unsigned char *)(pI830->LinearAddr + pScrn->fbOffset); - if (pI830->init == 0) + if (I830IsPrimary(pScrn)) { *size = pI830->FrontBuffer.Size; + *mem = (unsigned char *)(pI830->LinearAddr + pI830->FrontBuffer.Start); + pScrn->fbOffset = pI830->FrontBuffer.Start; + } else { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); *size = pI8301->FrontBuffer2.Size; + *mem = (unsigned char *)(pI8301->LinearAddr + pI8301->FrontBuffer2.Start); + pScrn->fbOffset = pI8301->FrontBuffer2.Start; } + pScrn->displayWidth = pI830->displayWidth; + I830SelectBuffer(pScrn, I830_SELECT_FRONT); *offset = 0; *flags = DGA_NEED_ROOT; @@ -300,3 +328,77 @@ I830_OpenFramebuffer(ScrnInfoPtr pScrn, return TRUE; } + +static void +I830_CloseFramebuffer(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + /* Good pitches to allow tiling. Don't care about pitches < 1024. */ + static const int pitches[] = { +/* + 128 * 2, + 128 * 4, +*/ + 128 * 8, + 128 * 16, + 128 * 32, + 128 * 64, + 0 + }; + + if (I830IsPrimary(pScrn)) { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI830->RotatedMem.Start; + else + pScrn->fbOffset = pI830->FrontBuffer.Start; + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn->fbOffset = pI8301->FrontBuffer2.Start; + } + I830SelectBuffer(pScrn, I830_SELECT_FRONT); + + switch (pI830->rotation) { + case RR_Rotate_0: + pScrn->displayWidth = pI830->displayWidth; + break; + case RR_Rotate_90: + pScrn->displayWidth = pScrn->pScreen->width; + break; + case RR_Rotate_180: + pScrn->displayWidth = pI830->displayWidth; + break; + case RR_Rotate_270: + pScrn->displayWidth = pScrn->pScreen->width; + break; + } + + /* As DRI doesn't run on the secondary head, we know that disableTiling + * is always TRUE. + */ + if (I830IsPrimary(pScrn) && !pI830->disableTiling) { +#if 0 + int dWidth = pScrn->displayWidth; /* save current displayWidth */ +#endif + + for (i = 0; pitches[i] != 0; i++) { + if (pitches[i] >= pScrn->displayWidth) { + pScrn->displayWidth = pitches[i]; + break; + } + } + + /* + * If the displayWidth is a tilable pitch, test if there's enough + * memory available to enable tiling. + */ + if (pScrn->displayWidth == pitches[i]) { + /* TODO */ + } + } + +} diff --git a/src/i830_dri.c b/src/i830_dri.c index ade0c0ce..c2e060fc 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -149,9 +149,9 @@ I830InitDma(ScrnInfoPtr pScrn) info.depth_offset = pI830->DepthBuffer.Start; info.w = pScrn->virtualX; info.h = pScrn->virtualY; - info.pitch = pI830->backPitch; - info.back_pitch = pI830->backPitch; - info.depth_pitch = pI830->backPitch; + info.pitch = pI830->displayWidth; + info.back_pitch = pI830->displayWidth; + info.depth_pitch = pI830->displayWidth; info.cpp = pI830->cpp; if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT, @@ -405,18 +405,12 @@ I830InitVisualConfigs(ScreenPtr pScreen) } Bool -I830DRIScreenInit(ScreenPtr pScreen) +I830CheckDRIAvailable(ScrnInfoPtr pScrn) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - DRIInfoPtr pDRIInfo; - I830DRIPtr pI830DRI; - - DPRINTF(PFX, "I830DRIScreenInit\n"); /* Hardware 3D rendering only implemented for 16bpp and 32 bpp */ if (((pScrn->bitsPerPixel / 8) != 2 && pScrn->depth != 16) && (pScrn->bitsPerPixel / 8) != 4) { - xf86DrvMsg(pScreen->myNum, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Direct rendering only supported in 16 and 32 bpp modes\n"); return FALSE; } @@ -428,7 +422,7 @@ I830DRIScreenInit(ScreenPtr pScreen) if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { - xf86DrvMsg(pScreen->myNum, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] %s failed (libdri.a too old)\n", "I830DRIScreenInit"); return FALSE; } @@ -439,7 +433,7 @@ I830DRIScreenInit(ScreenPtr pScreen) DRIQueryVersion(&major, &minor, &patch); if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { - xf86DrvMsg(pScreen->myNum, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] %s failed because of a version mismatch.\n" "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n" "[dri] Disabling DRI.\n", @@ -449,6 +443,22 @@ I830DRIScreenInit(ScreenPtr pScreen) } } + return TRUE; +} + +Bool +I830DRIScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + DRIInfoPtr pDRIInfo; + I830DRIPtr pI830DRI; + + DPRINTF(PFX, "I830DRIScreenInit\n"); + + if (!I830CheckDRIAvailable(pScrn)) + return FALSE; + pDRIInfo = DRICreateInfoRec(); if (!pDRIInfo) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -473,10 +483,15 @@ I830DRIScreenInit(ScreenPtr pScreen) pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL; - pDRIInfo->frameBufferPhysicalAddress = pI830->LinearAddr + + pDRIInfo->frameBufferPhysicalAddress = (pointer) pI830->LinearAddr + pI830->FrontBuffer.Start; +#if 0 pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp); +#else + /* For rotation we map a 0 length framebuffer as we remap ourselves later */ + pDRIInfo->frameBufferSize = 0; +#endif pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp; pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES; @@ -572,11 +587,11 @@ I830DRIScreenInit(ScreenPtr pScreen) /* Check the i915 DRM version */ version = drmGetVersion(pI830->drmSubFD); if (version) { - if (version->version_major != 1 || version->version_minor < 1) { + if (version->version_major != 1 || version->version_minor < 4) { /* incompatible drm version */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] %s failed because of a version mismatch.\n" - "[dri] i915 kernel module version is %d.%d.%d but version 1.1 or greater is needed.\n" + "[dri] i915 kernel module version is %d.%d.%d but version 1.4 or greater is needed.\n" "[dri] Disabling DRI.\n", "I830DRIScreenInit", version->version_major, @@ -601,57 +616,136 @@ I830DRIScreenInit(ScreenPtr pScreen) } Bool -I830DRIDoMappings(ScreenPtr pScreen) +I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ScreenPtr pScreen = pScrn->pScreen; I830Ptr pI830 = I830PTR(pScrn); - DRIInfoPtr pDRIInfo = pI830->pDRIInfo; - I830DRIPtr pI830DRI = pDRIInfo->devPrivate; - DPRINTF(PFX, "I830DRIDoMappings\n"); - pI830DRI->regsSize = I830_REG_SIZE; - if (drmAddMap(pI830->drmSubFD, (drm_handle_t)pI830->MMIOAddr, - pI830DRI->regsSize, DRM_REGISTERS, 0, &pI830DRI->regs) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] Mapping front buffer\n"); + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(sarea->front_offset + pI830->LinearAddr), + sarea->front_size, + DRM_FRAME_BUFFER, /*DRM_AGP,*/ + 0, + &sarea->front_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(front_handle) failed. Disabling DRI\n"); DRICloseScreen(pScreen); return FALSE; } - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n", - pI830DRI->regs); - - /* - * The tile setup is now initiated from I830BIOSScreenInit(). - */ - - pI830->backPitch = pScrn->displayWidth; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08lx\n", + sarea->front_handle); - pI830DRI->backbufferSize = pI830->BackBuffer.Size; + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(sarea->back_offset + pI830->LinearAddr), + sarea->back_size, DRM_AGP, 0, + &sarea->back_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(back_handle) failed. Disabling DRI\n"); + DRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08lx\n", + sarea->back_handle); if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)pI830->BackBuffer.Start + pI830->LinearAddr, - pI830->BackBuffer.Size, DRM_AGP, 0, - &pI830DRI->backbuffer) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n"); + (drm_handle_t)sarea->depth_offset + pI830->LinearAddr, + sarea->depth_size, DRM_AGP, 0, + &sarea->depth_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n"); DRICloseScreen(pScreen); return FALSE; } - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Back Buffer = 0x%08x\n", - pI830DRI->backbuffer); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08lx\n", + sarea->depth_handle); - pI830DRI->depthbufferSize = pI830->DepthBuffer.Size; if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)pI830->DepthBuffer.Start + pI830->LinearAddr, - pI830->DepthBuffer.Size, DRM_AGP, 0, - &pI830DRI->depthbuffer) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] drmAddMap(depthbuffer) failed. Disabling DRI\n"); + (drm_handle_t)sarea->tex_offset + pI830->LinearAddr, + sarea->tex_size, DRM_AGP, 0, + &sarea->tex_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n"); DRICloseScreen(pScreen); return FALSE; } - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Depth Buffer = 0x%08x\n", - pI830DRI->depthbuffer); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] textures = 0x%08lx\n", + sarea->tex_handle); + + return TRUE; +} + + +void +I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +{ + I830Ptr pI830 = I830PTR(pScrn); + +#if 1 + if (sarea->front_handle) { + drmRmMap(pI830->drmSubFD, sarea->front_handle); + sarea->front_handle = 0; + } +#endif + if (sarea->back_handle) { + drmRmMap(pI830->drmSubFD, sarea->back_handle); + sarea->back_handle = 0; + } + if (sarea->depth_handle) { + drmRmMap(pI830->drmSubFD, sarea->depth_handle); + sarea->depth_handle = 0; + } + if (sarea->tex_handle) { + drmRmMap(pI830->drmSubFD, sarea->tex_handle); + sarea->tex_handle = 0; + } +} +static void +I830InitTextureHeap(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +{ + I830Ptr pI830 = I830PTR(pScrn); + + /* Start up the simple memory manager for agp space */ + drmI830MemInitHeap drmHeap; + drmHeap.region = I830_MEM_REGION_AGP; + drmHeap.start = 0; + drmHeap.size = sarea->tex_size; + + if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP, + &drmHeap, sizeof(drmHeap))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] Failed to initialized agp heap manager\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] Initialized kernel agp heap manager, %d\n", + sarea->tex_size); + + I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, + sarea->log_tex_granularity); + } +} + +Bool +I830DRIDoMappings(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + DRIInfoPtr pDRIInfo = pI830->pDRIInfo; + I830DRIPtr pI830DRI = pDRIInfo->devPrivate; + drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); + + DPRINTF(PFX, "I830DRIDoMappings\n"); + pI830DRI->regsSize = I830_REG_SIZE; + if (drmAddMap(pI830->drmSubFD, (drm_handle_t)pI830->MMIOAddr, + pI830DRI->regsSize, DRM_REGISTERS, 0, &pI830DRI->regs) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n"); + DRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08lx\n", + pI830DRI->regs); if (drmAddMap(pI830->drmSubFD, (drm_handle_t)pI830->LpRing->mem.Start + pI830->LinearAddr, @@ -662,25 +756,29 @@ I830DRIDoMappings(ScreenPtr pScreen) DRICloseScreen(pScreen); return FALSE; } - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n", + xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08lx\n", pI830->ring_map); - pI830DRI->textureSize = pI830->TexMem.Size; - pI830DRI->logTextureGranularity = pI830->TexGranularity; - - if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)pI830->TexMem.Start + pI830->LinearAddr, - pI830->TexMem.Size, DRM_AGP, 0, - &pI830DRI->textures) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] drmAddMap(textures) failed. Disabling DRI\n"); + if (!I830InitDma(pScrn)) { DRICloseScreen(pScreen); return FALSE; } - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] textures = 0x%08x\n", - pI830DRI->textures); - if (!I830InitDma(pScrn)) { + /* init to zero to be safe */ + sarea->front_handle = 0; + sarea->back_handle = 0; + sarea->depth_handle = 0; + sarea->tex_handle = 0; + + /* Need to initialize pScreen now to let RandR know. */ + pScrn->pScreen->width = pScrn->virtualX; + pScrn->pScreen->height = pScrn->virtualY; + + /* this will map the screen regions */ + if (!I830UpdateDRIBuffers(pScrn, sarea)) { + /* screen mappings probably failed */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAddMap(screen mappings) failed. Disabling DRI\n"); DRICloseScreen(pScreen); return FALSE; } @@ -713,29 +811,6 @@ I830DRIDoMappings(ScreenPtr pScreen) pI830DRI->irq); } - /* Start up the simple memory manager for agp space */ - { - drmI830MemInitHeap drmHeap; - drmHeap.region = I830_MEM_REGION_AGP; - drmHeap.start = 0; - drmHeap.size = pI830DRI->textureSize; - - if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP, - &drmHeap, sizeof(drmHeap))) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] Failed to initialized agp heap manager\n"); - } else { - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Initialized kernel agp heap manager, %d\n", - pI830DRI->textureSize); - - I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, - pI830->TexGranularity); - } - } - - - pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; pI830DRI->deviceID = pI830->PciInfo->chipType; pI830DRI->width = pScrn->virtualX; @@ -748,13 +823,6 @@ I830DRIDoMappings(ScreenPtr pScreen) pI830DRI->bitsPerPixel = pScrn->bitsPerPixel; - pI830DRI->textureOffset = pI830->TexMem.Start; - - pI830DRI->backOffset = pI830->BackBuffer.Start; - pI830DRI->depthOffset = pI830->DepthBuffer.Start; - - pI830DRI->backPitch = pI830->backPitch; - pI830DRI->depthPitch = pI830->backPitch; pI830DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); if (!(I830InitVisualConfigs(pScreen))) { @@ -854,23 +922,23 @@ I830DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, Bool I830DRIFinishScreenInit(ScreenPtr pScreen) { - drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, "I830DRIFinishScreenInit\n"); - memset(sPriv, 0, sizeof(sPriv)); - /* Have shadow run only while there is 3d active. */ +#if 0 if (pI830->allowPageFlip && pI830->drmMinor >= 1) { shadowSetup(pScreen); shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0); } else +#endif pI830->allowPageFlip = 0; + return DRIFinishScreenInit(pScreen); } @@ -965,8 +1033,13 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, DDXPointPtr pptTmp, pptNew2; int xdir, ydir; +#if 0 int screenwidth = pScrn->virtualX; int screenheight = pScrn->virtualY; +#else + int screenwidth = pScreen->width; + int screenheight = pScreen->height; +#endif BoxPtr pbox = REGION_RECTS(prgnSrc); int nbox = REGION_NUM_RECTS(prgnSrc); @@ -1152,6 +1225,7 @@ I830EmitInvarientState(ScrnInfoPtr pScrn) */ +#if 0 /* This should be done *before* XAA syncs, * Otherwise will have to sync again??? */ @@ -1196,7 +1270,7 @@ I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) ADVANCE_LP_RING(); } } - +#endif static void I830EnablePageFlip(ScreenPtr pScreen) @@ -1261,7 +1335,6 @@ I830DRITransitionMultiToSingle3d(ScreenPtr pScreen) I830EnablePageFlip(pScreen); } - static void I830DRITransitionTo3d(ScreenPtr pScreen) { @@ -1294,3 +1367,107 @@ I830DRITransitionTo2d(ScreenPtr pScreen) } +/** + * Update the SAREA fields with the most recent values. + * This gets called after the screen orientation/rotation changes. + */ +Bool +I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +{ + I830Ptr pI830 = I830PTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; + Bool success; + + I830DRIUnmapScreenRegions(pScrn, sarea); + + if (pI830->rotation == RR_Rotate_0) { + sarea->front_offset = pI830->FrontBuffer.Start; + /* Don't use FrontBuffer.Size here as it includes the pixmap cache area + * Instead, calculate the entire framebuffer. + */ + sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp; + } else { + /* Need to deal with rotated2 once we have dual head DRI */ + sarea->front_offset = pI830->RotatedMem.Start; + sarea->front_size = pI830->RotatedMem.Size; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] init sarea width,height = %d x %d (pitch %d)\n", + pScreen->width, pScreen->height,pScrn->displayWidth); + + sarea->width = pScreen->width; + sarea->height = pScreen->height; + sarea->back_offset = pI830->BackBuffer.Start; + sarea->back_size = pI830->BackBuffer.Size; + sarea->depth_offset = pI830->DepthBuffer.Start; + sarea->depth_size = pI830->DepthBuffer.Size; + sarea->tex_offset = pI830->TexMem.Start; + sarea->tex_size = pI830->TexMem.Size; + sarea->log_tex_granularity = pI830->TexGranularity; + sarea->pitch = pScrn->displayWidth; + sarea->virtualX = pScrn->virtualX; + sarea->virtualY = pScrn->virtualY; + + switch (pI830->rotation) { + case RR_Rotate_0: + sarea->rotation = 0; + break; + case RR_Rotate_90: + sarea->rotation = 90; + break; + case RR_Rotate_180: + sarea->rotation = 180; + break; + case RR_Rotate_270: + sarea->rotation = 270; + break; + default: + sarea->rotation = 0; + } + if (pI830->rotation == RR_Rotate_0) { + sarea->rotated_offset = -1; + sarea->rotated_size = 0; + } + else { + sarea->rotated_offset = pI830->FrontBuffer.Start; + sarea->rotated_size = pI830->FrontBuffer.Size; + } + + /* This is the original pitch */ + sarea->rotated_pitch = pI830->displayWidth; + + success = I830DRIMapScreenRegions(pScrn, sarea); + + I830InitTextureHeap(pScrn, sarea); + + return success; +} + +Bool +I830DRILock(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (pI830->directRenderingEnabled && !pI830->LockHeld) { + DRILock(screenInfo.screens[pScrn->scrnIndex], 0); + pI830->LockHeld = 1; + I830RefreshRing(pScrn); + return TRUE; + } + else + return FALSE; +} + + + +void +I830DRIUnlock(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (pI830->directRenderingEnabled && pI830->LockHeld) { + DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); + pI830->LockHeld = 0; + } +} diff --git a/src/i830_dri.h b/src/i830_dri.h index 5ac99e5e..b1cb5887 100644 --- a/src/i830_dri.h +++ b/src/i830_dri.h @@ -9,8 +9,8 @@ #define I830_MAX_DRAWABLES 256 #define I830_MAJOR_VERSION 1 -#define I830_MINOR_VERSION 4 -#define I830_PATCHLEVEL 1 +#define I830_MINOR_VERSION 5 +#define I830_PATCHLEVEL 0 #define I830_REG_SIZE 0x80000 @@ -24,6 +24,9 @@ typedef struct _I830DRIRec { drmSize depthbufferSize; drm_handle_t depthbuffer; + drmSize rotatedSize; + drm_handle_t rotatedbuffer; + drm_handle_t textures; int textureSize; @@ -46,6 +49,9 @@ typedef struct _I830DRIRec { int depthOffset; int depthPitch; + int rotatedOffset; + int rotatedPitch; + int logTextureGranularity; int textureOffset; diff --git a/src/i830_driver.c b/src/i830_driver.c index b281affd..29606c42 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -144,8 +144,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * - Fix Xvideo with high-res LFP's * - Add ARGB HW cursor support * - * 30/2005 Alan Hourihane + * 05/2005 Alan Hourihane * - Add Intel(R) 945G support. + * + * 09/2005 Alan Hourihane + * - Add Intel(R) 945GM support. + * */ #ifdef HAVE_CONFIG_H @@ -168,14 +172,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "mipointer.h" #include "micmap.h" #include "shadowfb.h" - +#include <X11/extensions/randr.h> #include "fb.h" #include "miscstruct.h" #include "xf86xv.h" #include <X11/extensions/Xv.h> #include "vbe.h" #include "vbeModes.h" - +#include "shadow.h" #include "i830.h" #ifdef XF86DRI @@ -196,6 +200,7 @@ static SymTabRec I830BIOSChipsets[] = { {PCI_CHIP_E7221_G, "E7221 (i915)"}, {PCI_CHIP_I915_GM, "915GM"}, {PCI_CHIP_I945_G, "945G"}, + {PCI_CHIP_I945_GM, "945GM"}, {-1, NULL} }; @@ -208,6 +213,7 @@ static PciChipsets I830BIOSPciChipsets[] = { {PCI_CHIP_E7221_G, PCI_CHIP_E7221_G, RES_SHARED_VGA}, {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA}, {PCI_CHIP_I945_G, PCI_CHIP_I945_G, RES_SHARED_VGA}, + {PCI_CHIP_I945_GM, PCI_CHIP_I945_GM, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED} }; @@ -234,8 +240,8 @@ typedef enum { OPTION_CLONE_REFRESH, OPTION_CHECKDEVICES, OPTION_FIXEDPIPE, - OPTION_SHADOW_FB, - OPTION_ROTATE + OPTION_ROTATE, + OPTION_LINEARALLOC } I830Opts; static OptionInfoRec I830BIOSOptions[] = { @@ -255,8 +261,8 @@ static OptionInfoRec I830BIOSOptions[] = { {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER, {0}, FALSE}, {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN, {0}, FALSE}, {OPTION_FIXEDPIPE, "FixedPipe", OPTV_ANYSTR, {0}, FALSE}, - {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE}, + {OPTION_LINEARALLOC, "LinearAlloc", OPTV_INTEGER, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -271,10 +277,12 @@ static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock *block); static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg); static Bool SetPipeAccess(ScrnInfoPtr pScrn); -static Bool IsPrimary(ScrnInfoPtr pScrn); extern int I830EntityIndex; +/* temporary */ +extern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y); + #ifdef I830DEBUG void @@ -354,10 +362,12 @@ I830BIOSFreeRec(ScrnInfoPtr pScrn) } while (mode && mode != pScrn->modes); } - if (pI830->vbeInfo) - VBEFreeVBEInfo(pI830->vbeInfo); - if (pI830->pVbe) - vbeFree(pI830->pVbe); + if (I830IsPrimary(pScrn)) { + if (pI830->vbeInfo) + VBEFreeVBEInfo(pI830->vbeInfo); + if (pI830->pVbe) + vbeFree(pI830->pVbe); + } pVesa = pI830->vesa; if (pVesa->monitor) @@ -434,6 +444,93 @@ GetToggleList(ScrnInfoPtr pScrn, int toggle) } static int +GetNextDisplayDeviceList(ScrnInfoPtr pScrn, int toggle) +{ + vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; + int devices = 0; + int pipe = 0; + int i; + + DPRINTF(PFX, "GetNextDisplayDeviceList\n"); + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x5f64; + pVbe->pInt10->bx = 0xA00; + pVbe->pInt10->bx |= toggle; + pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); + pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); + + xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) + return 0; + + for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) { + CARD32 VODA = (CARD32)((CARD32*)pVbe->memory)[i]; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Next ACPI _DGS [%d] 0x%lx\n", + i, VODA); + + /* Check if it's a custom Video Output Device Attribute */ + if (!(VODA & 0x80000000)) + continue; + + pipe = (VODA & 0x000000F0) >> 4; + + if (pipe != 0 && pipe != 1) { + pipe = 0; +#if 0 + ErrorF("PIPE %d\n",pipe); +#endif + } + + switch ((VODA & 0x00000F00) >> 8) { + case 0x0: + case 0x1: /* CRT */ + devices |= PIPE_CRT << (pipe == 1 ? 8 : 0); + break; + case 0x2: /* TV/HDTV */ + devices |= PIPE_TV << (pipe == 1 ? 8 : 0); + break; + case 0x3: /* DFP */ + devices |= PIPE_DFP << (pipe == 1 ? 8 : 0); + break; + case 0x4: /* LFP */ + devices |= PIPE_LFP << (pipe == 1 ? 8 : 0); + break; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle devices 0x%x\n", devices); + + return devices; +} + +static int +GetAttachableDisplayDeviceList(ScrnInfoPtr pScrn) +{ + vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; + int i; + + DPRINTF(PFX, "GetAttachableDisplayDeviceList\n"); + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x5f64; + pVbe->pInt10->bx = 0x900; + pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); + pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); + + xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) + return 0; + + for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Attachable device 0x%lx.\n", ((CARD32*)pVbe->memory)[i]); + + return pVbe->pInt10->cx & 0xffff; +} + +static int BitToRefresh(int bits) { int i; @@ -624,6 +721,7 @@ SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh) return 0; } +#if 0 static Bool SetPowerStatus(ScrnInfoPtr pScrn, int mode) { @@ -640,6 +738,7 @@ SetPowerStatus(ScrnInfoPtr pScrn, int mode) return FALSE; } +#endif static Bool GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB, @@ -677,6 +776,7 @@ GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB, return FALSE; } +#if 0 static int GetLFPCompMode(ScrnInfoPtr pScrn) { @@ -695,7 +795,6 @@ GetLFPCompMode(ScrnInfoPtr pScrn) return -1; } -#if 0 static Bool SetLFPCompMode(ScrnInfoPtr pScrn, int compMode) { @@ -882,7 +981,7 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices) setmode = FALSE; if (pI830->closing) setmode = FALSE; - + if (setmode) { VBEGetVBEMode(pVbe, &getmode1); I830Set640x480(pScrn); @@ -1323,7 +1422,7 @@ I830DetectMemory(ScrnInfoPtr pScrn) * The GTT varying according the the FbMapSize and the popup is 4KB */ range = (pI830->FbMapSize / (1024*1024)) + 4; - if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: memsize = MB(1) - KB(range); @@ -1341,11 +1440,11 @@ I830DetectMemory(ScrnInfoPtr pScrn) memsize = MB(32) - KB(range); break; case I915G_GMCH_GMS_STOLEN_48M: - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) + if (IS_I9XX(pI830)) memsize = MB(48) - KB(range); break; case I915G_GMCH_GMS_STOLEN_64M: - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) + if (IS_I9XX(pI830)) memsize = MB(64) - KB(range); break; } @@ -1414,7 +1513,7 @@ I830MapMem(ScrnInfoPtr pScrn) if (!pI830->FbBase) return FALSE; - if (IsPrimary(pScrn)) + if (I830IsPrimary(pScrn)) pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem.Start; return TRUE; @@ -1513,6 +1612,9 @@ SaveBIOSMemSize(ScrnInfoPtr pScrn) DPRINTF(PFX, "SaveBIOSMemSize\n"); + if (!I830IsPrimary(pScrn)) + return FALSE; + pI830->useSWF1 = FALSE; #if HAVE_GET_PUT_BIOSMEMSIZE @@ -1572,6 +1674,9 @@ TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit) PCITAG tag =pciTag(0,0,0); + if (!I830IsPrimary(pScrn)) + return 0; + if(!pI830->PciInfo || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830))) return 0; @@ -1618,10 +1723,16 @@ TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit) if (preinit) { /* reinitialize VBE for new size */ - VBEFreeVBEInfo(pI830->vbeInfo); - vbeFree(pI830->pVbe); - pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + if (I830IsPrimary(pScrn)) { + VBEFreeVBEInfo(pI830->vbeInfo); + vbeFree(pI830->pVbe); + pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); + pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->pVbe = pI8301->pVbe; + pI830->vbeInfo = pI8301->vbeInfo; + } /* verify that change was successful */ if (pI830->vbeInfo->TotalMemory != (newsize >> 16)){ @@ -1648,8 +1759,11 @@ RestoreBIOSMemSize(ScrnInfoPtr pScrn) DPRINTF(PFX, "RestoreBIOSMemSize\n"); + if (!I830IsPrimary(pScrn)) + return; + if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE)) - return; + return; if (!pI830->overrideBIOSMemSize) return; @@ -1712,6 +1826,8 @@ SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize) } } +static CARD32 val8[256]; + static void I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual) @@ -1786,6 +1902,19 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, } break; default: +#if 1 + /* Dual head 8bpp modes seem to squish the primary's cmap - reload */ + if (I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) && + pScrn->depth == 8) { + for(i = 0; i < numColors; i++) { + index = indices[i]; + r = colors[index].red; + g = colors[index].green; + b = colors[index].blue; + val8[index] = (r << 16) | (g << 8) | b; + } + } +#endif for(i = 0; i < numColors; i++) { index = indices[i]; r = colors[index].red; @@ -1793,6 +1922,16 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, b = colors[index].blue; val = (r << 16) | (g << 8) | b; OUTREG(palreg + index * 4, val); +#if 1 + /* Dual head 8bpp modes seem to squish the primary's cmap - reload */ + if (!I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) && + pScrn->depth == 8) { + if (palreg == PALETTE_A) + OUTREG(PALETTE_B + index * 4, val8[index]); + else + OUTREG(PALETTE_A + index * 4, val8[index]); + } +#endif } break; } @@ -1868,30 +2007,32 @@ PreInitCleanup(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - if (IsPrimary(pScrn)) + if (I830IsPrimary(pScrn)) { + SetPipeAccess(pScrn); + pI830->entityPrivate->pScrn_1 = NULL; - if (IsPrimary(pScrn) && pI830->LpRing) { - xfree(pI830->LpRing); + if (pI830->LpRing) + xfree(pI830->LpRing); pI830->LpRing = NULL; - } - if (IsPrimary(pScrn) && pI830->CursorMem) { - xfree(pI830->CursorMem); + if (pI830->CursorMem) + xfree(pI830->CursorMem); pI830->CursorMem = NULL; - } - if (IsPrimary(pScrn) && pI830->CursorMemARGB) { - xfree(pI830->CursorMemARGB); + if (pI830->CursorMemARGB) + xfree(pI830->CursorMemARGB); pI830->CursorMemARGB = NULL; - } - if (IsPrimary(pScrn) && pI830->OverlayMem) { - xfree(pI830->OverlayMem); + if (pI830->OverlayMem) + xfree(pI830->OverlayMem); pI830->OverlayMem = NULL; - } - if (IsPrimary(pScrn) && pI830->overlayOn) { - xfree(pI830->overlayOn); + if (pI830->overlayOn) + xfree(pI830->overlayOn); pI830->overlayOn = NULL; + if (pI830->used3D) + xfree(pI830->used3D); + pI830->used3D = NULL; + } else { + if (pI830->entityPrivate) + pI830->entityPrivate->pScrn_2 = NULL; } - if (!IsPrimary(pScrn) && pI830->entityPrivate) - pI830->entityPrivate->pScrn_2 = NULL; RestoreBIOSMemSize(pScrn); if (pI830->swfSaved) { OUTREG(SWF0, pI830->saveSWF0); @@ -1902,8 +2043,8 @@ PreInitCleanup(ScrnInfoPtr pScrn) I830BIOSFreeRec(pScrn); } -static Bool -IsPrimary(ScrnInfoPtr pScrn) +Bool +I830IsPrimary(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); @@ -1920,7 +2061,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) { vgaHWPtr hwp; I830Ptr pI830; - MessageType from; + MessageType from = X_PROBED; rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; I830EntPtr pI830Ent = NULL; @@ -1974,6 +2115,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->SaveGeneration = -1; pI830->pEnt = pEnt; + pI830->displayWidth = 640; /* default it */ + if (pI830->pEnt->location.type != BUS_PCI) return FALSE; @@ -1994,6 +2137,30 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (xf86IsPrimInitDone(pScrn->entityList[0])) { + pI830->init = 1; + + if (!pI830Ent->pScrn_1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to setup second head due to primary head failure.\n"); + return FALSE; + } + } else { + xf86SetPrimInitDone(pScrn->entityList[0]); + pI830->init = 0; + } + } + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (!I830IsPrimary(pScrn)) { + pI830Ent->pScrn_2 = pScrn; + } else { + pI830Ent->pScrn_1 = pScrn; + pI830Ent->pScrn_2 = NULL; + } + } + pScrn->racMemFlags = RAC_FB | RAC_COLORMAP; pScrn->monitor = pScrn->confScreen->monitor; pScrn->progClock = TRUE; @@ -2039,9 +2206,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) I830SetPIOAccess(pI830); /* Initialize VBE record */ - if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n"); - return FALSE; + if (I830IsPrimary(pScrn)) { + if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n"); + return FALSE; + } + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->pVbe = pI8301->pVbe; } switch (pI830->PciInfo->chipType) { @@ -2090,6 +2262,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) case PCI_CHIP_I945_G: chipname = "945G"; break; + case PCI_CHIP_I945_GM: + chipname = "945GM"; + break; default: chipname = "unknown chipset"; break; @@ -2097,7 +2272,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Integrated Graphics Chipset: Intel(R) %s\n", chipname); - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + if (I830IsPrimary(pScrn)) { + pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->vbeInfo = pI8301->vbeInfo; + } /* Set the Chipset and ChipRev, allowing config file entries to override. */ if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) { @@ -2127,8 +2307,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->LinearAddr = pI830->pEnt->device->MemBase; from = X_CONFIG; } else { - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { - pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xF0000000; + if (IS_I9XX(pI830)) { + pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xFF000000; from = X_PROBED; } else if (pI830->PciInfo->memBase[1] != 0) { /* XXX Check mask. */ @@ -2149,7 +2329,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MMIOAddr = pI830->pEnt->device->IOBase; from = X_CONFIG; } else { - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + if (IS_I9XX(pI830)) { pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000; from = X_PROBED; } else if (pI830->PciInfo->memBase[1]) { @@ -2194,7 +2374,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */ } } else { - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + if (IS_I9XX(pI830)) { if (pI830->PciInfo->memBase[2] & 0x08000000) pI830->FbMapSize = 0x8000000; /* 128MB aperture */ else @@ -2207,27 +2387,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->FbMapSize = 0x8000000; } - - if (xf86IsEntityShared(pScrn->entityList[0])) { - if (xf86IsPrimInitDone(pScrn->entityList[0])) { - pI830->init = 1; - - if (!pI830Ent->pScrn_1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to setup second head due to primary head failure.\n"); - return FALSE; - } - - } else { - xf86SetPrimInitDone(pScrn->entityList[0]); - pI830->init = 0; - } - } - if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) pI830->availablePipes = 1; else - if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) pI830->availablePipes = 2; else pI830->availablePipes = 1; @@ -2251,7 +2414,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } /* Find the maximum amount of agpgart memory available. */ - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { mem = I830CheckAvailableMemory(pScrn); pI830->StolenOnly = FALSE; } else { @@ -2302,9 +2465,16 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif + pI830->LinearAlloc = 0; + if (xf86GetOptValInteger(pI830->Options, OPTION_LINEARALLOC, + &(pI830->LinearAlloc))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %dKbytes of memory\n", + pI830->LinearAlloc); + } + pI830->fixedPipe = -1; if ((s = xf86GetOptValString(pI830->Options, OPTION_FIXEDPIPE)) && - IsPrimary(pScrn)) { + I830IsPrimary(pScrn)) { if (strstr(s, "A") || strstr(s, "a") || strstr(s, "0")) pI830->fixedPipe = 0; @@ -2317,7 +2487,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->specifiedMonitor = FALSE; if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && - IsPrimary(pScrn)) { + I830IsPrimary(pScrn)) { char *Mon1; char *Mon2; char *sub; @@ -2429,7 +2599,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } - if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) { + if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) { if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout " "defined for use in a DualHead or Clone setup.\n"); @@ -2443,37 +2613,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) PreInitCleanup(pScrn); return FALSE; } - } - - xf86GetOptValBool(pI830->Options, OPTION_SHADOW_FB, &pI830->shadowFB); - if (pI830->shadowFB) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: shadow FB enabled\n"); - } - - if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) { - if(!xf86NameCmp(s, "CW")) { - /* accel is disabled below for shadowFB */ - pI830->shadowFB = TRUE; - pI830->rotate = 1; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Rotating screen clockwise - acceleration disabled\n"); - } else if(!xf86NameCmp(s, "CCW")) { - pI830->shadowFB = TRUE; - pI830->rotate = -1; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" - "counter clockwise - acceleration disabled\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" - "value for Option \"Rotate\"\n", s); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid options are \"CW\" or \"CCW\"\n"); - } - } + } - if (pI830->shadowFB && !pI830->noAccel) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "HW acceleration not supported with \"shadowFB\".\n"); - pI830->noAccel = TRUE; + pI830->rotation = RR_Rotate_0; + if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) { + pI830->InitialRotation = 0; + if(!xf86NameCmp(s, "CW") || !xf86NameCmp(s, "270")) + pI830->InitialRotation = 270; + if(!xf86NameCmp(s, "CCW") || !xf86NameCmp(s, "90")) + pI830->InitialRotation = 90; + if(!xf86NameCmp(s, "180")) + pI830->InitialRotation = 180; } /* @@ -2486,7 +2636,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->checkDevices = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n"); } else - if (pI830->entityPrivate && !IsPrimary(pScrn) && + if (pI830->entityPrivate && !I830IsPrimary(pScrn) && !I830PTR(pI830->entityPrivate->pScrn_1)->checkDevices) { /* If checklid is off, on the primary head, then * turn it off on the secondary*/ @@ -2525,7 +2675,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D; if (xf86IsEntityShared(pScrn->entityList[0])) { - if (IsPrimary(pScrn)) + if (I830IsPrimary(pScrn)) pScrn->videoRam *= 2; else pScrn->videoRam = I830_MAXIMUM_VBIOS_MEM; @@ -2538,6 +2688,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam = pI830->pEnt->device->videoRam; } + /* Make sure it's on a page boundary */ + if (pScrn->videoRam & (GTT_PAGE_SIZE - 1)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "VideoRAM reduced to %d kByte " + "(page aligned - was %d)\n", pScrn->videoRam & ~(GTT_PAGE_SIZE - 1), pScrn->videoRam); + pScrn->videoRam &= ~(GTT_PAGE_SIZE - 1); + } + DPRINTF(PFX, "Available memory: %dk\n" "Requested memory: %dk\n", mem, pScrn->videoRam); @@ -2597,10 +2755,16 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->overrideBIOSMemSize = TRUE; SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); - VBEFreeVBEInfo(pI830->vbeInfo); - vbeFree(pI830->pVbe); - pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + if (I830IsPrimary(pScrn)) { + VBEFreeVBEInfo(pI830->vbeInfo); + vbeFree(pI830->pVbe); + pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); + pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->pVbe = pI8301->pVbe; + pI830->vbeInfo = pI8301->vbeInfo; + } pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64); xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -2698,21 +2862,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version); - /* Great.. - * Intel changed the BIOS version codes and started at 1200. - * We know that bios codes for 830M started around 2400. - * So we test those conditions to make this judgement. Ugh. - */ - if (pI830->availablePipes == 2 && pI830->bios_version < 2000) + if (IS_I9XX(pI830)) pI830->newPipeSwitch = TRUE; - else if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) + else + if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) { /* BIOS build 3062 changed the pipe switching functionality */ pI830->newPipeSwitch = TRUE; - else - pI830->newPipeSwitch = FALSE; - - if (pI830->newPipeSwitch) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n"); + } else + pI830->newPipeSwitch = FALSE; pI830->devicePresence = FALSE; from = X_DEFAULT; @@ -2741,7 +2899,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) /* Save old configuration of detected devices */ pI830->savedDevices = GetDisplayDevices(pScrn); - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { pI830->pipe = pI830->origPipe = GetBIOSPipe(pScrn); /* Override */ @@ -2783,7 +2941,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) "Primary Pipe has been switched from original pipe (%s to %s)\n", pI830->origPipe ? "B" : "A", pI830->pipe ? "B" : "A"); } else { - I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1); + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); pI830->operatingDevices = pI8301->operatingDevices; pI830->pipe = !pI8301->pipe; pI830->MonType1 = pI8301->MonType1; @@ -2815,7 +2973,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to switch to monitor configuration (0x%x)\n", @@ -2832,18 +2990,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) PrintDisplayDeviceInfo(pScrn); if (xf86IsEntityShared(pScrn->entityList[0])) { - if (!IsPrimary(pScrn)) { - pI830Ent->pScrn_2 = pScrn; - + if (!I830IsPrimary(pScrn)) { /* This could be made to work with a little more fiddling */ pI830->directRenderingDisabled = TRUE; xf86DrvMsg(pScrn->scrnIndex, from, "Secondary head is using Pipe %s\n", pI830->pipe ? "B" : "A"); } else { - pI830Ent->pScrn_1 = pScrn; - pI830Ent->pScrn_2 = NULL; - xf86DrvMsg(pScrn->scrnIndex, from, "Primary head is using Pipe %s\n", pI830->pipe ? "B" : "A"); } @@ -2853,14 +3006,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } /* Alloc our pointers for the primary head */ - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { pI830->LpRing = xalloc(sizeof(I830RingBuffer)); pI830->CursorMem = xalloc(sizeof(I830MemRange)); pI830->CursorMemARGB = xalloc(sizeof(I830MemRange)); pI830->OverlayMem = xalloc(sizeof(I830MemRange)); pI830->overlayOn = xalloc(sizeof(Bool)); + pI830->used3D = xalloc(sizeof(int)); if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB || - !pI830->OverlayMem || !pI830->overlayOn) { + !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not allocate primary data structures.\n"); PreInitCleanup(pScrn); @@ -2872,7 +3026,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } /* Check if the HW cursor needs physical address. */ - if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) pI830->CursorNeedsPhysical = TRUE; else pI830->CursorNeedsPhysical = FALSE; @@ -2884,8 +3038,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * XXX If we knew the pre-initialised GTT format for certain, we could * probably figure out the physical address even in the StolenOnly case. */ - if (!IsPrimary(pScrn)) { - I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1); + if (!I830IsPrimary(pScrn)) { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); if (!pI8301->SWCursor) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using HW Cursor because it's enabled on primary head.\n"); @@ -3157,13 +3311,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * for it, and if there's also enough to allow tiling to be enabled. */ #if defined(XF86DRI) - if (IsPrimary(pScrn) && !pI830->directRenderingDisabled) { + if (!I830CheckDRIAvailable(pScrn)) + pI830->directRenderingDisabled = TRUE; + + if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) { int savedDisplayWidth = pScrn->displayWidth; int memNeeded = 0; - /* Good pitches to allow tiling. Don't care about pitches < 256. */ + /* Good pitches to allow tiling. Don't care about pitches < 1024. */ static const int pitches[] = { +/* 128 * 2, 128 * 4, +*/ 128 * 8, 128 * 16, 128 * 32, @@ -3264,8 +3423,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) "Unexpected dry run allocation failure (2).\n"); } } - } + } else #endif + pI830->disableTiling = TRUE; /* no DRI - so disableTiling */ + + pI830->displayWidth = pScrn->displayWidth; SetPipeAccess(pScrn); I830PrintModes(pScrn); @@ -3325,19 +3487,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr); xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr); - if (pI830->shadowFB) { - if (!xf86LoadSubModule(pScrn, "shadowfb")) { - I830BIOSFreeRec(pScrn); - vbeFree(pI830->pVbe); - return FALSE; - } - xf86LoaderReqSymLists(I810shadowFBSymbols, NULL); +#if 0 + if (I830IsPrimary(pScrn)) { + VBEFreeVBEInfo(pI830->vbeInfo); + vbeFree(pI830->pVbe); } - - VBEFreeVBEInfo(pI830->vbeInfo); pI830->vbeInfo = NULL; - vbeFree(pI830->pVbe); pI830->pVbe = NULL; +#endif /* Use the VBE mode restore workaround by default. */ pI830->vbeRestoreWorkaround = TRUE; @@ -3357,15 +3514,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL); } } +#endif - if (!pI830->directRenderingDisabled) { - if (!xf86LoadSubModule(pScrn, "shadow")) { - PreInitCleanup(pScrn); - return FALSE; - } - xf86LoaderReqSymLists(I810shadowSymbols, NULL); + if (!xf86LoadSubModule(pScrn, "shadow")) { + PreInitCleanup(pScrn); + return FALSE; } -#endif + xf86LoaderReqSymLists(I810shadowSymbols, NULL); pI830->preinit = FALSE; @@ -3383,7 +3538,7 @@ CheckInheritedState(ScrnInfoPtr pScrn) int errors = 0, fatal = 0; unsigned long temp, head, tail; - if (!IsPrimary(pScrn)) return TRUE; + if (!I830IsPrimary(pScrn)) return TRUE; /* Check first for page table errors */ temp = INREG(PGE_ERR); @@ -3438,7 +3593,7 @@ ResetState(ScrnInfoPtr pScrn, Bool flush) DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush)); - if (!IsPrimary(pScrn)) return; + if (!I830IsPrimary(pScrn)) return; if (pI830->entityPrivate) pI830->entityPrivate->RingRunning = 0; @@ -3460,9 +3615,9 @@ ResetState(ScrnInfoPtr pScrn, Bool flush) OUTREG(LP_RING + RING_HEAD, 0); OUTREG(LP_RING + RING_TAIL, 0); OUTREG(LP_RING + RING_START, 0); - + if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor) - pI830->CursorInfoRec->HideCursor(pScrn); + pI830->CursorInfoRec->HideCursor(pScrn); } static void @@ -3473,7 +3628,7 @@ SetFenceRegs(ScrnInfoPtr pScrn) DPRINTF(PFX, "SetFenceRegs\n"); - if (!IsPrimary(pScrn)) return; + if (!I830IsPrimary(pScrn)) return; for (i = 0; i < 8; i++) { OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]); @@ -3493,7 +3648,7 @@ SetRingRegs(ScrnInfoPtr pScrn) if (pI830->noAccel) return; - if (!IsPrimary(pScrn)) return; + if (!I830IsPrimary(pScrn)) return; if (pI830->entityPrivate) pI830->entityPrivate->RingRunning = 1; @@ -3556,7 +3711,7 @@ SaveHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "SaveHWState\n"); - if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) + if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) SetBIOSPipe(pScrn, pI830->origPipe); else SetPipeAccess(pScrn); @@ -3631,7 +3786,7 @@ RestoreHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "RestoreHWState\n"); - if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) + if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) SetBIOSPipe(pScrn, pI830->origPipe); else SetPipeAccess(pScrn); @@ -3745,6 +3900,16 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) DPRINTF(PFX, "Setting mode 0x%.8x\n", mode); +#if 0 + /* Clear the framebuffer (could do this with VBIOS call) */ + if (I830IsPrimary(pScrn)) + memset(pI830->FbBase + pI830->FrontBuffer.Start, 0, + pScrn->virtualY * pI830->displayWidth * pI830->cpp); + else + memset(pI830->FbBase + pI830->FrontBuffer2.Start, 0, + pScrn->virtualY * pI830->displayWidth * pI830->cpp); +#endif + if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay && !pI830->preinit && !pI830->closing) { VbeCRTCInfoBlock newblock; @@ -3814,7 +3979,6 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) "Set refresh rate to %dHz on Clone head.\n", pI830->CloneRefresh); } - SetPipeAccess(pScrn); } @@ -3894,11 +4058,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) mode = data->mode | (1 << 15) | (1 << 14); #ifdef XF86DRI - if (pI830->directRenderingEnabled && !pI830->LockHeld) { - DRILock(screenInfo.screens[pScrn->scrnIndex], 0); - pI830->LockHeld = 1; - didLock = TRUE; - } + didLock = I830DRILock(pScrn); #endif if (pI830->Clone) { @@ -3925,13 +4085,13 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) * memory than it's aware of. We check for this later, and set it * explicitly if necessary. */ - if (data->data->XResolution != pScrn->displayWidth) { + if (data->data->XResolution != pI830->displayWidth) { if (pI830->Clone) { SetBIOSPipe(pScrn, !pI830->pipe); - VBESetLogicalScanline(pVbe, pScrn->displayWidth); + VBESetLogicalScanline(pVbe, pI830->displayWidth); } SetPipeAccess(pScrn); - VBESetLogicalScanline(pVbe, pScrn->displayWidth); + VBESetLogicalScanline(pVbe, pI830->displayWidth); } if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) { @@ -4013,22 +4173,20 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp); } - - if (xf86IsEntityShared(pScrn->entityList[0])) { /* Clean this up !! */ - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE; CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); temp = INREG(stridereg); - if (temp / pI8301->cpp != (CARD32)(pI830->entityPrivate->pScrn_1->displayWidth)) { + if (temp / pI8301->cpp != (CARD32)(pI830->displayWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe), - (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth); - OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp); + "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe), + (int)(temp / pI8301->cpp), pI830->displayWidth); + OUTREG(stridereg, pI830->displayWidth * pI8301->cpp); } OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); /* Trigger update */ @@ -4042,11 +4200,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE; temp = INREG(stridereg); - if (temp / pI8302->cpp != (CARD32)(pI830->entityPrivate->pScrn_2->displayWidth)) { + if (temp / pI8302->cpp != (CARD32)(pI8302->displayWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe), - (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth); - OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp); + "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe), + (int)(temp / pI8302->cpp), pI8302->displayWidth); + OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp); } OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16)); /* Trigger update */ @@ -4061,11 +4219,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); temp = INREG(stridereg); - if (temp / pI8301->cpp != (CARD32)(pI830->entityPrivate->pScrn_1->displayWidth)) { + if (temp / pI8301->cpp != (CARD32)(pI8301->displayWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe), - (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth); - OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp); + (int)(temp / pI8301->cpp), pI8301->displayWidth); + OUTREG(stridereg, pI8301->displayWidth * pI8301->cpp); } OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16)); /* Trigger update */ @@ -4077,11 +4235,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; temp = INREG(stridereg); - if (temp / pI8302->cpp != ((CARD32)pI830->entityPrivate->pScrn_2->displayWidth)) { + if (temp / pI8302->cpp != ((CARD32)pI8302->displayWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe), - (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth); - OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp); + (int)(temp / pI8302->cpp), pI8302->displayWidth); + OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp); } OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); /* Trigger update */ @@ -4098,11 +4256,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) continue; temp = INREG(stridereg); - if (temp / pI830->cpp != (CARD32)pScrn->displayWidth) { + if (temp / pI830->cpp != (CARD32)pI830->displayWidth) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i), - (int)(temp / pI830->cpp), pScrn->displayWidth); - OUTREG(stridereg, pScrn->displayWidth * pI830->cpp); + (int)(temp / pI830->cpp), pI830->displayWidth); + OUTREG(stridereg, pI830->displayWidth * pI830->cpp); } OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); /* Trigger update */ @@ -4211,10 +4369,8 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) #endif #ifdef XF86DRI - if (pI830->directRenderingEnabled && didLock) { - DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); - pI830->LockHeld = 0; - } + if (didLock) + I830DRIUnlock(pScrn); #endif pScrn->vtSema = TRUE; @@ -4228,7 +4384,7 @@ InitRegisterRec(ScrnInfoPtr pScrn) I830RegPtr i830Reg = &pI830->ModeReg; int i; - if (!IsPrimary(pScrn)) return; + if (!I830IsPrimary(pScrn)) return; for (i = 0; i < 8; i++) i830Reg->Fence[i] = 0; @@ -4451,6 +4607,103 @@ I830_dump_registers(ScrnInfoPtr pScrn) } #endif +static void +I830PointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + I830Ptr pI830 = I830PTR(pScrn); + int newX = x, newY = y; + + switch (pI830->rotation) { + case RR_Rotate_0: + break; + case RR_Rotate_90: + newX = y; + newY = pScrn->pScreen->width - x - 1; + break; + case RR_Rotate_180: + newX = pScrn->pScreen->width - x - 1; + newY = pScrn->pScreen->height - y - 1; + break; + case RR_Rotate_270: + newX = pScrn->pScreen->height - y - 1; + newY = x; + break; + } + + (*pI830->PointerMoved)(index, newX, newY); +} + +static Bool +I830CreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + + pScreen->CreateScreenResources = pI830->CreateScreenResources; + if (!(*pScreen->CreateScreenResources)(pScreen)) + return FALSE; + + if (pI830->rotation != RR_Rotate_0) { + RRScreenSize p; + Rotation requestedRotation = pI830->rotation; + + pI830->rotation = RR_Rotate_0; + + /* Just setup enough for an initial rotate */ + p.width = pScreen->width; + p.height = pScreen->height; + p.mmWidth = pScreen->mmWidth; + p.mmHeight = pScreen->mmHeight; + + pI830->starting = TRUE; /* abuse this for dual head & rotation */ + I830RandRSetConfig (pScreen, requestedRotation, 0, &p); + pI830->starting = FALSE; + } + + return TRUE; +} + +static Bool +I830InitFBManager( + ScreenPtr pScreen, + BoxPtr FullBox +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RegionRec ScreenRegion; + RegionRec FullRegion; + BoxRec ScreenBox; + Bool ret; + + ScreenBox.x1 = 0; + ScreenBox.y1 = 0; + ScreenBox.x2 = pScrn->displayWidth; + if (pScrn->virtualX > pScrn->virtualY) + ScreenBox.y2 = pScrn->virtualX; + else + ScreenBox.y2 = pScrn->virtualY; + + if((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) || + (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) { + return FALSE; + } + + if (FullBox->y2 < FullBox->y1) return FALSE; + if (FullBox->x2 < FullBox->x2) return FALSE; + + REGION_INIT(pScreen, &ScreenRegion, &ScreenBox, 1); + REGION_INIT(pScreen, &FullRegion, FullBox, 1); + + REGION_SUBTRACT(pScreen, &FullRegion, &FullRegion, &ScreenRegion); + + ret = xf86InitFBManagerRegion(pScreen, &FullRegion); + + REGION_UNINIT(pScreen, &ScreenRegion); + REGION_UNINIT(pScreen, &FullRegion); + + return ret; +} + static Bool I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { @@ -4458,10 +4711,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) vgaHWPtr hwp; I830Ptr pI830; VisualPtr visual; - I830EntPtr pI830Ent = NULL; I830Ptr pI8301 = NULL; - int width, height, displayWidth; - unsigned char *fbbase; #ifdef XF86DRI Bool driDisabled; #endif @@ -4470,12 +4720,42 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830 = I830PTR(pScrn); hwp = VGAHWPTR(pScrn); - if (xf86IsEntityShared(pScrn->entityList[0])) { - pI830Ent = pI830->entityPrivate; - pI8301 = I830PTR(pI830Ent->pScrn_1); + pScrn->displayWidth = pI830->displayWidth; + switch (pI830->InitialRotation) { + case 0: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 0 degrees\n"); + pI830->rotation = RR_Rotate_0; + break; + case 90: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 90 degrees\n"); + pI830->rotation = RR_Rotate_90; + break; + case 180: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 180 degrees\n"); + pI830->rotation = RR_Rotate_180; + break; + case 270: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 270 degrees\n"); + pI830->rotation = RR_Rotate_270; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad rotation setting - defaulting to 0 degrees\n"); + pI830->rotation = RR_Rotate_0; + break; + } + + if (I830IsPrimary(pScrn)) { + /* Rotated Buffer */ + memset(&(pI830->RotatedMem), 0, sizeof(pI830->RotatedMem)); + pI830->RotatedMem.Key = -1; + /* Rotated2 Buffer */ + memset(&(pI830->RotatedMem2), 0, sizeof(pI830->RotatedMem2)); + pI830->RotatedMem2.Key = -1; + } + if (xf86IsEntityShared(pScrn->entityList[0])) { /* PreInit failed on the second head, so make sure we turn it off */ - if (IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) { + if (I830IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) { if (pI830->pipe == 0) { pI830->operatingDevices &= 0xFF; } else { @@ -4487,7 +4767,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->starting = TRUE; /* Alloc our pointers for the primary head */ - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { if (!pI830->LpRing) pI830->LpRing = xalloc(sizeof(I830RingBuffer)); if (!pI830->CursorMem) @@ -4498,8 +4778,10 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->OverlayMem = xalloc(sizeof(I830MemRange)); if (!pI830->overlayOn) pI830->overlayOn = xalloc(sizeof(Bool)); + if (!pI830->used3D) + pI830->used3D = xalloc(sizeof(int)); if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB || - !pI830->OverlayMem || !pI830->overlayOn) { + !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not allocate primary data structures.\n"); return FALSE; @@ -4509,31 +4791,42 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->entityPrivate->XvInUse = -1; } - if (xf86IsEntityShared(pScrn->entityList[0])) { - /* Make our second head point to the first heads structures */ - if (!IsPrimary(pScrn)) { - pI830->LpRing = pI8301->LpRing; - pI830->CursorMem = pI8301->CursorMem; - pI830->CursorMemARGB = pI8301->CursorMemARGB; - pI830->OverlayMem = pI8301->OverlayMem; - pI830->overlayOn = pI8301->overlayOn; - } + /* Make our second head point to the first heads structures */ + if (!I830IsPrimary(pScrn)) { + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->LpRing = pI8301->LpRing; + pI830->CursorMem = pI8301->CursorMem; + pI830->CursorMemARGB = pI8301->CursorMemARGB; + pI830->OverlayMem = pI8301->OverlayMem; + pI830->overlayOn = pI8301->overlayOn; + pI830->used3D = pI8301->used3D; } /* * If we're changing the BIOS's view of the video memory size, do that * first, then re-initialise the VBE information. */ - if (pI830->pVbe) - vbeFree(pI830->pVbe); - pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) - SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); + SetPipeAccess(pScrn); + if (I830IsPrimary(pScrn)) { + if (pI830->pVbe) + vbeFree(pI830->pVbe); + pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); + } else { + pI830->pVbe = pI8301->pVbe; + } + if (I830IsPrimary(pScrn)) { + if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) + SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); + } if (!pI830->pVbe) return FALSE; - if (pI830->vbeInfo) - VBEFreeVBEInfo(pI830->vbeInfo); - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + if (I830IsPrimary(pScrn)) { + if (pI830->vbeInfo) + VBEFreeVBEInfo(pI830->vbeInfo); + pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + } else { + pI830->vbeInfo = pI8301->vbeInfo; + } miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, @@ -4546,7 +4839,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef I830_XV pI830->XvEnabled = !pI830->XvDisabled; if (pI830->XvEnabled) { - if (!IsPrimary(pScrn)) { + if (!I830IsPrimary(pScrn)) { if (!pI8301->XvEnabled || pI830->noAccel) { pI830->XvEnabled = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n"); @@ -4562,7 +4855,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->XvEnabled = FALSE; #endif - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { I830ResetAllocations(pScrn, 0); if (!I830Allocate2DMemory(pScrn, ALLOC_INITIAL)) @@ -4618,7 +4911,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) */ if (pI830->directRenderingEnabled) { - if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && IsPrimary(pScrn))) { + if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it " "needs HW cursor, 2D accel and AGPGART.\n"); pI830->directRenderingEnabled = FALSE; @@ -4646,7 +4939,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * After the 3D allocations have been done, see if there's any free space * that can be added to the framebuffer allocation. */ - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { I830Allocate2DMemory(pScrn, 0); DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n"); @@ -4671,10 +4964,9 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScrn->memPhysBase = (unsigned long)pI830->FbBase; - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { pScrn->fbOffset = pI830->FrontBuffer.Start; } else { - I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1); pScrn->fbOffset = pI8301->FrontBuffer2.Start; } @@ -4696,26 +4988,10 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) return FALSE; DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n"); - if (pI830->rotate) { - height = pScrn->virtualX; - width = pScrn->virtualY; - } else { - width = pScrn->virtualX; - height = pScrn->virtualY; - } - if (pI830->shadowFB) { - pI830->shadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); - pI830->shadowPtr = xalloc(pI830->shadowPitch * height); - displayWidth = pI830->shadowPitch / (pScrn->bitsPerPixel >> 3); - fbbase = pI830->shadowPtr; - } else { - pI830->shadowPtr = NULL; - fbbase = pI830->FbBase; - displayWidth = pScrn->displayWidth; - } - if (!fbScreenInit(pScreen, fbbase + pScrn->fbOffset, width, height, + if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, + pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, - displayWidth, pScrn->bitsPerPixel)) + pScrn->displayWidth, pScrn->bitsPerPixel)) return FALSE; if (pScrn->bitsPerPixel > 8) { @@ -4737,22 +5013,24 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); - if (!pI830->shadowFB) - I830DGAInit(pScreen); + I830DGAInit(pScreen); DPRINTF(PFX, - "assert( if(!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) )\n"); - if (IsPrimary(pScrn)) { - if (!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) { + "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n"); + if (I830IsPrimary(pScrn)) { + if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n"); - return FALSE; } + + if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, pI830->LinearMem.Offset / pI830->cpp, pI830->LinearMem.Size / pI830->cpp)) + xf86DrvMsg(scrnIndex, X_INFO, + "Using %ld bytes of offscreen memory for linear (offset=0x%lx)\n", pI830->LinearMem.Size, pI830->LinearMem.Offset); + } else { - if (!xf86InitFBManager(pScreen, &(pI8301->FbMemBox2))) { + if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n"); - return FALSE; } } @@ -4776,31 +5054,6 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } else xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n"); - if (pI830->shadowFB) { - RefreshAreaFuncPtr refreshArea = I830RefreshArea; - if (pI830->rotate) { - if (!pI830->PointerMoved) { - pI830->PointerMoved = pScrn->PointerMoved; - pScrn->PointerMoved = I830PointerMoved; - } - switch (pScrn->bitsPerPixel) { - case 8: - refreshArea = I830RefreshArea8; - break; - case 16: - refreshArea = I830RefreshArea16; - break; - case 24: - refreshArea = I830RefreshArea24; - break; - case 32: - refreshArea = I830RefreshArea32; - break; - } - } - ShadowFBInit(pScreen, refreshArea); - } - DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n"); if (!miCreateDefColormap(pScreen)) return FALSE; @@ -4845,7 +5098,19 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScreen->SaveScreen = I830BIOSSaveScreen; pI830->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = I830BIOSCloseScreen; - + + /* Rotation */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR enabled, ignore the following RandR disabled message.\n"); + xf86DisableRandR(); /* Disable built-in RandR extension */ + + shadowSetup(pScreen); + /* support all rotations */ + I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); + pI830->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = I830PointerMoved; + pI830->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = I830CreateScreenResources; + if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); @@ -4856,6 +5121,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->starting = FALSE; pI830->closing = FALSE; pI830->suspended = FALSE; + return TRUE; } @@ -4865,6 +5131,7 @@ I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) ScrnInfoPtr pScrn; I830Ptr pI830; vbeInfoPtr pVbe; + unsigned long Start; pScrn = xf86Screens[scrnIndex]; pI830 = I830PTR(pScrn); @@ -4874,46 +5141,35 @@ I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) x, pI830->xoffset, y, pI830->yoffset); /* Sync the engine before adjust frame */ - if (!pI830->noAccel && pI830->AccelInfoRec) + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } - /* The i830M just happens to have some problems programming offsets via - * this VESA BIOS call. Especially in dual head configurations which - * have high resolutions which cause the DSP{A,B}BASE registers to be - * programmed incorrectly. Thus, it warrants bypassing the BIOS for i830M - * and hitting the DSP{A,B}BASE registers directly. - * - * We could probably do this for other platforms too, but we don't - * know what else the Video BIOS may do when calling it. It seems safe - * though for i830M during testing...... - * - * Also note, calling the Video BIOS version first and then fixing the - * registers fail on i830M and eventually cause a lockup of the hardware - * in my testing. + if (I830IsPrimary(pScrn)) + Start = pI830->FrontBuffer.Start; + else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + Start = pI8301->FrontBuffer2.Start; + } + + /* Sigh... + * It seems that there are quite a few Video BIOS' that get this wrong. + * So, we'll bypass the VBE call and hit the hardware directly. */ if (pI830->Clone) { - if (!IS_I830(pI830)) { - SetBIOSPipe(pScrn, !pI830->pipe); - VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE); + if (!pI830->pipe == 0) { + OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } else { - if (!pI830->pipe == 0) { - OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } else { - OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } + OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } } - if (!IS_I830(pI830)) { - SetPipeAccess(pScrn); - VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE); + if (pI830->pipe == 0) { + OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } else { - if (pI830->pipe == 0) { - OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } else { - OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } + OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } } @@ -4978,7 +5234,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags) pI830->CloneVDisplay = 0; } - if (!IsPrimary(pScrn)) { + if (!I830IsPrimary(pScrn)) { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); if (!pI8301->GttBound) { return; @@ -4987,9 +5243,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags) #ifdef XF86DRI if (pI830->directRenderingOpen) { - DPRINTF(PFX, "calling dri lock\n"); - DRILock(screenInfo.screens[scrnIndex], 0); - pI830->LockHeld = 1; + I830DRILock(pScrn); drmCtlUninstHandler(pI830->drmSubFD); } @@ -5005,7 +5259,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags) ResetState(pScrn, TRUE); - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { if (!SetDisplayDevices(pScrn, pI830->savedDevices)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch back to original display devices (0x%x)\n", @@ -5018,13 +5272,13 @@ I830BIOSLeaveVT(int scrnIndex, int flags) RestoreHWState(pScrn); RestoreBIOSMemSize(pScrn); - if (IsPrimary(pScrn)) - I830UnbindGARTMemory(pScrn); + if (I830IsPrimary(pScrn)) + I830UnbindAGPMemory(pScrn); if (pI830->AccelInfoRec) pI830->AccelInfoRec->NeedToSync = FALSE; /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */ - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { if (!SetDisplayDevices(pScrn, pI830->savedDevices)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch back to original display devices (0x%x) (2)\n", @@ -5230,7 +5484,13 @@ I830BIOSEnterVT(int scrnIndex, int flags) pI830->leaving = FALSE; - if (IsPrimary(pScrn)) { +#if 1 + /* Clear the framebuffer */ + memset(pI830->FbBase + pScrn->fbOffset, 0, + pScrn->virtualY * pScrn->displayWidth * pI830->cpp); +#endif + + if (I830IsPrimary(pScrn)) { /* * This is needed for restoring from ACPI modes (especially S3) * so that we warmboot the Video BIOS. Some platforms have problems, @@ -5259,7 +5519,7 @@ I830BIOSEnterVT(int scrnIndex, int flags) "Re-POSTing via int10 failed, trying to continue.\n"); } } - + /* Finally, re-setup the display devices */ if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -5269,25 +5529,21 @@ I830BIOSEnterVT(int scrnIndex, int flags) } /* Setup for device monitoring status */ - pI830->monitorSwitch = INREG(SWF0) & 0x0000FFFF; + pI830->monitorSwitch = pI830->toggleDevices = INREG(SWF0) & 0x0000FFFF; - if (IsPrimary(pScrn)) - if (!I830BindGARTMemory(pScrn)) + if (I830IsPrimary(pScrn)) + if (!I830BindAGPMemory(pScrn)) return FALSE; CheckInheritedState(pScrn); - if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) - SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); + if (I830IsPrimary(pScrn)) { + if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) + SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); + } ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); -#if 1 - /* Clear the framebuffer */ - memset(pI830->FbBase + pScrn->fbOffset, 0, - pScrn->virtualY * pScrn->displayWidth * pI830->cpp); -#endif - /* Detect monitor change and switch to suitable mode */ if (!pI830->starting) I830DetectMonitorChange(pScrn); @@ -5319,7 +5575,7 @@ I830BIOSEnterVT(int scrnIndex, int flags) DO_RING_IDLE(); DPRINTF(PFX, "calling dri unlock\n"); - DRIUnlock(screenInfo.screens[scrnIndex]); + I830DRIUnlock(pScrn); } pI830->LockHeld = 0; } @@ -5328,6 +5584,11 @@ I830BIOSEnterVT(int scrnIndex, int flags) if (pI830->checkDevices) pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn); + pI830->currentMode = pScrn->currentMode; + + /* Force invarient state when rotated to be emitted */ + *pI830->used3D = 1<<31; + return TRUE; } @@ -5337,35 +5598,64 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); - int ret = TRUE; + Bool ret = TRUE; + PixmapPtr pspix = (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen); DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode); - /* Sync the engine before mode switch */ - if (!pI830->noAccel && pI830->AccelInfoRec) - (*pI830->AccelInfoRec->Sync)(pScrn); - -#ifndef BINDUNBIND -#define BINDUNBIND 0 -#endif -#if BINDUNBIND - if (IsPrimary(pScrn)) - I830UnbindGARTMemory(pScrn); -#endif #ifdef I830_XV /* Give the video overlay code a chance to see the new mode. */ I830VideoSwitchModeBefore(pScrn, mode); #endif - if (!I830VESASetMode(pScrn, mode)) - ret = FALSE; + + /* Sync the engine before mode switch */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + + /* Check if our currentmode is about to change. We do this so if we + * are rotating, we don't need to call the mode setup again. + */ + if (pI830->currentMode != mode) { + if (!I830VESASetMode(pScrn, mode)) + ret = FALSE; + } + + /* Kludge to detect Rotate or Vidmode switch. Not very elegant, but + * workable given the implementation currently. We only need to call + * the rotation function when we know that the framebuffer has been + * disabled by the EnableDisableFBAccess() function. + * + * The extra WindowTable check detects a rotation at startup. + */ + if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) && + !pI830->DGAactive ) { + if (!I830Rotate(pScrn, mode)) + ret = FALSE; + } + + /* Either the original setmode or rotation failed, so restore the previous + * video mode here, as we'll have already re-instated the original rotation. + */ + if (!ret) { + if (!I830VESASetMode(pScrn, pI830->currentMode)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Failed to restore previous mode (SwitchMode)\n"); + } + #ifdef I830_XV - /* Give the video overlay code a chance to see the new mode. */ - I830VideoSwitchModeAfter(pScrn, mode); + /* Give the video overlay code a chance to see the new mode. */ + I830VideoSwitchModeAfter(pScrn, pI830->currentMode); #endif -#if BINDUNBIND - if (IsPrimary(pScrn)) - I830BindGARTMemory(pScrn); + } else { + pI830->currentMode = mode; + +#ifdef I830_XV + /* Give the video overlay code a chance to see the new mode. */ + I830VideoSwitchModeAfter(pScrn, mode); #endif + } return ret; } @@ -5515,7 +5805,7 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) pI830->CursorInfoRec = 0; } - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { xf86GARTCloseScreen(scrnIndex); xfree(pI830->LpRing); @@ -5528,8 +5818,11 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) pI830->OverlayMem = NULL; xfree(pI830->overlayOn); pI830->overlayOn = NULL; + xfree(pI830->used3D); + pI830->used3D = NULL; } + pScrn->PointerMoved = pI830->PointerMoved; pScrn->vtSema = FALSE; pI830->closing = FALSE; pScreen->CloseScreen = pI830->CloseScreen; @@ -5568,7 +5861,7 @@ I830PMEvent(int scrnIndex, pmEvent event, Bool undo) I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event, BOOLTOSTRING(undo)); - + switch(event) { case XF86_APM_SYS_SUSPEND: case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/ @@ -5603,6 +5896,34 @@ I830PMEvent(int scrnIndex, pmEvent event, Bool undo) SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); } break; + /* This is currently used for ACPI */ + case XF86_APM_CAPABILITY_CHANGED: +#if 0 + /* If we had status checking turned on, turn it off now */ + if (pI830->checkDevices) { + if (pI830->devicesTimer) + TimerCancel(pI830->devicesTimer); + pI830->devicesTimer = NULL; + pI830->checkDevices = FALSE; + } +#endif + if (!I830IsPrimary(pScrn)) + return TRUE; + + ErrorF("I830PMEvent: Capability change\n"); + + /* ACPI Toggle */ + pI830->toggleDevices = GetNextDisplayDeviceList(pScrn, 1); + if (xf86IsEntityShared(pScrn->entityList[0])) { + I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); + pI8302->toggleDevices = pI830->toggleDevices; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle to 0x%x\n",pI830->toggleDevices); + + I830CheckDevicesTimer(NULL, 0, pScrn); + SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); + break; default: ErrorF("I830PMEvent: received APM event %d\n", event); } @@ -5634,28 +5955,40 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) CARD32 adjust; CARD32 temp = INREG(SWF0) & 0x0000FFFF; int fixup = 0; + I830Ptr pI8301; + I830Ptr pI8302 = NULL; - /* this avoids a BIOS call if possible */ - if (pI830->monitorSwitch != temp) { - I830Ptr pI8301; - I830Ptr pI8302 = NULL; - unsigned int toggle = GetToggleList(pScrn, 1); + if (I830IsPrimary(pScrn)) + pI8301 = pI830; + else + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - GetToggleList(pScrn, 2); - GetToggleList(pScrn, 3); - GetToggleList(pScrn, 4); - - if (IsPrimary(pScrn)) - pI8301 = pI830; - else - pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + if (xf86IsEntityShared(pScrn->entityList[0])) + pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); - if (xf86IsEntityShared(pScrn->entityList[0])) - pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); + /* this avoids several BIOS calls if possible */ + if (pI830->monitorSwitch != temp || pI830->monitorSwitch != pI830->toggleDevices) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Hotkey switch to 0x%lx.\n", temp); + + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + if (xf86IsEntityShared(pScrn->entityList[0])) + pI8302->AccelInfoRec->NeedToSync = FALSE; + } + GetAttachableDisplayDeviceList(pScrn); + + pI8301->lastDevice0 = pI8301->lastDevice1; pI8301->lastDevice1 = pI8301->lastDevice2; pI8301->lastDevice2 = pI8301->monitorSwitch; + if (temp != pI8301->lastDevice1 && + temp != pI8301->lastDevice2) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected three device configs.\n"); + } else if (CountBits(temp & 0xff) > 1) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected cloned pipe mode (A).\n"); @@ -5684,15 +6017,15 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) } if (cloned && - ((CountBits(pI830->lastDevice1 & 0xff) > 1) || - ((CountBits((pI830->lastDevice1 & 0xff00) >> 8) > 1))) ) { + ((CountBits(pI8301->lastDevice1 & 0xff) > 1) || + ((CountBits((pI8301->lastDevice1 & 0xff00) >> 8) > 1))) ) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected duplicate (1).\n"); cloned = 0; } else if (cloned && - ((CountBits(pI830->lastDevice2 & 0xff) > 1) || - ((CountBits((pI830->lastDevice2 & 0xff00) >> 8) > 1))) ) { + ((CountBits(pI8301->lastDevice2 & 0xff) > 1) || + ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected duplicate (2).\n"); cloned = 0; @@ -5710,9 +6043,23 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) * * Cloned pipe mode should only be done when running single head. */ - if (xf86IsEntityShared(pScrn->entityList[0])) + if (xf86IsEntityShared(pScrn->entityList[0])) { cloned = 0; + /* Some BIOS' don't realize we may be in true dual head mode. + * And only display the primary output on both when switching. + * We detect this here and cycle back to both pipes. + */ + if ((pI830->lastDevice0 == temp) && + ((CountBits(pI8301->lastDevice2 & 0xff) > 1) || + ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected cloned pipe mode when dual head on previous switch. (0x%x -> 0x%x)\n", (int)temp, pI8301->MonType2 << 8 | pI8301->MonType1); + temp = pI8301->MonType2 << 8 | pI8301->MonType1; + } + + } + if (cloned) { if (pI830->Clone) temp = pI8301->MonType2 << 8 | pI8301->MonType1; @@ -5723,8 +6070,8 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) } /* Jump to our next mode if we detect we've been here before */ - if (temp == pI830->lastDevice1 || temp == pI830->lastDevice2) { - temp = toggle; + if (temp == pI8301->lastDevice1 || temp == pI8301->lastDevice2) { + temp = GetToggleList(pScrn, 1); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected duplicate devices. Toggling (0x%lx)\n", temp); } @@ -5736,6 +6083,24 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) /* So that if we close on the wrong config, we restore correctly */ pI830->specifiedMonitor = TRUE; + if (!xf86IsEntityShared(pScrn->entityList[0])) { + if ((temp & 0xFF00) && (temp & 0x00FF)) { + pI830->Clone = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n"); + } else { + pI830->Clone = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clearing Clone mode\n"); + } + } + + { + /* Turn Cursor off before switching */ + Bool on = pI830->cursorOn; + if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor) + pI830->CursorInfoRec->HideCursor(pScrn); + pI830->cursorOn = on; + } + /* double check the display devices are what's configured and try * not to do it twice because of dual heads with the code above */ if (!SetDisplayDevices(pScrn, temp)) { @@ -5748,20 +6113,37 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) if (!SetDisplayDevices(pScrn, temp)) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch " "to configured display devices (0x%lx).\n", temp); - else + else { pI830->Clone = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n"); + } } } + pI8301->monitorSwitch = temp; pI8301->operatingDevices = temp; + pI8301->toggleDevices = temp; + if (xf86IsEntityShared(pScrn->entityList[0])) { - pI8302->operatingDevices = temp; - pI8302->monitorSwitch = temp; + pI8302->operatingDevices = pI8301->operatingDevices; + pI8302->monitorSwitch = pI8301->monitorSwitch; + pI8302->toggleDevices = pI8301->toggleDevices; } fixup = 1; + +#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "ACPI _DGS queried devices is 0x%x, but probed is 0x%x monitorSwitch=0x%x\n", + pI830->toggleDevices, INREG(SWF0), pI830->monitorSwitch); +#endif } else { - int offset = pScrn->fbOffset + ((pScrn->frameY0 * pScrn->displayWidth + pScrn->frameX0) * pI830->cpp); + int offset = -1; + if (I830IsPrimary(pScrn)) + offset = pI8301->FrontBuffer.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp); + else { + offset = pI8301->FrontBuffer2.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp); + } if (pI830->pipe == 0) adjust = INREG(DSPABASE); @@ -5780,6 +6162,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) ScreenPtr pCursorScreen; int x = 0, y = 0; + pCursorScreen = miPointerCurrentScreen(); if (pScrn->pScreen == pCursorScreen) miPointerPosition(&x, &y); @@ -5794,13 +6177,15 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) "Primary pipe is now %s.\n", pI830->pipe ? "B" : "A"); } + pI830->currentMode = NULL; I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0); I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); + if (xf86IsEntityShared(pScrn->entityList[0])) { ScrnInfoPtr pScrn2; I830Ptr pI8302; - if (IsPrimary(pScrn)) { + if (I830IsPrimary(pScrn)) { pScrn2 = pI830->entityPrivate->pScrn_2; pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); } else { @@ -5808,8 +6193,16 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) pI8302 = I830PTR(pI830->entityPrivate->pScrn_1); } + if (pScrn2->pScreen == pCursorScreen) + miPointerPosition(&x, &y); + + pI8302->currentMode = NULL; I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0); I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0); + + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); + if (pScrn2->pScreen == pCursorScreen) { int sigstate = xf86BlockSIGIO (); miPointerWarpCursor(pScrn2->pScreen,x,y); @@ -5818,12 +6211,16 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) xf86UnblockSIGIO (sigstate); if (pI8302->CursorInfoRec && !pI8302->SWCursor && pI8302->cursorOn) { pI8302->CursorInfoRec->HideCursor(pScrn); + xf86SetCursor(pScrn2->pScreen, pI830->pCurs, x, y); pI8302->CursorInfoRec->ShowCursor(pScrn); pI8302->cursorOn = TRUE; } } } + (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, FALSE); + (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, TRUE); + if (pScrn->pScreen == pCursorScreen) { int sigstate = xf86BlockSIGIO (); miPointerWarpCursor(pScrn->pScreen,x,y); @@ -5832,12 +6229,14 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) xf86UnblockSIGIO (sigstate); if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { pI830->CursorInfoRec->HideCursor(pScrn); + xf86SetCursor(pScrn->pScreen, pI830->pCurs, x, y); pI830->CursorInfoRec->ShowCursor(pScrn); pI830->cursorOn = TRUE; } } } } + return 1000; } diff --git a/src/i830_memory.c b/src/i830_memory.c index 27cf0178..84de2c3e 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -61,6 +61,27 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i810_reg.h" +static int nextTile = 0; +static unsigned int tileGeneration = -1; + +#ifndef ALLOCATE_ALL_BIOSMEM +#define ALLOCATE_ALL_BIOSMEM 1 +#endif + +static unsigned long +GetBestTileAlignment(unsigned long size) +{ + unsigned long i; + + for (i = KB(512); i < size; i <<= 1) + ; + + if (i > MB(64)) + i = MB(64); + + return i; +} + /* * Allocate memory from the given pool. Grow the pool if needed and if * possible. @@ -212,6 +233,59 @@ AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, long size, return size; } +void +I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (!range || range->Size == 0) + return; + + if (range->Key != -1) + xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key); + + if (range->Pool) { + /* + * This code essentially resets what I830DoPoolAllocation() did. + * And if things are freed in the wrong order this can break wildly! + * USE CAUTION when changing anything here... + */ + I830MemPool *Pool = range->Pool; + if (pI830->overrideBIOSMemSize && + pI830->BIOSMemorySize > pI830->StolenMemory.Size) + Pool->Total.End = pI830->BIOSMemorySize; + else + Pool->Total.End = pI830->StolenMemory.End; + + if (pI830->StolenOnly) + Pool->Free.End += range->Size; + else + Pool->Free.End = Pool->Total.End; + + if (Pool->Free.End < Pool->Free.Start) { + Pool->Free.End = Pool->Free.Start; + } + + Pool->Free.Size = Pool->Free.End - Pool->Free.Start; + Pool->Total.Size = Pool->Total.End - Pool->Total.Start; + + if (!pI830->StolenOnly) { + pI830->FreeMemory -= Pool->Free.Size; + pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size); + pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size); + } + } else { + if (range->Alignment == GTT_PAGE_SIZE) + pI830->MemoryAperture.End = range->End; + else + pI830->MemoryAperture.End = range->End - range->Size + range->Alignment; + pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start; + } + + if (!pI830->StolenOnly) + pI830->FreeMemory += range->Size; + pI830->allocatedMemory -= range->Size; +} unsigned long I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool, @@ -345,25 +419,30 @@ AllocateOverlay(ScrnInfoPtr pScrn, int flags) alloced / 1024, pI830->OverlayMem->Start, pI830->OverlayMem->Physical); } - return TRUE; -} -#endif -static unsigned long -GetFreeSpace(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned long extra = 0; + /* Clear linearmem info */ + if (pI830->LinearAlloc) { + memset(&(pI830->LinearMem), 0, sizeof(I830MemRange)); + pI830->LinearMem.Key = -1; - /* First check for free space in StolenPool. */ - if (pI830->StolenPool.Free.Size > 0) - extra = pI830->StolenPool.Free.Size; - /* Next check for unallocated space. */ - if (pI830->FreeMemory > 0) - extra += pI830->FreeMemory; + size = KB(pI830->LinearAlloc); + alloced = I830AllocVidMem(pScrn, &(pI830->LinearMem), &(pI830->StolenPool), + size, GTT_PAGE_SIZE, + FROM_ANYWHERE | ALLOCATE_AT_TOP); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate linear buffer space\n"); + } + } else + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for the linear buffer at 0x%lx\n", s, + alloced / 1024, pI830->LinearMem.Start); + } - return extra; + return TRUE; } +#endif static Bool IsTileable(int pitch) @@ -386,6 +465,150 @@ IsTileable(int pitch) } } +Bool +I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long size, alloced; + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + int align; + Bool tileable; + int lines; + int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX; + + /* Rotated Buffer */ + memset(&(pI830->RotatedMem), 0, sizeof(I830MemRange)); + pI830->RotatedMem.Key = -1; + tileable = !(flags & ALLOC_NO_TILING) && + IsTileable(pScrn->displayWidth * pI830->cpp); + if (tileable) { + /* Make the height a multiple of the tile height (16) */ + lines = (height + 15) / 16 * 16; + } else { + lines = height; + } + + size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp); + /* + * Try to allocate on the best tile-friendly boundaries. + */ + alloced = 0; + if (tileable) { + align = GetBestTileAlignment(size); + for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { + alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem), + &(pI830->StolenPool), size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | + ALIGN_BOTH_ENDS); + if (alloced >= size) + break; + } + } + if (alloced < size) { + /* Give up on trying to tile */ + tileable = FALSE; + size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp); + align = GTT_PAGE_SIZE; + alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem), + &(pI830->StolenPool), size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); + } + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate rotated buffer space.\n"); + } + return FALSE; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for the rotated buffer at 0x%lx.\n", s, + alloced / 1024, pI830->RotatedMem.Start); + return TRUE; +} + +Bool +I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long size, alloced; + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + int align; + Bool tileable; + int lines; + I830EntPtr pI830Ent = pI830->entityPrivate; + I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); + int height = (pI8302->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pI830Ent->pScrn_2->virtualY : pI830Ent->pScrn_2->virtualX; + + /* Rotated Buffer */ + memset(&(pI830->RotatedMem2), 0, sizeof(I830MemRange)); + pI830->RotatedMem2.Key = -1; + tileable = !(flags & ALLOC_NO_TILING) && + IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); + if (tileable) { + /* Make the height a multiple of the tile height (16) */ + lines = (height + 15) / 16 * 16; + } else { + lines = height; + } + + size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * lines * pI8302->cpp); + /* + * Try to allocate on the best tile-friendly boundaries. + */ + alloced = 0; + if (tileable) { + align = GetBestTileAlignment(size); + for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { + alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2), + &(pI830->StolenPool), size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | + ALIGN_BOTH_ENDS); + if (alloced >= size) + break; + } + } + if (alloced < size) { + /* Give up on trying to tile */ + tileable = FALSE; + size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * height * pI8302->cpp); + align = GTT_PAGE_SIZE; + alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2), + &(pI830->StolenPool), size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); + } + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate rotated2 buffer space.\n"); + } + return FALSE; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for the rotated2 buffer at 0x%lx.\n", s, + alloced / 1024, pI830->RotatedMem2.Start); + return TRUE; +} + +static unsigned long +GetFreeSpace(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long extra = 0; + + /* First check for free space in StolenPool. */ + if (pI830->StolenPool.Free.Size > 0) + extra = pI830->StolenPool.Free.Size; + /* Next check for unallocated space. */ + if (pI830->FreeMemory > 0) + extra += pI830->FreeMemory; + + return extra; +} + /* * Allocate memory for 2D operation. This includes the (front) framebuffer, * ring buffer, scratch memory, HW cursor. @@ -452,7 +675,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->FbMemBox2.x1 = 0; pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; pI830->FbMemBox2.y1 = 0; - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; + if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) + pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX; + else + pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; /* * Calculate how much framebuffer memory to allocate. For the @@ -511,8 +737,12 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) alignflags = 0; } - size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); + if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) + size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines); + else + size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); size = ROUND_TO_PAGE(size); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sSecondary framebuffer allocation size: %ld kByte\n", s, size / 1024); @@ -537,7 +767,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->FbMemBox.x1 = 0; pI830->FbMemBox.x2 = pScrn->displayWidth; pI830->FbMemBox.y1 = 0; - pI830->FbMemBox.y2 = pScrn->virtualY; + if (pScrn->virtualX > pScrn->virtualY) + pI830->FbMemBox.y2 = pScrn->virtualX; + else + pI830->FbMemBox.y2 = pScrn->virtualY; /* * Calculate how much framebuffer memory to allocate. For the @@ -596,8 +829,12 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) alignflags = 0; } - size = lineSize * (pScrn->virtualY + cacheLines); + if (pScrn->virtualX > pScrn->virtualY) + size = lineSize * (pScrn->virtualX + cacheLines); + else + size = lineSize * (pScrn->virtualY + cacheLines); size = ROUND_TO_PAGE(size); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sInitial framebuffer allocation size: %ld kByte\n", s, size / 1024); @@ -633,7 +870,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) maxFb = ROUND_DOWN_TO(maxFb, lineSize); if (maxFb > lineSize * MAX_DISPLAY_HEIGHT) maxFb = lineSize * MAX_DISPLAY_HEIGHT; - if (maxFb > pI830->FrontBuffer.Size) { + if (0/*maxFb > pI830->FrontBuffer.Size*/) { unsigned long oldsize; /* * Sanity check -- the fb should be the last thing allocated at @@ -699,8 +936,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) */ if (!dryrun) { memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy)); - pI830->Dummy.Key = - xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL); + pI830->Dummy.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL); pI830->Dummy.Offset = 0; } #endif @@ -827,13 +1063,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) alloced / 1024, pI830->Scratch2.Start); } } + return TRUE; } -#ifndef ALLOCATE_ALL_BIOSMEM -#define ALLOCATE_ALL_BIOSMEM 1 -#endif - void I830ResetAllocations(ScrnInfoPtr pScrn, const int flags) { @@ -870,20 +1103,6 @@ I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn) } #ifdef XF86DRI -static unsigned long -GetBestTileAlignment(unsigned long size) -{ - unsigned long i; - - for (i = KB(512); i < size; i <<= 1) - ; - - if (i > MB(64)) - i = MB(64); - - return i; -} - static unsigned int myLog2(unsigned int n) { @@ -897,18 +1116,16 @@ myLog2(unsigned int n) } Bool -I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) +I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); unsigned long size, alloced, align = 0; - int i; Bool tileable; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); int verbosity = dryrun ? 4 : 1; const char *s = dryrun ? "[dryrun] " : ""; int lines; - - DPRINTF(PFX, "I830Allocate3DMemory\n"); + int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX; /* Back Buffer */ memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer)); @@ -917,9 +1134,9 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) IsTileable(pScrn->displayWidth * pI830->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ - lines = (pScrn->virtualY + 15) / 16 * 16; + lines = (height + 15) / 16 * 16; } else { - lines = pScrn->virtualY; + lines = height; } size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp); @@ -941,7 +1158,7 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) if (alloced < size) { /* Give up on trying to tile */ tileable = FALSE; - size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp); + size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp); align = GTT_PAGE_SIZE; alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer), &(pI830->StolenPool), size, align, @@ -958,16 +1175,41 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s, alloced / 1024, pI830->BackBuffer.Start); + return TRUE; +} + +Bool +I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long size, alloced, align = 0; + Bool tileable; + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + int lines; + int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX; + /* Depth Buffer -- same size as the back buffer */ memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer)); pI830->DepthBuffer.Key = -1; + tileable = !(flags & ALLOC_NO_TILING) && + IsTileable(pScrn->displayWidth * pI830->cpp); + if (tileable) { + /* Make the height a multiple of the tile height (16) */ + lines = (height + 15) / 16 * 16; + } else { + lines = height; + } + + size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp); /* * Try to allocate on the best tile-friendly boundaries. */ alloced = 0; if (tileable) { - /* Start with the previous align value. */ - for (; align >= KB(512); align >>= 1) { + align = GetBestTileAlignment(size); + for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | @@ -979,7 +1221,7 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) if (alloced < size) { /* Give up on trying to tile */ tileable = FALSE; - size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp); + size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp); align = GTT_PAGE_SIZE; alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer), &(pI830->StolenPool), size, align, @@ -996,24 +1238,18 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s, alloced / 1024, pI830->DepthBuffer.Start); - /* Space for logical context. 32k is fine for right now. */ - memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem)); - pI830->ContextMem.Key = -1; - size = KB(32); - alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem), - &(pI830->StolenPool), size, GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate logical context space.\n"); - } - return FALSE; - } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the logical context at 0x%lx.\n", s, - alloced / 1024, pI830->ContextMem.Start); + return TRUE; +} +Bool +I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long size, alloced; + int i; + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; /* Allocate the remaining space for textures. */ memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem)); @@ -1052,6 +1288,47 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) return TRUE; } + +Bool +I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long size, alloced; + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + + DPRINTF(PFX, "I830Allocate3DMemory\n"); + + /* Space for logical context. 32k is fine for right now. */ + memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem)); + pI830->ContextMem.Key = -1; + size = KB(32); + alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem), + &(pI830->StolenPool), size, GTT_PAGE_SIZE, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate logical context space.\n"); + } + return FALSE; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for the logical context at 0x%lx.\n", s, + alloced / 1024, pI830->ContextMem.Start); + + if (!I830AllocateBackBuffer(pScrn, flags)) + return FALSE; + + if (!I830AllocateDepthBuffer(pScrn, flags)) + return FALSE; + + if (!I830AllocateTextureMemory(pScrn, flags)) + return FALSE; + + return TRUE; +} #endif /* Allocate pool space that isn't pre-allocated */ @@ -1079,9 +1356,8 @@ I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool) if (pool->Total.Size > pool->Fixed.Size) { pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size; - pool->Allocated.Key = - xf86AllocateGARTMemory(pScrn->scrnIndex, pool->Allocated.Size, - 0, NULL); + pool->Allocated.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, + pool->Allocated.Size, 0, NULL); if (pool->Allocated.Key == -1) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n"); return FALSE; @@ -1115,8 +1391,8 @@ static unsigned long topOfMem = 0; #define PACK_RANGES 0 #define POOL_RANGES 0 -static Bool -FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem) +Bool +I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem) { #if POOL_RANGES I830Ptr pI830 = I830PTR(pScrn); @@ -1186,25 +1462,27 @@ I830FixupOffsets(ScrnInfoPtr pScrn) topOfMem = pI830->StolenPool.Total.End; if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - FixOffset(pScrn, &(pI830->FrontBuffer2)); - FixOffset(pScrn, &(pI830->FrontBuffer)); - FixOffset(pScrn, pI830->CursorMem); - FixOffset(pScrn, pI830->CursorMemARGB); - FixOffset(pScrn, &(pI830->LpRing->mem)); - FixOffset(pScrn, &(pI830->Scratch)); + I830FixOffset(pScrn, &(pI830->FrontBuffer2)); + I830FixOffset(pScrn, &(pI830->FrontBuffer)); + I830FixOffset(pScrn, pI830->CursorMem); + I830FixOffset(pScrn, pI830->CursorMemARGB); + I830FixOffset(pScrn, &(pI830->LpRing->mem)); + I830FixOffset(pScrn, &(pI830->Scratch)); if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - FixOffset(pScrn, &(pI830->Scratch2)); + I830FixOffset(pScrn, &(pI830->Scratch2)); #ifdef I830_XV if (pI830->XvEnabled) { - FixOffset(pScrn, pI830->OverlayMem); + I830FixOffset(pScrn, pI830->OverlayMem); + if (pI830->LinearAlloc) + I830FixOffset(pScrn, &(pI830->LinearMem)); } #endif #ifdef XF86DRI if (pI830->directRenderingEnabled) { - FixOffset(pScrn, &(pI830->BackBuffer)); - FixOffset(pScrn, &(pI830->DepthBuffer)); - FixOffset(pScrn, &(pI830->ContextMem)); - FixOffset(pScrn, &(pI830->TexMem)); + I830FixOffset(pScrn, &(pI830->ContextMem)); + I830FixOffset(pScrn, &(pI830->BackBuffer)); + I830FixOffset(pScrn, &(pI830->DepthBuffer)); + I830FixOffset(pScrn, &(pI830->TexMem)); } #endif return TRUE; @@ -1239,7 +1517,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, i830Reg->Fence[nr] = 0; - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) + if (IS_I9XX(pI830)) fence_mask = ~I915G_FENCE_START_MASK; else fence_mask = ~I830_FENCE_START_MASK; @@ -1247,7 +1525,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, if (start & fence_mask) { xf86DrvMsg(X_WARNING, pScrn->scrnIndex, "SetFence: %d: start (0x%08x) is not %s aligned\n", - nr, start, (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) ? "1MB" : "512k"); + nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k"); return; } @@ -1267,7 +1545,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, val = (start | FENCE_X_MAJOR | FENCE_VALID); - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + if (IS_I9XX(pI830)) { switch (size) { case MB(1): val |= I915G_FENCE_SIZE_1M; @@ -1328,7 +1606,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, } } - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) + if (IS_I9XX(pI830)) fence_pitch = pitch / 512; else fence_pitch = pitch / 128; @@ -1369,8 +1647,6 @@ MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem) { I830Ptr pI830 = I830PTR(pScrn); int pitch, ntiles, i; - static int nextTile = 0; - static unsigned int tileGeneration = -1; #if 0 /* Hack to "improve" the alignment of the front buffer. @@ -1405,6 +1681,14 @@ void I830SetupMemoryTiling(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + int i; + + /* Clear out */ + for (i = 0; i < 8; i++) + pI830->ModeReg.Fence[i] = 0; + + nextTile = 0; + tileGeneration = -1; /* We currently only attempt to tile the back and depth buffers. */ if (!pI830->directRenderingEnabled) @@ -1458,10 +1742,31 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) "Activating tiled memory for the depth buffer.\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MakeTiles failed for the back buffer.\n"); + "MakeTiles failed for the depth buffer.\n"); } } + if (pI830->RotatedMem.Alignment >= KB(512)) { + if (MakeTiles(pScrn, &(pI830->RotatedMem))) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Activating tiled memory for the rotated buffer.\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MakeTiles failed for the rotated buffer.\n"); + } + } + +#if 0 + if (pI830->RotatedMem2.Alignment >= KB(512)) { + if (MakeTiles(pScrn, &(pI830->RotatedMem2))) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Activating tiled memory for the rotated2 buffer.\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MakeTiles failed for the rotated buffer.\n"); + } + } +#endif } #endif /* XF86DRI */ @@ -1478,12 +1783,12 @@ BindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem) } Bool -I830BindGARTMemory(ScrnInfoPtr pScrn) +I830BindAGPMemory(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, - "I830BindGARTMemory: StolenOnly is %s, pI830->GttBound is %s\n", + "I830BindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n", BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound)); if (pI830->StolenOnly == TRUE) @@ -1517,17 +1822,29 @@ I830BindGARTMemory(ScrnInfoPtr pScrn) if (!BindMemRange(pScrn, &(pI830->Scratch2))) return FALSE; #ifdef I830_XV - if (!BindMemRange(pScrn, pI830->OverlayMem)) - return FALSE; + if (pI830->XvEnabled) { + if (!BindMemRange(pScrn, pI830->OverlayMem)) + return FALSE; + if (pI830->LinearAlloc) + if (!BindMemRange(pScrn, &(pI830->LinearMem))) + return FALSE; + } #endif + if (pI830->RotatedMem.Start) + if (!BindMemRange(pScrn, &(pI830->RotatedMem))) + return FALSE; + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 && + pI830->RotatedMem2.Start) + if (!BindMemRange(pScrn, &(pI830->RotatedMem2))) + return FALSE; #ifdef XF86DRI if (pI830->directRenderingEnabled) { + if (!BindMemRange(pScrn, &(pI830->ContextMem))) + return FALSE; if (!BindMemRange(pScrn, &(pI830->BackBuffer))) return FALSE; if (!BindMemRange(pScrn, &(pI830->DepthBuffer))) return FALSE; - if (!BindMemRange(pScrn, &(pI830->ContextMem))) - return FALSE; if (!BindMemRange(pScrn, &(pI830->TexMem))) return FALSE; } @@ -1552,12 +1869,12 @@ UnbindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem) Bool -I830UnbindGARTMemory(ScrnInfoPtr pScrn) +I830UnbindAGPMemory(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, - "I830UnbindGARTMemory: StolenOnly is %s, pI830->GttBound is %s\n", + "I830UnbindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n", BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound)); if (pI830->StolenOnly == TRUE) @@ -1589,17 +1906,29 @@ I830UnbindGARTMemory(ScrnInfoPtr pScrn) if (!UnbindMemRange(pScrn, &(pI830->Scratch2))) return FALSE; #ifdef I830_XV - if (!UnbindMemRange(pScrn, pI830->OverlayMem)) - return FALSE; + if (pI830->XvEnabled) { + if (!UnbindMemRange(pScrn, pI830->OverlayMem)) + return FALSE; + if (pI830->LinearAlloc) + if (!UnbindMemRange(pScrn, &(pI830->LinearMem))) + return FALSE; + } #endif + if (pI830->RotatedMem.Start) + if (!UnbindMemRange(pScrn, &(pI830->RotatedMem))) + return FALSE; + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 && + pI830->RotatedMem2.Start) + if (!UnbindMemRange(pScrn, &(pI830->RotatedMem2))) + return FALSE; #ifdef XF86DRI if (pI830->directRenderingEnabled) { + if (!UnbindMemRange(pScrn, &(pI830->ContextMem))) + return FALSE; if (!UnbindMemRange(pScrn, &(pI830->BackBuffer))) return FALSE; if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer))) return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->ContextMem))) - return FALSE; if (!UnbindMemRange(pScrn, &(pI830->TexMem))) return FALSE; } @@ -1617,7 +1946,7 @@ long I830CheckAvailableMemory(ScrnInfoPtr pScrn) { AgpInfoPtr agpinf; - long maxPages; + int maxPages; if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex) || @@ -1626,9 +1955,8 @@ I830CheckAvailableMemory(ScrnInfoPtr pScrn) return -1; maxPages = agpinf->totalPages - agpinf->usedPages; - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, - "Checking Available AGP Memory: %ld kB available (total %ld kB, used %ld kB)\n", - maxPages * 4, agpinf->totalPages * 4, agpinf->usedPages * 4); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %d kB available\n", + "I830CheckAvailableMemory", maxPages * 4); return maxPages * 4; } diff --git a/src/i830_modes.c b/src/i830_modes.c index 457b583e..a992bb60 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -346,7 +346,7 @@ I830GetGTF (int h_pixels, int v_lines, float freq, m->Clock = (int)(pixel_freq * 1000); m->SynthClock = m->Clock; m->HSync = h_freq; - m->VRefresh = freq; + m->VRefresh = v_frame_rate /* freq */; snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay); m->name = xnfstrdup(modename); diff --git a/src/i830_randr.c b/src/i830_randr.c new file mode 100644 index 00000000..be790c9a --- /dev/null +++ b/src/i830_randr.c @@ -0,0 +1,356 @@ +/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.3 2004/07/30 21:53:09 eich Exp $ */ +/* + * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.7tsi Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xf86.h" +#include "os.h" +#include "mibank.h" +#include "globals.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86DDC.h" +#include "mipointer.h" +#include "windowstr.h" +#include <randrstr.h> + +#include "i830.h" + +typedef struct _i830RandRInfo { + int virtualX; + int virtualY; + int mmWidth; + int mmHeight; + int maxX; + int maxY; + Rotation rotation; /* current mode */ + Rotation supported_rotations; /* driver supported */ +} XF86RandRInfoRec, *XF86RandRInfoPtr; + +static int i830RandRIndex; +static int i830RandRGeneration; + +#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) (p)->devPrivates[i830RandRIndex].ptr) + +static int +I830RandRModeRefresh (DisplayModePtr mode) +{ + if (mode->VRefresh) + return (int) (mode->VRefresh + 0.5); + else + return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); +} + +static Bool +I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + RRScreenSizePtr pSize; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int refresh0 = 60; + int maxX = 0, maxY = 0; + + *rotations = randrp->supported_rotations; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + } + + for (mode = scrp->modes; ; mode = mode->next) + { + int refresh = I830RandRModeRefresh (mode); + if (randrp->maxX == 0 || randrp->maxY == 0) + { + if (maxX < mode->HDisplay) + maxX = mode->HDisplay; + if (maxY < mode->VDisplay) + maxY = mode->VDisplay; + } + if (mode == scrp->modes) + refresh0 = refresh; + pSize = RRRegisterSize (pScreen, + mode->HDisplay, mode->VDisplay, + randrp->mmWidth, randrp->mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh); + if (mode == scrp->currentMode && + mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY) + RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); + if (mode->next == scrp->modes) + break; + } + + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + + if (scrp->currentMode->HDisplay != randrp->virtualX || + scrp->currentMode->VDisplay != randrp->virtualY) + { + mode = scrp->modes; + pSize = RRRegisterSize (pScreen, + randrp->virtualX, randrp->virtualY, + randrp->mmWidth, + randrp->mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh0); + if (scrp->virtualX == randrp->virtualX && + scrp->virtualY == randrp->virtualY) + { + RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize); + } + } + + return TRUE; +} + +static Bool +I830RandRSetMode (ScreenPtr pScreen, + DisplayModePtr mode, + Bool useVirtual, + int mmWidth, + int mmHeight) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int oldWidth = pScreen->width; + int oldHeight = pScreen->height; + int oldmmWidth = pScreen->mmWidth; + int oldmmHeight = pScreen->mmHeight; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + DisplayModePtr currentMode = NULL; + Bool ret = TRUE; + PixmapPtr pspix = NULL; + + if (pRoot) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); + if (useVirtual) + { + scrp->virtualX = randrp->virtualX; + scrp->virtualY = randrp->virtualY; + } + else + { + scrp->virtualX = mode->HDisplay; + scrp->virtualY = mode->VDisplay; + } + if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) + { + /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ + pScreen->width = scrp->virtualY; + pScreen->height = scrp->virtualX; + pScreen->mmWidth = mmHeight; + pScreen->mmHeight = mmWidth; + } + else + { + pScreen->width = scrp->virtualX; + pScreen->height = scrp->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + } + if (scrp->currentMode == mode) { + /* Save current mode */ + currentMode = scrp->currentMode; + /* Reset, just so we ensure the drivers SwitchMode is called */ + scrp->currentMode = NULL; + } + /* + * We know that if the driver failed to SwitchMode to the rotated + * version, then it should revert back to it's prior mode. + */ + if (!xf86SwitchMode (pScreen, mode)) + { + ret = FALSE; + scrp->virtualX = pScreen->width = oldWidth; + scrp->virtualY = pScreen->height = oldHeight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + scrp->currentMode = currentMode; + } + /* + * Get the new Screen pixmap ptr as SwitchMode might have called + * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back... + * Unfortunately. + */ + pspix = (*pScreen->GetScreenPixmap) (pScreen); + if (pspix->devPrivate.ptr) + scrp->pixmapPrivate = pspix->devPrivate; + + /* + * Make sure the layout is correct + */ + xf86ReconfigureLayout(); + + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); + return ret; +} + +Bool +I830RandRSetConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int px, py; + Bool useVirtual = FALSE; + int maxX = 0, maxY = 0; + Rotation oldRotation = randrp->rotation; + + randrp->rotation = rotation; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + } + + miPointerPosition (&px, &py); + for (mode = scrp->modes; ; mode = mode->next) + { + if (randrp->maxX == 0 || randrp->maxY == 0) + { + if (maxX < mode->HDisplay) + maxX = mode->HDisplay; + if (maxY < mode->VDisplay) + maxY = mode->VDisplay; + } + if (mode->HDisplay == pSize->width && + mode->VDisplay == pSize->height && + (rate == 0 || I830RandRModeRefresh (mode) == rate)) + break; + if (mode->next == scrp->modes) + { + if (pSize->width == randrp->virtualX && + pSize->height == randrp->virtualY) + { + mode = scrp->modes; + useVirtual = TRUE; + break; + } + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + return FALSE; + } + } + + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + + if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) { + randrp->rotation = oldRotation; + return FALSE; + } + + /* + * Move the cursor back where it belongs; SwitchMode repositions it + */ + if (pScreen == miPointerCurrentScreen ()) + { + px = (px >= pScreen->width ? (pScreen->width - 1) : px); + py = (py >= pScreen->height ? (pScreen->height - 1) : py); + + xf86SetViewport(pScreen, px, py); + + (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE); + } + + return TRUE; +} + +Rotation +I830GetRotation(ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + return randrp->rotation; +} + +Bool +I830RandRInit (ScreenPtr pScreen, int rotation) +{ + rrScrPrivPtr rp; + XF86RandRInfoPtr randrp; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif + if (i830RandRGeneration != serverGeneration) + { + i830RandRIndex = AllocateScreenPrivateIndex(); + i830RandRGeneration = serverGeneration; + } + + randrp = xalloc (sizeof (XF86RandRInfoRec)); + if (!randrp) + return FALSE; + + if (!RRScreenInit(pScreen)) + { + xfree (randrp); + return FALSE; + } + rp = rrGetScrPriv(pScreen); + rp->rrGetInfo = I830RandRGetInfo; + rp->rrSetConfig = I830RandRSetConfig; + + randrp->virtualX = -1; + randrp->virtualY = -1; + randrp->mmWidth = pScreen->mmWidth; + randrp->mmHeight = pScreen->mmHeight; + + randrp->rotation = RR_Rotate_0; /* initial rotated mode */ + + randrp->supported_rotations = rotation; + + randrp->maxX = randrp->maxY = 0; + + pScreen->devPrivates[i830RandRIndex].ptr = randrp; + + return TRUE; +} diff --git a/src/i830_rotate.c b/src/i830_rotate.c new file mode 100644 index 00000000..f60d64fe --- /dev/null +++ b/src/i830_rotate.c @@ -0,0 +1,1181 @@ +/************************************************************************** + +Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Reformatted with GNU indent (2.2.8), using the following options: + * + * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78 + * -lp -npcs -psl -sob -ss -br -ce -sc -hnl + * + * This provides a good match with the original i810 code and preferred + * XFree86 formatting conventions. + * + * When editing this driver, please follow the existing formatting, and edit + * with <TAB> characters expanded at 8-column intervals. + */ + +/* + * Authors: + * Alan Hourihane <alanh@tungstengraphics.com> + * Brian Paul <brian.paul@tungstengraphics.com> + * Keith Whitwell <keith@tungstengraphics.com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "servermd.h" +#include "shadow.h" + +#include "i830.h" + +#ifdef XF86DRI +#include "dri.h" +#endif + +static void * +I830WindowLinear (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + CARD8 *ptr; + + *size = (pScrn->bitsPerPixel * pI830->displayWidth >> 3); + if (I830IsPrimary(pScrn)) + ptr = (CARD8 *) (pI830->FbBase + pI830->FrontBuffer.Start) + row * (*size) + offset; + else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + ptr = (CARD8 *) (pI830->FbBase + pI8301->FrontBuffer2.Start) + row * (*size) + offset; + } + return (void *)ptr; +} + +struct matrix23 +{ + int m00, m01, m02; + int m10, m11, m12; +}; + +static void +matrix23Set(struct matrix23 *m, + int m00, int m01, int m02, + int m10, int m11, int m12) +{ + m->m00 = m00; m->m01 = m01; m->m02 = m02; + m->m10 = m10; m->m11 = m11; m->m12 = m12; +} + + +/* + * Transform (x,y) coordinate by the given matrix. + */ +static void +matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y) +{ + const float x0 = *x; + const float y0 = *y; + + *x = m->m00 * x0 + m->m01 * y0 + m->m02; + *y = m->m10 * x0 + m->m11 * y0 + m->m12; +} + +/* + * Make rotation matrix for width X height screen. + */ +static void +matrix23Rotate(struct matrix23 *m, int width, int height, int angle) +{ + switch (angle) { + case 0: + matrix23Set(m, 1, 0, 0, 0, 1, 0); + break; + case 90: + matrix23Set(m, 0, 1, 0, -1, 0, width); + break; + case 180: + matrix23Set(m, -1, 0, width, 0, -1, height); + break; + case 270: + matrix23Set(m, 0, -1, height, 1, 0, 0); + break; + default: + break; + } +} + +/* Doesn't matter on the order for our purposes */ +typedef struct { + unsigned char red, green, blue, alpha; +} intel_color_t; + +/* Vertex format */ +typedef union { + struct { + float x, y, z, w; + intel_color_t color; + intel_color_t specular; + float u0, v0; + float u1, v1; + float u2, v2; + float u3, v3; + } v; + float f[24]; + unsigned int ui[24]; + unsigned char ub4[24][4]; +} intelVertex, *intelVertexPtr; + +static void draw_poly(CARD32 *vb, + float verts[][2], + float texcoords[][2]) +{ + int vertex_size = 8; + intelVertex tmp; + int i, k; + + /* initial constant vertex fields */ + tmp.v.z = 1.0; + tmp.v.w = 1.0; + tmp.v.color.red = 255; + tmp.v.color.green = 255; + tmp.v.color.blue = 255; + tmp.v.color.alpha = 255; + tmp.v.specular.red = 0; + tmp.v.specular.green = 0; + tmp.v.specular.blue = 0; + tmp.v.specular.alpha = 0; + + for (k = 0; k < 4; k++) { + tmp.v.x = verts[k][0]; + tmp.v.y = verts[k][1]; + tmp.v.u0 = texcoords[k][0]; + tmp.v.v0 = texcoords[k][1]; + + for (i = 0 ; i < vertex_size ; i++) + vb[i] = tmp.ui[i]; + + vb += vertex_size; + } +} + +static void +I915UpdateRotate (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn1 = pScrn; + I830Ptr pI8301 = NULL; + RegionPtr damage = shadowDamage(pBuf); + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + int box_x1, box_x2, box_y1, box_y2; + CARD32 vb[32]; /* 32 dword vertex buffer */ + float verts[4][2], tex[4][2]; + struct matrix23 rotMatrix; + int j; + int use_fence; + Bool updateInvarient = FALSE; +#ifdef XF86DRI + drmI830Sarea *sarea = NULL; + drm_context_t myContext = 0; +#endif + Bool didLock = FALSE; + + if (I830IsPrimary(pScrn)) { + pI8301 = pI830; + } else { + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pScrn1 = pI830->entityPrivate->pScrn_1; + } + + switch (pI830->rotation) { + case RR_Rotate_90: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 90); + break; + case RR_Rotate_180: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 180); + break; + case RR_Rotate_270: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 270); + break; + default: + break; + } + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) { + sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + myContext = DRIGetContext(pScrn1->pScreen); + didLock = I830DRILock(pScrn1); + } +#endif + + if (pScrn->scrnIndex != *pI830->used3D) + updateInvarient = TRUE; + +#ifdef XF86DRI + if (sarea->ctxOwner != myContext) + updateInvarient = TRUE; +#endif + + if (updateInvarient) { + *pI830->used3D = pScrn->scrnIndex; +#ifdef XF86DRI + if (sarea) + sarea->ctxOwner = myContext; +#endif + BEGIN_LP_RING(64); + /* invarient state */ + OUT_RING(MI_NOOP); + OUT_RING(0x66014140); + OUT_RING(0x7d990000); + OUT_RING(0x00000000); + OUT_RING(0x7d9a0000); + OUT_RING(0x00000000); + OUT_RING(0x7d980000); + OUT_RING(0x00000000); + OUT_RING(0x76fac688); + OUT_RING(0x6700a770); + OUT_RING(0x7d040081); + OUT_RING(0x00000000); + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + /* draw rect */ + OUT_RING(0x7d800003); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + /* scissor */ + OUT_RING(0x7c800002); + OUT_RING(0x7d810001); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x7c000003); + OUT_RING(0x7d070000); + OUT_RING(0x00000000); + OUT_RING(0x68000002); + /* context setup */ + OUT_RING(0x6db3ffff); + OUT_RING(0x7d040744); + OUT_RING(0xfffffff0); + OUT_RING(0x00902c80); + OUT_RING(0x00000000); + OUT_RING(0x00020216); + OUT_RING(0x6ba008a1); + OUT_RING(0x7d880000); + OUT_RING(0x00000000); + /* dv0 */ + OUT_RING(0x7d850000); + /* dv1 */ + if (pI830->cpp == 1) + OUT_RING(0x10880000); + else if (pI830->cpp == 2) + OUT_RING(0x10880200); + else + OUT_RING(0x10880308); + /* stipple */ + OUT_RING(0x7d830000); + OUT_RING(0x00000000); + /* fragment program - texture blend replace*/ + OUT_RING(0x7d050008); + OUT_RING(0x19180000); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x19083c00); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x15200000); + OUT_RING(0x01000000); + OUT_RING(0x00000000); + /* texture sampler state */ + OUT_RING(0x7d010003); + OUT_RING(0x00000001); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + /* front buffer, pitch, offset */ + OUT_RING(0x7d8e0001); + OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2)); + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->FrontBuffer.Start); + else + OUT_RING(pI8301->FrontBuffer2.Start); + + /* Set the entire frontbuffer up as a texture */ + OUT_RING(0x7d000003); + OUT_RING(0x00000001); + + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->RotatedMem.Start); + else + OUT_RING(pI8301->RotatedMem2.Start); + + if (pI830->disableTiling) + use_fence = 0; + else + use_fence = 4; + + if (pI830->cpp == 1) + use_fence |= 0x80; /* MAPSURF_8BIT */ + else + if (pI830->cpp == 2) + use_fence |= 0x100; /* MAPSURF_16BIT */ + else + use_fence |= 0x180; /* MAPSURF_32BIT */ + OUT_RING(use_fence | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + OUT_RING(((((pScrn->displayWidth * pI830->cpp) / 4) - 1) << 21)); + ADVANCE_LP_RING(); + } + + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + ADVANCE_LP_RING(); + } + + while (nbox--) + { + box_x1 = pbox->x1; + box_y1 = pbox->y1; + box_x2 = pbox->x2; + box_y2 = pbox->y2; + pbox++; + + BEGIN_LP_RING(40); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + + /* vertex data */ + OUT_RING(0x7f0c001f); + verts[0][0] = box_x1; verts[0][1] = box_y1; + verts[1][0] = box_x2; verts[1][1] = box_y1; + verts[2][0] = box_x2; verts[2][1] = box_y2; + verts[3][0] = box_x1; verts[3][1] = box_y2; + tex[0][0] = box_x1; tex[0][1] = box_y1; + tex[1][0] = box_x2; tex[1][1] = box_y1; + tex[2][0] = box_x2; tex[2][1] = box_y2; + tex[3][0] = box_x1; tex[3][1] = box_y2; + + /* transform coordinates to rotated versions, but leave texcoords unchanged */ + for (j = 0; j < 4; j++) + matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]); + + /* emit vertex buffer */ + draw_poly(vb, verts, tex); + for (j = 0; j < 32; j++) + OUT_RING(vb[j]); + + ADVANCE_LP_RING(); + } + +#ifdef XF86DRI + if (didLock) + I830DRIUnlock(pScrn1); +#endif +} + +static void +I830UpdateRotate (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + I830Ptr pI8301 = NULL; + ScrnInfoPtr pScrn1 = pScrn; + RegionPtr damage = shadowDamage(pBuf); + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + int box_x1, box_x2, box_y1, box_y2; + CARD32 vb[32]; /* 32 dword vertex buffer */ + float verts[4][2], tex[4][2]; + struct matrix23 rotMatrix; + Bool updateInvarient = FALSE; + int use_fence; + int j; +#ifdef XF86DRI + drmI830Sarea *sarea = NULL; + drm_context_t myContext = 0; +#endif + Bool didLock = FALSE; + + if (I830IsPrimary(pScrn)) { + pI8301 = pI830; + } else { + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pScrn1 = pI830->entityPrivate->pScrn_1; + } + + switch (pI830->rotation) { + case RR_Rotate_90: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 90); + break; + case RR_Rotate_180: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 180); + break; + case RR_Rotate_270: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 270); + break; + default: + break; + } + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) { + sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + myContext = DRIGetContext(pScrn1->pScreen); + didLock = I830DRILock(pScrn1); + } +#endif + + if (pScrn->scrnIndex != *pI830->used3D) + updateInvarient = TRUE; + +#ifdef XF86DRI + if (sarea->ctxOwner != myContext) + updateInvarient = TRUE; +#endif + + if (updateInvarient) { + *pI830->used3D = pScrn->scrnIndex; +#ifdef XF86DRI + if (sarea) + sarea->ctxOwner = myContext; +#endif + + BEGIN_LP_RING(48); + OUT_RING(0x682008a1); + OUT_RING(0x6f402100); + OUT_RING(0x62120aa9); + OUT_RING(0x76b3ffff); + OUT_RING(0x6c818a01); + OUT_RING(0x6ba008a1); + OUT_RING(0x69802100); + OUT_RING(0x63a00aaa); + OUT_RING(0x6423070e); + OUT_RING(0x66014142); + OUT_RING(0x75000000); + OUT_RING(0x7d880000); + OUT_RING(0x00000000); + OUT_RING(0x650001c4); + OUT_RING(0x6a000000); + OUT_RING(0x7d020000); + OUT_RING(0x0000ba98); + + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + /* draw rect */ + OUT_RING(0x7d800003); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + + /* front buffer */ + OUT_RING(0x7d8e0001); + OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2)); + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->FrontBuffer.Start); + else + OUT_RING(pI8301->FrontBuffer2.Start); + OUT_RING(0x7d850000); + if (pI830->cpp == 1) + OUT_RING(0x00880000); + else + if (pI830->cpp == 2) + OUT_RING(0x00880200); + else + OUT_RING(0x00880308); + /* scissor */ + OUT_RING(0x7c800002); + OUT_RING(0x7d810001); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + /* stipple */ + OUT_RING(0x7d830000); + OUT_RING(0x00000000); + + /* texture blend replace */ + OUT_RING(0x7c088088); + OUT_RING(0x00000000); + OUT_RING(0x6d021181); + OUT_RING(0x6d060101); + OUT_RING(0x6e008046); + OUT_RING(0x6e048046); + + + /* Set the entire frontbuffer up as a texture */ + OUT_RING(0x7d030804); + + if (pI830->disableTiling) + use_fence = 0; + else + use_fence = 2; + + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->RotatedMem.Start | use_fence); + else + OUT_RING(pI8301->RotatedMem2.Start | use_fence); + + if (pI830->cpp == 1) + OUT_RING(0x00 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + else if (pI830->cpp == 2) + OUT_RING(0x40 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + else + OUT_RING(0xc0 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + + OUT_RING((((pScrn->displayWidth * pI830->cpp / 4) - 1) << 21)); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + + + ADVANCE_LP_RING(); + } + + { + BEGIN_LP_RING(2); + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + ADVANCE_LP_RING(); + } + + while (nbox--) + { + box_x1 = pbox->x1; + box_y1 = pbox->y1; + box_x2 = pbox->x2; + box_y2 = pbox->y2; + pbox++; + + BEGIN_LP_RING(40); + + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + + /* vertex data */ + OUT_RING(0x7f0c001f); + verts[0][0] = box_x1; verts[0][1] = box_y1; + verts[1][0] = box_x2; verts[1][1] = box_y1; + verts[2][0] = box_x2; verts[2][1] = box_y2; + verts[3][0] = box_x1; verts[3][1] = box_y2; + tex[0][0] = box_x1; tex[0][1] = box_y1; + tex[1][0] = box_x2; tex[1][1] = box_y1; + tex[2][0] = box_x2; tex[2][1] = box_y2; + tex[3][0] = box_x1; tex[3][1] = box_y2; + + /* transform coordinates to rotated versions, but leave texcoords unchanged */ + for (j = 0; j < 4; j++) + matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]); + + /* emit vertex buffer */ + draw_poly(vb, verts, tex); + for (j = 0; j < 32; j++) + OUT_RING(vb[j]); + + OUT_RING(0x05000000); + OUT_RING(0x00000000); + + ADVANCE_LP_RING(); + } + + { + BEGIN_LP_RING(2); + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + ADVANCE_LP_RING(); + } + +#ifdef XF86DRI + if (didLock) + I830DRIUnlock(pScrn1); +#endif +} + +Bool +I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830Ptr pI8301 = NULL; + I830Ptr pI8302 = NULL; + ScrnInfoPtr pScrn1 = NULL; + ScrnInfoPtr pScrn2 = NULL; + int i; + ShadowUpdateProc func = NULL; + Rotation oldRotation = pI830->rotation; /* save old state */ + int displayWidth = pScrn->displayWidth; /* save displayWidth */ + Bool reAllocate = TRUE; + Bool didLock = FALSE; + + /* Good pitches to allow tiling. Don't care about pitches < 1024. */ + static const int pitches[] = { +/* + 128 * 2, + 128 * 4, +*/ + 128 * 8, + 128 * 16, + 128 * 32, + 128 * 64, + 0 + }; + + if (pI830->noAccel) + func = LoaderSymbol("shadowUpdateRotatePacked"); + else + if (IS_I9XX(pI830)) + func = I915UpdateRotate; + else + func = I830UpdateRotate; + + if (I830IsPrimary(pScrn)) { + pI8301 = pI830; + pScrn1 = pScrn; + if (pI830->entityPrivate) { + pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); + pScrn2 = pI830->entityPrivate->pScrn_2; + } + } else { + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pScrn1 = pI830->entityPrivate->pScrn_1; + pI8302 = pI830; + pScrn2 = pScrn; + } + + pI830->rotation = I830GetRotation(pScrn->pScreen); + + /* Check if we've still got the same orientation, or same mode */ + if (pI830->rotation == oldRotation && pI830->currentMode == mode) +#if 0 + reAllocate = FALSE; +#else + return TRUE; +#endif + + /* + * We grab the DRI lock when reallocating buffers to avoid DRI clients + * getting bogus information. + */ +#ifdef XF86DRI + if (pI8301->directRenderingEnabled && reAllocate) { + didLock = I830DRILock(pScrn1); + + /* Do heap teardown here + */ + { + drmI830MemDestroyHeap destroy; + destroy.region = I830_MEM_REGION_AGP; + + if (drmCommandWrite(pI8301->drmSubFD, + DRM_I830_DESTROY_HEAP, + &destroy, sizeof(destroy))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] I830 destroy heap failed\n"); + } + } + + if (pI8301->TexMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key); + I830FreeVidMem(pScrn1, &(pI8301->TexMem)); + if (pI8301->StolenPool.Allocated.Key != -1) { + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key); + xf86DeallocateGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key); + } + if (pI8301->DepthBuffer.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key); + I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer)); + if (pI8301->BackBuffer.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key); + I830FreeVidMem(pScrn1, &(pI8301->BackBuffer)); + } +#endif + + if (reAllocate) { + *pI830->used3D |= 1<<31; /* use high bit to denote new rotation occured */ + + if (pI8301->RotatedMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem)); + memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem)); + pI8301->RotatedMem.Key = -1; + + if (pI830->entityPrivate) { + if (pI8301->RotatedMem2.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem2)); + memset(&(pI8301->RotatedMem2), 0, sizeof(pI8301->RotatedMem2)); + pI8301->RotatedMem2.Key = -1; + } + } + + switch (pI830->rotation) { + case RR_Rotate_0: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 0 degrees\n"); + pScrn->displayWidth = pI830->displayWidth; + break; + case RR_Rotate_90: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 90 degrees\n"); + pScrn->displayWidth = pScrn->pScreen->width; + break; + case RR_Rotate_180: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 180 degrees\n"); + pScrn->displayWidth = pI830->displayWidth; + break; + case RR_Rotate_270: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 270 degrees\n"); + pScrn->displayWidth = pScrn->pScreen->width; + break; + } + + /* As DRI doesn't run on the secondary head, we know that disableTiling + * is always TRUE. + */ + if (I830IsPrimary(pScrn) && !pI830->disableTiling) { +#if 0 + int dWidth = pScrn->displayWidth; /* save current displayWidth */ +#endif + + for (i = 0; pitches[i] != 0; i++) { + if (pitches[i] >= pScrn->displayWidth) { + pScrn->displayWidth = pitches[i]; + break; + } + } + + /* + * If the displayWidth is a tilable pitch, test if there's enough + * memory available to enable tiling. + */ + if (pScrn->displayWidth == pitches[i]) { + /* TODO */ + } + } + + if (reAllocate) { + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) { + if (!I830AllocateRotated2Buffer(pScrn1, + pI8302->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL0; + + I830FixOffset(pScrn1, &(pI8301->RotatedMem2)); + if (pI8301->RotatedMem2.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset); + } + } + + if (pI8301->rotation != RR_Rotate_0) { + if (!I830AllocateRotatedBuffer(pScrn1, + (pI8301->disableTiling ? ALLOC_NO_TILING : 0))) + goto BAIL1; + + I830FixOffset(pScrn1, &(pI8301->RotatedMem)); + if (pI8301->RotatedMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset); + } + } + + shadowRemove (pScrn->pScreen, NULL); + if (pI830->rotation != RR_Rotate_0) + shadowAdd (pScrn->pScreen, + (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), + func, I830WindowLinear, pI830->rotation, 0); + + if (I830IsPrimary(pScrn)) { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI830->RotatedMem.Start; + else + pScrn->fbOffset = pI830->FrontBuffer.Start; + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) + pScrn2->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn2->fbOffset = pI8301->FrontBuffer2.Start; + I830SelectBuffer(pScrn2, I830_SELECT_FRONT); + } + } else { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn->fbOffset = pI8301->FrontBuffer2.Start; + if (pI8301->rotation != RR_Rotate_0) + pScrn1->fbOffset = pI8301->RotatedMem.Start; + else + pScrn1->fbOffset = pI8301->FrontBuffer.Start; + I830SelectBuffer(pScrn1, I830_SELECT_FRONT); + } + I830SelectBuffer(pScrn, I830_SELECT_FRONT); + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled && reAllocate) { + if (!I830AllocateBackBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL2; + + if (!I830AllocateDepthBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL3; + + if (!I830AllocateTextureMemory(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL4; + + I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool)); + + I830FixOffset(pScrn1, &(pI8301->BackBuffer)); + I830FixOffset(pScrn1, &(pI8301->DepthBuffer)); + + if (pI8301->BackBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset); + if (pI8301->DepthBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset); + if (pI8301->StolenPool.Allocated.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset); + if (pI8301->TexMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset); + I830SetupMemoryTiling(pScrn1); + /* update fence registers */ + for (i = 0; i < 8; i++) + OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]); + { + drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + I830UpdateDRIBuffers(pScrn1, sarea ); + } + + if (didLock) + I830DRIUnlock(pScrn1); + } +#endif + +#if 0 + if (I830IsPrimary(pScrn)) { + pI830->xoffset = (pI830->FrontBuffer.Start / pI830->cpp) % pI830->displayWidth; + pI830->yoffset = (pI830->FrontBuffer.Start / pI830->cpp) / pI830->displayWidth; + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->xoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) % pI830->displayWidth; + pI830->yoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) / pI830->displayWidth; + } +#endif + + pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), pScrn->pScreen->width, + pScrn->pScreen->height, pScrn->pScreen->rootDepth, pScrn->bitsPerPixel, + PixmapBytePad(pScrn->displayWidth, pScrn->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn->fbOffset)); + + if (pI830->entityPrivate) { + if (I830IsPrimary(pScrn)) { + if (!pI830->starting) { + pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width, + pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel, + PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn2->fbOffset)); + + /* Repaint the second head */ + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); + } + } else { + if (!pI830->starting) { + pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width, + pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel, + PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn1->fbOffset)); + + /* Repaint the first head */ + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE); + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE); + } + } + } + + /* Don't allow pixmap cache or offscreen pixmaps when rotated */ + /* XAA needs some serious fixing for this to happen */ + if (pI830->rotation == RR_Rotate_0) { + pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE; + pI830->AccelInfoRec->UsingPixmapCache = TRUE; + /* funny as it seems this will enable XAA's createpixmap */ + pI830->AccelInfoRec->maxOffPixWidth = 0; + pI830->AccelInfoRec->maxOffPixHeight = 0; + } else { + pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER; + pI830->AccelInfoRec->UsingPixmapCache = FALSE; + /* funny as it seems this will disable XAA's createpixmap */ + pI830->AccelInfoRec->maxOffPixWidth = 1; + pI830->AccelInfoRec->maxOffPixHeight = 1; + } + + return TRUE; + +BAIL4: +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) + I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer)); +#endif +BAIL3: +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) + I830FreeVidMem(pScrn1, &(pI8301->BackBuffer)); +#endif +BAIL2: + if (pI8301->rotation != RR_Rotate_0) { + if (pI8301->RotatedMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem)); + memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem)); + pI8301->RotatedMem.Key = -1; + } +BAIL1: + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) { + if (pI8301->RotatedMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem)); + memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem)); + pI8301->RotatedMem.Key = -1; + } + } +BAIL0: + pScrn->displayWidth = displayWidth; + + /* must flip mmWidth & mmHeight */ + if ( ((oldRotation & (RR_Rotate_90 | RR_Rotate_270)) && + (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))) || + ((oldRotation & (RR_Rotate_0 | RR_Rotate_180)) && + (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270))) ) { + int tmp = pScrn->pScreen->mmWidth; + pScrn->pScreen->mmWidth = pScrn->pScreen->mmHeight; + pScrn->pScreen->mmHeight = tmp; + } + + if (oldRotation & (RR_Rotate_0 | RR_Rotate_180)) { + pScrn->pScreen->width = pScrn->virtualX; + pScrn->pScreen->height = pScrn->virtualY; + } else { + pScrn->pScreen->width = pScrn->virtualY; + pScrn->pScreen->height = pScrn->virtualX; + } + + pI830->rotation = oldRotation; + + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) { + if (!I830AllocateRotated2Buffer(pScrn1, + pI8302->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Oh dear, the rotated2 buffer failed - badness\n"); + + I830FixOffset(pScrn1, &(pI8301->RotatedMem2)); + if (pI8301->RotatedMem2.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset); + } + } + + if (pI8301->rotation != RR_Rotate_0) { + if (!I830AllocateRotatedBuffer(pScrn1, + (pI8301->disableTiling ? ALLOC_NO_TILING : 0))) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Oh dear, the rotated buffer failed - badness\n"); + + I830FixOffset(pScrn1, &(pI8301->RotatedMem)); + if (pI8301->RotatedMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset); + } + + shadowRemove (pScrn->pScreen, NULL); + if (pI830->rotation != RR_Rotate_0) + shadowAdd (pScrn->pScreen, + (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), + func, I830WindowLinear, pI830->rotation, 0); + + if (I830IsPrimary(pScrn)) { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI830->RotatedMem.Start; + else + pScrn->fbOffset = pI830->FrontBuffer.Start; + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) + pScrn2->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn2->fbOffset = pI8301->FrontBuffer2.Start; + I830SelectBuffer(pScrn2, I830_SELECT_FRONT); + } + } else { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn->fbOffset = pI8301->FrontBuffer2.Start; + if (pI8301->rotation != RR_Rotate_0) + pScrn1->fbOffset = pI8301->RotatedMem.Start; + else + pScrn1->fbOffset = pI8301->FrontBuffer.Start; + I830SelectBuffer(pScrn1, I830_SELECT_FRONT); + } + I830SelectBuffer(pScrn, I830_SELECT_FRONT); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Reverting to previous configured mode\n"); + + switch (oldRotation) { + case RR_Rotate_0: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 0 degrees\n"); + break; + case RR_Rotate_90: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 90 degrees\n"); + break; + case RR_Rotate_180: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 180 degrees\n"); + break; + case RR_Rotate_270: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 270 degrees\n"); + break; + } + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) { + if (!I830AllocateBackBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Oh dear, the back buffer failed - badness\n"); + + if (!I830AllocateDepthBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Oh dear, the depth buffer failed - badness\n"); + + if (!I830AllocateTextureMemory(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Oh dear, the texture cache failed - badness\n"); + + I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool)); + + I830FixOffset(pScrn1, &(pI8301->BackBuffer)); + I830FixOffset(pScrn1, &(pI8301->DepthBuffer)); + + if (pI8301->BackBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset); + if (pI8301->DepthBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset); + if (pI8301->StolenPool.Allocated.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset); + if (pI8301->TexMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset); + I830SetupMemoryTiling(pScrn1); + /* update fence registers */ + for (i = 0; i < 8; i++) + OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]); + { + drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + I830UpdateDRIBuffers(pScrn1, sarea ); + } + + if (didLock) + I830DRIUnlock(pScrn1); + } +#endif + + pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), pScrn->pScreen->width, + pScrn->pScreen->height, pScrn->pScreen->rootDepth, pScrn->bitsPerPixel, + PixmapBytePad(pScrn->displayWidth, pScrn->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn->fbOffset)); + + if (pI830->entityPrivate) { + if (I830IsPrimary(pScrn)) { + pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width, + pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel, + PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn2->fbOffset)); + + /* Repaint the second head */ + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); + } else { + pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width, + pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel, + PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn1->fbOffset)); + + /* Repaint the first head */ + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE); + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE); + } + } + + return FALSE; +} diff --git a/src/i830_shadow.c b/src/i830_shadow.c deleted file mode 100644 index 93c72c59..00000000 --- a/src/i830_shadow.c +++ /dev/null @@ -1,253 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_shadow.c,v 1.3 2000/03/31 20:13:33 dawes Exp $ */ - -/* - Copyright (c) 1999,2000 The XFree86 Project Inc. - based on code written by Mark Vojkovich <markv@valinux.com> -*/ - -/* - * Ported from the savage driver to the I830 by - * Helmar Spangenberg <hspangenberg@frey.de> and Dima Dorfman - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "xf86.h" -#include "i830.h" -#include "shadowfb.h" -#include "servermd.h" - - -void -I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) -{ - I830Ptr pI830 = I830PTR(pScrn); - int width, height, Bpp, FBPitch; - unsigned char *src, *dst; - - Bpp = pScrn->bitsPerPixel >> 3; - FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel); - - while(num--) { - width = (pbox->x2 - pbox->x1) * Bpp; - height = pbox->y2 - pbox->y1; - src = pI830->shadowPtr + (pbox->y1 * pI830->shadowPitch) + - (pbox->x1 * Bpp); - dst = pI830->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); - - while(height--) { - memcpy(dst, src, width); - dst += FBPitch; - src += pI830->shadowPitch; - } - - pbox++; - } -} - - -void -I830PointerMoved(int index, int x, int y) -{ - ScrnInfoPtr pScrn = xf86Screens[index]; - I830Ptr pI830 = I830PTR(pScrn); - int newX, newY; - - if(pI830->rotate == 1) { - newX = pScrn->pScreen->height - y - 1; - newY = x; - } else { - newX = y; - newY = pScrn->pScreen->width - x - 1; - } - - (*pI830->PointerMoved)(index, newX, newY); -} - -void -I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox) -{ - I830Ptr pI830 = I830PTR(pScrn); - int count, width, height, y1, y2, dstPitch, srcPitch; - CARD8 *dstPtr, *srcPtr, *src; - CARD32 *dst; - - dstPitch = pScrn->displayWidth; - srcPitch = -pI830->rotate * pI830->shadowPitch; - - while(num--) { - width = pbox->x2 - pbox->x1; - y1 = pbox->y1 & ~3; - y2 = (pbox->y2 + 3) & ~3; - height = (y2 - y1) >> 2; /* in dwords */ - - if(pI830->rotate == 1) { - dstPtr = pI830->FbBase + - (pbox->x1 * dstPitch) + pScrn->virtualX - y2; - srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + pbox->x1; - } else { - dstPtr = pI830->FbBase + - ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; - srcPtr = pI830->shadowPtr + (y1 * srcPitch) + pbox->x2 - 1; - } - - while(width--) { - src = srcPtr; - dst = (CARD32*)dstPtr; - count = height; - while(count--) { - *(dst++) = src[0] | (src[srcPitch] << 8) | - (src[srcPitch * 2] << 16) | - (src[srcPitch * 3] << 24); - src += srcPitch * 4; - } - srcPtr += pI830->rotate; - dstPtr += dstPitch; - } - - pbox++; - } -} - - -void -I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox) -{ - I830Ptr pI830 = I830PTR(pScrn); - int count, width, height, y1, y2, dstPitch, srcPitch; - CARD16 *dstPtr, *srcPtr, *src; - CARD32 *dst; - - dstPitch = pScrn->displayWidth; - srcPitch = -pI830->rotate * pI830->shadowPitch >> 1; - - while(num--) { - width = pbox->x2 - pbox->x1; - y1 = pbox->y1 & ~1; - y2 = (pbox->y2 + 1) & ~1; - height = (y2 - y1) >> 1; /* in dwords */ - - if(pI830->rotate == 1) { - dstPtr = (CARD16*)pI830->FbBase + - (pbox->x1 * dstPitch) + pScrn->virtualX - y2; - srcPtr = (CARD16*)pI830->shadowPtr + - ((1 - y2) * srcPitch) + pbox->x1; - } else { - dstPtr = (CARD16*)pI830->FbBase + - ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; - srcPtr = (CARD16*)pI830->shadowPtr + - (y1 * srcPitch) + pbox->x2 - 1; - } - - while(width--) { - src = srcPtr; - dst = (CARD32*)dstPtr; - count = height; - while(count--) { - *(dst++) = src[0] | (src[srcPitch] << 16); - src += srcPitch * 2; - } - srcPtr += pI830->rotate; - dstPtr += dstPitch; - } - - pbox++; - } -} - - -/* this one could be faster */ -void -I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox) -{ - I830Ptr pI830 = I830PTR(pScrn); - int count, width, height, y1, y2, dstPitch, srcPitch; - CARD8 *dstPtr, *srcPtr, *src; - CARD32 *dst; - - dstPitch = BitmapBytePad(pScrn->displayWidth * 24); - srcPitch = -pI830->rotate * pI830->shadowPitch; - - while(num--) { - width = pbox->x2 - pbox->x1; - y1 = pbox->y1 & ~3; - y2 = (pbox->y2 + 3) & ~3; - height = (y2 - y1) >> 2; /* blocks of 3 dwords */ - - if(pI830->rotate == 1) { - dstPtr = pI830->FbBase + - (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3); - srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3); - } else { - dstPtr = pI830->FbBase + - ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3); - srcPtr = pI830->shadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3; - } - - while(width--) { - src = srcPtr; - dst = (CARD32*)dstPtr; - count = height; - while(count--) { - dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) | - (src[srcPitch] << 24); - dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) | - (src[srcPitch * 2] << 16) | - (src[(srcPitch * 2) + 1] << 24); - dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) | - (src[(srcPitch * 3) + 1] << 16) | - (src[(srcPitch * 3) + 2] << 24); - dst += 3; - src += srcPitch * 4; - } - srcPtr += pI830->rotate * 3; - dstPtr += dstPitch; - } - - pbox++; - } -} - -void -I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox) -{ - I830Ptr pI830 = I830PTR(pScrn); - int count, width, height, dstPitch, srcPitch; - CARD32 *dstPtr, *srcPtr, *src, *dst; - - dstPitch = pScrn->displayWidth; - srcPitch = -pI830->rotate * pI830->shadowPitch >> 2; - - while(num--) { - width = pbox->x2 - pbox->x1; - height = pbox->y2 - pbox->y1; - - if(pI830->rotate == 1) { - dstPtr = (CARD32*)pI830->FbBase + - (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2; - srcPtr = (CARD32*)pI830->shadowPtr + - ((1 - pbox->y2) * srcPitch) + pbox->x1; - } else { - dstPtr = (CARD32*)pI830->FbBase + - ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1; - srcPtr = (CARD32*)pI830->shadowPtr + - (pbox->y1 * srcPitch) + pbox->x2 - 1; - } - - while(width--) { - src = srcPtr; - dst = dstPtr; - count = height; - while(count--) { - *(dst++) = *src; - src += srcPitch; - } - srcPtr += pI830->rotate; - dstPtr += dstPitch; - } - - pbox++; - } -} diff --git a/src/i830_video.c b/src/i830_video.c index 12c25e05..28e95be9 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -73,7 +73,7 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86Pci.h" #include "xf86fbman.h" #include "regionstr.h" - +#include "randrstr.h" #include "i830.h" #include "xf86xv.h" #include <X11/extensions/Xv.h> @@ -114,12 +114,13 @@ static void I830BlockHandler(int, pointer, pointer, pointer); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) -static Atom xvBrightness, xvContrast, xvColorKey, xvPipe; +static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer; static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; -#define IMAGE_MAX_WIDTH 1440 +#define IMAGE_MAX_WIDTH 1920 #define IMAGE_MAX_HEIGHT 1080 -#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT) +#define IMAGE_MAX_WIDTH_LEGACY 1024 +#define IMAGE_MAX_HEIGHT_LEGACY 1080 #if !VIDEO_DEBUG #define ErrorF Edummy @@ -138,13 +139,13 @@ Edummy(const char *dummy, ...) * all modes of server exit. */ -#define OVERLAY_UPDATE \ +#define OVERLAY_UPDATE \ do { \ BEGIN_LP_RING(6); \ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \ OUT_RING(MI_NOOP); \ if (!*pI830->overlayOn) { \ - OUT_RING(MI_NOOP); \ + OUT_RING(MI_NOOP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON); \ ErrorF("Overlay goes from off to on\n"); \ @@ -154,7 +155,7 @@ Edummy(const char *dummy, ...) OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ } \ - OUT_RING(pI830->OverlayMem->Physical | 1); \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ ADVANCE_LP_RING(); \ ErrorF("OVERLAY_UPDATE\n"); \ } while(0) @@ -162,18 +163,28 @@ Edummy(const char *dummy, ...) #define OVERLAY_OFF \ do { \ if (*pI830->overlayOn) { \ - BEGIN_LP_RING(8); \ + int spin = 1000000; \ + BEGIN_LP_RING(12); \ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ + OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF); \ - OUT_RING(pI830->OverlayMem->Physical); \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ *pI830->overlayOn = FALSE; \ ErrorF("Overlay goes from on to off\n"); \ + while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){ \ + ErrorF("SPIN %d\n",spin); \ + spin--; \ + } \ + if (spin == 0) ErrorF("OVERLAY FAILED TO GO OFF\n"); \ ErrorF("OVERLAY_OFF\n"); \ } \ } while(0) @@ -181,6 +192,7 @@ Edummy(const char *dummy, ...) /* * OCMD - Overlay Command Register */ +#define OCMD_REGISTER 0x30168 #define MIRROR_MODE (0x3<<17) #define MIRROR_HORIZONTAL (0x1<<17) #define MIRROR_VERTICAL (0x2<<17) @@ -212,11 +224,15 @@ Edummy(const char *dummy, ...) #define FIELD1 (0x1<<1) #define OVERLAY_ENABLE 0x1 +#define OFC_UPDATE 0x1 + /* OCONFIG register */ #define CC_OUT_8BIT (0x1<<3) #define OVERLAY_PIPE_MASK (0x1<<18) #define OVERLAY_PIPE_A (0x0<<18) #define OVERLAY_PIPE_B (0x1<<18) +#define THREE_LINE_BUFFERS (0x1<<0) +#define TWO_LINE_BUFFERS (0x0<<0) /* DCLRKM register */ #define DEST_KEY_ENABLE (0x1<<31) @@ -260,11 +276,12 @@ static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 1, "XV_PIPE"} }; -#define NUM_ATTRIBUTES 3 +#define NUM_ATTRIBUTES 4 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, - {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} }; #define GAMMA_ATTRIBUTES 6 @@ -355,6 +372,7 @@ typedef struct { int brightness; int contrast; int pipe; + int doubleBuffer; RegionRec clip; CARD32 colorKey; @@ -390,7 +408,7 @@ CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size) for (i = 0; i < size; i += 4) { val = INREG(0x30100 + i); if (val != overlay[i / 4]) { - ErrorF("0x%05x value doesn't match (0x%08x != 0x%08x)\n", + ErrorF("0x%05x value doesn't match (0x%lx != 0x%lx)\n", 0x30100 + i, val, overlay[i / 4]); bad++; } @@ -463,7 +481,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); - DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%08x, obase: %p\n", + DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n", pI830->FbBase, pI830->OverlayMem->Start, overlay); /* * Default to maximum image size in YV12 @@ -475,10 +493,10 @@ I830ResetVideo(ScrnInfoPtr pScrn) overlay->HORZ_PH = 0; overlay->INIT_PHS = 0; overlay->DWINPOS = 0; - overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH; - overlay->SWIDTH = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 16); - overlay->SWIDTHSW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); - overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); + overlay->DWINSZ = 0; + overlay->SWIDTH = 0; + overlay->SWIDTHSW = 0; + overlay->SHEIGHT = 0; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); overlay->OCLRC1 = 0x00000080; /* saturation: bypass */ overlay->AWINPOS = 0; @@ -532,7 +550,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) { int i; for (i = 0x30000; i < 0x31000; i += 4) - ErrorF("0x%x 0x%08x\n", i, INREG(i)); + ErrorF("0x%x 0x%lx\n", i, INREG(i)); } #endif } @@ -602,10 +620,15 @@ I830SetupImageVideo(ScreenPtr pScreen) return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask; - adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; adapt->name = "Intel(R) Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = DummyEncoding; + /* update the DummyEncoding for these two chipsets */ + if (IS_845G(pI830) || IS_I830(pI830)) { + adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY; + adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY; + } adapt->nFormats = NUM_FORMATS; adapt->pFormats = Formats; adapt->nPorts = 1; @@ -617,7 +640,7 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->nAttributes = NUM_ATTRIBUTES; if (pI830->Clone) adapt->nAttributes += CLONE_ATTRIBUTES; - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) + if (IS_I9XX(pI830)) adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */ adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes); /* Now copy the attributes */ @@ -628,7 +651,7 @@ I830SetupImageVideo(ScreenPtr pScreen) memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES); att+=CLONE_ATTRIBUTES; } - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + if (IS_I9XX(pI830)) { memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES); att+=GAMMA_ATTRIBUTES; } @@ -658,6 +681,7 @@ I830SetupImageVideo(ScreenPtr pScreen) pPriv->gamma2 = 0x202020; pPriv->gamma1 = 0x101010; pPriv->gamma0 = 0x080808; + pPriv->doubleBuffer = 1; /* gotta uninit this someplace */ REGION_NULL(pScreen, &pPriv->clip); @@ -680,15 +704,16 @@ I830SetupImageVideo(ScreenPtr pScreen) pI830->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = I830BlockHandler; + xvColorKey = MAKE_ATOM("XV_COLORKEY"); xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); - xvColorKey = MAKE_ATOM("XV_COLORKEY"); + xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); /* Allow the pipe to be switched from pipe A to B when in clone mode */ if (pI830->Clone) xvPipe = MAKE_ATOM("XV_PIPE"); - - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + + if (IS_I9XX(pI830)) { xvGamma0 = MAKE_ATOM("XV_GAMMA0"); xvGamma1 = MAKE_ATOM("XV_GAMMA1"); xvGamma2 = MAKE_ATOM("XV_GAMMA2"); @@ -747,10 +772,12 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) if (shutdown) { if (pPriv->videoStatus & CLIENT_VIDEO_ON) { + overlay->OCMD &= ~OVERLAY_ENABLE; OVERLAY_UPDATE; - +#if 1 OVERLAY_OFF; +#endif if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; @@ -783,15 +810,23 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, return BadValue; pPriv->brightness = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - if (pPriv->overlayOK) - OVERLAY_UPDATE; + ErrorF("BRIGHTNESS\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif } else if (attribute == xvContrast) { if ((value < 0) || (value > 255)) return BadValue; pPriv->contrast = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - if (pPriv->overlayOK) - OVERLAY_UPDATE; + ErrorF("CONTRAST\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif } else if (pI830->Clone && attribute == xvPipe) { if ((value < 0) || (value > 1)) return BadValue; @@ -804,52 +839,36 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->OCONFIG |= OVERLAY_PIPE_A; else overlay->OCONFIG |= OVERLAY_PIPE_B; - if (pPriv->overlayOK) - OVERLAY_UPDATE; - } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - /* Avoid video anomalies, so set gamma registers when overlay is off */ - /* We also clamp the values if they are outside the ranges */ - if (!*pI830->overlayOn) { - pPriv->gamma0 = value; - if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) - pPriv->gamma1 = pPriv->gamma0 + 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma1 = value; - if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) - pPriv->gamma0 = pPriv->gamma1 - 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma2 = value; - if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) - pPriv->gamma3 = pPriv->gamma2 + 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma3 = value; - if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) - pPriv->gamma2 = pPriv->gamma3 - 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma4 = value; - if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) - pPriv->gamma5 = pPriv->gamma4 + 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma5 = value; - if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) - pPriv->gamma4 = pPriv->gamma5 - 0x7d; - } else - return BadRequest; + ErrorF("PIPE CHANGE\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif + } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { + pPriv->gamma0 = value; + if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) + pPriv->gamma1 = pPriv->gamma0 + 0x7d; + } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) { + pPriv->gamma1 = value; + if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) + pPriv->gamma0 = pPriv->gamma1 - 0x7d; + } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) { + pPriv->gamma2 = value; + if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) + pPriv->gamma3 = pPriv->gamma2 + 0x7d; + } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) { + pPriv->gamma3 = value; + if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) + pPriv->gamma2 = pPriv->gamma3 - 0x7d; + } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) { + pPriv->gamma4 = value; + if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) + pPriv->gamma5 = pPriv->gamma4 + 0x7d; + } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) { + pPriv->gamma5 = value; + if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) + pPriv->gamma4 = pPriv->gamma5 - 0x7d; } else if (attribute == xvColorKey) { pPriv->colorKey = value; switch (pScrn->depth) { @@ -863,9 +882,19 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->DCLRKV = pPriv->colorKey; break; } - if (pPriv->overlayOK) - OVERLAY_UPDATE; + ErrorF("COLORKEY\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else if(attribute == xvDoubleBuffer) { + if ((value < 0) || (value > 1)) + return BadValue; + /* Do not allow buffer change while playing video */ + if(!*pI830->overlayOn) + pPriv->doubleBuffer = value; } else return BadMatch; @@ -875,7 +904,13 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, attribute == xvGamma2 || attribute == xvGamma3 || attribute == xvGamma4 || - attribute == xvGamma5) && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + attribute == xvGamma5) && (IS_I9XX(pI830))) { + ErrorF("GAMMA\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif I830UpdateGamma(pScrn); } @@ -895,21 +930,23 @@ I830GetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->contrast; } else if (pI830->Clone && attribute == xvPipe) { *value = pPriv->pipe; - } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { *value = pPriv->gamma0; - } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) { *value = pPriv->gamma1; - } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) { *value = pPriv->gamma2; - } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) { *value = pPriv->gamma3; - } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) { *value = pPriv->gamma4; - } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) { *value = pPriv->gamma5; } else if (attribute == xvColorKey) { *value = pPriv->colorKey; - } else + } else if (attribute == xvDoubleBuffer) { + *value = pPriv->doubleBuffer; + } else return BadMatch; return Success; @@ -940,8 +977,10 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; unsigned char *src, *dst; + int i,j; + unsigned char *s; - DPRINTF(PFX, "I830CopyPackedData: (%d,%d) (%d,%d)\n" + ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n" "srcPitch: %d, dstPitch: %d\n", top, left, h, w, srcPitch, dstPitch); src = buf + (top * srcPitch) + (left << 1); @@ -951,11 +990,76 @@ I830CopyPackedData(ScrnInfoPtr pScrn, else dst = pI830->FbBase + pPriv->YBuf1offset; - w <<= 1; - while (h--) { - memcpy(dst, src, w); - src += srcPitch; - dst += dstPitch; + switch (pI830->rotation) { + case RR_Rotate_0: + w <<= 1; + for (i = 0; i < h; i++) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } + break; + case RR_Rotate_90: + h <<= 1; + for (i = 0; i < h; i+=2) { + s = src; + for (j = 0; j < w; j++) { + /* Copy Y */ + dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; + (void)*s++; + } + src += srcPitch; + } + h >>= 1; + src = buf + (top * srcPitch) + (left << 1); + for (i = 0; i < h; i+=2) { + for (j = 0; j < w; j+=2) { + /* Copy U */ + dst[((i*2) + 1) + ((w - j - 1) * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)]; + dst[((i*2) + 1) + ((w - j - 2) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)]; + /* Copy V */ + dst[((i*2) + 3) + ((w - j - 1) * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)]; + dst[((i*2) + 3) + ((w - j - 2) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)]; + } + } + break; + case RR_Rotate_180: + w <<= 1; + for (i = 0; i < h; i++) { + s = src; + for (j = 0; j < w; j+=4) { + dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = *s++; + dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = *s++; + dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = *s++; + dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = *s++; + } + src += srcPitch; + } + break; + case RR_Rotate_270: + h <<= 1; + for (i = 0; i < h; i+=2) { + s = src; + for (j = 0; j < w; j++) { + /* Copy Y */ + dst[(h - i - 2) + (j * dstPitch)] = *s++; + (void)*s++; + } + src += srcPitch; + } + h >>= 1; + src = buf + (top * srcPitch) + (left << 1); + for (i = 0; i < h; i+=2) { + for (j = 0; j < w; j+=2) { + /* Copy U */ + dst[(((h - i)*2) - 3) + (j * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)]; + dst[(((h - i)*2) - 3) + ((j - 1) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)]; + /* Copy V */ + dst[(((h - i)*2) - 1) + (j * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)]; + dst[(((h - i)*2) - 1) + ((j - 1) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)]; + } + } + break; } } @@ -966,8 +1070,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, { I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; - int i; + int i, j = 0; unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; + unsigned char *s; + int dstPitch2 = dstPitch << 1; ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n" "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, dstPitch, @@ -975,22 +1081,53 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, /* Copy Y data */ src1 = buf + (top * srcPitch) + left; - ErrorF("src1 is %p, offset is %d\n", src1, + ErrorF("src1 is %p, offset is %ld\n", src1, (unsigned long)src1 - (unsigned long)buf); if (pPriv->currentBuf == 0) dst1 = pI830->FbBase + pPriv->YBuf0offset; else dst1 = pI830->FbBase + pPriv->YBuf1offset; - for (i = 0; i < h; i++) { - memcpy(dst1, src1, w); - src1 += srcPitch; - dst1 += dstPitch << 1; + switch (pI830->rotation) { + case RR_Rotate_0: + for (i = 0; i < h; i++) { + memcpy(dst1, src1, w); + src1 += srcPitch; + dst1 += dstPitch2; + } + break; + case RR_Rotate_90: + for (i = 0; i < h; i++) { + s = src1; + for (j = 0; j < w; j++) { + dst1[(i) + ((w - j - 1) * dstPitch2)] = *s++; + } + src1 += srcPitch; + } + break; + case RR_Rotate_180: + for (i = 0; i < h; i++) { + s = src1; + for (j = 0; j < w; j++) { + dst1[(w - j - 1) + ((h - i - 1) * dstPitch2)] = *s++; + } + src1 += srcPitch; + } + break; + case RR_Rotate_270: + for (i = 0; i < h; i++) { + s = src1; + for (j = 0; j < w; j++) { + dst1[(h - i - 1) + (j * dstPitch2)] = *s++; + } + src1 += srcPitch; + } + break; } /* Copy V data for YV12, or U data for I420 */ src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1); - ErrorF("src2 is %p, offset is %d\n", src2, + ErrorF("src2 is %p, offset is %ld\n", src2, (unsigned long)src2 - (unsigned long)buf); if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) @@ -1004,16 +1141,47 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, dst2 = pI830->FbBase + pPriv->VBuf1offset; } - for (i = 0; i < h / 2; i++) { - memcpy(dst2, src2, w / 2); - src2 += srcPitch2; - dst2 += dstPitch; + switch (pI830->rotation) { + case RR_Rotate_0: + for (i = 0; i < h / 2; i++) { + memcpy(dst2, src2, w / 2); + src2 += srcPitch2; + dst2 += dstPitch; + } + break; + case RR_Rotate_90: + for (i = 0; i < (h/2); i++) { + s = src2; + for (j = 0; j < (w/2); j++) { + dst2[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++; + } + src2 += srcPitch2; + } + break; + case RR_Rotate_180: + for (i = 0; i < (h/2); i++) { + s = src2; + for (j = 0; j < (w/2); j++) { + dst2[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++; + } + src2 += srcPitch2; + } + break; + case RR_Rotate_270: + for (i = 0; i < (h/2); i++) { + s = src2; + for (j = 0; j < (w/2); j++) { + dst2[((h/2) - i - 1) + (j * dstPitch)] = *s++; + } + src2 += srcPitch2; + } + break; } /* Copy U data for YV12, or V data for I420 */ src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) + ((top * srcPitch) >> 2) + (left >> 1); - ErrorF("src3 is %p, offset is %d\n", src3, + ErrorF("src3 is %p, offset is %ld\n", src3, (unsigned long)src3 - (unsigned long)buf); if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) @@ -1027,10 +1195,41 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, dst3 = pI830->FbBase + pPriv->UBuf1offset; } - for (i = 0; i < h / 2; i++) { - memcpy(dst3, src3, w / 2); - src3 += srcPitch2; - dst3 += dstPitch; + switch (pI830->rotation) { + case RR_Rotate_0: + for (i = 0; i < h / 2; i++) { + memcpy(dst3, src3, w / 2); + src3 += srcPitch2; + dst3 += dstPitch; + } + break; + case RR_Rotate_90: + for (i = 0; i < (h/2); i++) { + s = src3; + for (j = 0; j < (w/2); j++) { + dst3[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++; + } + src3 += srcPitch2; + } + break; + case RR_Rotate_180: + for (i = 0; i < (h/2); i++) { + s = src3; + for (j = 0; j < (w/2); j++) { + dst3[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++; + } + src3 += srcPitch2; + } + break; + case RR_Rotate_270: + for (i = 0; i < (h/2); i++) { + s = src3; + for (j = 0; j < (w/2); j++) { + dst3[((h/2) - i - 1) + (j * dstPitch)] = *s++; + } + src3 += srcPitch2; + } + break; } } @@ -1175,6 +1374,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); unsigned int swidth; unsigned int mask, shift, offsety, offsetu; + int tmp; ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, dstPitch); @@ -1182,7 +1382,159 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, if (!pPriv->overlayOK) return; - if (IS_I915G(pI830) || IS_I915GM(pI830)) { +#if VIDEO_DEBUG + CompareOverlay(pI830, (CARD32 *) overlay, 0x100); +#endif + + /* When in dual head with different bpp setups we need to refresh the + * color key, so let's reset the video parameters and refresh here */ +#if 0 + if (pI830->entityPrivate) +#endif + I830ResetVideo(pScrn); + + /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */ + if (!*pI830->overlayOn) + OVERLAY_UPDATE; + + switch (pI830->rotation) { + case RR_Rotate_0: + dstBox->x1 -= pScrn->frameX0; + dstBox->x2 -= pScrn->frameX0; + dstBox->y1 -= pScrn->frameY0; + dstBox->y2 -= pScrn->frameY0; + break; + case RR_Rotate_90: + tmp = dstBox->x1; + dstBox->x1 = dstBox->y1 - pScrn->frameX0; + dstBox->y1 = pScrn->virtualY - tmp - pScrn->frameY0; + tmp = dstBox->x2; + dstBox->x2 = dstBox->y2 - pScrn->frameX0; + dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0; + tmp = dstBox->y1; + dstBox->y1 = dstBox->y2; + dstBox->y2 = tmp; + break; + case RR_Rotate_180: + tmp = dstBox->x1; + dstBox->x1 = pScrn->virtualX - dstBox->x2 - pScrn->frameX0; + dstBox->x2 = pScrn->virtualX - tmp - pScrn->frameX0; + tmp = dstBox->y1; + dstBox->y1 = pScrn->virtualY - dstBox->y2 - pScrn->frameY0; + dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0; + break; + case RR_Rotate_270: + tmp = dstBox->x1; + dstBox->x1 = pScrn->virtualX - dstBox->y1 - pScrn->frameX0; + dstBox->y1 = tmp - pScrn->frameY0; + tmp = dstBox->x2; + dstBox->x2 = pScrn->virtualX - dstBox->y2 - pScrn->frameX0; + dstBox->y2 = tmp - pScrn->frameY0; + tmp = dstBox->x1; + dstBox->x1 = dstBox->x2; + dstBox->x2 = tmp; + break; + } + + /* Fix up the dstBox if outside the visible screen */ + { + int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0; + int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0; + int offset, offset2; + + /* align */ + offset_x = (offset_x + 3) & ~3; + offset_y = (offset_y + 3) & ~3; + + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + height -= offset_x; + width -= offset_y; + } else { + height -= offset_y; + width -= offset_x; + } + + if (id == FOURCC_I420 || id == FOURCC_YV12) { + offset = ((offset_x/2) + (dstPitch * offset_y)) * 2; + offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y)); + } else { + offset = ((offset_x*2) + (dstPitch * offset_y)); + offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y)); + } + + /* buffer locations */ + pPriv->YBuf0offset += offset; + pPriv->UBuf0offset += offset2; + pPriv->VBuf0offset += offset2; + + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset += offset; + pPriv->UBuf1offset += offset2; + pPriv->VBuf1offset += offset2; + } + } + + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + tmp = width; + width = height; + height = tmp; + tmp = drw_w; + drw_w = drw_h; + drw_h = tmp; + tmp = src_w; + src_w = src_h; + src_h = tmp; + } + + if (pPriv->oneLineMode) { + /* change the coordinates with panel fitting active */ + dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1; + dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1; + + /* Now, alter the height, so we scale to the correct size */ + drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1; + } + + { + /* Keep the engine happy and clip to the real vertical size just + * in case an LFP is in use and it's not at it's native resolution. + */ + int vactive = pI830->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); + + vactive += 1; + + if (dstBox->y1 < 0) dstBox->y1 = 0; + if (dstBox->y2 < 0) dstBox->y2 = 0; + if (dstBox->x1 < 0) dstBox->x1 = 0; + if (dstBox->x2 < 0) dstBox->x2 = 0; + if (dstBox->y1 > vactive) dstBox->y1 = vactive; + if (dstBox->y2 > vactive) dstBox->y2 = vactive; + if (dstBox->x1 > pScrn->currentMode->HDisplay) dstBox->x1 = pScrn->currentMode->HDisplay - 1; + if (dstBox->x2 > pScrn->currentMode->HDisplay) dstBox->x2 = pScrn->currentMode->HDisplay - 1; + + /* nothing do to */ + if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) { + ErrorF("NOTHING TO DO\n"); + return; + } + if ((dstBox->x1 == (pScrn->currentMode->HDisplay - 1) && + dstBox->x2 == (pScrn->currentMode->HDisplay - 1)) || + (dstBox->y1 == vactive && + dstBox->y2 == vactive)) { + ErrorF("NOTHING TO DO\n"); + return; + } + if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) { + ErrorF("NOTHING TO DO\n"); + return; + } + if ((dstBox->x2 - dstBox->x1) <= 2) { + ErrorF("NOTHING TO DO\n"); + return; + } + } + + if (IS_I9XX(pI830)) { shift = 6; mask = 0x3f; } else { @@ -1198,17 +1550,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, offsetu = pPriv->UBuf1offset; } -#if VIDEO_DEBUG - CompareOverlay(pI830, (CARD32 *) overlay, 0x100); -#endif - - /* When in dual head with different bpp setups we need to refresh the - * color key, so let's reset the video parameters and refresh here */ -#if 0 - if (pI830->entityPrivate) -#endif - I830ResetVideo(pScrn); - switch (id) { case FOURCC_YV12: case FOURCC_I420: @@ -1221,7 +1562,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = ((offsety + width + mask) >> shift) - (offsety >> shift); - if (IS_I915G(pI830) || IS_I915GM(pI830)) + if (IS_I9XX(pI830)) swidth <<= 1; swidth -= 1; @@ -1233,7 +1574,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = ((offsetu + (width / 2) + mask) >> shift) - (offsetu >> shift); - if (IS_I915G(pI830) || IS_I915GM(pI830)) + if (IS_I9XX(pI830)) swidth <<= 1; swidth -= 1; @@ -1257,7 +1598,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = ((offsety + (width << 1) + mask) >> shift) - (offsety >> shift); - if (IS_I915G(pI830) || IS_I915GM(pI830)) + if (IS_I9XX(pI830)) swidth <<= 1; swidth -= 1; @@ -1272,19 +1613,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, break; } - if (pPriv->oneLineMode) { - /* change the coordinates with panel fitting active */ - dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1; - dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1; - - /* Now, alter the height, so we scale to the correct size */ - drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1; - - /* Keep the engine happy */ - if (dstBox->y1 < 0) dstBox->y1 = 0; - if (dstBox->y2 < 0) dstBox->y2 = 0; - } - + overlay->OCMD = OVERLAY_ENABLE; overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1; @@ -1299,13 +1628,15 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, overlay->OBUF_0U = pPriv->UBuf0offset; overlay->OBUF_0V = pPriv->VBuf0offset; - overlay->OBUF_1Y = pPriv->YBuf1offset; - overlay->OBUF_1U = pPriv->UBuf1offset; - overlay->OBUF_1V = pPriv->VBuf1offset; + if(pPriv->doubleBuffer) { + overlay->OBUF_1Y = pPriv->YBuf1offset; + overlay->OBUF_1U = pPriv->UBuf1offset; + overlay->OBUF_1V = pPriv->VBuf1offset; + } - ErrorF("Buffers: Y0: 0x%08x, U0: 0x%08x, V0: 0x%08x\n", overlay->OBUF_0Y, + ErrorF("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", overlay->OBUF_0Y, overlay->OBUF_0U, overlay->OBUF_0V); - ErrorF("Buffers: Y1: 0x%08x, U1: 0x%08x, V1: 0x%08x\n", overlay->OBUF_1Y, + ErrorF("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", overlay->OBUF_1Y, overlay->OBUF_1U, overlay->OBUF_1V); #if 0 @@ -1330,11 +1661,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, } #endif -#if 1 - overlay->OCMD = OVERLAY_ENABLE; -#endif - - ErrorF("pos: 0x%08x, size: 0x%08x\n", overlay->DWINPOS, overlay->DWINSZ); + ErrorF("pos: 0x%lx, size: 0x%lx\n", overlay->DWINPOS, overlay->DWINSZ); ErrorF("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h); /* @@ -1383,6 +1710,18 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, ErrorF("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV, xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF); + /* shouldn't get here */ + if (xscaleInt > 7) { + ErrorF("xscale: bad scale\n"); + return; + } + + /* shouldn't get here */ + if (xscaleIntUV > 7) { + ErrorF("xscaleUV: bad scale\n"); + return; + } + newval = (xscaleInt << 16) | ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20); if (newval != overlay->YRGBSCALE) { @@ -1480,7 +1819,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, else overlay->OCMD |= BUFFER1; - ErrorF("OCMD is 0x%08x\n", overlay->OCMD); + ErrorF("OCMD is 0x%lx\n", overlay->OCMD); OVERLAY_UPDATE; } @@ -1489,7 +1828,7 @@ static FBLinearPtr I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) { ScreenPtr pScreen; - FBLinearPtr new_linear; + FBLinearPtr new_linear = NULL; DPRINTF(PFX, "I830AllocateMemory\n"); @@ -1514,8 +1853,10 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME); - if (max_size < size) + if (max_size < size) { + ErrorF("No memory available\n"); return NULL; + } xf86PurgeUnlockedOffscreenAreas(pScreen); new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, @@ -1538,6 +1879,8 @@ I830PutImage(ScrnInfoPtr pScrn, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = (I830PortPrivPtr) data; ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + I830OverlayRegPtr overlay = + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); INT32 x1, x2, y1, y2; int srcPitch, srcPitch2 = 0, dstPitch; int top, left, npixels, nlines, size, loops; @@ -1585,68 +1928,106 @@ I830PutImage(ScrnInfoPtr pScrn, width, height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - switch (id) { case FOURCC_YV12: case FOURCC_I420: srcPitch = (width + 3) & ~3; srcPitch2 = ((width >> 1) + 3) & ~3; - dstPitch = ((width / 2) + 63) & ~63; /* of chroma */ - size = dstPitch * height * 3; +#if 1 + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height / 2) + 63) & ~63; + size = dstPitch * width * 3; + } else { + dstPitch = ((width / 2) + 63) & ~63; /* of chroma */ + size = dstPitch * height * 3; + } +#else + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height / 2) + 511) & ~511; + size = dstPitch * width * 3; + } else { + dstPitch = ((width / 2) + 511) & ~511; /* of chroma */ + size = dstPitch * height * 3; + } +#endif break; case FOURCC_UYVY: case FOURCC_YUY2: default: srcPitch = width << 1; - dstPitch = (srcPitch + 63) & ~63; /* of chroma */ - size = dstPitch * height; +#if 1 + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height << 1) + 63) & ~63; + size = dstPitch * width; + } else { + dstPitch = ((width << 1) + 63) & ~63; /* of chroma */ + size = dstPitch * height; + } +#else + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height << 1) + 511) & ~511; + size = dstPitch * width; + } else { + dstPitch = ((width << 1) + 511) & ~511; /* of chroma */ + size = dstPitch * height; + } +#endif break; } ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size); /* size is multiplied by 2 because we have two buffers that are flipping */ - if (!(pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, size * 2 / pI830->cpp))) + pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, + (pPriv->doubleBuffer ? size * 2 : size) / pI830->cpp); + + if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY)) return BadAlloc; /* fixup pointers */ - pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp; - pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); - pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2); - - pPriv->YBuf1offset = pPriv->YBuf0offset + size; - pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); - pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2); - - /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead - * of this code....*/ + pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp; + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); + pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2); + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset = pPriv->YBuf0offset + size; + pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width); + pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2); + } + } else { + pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); + pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2); + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset = pPriv->YBuf0offset + size; + pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); + pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2); + } + } /* Make sure this buffer isn't in use */ loops = 0; - while (loops < 1000000) { + if (*pI830->overlayOn && pPriv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) { + while (loops < 1000000) { #if USE_USLEEP_FOR_VIDEO - usleep(10); + usleep(10); #endif - if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) { - break; + if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) { + break; + } + loops++; } - loops++; - } - if (loops >= 1000000) { - ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf); + if (loops >= 1000000) { + ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf); #if 0 - pPriv->currentBuf = !pPriv->currentBuf; + pPriv->currentBuf = !pPriv->currentBuf; #endif - } + } - /* buffer swap */ - if (pPriv->currentBuf == 0) - pPriv->currentBuf = 1; - else - pPriv->currentBuf = 0; + /* buffer swap */ + if (pPriv->currentBuf == 0) + pPriv->currentBuf = 1; + else + pPriv->currentBuf = 0; + } /* copy data */ top = y1 >> 16; @@ -1690,14 +2071,22 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, unsigned short *w, unsigned short *h, int *pitches, int *offsets) { + I830Ptr pI830 = I830PTR(pScrn); int size, tmp; - DPRINTF(PFX, "I830QueryImageAttributes: w is %d, h is %d\n", *w, *h); + ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h); + if (IS_845G(pI830) || IS_I830(pI830)) { + if (*w > IMAGE_MAX_WIDTH_LEGACY) + *w = IMAGE_MAX_WIDTH_LEGACY; + if (*h > IMAGE_MAX_HEIGHT_LEGACY) + *h = IMAGE_MAX_HEIGHT_LEGACY; + } else { if (*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; if (*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; + } *w = (*w + 1) & ~1; if (offsets) @@ -1767,24 +2156,25 @@ I830BlockHandler(int i, pScreen->BlockHandler = I830BlockHandler; if (pPriv->videoStatus & TIMER_MASK) { - UpdateCurrentTime(); + Time now = currentTime.milliseconds; if (pPriv->videoStatus & OFF_TIMER) { - if (pPriv->offTime < currentTime.milliseconds) { + if (pPriv->offTime < now) { /* Turn off the overlay */ + ErrorF("BLOCKHANDLER\n"); overlay->OCMD &= ~OVERLAY_ENABLE; - - OVERLAY_UPDATE; - - OVERLAY_OFF; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif pPriv->videoStatus = FREE_TIMER; - pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + pPriv->freeTime = now + FREE_DELAY; if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; } } else { /* FREE_TIMER */ - if (pPriv->freeTime < currentTime.milliseconds) { + if (pPriv->freeTime < now) { if (pPriv->linear) { xf86FreeOffscreenLinear(pPriv->linear); pPriv->linear = NULL; @@ -1815,9 +2205,18 @@ I830AllocateSurface(ScrnInfoPtr pScrn, OffscreenPrivPtr pPriv; I830Ptr pI830 = I830PTR(pScrn); - DPRINTF(PFX, "I830AllocateSurface\n"); + ErrorF("I830AllocateSurface\n"); + + if (IS_845G(pI830) || IS_I830(pI830)) { + if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY)) + return BadAlloc; + } else { + if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT)) + return BadAlloc; + } - if ((w > 1024) || (h > 1024)) + /* What to do when rotated ?? */ + if (pI830->rotation != RR_Rotate_0) return BadAlloc; w = (w + 1) & ~1; @@ -1857,7 +2256,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn, surface->offsets[0] = linear->offset * bpp; surface->devPrivate.ptr = (pointer) pPriv; - memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size); + memset(pI830->FbBase + pI830->FrontBuffer.Start + surface->offsets[0], 0, size); return Success; } @@ -1874,11 +2273,12 @@ I830StopSurface(XF86SurfacePtr surface) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + ErrorF("StopSurface\n"); overlay->OCMD &= ~OVERLAY_ENABLE; - OVERLAY_UPDATE; - +#if 1 OVERLAY_OFF; +#endif if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; @@ -1929,11 +2329,13 @@ I830DisplaySurface(XF86SurfacePtr surface, ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn); + I830OverlayRegPtr overlay = + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); INT32 x1, y1, x2, y2; INT32 loops = 0; BoxRec dstBox; - DPRINTF(PFX, "I830DisplaySurface\n"); + ErrorF("I830DisplaySurface\n"); if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && @@ -1965,35 +2367,35 @@ I830DisplaySurface(XF86SurfacePtr surface, surface->width, surface->height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - /* fixup pointers */ pI830Priv->YBuf0offset = surface->offsets[0]; pI830Priv->YBuf1offset = pI830Priv->YBuf0offset; - /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead - * of this code....*/ - - /* wait for the last rendered buffer to be flipped in */ - while (((INREG(DOVSTA) & OC_BUF) >> 20) != pI830Priv->currentBuf) { + /* Make sure this buffer isn't in use */ + loops = 0; + if (*pI830->overlayOn && pI830Priv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) { + while (loops < 1000000) { #if USE_USLEEP_FOR_VIDEO - usleep(10); + usleep(10); +#endif + if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) { + break; + } + loops++; + } + if (loops >= 1000000) { + ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf); +#if 0 + pI830Priv->currentBuf = !pI830Priv->currentBuf; #endif - if (loops == 200000) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n"); - break; } - loops++; - } - /* buffer swap */ - if (pI830Priv->currentBuf == 0) - pI830Priv->currentBuf = 1; - else - pI830Priv->currentBuf = 0; + /* buffer swap */ + if (pI830Priv->currentBuf == 0) + pI830Priv->currentBuf = 1; + else + pI830Priv->currentBuf = 0; + } I830DisplayVideo(pScrn, surface->id, surface->width, surface->height, surface->pitches[0], x1, y1, x2, y2, &dstBox, @@ -2018,6 +2420,8 @@ static void I830InitOffscreenImages(ScreenPtr pScreen) { XF86OffscreenImagePtr offscreenImages; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); /* need to free this someplace */ if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) { @@ -2025,15 +2429,20 @@ I830InitOffscreenImages(ScreenPtr pScreen) } offscreenImages[0].image = &Images[0]; - offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; offscreenImages[0].alloc_surface = I830AllocateSurface; offscreenImages[0].free_surface = I830FreeSurface; offscreenImages[0].display = I830DisplaySurface; offscreenImages[0].stop = I830StopSurface; offscreenImages[0].setAttribute = I830SetSurfaceAttribute; offscreenImages[0].getAttribute = I830GetSurfaceAttribute; - offscreenImages[0].max_width = 1024; - offscreenImages[0].max_height = 1024; + if (IS_845G(pI830) || IS_I830(pI830)) { + offscreenImages[0].max_width = IMAGE_MAX_WIDTH_LEGACY; + offscreenImages[0].max_height = IMAGE_MAX_HEIGHT_LEGACY; + } else { + offscreenImages[0].max_width = IMAGE_MAX_WIDTH; + offscreenImages[0].max_height = IMAGE_MAX_HEIGHT; + } offscreenImages[0].num_attributes = 1; offscreenImages[0].attributes = Attributes; @@ -2043,9 +2452,10 @@ I830InitOffscreenImages(ScreenPtr pScreen) void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) { + I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv; - if (!I830PTR(pScrn)->adaptor) { + if (!pI830->adaptor) { return; } @@ -2062,6 +2472,8 @@ I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) */ I830StopVideo(pScrn, pPriv, TRUE); + pPriv->overlayOK = FALSE; + pPriv->oneLineMode = FALSE; } @@ -2079,6 +2491,17 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) if (!pPriv) return; + pPriv->overlayOK = TRUE; + + /* ensure pipe is updated on mode switch */ + if (!pI830->Clone) { + if (pPriv->pipe != pI830->pipe) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Changing XVideo pipe (%d to %d).\n", pPriv->pipe, pI830->pipe); + pPriv->pipe = pI830->pipe; + } + } + if (pPriv->pipe == 0) { if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, |