xref: /haiku/src/add-ons/accelerants/s3/savage_cursor.cpp (revision 35db13ea5a14c9f6fee81f3de4d54a2fe42502b8)
1*35db13eaSAxel Dörfler /*
2*35db13eaSAxel Dörfler 	Haiku S3 Savage driver adapted from the X.org Savage driver.
3*35db13eaSAxel Dörfler 
4*35db13eaSAxel Dörfler 	Copyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
5*35db13eaSAxel Dörfler 	Copyright (c) 2003-2006, X.Org Foundation
6*35db13eaSAxel Dörfler 
7*35db13eaSAxel Dörfler 	Copyright 2007-2008 Haiku, Inc.  All rights reserved.
8*35db13eaSAxel Dörfler 	Distributed under the terms of the MIT license.
9*35db13eaSAxel Dörfler 
10*35db13eaSAxel Dörfler 	Authors:
11*35db13eaSAxel Dörfler 	Gerald Zajac 2006-2008
12*35db13eaSAxel Dörfler */
13*35db13eaSAxel Dörfler 
14*35db13eaSAxel Dörfler 
15*35db13eaSAxel Dörfler #include "accel.h"
16*35db13eaSAxel Dörfler #include "savage.h"
17*35db13eaSAxel Dörfler 
18*35db13eaSAxel Dörfler 
19*35db13eaSAxel Dörfler 
20*35db13eaSAxel Dörfler // Certain HW cursor operations seem to require a delay to prevent lockups.
21*35db13eaSAxel Dörfler 
22*35db13eaSAxel Dörfler static void
WaitHSync(int n)23*35db13eaSAxel Dörfler WaitHSync(int n)
24*35db13eaSAxel Dörfler {
25*35db13eaSAxel Dörfler 	while (n--) {
26*35db13eaSAxel Dörfler 		while (ReadReg8(SYSTEM_CONTROL_REG) & 0x01) {};
27*35db13eaSAxel Dörfler 		while ( ! ReadReg8(SYSTEM_CONTROL_REG) & 0x01) {};
28*35db13eaSAxel Dörfler 	}
29*35db13eaSAxel Dörfler }
30*35db13eaSAxel Dörfler 
31*35db13eaSAxel Dörfler 
32*35db13eaSAxel Dörfler void
Savage_ShowCursor(bool bShow)33*35db13eaSAxel Dörfler Savage_ShowCursor(bool bShow)
34*35db13eaSAxel Dörfler {
35*35db13eaSAxel Dörfler 	// Turn cursor on/off.
36*35db13eaSAxel Dörfler 
37*35db13eaSAxel Dörfler 	if ( ! bShow && S3_SAVAGE4_SERIES(gInfo.sharedInfo->chipType))
38*35db13eaSAxel Dörfler 		WaitHSync(5);
39*35db13eaSAxel Dörfler 
40*35db13eaSAxel Dörfler 	WriteCrtcReg(0x45, bShow ? 0x01 : 0x00, 0x01);
41*35db13eaSAxel Dörfler }
42*35db13eaSAxel Dörfler 
43*35db13eaSAxel Dörfler 
44*35db13eaSAxel Dörfler void
Savage_SetCursorPosition(int x,int y)45*35db13eaSAxel Dörfler Savage_SetCursorPosition(int x, int y)
46*35db13eaSAxel Dörfler {
47*35db13eaSAxel Dörfler 	SharedInfo& si = *gInfo.sharedInfo;
48*35db13eaSAxel Dörfler 
49*35db13eaSAxel Dörfler 	if (S3_SAVAGE4_SERIES(si.chipType))
50*35db13eaSAxel Dörfler 		WaitHSync(5);
51*35db13eaSAxel Dörfler 
52*35db13eaSAxel Dörfler 	// xOffset & yOffset are used for displaying partial cursors on screen edges.
53*35db13eaSAxel Dörfler 
54*35db13eaSAxel Dörfler 	uint8 xOffset = 0;
55*35db13eaSAxel Dörfler 	uint8 yOffset = 0;
56*35db13eaSAxel Dörfler 
57*35db13eaSAxel Dörfler 	if (x < 0) {
58*35db13eaSAxel Dörfler 		xOffset = (( -x) & 0xFE);
59*35db13eaSAxel Dörfler 		x = 0;
60*35db13eaSAxel Dörfler 	}
61*35db13eaSAxel Dörfler 
62*35db13eaSAxel Dörfler 	if (y < 0) {
63*35db13eaSAxel Dörfler 		yOffset = (( -y) & 0xFE);
64*35db13eaSAxel Dörfler 		y = 0;
65*35db13eaSAxel Dörfler 	}
66*35db13eaSAxel Dörfler 
67*35db13eaSAxel Dörfler 
68*35db13eaSAxel Dörfler 	// Note: when setting the cursor position, register 48 must be set last
69*35db13eaSAxel Dörfler 	// since setting register 48 activates the new cursor position.
70*35db13eaSAxel Dörfler 
71*35db13eaSAxel Dörfler 	WriteCrtcReg( 0x4e, xOffset );
72*35db13eaSAxel Dörfler 	WriteCrtcReg( 0x4f, yOffset );
73*35db13eaSAxel Dörfler 
74*35db13eaSAxel Dörfler 	WriteCrtcReg( 0x47, (x & 0xff) );
75*35db13eaSAxel Dörfler 	WriteCrtcReg( 0x46, (x & 0x0700) >> 8 );
76*35db13eaSAxel Dörfler 
77*35db13eaSAxel Dörfler 	WriteCrtcReg( 0x49, (y & 0xff) );
78*35db13eaSAxel Dörfler 	WriteCrtcReg( 0x48, (y & 0x0700) >> 8 );
79*35db13eaSAxel Dörfler }
80*35db13eaSAxel Dörfler 
81*35db13eaSAxel Dörfler 
82*35db13eaSAxel Dörfler bool
Savage_LoadCursorImage(int width,int height,uint8 * andMask,uint8 * xorMask)83*35db13eaSAxel Dörfler Savage_LoadCursorImage(int width, int height, uint8* andMask, uint8* xorMask)
84*35db13eaSAxel Dörfler {
85*35db13eaSAxel Dörfler 	SharedInfo& si = *gInfo.sharedInfo;
86*35db13eaSAxel Dörfler 
87*35db13eaSAxel Dörfler 	if (andMask == NULL || xorMask == NULL)
88*35db13eaSAxel Dörfler 		return false;
89*35db13eaSAxel Dörfler 
90*35db13eaSAxel Dörfler 	// Initialize the hardware cursor as completely transparent.
91*35db13eaSAxel Dörfler 
92*35db13eaSAxel Dörfler 	uint16* fbCursor16 = (uint16*)((addr_t)si.videoMemAddr + si.cursorOffset);
93*35db13eaSAxel Dörfler 
94*35db13eaSAxel Dörfler 	for (int i = 0; i < CURSOR_BYTES; i += 4) {
95*35db13eaSAxel Dörfler 		*fbCursor16++ = ~0;		// and bits
96*35db13eaSAxel Dörfler 		*fbCursor16++ = 0;		// xor bits
97*35db13eaSAxel Dörfler 	}
98*35db13eaSAxel Dörfler 
99*35db13eaSAxel Dörfler 	// Now load the AND & XOR masks for the cursor image into the cursor
100*35db13eaSAxel Dörfler 	// buffer.  Note that a particular bit in these masks will have the
101*35db13eaSAxel Dörfler 	// following effect upon the corresponding cursor pixel:
102*35db13eaSAxel Dörfler 	//	AND  XOR	Result
103*35db13eaSAxel Dörfler 	//	 0    0		 White pixel
104*35db13eaSAxel Dörfler 	//	 0    1		 Black pixel
105*35db13eaSAxel Dörfler 	//	 1    0		 Screen color (for transparency)
106*35db13eaSAxel Dörfler 	//	 1    1		 Reverse screen color to black or white
107*35db13eaSAxel Dörfler 
108*35db13eaSAxel Dörfler 	uint8* fbCursor = (uint8*)((addr_t)si.videoMemAddr + si.cursorOffset);
109*35db13eaSAxel Dörfler 
110*35db13eaSAxel Dörfler 	for (int row = 0; row < height; row++) {
111*35db13eaSAxel Dörfler 		for (int colByte = 0; colByte < width / 8; colByte++) {
112*35db13eaSAxel Dörfler 			fbCursor[row * 16 + colByte] = *andMask++;
113*35db13eaSAxel Dörfler 			fbCursor[row * 16 + colByte + 2] = *xorMask++;
114*35db13eaSAxel Dörfler 		}
115*35db13eaSAxel Dörfler 	}
116*35db13eaSAxel Dörfler 
117*35db13eaSAxel Dörfler 	if (S3_SAVAGE4_SERIES(si.chipType)) {
118*35db13eaSAxel Dörfler 
119*35db13eaSAxel Dörfler 		// Bug in Savage4 Rev B requires us to do an MMIO read after
120*35db13eaSAxel Dörfler 		// loading the cursor.
121*35db13eaSAxel Dörfler 
122*35db13eaSAxel Dörfler 		volatile unsigned int k = ALT_STATUS_WORD0;
123*35db13eaSAxel Dörfler 		(void)k++;	// Not to be optimised out
124*35db13eaSAxel Dörfler 	}
125*35db13eaSAxel Dörfler 
126*35db13eaSAxel Dörfler 	// Set cursor location in video memory.
127*35db13eaSAxel Dörfler 
128*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4d, (0xff & si.cursorOffset / 1024));
129*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4c, (0xff00 & si.cursorOffset / 1024) >> 8);
130*35db13eaSAxel Dörfler 
131*35db13eaSAxel Dörfler 	// Set the cursor colors which are black foreground and white background.
132*35db13eaSAxel Dörfler 
133*35db13eaSAxel Dörfler 	ReadCrtcReg(0x45);		// reset cursor color stack pointer
134*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4a, 0);	// set foreground color stack low, mid, high bytes
135*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4a, 0);
136*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4a, 0);
137*35db13eaSAxel Dörfler 
138*35db13eaSAxel Dörfler 	ReadCrtcReg(0x45);		// reset cursor color stack pointer
139*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4b, ~0);	// set background color stack low, mid, high bytes
140*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4b, ~0);
141*35db13eaSAxel Dörfler 	WriteCrtcReg(0x4b, ~0);
142*35db13eaSAxel Dörfler 
143*35db13eaSAxel Dörfler 	return true;
144*35db13eaSAxel Dörfler }
145