1/*
2 * Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 */
8
9
10#include "accelerant_protos.h"
11#include "accelerant.h"
12
13#include <string.h>
14
15
16status_t
17intel_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotY,
18	uint8* andMask, uint8* xorMask)
19{
20	if (width > 64 || height > 64)
21		return B_BAD_VALUE;
22
23	write32(INTEL_CURSOR_CONTROL, 0);
24		// disable cursor
25
26	// In two-color mode, the data is ordered as follows (always 64 bit per
27	// line):
28	//	plane 1: line 0 (AND mask)
29	//	plane 0: line 0 (XOR mask)
30	//	plane 1: line 1 (AND mask)
31	//	...
32	//
33	// If the planes add to the value 0x2, the corresponding pixel is
34	// transparent, for 0x3 it inverts the background, so only the first
35	// two palette entries will be used (since we're using the 2 color mode).
36
37	uint8* data = gInfo->shared_info->cursor_memory;
38	uint8 byteWidth = (width + 7) / 8;
39
40	for (int32 y = 0; y < height; y++) {
41		for (int32 x = 0; x < byteWidth; x++) {
42			data[16 * y + x] = andMask[byteWidth * y + x];
43			data[16 * y + x + 8] = xorMask[byteWidth * y + x];
44		}
45	}
46
47	// set palette entries to white/black
48	write32(INTEL_CURSOR_PALETTE + 0, 0x00ffffff);
49	write32(INTEL_CURSOR_PALETTE + 4, 0);
50
51	gInfo->shared_info->cursor_format = CURSOR_FORMAT_2_COLORS;
52
53	write32(INTEL_CURSOR_CONTROL,
54		CURSOR_ENABLED | gInfo->shared_info->cursor_format);
55	write32(INTEL_CURSOR_SIZE, height << 12 | width);
56
57	write32(INTEL_CURSOR_BASE,
58		(uint32)gInfo->shared_info->physical_graphics_memory
59		+ gInfo->shared_info->cursor_buffer_offset);
60
61	// changing the hot point changes the cursor position, too
62
63	if (hotX != gInfo->shared_info->cursor_hot_x
64		|| hotY != gInfo->shared_info->cursor_hot_y) {
65		int32 x = read32(INTEL_CURSOR_POSITION);
66		int32 y = x >> 16;
67		x &= 0xffff;
68
69		if (x & CURSOR_POSITION_NEGATIVE)
70			x = -(x & CURSOR_POSITION_MASK);
71		if (y & CURSOR_POSITION_NEGATIVE)
72			y = -(y & CURSOR_POSITION_MASK);
73
74		x += gInfo->shared_info->cursor_hot_x;
75		y += gInfo->shared_info->cursor_hot_y;
76
77		gInfo->shared_info->cursor_hot_x = hotX;
78		gInfo->shared_info->cursor_hot_y = hotY;
79
80		intel_move_cursor(x, y);
81	}
82
83	return B_OK;
84}
85
86
87void
88intel_move_cursor(uint16 _x, uint16 _y)
89{
90	int32 x = (int32)_x - gInfo->shared_info->cursor_hot_x;
91	int32 y = (int32)_y - gInfo->shared_info->cursor_hot_x;
92
93	if (x < 0)
94		x = -x | CURSOR_POSITION_NEGATIVE;
95	if (y < 0)
96		y = -y | CURSOR_POSITION_NEGATIVE;
97
98	write32(INTEL_CURSOR_POSITION, (y << 16) | x);
99}
100
101
102void
103intel_show_cursor(bool isVisible)
104{
105	if (gInfo->shared_info->cursor_visible == isVisible)
106		return;
107
108	write32(INTEL_CURSOR_CONTROL, (isVisible ? CURSOR_ENABLED : 0)
109		| gInfo->shared_info->cursor_format);
110	write32(INTEL_CURSOR_BASE,
111		(uint32)gInfo->shared_info->physical_graphics_memory
112		+ gInfo->shared_info->cursor_buffer_offset);
113
114	gInfo->shared_info->cursor_visible = isVisible;
115}
116
117