1/*
2	Haiku S3 Trio64 driver adapted from the X.org S3 driver.
3
4	Copyright 2001	Ani Joshi <ajoshi@unixbox.com>
5
6	Copyright 2008 Haiku, Inc.  All rights reserved.
7	Distributed under the terms of the MIT license.
8
9	Authors:
10	Gerald Zajac 2008
11*/
12
13
14#include "accel.h"
15#include "trio64.h"
16
17
18
19void
20Trio64_FillRectangle(engine_token* et, uint32 color, fill_rect_params* pList,
21					 uint32 count)
22{
23	(void)et;		// avoid compiler warning for unused arg
24
25	gInfo.WaitQueue(3);
26	WriteReg16(MULTIFUNC_CNTL, 0xa000);
27	WriteReg32(FRGD_COLOR, color);
28	WriteReg16(FRGD_MIX, FSS_FRGDCOL | 0x07);		// 7 = GXcopy rop
29
30	while (count--) {
31		int x = pList->left;
32		int y = pList->top;
33		int w = pList->right - x;
34		int h = pList->bottom - y;
35
36		gInfo.WaitQueue(5);
37		WriteReg16(CUR_X, x);
38		WriteReg16(CUR_Y, y);
39		WriteReg16(CUR_WIDTH, w);
40		WriteReg16(MULTIFUNC_CNTL, h);
41		WriteReg16(CMD, CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA);
42
43		pList++;
44	}
45}
46
47
48void
49Trio64_FillSpan(engine_token* et, uint32 color, uint16* pList, uint32 count)
50{
51	(void)et;		// avoid compiler warning for unused arg
52
53	gInfo.WaitQueue(3);
54	WriteReg16(MULTIFUNC_CNTL, 0xa000);
55	WriteReg32(FRGD_COLOR, color);
56	WriteReg16(FRGD_MIX, FSS_FRGDCOL | 0x07);		// 7 = GXcopy rop
57
58	while (count--) {
59		int y = *pList++;
60		int x = *pList++;
61		int w = *pList++ - x;
62
63		// Some S3 chips display a line completely across the screen when a
64		// span has zero width;  thus, the following if statement discards any
65		// span with zero or negative width.
66
67		if (w < 0)
68			continue;
69
70		// Draw the span as a rectangle with a height of 1 to avoid the
71		// extra complexity of drawing a line.
72
73		gInfo.WaitQueue(5);
74		WriteReg16(CUR_X, x);
75		WriteReg16(CUR_Y, y);
76		WriteReg16(CUR_WIDTH, w);
77		WriteReg16(MULTIFUNC_CNTL, 0);	// height is 1; but as computed it is 0
78		WriteReg16(CMD, CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA);
79	}
80}
81
82
83void
84Trio64_InvertRectangle(engine_token* et, fill_rect_params* pList, uint32 count)
85{
86	(void)et;		// avoid compiler warning for unused arg
87
88	gInfo.WaitQueue(2);
89	WriteReg16(MULTIFUNC_CNTL, 0xa000);
90	WriteReg16(FRGD_MIX, FSS_FRGDCOL | 0x00);		// 0 = GXinvert rop
91
92	while (count--) {
93		int x = pList->left;
94		int y = pList->top;
95		int w = pList->right - x;
96		int h = pList->bottom - y;
97
98		gInfo.WaitQueue(5);
99		WriteReg16(CUR_X, x);
100		WriteReg16(CUR_Y, y);
101		WriteReg16(CUR_WIDTH, w);
102		WriteReg16(MULTIFUNC_CNTL, h);
103		WriteReg16(CMD, CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA);
104
105		pList++;
106	}
107}
108
109
110void
111Trio64_ScreenToScreenBlit(engine_token* et, blit_params* pList, uint32 count)
112{
113	(void)et;		// avoid compiler warning for unused arg
114
115	gInfo.WaitQueue(2);
116	WriteReg16(MULTIFUNC_CNTL, 0xa000);
117	WriteReg16(FRGD_MIX, FSS_BITBLT | 0x07);		// 7 = GXcopy rop
118
119	while (count--) {
120		int src_x = pList->src_left;
121		int src_y = pList->src_top;
122		int dest_x = pList->dest_left;
123		int dest_y = pList->dest_top;
124		int width = pList->width;
125		int height = pList->height;
126
127		if (src_x == dest_x &&  src_y == dest_y)
128			continue;
129
130		int cmd = CMD_BITBLT | DRAW | INC_X | INC_Y | WRTDATA;
131
132		if (src_x < dest_x) {
133			src_x += width;
134			dest_x += width;
135			cmd &= ~INC_X;
136		}
137
138		if (src_y < dest_y) {
139			src_y += height;
140			dest_y += height;
141			cmd &= ~INC_Y;
142		}
143
144		gInfo.WaitQueue(7);
145		WriteReg16(CUR_X, src_x);
146		WriteReg16(CUR_Y, src_y);
147		WriteReg16(DESTX_DIASTP, dest_x);
148		WriteReg16(DESTY_AXSTP, dest_y);
149		WriteReg16(CUR_WIDTH, width);
150		WriteReg16(MULTIFUNC_CNTL, height);
151		WriteReg16(CMD, cmd);
152
153		pList ++;
154	}
155}
156