xref: /haiku/src/add-ons/accelerants/radeon/Acceleration.c (revision 17889a8c70dbb3d59c1412f6431968753c767bab)
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 "3d_regs.h"
15 #include "2d_regs.h"
16 #include "radeon_regs.h"
17 #include "mmio.h"
18 #include "CP.h"
19 
20 
21 // copy screen to screen
22 //	et - ignored
23 //	list - list of rectangles
24 //	count - number of rectangles
25 void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count)
26 {
27 	virtual_card *vc = ai->vc;
28 
29 	SHOW_FLOW0( 4, "" );
30 
31 	(void)et;
32 
33 	while( count > 0 ) {
34 		uint32 sub_count;
35 
36 		START_IB();
37 
38 		WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_BITBLT_MULTI, count,
39 			INDIRECT_BUFFER_SIZE, 3, 2 );
40 
41 		*buffer++ = 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 		for( ; sub_count > 0; --sub_count, ++list ) {
48 			*buffer++ = (list->src_left << 16) | list->src_top;
49 			*buffer++ = (list->dest_left << 16) | list->dest_top;
50 			*buffer++ = ((list->width + 1) << 16) | (list->height + 1);
51 		}
52 
53 		SUBMIT_IB_VC();
54 	}
55 
56 	++ai->si->engine.count;
57 }
58 
59 #define SRC_DSTCOLOR			0x00030000
60 #define DP_SRC_RECT				0x00000200
61 
62 void SCREEN_TO_SCREEN_BLIT_PIO(engine_token *et, blit_params *list, uint32 count)
63 {
64 	int xdir;
65 	int ydir;
66 	virtual_card *vc = ai->vc;
67 
68 	SHOW_FLOW0( 4, "" );
69 
70 	Radeon_WaitForFifo ( ai , 1 );
71 
72 	// Setup for Screen to screen blit
73 	OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT
74 								 | RADEON_GMC_BRUSH_NONE
75 								 | RADEON_GMC_SRC_DATATYPE_COLOR
76 								 | RADEON_ROP3_S
77 								 | RADEON_DP_SRC_SOURCE_MEMORY
78 								 | RADEON_GMC_SRC_PITCH_OFFSET_CNTL));
79 
80 
81 	for( ; count > 0; --count, ++list ) {
82 
83 		// make sure there is space in the FIFO for 4 register writes
84 		Radeon_WaitForFifo ( ai , 4 );
85 
86 		xdir = ((list->src_left < list->dest_left) && (list->src_top == list->dest_top)) ? -1 : 1;
87 		ydir = (list->src_top < list->dest_top) ? -1 : 1;
88 
89 		if (xdir < 0) list->src_left += list->width , list->dest_left += list->width ;
90     	if (ydir < 0) list->src_top += list->height , list->dest_top += list->height ;
91 
92 		OUTREG(ai->regs, RADEON_DP_CNTL, ((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0)
93 										| (ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
94 
95 		// Tell the engine where the source data resides.
96 		OUTREG( ai->regs, RADEON_SRC_Y_X, (list->src_top << 16 ) | list->src_left);
97 		OUTREG( ai->regs, RADEON_DST_Y_X, (list->dest_top << 16 ) | list->dest_left);
98 
99 		// this is the blt initiator.
100 		OUTREG( ai->regs, RADEON_DST_HEIGHT_WIDTH, ((list->height + 1) << 16 ) | (list->width + 1));
101 
102 	}
103 
104 	++ai->si->engine.count;
105 	(void)et;
106 
107 }
108 
109 
110 // fill rectangles on screen
111 //	et - ignored
112 //	colorIndex - fill colour
113 //	list - list of rectangles
114 //	count - number of rectangles
115 void FILL_RECTANGLE_DMA(engine_token *et, uint32 colorIndex,
116 	fill_rect_params *list, uint32 count)
117 {
118 	virtual_card *vc = ai->vc;
119 
120 	SHOW_FLOW0( 4, "" );
121 
122 	(void)et;
123 
124 	while( count > 0 ) {
125 		uint32 sub_count;
126 
127 		START_IB();
128 
129 		WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
130 			INDIRECT_BUFFER_SIZE, 2, 3 );
131 
132 		*buffer++ = RADEON_GMC_BRUSH_SOLID_COLOR
133 				| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
134 				| RADEON_GMC_SRC_DATATYPE_COLOR
135 				| RADEON_ROP3_P;
136 		*buffer++ = colorIndex;
137 
138 		for( ; sub_count > 0; --sub_count, ++list ) {
139 			*buffer++ = (list->left << 16) | list->top;
140 			*buffer++ =
141 				((list->right - list->left + 1) << 16) |
142 				(list->bottom - list->top + 1);
143 		}
144 
145 		SUBMIT_IB_VC();
146 	}
147 
148 	++ai->si->engine.count;
149 }
150 
151 
152 // fill rectangles on screen
153 //	et - ignored
154 //	colorIndex - fill colour
155 //	list - list of rectangles
156 //	count - number of rectangles
157 #define BRUSH_SOLIDCOLOR		0x00000d00
158 
159 void FILL_RECTANGLE_PIO(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count)
160 {
161 	virtual_card *vc = ai->vc;
162 
163 	SHOW_FLOW( 4, "colorIndex", colorIndex);
164 
165 	Radeon_WaitForFifo(ai, 3);
166     OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, ((vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
167 									 | RADEON_GMC_BRUSH_SOLID_COLOR
168 									 | RADEON_GMC_SRC_DATATYPE_COLOR
169 									 | RADEON_ROP3_P));
170 	// Set brush colour
171     OUTREG(ai->regs, RADEON_DP_BRUSH_FRGD_CLR,  colorIndex);
172     OUTREG(ai->regs, RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
173 
174 	for( ; count > 0; --count, ++list )
175 	{
176 
177 		Radeon_WaitForFifo(ai, 2);
178 		OUTREG(ai->regs, RADEON_DST_Y_X,          (list->top << 16) | list->left);
179 		OUTREG(ai->regs, RADEON_DST_WIDTH_HEIGHT, ((list->right - list->left + 1) << 16) | (list->bottom - list->top + 1));
180 
181 	}
182 	++ai->si->engine.count;
183 	(void)et;
184 }
185 
186 
187 
188 // invert rectangle on screen
189 //	et - ignored
190 //	list - list of rectangles
191 //	count - number of rectangles
192 void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count)
193 {
194 	virtual_card *vc = ai->vc;
195 
196 	SHOW_FLOW0( 4, "" );
197 
198 	(void)et;
199 
200 	while( count > 0 ) {
201 		uint32 sub_count;
202 
203 		START_IB();
204 
205 		// take core to leave space for ROP reset!
206 		WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
207 			INDIRECT_BUFFER_SIZE - 2, 2, 2 );
208 
209 		*buffer++ = RADEON_GMC_BRUSH_NONE
210 			| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
211 			| RADEON_GMC_SRC_DATATYPE_COLOR
212 			| RADEON_ROP3_Dn;
213 
214 		for( ; sub_count > 0; --sub_count, ++list ) {
215 			*buffer++ = (list->left << 16) | list->top;
216 			*buffer++ =
217 				((list->right - list->left + 1) << 16) |
218 				(list->bottom - list->top + 1);
219 		}
220 
221 		// we have to reset ROP, else we get garbage during next
222 		// CPU access; it looks like some cache coherency/forwarding
223 		// problem as it goes away later on; things like flushing the
224 		// destination cache or waiting for 2D engine or HDP to become
225 		// idle and clean didn't change a thing
226 		// (I dont't really understand what exactly happens,
227 		//  but this code fixes it)
228 		*buffer++ = CP_PACKET0( RADEON_DP_GUI_MASTER_CNTL, 1 );
229 		*buffer++ = RADEON_GMC_BRUSH_NONE
230 			| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
231 			| RADEON_GMC_SRC_DATATYPE_COLOR
232 			| RADEON_ROP3_S
233 			| RADEON_DP_SRC_SOURCE_MEMORY;
234 
235 		SUBMIT_IB_VC();
236 	}
237 
238 	++ai->si->engine.count;
239 }
240 
241 
242 void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count)
243 {
244 	virtual_card *vc = ai->vc;
245 
246 	SHOW_FLOW0( 4, "" );
247 
248 	Radeon_WaitForFifo(ai, 3);
249     OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, ((vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
250 									 | RADEON_GMC_BRUSH_NONE
251 									 | RADEON_GMC_SRC_DATATYPE_COLOR
252 									 | RADEON_ROP3_Dn
253 									 | RADEON_DP_SRC_SOURCE_MEMORY));
254 
255     OUTREG(ai->regs, RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
256 
257 	for( ; count > 0; --count, ++list )
258 	{
259 
260 		Radeon_WaitForFifo(ai, 2);
261 		OUTREG(ai->regs, RADEON_DST_Y_X,          (list->top << 16) | list->left);
262 		OUTREG(ai->regs, RADEON_DST_WIDTH_HEIGHT, ((list->right - list->left + 1) << 16) | (list->bottom - list->top + 1));
263 	}
264 
265 	++ai->si->engine.count;
266 	(void)et;
267 
268 }
269 
270 // fill horizontal spans on screen
271 //	et - ignored
272 //	colorIndex - fill colour
273 //	list - list of spans
274 //	count - number of spans
275 void FILL_SPAN_DMA(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
276 {
277 	virtual_card *vc = ai->vc;
278 
279 	SHOW_FLOW0( 4, "" );
280 
281 	(void)et;
282 
283 	while( count > 0 ) {
284 		uint32 sub_count;
285 
286 		START_IB();
287 
288 		WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
289 			INDIRECT_BUFFER_SIZE , 2, 3 );
290 
291 		*buffer++ = RADEON_GMC_BRUSH_SOLID_COLOR
292 			| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
293 			| RADEON_GMC_SRC_DATATYPE_COLOR
294 			| RADEON_ROP3_P;
295 		*buffer++ = colorIndex;
296 
297 		for( ; sub_count > 0; --sub_count ) {
298 			uint16 y, x, width;
299 
300 			y = *list++;
301 			x = *list++;
302 			width = *list++ - x + 1;
303 
304 			*buffer++ = (x << 16) | y;
305 			*buffer++ = (width << 16) | 1;
306 		}
307 
308 		SUBMIT_IB_VC();
309 	}
310 
311 	++ai->si->engine.count;
312 }
313 
314 
315 // fill horizontal spans on screen
316 //	et - ignored
317 //	colorIndex - fill colour
318 //	list - list of spans
319 //	count - number of spans
320 void FILL_SPAN_PIO(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
321 {
322 
323 	virtual_card *vc = ai->vc;
324 	//int offset = 0;
325 	uint16 y, x, width;
326 
327 	SHOW_FLOW0( 4, "" );
328 
329 	Radeon_WaitForFifo( ai , 1);
330     OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL, 0
331 									 | RADEON_GMC_BRUSH_SOLID_COLOR
332 									 | (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
333 									 | RADEON_GMC_SRC_DATATYPE_COLOR
334 									 | RADEON_ROP3_P);
335 
336 	if ( ai->si->asic >= rt_rv200 ) {
337 		Radeon_WaitForFifo( ai , 1);
338 		OUTREG( ai->regs, RADEON_DST_LINE_PATCOUNT, 0x55 << RADEON_BRES_CNTL_SHIFT);
339 	}
340 
341 	Radeon_WaitForFifo( ai , 1);
342 	OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR,  colorIndex);
343 
344 	for( ; count > 0; --count ) {
345 
346 		Radeon_WaitForFifo( ai , 2);
347 
348 		y = *list++;
349 		x = *list++;
350 		width = *list++ - x + 1;
351 
352 	    OUTREG( ai->regs, RADEON_DST_LINE_START,           (y << 16) | x);
353     	OUTREG( ai->regs, RADEON_DST_LINE_END,             ((y) << 16) | (x + width));
354 
355 	}
356 
357 	++ai->si->engine.count;
358 	(void)et;
359 }
360 
361 
362 void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count)
363 {
364 	if ( ai->si->acc_dma )
365 		SCREEN_TO_SCREEN_BLIT_DMA(et,list,count);
366 	else
367 		SCREEN_TO_SCREEN_BLIT_PIO(et,list,count);
368 }
369 
370 void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count)
371 {
372 	if ( ai->si->acc_dma )
373 		FILL_RECTANGLE_DMA(et, color, list, count);
374 	else
375 		FILL_RECTANGLE_PIO(et, color, list, count);
376 }
377 
378 void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count)
379 {
380 	if ( ai->si->acc_dma )
381 		INVERT_RECTANGLE_DMA(et, list, count);
382 	else
383 		INVERT_RECTANGLE_PIO(et, list, count);
384 }
385 
386 void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count)
387 {
388 	if ( ai->si->acc_dma )
389 		FILL_SPAN_DMA(et, color, list, count);
390 	else
391 		FILL_SPAN_PIO(et, color, list, count);
392 
393 }
394 
395 
396 // prepare 2D acceleration
397 void Radeon_Init2D( accelerator_info *ai )
398 {
399 	SHOW_FLOW0( 3, "" );
400 
401 	// forget about 3D
402 	if ( ai->si->acc_dma ) {
403 		START_IB();
404 		WRITE_IB_REG( RADEON_RB3D_CNTL, 0 );
405 		SUBMIT_IB();
406 	}
407 	else {
408 		OUTREG( ai->regs, RADEON_RB3D_CNTL, 0 );
409 	}
410 }
411 
412 // fill state buffer that sets 2D registers up for accelerated operations
413 void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
414 {
415 	virtual_card *vc = ai->vc;
416 	uint32 pitch_offset;
417 	uint32 *buffer = NULL, *buffer_start = NULL;
418 
419 	SHOW_FLOW0( 4, "" );
420 
421 	// set offset of frame buffer and pitch
422 	pitch_offset =
423 		((ai->si->memory[mt_local].virtual_addr_start + vc->fb_offset) >> 10) |
424 		((vc->pitch >> 6) << 22);
425 
426 	if ( ai->si->acc_dma ) {
427 		// make sure buffer is not used
428 		Radeon_InvalidateStateBuffer( ai, vc->state_buffer_idx );
429 		buffer = buffer_start = Radeon_GetIndirectBufferPtr( ai, vc->state_buffer_idx );
430 
431 		WRITE_IB_REG( RADEON_DEFAULT_OFFSET, pitch_offset );
432 		WRITE_IB_REG( RADEON_DST_PITCH_OFFSET, pitch_offset );
433 		WRITE_IB_REG( RADEON_SRC_PITCH_OFFSET, pitch_offset );
434 		// no sissors
435 		WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT,
436 			(RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX));
437 
438 		// general fluff
439 		WRITE_IB_REG( RADEON_DP_GUI_MASTER_CNTL,
440 			(datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
441 			| RADEON_GMC_CLR_CMP_CNTL_DIS
442 
443 			| RADEON_GMC_BRUSH_SOLID_COLOR
444 			| RADEON_GMC_SRC_DATATYPE_COLOR
445 
446 			| RADEON_ROP3_P
447 			| RADEON_DP_SRC_SOURCE_MEMORY
448 			| RADEON_GMC_WR_MSK_DIS );
449 
450 		// most of this init is probably not necessary
451 		// as we neither draw lines nor use brushes
452 		WRITE_IB_REG( RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
453 		WRITE_IB_REG( RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
454 		WRITE_IB_REG( RADEON_DP_SRC_FRGD_CLR,   0xffffffff);
455 		WRITE_IB_REG( RADEON_DP_SRC_BKGD_CLR,   0x00000000);
456 		WRITE_IB_REG( RADEON_DP_WRITE_MASK,     0xffffffff);
457 
458 		// this is required
459 		vc->state_buffer_size = buffer - buffer_start;
460 
461 	} else {
462 		Radeon_WaitForFifo( ai, 10 );
463 		OUTREG( ai->regs, RADEON_DEFAULT_OFFSET, pitch_offset );
464 		OUTREG( ai->regs, RADEON_DST_PITCH_OFFSET, pitch_offset );
465 		OUTREG( ai->regs, RADEON_SRC_PITCH_OFFSET, pitch_offset );
466 		// no sissors
467 		OUTREG( ai->regs, RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
468 		    | RADEON_DEFAULT_SC_BOTTOM_MAX));
469 		// general fluff
470 		OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL,
471 			(datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
472 			| RADEON_GMC_CLR_CMP_CNTL_DIS
473 
474 			| RADEON_GMC_BRUSH_SOLID_COLOR
475 			| RADEON_GMC_SRC_DATATYPE_COLOR
476 
477 			| RADEON_ROP3_P
478 			| RADEON_DP_SRC_SOURCE_MEMORY
479 			| RADEON_GMC_WR_MSK_DIS );
480 
481 		// most of this init is probably not necessary
482 		// as we neither draw lines nor use brushes
483 		OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
484 		OUTREG( ai->regs, RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
485 		OUTREG( ai->regs, RADEON_DP_SRC_FRGD_CLR,   0xffffffff);
486 		OUTREG( ai->regs, RADEON_DP_SRC_BKGD_CLR,   0x00000000);
487 		OUTREG( ai->regs, RADEON_DP_WRITE_MASK,     0xffffffff);
488 
489 	}
490 
491 	ai->si->active_vc = vc->id;
492 }
493 
494 
495 // allocate indirect buffer to contain state of virtual card
496 void Radeon_AllocateVirtualCardStateBuffer( accelerator_info *ai )
497 {
498 	virtual_card *vc = ai->vc;
499 
500 	vc->state_buffer_idx = Radeon_AllocIndirectBuffer( ai, false );
501 	// mark as being unused
502 	vc->state_buffer_size = -1;
503 }
504 
505 
506 // free indirect buffer containing state of virtual card
507 void Radeon_FreeVirtualCardStateBuffer( accelerator_info *ai )
508 {
509 	virtual_card *vc = ai->vc;
510 
511 	// make sure it's not used anymore
512 	Radeon_InvalidateStateBuffer( ai, vc->state_buffer_idx );
513 
514 	// get rid of it
515 	Radeon_FreeIndirectBuffer( ai, vc->state_buffer_idx, false );
516 }
517