1 #ifdef SH7723_DEBUG_BLT
2 #define DIRECT_ENABLE_DEBUG
3 #endif
4
5
6 #include <config.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10
11 #include <sys/mman.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <malloc.h>
15 #include <errno.h>
16
17 #include <asm/types.h>
18
19 #include <directfb.h>
20
21 #include <direct/debug.h>
22 #include <direct/mem.h>
23 #include <direct/memcpy.h>
24 #include <direct/messages.h>
25 #include <direct/util.h>
26
27 #include <core/coredefs.h>
28 #include <core/coretypes.h>
29
30 #include <core/state.h>
31 #include <core/gfxcard.h>
32 #include <core/surface.h>
33 #include <core/surface_buffer.h>
34
35 #include <gfx/convert.h>
36
37 #include "sh7722.h"
38
39 #include "sh7723_blt.h"
40
41
42 D_DEBUG_DOMAIN( SH7723_BLT, "SH7723/BLT", "Renesas SH7723 Drawing Engine" );
43
44 /*
45 * State validation flags.
46 *
47 * There's no prefix because of the macros below.
48 */
49 enum {
50 DEST = 0x00000001,
51 CLIP = 0x00000002,
52 DEST_CLIP = 0x00000003,
53
54 COLOR16 = 0x00000100,
55
56 ALPHA = 0x00001000,
57
58 SOURCE = 0x00010000,
59 STRANS = 0x00020000,
60
61 ALL = 0x00031103,
62 };
63
64 /*
65 * State handling macros.
66 */
67
68 #define SH7723_VALIDATE(flags) do { sdev->v_flags |= (flags); } while (0)
69 #define SH7723_INVALIDATE(flags) do { sdev->v_flags &= ~(flags); } while (0)
70
71 #define SH7723_CHECK_VALIDATE(flag) do { \
72 if ((sdev->v_flags & flag) != flag) \
73 sh7723_validate_##flag( sdrv, sdev, state ); \
74 } while (0)
75
76 #define DUMP_INFO() D_DEBUG_AT( SH7723_BLT, " -> %srunning, hw %d-%d, next %d-%d - %svalid\n", \
77 sdrv->gfx_shared->hw_running ? "" : "not ", \
78 sdrv->gfx_shared->hw_start, \
79 sdrv->gfx_shared->hw_end, \
80 sdrv->gfx_shared->next_start, \
81 sdrv->gfx_shared->next_end, \
82 sdrv->gfx_shared->next_valid ? "" : "not " );
83
84 /**********************************************************************************************************************/
85
86 static inline bool
start_hardware(SH7722DriverData * sdrv)87 start_hardware( SH7722DriverData *sdrv )
88 {
89 SH772xGfxSharedArea *shared = sdrv->gfx_shared;
90
91 D_DEBUG_AT( SH7723_BLT, "%s()\n", __FUNCTION__ );
92
93 DUMP_INFO();
94
95 if (shared->hw_running || !shared->next_valid || shared->next_end == shared->next_start)
96 return false;
97
98 shared->hw_running = true;
99 shared->hw_start = shared->next_start;
100 shared->hw_end = shared->next_end;
101
102 shared->next_start = shared->next_end = (shared->hw_end + 1 + 3) & ~3;
103 shared->next_valid = false;
104
105 shared->num_words += shared->hw_end - shared->hw_start;
106
107 shared->num_starts++;
108
109 DUMP_INFO();
110
111 D_ASSERT( shared->buffer[shared->hw_end] == M2DG_OPCODE_TRAP );
112
113 SH7722_TDG_SETREG32( sdrv, M2DG_DLSAR, shared->buffer_phys + shared->hw_start*4 );
114 SH7722_TDG_SETREG32( sdrv, M2DG_SCLR, 1 );
115 return true;
116 }
117
118 __attribute__((noinline))
119 static void
flush_prepared(SH7722DriverData * sdrv)120 flush_prepared( SH7722DriverData *sdrv )
121 {
122 SH772xGfxSharedArea *shared = sdrv->gfx_shared;
123 unsigned int timeout = 2;
124
125 D_DEBUG_AT( SH7723_BLT, "%s()\n", __FUNCTION__ );
126
127 DUMP_INFO();
128
129 D_ASSERT( sdrv->prep_num < SH772xGFX_BUFFER_WORDS );
130 D_ASSERT( sdrv->prep_num <= D_ARRAY_SIZE(sdrv->prep_buf) );
131
132 /* Something prepared? */
133 while (sdrv->prep_num) {
134 int next_end;
135
136 /* Mark shared information as invalid. From this point on the interrupt handler
137 * will not continue with the next block, and we'll start the hardware ourself. */
138 shared->next_valid = false;
139
140 /* Check if there's enough space at the end.
141 * Wait until hardware has started next block before it gets too big. */
142 if (shared->next_end + sdrv->prep_num >= SH772xGFX_BUFFER_WORDS ||
143 shared->next_end - shared->next_start >= SH772xGFX_BUFFER_WORDS/4) {
144 /* If there's no next block waiting, start at the beginning. */
145 if (shared->next_start == shared->next_end)
146 shared->next_start = shared->next_end = 0;
147 else {
148 D_ASSERT( shared->buffer[shared->hw_end] == M2DG_OPCODE_TRAP );
149
150 /* Mark area as valid again. */
151 shared->next_valid = true;
152
153 /* Start in case it got idle while doing the checks. */
154 if (!start_hardware( sdrv )) {
155 /*
156 * Hardware has not been started (still running).
157 * Check for timeout. */
158 if (!timeout--) {
159 D_ERROR( "SH7723/Blt: Timeout waiting for processing!\n" );
160 direct_log_printf( NULL, " -> %srunning, hw %d-%d, next %d-%d - %svalid\n", \
161 sdrv->gfx_shared->hw_running ? "" : "not ", \
162 sdrv->gfx_shared->hw_start, \
163 sdrv->gfx_shared->hw_end, \
164 sdrv->gfx_shared->next_start, \
165 sdrv->gfx_shared->next_end, \
166 sdrv->gfx_shared->next_valid ? "" : "not " );
167 D_ASSERT( shared->buffer[shared->hw_end] == M2DG_OPCODE_TRAP );
168 sh7723EngineReset( sdrv, sdrv->dev );
169 }
170
171 /* Wait til next block is started. */
172 ioctl( sdrv->gfx_fd, SH772xGFX_IOCTL_WAIT_NEXT );
173 }
174
175 /* Start over with the checks. */
176 continue;
177 }
178 }
179
180 /* We are appending in case there was already a next block. */
181 next_end = shared->next_end + sdrv->prep_num;
182
183 /* Reset the timeout counter. */
184 timeout = 2;
185
186 /* While the hardware is running... */
187 while (shared->hw_running) {
188 D_ASSERT( shared->buffer[shared->hw_end] == M2DG_OPCODE_TRAP );
189
190 /* ...make sure we don't over lap with its current buffer, otherwise wait. */
191 if (shared->hw_start > next_end || shared->hw_end < shared->next_start)
192 break;
193
194 /* Check for timeout. */
195 if (!timeout--) {
196 D_ERROR( "SH7723/Blt: Timeout waiting for space!\n" );
197 direct_log_printf( NULL, " -> %srunning, hw %d-%d, next %d-%d - %svalid\n", \
198 sdrv->gfx_shared->hw_running ? "" : "not ", \
199 sdrv->gfx_shared->hw_start, \
200 sdrv->gfx_shared->hw_end, \
201 sdrv->gfx_shared->next_start, \
202 sdrv->gfx_shared->next_end, \
203 sdrv->gfx_shared->next_valid ? "" : "not " );
204 D_ASSERT( shared->buffer[shared->hw_end] == M2DG_OPCODE_TRAP );
205 sh7723EngineReset( sdrv, sdrv->dev );
206 }
207
208 /* Wait til next block is started. */
209 ioctl( sdrv->gfx_fd, SH772xGFX_IOCTL_WAIT_NEXT );
210 }
211
212 /* Copy from local to shared buffer. */
213 direct_memcpy( (void*) &shared->buffer[shared->next_end], &sdrv->prep_buf[0], sdrv->prep_num * sizeof(__u32) );
214
215 /* Terminate the block. */
216 shared->buffer[next_end] = M2DG_OPCODE_TRAP;
217
218 /* Update next block information and mark valid. */
219 shared->next_end = next_end;
220 shared->next_valid = true;
221
222 /* Reset local counter. */
223 sdrv->prep_num = 0;
224 }
225
226 /* Start in case it is idle. */
227 start_hardware( sdrv );
228 }
229
230 static inline __u32 *
start_buffer(SH7722DriverData * sdrv,int space)231 start_buffer( SH7722DriverData *sdrv,
232 int space )
233 {
234 /* Check for space in local buffer. */
235 if (sdrv->prep_num + space > SH7722GFX_MAX_PREPARE) {
236 /* Flush local buffer. */
237 flush_prepared( sdrv );
238
239 D_ASSERT( sdrv->prep_num == 0 );
240 }
241
242 /* Return next write position. */
243 return &sdrv->prep_buf[sdrv->prep_num];
244 }
245
246 static inline void
submit_buffer(SH7722DriverData * sdrv,int entries)247 submit_buffer( SH7722DriverData *sdrv,
248 int entries )
249 {
250 D_ASSERT( sdrv->prep_num + entries <= SH7722GFX_MAX_PREPARE );
251
252 /* Increment next write position. */
253 sdrv->prep_num += entries;
254 }
255
256 /**********************************************************************************************************************/
257
258 static inline void
sh7723_validate_DEST_CLIP(SH7722DriverData * sdrv,SH7722DeviceData * sdev,CardState * state)259 sh7723_validate_DEST_CLIP( SH7722DriverData *sdrv,
260 SH7722DeviceData *sdev,
261 CardState *state )
262 {
263 __u32 *prep = start_buffer( sdrv, 18 );
264
265 D_DEBUG_AT( SH7723_BLT, "%s( 0x%08lx [%d] - %4d,%4d-%4dx%4d )\n", __FUNCTION__,
266 state->dst.phys, state->dst.pitch, DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ) );
267
268 prep[0] = M2DG_OPCODE_WPR;
269 prep[1] = 0x0d4;
270 prep[2] = SH7723_XY( state->clip.x1, state->clip.y1 ) ;
271
272 prep[3] = M2DG_OPCODE_WPR;
273 prep[4] = 0x0d8;
274 prep[5] = SH7723_XY( state->clip.x2, state->clip.y2) ;
275
276 if (sdev->v_flags & DEST) {
277 submit_buffer( sdrv, 6 );
278 }
279 else {
280 CoreSurface *surface = state->destination;
281 CoreSurfaceBuffer *buffer = state->dst.buffer;
282
283 sdev->dst_phys = state->dst.phys;
284 sdev->dst_pitch = state->dst.pitch;
285 sdev->dst_bpp = DFB_BYTES_PER_PIXEL( buffer->format );
286 sdev->dst_index = DFB_PIXELFORMAT_INDEX( buffer->format ) % DFB_NUM_PIXELFORMATS;
287
288 sdev->rclr &= ~0x00140000;
289
290 switch (buffer->format) {
291 case DSPF_RGB16:
292 sdev->rclr |= 0x00040000;
293 break;
294
295 case DSPF_ARGB1555:
296 sdev->rclr |= 0x00140000;
297 break;
298
299 default:
300 D_BUG("Unexpected pixelformat\n");
301 return;
302 }
303
304 /* Set destination start address. */
305 prep[ 6] = M2DG_OPCODE_WPR;
306 prep[ 7] = 0x50;
307 prep[ 8] = sdev->dst_phys;
308
309 /* Set destination stride. */
310 prep[ 9] = M2DG_OPCODE_WPR;
311 prep[10] = 0x5c;
312 prep[11] = sdev->dst_pitch / sdev->dst_bpp;
313
314 /* Set destination pixelformat in rendering control. */
315 prep[12] = M2DG_OPCODE_WPR;
316 prep[13] = 0xc0;
317 prep[14] = sdev->rclr;
318
319 /* Set system clipping rectangle. */
320 prep[15] = M2DG_OPCODE_WPR;
321 prep[16] = 0xd0;
322 prep[17] = SH7723_XY( surface->config.size.w - 1, surface->config.size.h - 1 );
323
324 submit_buffer( sdrv, 18 );
325 }
326
327 /* Set the flags. */
328 SH7723_VALIDATE( DEST_CLIP );
329 }
330
331 static inline void
sh7723_validate_COLOR16(SH7722DriverData * sdrv,SH7722DeviceData * sdev,CardState * state)332 sh7723_validate_COLOR16( SH7722DriverData *sdrv,
333 SH7722DeviceData *sdev,
334 CardState *state )
335 {
336 sdev->color16 = dfb_pixel_from_color( state->destination->config.format, &state->color );
337
338 /* Set the flags. */
339 SH7723_VALIDATE( COLOR16 );
340 }
341
342 static inline void
sh7723_validate_ALPHA(SH7722DriverData * sdrv,SH7722DeviceData * sdev,CardState * state)343 sh7723_validate_ALPHA( SH7722DriverData *sdrv,
344 SH7722DeviceData *sdev,
345 CardState *state )
346 {
347 __u32 *prep = start_buffer( sdrv, 3 );
348
349 prep[0] = M2DG_OPCODE_WPR;
350 prep[1] = 0x088;
351 prep[2] = state->color.a;
352
353 submit_buffer( sdrv, 3 );
354
355 /* Set the flags. */
356 SH7723_VALIDATE( ALPHA );
357 }
358
359 static inline void
sh7723_validate_SOURCE(SH7722DriverData * sdrv,SH7722DeviceData * sdev,CardState * state)360 sh7723_validate_SOURCE( SH7722DriverData *sdrv,
361 SH7722DeviceData *sdev,
362 CardState *state )
363 {
364 __u32 *prep = start_buffer( sdrv, 6 );
365
366 CoreSurfaceBuffer *buffer = state->src.buffer;
367
368 sdev->src_phys = state->src.phys;
369 sdev->src_pitch = state->src.pitch;
370 sdev->src_bpp = DFB_BYTES_PER_PIXEL( buffer->format );
371 sdev->src_index = DFB_PIXELFORMAT_INDEX( buffer->format ) % DFB_NUM_PIXELFORMATS;
372
373 /* Set source start address. */
374 prep[0] = M2DG_OPCODE_WPR;
375 prep[1] = 0x4c;
376 prep[2] = sdev->src_phys;
377
378 /* Set source stride. */
379 prep[3] = M2DG_OPCODE_WPR;
380 prep[4] = 0x58;
381 prep[5] = sdev->src_pitch / sdev->src_bpp;
382
383 submit_buffer( sdrv, 6 );
384
385 /* Set the flags. */
386 SH7723_VALIDATE( SOURCE );
387 }
388
389 static inline void
sh7723_validate_STRANS(SH7722DriverData * sdrv,SH7722DeviceData * sdev,CardState * state)390 sh7723_validate_STRANS( SH7722DriverData *sdrv,
391 SH7722DeviceData *sdev,
392 CardState *state )
393 {
394 __u32 *prep = start_buffer( sdrv, 3 );
395
396 prep[0] = M2DG_OPCODE_WPR;
397 prep[1] = 0x080;
398 prep[2] = state->src_colorkey;
399
400 submit_buffer( sdrv, 3 );
401
402 /* Set the flags. */
403 SH7723_VALIDATE( STRANS );
404 }
405
406 /**********************************************************************************************************************/
407
408 DFBResult
sh7723EngineSync(void * drv,void * dev)409 sh7723EngineSync( void *drv, void *dev )
410 {
411 DFBResult ret = DFB_OK;
412 SH7722DriverData *sdrv = drv;
413 SH772xGfxSharedArea *shared = sdrv->gfx_shared;
414
415 D_DEBUG_AT( SH7723_BLT, "%s()\n", __FUNCTION__ );
416
417 DUMP_INFO();
418
419 while (shared->hw_running && ioctl( sdrv->gfx_fd, SH772xGFX_IOCTL_WAIT_IDLE ) < 0) {
420 if (errno == EINTR)
421 continue;
422
423 ret = errno2result( errno );
424 D_PERROR( "SH7723/BLT: SH7723GFX_IOCTL_WAIT_IDLE failed!\n" );
425
426 direct_log_printf( NULL, " -> %srunning, hw %d-%d, next %d-%d - %svalid\n", \
427 sdrv->gfx_shared->hw_running ? "" : "not ", \
428 sdrv->gfx_shared->hw_start, \
429 sdrv->gfx_shared->hw_end, \
430 sdrv->gfx_shared->next_start, \
431 sdrv->gfx_shared->next_end, \
432 sdrv->gfx_shared->next_valid ? "" : "not " );
433
434 break;
435 }
436
437 if (ret == DFB_OK) {
438 D_ASSERT( !shared->hw_running );
439 D_ASSERT( !shared->next_valid );
440 }
441
442 return ret;
443 }
444
445 void
sh7723EngineReset(void * drv,void * dev)446 sh7723EngineReset( void *drv, void *dev )
447 {
448 SH7722DriverData *sdrv = drv;
449 __u32 *prep;
450
451 D_DEBUG_AT( SH7723_BLT, "%s()\n", __FUNCTION__ );
452
453 DUMP_INFO();
454
455 ioctl( sdrv->gfx_fd, SH772xGFX_IOCTL_RESET );
456
457 prep = start_buffer( sdrv, 4 );
458
459 /* Reset current pointer. */
460 prep[0] = M2DG_OPCODE_MOVE;
461 prep[1] = 0;
462
463 /* Reset local offset. */
464 prep[2] = M2DG_OPCODE_LCOFS;
465 prep[3] = 0;
466
467 submit_buffer( sdrv, 4 );
468 }
469
470 void
sh7723EmitCommands(void * drv,void * dev)471 sh7723EmitCommands( void *drv, void *dev )
472 {
473 SH7722DriverData *sdrv = drv;
474
475 D_DEBUG_AT( SH7723_BLT, "%s()\n", __FUNCTION__ );
476
477 flush_prepared( sdrv );
478 }
479
480 void
sh7723FlushTextureCache(void * drv,void * dev)481 sh7723FlushTextureCache( void *drv, void *dev )
482 {
483 SH7722DriverData *sdrv = drv;
484 __u32 *prep = start_buffer( sdrv, 1 );
485
486 D_DEBUG_AT( SH7723_BLT, "%s()\n", __FUNCTION__ );
487
488 DUMP_INFO();
489
490 prep[0] = M2DG_OPCODE_SYNC | M2DG_SYNC_TCLR;
491
492 submit_buffer( sdrv, 1 );
493 }
494
495 /**********************************************************************************************************************/
496
497 void
sh7723CheckState(void * drv,void * dev,CardState * state,DFBAccelerationMask accel)498 sh7723CheckState( void *drv,
499 void *dev,
500 CardState *state,
501 DFBAccelerationMask accel )
502 {
503 D_DEBUG_AT( SH7723_BLT, "%s( %p, 0x%08x )\n", __FUNCTION__, state, accel );
504
505 /* Return if the desired function is not supported at all. */
506 if (accel & ~(SH7723_SUPPORTED_DRAWINGFUNCTIONS | SH7723_SUPPORTED_BLITTINGFUNCTIONS))
507 return;
508
509 /* Return if the destination format is not supported. */
510 switch (state->destination->config.format) {
511 case DSPF_RGB16:
512 // case DSPF_ARGB1555:
513 break;
514
515 default:
516 return;
517 }
518
519 /* Check if drawing or blitting is requested. */
520 if (DFB_DRAWING_FUNCTION( accel )) {
521 /* Return if unsupported drawing flags are set. */
522 if (state->drawingflags & ~SH7723_SUPPORTED_DRAWINGFLAGS)
523 return;
524
525 /* Return if blending with unsupported blend functions is requested. */
526 if (state->drawingflags & DSDRAW_BLEND) {
527 switch (accel) {
528 case DFXL_FILLRECTANGLE:
529 case DFXL_FILLTRIANGLE:
530 break;
531 default:
532 return;
533 }
534
535 /* Return if blending with unsupported blend functions is requested. */
536 if (state->src_blend != DSBF_SRCALPHA || state->dst_blend != DSBF_INVSRCALPHA)
537 return;
538
539 /* XOR only without blending. */
540 if (state->drawingflags & DSDRAW_XOR)
541 return;
542 }
543
544 /* Enable acceleration of drawing functions. */
545 state->accel |= accel;
546 } else {
547 DFBSurfaceBlittingFlags flags = state->blittingflags;
548
549 /* Return if unsupported blitting flags are set. */
550 if (flags & ~SH7723_SUPPORTED_BLITTINGFLAGS)
551 return;
552
553 /* Return if the source format is not supported. */
554 if (state->source->config.format != state->destination->config.format)
555 return;
556
557 /* Return if blending with unsupported blend functions is requested. */
558 if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {
559 if (state->src_blend != DSBF_SRCALPHA || state->dst_blend != DSBF_INVSRCALPHA)
560 return;
561 }
562
563 /* XOR only without blending etc. */
564 if (flags & DSBLIT_XOR &&
565 flags & ~(DSBLIT_SRC_COLORKEY | DSBLIT_ROTATE180 | DSBLIT_XOR))
566 return;
567
568 /* Return if colorizing for non-font surfaces is requested. */
569 if ((flags & DSBLIT_COLORIZE) && !(state->source->type & CSTF_FONT))
570 return;
571
572 /* Return if blending with both alpha channel and value is requested. */
573 if (D_FLAGS_ARE_SET( flags, DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA))
574 return;
575
576 /* Enable acceleration of blitting functions. */
577 state->accel |= accel;
578 }
579 }
580
581 /*
582 * Make sure that the hardware is programmed for execution of 'accel' according to the 'state'.
583 */
584 void
sh7723SetState(void * drv,void * dev,GraphicsDeviceFuncs * funcs,CardState * state,DFBAccelerationMask accel)585 sh7723SetState( void *drv,
586 void *dev,
587 GraphicsDeviceFuncs *funcs,
588 CardState *state,
589 DFBAccelerationMask accel )
590 {
591 SH7722DriverData *sdrv = drv;
592 SH7722DeviceData *sdev = dev;
593 StateModificationFlags modified = state->mod_hw;
594
595 D_DEBUG_AT( SH7723_BLT, "%s( %p, 0x%08x ) <- modified 0x%08x\n",
596 __FUNCTION__, state, accel, modified );
597
598 DUMP_INFO();
599
600 /*
601 * 1) Invalidate hardware states
602 *
603 * Each modification to the hw independent state invalidates one or more hardware states.
604 */
605
606 /* Simply invalidate all? */
607 if (modified == SMF_ALL) {
608 SH7723_INVALIDATE( ALL );
609 } else if (modified) {
610 /* Invalidate destination registers. */
611 if (modified & SMF_DESTINATION)
612 SH7723_INVALIDATE( DEST | COLOR16 );
613
614 /* Invalidate clipping registers. */
615 if (modified & SMF_CLIP)
616 SH7723_INVALIDATE( CLIP );
617
618 /* Invalidate color registers. */
619 if (modified & SMF_COLOR)
620 SH7723_INVALIDATE( ALPHA | COLOR16 );
621
622 /* Invalidate source registers. */
623 if (modified & SMF_SOURCE)
624 SH7723_INVALIDATE( SOURCE );
625
626 /* Invalidate source colorkey. */
627 if (modified & SMF_SRC_COLORKEY)
628 SH7723_INVALIDATE( STRANS );
629 }
630
631 /*
632 * 2) Validate hardware states
633 *
634 * Each function has its own set of states that need to be validated.
635 */
636
637 /* Always requiring valid destination and clip. */
638 SH7723_CHECK_VALIDATE( DEST_CLIP );
639
640 /* Depending on the function... */
641 switch (accel) {
642 case DFXL_FILLRECTANGLE:
643 case DFXL_DRAWRECTANGLE:
644 case DFXL_FILLTRIANGLE:
645 case DFXL_DRAWLINE:
646 /* ...require valid color. */
647 SH7723_CHECK_VALIDATE( COLOR16 );
648
649 /* If blending is used, validate the alpha value. */
650 if (state->drawingflags & DSDRAW_BLEND)
651 SH7723_CHECK_VALIDATE( ALPHA );
652
653 /*
654 * 3) Tell which functions can be called without further validation, i.e. SetState()
655 *
656 * When the hw independent state is changed, this collection is reset.
657 */
658 state->set = SH7723_SUPPORTED_DRAWINGFUNCTIONS;
659
660 break;
661
662 case DFXL_BLIT:
663 /* ...require valid source. */
664 SH7723_CHECK_VALIDATE( SOURCE );
665
666 /* If blending is used, validate the alpha value. */
667 if (state->blittingflags & DSBLIT_BLEND_COLORALPHA)
668 SH7723_CHECK_VALIDATE( ALPHA );
669
670 /* If colorkeying is used, validate the colorkey. */
671 if (state->blittingflags & DSBLIT_SRC_COLORKEY)
672 SH7723_CHECK_VALIDATE( STRANS );
673
674 /*
675 * 3) Tell which functions can be called without further validation, i.e. SetState()
676 *
677 * When the hw independent state is changed, this collection is reset.
678 */
679 state->set = SH7723_SUPPORTED_BLITTINGFUNCTIONS;
680
681 break;
682
683 default:
684 D_BUG( "unexpected drawing/blitting function" );
685 break;
686
687 }
688
689 sdev->dflags = state->drawingflags;
690 sdev->bflags = state->blittingflags;
691 sdev->render_options = state->render_options;
692 sdev->color = state->color;
693
694 /*
695 * 4) Clear modification flags
696 *
697 * All flags have been evaluated in 1) and remembered for further validation.
698 * If the hw independent state is not modified, this function won't get called
699 * for subsequent rendering functions, unless they aren't defined by 3).
700 */
701 state->mod_hw = 0;
702 }
703
704 /**********************************************************************************************************************/
705
706 /*
707 * Render a filled rectangle using the current hardware state.
708 */
709 bool
sh7723FillRectangle(void * drv,void * dev,DFBRectangle * rect)710 sh7723FillRectangle( void *drv, void *dev, DFBRectangle *rect )
711 {
712 SH7722DriverData *sdrv = drv;
713 SH7722DeviceData *sdev = dev;
714 __u32 *prep = start_buffer( sdrv, 6 );
715
716 D_DEBUG_AT( SH7723_BLT, "%s( %d, %d - %dx%d )\n", __FUNCTION__,
717 DFB_RECTANGLE_VALS( rect ) );
718 DUMP_INFO();
719
720 prep[0] = M2DG_OPCODE_BITBLTC | M2DG_DRAWMODE_CLIP;
721
722 if (sdev->dflags & DSDRAW_BLEND)
723 prep[0] |= M2DG_DRAWMODE_ALPHA;
724
725 prep[1] = 0xcc;
726 prep[2] = sdev->color16;
727 prep[3] = rect->w - 1;
728 prep[4] = rect->h - 1;
729 prep[5] = SH7723_XY( rect->x, rect->y );
730
731 submit_buffer( sdrv, 6 );
732
733 return true;
734 }
735
736 /**********************************************************************************************************************/
737
738 /*
739 * Render rectangle outlines using the current hardware state.
740 */
741 bool
sh7723DrawRectangle(void * drv,void * dev,DFBRectangle * rect)742 sh7723DrawRectangle( void *drv, void *dev, DFBRectangle *rect )
743 {
744 SH7722DriverData *sdrv = drv;
745 SH7722DeviceData *sdev = dev;
746 __u32 *prep = start_buffer(sdrv, 8 );
747
748 int x1, x2, y1, y2;
749
750 x1 = rect->x;
751 y1 = rect->y;
752 x2 = rect->x + rect->w - 1;
753 y2 = rect->y + rect->h - 1;
754
755 D_DEBUG_AT( SH7723_BLT, "%s( %d, %d - %dx%d )\n", __FUNCTION__,
756 DFB_RECTANGLE_VALS( rect ) );
757 DUMP_INFO();
758
759 prep[0] = M2DG_OPCODE_LINE_C | M2DG_DRAWMODE_CLIP;
760
761 if (sdev->dflags & DSDRAW_BLEND)
762 prep[0] |= M2DG_DRAWMODE_ALPHA;
763
764 prep[1] = (sdev->color16 << 16 ) | 5;
765 prep[2] = 0;
766
767 prep[3] = SH7723_XY( x1, y1 );
768 prep[4] = SH7723_XY( x2, y1 );
769 prep[5] = SH7723_XY( x2, y2 );
770 prep[6] = SH7723_XY( x1, y2 );
771 prep[7] = SH7723_XY( x1, y1 );
772
773 submit_buffer( sdrv, 8 );
774
775 return true;
776 }
777
778 /**********************************************************************************************************************/
779
780 /*
781 * Render a triangle using the current hardware state.
782 */
783 bool
sh7723FillTriangle(void * drv,void * dev,DFBTriangle * triangle)784 sh7723FillTriangle( void *drv, void *dev, DFBTriangle *triangle )
785 {
786 SH7722DriverData *sdrv = drv;
787 SH7722DeviceData *sdev = dev;
788 __u32 *prep = start_buffer( sdrv, 6 );
789
790 D_DEBUG_AT( SH7723_BLT, "%s( %d, %d - %dx, %d - %d, %d )\n", __FUNCTION__,
791 DFB_TRIANGLE_VALS( triangle ) );
792 DUMP_INFO();
793
794 prep[0] = M2DG_OPCODE_POLYGON_4C | M2DG_DRAWMODE_CLIP;
795
796 if (sdev->dflags & DSDRAW_BLEND)
797 prep[0] |= M2DG_DRAWMODE_ALPHA;
798
799 prep[1] = sdev->color16;
800
801 prep[2] = SH7723_XY( triangle->x1, triangle->y1 );
802 prep[3] = SH7723_XY( triangle->x2, triangle->y2 );
803 prep[4] = SH7723_XY( triangle->x3, triangle->y3 );
804 prep[5] = SH7723_XY( triangle->x3, triangle->y3 );
805
806 submit_buffer( sdrv, 6 );
807
808 /*
809 * TODO: use rlined to draw the aa'ed outline of a polygon
810 * if also aval, set blke to 1
811 */
812
813
814
815 return true;
816 }
817
818 /**********************************************************************************************************************/
819
820 /*
821 * Render a line with the specified width using the current hardware state.
822 */
823 bool
sh7723DrawLine(void * drv,void * dev,DFBRegion * line)824 sh7723DrawLine( void *drv, void *dev, DFBRegion *line )
825 {
826 SH7722DriverData *sdrv = drv;
827 SH7722DeviceData *sdev = dev;
828 __u32 *prep = start_buffer( sdrv, 5 );
829
830 D_DEBUG_AT( SH7723_BLT, "%s( %d, %d - %d, %d )\n", __FUNCTION__,
831 line->x1, line->y1, line->x2, line->y2 );
832 DUMP_INFO();
833
834 prep[0] = M2DG_OPCODE_LINE_C | M2DG_DRAWMODE_CLIP;
835
836 if (sdev->render_options & DSRO_ANTIALIAS)
837 prep[0] |= M2DG_DRAWMODE_ANTIALIAS;
838
839 prep[1] = (sdev->color16 << 16) | 2;
840 prep[2] = 0;
841
842 prep[3] = SH7723_XY( line->x1, line->y1 );
843 prep[4] = SH7723_XY( line->x2, line->y2 );
844
845 submit_buffer( sdrv, 5);
846
847 return true;
848 }
849
850 /*
851 * Blit a rectangle using the current hardware state.
852 */
853 bool
sh7723Blit(void * drv,void * dev,DFBRectangle * rect,int dx,int dy)854 sh7723Blit( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
855 {
856 SH7722DriverData *sdrv = drv;
857 SH7722DeviceData *sdev = dev;
858 __u32 *prep = start_buffer( sdrv, 6 );
859
860 D_DEBUG_AT( SH7723_BLT, "%s( %d, %d - %dx%d <- %d, %d )\n", __FUNCTION__,
861 dx, dy, rect->w, rect->h, rect->x, rect->y );
862 DUMP_INFO();
863
864 prep[0] = M2DG_OPCODE_BITBLTA | M2DG_DRAWMODE_CLIP;
865
866 if (sdev->bflags & DSBLIT_BLEND_COLORALPHA)
867 prep[0] |= M2DG_DRAWMODE_ALPHA;
868
869 if (sdev->bflags & DSBLIT_SRC_COLORKEY)
870 prep[0] |= M2DG_DRAWMODE_STRANS;
871
872 if (sdev->src_phys == sdev->dst_phys) {
873 if (dy > rect->y)
874 prep[0] |= M2DG_DRAWMODE_DSTDIR_Y | M2DG_DRAWMODE_SRCDIR_Y;
875 else if (dy == rect->y) {
876 if (dx > rect->x)
877 prep[0] |= M2DG_DRAWMODE_DSTDIR_X | M2DG_DRAWMODE_SRCDIR_X;
878 }
879 }
880
881 prep[1] = 0xcc;
882 prep[2] = SH7723_XY( rect->x, rect->y );
883 prep[3] = rect->w - 1;
884 prep[4] = rect->h - 1;
885 prep[5] = SH7723_XY( dx, dy );
886
887 submit_buffer( sdrv, 6 );
888
889 return true;
890 }
891