1/*
2	Haiku S3 Virge driver adapted from the X.org Virge driver.
3
4	Copyright (C) 1994-1999 The XFree86 Project, Inc.	All Rights Reserved.
5
6	Copyright 2007 Haiku, Inc.  All rights reserved.
7	Distributed under the terms of the MIT license.
8
9	Authors:
10	Gerald Zajac 2007
11*/
12
13
14#include "accel.h"
15#include "virge.h"
16
17
18
19static inline void WaitForSync()
20{
21	while ((IN_SUBSYS_STAT() & 0x2000) == 0) ;
22}
23
24
25
26void
27Virge_FillRectangle(engine_token* et, uint32 color, fill_rect_params* pList, uint32 count)
28{
29	int rop = 0xF0;
30	int cmd = DRAW | rop << 17 | CMD_RECT | CMD_XP | CMD_YP ;
31
32	(void)et;		// avoid compiler warning for unused arg
33
34	cmd |= gInfo.sharedInfo->commonCmd;
35
36	while (count--) {
37		int x = pList->left;
38		int y = pList->top;
39		int w = pList->right - x + 1;
40		int h = pList->bottom - y + 1;
41
42		gInfo.WaitQueue(4);
43		WriteReg32(PAT_FG_CLR, color);
44		WriteReg32(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
45		WriteReg32(RDEST_XY, (x << 16) | y);
46		WriteReg32(CMD_SET, cmd);
47		WaitForSync();
48
49		pList++;
50	}
51}
52
53
54void
55Virge_FillSpan(engine_token* et, uint32 color, uint16* pList, uint32 count)
56{
57	int rop = 0xF0;
58	int cmd = DRAW | rop << 17 | CMD_RECT | CMD_XP | CMD_YP ;
59
60	(void)et;		// avoid compiler warning for unused arg
61
62	cmd |= gInfo.sharedInfo->commonCmd;
63
64	while (count--) {
65		int y = *pList++;
66		int x = *pList++;
67		int w = *pList++ - x + 1;
68
69		// The MediaPlayer in Zeta 1.21 displays a window which has 2 zero width
70		// spans which the Virge chips display as a line completely across the
71		// screen;  thus, the following if statement discards any span with zero
72		// or negative width.
73
74		if (w <= 0)
75			continue;
76
77		// Draw the span as a rectangle with a height of 1 to avoid the
78		// extra complexity of drawing a line.
79
80		gInfo.WaitQueue(4);
81		WriteReg32(PAT_FG_CLR, color);
82		WriteReg32(RWIDTH_HEIGHT, ((w - 1) << 16) | 1);
83		WriteReg32(RDEST_XY, (x << 16) | y);
84		WriteReg32(CMD_SET, cmd);
85		WaitForSync();
86	}
87}
88
89
90void
91Virge_InvertRectangle(engine_token* et, fill_rect_params* pList, uint32 count)
92{
93	int rop = 0x55;			// use GXinvert for rop
94	int cmd = DRAW | rop << 17 | CMD_RECT | CMD_XP | CMD_YP;
95
96	(void)et;		// avoid compiler warning for unused arg
97
98	cmd |= gInfo.sharedInfo->commonCmd;
99
100	while (count--) {
101		int x = pList->left;
102		int y = pList->top;
103		int w = pList->right - x + 1;
104		int h = pList->bottom - y + 1;
105
106		gInfo.WaitQueue(3);
107		WriteReg32(RWIDTH_HEIGHT, ((w - 1) << 16) + h);
108		WriteReg32(RDEST_XY, (x << 16) | y);
109		WriteReg32(CMD_SET, cmd);
110		WaitForSync();
111
112		pList++;
113	}
114}
115
116
117void
118Virge_ScreenToScreenBlit(engine_token* et, blit_params* pList, uint32 count)
119{
120	int rop = 0xCC;		// use GXcopy for rop
121	int cmd = DRAW | rop << 17 | CMD_BITBLT | CMD_XP | CMD_YP;
122
123	(void)et;		// avoid compiler warning for unused arg
124
125	cmd |= gInfo.sharedInfo->commonCmd;
126
127	while (count--) {
128		int src_x = pList->src_left;
129		int src_y = pList->src_top;
130		int dest_x = pList->dest_left;
131		int dest_y = pList->dest_top;
132		int width = pList->width;
133		int height = pList->height;
134
135		if (src_x == dest_x &&  src_y == dest_y)
136			continue;
137
138		cmd |= CMD_XP | CMD_YP;		// restore these flags in case removed on last iteration
139
140		if (src_x < dest_x) {
141			src_x += width;
142			dest_x += width;
143			cmd &= ~CMD_XP;
144		}
145
146		if (src_y < dest_y) {
147			src_y += height;
148			dest_y += height;
149			cmd &= ~CMD_YP;
150		}
151
152		gInfo.WaitQueue(4);
153		WriteReg32(RWIDTH_HEIGHT, ((width) << 16) | (height + 1));
154		WriteReg32(RSRC_XY, (src_x << 16) | src_y);
155		WriteReg32(RDEST_XY, (dest_x << 16) | dest_y);
156		WriteReg32(CMD_SET, cmd);
157		WaitForSync();
158
159		pList ++;
160	}
161}
162