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