r128_cursor.c revision 42a55b46
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 5742a55b46Smrg /* Because for EXA we need to use a different allocator */ 5842a55b46Smrg#ifdef USE_EXA 5942a55b46Smrg#include "exa.h" 6042a55b46Smrg#endif 6142a55b46Smrg 62c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 63c582b7e3Smrg#define P_SWAP32( a , b ) \ 64c582b7e3Smrg ((char *)a)[0] = ((char *)b)[3]; \ 65c582b7e3Smrg ((char *)a)[1] = ((char *)b)[2]; \ 66c582b7e3Smrg ((char *)a)[2] = ((char *)b)[1]; \ 67c582b7e3Smrg ((char *)a)[3] = ((char *)b)[0] 68c582b7e3Smrg 69c582b7e3Smrg#define P_SWAP16( a , b ) \ 70c582b7e3Smrg ((char *)a)[0] = ((char *)b)[1]; \ 71c582b7e3Smrg ((char *)a)[1] = ((char *)b)[0]; \ 72c582b7e3Smrg ((char *)a)[2] = ((char *)b)[3]; \ 73c582b7e3Smrg ((char *)a)[3] = ((char *)b)[2] 74c582b7e3Smrg#endif 75c582b7e3Smrg 76c582b7e3Smrg 77c582b7e3Smrg/* Set cursor foreground and background colors. */ 78c582b7e3Smrgstatic void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 79c582b7e3Smrg{ 80c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 81c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 82c582b7e3Smrg 83c582b7e3Smrg if(info->IsSecondary) 84c582b7e3Smrg { 85c582b7e3Smrg OUTREG(R128_CUR2_CLR0, bg); 86c582b7e3Smrg OUTREG(R128_CUR2_CLR1, fg); 87c582b7e3Smrg } 88c582b7e3Smrg else 89c582b7e3Smrg { 90c582b7e3Smrg OUTREG(R128_CUR_CLR0, bg); 91c582b7e3Smrg OUTREG(R128_CUR_CLR1, fg); 92c582b7e3Smrg } 93c582b7e3Smrg} 94c582b7e3Smrg 95c582b7e3Smrg/* Set cursor position to (x,y) with offset into cursor bitmap at 96c582b7e3Smrg (xorigin,yorigin). */ 97c582b7e3Smrgstatic void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 98c582b7e3Smrg{ 99c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 100c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 101c582b7e3Smrg xf86CursorInfoPtr cursor = info->cursor; 102c582b7e3Smrg int xorigin = 0; 103c582b7e3Smrg int yorigin = 0; 104c582b7e3Smrg int total_y = pScrn->frameY1 - pScrn->frameY0; 105c582b7e3Smrg 106c582b7e3Smrg if (x < 0) xorigin = -x; 107c582b7e3Smrg if (y < 0) yorigin = -y; 108c582b7e3Smrg if (y > total_y) y = total_y; 109c582b7e3Smrg if (info->Flags & V_DBLSCAN) y *= 2; 110c582b7e3Smrg if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; 111c582b7e3Smrg if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; 112c582b7e3Smrg 113c582b7e3Smrg if(!info->IsSecondary) 114c582b7e3Smrg { 115c582b7e3Smrg OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin); 116c582b7e3Smrg OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK 117c582b7e3Smrg | ((xorigin ? 0 : x) << 16) 118c582b7e3Smrg | (yorigin ? 0 : y))); 119c582b7e3Smrg OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16); 120c582b7e3Smrg } 121c582b7e3Smrg else 122c582b7e3Smrg { 123c582b7e3Smrg OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK 124c582b7e3Smrg | (xorigin << 16) 125c582b7e3Smrg | yorigin)); 126c582b7e3Smrg OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK 127c582b7e3Smrg | ((xorigin ? 0 : x) << 16) 128c582b7e3Smrg | (yorigin ? 0 : y))); 129c582b7e3Smrg OUTREG(R128_CUR2_OFFSET, 130c582b7e3Smrg info->cursor_start + pScrn->fbOffset + yorigin * 16); 131c582b7e3Smrg } 132c582b7e3Smrg} 133c582b7e3Smrg 134c582b7e3Smrg/* Copy cursor image from `image' to video memory. R128SetCursorPosition 135c582b7e3Smrg will be called after this, so we can ignore xorigin and yorigin. */ 136c582b7e3Smrgstatic void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) 137c582b7e3Smrg{ 138c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 139c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 140c582b7e3Smrg CARD32 *s = (pointer)image; 141c582b7e3Smrg CARD32 *d = (pointer)((CARD8*)info->FB + info->cursor_start); 142c582b7e3Smrg int y; 143c582b7e3Smrg CARD32 save; 144c582b7e3Smrg 145c582b7e3Smrg if(!info->IsSecondary) 146c582b7e3Smrg { 147c582b7e3Smrg save = INREG(R128_CRTC_GEN_CNTL); 148c582b7e3Smrg OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN); 149c582b7e3Smrg } 150c582b7e3Smrg else 151c582b7e3Smrg { 152c582b7e3Smrg save = INREG(R128_CRTC2_GEN_CNTL); 153c582b7e3Smrg OUTREG(R128_CRTC2_GEN_CNTL, save & (CARD32)~R128_CRTC2_CUR_EN); 154c582b7e3Smrg } 155c582b7e3Smrg 156c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 157c582b7e3Smrg switch(info->CurrentLayout.pixel_bytes) { 158c582b7e3Smrg case 4: 159c582b7e3Smrg case 3: 160c582b7e3Smrg for (y = 0; y < 64; y++) { 161c582b7e3Smrg P_SWAP32(d,s); 162c582b7e3Smrg d++; s++; 163c582b7e3Smrg P_SWAP32(d,s); 164c582b7e3Smrg d++; s++; 165c582b7e3Smrg P_SWAP32(d,s); 166c582b7e3Smrg d++; s++; 167c582b7e3Smrg P_SWAP32(d,s); 168c582b7e3Smrg d++; s++; 169c582b7e3Smrg } 170c582b7e3Smrg break; 171c582b7e3Smrg case 2: 172c582b7e3Smrg for (y = 0; y < 64; y++) { 173c582b7e3Smrg P_SWAP16(d,s); 174c582b7e3Smrg d++; s++; 175c582b7e3Smrg P_SWAP16(d,s); 176c582b7e3Smrg d++; s++; 177c582b7e3Smrg P_SWAP16(d,s); 178c582b7e3Smrg d++; s++; 179c582b7e3Smrg P_SWAP16(d,s); 180c582b7e3Smrg d++; s++; 181c582b7e3Smrg } 182c582b7e3Smrg break; 183c582b7e3Smrg default: 184c582b7e3Smrg for (y = 0; y < 64; y++) { 185c582b7e3Smrg *d++ = *s++; 186c582b7e3Smrg *d++ = *s++; 187c582b7e3Smrg *d++ = *s++; 188c582b7e3Smrg *d++ = *s++; 189c582b7e3Smrg } 190c582b7e3Smrg } 191c582b7e3Smrg#else 192c582b7e3Smrg for (y = 0; y < 64; y++) { 193c582b7e3Smrg *d++ = *s++; 194c582b7e3Smrg *d++ = *s++; 195c582b7e3Smrg *d++ = *s++; 196c582b7e3Smrg *d++ = *s++; 197c582b7e3Smrg } 198c582b7e3Smrg#endif 199c582b7e3Smrg 200c582b7e3Smrg /* Set the area after the cursor to be all transparent so that we 201c582b7e3Smrg won't display corrupted cursors on the screen */ 202c582b7e3Smrg for (y = 0; y < 64; y++) { 203c582b7e3Smrg *d++ = 0xffffffff; /* The AND bits */ 204c582b7e3Smrg *d++ = 0xffffffff; 205c582b7e3Smrg *d++ = 0x00000000; /* The XOR bits */ 206c582b7e3Smrg *d++ = 0x00000000; 207c582b7e3Smrg } 208c582b7e3Smrg 209c582b7e3Smrg 210c582b7e3Smrg if(!info->IsSecondary) 211c582b7e3Smrg OUTREG(R128_CRTC_GEN_CNTL, save); 212c582b7e3Smrg else 213c582b7e3Smrg OUTREG(R128_CRTC2_GEN_CNTL, save); 214c582b7e3Smrg 215c582b7e3Smrg} 216c582b7e3Smrg 217c582b7e3Smrg/* Hide hardware cursor. */ 218c582b7e3Smrgstatic void R128HideCursor(ScrnInfoPtr pScrn) 219c582b7e3Smrg{ 220c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 221c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 222c582b7e3Smrg 223c582b7e3Smrg if(info->IsSecondary) 224c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); 225c582b7e3Smrg else 226c582b7e3Smrg OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); 227c582b7e3Smrg} 228c582b7e3Smrg 229c582b7e3Smrg/* Show hardware cursor. */ 230c582b7e3Smrgstatic void R128ShowCursor(ScrnInfoPtr pScrn) 231c582b7e3Smrg{ 232c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 233c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 234c582b7e3Smrg 235c582b7e3Smrg if(info->IsSecondary) 236c582b7e3Smrg { 237c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, 238c582b7e3Smrg ~R128_CRTC2_CUR_EN); 239c582b7e3Smrg } 240c582b7e3Smrg else 241c582b7e3Smrg { 242c582b7e3Smrg OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); 243c582b7e3Smrg } 244c582b7e3Smrg} 245c582b7e3Smrg 246c582b7e3Smrg/* Determine if hardware cursor is in use. */ 247c582b7e3Smrgstatic Bool R128UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 248c582b7e3Smrg{ 24942a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 250c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 251c582b7e3Smrg 252c582b7e3Smrg return info->cursor_start ? TRUE : FALSE; 253c582b7e3Smrg} 254c582b7e3Smrg 255c582b7e3Smrg/* Initialize hardware cursor support. */ 256c582b7e3SmrgBool R128CursorInit(ScreenPtr pScreen) 257c582b7e3Smrg{ 25842a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 259c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 260c582b7e3Smrg xf86CursorInfoPtr cursor; 26142a55b46Smrg FBAreaPtr fbarea = NULL; 26242a55b46Smrg#ifdef USE_EXA 26342a55b46Smrg ExaOffscreenArea* osArea = NULL; 26442a55b46Smrg#else 26542a55b46Smrg void* osArea = NULL; 26642a55b46Smrg#endif 267c582b7e3Smrg int width; 268c582b7e3Smrg int height; 269c582b7e3Smrg int size; 270c582b7e3Smrg 27142a55b46Smrg int cpp = info->CurrentLayout.pixel_bytes; 272c582b7e3Smrg 273c582b7e3Smrg if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE; 274c582b7e3Smrg 275c582b7e3Smrg cursor->MaxWidth = 64; 276c582b7e3Smrg cursor->MaxHeight = 64; 277c582b7e3Smrg cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP 278c582b7e3Smrg | HARDWARE_CURSOR_SHOW_TRANSPARENT 279c582b7e3Smrg | HARDWARE_CURSOR_UPDATE_UNHIDDEN 280c582b7e3Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 281c582b7e3Smrg | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST 282c582b7e3Smrg#endif 283c582b7e3Smrg | HARDWARE_CURSOR_INVERT_MASK 284c582b7e3Smrg | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK 285c582b7e3Smrg | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 286c582b7e3Smrg | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK); 287c582b7e3Smrg 288c582b7e3Smrg cursor->SetCursorColors = R128SetCursorColors; 289c582b7e3Smrg cursor->SetCursorPosition = R128SetCursorPosition; 290c582b7e3Smrg cursor->LoadCursorImage = R128LoadCursorImage; 291c582b7e3Smrg cursor->HideCursor = R128HideCursor; 292c582b7e3Smrg cursor->ShowCursor = R128ShowCursor; 293c582b7e3Smrg cursor->UseHWCursor = R128UseHWCursor; 294c582b7e3Smrg 295c582b7e3Smrg size = (cursor->MaxWidth/4) * cursor->MaxHeight; 296c582b7e3Smrg width = pScrn->displayWidth; 297c582b7e3Smrg height = (size*2 + 1023) / pScrn->displayWidth; 29842a55b46Smrg 29942a55b46Smrg if(!info->useEXA) { 30042a55b46Smrg fbarea = xf86AllocateOffscreenArea(pScreen, width, height, 30142a55b46Smrg 16, NULL, NULL, NULL); 30242a55b46Smrg 30342a55b46Smrg if (fbarea) { 30442a55b46Smrg info->cursor_start = R128_ALIGN((fbarea->box.x1 30542a55b46Smrg + width * fbarea->box.y1) 30642a55b46Smrg * cpp, 16); 30742a55b46Smrg info->cursor_end = info->cursor_start + size; 30842a55b46Smrg } 30942a55b46Smrg } 31042a55b46Smrg#ifdef USE_EXA 31142a55b46Smrg else { 31242a55b46Smrg osArea = exaOffscreenAlloc(pScreen, width * height, 16, 31342a55b46Smrg TRUE, NULL, NULL); 31442a55b46Smrg 31542a55b46Smrg if (osArea) { 31642a55b46Smrg info->cursor_start = osArea->offset; 31742a55b46Smrg info->cursor_end = osArea->offset + osArea->size; 31842a55b46Smrg } 31942a55b46Smrg } 32042a55b46Smrg#endif 32142a55b46Smrg 32242a55b46Smrg if ((!info->useEXA && !fbarea) || (info->useEXA && !osArea)) { 323c582b7e3Smrg info->cursor_start = 0; 324c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 325c582b7e3Smrg "Hardware cursor disabled" 326c582b7e3Smrg " due to insufficient offscreen memory\n"); 327c582b7e3Smrg } 328c582b7e3Smrg 329c582b7e3Smrg R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n", 330c582b7e3Smrg info->cursor_start, info->cursor_end)); 331c582b7e3Smrg 332c582b7e3Smrg return xf86InitCursor(pScreen, cursor); 333c582b7e3Smrg} 334