ast_cursor.c revision 83cab373
1/* 2 * Copyright (c) 2005 ASPEED Technology Inc. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of the authors not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. The authors makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include <config.h> 25#endif 26#include "xf86.h" 27#include "xf86_OSproc.h" 28#include "xf86cmap.h" 29#include "compiler.h" 30#include "mibstore.h" 31#include "vgaHW.h" 32#include "mipointer.h" 33#include "micmap.h" 34 35#include "fb.h" 36#include "regionstr.h" 37#include "xf86xv.h" 38#include <X11/extensions/Xv.h> 39#include "vbe.h" 40 41#include "xf86PciInfo.h" 42#include "xf86Pci.h" 43 44/* framebuffer offscreen manager */ 45#include "xf86fbman.h" 46 47/* include xaa includes */ 48#include "xaa.h" 49#include "xaarop.h" 50 51/* H/W cursor support */ 52#include "xf86Cursor.h" 53#include "cursorstr.h" 54 55/* Driver specific headers */ 56#include "ast.h" 57 58#ifdef HWC 59/* Prototype type declaration */ 60Bool ASTCursorInit(ScreenPtr pScreen); 61Bool bInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST); 62static void ASTShowCursor(ScrnInfoPtr pScrn); 63void ASTHideCursor(ScrnInfoPtr pScrn); 64static void ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y); 65static void ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg); 66static void ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src); 67static Bool ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs); 68static void ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs); 69static Bool ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs); 70 71static void ASTFireCursor(ScrnInfoPtr pScrn); 72 73Bool 74ASTCursorInit(ScreenPtr pScreen) 75{ 76 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 77 ASTRecPtr pAST = ASTPTR(pScrn); 78 xf86CursorInfoPtr infoPtr; 79 80 infoPtr = xf86CreateCursorInfoRec(); 81 if(!infoPtr) return FALSE; 82 83 pAST->HWCInfoPtr = infoPtr; 84 85 infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 86 HARDWARE_CURSOR_INVERT_MASK | 87 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST; 88 89 infoPtr->MaxWidth = MAX_HWC_WIDTH; 90 infoPtr->MaxHeight = MAX_HWC_HEIGHT; 91 infoPtr->ShowCursor = ASTShowCursor; 92 infoPtr->HideCursor = ASTHideCursor; 93 infoPtr->SetCursorPosition = ASTSetCursorPosition; 94 infoPtr->SetCursorColors = ASTSetCursorColors; 95 infoPtr->LoadCursorImage = ASTLoadCursorImage; 96 infoPtr->UseHWCursor = ASTUseHWCursor; 97#ifdef ARGB_CURSOR 98 infoPtr->UseHWCursorARGB = ASTUseHWCursorARGB; 99 infoPtr->LoadCursorARGB = ASTLoadCursorARGB; 100#endif 101 102 return(xf86InitCursor(pScreen, infoPtr)); 103 104} 105 106Bool bInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST) 107{ 108 ScreenPtr pScreen; 109 110 /* init cursor cache info */ 111 /* Set HWC_NUM in Options instead */ 112 /* pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM; */ 113 pAST->HWCInfo.HWC_NUM_Next = 0; 114 115 /* allocate HWC cache */ 116 if (!pAST->pHWCPtr) { 117 pScreen = screenInfo.screens[pScrn->scrnIndex]; 118 pAST->pHWCPtr = xf86AllocateOffscreenLinear (pScreen, (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM, HWC_ALIGN, NULL, NULL, NULL); 119 120 if (!pAST->pHWCPtr) { 121 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Allocate HWC Cache failed \n"); 122 return (FALSE); 123 } 124 125 pAST->HWCInfo.ulHWCOffsetAddr = pAST->pHWCPtr->offset*((pScrn->bitsPerPixel + 1) / 8); 126 pAST->HWCInfo.pjHWCVirtualAddr = pAST->FBVirtualAddr + pAST->HWCInfo.ulHWCOffsetAddr; 127 } 128 129 return (TRUE); 130} 131 132 133static void 134ASTShowCursor(ScrnInfoPtr pScrn) 135{ 136 ASTRecPtr pAST = ASTPTR(pScrn); 137 UCHAR jReg; 138 139 jReg= 0x02; 140 if (pAST->HWCInfo.cursortype ==HWC_COLOR) 141 jReg |= 0x01; 142 143 SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, jReg); /* enable mono */ 144 145} 146 147void 148ASTHideCursor(ScrnInfoPtr pScrn) 149{ 150 ASTRecPtr pAST = ASTPTR(pScrn); 151 152 SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, 0x00); /* disable HWC */ 153 154} 155 156static void 157ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 158{ 159 ASTRecPtr pAST = ASTPTR(pScrn); 160 DisplayModePtr mode = pAST->ModePtr; 161 int x_offset, y_offset; 162 UCHAR *pjSignature; 163 164 /* Set cursor info to Offscreen */ 165 pjSignature = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE; 166 *((ULONG *) (pjSignature + HWC_SIGNATURE_X)) = x; 167 *((ULONG *) (pjSignature + HWC_SIGNATURE_Y)) = y; 168 169 x_offset = pAST->HWCInfo.offset_x; 170 y_offset = pAST->HWCInfo.offset_y; 171 172 if(x < 0) { 173 x_offset = (-x) + pAST->HWCInfo.offset_x; 174 x = 0; 175 } 176 177 if(y < 0) { 178 y_offset = (-y) + pAST->HWCInfo.offset_y; 179 y = 0; 180 } 181 182 if(mode->Flags & V_DBLSCAN) y *= 2; 183 184 /* Set to Reg. */ 185 SetIndexReg(CRTC_PORT, 0xC2, (UCHAR) (x_offset)); 186 SetIndexReg(CRTC_PORT, 0xC3, (UCHAR) (y_offset)); 187 SetIndexReg(CRTC_PORT, 0xC4, (UCHAR) (x & 0xFF)); 188 SetIndexReg(CRTC_PORT, 0xC5, (UCHAR) ((x >> 8) & 0x0F)); 189 SetIndexReg(CRTC_PORT, 0xC6, (UCHAR) (y & 0xFF)); 190 SetIndexReg(CRTC_PORT, 0xC7, (UCHAR) ((y >> 8) & 0x07)); 191 192 /* Fire HWC */ 193 ASTFireCursor(pScrn); 194 195} 196 197static void 198ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 199{ 200 ASTRecPtr pAST = ASTPTR(pScrn); 201 ULONG fg1, bg1; 202 203 fg1 = (fg & 0x0F) | (((fg>>8) & 0x0F) << 4) | (((fg>>16) & 0x0F) << 8); 204 bg1 = (bg & 0x0F) | (((bg>>8) & 0x0F) << 4) | (((bg>>16) & 0x0F) << 8); 205 206 /* Fixed xorg bugzilla #20609, ycchen@031209 */ 207 if ( (fg1 != pAST->HWCInfo.fg) || (bg1 != pAST->HWCInfo.bg) ) 208 { 209 pAST->HWCInfo.fg = fg1; 210 pAST->HWCInfo.bg = bg1; 211 ASTLoadCursorImage(pScrn, pAST->HWCInfo.cursorpattern); 212 } 213 214} 215 216static void 217ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src) 218{ 219 ASTRecPtr pAST = ASTPTR(pScrn); 220 int i, j, k; 221 UCHAR *pjSrcAnd, *pjSrcXor, *pjDstData; 222 ULONG ulTempDstAnd32[2], ulTempDstXor32[2], ulTempDstData32[2]; 223 UCHAR jTempSrcAnd32, jTempSrcXor32; 224 ULONG ulCheckSum = 0; 225 ULONG ulPatternAddr; 226 227 /* init cursor info. */ 228 pAST->HWCInfo.cursortype = HWC_MONO; 229 pAST->HWCInfo.width = (USHORT) MAX_HWC_WIDTH; 230 pAST->HWCInfo.height = (USHORT) MAX_HWC_HEIGHT; 231 pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width; 232 pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height; 233 234 /* copy to hwc info */ 235 for (i=0; i< MAX_HWC_WIDTH*MAX_HWC_HEIGHT/4; i+=4) 236 *(ULONG *) (pAST->HWCInfo.cursorpattern + i) = *(ULONG *) (src + i); 237 238 /* copy cursor image to cache */ 239 pjSrcXor = src; 240 pjSrcAnd = src + (MAX_HWC_WIDTH*MAX_HWC_HEIGHT/8); 241 pjDstData = pAST->HWCInfo.pjHWCVirtualAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next; 242 243 for (j = 0; j < MAX_HWC_HEIGHT; j++) 244 { 245 for (i = 0; i < (MAX_HWC_WIDTH/8); i++ ) 246 { 247 for (k=7; k>0; k-=2) 248 { 249 jTempSrcAnd32 = *((UCHAR *) pjSrcAnd); 250 jTempSrcXor32 = *((UCHAR *) pjSrcXor); 251 ulTempDstAnd32[0] = ((jTempSrcAnd32 >> k) & 0x01) ? 0x00008000L:0x00L; 252 ulTempDstXor32[0] = ((jTempSrcXor32 >> k) & 0x01) ? 0x00004000L:0x00L; 253 ulTempDstData32[0] = ((jTempSrcXor32 >> k) & 0x01) ? pAST->HWCInfo.fg:pAST->HWCInfo.bg; 254 ulTempDstAnd32[1] = ((jTempSrcAnd32 >> (k-1)) & 0x01) ? 0x80000000L:0x00L; 255 ulTempDstXor32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? 0x40000000L:0x00L; 256 ulTempDstData32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? (pAST->HWCInfo.fg << 16):(pAST->HWCInfo.bg << 16); 257 /* No inverse for X Window cursor, ycchen@111808 */ 258 if (ulTempDstAnd32[0]) 259 ulTempDstXor32[0] = 0; 260 if (ulTempDstAnd32[1]) 261 ulTempDstXor32[1] = 0; 262 *((ULONG *) pjDstData) = ulTempDstAnd32[0] | ulTempDstXor32[0] | ulTempDstData32[0] | ulTempDstAnd32[1] | ulTempDstXor32[1] | ulTempDstData32[1]; 263 ulCheckSum += *((ULONG *) pjDstData); 264 pjDstData += 4; 265 266 } 267 pjSrcAnd ++; 268 pjSrcXor ++; 269 270 } 271 272 } 273 274 /* Write Checksum as signature */ 275 pjDstData = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE; 276 *((ULONG *) pjDstData) = ulCheckSum; 277 *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width; 278 *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height; 279 *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTX)) = 0; 280 *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTY)) = 0; 281 282 /* set pattern offset */ 283 ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3); 284 SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF)); 285 SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF)); 286 SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF)); 287 288 /* update HWC_NUM_Next */ 289 pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM; 290 291} 292 293static Bool 294ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 295{ 296 if ( (pCurs->bits->width > MAX_HWC_WIDTH) || (pCurs->bits->height > MAX_HWC_HEIGHT) ) 297 return FALSE; 298 299 return TRUE; 300} 301 302static void 303ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) 304{ 305 ASTRecPtr pAST = ASTPTR(pScrn); 306 307 UCHAR *pjDstXor, *pjSrcXor; 308 ULONG i, j, ulSrcWidth, ulSrcHeight; 309 ULONG ulPerPixelCopy, ulTwoPixelCopy; 310 LONG lAlphaDstDelta, lLastAlphaDstDelta; 311 union 312 { 313 ULONG ul; 314 UCHAR b[4]; 315 } ulSrcData32[2], ulData32; 316 union 317 { 318 USHORT us; 319 UCHAR b[2]; 320 } usData16; 321 ULONG ulCheckSum = 0; 322 ULONG ulPatternAddr; 323 324 /* init cursor info. */ 325 pAST->HWCInfo.cursortype = HWC_COLOR; 326 pAST->HWCInfo.width = pCurs->bits->width; 327 pAST->HWCInfo.height = pCurs->bits->height; 328 pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width; 329 pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height; 330 331 /* copy cursor image to cache */ 332 ulSrcWidth = pAST->HWCInfo.width; 333 ulSrcHeight = pAST->HWCInfo.height; 334 335 lAlphaDstDelta = MAX_HWC_WIDTH << 1; 336 lLastAlphaDstDelta = lAlphaDstDelta - (ulSrcWidth << 1); 337 338 pjSrcXor = (UCHAR *) pCurs->bits->argb;; 339 pjDstXor = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next 340 + lLastAlphaDstDelta + (MAX_HWC_HEIGHT - ulSrcHeight) * lAlphaDstDelta; 341 342 ulPerPixelCopy = ulSrcWidth & 1; 343 ulTwoPixelCopy = ulSrcWidth >> 1; 344 345 for (j = 0; j < ulSrcHeight; j++) 346 { 347 348 for (i = 0; i < ulTwoPixelCopy; i++ ) 349 { 350 ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0; 351 ulSrcData32[1].ul = *((ULONG *) (pjSrcXor+4)) & 0xF0F0F0F0; 352 ulData32.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4); 353 ulData32.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4); 354 ulData32.b[2] = ulSrcData32[1].b[1] | (ulSrcData32[1].b[0] >> 4); 355 ulData32.b[3] = ulSrcData32[1].b[3] | (ulSrcData32[1].b[2] >> 4); 356 *((ULONG *) pjDstXor) = ulData32.ul; 357 ulCheckSum += (ULONG) ulData32.ul; 358 pjDstXor += 4; 359 pjSrcXor += 8; 360 } 361 362 for (i = 0; i < ulPerPixelCopy; i++ ) 363 { 364 ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0; 365 usData16.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4); 366 usData16.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4); 367 *((USHORT *) pjDstXor) = usData16.us; 368 ulCheckSum += (ULONG) usData16.us; 369 pjDstXor += 2; 370 pjSrcXor += 4; 371 } 372 373 /* Point to next source and dest scans */ 374 pjDstXor += lLastAlphaDstDelta; 375 376 } /* end of for-loop */ 377 378 /* Write Checksum as signature */ 379 pjDstXor = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE; 380 *((ULONG *) pjDstXor) = ulCheckSum; 381 *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width; 382 *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height; 383 *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTX)) = 0; 384 *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTY)) = 0; 385 386 /* set pattern offset */ 387 ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr +(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3); 388 SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF)); 389 SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF)); 390 SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF)); 391 392 /* update HWC_NUM_Next */ 393 pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM; 394 395} 396 397static Bool 398ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs) 399{ 400 if ( (pCurs->bits->width > MAX_HWC_WIDTH) || (pCurs->bits->height > MAX_HWC_HEIGHT) ) 401 return FALSE; 402 403 return TRUE; 404} 405 406static void 407ASTFireCursor(ScrnInfoPtr pScrn) 408{ 409 ASTRecPtr pAST = ASTPTR(pScrn); 410 411 SetIndexRegMask(CRTC_PORT, 0xCB, 0xFF, 0x00); /* dummp write to fire HWC */ 412 413} 414 415#endif /* End of HWC */ 416