1/*
2	Copyright 2010 Haiku, Inc.  All rights reserved.
3	Distributed under the terms of the MIT license.
4
5	Authors:
6	Gerald Zajac
7*/
8
9
10#include "accelerant.h"
11#include "3dfx.h"
12
13
14// Constants for the DST_FORMAT register based upon the color depth.
15
16static const uint32 fmtColorDepth[] = {
17	0x10000,		// 1 byte/pixel
18	0x30000,		// 2 bytes/pixel
19	0x50000,		// 3 bytes/pixel (not used)
20	0x50000			// 4 bytes/pixel
21};
22
23
24void
25TDFX_FillRectangle(engine_token* et, uint32 color, fill_rect_params* list,
26	uint32 count)
27{
28	(void)et;		// avoid compiler warning for unused arg
29
30	DisplayModeEx& mode = gInfo.sharedInfo->displayMode;
31	uint32 fmt = mode.bytesPerRow | fmtColorDepth[mode.bytesPerPixel - 1];
32
33	TDFX_WaitForFifo(3);
34	OUTREG32(DST_FORMAT, fmt);
35	OUTREG32(COLOR_BACK, color);
36	OUTREG32(COLOR_FORE, color);
37
38	while (count--) {
39		int x = list->left;
40		int y = list->top;
41		int w = list->right - x + 1;
42		int h = list->bottom - y + 1;
43
44		TDFX_WaitForFifo(3);
45		OUTREG32(DST_SIZE, w | (h << 16));
46		OUTREG32(DST_XY,   x | (y << 16));
47		OUTREG32(CMD_2D, RECTANGLE_FILL | CMD_2D_GO | (ROP_COPY << 24));
48
49		list++;
50	}
51}
52
53
54void
55TDFX_FillSpan(engine_token* et, uint32 color, uint16* list, uint32 count)
56{
57	(void)et;		// avoid compiler warning for unused arg
58
59	DisplayModeEx& mode = gInfo.sharedInfo->displayMode;
60	uint32 fmt = mode.bytesPerRow | fmtColorDepth[mode.bytesPerPixel - 1];
61
62	TDFX_WaitForFifo(3);
63	OUTREG32(DST_FORMAT, fmt);
64	OUTREG32(COLOR_BACK, color);
65	OUTREG32(COLOR_FORE, color);
66
67	while (count--) {
68		int y = *list++;
69		int x = *list++;
70		int w = *list++ - x + 1;
71
72		if (w <= 0)
73			continue;	// discard span with zero or negative width
74
75		TDFX_WaitForFifo(3);
76		OUTREG32(DST_SIZE, w | (1 << 16));
77		OUTREG32(DST_XY,   x | (y << 16));
78		OUTREG32(CMD_2D, RECTANGLE_FILL | CMD_2D_GO | (ROP_COPY << 24));
79	}
80}
81
82
83void
84TDFX_InvertRectangle(engine_token* et, fill_rect_params* list, uint32 count)
85{
86	(void)et;		// avoid compiler warning for unused arg
87
88	DisplayModeEx& mode = gInfo.sharedInfo->displayMode;
89	uint32 fmt = mode.bytesPerRow | fmtColorDepth[mode.bytesPerPixel - 1];
90
91	TDFX_WaitForFifo(1);
92	OUTREG32(DST_FORMAT, fmt);
93
94	while (count--) {
95		int x = list->left;
96		int y = list->top;
97		int w = list->right - x + 1;
98		int h = list->bottom - y + 1;
99
100		TDFX_WaitForFifo(3);
101		OUTREG32(DST_SIZE, w | (h << 16));
102		OUTREG32(DST_XY,   x | (y << 16));
103		OUTREG32(CMD_2D, RECTANGLE_FILL | CMD_2D_GO | (ROP_INVERT << 24));
104
105		list++;
106	}
107}
108
109
110void
111TDFX_ScreenToScreenBlit(engine_token* et, blit_params* list, uint32 count)
112{
113	(void)et;		// avoid compiler warning for unused arg
114
115	DisplayModeEx& mode = gInfo.sharedInfo->displayMode;
116	uint32 fmt = mode.bytesPerRow | fmtColorDepth[mode.bytesPerPixel - 1];
117
118	TDFX_WaitForFifo(2);
119	OUTREG32(DST_FORMAT, fmt);
120	OUTREG32(SRC_FORMAT, fmt);
121
122	while (count--) {
123		int src_x = list->src_left;
124		int src_y = list->src_top;
125		int dest_x = list->dest_left;
126		int dest_y = list->dest_top;
127		int width = list->width;
128		int height = list->height;
129
130		uint32 cmd = SCRN_TO_SCRN_BLIT | CMD_2D_GO | (ROP_COPY << 24);
131
132		if (src_x <= dest_x) {
133			cmd |= X_RIGHT_TO_LEFT;
134			src_x += width;
135			dest_x += width;
136		}
137
138		if (src_y <= dest_y) {
139			cmd |= Y_BOTTOM_TO_TOP;
140			src_y += height;
141			dest_y += height;
142		}
143
144		TDFX_WaitForFifo(4);
145		OUTREG32(SRC_XY, src_x | (src_y << 16));
146		OUTREG32(DST_SIZE, (width + 1) | ((height + 1) << 16));
147		OUTREG32(DST_XY, dest_x | (dest_y << 16));
148		OUTREG32(CMD_2D, cmd);
149
150		list++;
151	}
152}
153