CircleOS  1
dma2d_graphic.c
Go to the documentation of this file.
1 /****************** COPYRIGHT (C) 2007-2013 RAISONANCE S.A.S. *****************/
11 /******************************************************************************/
12 
13 /* Includes ------------------------------------------------------------------*/
14 #include "circle.h"
15 #include "string.h"
16 #include "DMA2D_Graphic.h"
17 
19 
20 /* Private define ------------------------------------------------------------*/
21 #define IS_FLAGREAD(n) ( FlagRead[n>>3] & (1<<(n&7)) )
22 #define SET_FLAGREAD(n) { FlagRead[n>>3] |= (1<<(n&7)); }
23 #define IS_FLAGWRITTEN(n) ( FlagWritten[n>>3] & (1<<(n&7)) )
24 #define SET_FLAGWRITTEN(n) { FlagWritten[n>>3] |= (1<<(n&7)); }
25 #define DMA2D_START_TRANSFER() {DMA2D_StartTransfer(); fTransfering = TRUE;}
26 
27 /* Private variables ---------------------------------------------------------*/
28 __attribute__( ( section( ".sdram" ) ) )
29 tDMA2D_Screen LCD_ScreenImage [MAX_DMA2D_SCREEN];
30 
31 __attribute__( ( section( ".sdram" ) ) )
32 unsigned char ObjectSingleMemoryPool [OBJECT_SINGLE_MEMORY_POOL_SIZE];
33 
34 __attribute__( ( section( ".sdram" ) ) )
35 unsigned char FlagWritten [( PHYS_SCREEN_HEIGHT* PHYS_SCREEN_WIDTH ) / 8];
36 
37 __attribute__( ( section( ".sdram" ) ) )
38 unsigned char FlagRead [( PHYS_SCREEN_HEIGHT* PHYS_SCREEN_WIDTH ) / 8];
39 
40 unsigned char* pFreeObjectMem = ObjectSingleMemoryPool;
41 
42 unsigned AvailableObjectMemory = OBJECT_SINGLE_MEMORY_POOL_SIZE;
43 
44 tDMA2D_pObject TailObj = 0;
45 
46 tDMA2D_pObject SelectedObject = 0;
47 int DisplayedScreen = 0;
48 int AddressedScreen = 0;
49 int fTransfering = FALSE;
50 
51 
52 t_DMALCD_ModeLCDAccess DMALCD_ModeLCDAccess = LCD_Only;
53 
54 
55 coord_t Xmin = -1 ;
56 coord_t Xmax = -1 ;
57 coord_t Ymin = -1 ;
58 coord_t Ymax = -1 ;
59 
60 int fNeutralX( int x, int y ) { return x; }
61 int fNeutralY( int x, int y ) { return y; }
62 tTrans CurrentTransformation = { fNeutralX, fNeutralY, 0};
63 tDMA2D_pObject pCurrentSrcObj = 0;
64 
65 //Structures
66 DMA2D_InitTypeDef DMA2D_InitStruct;
67 DMA2D_FG_InitTypeDef DMA2D_FG_InitStruct;
68 DMA2D_BG_InitTypeDef DMA2D_BG_InitStruct;
69 
70 
71 /* External variable ---------------------------------------------------------*/
72 
73 /* Private function prototypes -----------------------------------------------*/
74 
75 /* Private functions ---------------------------------------------------------*/
76 NODEBUG int fRot270X( int x, int y ) { return pCurrentSrcObj->mWidthUsed - y - 1; }
77 NODEBUG int fRot270Y( int x, int y ) { return x; }
78 NODEBUG int fRot180X( int x, int y ) { return pCurrentSrcObj->mWidthUsed - x - 1; }
79 NODEBUG int fRot180Y( int x, int y ) { return pCurrentSrcObj->mHeightUsed - y - 1; }
80 NODEBUG int fRot90X( int x, int y ) { return y; }
81 NODEBUG int fRot90Y( int x, int y ) { return pCurrentSrcObj->mHeightUsed - x - 1; }
82 
83 NODEBUG void DMA2D_WaitForEndOfTransfer()
84 {
85  if ( !fTransfering )
86  return;
87 
88  while ( DMA2D_GetFlagStatus( DMA2D_FLAG_TC ) == RESET );
89 
90  fTransfering = FALSE;
91 }
92 
93 /*******************************************************************************
94 *
95 * ResetScreenApp
96 *
97 *******************************************************************************/
103 /******************************************************************************/
104 NODEBUG void ResetScreenApp( void )
105 {
106  int i;
107 
108  pFreeObjectMem = ObjectSingleMemoryPool;
110  AvailableObjectMemory = OBJECT_SINGLE_MEMORY_POOL_SIZE;
111  TailObj = 0;
112 
113  for ( i = 1 ; i < MAX_DMA2D_SCREEN ; i++ ) //init all but screen0
114  {
115  memset( ( void* ) & ( LCD_ScreenImage[i] ), 0, sizeof( LCD_ScreenImage[i] ) );
116  }
117  LCD_ScreenImage[0].mObjectCount = 0; // all objects are deleted
118 
119  //Clear the object file
120  memset( ( void* ) & ( ObjectSingleMemoryPool ), 0, sizeof( ObjectSingleMemoryPool ) );
121 
122  //Select screen0
124 }
125 
126 /*******************************************************************************
127 *
128 * RotateIndex
129 *
130 *******************************************************************************/
141 /******************************************************************************/
142 NODEBUG static int RotateIndex( int old_orientation, int new_orientation, int k )
143 {
144  int H = PHYS_SCREEN_HEIGHT;
145  int W = PHYS_SCREEN_WIDTH;
146 
147  old_orientation %= 4;
148  new_orientation %= 4;
149  if ( old_orientation == new_orientation ) //unchanged direction
150  return k;
151 
152  else if ( ( old_orientation & 1 ) == ( new_orientation & 1 ) ) //opposite direction (180°)
153  return ( H * W - 1 - k );
154 
155  if ( old_orientation & 1 ) //old orientation was horizontal
156  {
157  //Change the width/height
158  W = PHYS_SCREEN_HEIGHT;
159  H = PHYS_SCREEN_WIDTH;
160  }
161 
162  //We have now 2 cases: clockwise or anticlockwise... (+/- 90°)
163  if ( ( 4 + new_orientation - old_orientation ) % 4 == 1 ) //Clockwise: V12=>V3, V3=>V6, etc...
164  return ( k / W ) + H * ( W - ( k % W ) - 1 );
165  else
166  return ( H - 1 - ( k / W ) ) + H * ( k % W ); //anticlockwise: V12=>V9, V9=>V6, V6=>V3,...
167 }
168 
169 
170 /*******************************************************************************
171 *
172 * DMA2D_CopyBMP
173 *
174 *******************************************************************************/
187 /******************************************************************************/
188 NODEBUG void DMA2D_CopyBMP( int scr, tDMA2D_pObject obj, int blendingmode )
189 {
190  int x = obj->mX[scr];
191  int y = obj->mY[scr];
192  u8* pdata = 0;
193  int format = obj->mStatus.mFormat; //Format
194  int ofsx = 0;
195  int ofsy = 0;
196  int pixelperline = obj->mWidthTotal; //Pixel per line
197  int numberofline = obj->mHeightTotal; //Number of line
198  int data_offset = 0;
199  unsigned fg_offset = 0;
200 
201  int pixelsize = obj->mStatus.mIsRdonly ? ( obj->mContents.mBmpDesc.mBitPerPixel >> 3 ) : 4 ;
202 
203  if ( format == -1 ) //unsupported format
204  {
205  return;
206  }
207 
208  if ( obj->mStatus.mIsPartial )
209  {
210  pixelperline = obj->mWidthUsed; //Pixel per line
211  numberofline = obj->mHeightUsed; //Number of line
212  ofsx = obj->mOffsX;
213  ofsy = obj->mOffsY;
214  x += ofsx;
215  y += ofsy;
216  data_offset = ofsy * obj->mWidthTotal + ofsx ;
217  fg_offset = obj->mWidthTotal - obj->mWidthUsed;
218  }
219  if ( !pixelperline )
220  return;
221 
222  if ( obj->mStatus.mIsRdonly )
223  {
224  pdata = ( u8* ) obj->mContents.mBmpDesc.mData; //Data to be copied (full image at a first step)
225  }
226  else
227  {
228  pdata = ( u8* ) & ( obj->mContents.mDynamicImage[0] );
229  }
230 
231  /* Initialize the alpha and RGB values */
232  DMA2D_InitStruct.DMA2D_OutputGreen = 0;
233  DMA2D_InitStruct.DMA2D_OutputBlue = 0;
234  DMA2D_InitStruct.DMA2D_OutputRed = 0;
235  DMA2D_InitStruct.DMA2D_OutputAlpha = 0;
236 
237  /* Initialize the output offset */
238  switch ( CurrentScreenOrientation )
239  {
240  case V6: case V12: //Vertical
241  {
242  //Check whether we are still inside the screen...
243  if ( ( x >= PHYS_SCREEN_WIDTH ) || ( ( x + pixelperline ) <= 0 ) )
244  return;
245 
246  if ( ( y >= PHYS_SCREEN_HEIGHT ) || ( ( y + numberofline ) <= 0 ) )
247  return;
248 
249  //Reduce the size if we are partially out
250  //First, remove the part that is on the right of the screen.
251  if ( pixelperline > ( PHYS_SCREEN_WIDTH - x ) )
252  {
253  fg_offset += pixelperline - ( PHYS_SCREEN_WIDTH - x );
254  pixelperline = ( PHYS_SCREEN_WIDTH - x );
255  }
256 
257  //Then the part on the left..
258  if ( x < 0 )
259  {
260  pixelperline += x;
261  fg_offset -= x;
262  data_offset = -x;
263  x = 0;
264  }
265 
266  //Then check the vertical position
267  if ( numberofline > ( PHYS_SCREEN_HEIGHT - y ) )
268  {
269  numberofline = ( PHYS_SCREEN_HEIGHT - y );
270  }
271  if ( y < 0 )
272  {
273  numberofline += y;
274  data_offset = -( y * obj->mWidthTotal );
275  y = 0;
276  }
277  DMA2D_InitStruct.DMA2D_OutputOffset = PHYS_SCREEN_WIDTH - pixelperline;
278  /* Output Address: back on screen */
279  DMA2D_InitStruct.DMA2D_OutputMemoryAdd = ( uint32_t ) & ( LCD_ScreenImage[DisplayedScreen].mScreenImage.mVerView[y][x] );
280  break;
281  }
282 
283  case V3: case V9: //Horizontal
284  {
285  //Check whether we are still inside the screen...
286  if ( ( x >= PHYS_SCREEN_HEIGHT ) || ( ( x + pixelperline ) <= 0 ) )
287  return;
288 
289  if ( ( y >= PHYS_SCREEN_WIDTH ) || ( ( y + numberofline ) <= 0 ) )
290  return;
291 
292  if ( pixelperline > ( PHYS_SCREEN_HEIGHT - x ) )
293  {
294  fg_offset += pixelperline - ( PHYS_SCREEN_HEIGHT - x );
295  pixelperline = ( PHYS_SCREEN_HEIGHT - x );
296  }
297 
298  //Then the part on the left..
299  if ( x < 0 )
300  {
301  pixelperline += x;
302  fg_offset -= x;
303  data_offset = -x;
304  x = 0;
305  }
306  //Then check the vertical position
307  if ( numberofline > ( PHYS_SCREEN_WIDTH - y ) )
308  {
309  numberofline = ( PHYS_SCREEN_WIDTH - y );
310  }
311 
312  if ( y < 0 )
313  {
314  numberofline += y;
315  data_offset -= ( y * obj->mWidthTotal );
316  y = 0;
317  }
318 
319  DMA2D_InitStruct.DMA2D_OutputOffset = PHYS_SCREEN_HEIGHT - pixelperline;
320  /* Output Address: back on screen */
321  DMA2D_InitStruct.DMA2D_OutputMemoryAdd = ( uint32_t ) & ( LCD_ScreenImage[DisplayedScreen].mScreenImage.mHorView[y][x] );
322  break;
323  }
324 
325  default:
326  break;
327 
328  }
329 
330  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA2D, ENABLE );
331  DMA2D_DeadTimeConfig( 255, 1 );
332 
333 #if TEST_BEFORE_TRANSFER
334  DMA2D_WaitForEndOfTransfer();
335 #endif
336 
337  DMA2D_ClearFlag( DMA2D_FLAG_CE | DMA2D_FLAG_CTC | DMA2D_FLAG_CAE | DMA2D_FLAG_TW | DMA2D_FLAG_TC | DMA2D_FLAG_TE );
338 
339  /* Number of lines : width */
340  DMA2D_InitStruct.DMA2D_NumberOfLine = numberofline;
341 
342  /* Number of pixel per line : height */
343  DMA2D_InitStruct.DMA2D_PixelPerLine = pixelperline;
344 
345  /* Output color mode */
346  DMA2D_InitStruct.DMA2D_CMode = CM_RGB888;
347 
348  if ( blendingmode )
349  {
350  /* Transfer mode => Memory to memory with pixel format conversion and blending*/
351  DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_BLEND;
352 
353  /* Configure default values for background */
354  DMA2D_BG_StructInit( &DMA2D_BG_InitStruct );
355 
356  /* Input Address at flash memory */
357  DMA2D_BG_InitStruct.DMA2D_BGMA = DMA2D_InitStruct.DMA2D_OutputMemoryAdd;
358 
359  /* Input color mode */
360  DMA2D_BG_InitStruct.DMA2D_BGCM = CM_RGB888;
361  DMA2D_BG_InitStruct.DMA2D_BGO = DMA2D_InitStruct.DMA2D_OutputOffset;
362  DMA2D_BG_InitStruct.DMA2D_BGPFC_ALPHA_VALUE = 0xFF;
363 
364  /* Initialize foreground */
365  DMA2D_BGConfig( &DMA2D_BG_InitStruct );
366  }
367  else
368  {
369  /* Transfer mode => Memory to memory with pixel format conversion*/
370  DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_PFC;
371  }
372 
373  /* Configure default values for foreground */
374  DMA2D_FG_StructInit( &DMA2D_FG_InitStruct );
375 
376  if ( obj->mStatus.mIsCst ) //Unified rectangle with a constant color.
377  {
378  DMA2D_InitStruct.DMA2D_Mode = DMA2D_R2M;
379  /* Input Address at flash memory */
380  DMA2D_InitStruct.DMA2D_CMode = CM_RGB888;
381  /* Configure A,R,G,B value : color to be used to fill user defined area */
382  DMA2D_InitStruct.DMA2D_OutputBlue = obj->mData.mARGB_Cst & 0xff ;
383  DMA2D_InitStruct.DMA2D_OutputGreen = ( obj->mData.mARGB_Cst >> 8 ) & 0xff;
384  DMA2D_InitStruct.DMA2D_OutputRed = ( obj->mData.mARGB_Cst >> 16 ) & 0xff;
385  }
386  else
387  {
388  /* Input Address at flash memory */
389  DMA2D_FG_InitStruct.DMA2D_FGMA = ( ( u32 )pdata + pixelsize * data_offset /*& 0xfffffffc*/ );
390  /* Input color mode */
391  DMA2D_FG_InitStruct.DMA2D_FGCM = format;
392  DMA2D_FG_InitStruct.DMA2D_FGO = fg_offset ;
393  DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_VALUE = obj->mStatus.mAlpha;
394  DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = 2;
395 
396  /* Initialize palettes if any */
398  {
399  DMA2D_FG_InitStruct.DMA2D_FGCMAR = ( u32 ) obj->mContents.mBmpDesc.mColorTable;
400  DMA2D_FG_InitStruct.DMA2D_FG_CLUT_SIZE = obj->mContents.mBmpDesc.mNumberOfColorInPalette;
401  DMA2D_FG_InitStruct.DMA2D_FG_CLUT_CM = CLUT_CM_ARGB8888 ; /*32 bit colors but the alpha constant is 0.. */
402  DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = 1;
403  }
404 
405  /* Initialize foreground */
406  DMA2D_FGConfig( &DMA2D_FG_InitStruct );
408  {
409  int i;
410  u32* ptrdest = ( u32* )( DMA2D_BASE + 0x400 );
411  u32* ptrsrc = ( u32* )( obj->mContents.mBmpDesc.mColorTable );
412 
413 #if 0 //FL1308: Unable to make automatic load working properly???
414  DMA2D_FGStart( ENABLE );
415  while ( DMA2D_GetFlagStatus( DMA2D_FLAG_CTC ) == RESET );
416 #else //but manual loading is fine!
417  for ( i = 0 ; i < obj->mContents.mBmpDesc.mNumberOfColorInPalette; i++ )
418  {
419  *ptrdest++ = *ptrsrc++;
420  }
421 #endif
422  }
423  }
424 
425  /* Initialize DMA2D */
426  DMA2D_Init( &DMA2D_InitStruct );
427 
428 
429  /* Start Transfer */
430  DMA2D_START_TRANSFER();
431 #if TEST_AFTER_TRANSFER
432  DMA2D_WaitForEndOfTransfer();
433 #endif
434 }
435 
437 
438 /* Public functions ---------------------------------------------------------*/
439 
440 /*******************************************************************************
441 *
442 * DRAW_DMA2D_Dispatch
443 *
444 *******************************************************************************/
456 /******************************************************************************/
457 NODEBUG u32 DRAW_DMA2D_Dispatch( u32 fct, u32 param1, u32 param2, u32 param3 )
458 {
459  switch ( fct )
460  {
461  //Screen management
462  case CD_SCREENINIT:
464  return 0;
465 
466  case CD_UPDATE:
467  DMA_LCD_UpdateScreen();
468  return 0;
469 
470  case CD_SCREENCLEAR:
471  DMA2D_ScreenClear( param1, param2 );
472  return 0;
473 
474  case CD_SCREENSELECT:
475  DMA2D_ScreenSelect( param1, param2 );
476  return 0;
477 
478  case CD_SCREENSETDIRTY:
479  DMA2D_ScreenSetDirty( param1 );
480  return 0;
481 
482  case CD_SCREENREDRAW:
483  DMA2D_ScreenRedraw( param1 );
484  return 0;
485 
486  case CD_SCREENCOPY:
487  DMA2D_ScreenCopy( param1, param2 );
488  return 0;
489 
490  //Then object specific functions
491  case CD_OBJECTCREATE:
492  return ( u32 ) DMA2D_ObjectCreate( param1, param2, param3 );
493 
494  case CD_OBJECTDELETE:
495  DMA2D_ObjectDelete( ( tDMA2D_pObject )param1 );
496  return 0;
497 
499  return DMA2D_ObjectSetToScreen( ( tDMA2D_pObject )param1, param2 );
500 
502  return DMA2D_ObjectAssignBitmap( ( tDMA2D_pObject )param1, ( void* )param2, param3 );
503 
504  case CD_OBJECTSETPARTIAL:
505  return DMA2D_ObjectSetPartial( ( tDMA2D_pObject )param1, param2, param3 );
506 
507  case CD_OBJECTSETOFFSET:
508  return DMA2D_ObjectSetOffset( ( tDMA2D_pObject )param1, param2, param3 );
509 
510  case CD_OBJECTMOVE:
511  return DMA2D_ObjectMove( ( tDMA2D_pObject )param1, param2, param3 );
512 
513  case CD_OBJECTSETVISIBLE:
514  DMA2D_ObjectSetVisible( ( tDMA2D_pObject )param1, param2 );
515  return 0;
516 
517  case CD_OBJECTSELECT:
518  return DMA2D_ObjectSelect( ( tDMA2D_pObject )param1 );
519 
521  DMA2D_ObjectSetTransparency( ( tDMA2D_pObject )param1, param2 );
522  return 0;
523 
524  case CD_OBJECTGETPIXEL :
525  return DMA2D_ObjectGetPixel( ( tDMA2D_pObject )param1, param2, param3 );
526 
528  return DMA2D_ObjectGetIntersection( param1, ( tDMA2D_pObject )param2, ( tDMA2D_pObject )param3 );
529 
530  case CD_OBJECTGETPOS :
531  return ( u32 ) DMA2D_ObjectGetPos( ( tDMA2D_pObject )param1, param2 );
532 
533  case CD_OBJECTGETSIZE :
534  return ( u32 ) DMA2D_ObjectGetSize( ( tDMA2D_pObject )param1 );
535 
536  case CD_OBJECTFIND :
537  return ( u32 ) DMA2D_ObjectFind( param1, param2, param3 );
538 
539  case CD_OBJECTGETIMAGE :
540  return ( u32 ) DMA2D_ObjectGetImage( ( tDMA2D_pObject )param1 );
541 
542  case CD_OBJECTPOPZ :
543  return ( u32 ) DMA2D_ObjectPopZ( ( tDMA2D_pObject )param1, param2 );
544 
545  case CD_OBJECTPUSHZ :
546  return ( u32 ) DMA2D_ObjectPushZ( ( tDMA2D_pObject )param1, param2 );
547 
549  return ( u32 ) DMA2D_ObjectSetForeground( ( tDMA2D_pObject )param1, param2 );
550 
552  return ( u32 ) DMA2D_ObjectSetBackground( ( tDMA2D_pObject )param1, param2 );
553 
554  case CD_SETTRANSFORM :
555  DMA2D_SetTransform( ( tFctXY )param1, ( tFctXY )param2 );
556  return 0;
557 
558  case CD_OBJECTTRANSFORM:
559  CurrentTransformation.mDefaultColor = param3;
560  return DMA2D_ObjectTransform( ( tDMA2D_pObject ) param1, ( tDMA2D_pObject ) param2, ( tTrans* ) &CurrentTransformation );
561 
563  return DMA2D_ObjectTransformReverse( ( tDMA2D_pObject ) param1, ( tDMA2D_pObject ) param2, ( tFctObjXY ) param3 );
564 
565  }
566 
567  return 0;
568 }
569 
570 
571 /*******************************************************************************
572 *
573 * DMA2D_ScreenInit
574 *
575 *******************************************************************************/
585 /******************************************************************************/
586 NODEBUG void DMA2D_ScreenInit( void )
587 {
588  int i;
589 
590  DMALCD_ModeLCDAccess = SDRAM_Only;
591 
592  //Clear all screens
593  for ( i = 0 ; i < MAX_DMA2D_SCREEN ; i++ )
594  {
595  memset( ( void* ) & ( LCD_ScreenImage[i] ), 0, sizeof( LCD_ScreenImage[i] ) );
596  }
597 
598  //Clear the object file
599  memset( ( void* ) & ( ObjectSingleMemoryPool ), 0, sizeof( ObjectSingleMemoryPool ) );
600 
601  //Select screen0
603 
604  //Create generic home page for the application on screen0
605  DRAW_Clear();
606 
607  //Update screen0
608  ResetScreenApp();
609 }
610 
611 /*******************************************************************************
612 *
613 * DMA2D_ScreenSetDirty
614 *
615 *******************************************************************************/
623 /******************************************************************************/
624 NODEBUG inline void DMA2D_ScreenSetDirty( unsigned int screen )
625 {
626  LCD_ScreenImage[screen].mStatus.mIsDirty = 1;
627 }
628 
629 /*******************************************************************************
630 *
631 * DMA2D_ScreenSelect
632 *
633 *******************************************************************************/
642 /******************************************************************************/
643 NODEBUG void DMA2D_ScreenSelect( unsigned int screen, enum SELECT_MODE mode )
644 {
645  if ( ( screen >= 0 ) && ( screen < MAX_DMA2D_SCREEN ) )
646  {
647  if ( mode & SELADDR )
648  AddressedScreen = screen;
649 
650  if ( mode & SELDISP )
651  {
652  DisplayedScreen = screen;
653  DMA2D_ScreenSetDirty( screen ) ;
654  }
655  }
656 
657  SelectedObject = 0; //Selecting a screen unselect the current object (if any)
658 }
659 
660 
661 /*******************************************************************************
662 *
663 * DMA2D_ScreenClear
664 *
665 *******************************************************************************/
673 /******************************************************************************/
674 NODEBUG void DMA2D_ScreenClear( unsigned int screen, int del )
675 {
676  int i;
677  tDMA2D_pObject obj, object_bak = SelectedObject;
678  int screen_bak = AddressedScreen;
679 
680  AddressedScreen = screen;
681  SelectedObject = 0;
682 
683  //Hide all objects
684  for ( i = 0 ; i < LCD_ScreenImage[screen].mObjectCount ; i++ )
685  {
686  obj = LCD_ScreenImage[screen].mObjectTable[i];
687  obj->mStatus.mIsVisible = 0;
688  }
689 
690  DRAW_Clear();
691 
692  AddressedScreen = screen_bak ;
693  SelectedObject = object_bak;
694 
695 }
696 
697 /*******************************************************************************
698 *
699 * DMA2D_ScreenRedraw
700 *
701 *******************************************************************************/
709 /******************************************************************************/
710 NODEBUG void DMA2D_ScreenRedraw( unsigned int screen )
711 {
712  int i;
713  tDMA2D_pObject obj;
714 
715  for ( i = 0 ; i < LCD_ScreenImage[screen].mObjectCount ; i++ )
716  {
717  obj = LCD_ScreenImage[screen].mObjectTable[i];
718  //redraw i-th object
719  //First set the FG source.
720  if ( !obj->mStatus.mIsVisible )
721  {
722  //the object is currently not displayed
723  continue;
724  }
725  if ( obj->mStatus.mIsRdonly )
726  {
727  if ( obj->mStatus.mIsCst )
728  {
729  DMA2D_CopyBMP( screen, obj, ( i != 0 ) );
730  }
731  //we have a bitmap to copy thru the DMA2D...
732  else switch ( obj->mContents.mBmpDesc.mBitPerPixel )
733  {
734  case 4:
735  case 8:
736  DMA2D_CopyBMP( screen, obj, ( i != 0 ) );
737  break;
738  case 16:
739  if ( ( obj->mContents.mBmpDesc.mCompressionMethod == 0 /*BI_RGB*/ )
740  || ( obj->mContents.mBmpDesc.mCompressionMethod == 3 /*BI_BITFIELDS*/ ) )
741  {
742  //no compression but 565 encoding
743  DMA2D_CopyBMP( screen, obj, ( i != 0 ) );
744  break;
745  }
746  continue; //Ignore this object
747  case 24:
748  continue; //Ignore this object
749  case 32:
750  if ( ( obj->mContents.mBmpDesc.mCompressionMethod == 0 /*BI_RGB*/ )
751  || ( obj->mContents.mBmpDesc.mCompressionMethod == 3 /*BI_BITFIELDS*/ ) )
752  {
753  //no compression but a888 encoding
754  DMA2D_CopyBMP( screen, obj, 1 /*( i != 0 )*/ ); // (i!=0) means blending except for the first image
755  break;
756  }
757  continue; //Ignore this object
758  default:
759  continue; //Ignore this object
760  }
761  }
762  else //it's a dynamic object. A888 format to copy...
763  {
764  DMA2D_CopyBMP( screen, obj, ( i != 0 ) ); //(i != 0) means blending except for the first image
765  }
766  //Set destination
767  }
768 
769  //Need to be optimized
770  Xmin = 0;
771  Xmax = PHYS_SCREEN_WIDTH - 1;
772  Ymin = 0;
773  Ymax = PHYS_SCREEN_HEIGHT - 1;
774 }
775 
776 /*******************************************************************************
777 *
778 * DMA2D_ObjectGetPixel
779 *
780 *******************************************************************************/
790 /******************************************************************************/
791 NODEBUG color32_t DMA2D_ObjectGetPixel( tDMA2D_pObject obj, int x, int y )
792 {
793  u32 val32 = 0;
794  u16 val16 = 0;
795  u8* pval24;
796 
797  if ( obj->mStatus.mIsVisible == FALSE )
798  return 0;
799 
800  if ( ( x < 0 ) || ( x >= obj->mWidthTotal ) )
801  return 0;
802 
803  if ( ( y < 0 ) || ( y >= obj->mHeightTotal ) )
804  return 0;
805 
806  if ( obj->mStatus.mIsRdonly )
807  {
808  switch ( ( u8 ) obj->mStatus.mFormat )
809  {
810  //we rebuild the R G B components and left-align them.
811  //then, we had the alpha channel
812  case DMA2D_RGB888:
813  pval24 = ( u8* ) & ( ( ( tpixel24* )( obj->mContents.mBmpDesc.mData ) )[y * obj->mContents.mBmpDesc.mWidth + x] );
814  val32 = pval24[0] | ( pval24[1] << 8 ) | ( pval24[2] << 16 );
815  return val32 | 0xff000000;
816 
817  case DMA2D_RGB565:
818  val16 = ( ( ( u16* )( obj->mContents.mBmpDesc.mData ) )[y * obj->mContents.mBmpDesc.mWidth + x] );
819  val32 = ( ( val16 & 0x1F ) << ( 0 + 3 ) ) | ( ( ( val16 >> 5 ) & 0x3F ) << ( 8 + 2 ) ) | ( ( ( val16 >> 11 ) & 0x1F ) << ( 16 + 3 ) ) ;
820  return val32 | 0xff000000;
821 
822  case DMA2D_ARGB1555:
823  val16 = ( ( ( u16* )( obj->mContents.mBmpDesc.mData ) )[y * obj->mContents.mBmpDesc.mWidth + x] );
824  val32 = ( ( val16 & 0x1F ) << ( 0 + 3 ) ) | ( ( ( val16 >> 5 ) & 0x1F ) << ( 8 + 3 ) ) | ( ( ( val16 >> 10 ) & 0x1F ) << ( 16 + 3 ) ) ;
825  return val32 | ( ( val16 & 0x8000 ) ? 0xff000000 : 0 );
826 
827  case DMA2D_ARGB4444:
828  val16 = ( ( ( u16* )( obj->mContents.mBmpDesc.mData ) )[y * obj->mContents.mBmpDesc.mWidth + x] );
829  val32 = ( ( val16 & 0x0F ) << ( 0 + 4 ) ) | ( ( ( val16 >> 4 ) & 0x0F ) << ( 8 + 4 ) ) | ( ( ( val16 >> 8 ) & 0x0F ) << ( 16 + 4 ) ) ;
830  return val32 | ( ( val16 & 0xF000 ) << 16 );
831 
832  case DMA2D_ARGB8888:
833  default:
834  val32 = ( ( ( u32* )( obj->mContents.mBmpDesc.mData ) )[y * obj->mContents.mBmpDesc.mWidth + x] );
835  return val32;
836  }
837  }
838  else
839  {
840  //read the (x,y) value in the RAM image.
841  return obj->mContents.mDynamicImage[y * obj->mWidthTotal + x];
842  }
843 
844  return 0;
845 }
846 /*******************************************************************************
847 *
848 * DMA2D_ObjectGetIntersection
849 *
850 *******************************************************************************/
864 /******************************************************************************/
865 NODEBUG u32 DMA2D_ObjectGetIntersection( unsigned int scrn, tDMA2D_pObject obj1, tDMA2D_pObject obj2 )
866 {
867  int i, j, val32 = 0;
868  //First, calculte the rectangle that contains the intersection
869  int x1 = obj1->mX[scrn];
870  int y1 = obj1->mY[scrn];
871  int width1 = obj1->mWidthTotal;
872  int height1 = obj1->mHeightTotal;
873  int x2 = obj2->mX[scrn];
874  int y2 = obj2->mY[scrn];
875  int width2 = obj2->mWidthTotal;
876  int height2 = obj2->mHeightTotal;
877 
878  int x, y, height, width; //for the intersection
879 
880  // Calculate the two rectangles wherein the objects are included
881  // if no intersection, we quit
882  if ( x1 <= x2 )
883  {
884  if ( ( x1 + width1 ) <= x2 )
885  return 0; //no intersection;
886  else
887  {
888  x = x2;
889  width = MIN( width2, ( x1 + width1 - x2 ) );
890  }
891  }
892  else //x1>x2
893  {
894  if ( ( x2 + width2 ) <= x1 )
895  return 0; //no intersection;
896  else
897  {
898  x = x1;
899  width = MIN( width1, ( x2 + width2 - x1 ) );
900  }
901  }
902  if ( y1 <= y2 )
903  {
904  if ( ( y1 + height1 ) <= y2 )
905  return 0; //no intersection;
906  else
907  {
908  y = y2;
909  height = MIN( height2, ( y1 + height1 - y2 ) );
910  }
911  }
912  else //x1>x2
913  {
914  if ( ( y2 + height2 ) <= y1 )
915  return 0; //no intersection;
916  else
917  {
918  y = y1;
919  height = MIN( height1, ( y2 + height2 - y1 ) );
920  }
921  }
922 
923 #ifdef TIMING_ANALYSIS // to debug with a scope
924  CX_Write( CX_GPIO_PIN9, Bit_RESET, 0 ); /* DMA2D intersection on CAN_RX */
925 #endif
926 
927  // Once we have the rectangle, we look at the pixels...
928  for ( i = 0; i < width ; i++ )
929  {
930  for ( j = 0; ( j < height ) && ( !val32 ) ; j++ )
931  {
932  u32 pixel1, pixel2;
933  u8 inter;
934  pixel1 = DMA2D_ObjectGetPixel( obj1, i + ( x - x1 ), j + ( y - y1 ) );
935  pixel2 = DMA2D_ObjectGetPixel( obj2, i + ( x - x2 ), j + ( y - y2 ) );
936  //we extract the alpha constant and keep the smallest one.
937  inter = MIN( ( pixel1 >> 24 ), ( pixel2 >> 24 ) );
938  val32 += inter;
939  }
940  }
941 
942 #ifdef TIMING_ANALYSIS // to debug with a scope
943  CX_Write( CX_GPIO_PIN9, Bit_SET, 0 ); /* DMA2D intersection on CAN_RX */
944 #endif
945 
946  return val32;
947 }
948 
949 /*******************************************************************************
950 *
951 * DMA2D_ScreenCopy
952 *
953 *******************************************************************************/
962 /******************************************************************************/
963 NODEBUG void DMA2D_ScreenCopy( unsigned int dest, unsigned int src )
964 {
965  int i;
966 
967  if ( ( dest >= MAX_DMA2D_SCREEN ) || ( dest >= MAX_DMA2D_SCREEN ) )
968  {
969  return; //inconsistent reference
970  }
971 
972  DMA2D_ScreenClear( dest, 0 );
973 
974  //Copy the objects from Source from destination
975  for ( i = 0; i < LCD_ScreenImage[src].mObjectCount ; i++ )
976  {
977  DMA2D_ObjectSetToScreen( LCD_ScreenImage[src].mObjectTable [i], dest );
978  //Assign same position of the object
979  LCD_ScreenImage[src].mObjectTable [i]->mX[dest] = LCD_ScreenImage[src].mObjectTable [i]->mX[src] ;
980  LCD_ScreenImage[src].mObjectTable [i]->mY[dest] = LCD_ScreenImage[src].mObjectTable [i]->mY[src] ;
981  }
983 
984  //Copy the current contents of the screen
985  memcpy( ( void* ) & ( LCD_ScreenImage[dest].mScreenImage ), ( void* ) & ( LCD_ScreenImage[src].mScreenImage ), sizeof( LCD_ScreenImage[src].mScreenImage ) );
986 
987  //and update the status
989  LCD_ScreenImage[dest].mStatus.mIsDirty = TRUE;
990 }
991 
992 /*******************************************************************************
993 *
994 * DMA2D_ObjectCreate
995 *
996 *******************************************************************************/
1010 /******************************************************************************/
1011 NODEBUG tDMA2D_pObject DMA2D_ObjectCreate( int max_width, int max_height, int rdonly )
1012 {
1013  unsigned size;
1014  tDMA2D_pObject pObj;
1015 
1016  if ( rdonly ) //The object does not feature any RAM storage (bmp in FLASH)
1017  {
1018  size = sizeof( tDMA2D_Object );
1019  }
1020  else //image is in SDRAM
1021  {
1022  size = ( max_width * max_height ) * 4 + sizeof( tDMA2D_Object );
1023  }
1024  if ( size > AvailableObjectMemory )
1025  {
1026  //At a very first step, we don't manage any garbage collector.
1027  return 0;
1028  }
1029  else
1030  {
1031  //take memory from the pool
1032  pObj = ( tDMA2D_pObject ) pFreeObjectMem;
1033  AvailableObjectMemory -= size;
1034  pFreeObjectMem += size;
1035 
1036  //initialize the object
1037  pObj->mStatus.mIsVisible = FALSE;
1038  pObj->mStatus.mIsRdonly = rdonly;
1039  pObj->mStatus.mIsPartial = FALSE;
1040  pObj->mStatus.mFormat = DMA2D_ARGB8888; //will be updated in case of BMP.
1041  pObj->mStatus.mAlpha = 0xff;
1042  pObj->mStatus.mScreenCnt = 0;
1043  pObj->mStatus.mIsDeleted = 0;
1044  pObj->mWidthTotal = pObj->mWidthUsed = max_width; //width of the bitmap
1045  pObj->mHeightTotal = pObj->mHeightUsed = max_height; //height of the bitmap
1046 
1047  pObj->mSizeGraph = max_width * max_height;
1048  pObj->mSize = size;
1049  pObj->mCurrentRect_transparency = 0xff;
1050 
1051  //Add at the object tail of the file.
1052  pObj->mNextObject = 0;
1053  TailObj->mNextObject = pObj;
1054  TailObj = pObj;
1055 
1056  //Initialise the image if in RAM (!rdonly)
1057  if ( !rdonly )
1058  {
1059  int i;
1060  color32_t* ptr;
1061 
1062  ptr = pObj->mData.mBitmap = ( color32_t* )( ( 3 + ( unsigned )( pObj->mContents.mDynamicImage ) )&~3 ); //need to be aligned!
1063  for ( i = 0 ; i < ( max_width * max_height ) ; i++ )
1064  ptr[i] = 0xff000000;
1065  }
1066  return pObj;
1067  }
1068 }
1069 
1070 /*******************************************************************************
1071 *
1072 * DMA2D_ObjectDelete
1073 *
1074 *******************************************************************************/
1083 /******************************************************************************/
1085 {
1086  obj->mStatus.mIsDeleted = 1; //No garbage collector for the moment.
1087 }
1088 
1089 /*******************************************************************************
1090 *
1091 * DMA2D_ObjectSetToScreen
1092 *
1093 *******************************************************************************/
1102 /******************************************************************************/
1103 NODEBUG int DMA2D_ObjectSetToScreen( tDMA2D_pObject obj, unsigned int screen )
1104 {
1105  if ( LCD_ScreenImage[screen].mObjectCount == ( MAX_DMA2D_OBJECT - 1 ) )
1106  return -1;
1107 
1108  LCD_ScreenImage[screen].mObjectTable [LCD_ScreenImage[screen].mObjectCount++] = obj;
1109 
1110  obj->mZOrder[screen] = LCD_ScreenImage[screen].mObjectCount;
1111  obj->mStatus.mScreenCnt++; //increment the counter for the number of instances.
1112  obj->mX[screen] = 0;
1113  obj->mY[screen] = 0;
1114  obj->mStatus.mIsDirty = 1;
1115 
1116  if ( obj->mStatus.mIsVisible )
1117  DMA2D_ScreenSetDirty( screen );
1118 
1119  return 0;
1120 }
1121 
1122 /*******************************************************************************
1123 *
1124 * DMA2D_ObjectAssignBitmap
1125 *
1126 *******************************************************************************/
1136 /******************************************************************************/
1137 NODEBUG int DMA2D_ObjectAssignBitmap( tDMA2D_pObject obj, void* pbitmap, int fbitmap0constant1 )
1138 {
1139  u16* iptr = pbitmap;
1140 
1141  if ( fbitmap0constant1 == 1 ) //Fixed color (filled rectangle)
1142  {
1143  obj->mData.mARGB_Cst = *( u32* )pbitmap;
1144  obj->mStatus.mFormat = 0;
1145  obj->mStatus.mIsCst = 1;
1146  return 0;
1147  }
1148  obj->mData.mBitmap = pbitmap;
1149  obj->mStatus.mFormat = 0;
1150  obj->mStatus.mIsDirty = TRUE;
1151 
1152  if ( *iptr == 0xffff )
1153  iptr++;
1154 
1155  // BMP header test
1156  if ( ( iptr [0] != 0x4D42 ) || ( iptr[3] != 0 ) )
1157  {
1158  //Illegal BMP format!
1159  return -1;
1160  }
1161  //else we suppose we have a regular BMP file.
1162  //The description of the BMP files is available at:
1163  // http://en.wikipedia.org/wiki/BMP_file_format
1164  obj->mData.mBitmap = ( color32_t* )iptr ;
1165  obj->mContents.mBmpDesc.mData = ( u8* )iptr + iptr[0xA / 2];
1166  obj->mWidthUsed = obj->mWidthTotal = obj->mContents.mBmpDesc.mWidth = iptr[0x12 / 2];
1167  obj->mHeightUsed = obj->mHeightTotal = obj->mContents.mBmpDesc.mHeight = iptr[0x16 / 2];
1168  obj->mContents.mBmpDesc.mBitPerPixel = iptr[0x1C / 2];
1169  obj->mContents.mBmpDesc.mCompressionMethod = iptr[0x1E / 2];
1170  obj->mContents.mBmpDesc.mNumberOfColorInPalette = iptr[0x2E / 2];
1171  obj->mContents.mBmpDesc.mColorTable = ( u8* )iptr + 0x36;
1172 
1173  obj->mStatus.mFormat = -1; //not supported format.
1174 
1175  switch ( obj->mContents.mBmpDesc.mBitPerPixel )
1176  {
1177  case 4:
1178  if ( ( obj->mContents.mBmpDesc.mCompressionMethod == 0 )/*BI_RGB*/ &&
1179  ( obj->mContents.mBmpDesc.mNumberOfColorInPalette == 16 ) )
1180  obj->mStatus.mFormat = ( int )CM_L4;
1181  break;
1182 
1183  case 8:
1184  if ( ( obj->mContents.mBmpDesc.mCompressionMethod == 0 )/*BI_RGB*/ &&
1185  ( obj->mContents.mBmpDesc.mNumberOfColorInPalette == 256 ) )
1186  obj->mStatus.mFormat = ( int )CM_L8;
1187  else obj->mStatus.mFormat = ( int )CM_A8;
1188  break;
1189 
1190  case 16:
1191  if ( ( obj->mContents.mBmpDesc.mCompressionMethod == 0 /*BI_RGB*/ )
1192  || ( obj->mContents.mBmpDesc.mCompressionMethod == 3 /*BI_BITFIELDS*/ ) )
1193  {
1194  obj->mStatus.mFormat = DMA2D_RGB565;
1195  break;
1196  }
1197  break;
1198 
1199  case 24:
1200  return -1;
1201  break; //Ignore this object
1202 
1203  case 32:
1204  if ( ( obj->mContents.mBmpDesc.mCompressionMethod == 0 /*BI_RGB*/ )
1205  || ( obj->mContents.mBmpDesc.mCompressionMethod == 3 /*BI_BITFIELDS*/ ) )
1206  {
1207  obj->mStatus.mFormat = DMA2D_ARGB8888;
1208  break;
1209  }
1210  break;
1211 
1212  default:
1213  return -1;
1214  break; //Ignore this object
1215  }
1216 
1217  return 0;
1218 }
1219 
1220 /*******************************************************************************
1221 *
1222 * DMA2D_ObjectSetPartial
1223 *
1224 *******************************************************************************/
1235 /******************************************************************************/
1236 NODEBUG int DMA2D_ObjectSetPartial( tDMA2D_pObject obj, int width, int height )
1237 {
1238  if ( width > obj->mWidthTotal )
1239  return -1;
1240 
1241  if ( height > obj->mHeightTotal )
1242  return -1;
1243 
1244  obj->mHeightUsed = height;
1245  obj->mWidthUsed = width;
1246 
1247  if ( ( obj->mOffsX + obj->mWidthUsed ) > obj->mWidthTotal )
1248  obj->mOffsX = obj->mWidthTotal - obj->mWidthUsed;
1249 
1250  if ( ( obj->mOffsY + obj->mHeightUsed ) > obj->mHeightTotal )
1251  obj->mOffsY = obj->mHeightTotal - obj->mHeightUsed;
1252 
1253  obj->mStatus.mIsPartial = ( width != obj->mWidthTotal ) || ( height != obj->mHeightTotal );
1254 
1255  return 0;
1256 }
1257 
1258 /*******************************************************************************
1259 *
1260 * DMA2D_ObjectSetOffset
1261 *
1262 *******************************************************************************/
1274 /******************************************************************************/
1275 NODEBUG int DMA2D_ObjectSetOffset( tDMA2D_pObject obj, int offsX, int offsY )
1276 {
1277  if ( offsX > obj->mWidthTotal )
1278  return -1;
1279 
1280  if ( offsY > obj->mHeightTotal )
1281  return -1;
1282 
1283  obj->mOffsX = offsX;
1284  obj->mOffsY = offsY;
1285 
1286  if ( ( obj->mOffsX + obj->mWidthUsed ) > obj->mWidthTotal )
1287  obj->mWidthUsed = obj->mWidthTotal - obj->mOffsX ;
1288 
1289  if ( ( obj->mOffsY + obj->mHeightUsed ) > obj->mHeightTotal )
1290  obj->mHeightUsed = obj->mHeightTotal - obj->mOffsY ;
1291 
1292  obj->mStatus.mIsPartial = ( obj->mWidthUsed != obj->mWidthTotal )
1293  || ( obj->mHeightUsed != obj->mHeightTotal ) ;
1294 
1295  return 0;
1296 }
1297 
1298 /*******************************************************************************
1299 *
1300 * DMA2D_ObjectMove
1301 *
1302 *******************************************************************************/
1312 /******************************************************************************/
1313 NODEBUG int DMA2D_ObjectMove( tDMA2D_pObject obj, int x, int y )
1314 {
1315  obj->mX[AddressedScreen] = x;
1316  obj->mY[AddressedScreen] = y;
1317  obj->mStatus.mIsDirty = 1;
1318 
1319  if ( obj->mStatus.mIsVisible )
1321 
1322  return 0;
1323 }
1324 
1325 /*******************************************************************************
1326 *
1327 * DMA2D_ObjectSetVisible
1328 *
1329 *******************************************************************************/
1338 /******************************************************************************/
1339 NODEBUG void DMA2D_ObjectSetVisible( tDMA2D_pObject obj, int mode )
1340 {
1341  obj->mStatus.mIsVisible = mode;
1342 }
1343 
1344 
1345 /*******************************************************************************
1346 *
1347 * DMA2D_ObjectSelect
1348 *
1349 *******************************************************************************/
1359 /******************************************************************************/
1361 {
1362  if ( obj && obj->mStatus.mIsRdonly )
1363  return -1;
1364 
1365  SelectedObject = obj;
1366 
1367  return 0;
1368 }
1369 
1370 
1371 /*******************************************************************************
1372 *
1373 * DMA2D_ObjectSetTransparency
1374 *
1375 *******************************************************************************/
1386 /******************************************************************************/
1387 NODEBUG void DMA2D_ObjectSetTransparency( tDMA2D_pObject obj, int transparency )
1388 {
1389  if ( obj )
1390  {
1391  //To be distinguished ??
1392  obj->mCurrentRect_transparency = transparency & 255;
1393  obj->mStatus.mAlpha = transparency & 255;
1394  }
1395 }
1396 
1397 /*******************************************************************************
1398 *
1399 * DMA2D_ObjectFind
1400 *
1401 *******************************************************************************/
1411 /******************************************************************************/
1412 NODEBUG tDMA2D_pObject DMA2D_ObjectFind( unsigned int screen, int x, int y )
1413 {
1414  int count = LCD_ScreenImage[screen].mObjectCount;
1415  int objx, objy, width, height;
1416  int i;
1417 
1418  for ( i = 0 ; i < count ; i++ )
1419  {
1420  tDMA2D_pObject obj = LCD_ScreenImage[screen].mObjectTable[count - 1 - i];
1421 
1422  if ( !obj || !obj->mStatus.mIsVisible )
1423  continue;
1424 
1425  objx = obj->mX[screen];
1426  objy = obj->mY[screen];
1427  width = obj->mWidthTotal;
1428  height = obj->mHeightTotal;
1429 
1430  if ( DMA2D_ObjectGetPixel( obj, x - objx, y - objy ) & 0xff000000 )
1431  return obj;
1432  }
1433  return 0;
1434 }
1435 
1436 /*******************************************************************************
1437 *
1438 * DMA2D_ObjectGetImage
1439 *
1440 *******************************************************************************/
1447 /******************************************************************************/
1449 {
1450  if ( !obj->mStatus.mIsRdonly )
1451  {
1452  return ( u32 ) & ( obj->mContents.mDynamicImage );
1453  }
1454  else
1455  {
1456  return ( u32 ) obj->mContents.mBmpDesc.mData ;
1457  }
1458 }
1459 
1460 /*******************************************************************************
1461 *
1462 * DMA2D_ObjectGetPos
1463 *
1464 *******************************************************************************/
1474 /******************************************************************************/
1475 NODEBUG int DMA2D_ObjectGetPos( tDMA2D_pObject obj, unsigned int screen )
1476 {
1477  return ( obj->mY[screen] << 16 ) | ( unsigned short ) obj->mX[screen];
1478 }
1479 
1480 /*******************************************************************************
1481 *
1482 * DMA2D_ObjectGetSize
1483 *
1484 *******************************************************************************/
1493 /******************************************************************************/
1495 {
1496  return ( obj->mHeightTotal << 16 ) | ( unsigned short ) obj->mWidthTotal;
1497 }
1498 
1499 
1500 /*******************************************************************************
1501 *
1502 * DMA2D_ObjectPopZ
1503 *
1504 *******************************************************************************/
1513 /******************************************************************************/
1514 NODEBUG int DMA2D_ObjectPopZ( tDMA2D_pObject obj, unsigned int scr )
1515 {
1516  int i;
1517  int N = LCD_ScreenImage [scr].mObjectCount;
1518 
1519  for ( i = 0 ; i < N; i++ )
1520  {
1521  if ( LCD_ScreenImage [scr].mObjectTable[i] == obj )
1522  {
1523  if ( i != ( N - 1 ) )
1524  {
1525  LCD_ScreenImage [scr].mObjectTable[i] = LCD_ScreenImage [scr].mObjectTable[i + 1];
1526  LCD_ScreenImage [scr].mObjectTable[i]->mZOrder[scr] = i;
1527  LCD_ScreenImage [scr].mObjectTable[i + 1] = obj;
1528  obj->mZOrder[scr] = i + 1;
1529  return ( i + 1 );
1530  }
1531  else
1532  return N - 1;
1533  }
1534  }
1535  return -1; //the object is not assigned to the screen.
1536 }
1537 
1538 /*******************************************************************************
1539 *
1540 * DMA2D_ObjectPushZ
1541 *
1542 *******************************************************************************/
1551 /******************************************************************************/
1552 NODEBUG int DMA2D_ObjectPushZ( tDMA2D_pObject obj, unsigned int scr )
1553 {
1554  int i;
1555  int N = LCD_ScreenImage [scr].mObjectCount;
1556 
1557  for ( i = 0 ; i < N; i++ )
1558  {
1559  if ( LCD_ScreenImage [scr].mObjectTable[i] == obj )
1560  {
1561  if ( i )
1562  {
1563  LCD_ScreenImage [scr].mObjectTable[i] = LCD_ScreenImage [scr].mObjectTable[i - 1];
1564  LCD_ScreenImage [scr].mObjectTable[i]->mZOrder[scr] = i;
1565  LCD_ScreenImage [scr].mObjectTable[i - 1] = obj;
1566  obj->mZOrder[scr] = i - 1;
1567  return ( i - 1 );
1568  }
1569  else
1570  return 0;
1571  }
1572  }
1573  return -1; //the object is not assigned to the screen.
1574 }
1575 
1576 /*******************************************************************************
1577 *
1578 * DMA2D_ObjectSetForeground
1579 *
1580 *******************************************************************************/
1589 /******************************************************************************/
1590 NODEBUG int DMA2D_ObjectSetForeground( tDMA2D_pObject obj, unsigned int scr )
1591 {
1592  int i;
1593  int N = LCD_ScreenImage [scr].mObjectCount;
1594 
1595  for ( i = 0 ; i < N; i++ )
1596  {
1597  if ( LCD_ScreenImage [scr].mObjectTable[i] == obj )
1598  {
1599  for ( ; i < ( N - 1 ) ; i++ )
1600  {
1601  LCD_ScreenImage [scr].mObjectTable[i] = LCD_ScreenImage [scr].mObjectTable[i + 1];
1602  LCD_ScreenImage [scr].mObjectTable[i]->mZOrder[scr] = i;
1603  }
1604  LCD_ScreenImage [scr].mObjectTable[N - 1] = obj;
1605  obj->mZOrder[scr] = N - 1;
1606  return ( N - 1 );
1607  }
1608  }
1609  return -1; // the object is not assigned to the screen.
1610 }
1611 
1612 /*******************************************************************************
1613 *
1614 * DMA2D_ObjectSetBackground
1615 *
1616 *******************************************************************************/
1625 /******************************************************************************/
1626 NODEBUG int DMA2D_ObjectSetBackground( tDMA2D_pObject obj, unsigned int scr )
1627 {
1628  int i;
1629  int N = LCD_ScreenImage [scr].mObjectCount;
1630 
1631  for ( i = 0 ; i < N; i++ )
1632  {
1633  if ( LCD_ScreenImage [scr].mObjectTable[N - i - 1] == obj )
1634  {
1635  for ( ; i < ( N - 1 ) ; i++ )
1636  {
1637  LCD_ScreenImage [scr].mObjectTable[N - i - 1] = LCD_ScreenImage [scr].mObjectTable[N - i - 2]; //FL131219
1638  LCD_ScreenImage [scr].mObjectTable[N - i - 1]->mZOrder[scr] = N - i - 1;
1639  }
1640  LCD_ScreenImage [scr].mObjectTable[0] = obj;
1641  obj->mZOrder[scr] = 0;
1642  return 0;
1643  }
1644  }
1645  return -1;
1646 }
1647 
1648 
1649 /*******************************************************************************
1650 *
1651 * DMA2D_ScreenRotate
1652 *
1653 *******************************************************************************/
1662 /******************************************************************************/
1663 NODEBUG void DMA2D_ScreenRotate( Rotate_H12_V_Match_TypeDef old_orientation, Rotate_H12_V_Match_TypeDef new_orientation )
1664 {
1665  int i, j, k;
1666 
1667  if ( ( old_orientation & 3 ) != ( new_orientation & 3 ) )
1668  {
1669  memset( FlagRead, 0, sizeof( FlagRead ) );
1670  for ( i = 0 ; i < PHYS_SCREEN_HEIGHT * PHYS_SCREEN_WIDTH ; i++ )
1671  {
1672  tpixel24 tmp1, tmp2 ;
1673 
1674  if ( IS_FLAGREAD( i ) ) //already relocated (read)
1675  continue;
1676 
1677  //try to relocate the i th pixel in the memory.
1678  memcpy( tmp1, LCD_ScreenImage[DisplayedScreen].mScreenImage.mArray[i], 3 );
1679  SET_FLAGREAD( i ); //we don't have to read it anymore for relocation!
1680 
1681  k = i; //current pixel to be relocated
1682  while ( 1 ) //loop while we have a pixel tmp1 to relocate...
1683  {
1684  j = RotateIndex( old_orientation, new_orientation, k ); //destination of the current pixel
1685 
1686  if ( IS_FLAGREAD( j ) ) //dest pixel already read: we can overwrite its contents
1687  {
1688  memcpy( LCD_ScreenImage[DisplayedScreen].mScreenImage.mArray[j], tmp1, 3 );
1689  break;
1690  }
1691  else //we need to save the contents
1692  {
1693  memcpy( tmp2, LCD_ScreenImage[DisplayedScreen].mScreenImage.mArray[j], 3 ); //read j, to be relocated!
1694  SET_FLAGREAD( j ); //Set the flag to avoid any future reactivation...
1695  memcpy( LCD_ScreenImage[DisplayedScreen].mScreenImage.mArray[j], tmp1, 3 ); //save "k" image (could be i)
1696  //but we have now to relocate the contents of [i] not to loose it...
1697  memcpy( tmp1, tmp2, 3 );
1698  k = j; //need to relocate the j before going further
1699  continue;
1700  }
1701  }
1702  }
1703  }
1704 }
1705 
1706 /*******************************************************************************
1707 *
1708 * DMA2D_ObjectTransform
1709 *
1710 *******************************************************************************/
1724 /******************************************************************************/
1725 NODEBUG u32 DMA2D_ObjectTransform( tDMA2D_pObject obj_dest, tDMA2D_pObject obj_src, tTrans* trsf )
1726 {
1727  int sx, sy; // Source position
1728  int sx_0, sy_0; // Source position
1729  int dx, dy; // Destination position
1730  int pos_s, pos_d, pos_0;
1731  int ibak;
1732 
1733  if ( obj_dest->mStatus.mIsRdonly )
1734  {
1735  return 1; // error: cannot modify destination
1736  }
1737 
1738  memset( FlagRead, 0, sizeof( FlagRead ) );
1739  memset( FlagWritten, 0, sizeof( FlagWritten ) );
1740 
1741  //First, we erase the destination when it is not the source!
1742  if ( obj_src != obj_dest )
1743  {
1744  for ( dy = 0; dy < obj_dest->mHeightUsed; dy++ )
1745  {
1746  for ( dx = 0; dx < obj_dest->mWidthUsed ; dx++ )
1747  {
1748  pos_d = ( dy + obj_dest->mOffsY ) * obj_dest->mWidthTotal + ( dx + obj_dest->mOffsX );
1749  obj_dest->mContents.mDynamicImage[pos_d] = trsf->mDefaultColor;
1750  }
1751  }
1752  }
1753 
1754  //We apply the transformation
1755  for ( sy = 0; sy < obj_src->mHeightUsed; sy++ )
1756  {
1757  for ( sx = 0; sx < obj_src->mWidthUsed ; sx++ )
1758  {
1759  color32_t tmp1, tmp2 ;
1760  pos_s = ( sy + obj_src->mOffsY ) * obj_src->mWidthTotal + ( sx + obj_src->mOffsX );
1761 
1762  if ( IS_FLAGREAD( pos_s ) ) //already relocated (read)
1763  {
1764  if ( obj_src == obj_dest ) //cannot loose pixel when transforming!
1765  {
1766  continue;
1767  }
1768  }
1769 
1770  //Try to relocate the pos_s-th pixel in the memory.
1771  ibak = obj_src->mStatus.mIsVisible;
1772  obj_src->mStatus.mIsVisible = 1; //need to force visibility to make the copy
1773  tmp1 = DMA2D_ObjectGetPixel( obj_src, sx + obj_src->mOffsX, sy + obj_src->mOffsY );
1774  obj_src->mStatus.mIsVisible = ibak;
1775  SET_FLAGREAD( pos_s ); //we don't have to read it anymore for relocation!
1776 
1777  pos_0 = pos_s; //current pixel to be relocated
1778  sx_0 = sx;
1779  sy_0 = sy;
1780 
1781  // Loop while we have a pixel tmp1 to relocate...
1782  while ( 1 )
1783  {
1784  dx = trsf->mFctX( sx_0, sy_0 ); //x destination of the current pixel
1785  dy = trsf->mFctY( sx_0, sy_0 ); //y destination of the current pixel
1786  pos_d = ( dy + obj_dest->mOffsY ) * obj_dest->mWidthTotal + ( dx + obj_dest->mOffsX );
1787 
1788  //Check that the destination is inside the specified window
1789  if ( ( dx < 0 ) || ( dy < 0 ) )
1790  break;
1791  if ( ( dx >= obj_dest->mWidthUsed ) || ( dy >= obj_dest->mHeightUsed ) )
1792  break;
1793 
1794  if ( obj_src == obj_dest ) //Cannot loose pixel when transforming!
1795  {
1796  if ( IS_FLAGREAD( pos_d ) ) //Dest pixel already read: we can overwrite its contents
1797  {
1798  //Write destination pixel
1799  obj_dest->mContents.mDynamicImage[pos_d] = tmp1;
1800  SET_FLAGWRITTEN( pos_d ); //we mark it as destination
1801  break;
1802  }
1803  else //We need to save the contents
1804  {
1805  tmp2 = obj_dest->mContents.mDynamicImage[pos_d]; //Read posd, to be relocated!
1806  SET_FLAGREAD( pos_d ); //Set the flag to avoid any future reactivation...
1807  obj_dest->mContents.mDynamicImage[pos_d] = tmp1; //Save "k" image (could be i)
1808  SET_FLAGWRITTEN( pos_d ); //We mark it as destination
1809  //but we have now to relocate the contents of [pos] not to loose it...
1810  tmp1 = tmp2;
1811  pos_0 = pos_d; //Need to relocate the posd before going further
1812  sx_0 = dx;
1813  sy_0 = dy;
1814  continue;
1815  }
1816  }
1817  else //Dest is not the source, thus we just copy the value!
1818  {
1819  obj_dest->mContents.mDynamicImage[pos_d] = tmp1;
1820  SET_FLAGWRITTEN( pos_d ); //We mark the destination
1821  break;
1822  }
1823  }
1824  }
1825  }
1826 
1827  //When the destination is the source, we clean the pixels from the source that are not overwritten
1828  if ( obj_dest == obj_src )
1829  {
1830  //Clean unwritten pixels
1831  for ( dy = 0; dy < obj_dest->mHeightUsed; dy++ )
1832  {
1833  for ( dx = 0; dx < obj_dest->mWidthUsed ; dx++ )
1834  {
1835  pos_d = ( dy + obj_dest->mOffsY ) * obj_dest->mWidthTotal + dx;
1836  if ( !IS_FLAGWRITTEN( pos_d ) ) //Dest has not been written,
1837  {
1838  ( ( ( u32* )( obj_dest->mContents.mDynamicImage ) )[pos_d] ) = 0;//0xffff0000;
1839  }
1840  }
1841  }
1842  }
1843 
1844  return 0;
1845 }
1846 
1847 /*******************************************************************************
1848 *
1849 * DMA2D_SetTransform
1850 *
1851 *******************************************************************************/
1860 /******************************************************************************/
1861 NODEBUG void DMA2D_SetTransform( tFctXY fct_X, tFctXY fct_Y )
1862 {
1863  CurrentTransformation.mFctX = fct_X;
1864  CurrentTransformation.mFctY = fct_Y;
1865 }
1866 
1867 /*******************************************************************************
1868 *
1869 * DMA2D_ObjectTransformReverse
1870 *
1871 *******************************************************************************/
1884 /******************************************************************************/
1886 {
1887  int dx, dy; // Destination position
1888  int pos_d;
1889 
1890  if ( obj_dest->mStatus.mIsRdonly || !fct )
1891  {
1892  return 1; // error: cannot modify destination
1893  }
1894 
1895  //For each pixel, we evaluate the new contents by calling fct.
1896  for ( dy = 0; dy < obj_dest->mHeightUsed; dy++ )
1897  {
1898  for ( dx = 0; dx < obj_dest->mWidthUsed ; dx++ )
1899  {
1900  pos_d = ( dy + obj_dest->mOffsY ) * obj_dest->mWidthTotal + ( dx + obj_dest->mOffsX );
1901  obj_dest->mContents.mDynamicImage[pos_d] = fct( obj_src, dx, dy );
1902  }
1903  }
1904  return 0;
1905 }
1906