xref: /haiku/src/add-ons/accelerants/matrox/Cursor.c (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
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-11/2004
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\n", width, height));
28 	if ((width != 16) || (height != 16))
29 	{
30 		return B_ERROR;
31 	}
32 	else if ((hot_x >= width) || (hot_y >= height))
33 	{
34 		return B_ERROR;
35 	}
36 	else
37 	{
38 		gx00_crtc_cursor_define(andMask,xorMask);
39 
40 		/* Update cursor variables appropriately. */
41 		si->cursor.width = width;
42 		si->cursor.height = height;
43 		si->cursor.hot_x = hot_x;
44 		si->cursor.hot_y = hot_y;
45 	}
46 
47 	return B_OK;
48 }
49 
50 /* Move the cursor to the specified position on the desktop, taking account of virtual/dual issues */
51 void MOVE_CURSOR(uint16 x, uint16 y)
52 {
53 	uint16 hds = si->dm.h_display_start;	/* the current horizontal starting pixel */
54 	uint16 vds = si->dm.v_display_start;	/* the current vertical starting line */
55 	uint16 h_adjust;
56 
57 	/* clamp cursor to display */
58 	if (x >= si->dm.virtual_width) x = si->dm.virtual_width - 1;
59 	if (y >= si->dm.virtual_height) y = si->dm.virtual_height - 1;
60 
61 	/* store, for our info */
62 	si->cursor.x = x;
63 	si->cursor.y = y;
64 
65 	/*set up minimum amount to scroll*/
66 	if (si->dm.flags & DUALHEAD_BITS)
67 	{
68 		switch(si->dm.space)
69 		{
70 		case B_RGB16_LITTLE:
71 			h_adjust = 0x1f;
72 			break;
73 		case B_RGB32_LITTLE:
74 			h_adjust = 0x0f;
75 			break;
76 		default:
77 			h_adjust = 0x1f;
78 			break;
79 		}
80 	}
81 	else
82 	{
83 		switch(si->dm.space)
84 		{
85 		case B_CMAP8:
86 			h_adjust = 0x07;
87 			break;
88 		case B_RGB15_LITTLE:case B_RGB16_LITTLE:
89 			h_adjust = 0x03;
90 			break;
91 		case B_RGB32_LITTLE:
92 			h_adjust = 0x01;
93 			break;
94 		default:
95 			h_adjust = 0x07;
96 			break;
97 		}
98 	}
99 
100 	/* adjust h/v_display_start to move cursor onto screen */
101 	switch (si->dm.flags & DUALHEAD_BITS)
102 	{
103 	case DUALHEAD_ON:
104 	case DUALHEAD_SWITCH:
105 		if (x >= ((si->dm.timing.h_display * 2) + hds))
106 		{
107 			hds = ((x - (si->dm.timing.h_display * 2)) + 1 + h_adjust) & ~h_adjust;
108 			/* make sure we stay within the display! */
109 			if ((hds + (si->dm.timing.h_display * 2)) > si->dm.virtual_width)
110 				hds -= (h_adjust + 1);
111 		}
112 		else if (x < hds)
113 			hds = x & ~h_adjust;
114 		break;
115 	default:
116 		if (x >= (si->dm.timing.h_display + hds))
117 		{
118 			hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
119 			/* make sure we stay within the display! */
120 			if ((hds + si->dm.timing.h_display) > si->dm.virtual_width)
121 				hds -= (h_adjust + 1);
122 		}
123 		else if (x < hds)
124 			hds = x & ~h_adjust;
125 		break;
126 	}
127 
128 	if (y >= (si->dm.timing.v_display + vds))
129 		vds = y - si->dm.timing.v_display + 1;
130 	else if (y < vds)
131 		vds = y;
132 
133 	/* reposition the desktop _and_ the overlay on the display if required */
134 	if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
135 	{
136 		MOVE_DISPLAY(hds,vds);
137 		gx00_bes_move_overlay();
138 	}
139 
140 	/* put cursor in correct physical position */
141 	x -= hds + si->cursor.hot_x;
142 	y -= vds + si->cursor.hot_y;
143 
144 	/* account for switched CRTC's */
145 	if (si->switched_crtcs)	x -= si->dm.timing.h_display;
146 
147 	/* position the cursor on the display */
148 	gx00_crtc_cursor_position(x,y);
149 }
150 
151 void SHOW_CURSOR(bool is_visible)
152 {
153 	/* record for our info */
154 	si->cursor.is_visible = is_visible;
155 
156 	if (is_visible)
157 		gx00_crtc_cursor_show();
158 	else
159 		gx00_crtc_cursor_hide();
160 }
161