r128_cursor.c revision c582b7e3
1c582b7e3Smrg/* 2c582b7e3Smrg * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, 3c582b7e3Smrg * Precision Insight, Inc., Cedar Park, Texas, and 4c582b7e3Smrg * VA Linux Systems Inc., Fremont, California. 5c582b7e3Smrg * 6c582b7e3Smrg * All Rights Reserved. 7c582b7e3Smrg * 8c582b7e3Smrg * Permission is hereby granted, free of charge, to any person obtaining 9c582b7e3Smrg * a copy of this software and associated documentation files (the 10c582b7e3Smrg * "Software"), to deal in the Software without restriction, including 11c582b7e3Smrg * without limitation on the rights to use, copy, modify, merge, 12c582b7e3Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 13c582b7e3Smrg * and to permit persons to whom the Software is furnished to do so, 14c582b7e3Smrg * subject to the following conditions: 15c582b7e3Smrg * 16c582b7e3Smrg * The above copyright notice and this permission notice (including the 17c582b7e3Smrg * next paragraph) shall be included in all copies or substantial 18c582b7e3Smrg * portions of the Software. 19c582b7e3Smrg * 20c582b7e3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21c582b7e3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22c582b7e3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23c582b7e3Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX 24c582b7e3Smrg * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25c582b7e3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26c582b7e3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27c582b7e3Smrg * OTHER DEALINGS IN THE SOFTWARE. 28c582b7e3Smrg */ 29c582b7e3Smrg 30c582b7e3Smrg/* 31c582b7e3Smrg * Authors: 32c582b7e3Smrg * Rickard E. Faith <faith@valinux.com> 33c582b7e3Smrg * Kevin E. Martin <martin@valinux.com> 34c582b7e3Smrg * 35c582b7e3Smrg * References: 36c582b7e3Smrg * 37c582b7e3Smrg * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical 38c582b7e3Smrg * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April 39c582b7e3Smrg * 1999. 40c582b7e3Smrg * 41c582b7e3Smrg * RAGE 128 Software Development Manual (Technical Reference Manual P/N 42c582b7e3Smrg * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. 43c582b7e3Smrg * 44c582b7e3Smrg */ 45c582b7e3Smrg 46c582b7e3Smrg#ifdef HAVE_CONFIG_H 47c582b7e3Smrg#include "config.h" 48c582b7e3Smrg#endif 49c582b7e3Smrg 50c582b7e3Smrg /* Driver data structures */ 51c582b7e3Smrg#include "r128.h" 52c582b7e3Smrg#include "r128_reg.h" 53c582b7e3Smrg 54c582b7e3Smrg /* X and server generic header files */ 55c582b7e3Smrg#include "xf86.h" 56c582b7e3Smrg 57c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 58c582b7e3Smrg#define P_SWAP32( a , b ) \ 59c582b7e3Smrg ((char *)a)[0] = ((char *)b)[3]; \ 60c582b7e3Smrg ((char *)a)[1] = ((char *)b)[2]; \ 61c582b7e3Smrg ((char *)a)[2] = ((char *)b)[1]; \ 62c582b7e3Smrg ((char *)a)[3] = ((char *)b)[0] 63c582b7e3Smrg 64c582b7e3Smrg#define P_SWAP16( a , b ) \ 65c582b7e3Smrg ((char *)a)[0] = ((char *)b)[1]; \ 66c582b7e3Smrg ((char *)a)[1] = ((char *)b)[0]; \ 67c582b7e3Smrg ((char *)a)[2] = ((char *)b)[3]; \ 68c582b7e3Smrg ((char *)a)[3] = ((char *)b)[2] 69c582b7e3Smrg#endif 70c582b7e3Smrg 71c582b7e3Smrg 72c582b7e3Smrg/* Set cursor foreground and background colors. */ 73c582b7e3Smrgstatic void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 74c582b7e3Smrg{ 75c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 76c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 77c582b7e3Smrg 78c582b7e3Smrg if(info->IsSecondary) 79c582b7e3Smrg { 80c582b7e3Smrg OUTREG(R128_CUR2_CLR0, bg); 81c582b7e3Smrg OUTREG(R128_CUR2_CLR1, fg); 82c582b7e3Smrg } 83c582b7e3Smrg else 84c582b7e3Smrg { 85c582b7e3Smrg OUTREG(R128_CUR_CLR0, bg); 86c582b7e3Smrg OUTREG(R128_CUR_CLR1, fg); 87c582b7e3Smrg } 88c582b7e3Smrg} 89c582b7e3Smrg 90c582b7e3Smrg/* Set cursor position to (x,y) with offset into cursor bitmap at 91c582b7e3Smrg (xorigin,yorigin). */ 92c582b7e3Smrgstatic void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 93c582b7e3Smrg{ 94c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 95c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 96c582b7e3Smrg xf86CursorInfoPtr cursor = info->cursor; 97c582b7e3Smrg int xorigin = 0; 98c582b7e3Smrg int yorigin = 0; 99c582b7e3Smrg int total_y = pScrn->frameY1 - pScrn->frameY0; 100c582b7e3Smrg 101c582b7e3Smrg if (x < 0) xorigin = -x; 102c582b7e3Smrg if (y < 0) yorigin = -y; 103c582b7e3Smrg if (y > total_y) y = total_y; 104c582b7e3Smrg if (info->Flags & V_DBLSCAN) y *= 2; 105c582b7e3Smrg if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; 106c582b7e3Smrg if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; 107c582b7e3Smrg 108c582b7e3Smrg if(!info->IsSecondary) 109c582b7e3Smrg { 110c582b7e3Smrg OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin); 111c582b7e3Smrg OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK 112c582b7e3Smrg | ((xorigin ? 0 : x) << 16) 113c582b7e3Smrg | (yorigin ? 0 : y))); 114c582b7e3Smrg OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16); 115c582b7e3Smrg } 116c582b7e3Smrg else 117c582b7e3Smrg { 118c582b7e3Smrg OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK 119c582b7e3Smrg | (xorigin << 16) 120c582b7e3Smrg | yorigin)); 121c582b7e3Smrg OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK 122c582b7e3Smrg | ((xorigin ? 0 : x) << 16) 123c582b7e3Smrg | (yorigin ? 0 : y))); 124c582b7e3Smrg OUTREG(R128_CUR2_OFFSET, 125c582b7e3Smrg info->cursor_start + pScrn->fbOffset + yorigin * 16); 126c582b7e3Smrg } 127c582b7e3Smrg} 128c582b7e3Smrg 129c582b7e3Smrg/* Copy cursor image from `image' to video memory. R128SetCursorPosition 130c582b7e3Smrg will be called after this, so we can ignore xorigin and yorigin. */ 131c582b7e3Smrgstatic void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) 132c582b7e3Smrg{ 133c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 134c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 135c582b7e3Smrg CARD32 *s = (pointer)image; 136c582b7e3Smrg CARD32 *d = (pointer)((CARD8*)info->FB + info->cursor_start); 137c582b7e3Smrg int y; 138c582b7e3Smrg CARD32 save; 139c582b7e3Smrg 140c582b7e3Smrg if(!info->IsSecondary) 141c582b7e3Smrg { 142c582b7e3Smrg save = INREG(R128_CRTC_GEN_CNTL); 143c582b7e3Smrg OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN); 144c582b7e3Smrg } 145c582b7e3Smrg else 146c582b7e3Smrg { 147c582b7e3Smrg save = INREG(R128_CRTC2_GEN_CNTL); 148c582b7e3Smrg OUTREG(R128_CRTC2_GEN_CNTL, save & (CARD32)~R128_CRTC2_CUR_EN); 149c582b7e3Smrg } 150c582b7e3Smrg 151c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 152c582b7e3Smrg switch(info->CurrentLayout.pixel_bytes) { 153c582b7e3Smrg case 4: 154c582b7e3Smrg case 3: 155c582b7e3Smrg for (y = 0; y < 64; y++) { 156c582b7e3Smrg P_SWAP32(d,s); 157c582b7e3Smrg d++; s++; 158c582b7e3Smrg P_SWAP32(d,s); 159c582b7e3Smrg d++; s++; 160c582b7e3Smrg P_SWAP32(d,s); 161c582b7e3Smrg d++; s++; 162c582b7e3Smrg P_SWAP32(d,s); 163c582b7e3Smrg d++; s++; 164c582b7e3Smrg } 165c582b7e3Smrg break; 166c582b7e3Smrg case 2: 167c582b7e3Smrg for (y = 0; y < 64; y++) { 168c582b7e3Smrg P_SWAP16(d,s); 169c582b7e3Smrg d++; s++; 170c582b7e3Smrg P_SWAP16(d,s); 171c582b7e3Smrg d++; s++; 172c582b7e3Smrg P_SWAP16(d,s); 173c582b7e3Smrg d++; s++; 174c582b7e3Smrg P_SWAP16(d,s); 175c582b7e3Smrg d++; s++; 176c582b7e3Smrg } 177c582b7e3Smrg break; 178c582b7e3Smrg default: 179c582b7e3Smrg for (y = 0; y < 64; y++) { 180c582b7e3Smrg *d++ = *s++; 181c582b7e3Smrg *d++ = *s++; 182c582b7e3Smrg *d++ = *s++; 183c582b7e3Smrg *d++ = *s++; 184c582b7e3Smrg } 185c582b7e3Smrg } 186c582b7e3Smrg#else 187c582b7e3Smrg for (y = 0; y < 64; y++) { 188c582b7e3Smrg *d++ = *s++; 189c582b7e3Smrg *d++ = *s++; 190c582b7e3Smrg *d++ = *s++; 191c582b7e3Smrg *d++ = *s++; 192c582b7e3Smrg } 193c582b7e3Smrg#endif 194c582b7e3Smrg 195c582b7e3Smrg /* Set the area after the cursor to be all transparent so that we 196c582b7e3Smrg won't display corrupted cursors on the screen */ 197c582b7e3Smrg for (y = 0; y < 64; y++) { 198c582b7e3Smrg *d++ = 0xffffffff; /* The AND bits */ 199c582b7e3Smrg *d++ = 0xffffffff; 200c582b7e3Smrg *d++ = 0x00000000; /* The XOR bits */ 201c582b7e3Smrg *d++ = 0x00000000; 202c582b7e3Smrg } 203c582b7e3Smrg 204c582b7e3Smrg 205c582b7e3Smrg if(!info->IsSecondary) 206c582b7e3Smrg OUTREG(R128_CRTC_GEN_CNTL, save); 207c582b7e3Smrg else 208c582b7e3Smrg OUTREG(R128_CRTC2_GEN_CNTL, save); 209c582b7e3Smrg 210c582b7e3Smrg} 211c582b7e3Smrg 212c582b7e3Smrg/* Hide hardware cursor. */ 213c582b7e3Smrgstatic void R128HideCursor(ScrnInfoPtr pScrn) 214c582b7e3Smrg{ 215c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 216c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 217c582b7e3Smrg 218c582b7e3Smrg if(info->IsSecondary) 219c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); 220c582b7e3Smrg else 221c582b7e3Smrg OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); 222c582b7e3Smrg} 223c582b7e3Smrg 224c582b7e3Smrg/* Show hardware cursor. */ 225c582b7e3Smrgstatic void R128ShowCursor(ScrnInfoPtr pScrn) 226c582b7e3Smrg{ 227c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 228c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 229c582b7e3Smrg 230c582b7e3Smrg if(info->IsSecondary) 231c582b7e3Smrg { 232c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, 233c582b7e3Smrg ~R128_CRTC2_CUR_EN); 234c582b7e3Smrg } 235c582b7e3Smrg else 236c582b7e3Smrg { 237c582b7e3Smrg OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); 238c582b7e3Smrg } 239c582b7e3Smrg} 240c582b7e3Smrg 241c582b7e3Smrg/* Determine if hardware cursor is in use. */ 242c582b7e3Smrgstatic Bool R128UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 243c582b7e3Smrg{ 244c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 245c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 246c582b7e3Smrg 247c582b7e3Smrg return info->cursor_start ? TRUE : FALSE; 248c582b7e3Smrg} 249c582b7e3Smrg 250c582b7e3Smrg/* Initialize hardware cursor support. */ 251c582b7e3SmrgBool R128CursorInit(ScreenPtr pScreen) 252c582b7e3Smrg{ 253c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 254c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 255c582b7e3Smrg xf86CursorInfoPtr cursor; 256c582b7e3Smrg FBAreaPtr fbarea; 257c582b7e3Smrg int width; 258c582b7e3Smrg int height; 259c582b7e3Smrg int size; 260c582b7e3Smrg 261c582b7e3Smrg 262c582b7e3Smrg if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE; 263c582b7e3Smrg 264c582b7e3Smrg cursor->MaxWidth = 64; 265c582b7e3Smrg cursor->MaxHeight = 64; 266c582b7e3Smrg cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP 267c582b7e3Smrg | HARDWARE_CURSOR_SHOW_TRANSPARENT 268c582b7e3Smrg | HARDWARE_CURSOR_UPDATE_UNHIDDEN 269c582b7e3Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 270c582b7e3Smrg | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST 271c582b7e3Smrg#endif 272c582b7e3Smrg | HARDWARE_CURSOR_INVERT_MASK 273c582b7e3Smrg | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK 274c582b7e3Smrg | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 275c582b7e3Smrg | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK); 276c582b7e3Smrg 277c582b7e3Smrg cursor->SetCursorColors = R128SetCursorColors; 278c582b7e3Smrg cursor->SetCursorPosition = R128SetCursorPosition; 279c582b7e3Smrg cursor->LoadCursorImage = R128LoadCursorImage; 280c582b7e3Smrg cursor->HideCursor = R128HideCursor; 281c582b7e3Smrg cursor->ShowCursor = R128ShowCursor; 282c582b7e3Smrg cursor->UseHWCursor = R128UseHWCursor; 283c582b7e3Smrg 284c582b7e3Smrg size = (cursor->MaxWidth/4) * cursor->MaxHeight; 285c582b7e3Smrg width = pScrn->displayWidth; 286c582b7e3Smrg height = (size*2 + 1023) / pScrn->displayWidth; 287c582b7e3Smrg fbarea = xf86AllocateOffscreenArea(pScreen, 288c582b7e3Smrg width, 289c582b7e3Smrg height, 290c582b7e3Smrg 16, 291c582b7e3Smrg NULL, 292c582b7e3Smrg NULL, 293c582b7e3Smrg NULL); 294c582b7e3Smrg 295c582b7e3Smrg if (!fbarea) { 296c582b7e3Smrg info->cursor_start = 0; 297c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 298c582b7e3Smrg "Hardware cursor disabled" 299c582b7e3Smrg " due to insufficient offscreen memory\n"); 300c582b7e3Smrg } else { 301c582b7e3Smrg info->cursor_start = R128_ALIGN((fbarea->box.x1 302c582b7e3Smrg + width * fbarea->box.y1) 303c582b7e3Smrg * info->CurrentLayout.pixel_bytes, 16); 304c582b7e3Smrg info->cursor_end = info->cursor_start + size; 305c582b7e3Smrg } 306c582b7e3Smrg 307c582b7e3Smrg R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n", 308c582b7e3Smrg info->cursor_start, info->cursor_end)); 309c582b7e3Smrg 310c582b7e3Smrg return xf86InitCursor(pScreen, cursor); 311c582b7e3Smrg} 312