xref: /haiku/src/add-ons/accelerants/s3/virge_draw.cpp (revision 35db13ea5a14c9f6fee81f3de4d54a2fe42502b8)
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 
WaitForSync()19 static inline void WaitForSync()
20 {
21 	while ((IN_SUBSYS_STAT() & 0x2000) == 0) ;
22 }
23 
24 
25 
26 void
Virge_FillRectangle(engine_token * et,uint32 color,fill_rect_params * pList,uint32 count)27 Virge_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 
54 void
Virge_FillSpan(engine_token * et,uint32 color,uint16 * pList,uint32 count)55 Virge_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 
90 void
Virge_InvertRectangle(engine_token * et,fill_rect_params * pList,uint32 count)91 Virge_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 
117 void
Virge_ScreenToScreenBlit(engine_token * et,blit_params * pList,uint32 count)118 Virge_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