xref: /haiku/src/add-ons/accelerants/nvidia/Cursor.c (revision 01b25646004ff628ecad0281a9795e5e90f71746)
1 /*
2 	Copyright 1999, Be Incorporated.   All Rights Reserved.
3 	This file may be used under the terms of the Be Sample Code License.
4 
5 	Other authors:
6 	Mark Watson,
7 	Rudolf Cornelissen 4/2003-8/2003
8 */
9 
10 #define MODULE_BIT 0x20000000
11 
12 /*DUALHEAD notes -
13 	No hardware cursor possible on the secondary head :(
14 		Reasons:
15 		CRTC1 has a cursor, can be displayed on DAC or MAVEN
16 		CRTC2 has no cursor
17 		Can not switch CRTC in one vblank (has to resync)
18 		CRTC2 does not support split screen
19 		app_server does not support some modes with and some without cursor
20 	virtual not supported, because of MAVEN blanking issues
21 */
22 
23 #include "acc_std.h"
24 
25 status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask)
26 {
27 	LOG(4,("SET_CURSOR_SHAPE: width %d, height %d, hot_x %d, hot_y %d\n",
28 		width, height, hot_x, hot_y));
29 
30 	if ((width != 16) || (height != 16))
31 	{
32 		return B_ERROR;
33 	}
34 	else if ((hot_x >= width) || (hot_y >= height))
35 	{
36 		return B_ERROR;
37 	}
38 	else
39 	{
40 		nv_crtc_cursor_define(andMask,xorMask);
41 
42 		/* Update cursor variables appropriately. */
43 		si->cursor.width = width;
44 		si->cursor.height = height;
45 		si->cursor.hot_x = hot_x;
46 		si->cursor.hot_y = hot_y;
47 	}
48 
49 	return B_OK;
50 }
51 
52 /* Move the cursor to the specified position on the desktop, taking account of virtual/dual issues */
53 void MOVE_CURSOR(uint16 x, uint16 y)
54 {
55 	uint16 hds = si->dm.h_display_start;	/* the current horizontal starting pixel */
56 	uint16 vds = si->dm.v_display_start;	/* the current vertical starting line */
57 	uint16 h_adjust;
58 
59 	/* clamp cursor to display */
60 	if (x >= si->dm.virtual_width) x = si->dm.virtual_width - 1;
61 	if (y >= si->dm.virtual_height) y = si->dm.virtual_height - 1;
62 
63 	/* store, for our info */
64 	si->cursor.x = x;
65 	si->cursor.y = y;
66 
67 	/*set up minimum amount to scroll*/
68 	if (si->dm.flags & DUALHEAD_BITS)
69 	{
70 /* fixme???? Nvidia always does pixelprecise panning on sec head?? */
71 		switch(si->dm.space)
72 		{
73 		case B_RGB16_LITTLE:
74 			h_adjust = 0x1f;
75 			break;
76 		case B_RGB32_LITTLE:
77 			h_adjust = 0x0f;
78 			break;
79 		default:
80 			h_adjust = 0x1f;
81 			break;
82 		}
83 	}
84 	else
85 	{
86 /*		switch(si->dm.space)
87 		{
88 		case B_CMAP8:
89 			h_adjust = 0x07;
90 			break;
91 		case B_RGB15_LITTLE:case B_RGB16_LITTLE:
92 			h_adjust = 0x03;
93 			break;
94 		case B_RGB32_LITTLE:
95 			h_adjust = 0x01;
96 			break;
97 		default:
98 			h_adjust = 0x07;
99 			break;
100 		}
101 */
102 		/* Nvidia always does pixelprecise panning on primary head */
103 		h_adjust = 0x00;
104 	}
105 
106 	/* adjust h/v_display_start to move cursor onto screen */
107 	switch (si->dm.flags & DUALHEAD_BITS)
108 	{
109 	case DUALHEAD_ON:
110 	case DUALHEAD_SWITCH:
111 		if (x >= ((si->dm.timing.h_display * 2) + hds))
112 		{
113 			hds = ((x - (si->dm.timing.h_display * 2)) + 1 + h_adjust) & ~h_adjust;
114 			/* make sure we stay within the display! */
115 			if ((hds + (si->dm.timing.h_display * 2)) > si->dm.virtual_width)
116 				hds -= (h_adjust + 1);
117 		}
118 		else if (x < hds)
119 			hds = x & ~h_adjust;
120 		break;
121 	default:
122 		if (x >= (si->dm.timing.h_display + hds))
123 		{
124 			hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
125 			/* make sure we stay within the display! */
126 			if ((hds + si->dm.timing.h_display) > si->dm.virtual_width)
127 				hds -= (h_adjust + 1);
128 		}
129 		else if (x < hds)
130 			hds = x & ~h_adjust;
131 		break;
132 	}
133 
134 	if (y >= (si->dm.timing.v_display + vds))
135 		vds = y - si->dm.timing.v_display + 1;
136 	else if (y < vds)
137 		vds = y;
138 
139 	/* reposition the desktop _and_ the overlay on the display if required */
140 	if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
141 	{
142 		MOVE_DISPLAY(hds,vds);
143 		//fixme: implement:
144 		//move_overlay(hds,vds);
145 	}
146 
147 	/* put cursor in correct physical position, so stay onscreen (rel. to CRTC) */
148 	if (x > (hds + si->cursor.hot_x)) x -= (hds + si->cursor.hot_x);
149 	else x = 0;
150 	if (y > (vds + si->cursor.hot_y)) y -= (vds + si->cursor.hot_y);
151 	else y = 0;
152 
153 	/* account for switched CRTC's */
154 	if (si->switched_crtcs)	x -= si->dm.timing.h_display;
155 
156 	/* position the cursor on the display */
157 	nv_crtc_cursor_position(x,y);
158 }
159 
160 void SHOW_CURSOR(bool is_visible)
161 {
162 	/* record for our info */
163 	si->cursor.is_visible = is_visible;
164 
165 	if (is_visible)
166 		nv_crtc_cursor_show();
167 	else
168 		nv_crtc_cursor_hide();
169 }
170