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