apm_cursor.c revision 17a48c7c
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_cursor.c,v 1.14 2000/06/30 18:27:02 dawes Exp $ */ 2 3#ifdef HAVE_CONFIG_H 4#include "config.h" 5#endif 6 7#include <X11/X.h> 8#include <X11/Xproto.h> 9#include "misc.h" 10#include "input.h" 11#include "cursorstr.h" 12#include "regionstr.h" 13#include "scrnintstr.h" 14#include "servermd.h" 15#include "windowstr.h" 16#include "mfb.h" 17#include "mipointer.h" 18 19#include "apm.h" 20 21#define CURSORWIDTH 64 22#define CURSORHEIGHT 64 23#define CURSORSIZE (CURSORWIDTH * CURSORHEIGHT / 8) 24#define CURSORALIGN ((CURSORSIZE + 1023) & ~1023l) 25 26static void ApmShowCursor(ScrnInfoPtr pScrn); 27static void ApmHideCursor(ScrnInfoPtr pScrn); 28static void ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y); 29static void ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg); 30static void ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data); 31static Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs); 32 33static u8 ConvertTable[256]; 34 35/* Inline functions */ 36static __inline__ void 37WaitForFifo(ApmPtr pApm, int slots) 38{ 39 if (!pApm->UsePCIRetry) { 40 volatile int i; 41#define MAXLOOP 1000000 42 43 for(i = 0; i < MAXLOOP; i++) { 44 if ((STATUS() & STATUS_FIFO) >= slots) 45 break; 46 } 47 if (i == MAXLOOP) { 48 unsigned int status = STATUS(); 49 50 WRXB(0x1FF, 0); 51 if (!xf86ServerIsExiting()) 52 FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status); 53 } 54 } 55} 56 57void ApmHWCursorReserveSpace(ApmPtr pApm) 58{ 59 pApm->OffscreenReserved += 2 * CURSORALIGN; 60 pApm->DisplayedCursorAddress = pApm->BaseCursorAddress = 61 pApm->CursorAddress = 1024 * xf86Screens[pApm->pScreen->myNum]->videoRam - 62 pApm->OffscreenReserved; 63} 64 65 66int ApmHWCursorInit(ScreenPtr pScreen) 67{ 68 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 69 APMDECL(pScrn); 70 xf86CursorInfoPtr infoPtr; 71 u32 i; 72 73 infoPtr = xf86CreateCursorInfoRec(); 74 if (!infoPtr) 75 return FALSE; 76 77 pApm->CursorInfoRec = infoPtr; 78 79 infoPtr->MaxWidth = CURSORWIDTH; 80 infoPtr->MaxHeight = CURSORHEIGHT; 81 82 infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1; 83 infoPtr->SetCursorColors = ApmSetCursorColors; 84 infoPtr->SetCursorPosition = ApmSetCursorPosition; 85 infoPtr->LoadCursorImage = ApmLoadCursorImage; 86 infoPtr->HideCursor = ApmHideCursor; 87 infoPtr->ShowCursor = ApmShowCursor; 88 infoPtr->UseHWCursor = ApmUseHWCursor; 89 90 /* Set up the convert table for the input cursor data */ 91 for (i = 0; i < 256; i++) 92 ConvertTable[i] = ((~i) & 0xAA) | (i & (i >> 1) & 0x55); 93 94 return xf86InitCursor(pScreen, infoPtr); 95} 96 97 98static void 99ApmShowCursor(ScrnInfoPtr pScrn) 100{ 101 APMDECL(pScrn); 102 103 WaitForFifo(pApm, 2); 104 WRXW(0x144, pApm->CursorAddress >> 10); 105 WRXB(0x140, 1); 106 pApm->DisplayedCursorAddress = pApm->CursorAddress; 107} 108 109 110static void 111ApmHideCursor(ScrnInfoPtr pScrn) 112{ 113 APMDECL(pScrn); 114 115 WaitForFifo(pApm, 1); 116 WRXB(0x140, 0); 117} 118 119static Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 120{ 121 return APMPTR(xf86Screens[pScreen->myNum])->CurrentLayout.bitsPerPixel >= 8; 122} 123 124static void 125ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 126{ 127 APMDECL(pScrn); 128 int xoff, yoff; 129 130 if (x < -CURSORWIDTH || y < -CURSORHEIGHT) { 131 WaitForFifo(pApm, 1); 132 WRXB(0x140, 0); 133 return; 134 } 135 136 if (x < 0) { 137 xoff = -x; 138 x = 0; 139 } 140 else 141 xoff = 0; 142 if (y < 0) { 143 yoff = -y; 144 y = 0; 145 } 146 else 147 yoff = 0; 148 149 WaitForFifo(pApm, 2); 150 WRXW(0x14C, (yoff << 8) | (xoff & 0xFF)); 151 WRXL(0x148, (y << 16) | (x & 0xFFFF)); 152} 153 154 155static void 156ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 157{ 158 APMDECL(pScrn); 159 u16 packedcolfg, packedcolbg; 160 161 if (pApm->CurrentLayout.bitsPerPixel == 8) 162 { 163 WaitForFifo(pApm, 2); 164 WRXB(0x141, fg); 165 WRXB(0x142, bg); 166 } 167 else 168 { 169 packedcolfg = 170 ((fg & 0xE00000) >> 16) | 171 ((fg & 0x00E000) >> 11) | 172 ((fg & 0x0000C0) >> 6); 173 packedcolbg = 174 ((bg & 0xE00000) >> 16) | 175 ((bg & 0x00E000) >> 11) | 176 ((bg & 0x0000C0) >> 6); 177 WaitForFifo(pApm, 2); 178 WRXB(0x141, packedcolfg); 179 WRXB(0x142, packedcolbg); 180 } 181} 182 183 184static void 185ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data) 186{ 187 APMDECL(pScrn); 188 u32 i; 189 u8 tmp[2 * CURSORSIZE]; 190 191 /* Correct input data */ 192 for (i = 0; i < sizeof tmp; i++) 193 tmp[i] = ConvertTable[data[i]]; 194 /* 195 * To avoid flicker. 196 * Note: 2*pApm->BaseCursorAddress + CURSORALIGN (=1024) < 2^31 all the time. 197 */ 198 pApm->CursorAddress = 2*pApm->BaseCursorAddress + CURSORALIGN - pApm->DisplayedCursorAddress; 199 memcpy((u8*)pApm->FbBase + pApm->CursorAddress, tmp, sizeof tmp); 200} 201