xref: /haiku/src/add-ons/accelerants/radeon/Acceleration.c (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 
5 	Part of Radeon accelerant
6 
7 	Public functions to provide 2D hardware acceleration
8 */
9 
10 
11 #include "radeon_accelerant.h"
12 #include "GlobalData.h"
13 #include "generic.h"
14 #include "cp_regs.h"
15 #include "3d_regs.h"
16 #include "2d_regs.h"
17 #include "mmio.h"
18 
19 
20 // currently, an CP instruction stream is written to
21 // a buffer on stack and then copied into the official
22 // CP buffer
23 
24 #define PACKET_BUFFER_LEN 0x100
25 
26 // copy screen to screen
27 //	et - ignored
28 //	list - list of rectangles
29 //	count - number of rectangles
30 void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count)
31 {
32 	virtual_card *vc = ai->vc;
33 	int offset = 0;
34 	uint32 buffer[PACKET_BUFFER_LEN];
35 
36 	SHOW_FLOW0( 4, "" );
37 
38 	for( ; count > 0; --count, ++list ) {
39 		if( offset == 0 ) {
40 			buffer[offset++] = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI;
41 			buffer[offset++] = RADEON_GMC_BRUSH_NONE
42 				| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
43 				| RADEON_GMC_SRC_DATATYPE_COLOR
44 				| RADEON_ROP3_S
45 				| RADEON_DP_SRC_SOURCE_MEMORY;
46 		}
47 
48 		buffer[offset++] = (list->src_left << 16) | list->src_top;
49 		buffer[offset++] = (list->dest_left << 16) | list->dest_top;
50 		buffer[offset++] = ((list->width + 1) << 16) | (list->height + 1);
51 
52 		if( offset + 3 > PACKET_BUFFER_LEN ) {
53 			buffer[0] |= (offset - 2) << 16;
54 
55 			Radeon_SendCP( ai, buffer, offset );
56 
57 			offset = 0;
58 		}
59 	}
60 
61 	if( offset > 0 ) {
62 		buffer[0] |= (offset - 2) << 16;
63 
64 		Radeon_SendCP( ai, buffer, offset );
65 	}
66 
67 	++ai->si->engine.count;
68 }
69 
70 
71 // fill rectangles on screen
72 //	et - ignored
73 //	colorIndex - fill colour
74 //	list - list of rectangles
75 //	count - number of rectangles
76 void FILL_RECTANGLE(engine_token *et, uint32 colorIndex,
77 	fill_rect_params *list, uint32 count)
78 {
79 	virtual_card *vc = ai->vc;
80 	int offset = 0;
81 	uint32 buffer[PACKET_BUFFER_LEN];
82 
83 	SHOW_FLOW0( 4, "" );
84 
85 	for( ; count > 0; --count, ++list ) {
86 		if( offset == 0 ) {
87 			buffer[offset++] = RADEON_CP_PACKET3_CNTL_PAINT_MULTI;
88 			buffer[offset++] = RADEON_GMC_BRUSH_SOLID_COLOR
89 				| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
90 				| RADEON_GMC_SRC_DATATYPE_COLOR
91 				| RADEON_ROP3_P;
92 			buffer[offset++] = colorIndex;
93 		}
94 
95 		buffer[offset++] = (list->left << 16) | list->top;
96 		buffer[offset++] =
97 			((list->right - list->left + 1) << 16) |
98 			(list->bottom - list->top + 1);
99 
100 		if( offset + 2 > PACKET_BUFFER_LEN ) {
101 			buffer[0] |= (offset - 2) << 16;
102 
103 			Radeon_SendCP( ai, buffer, offset );
104 
105 			offset = 0;
106 		}
107 	}
108 
109 	if( offset > 0 ) {
110 		buffer[0] |= (offset - 2) << 16;
111 
112 		Radeon_SendCP( ai, buffer, offset );
113 	}
114 
115 	++ai->si->engine.count;
116 }
117 
118 
119 // invert rectangle on screen
120 //	et - ignored
121 //	list - list of rectangles
122 //	count - number of rectangles
123 void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count)
124 {
125 	virtual_card *vc = ai->vc;
126 	int offset = 0;
127 	uint32 buffer[PACKET_BUFFER_LEN];
128 
129 	SHOW_FLOW0( 4, "" );
130 
131 	for( ; count > 0; --count, ++list ) {
132 		if( offset == 0 ) {
133 			buffer[offset++] = RADEON_CP_PACKET3_CNTL_PAINT_MULTI;
134 			buffer[offset++] = RADEON_GMC_BRUSH_NONE
135 				| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
136 				| RADEON_GMC_SRC_DATATYPE_COLOR
137 				| RADEON_ROP3_Dn;
138 		}
139 
140 		buffer[offset++] = (list->left << 16) | list->top;
141 		buffer[offset++] =
142 			((list->right - list->left + 1) << 16) |
143 			(list->bottom - list->top + 1);
144 
145 		// always leave 2 extra bytes for fix (see below)
146 		if( offset + 2 > PACKET_BUFFER_LEN - 2 ) {
147 			buffer[0] |= (offset - 2) << 16;
148 
149 			Radeon_SendCP( ai, buffer, offset );
150 
151 			offset = 0;
152 		}
153 	}
154 
155 	buffer[0] |= (offset - 2) << 16;
156 
157 	// we have to reset ROP, else we get garbage during next
158 	// CPU access; it looks like some cache coherency/forwarding
159 	// problem as it goes away later on; things like flushing the
160 	// destination cache or waiting for 2D engine or HDP to become
161 	// idle and clean didn't change a thing
162 	// (I dont't really understand what exactly happens,
163 	//  but this code fixes it)
164 	buffer[offset++] = CP_PACKET0( RADEON_DP_GUI_MASTER_CNTL, 0 );
165 	buffer[offset++] = RADEON_GMC_BRUSH_NONE
166 		| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
167 		| RADEON_GMC_SRC_DATATYPE_COLOR
168 		| RADEON_ROP3_S
169 		| RADEON_DP_SRC_SOURCE_MEMORY;
170 
171 	if( offset > 0 )
172 		Radeon_SendCP( ai, buffer, offset );
173 
174 	++ai->si->engine.count;
175 }
176 
177 // fill horizontal spans on screen
178 //	et - ignored
179 //	colorIndex - fill colour
180 //	list - list of spans
181 //	count - number of spans
182 void FILL_SPAN(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
183 {
184 	virtual_card *vc = ai->vc;
185 	int offset = 0;
186 	uint32 buffer[PACKET_BUFFER_LEN];
187 
188 	SHOW_FLOW0( 4, "" );
189 
190 	for( ; count > 0; --count ) {
191 		uint16 y, x, width;
192 
193 		if( offset == 0 ) {
194 			buffer[offset++] = RADEON_CP_PACKET3_CNTL_PAINT_MULTI;
195 			buffer[offset++] = RADEON_GMC_BRUSH_SOLID_COLOR
196 				| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
197 				| RADEON_GMC_SRC_DATATYPE_COLOR
198 				| RADEON_ROP3_P;
199 			buffer[offset++] = colorIndex;
200 		}
201 
202 		y = *list++;
203 		x = *list++;
204 		width = *list++ - x + 1;
205 
206 		buffer[offset++] = (x << 16) | y;
207 		buffer[offset++] = (width << 16) | 1;
208 
209 		if( offset + 2 > PACKET_BUFFER_LEN ) {
210 			buffer[0] |= (offset - 2) << 16;
211 
212 			Radeon_SendCP( ai, buffer, offset );
213 
214 			offset = 0;
215 		}
216 	}
217 
218 	if( offset > 0 ) {
219 		buffer[0] |= (offset - 2) << 16;
220 
221 		Radeon_SendCP( ai, buffer, offset );
222 	}
223 
224 	++ai->si->engine.count;
225 }
226 
227 
228 // prepare 2D acceleration
229 void Radeon_Init2D( accelerator_info *ai, uint32 datatype )
230 {
231 	SHOW_FLOW0( 3, "" );
232 
233 	// forget about 3D
234 	OUTREG( ai->regs, RADEON_RB3D_CNTL, 0 );
235 
236 	//Radeon_ResetEngine( ai );
237 
238 	// no siccors
239 	Radeon_WaitForFifo( ai, 1 );
240 	OUTREG( ai->regs, RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
241 		    | RADEON_DEFAULT_SC_BOTTOM_MAX));
242 
243 	// setup general flags - perhaps this is not needed as all
244 	// 2D commands contain this register
245 	Radeon_WaitForFifo( ai, 1 );
246 	OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL,
247 		(datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
248 		| RADEON_GMC_CLR_CMP_CNTL_DIS
249 
250 		| RADEON_GMC_BRUSH_SOLID_COLOR
251 		| RADEON_GMC_SRC_DATATYPE_COLOR
252 
253 		| RADEON_ROP3_P
254 		| RADEON_DP_SRC_SOURCE_MEMORY
255 		| RADEON_GMC_WR_MSK_DIS );
256 
257 
258 	// most of this init is probably not nessacary
259 	// as we neither draw lines nor use brushes
260 	Radeon_WaitForFifo( ai, 7 );
261 	OUTREG( ai->regs, RADEON_DST_LINE_START,    0);
262 	OUTREG( ai->regs, RADEON_DST_LINE_END,      0);
263 	OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
264 	OUTREG( ai->regs, RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
265 	OUTREG( ai->regs, RADEON_DP_SRC_FRGD_CLR,   0xffffffff);
266 	OUTREG( ai->regs, RADEON_DP_SRC_BKGD_CLR,   0x00000000);
267 	OUTREG( ai->regs, RADEON_DP_WRITE_MASK,     0xffffffff);
268 
269 	Radeon_WaitForIdle( ai );
270 }
271 
272 // switch to virtual card, i.e. setup all specific engine registers
273 void Radeon_ActivateVirtualCard( accelerator_info *ai )
274 {
275 	virtual_card *vc = ai->vc;
276 	uint32 buffer[3*2];
277 	uint32 pitch_offset;
278 	int idx = 0;
279 
280 	SHOW_FLOW0( 4, "" );
281 
282 	pitch_offset = (vc->fb_offset >> 10) | ((vc->pitch >> 6) << 22);
283 	buffer[idx++] = CP_PACKET0( RADEON_DEFAULT_OFFSET, 0 );
284 	buffer[idx++] = pitch_offset;
285 	buffer[idx++] = CP_PACKET0( RADEON_DST_PITCH_OFFSET, 0 );
286 	buffer[idx++] = pitch_offset;
287 	buffer[idx++] = CP_PACKET0( RADEON_SRC_PITCH_OFFSET, 0 );
288 	buffer[idx++] = pitch_offset;
289 
290 	Radeon_SendCP( ai, buffer, idx );
291 
292 	ai->si->active_vc = vc->id;
293 }
294