2019-08-19 16:03:27 +08:00
# ifndef GUILITE_CORE_INCLUDE_DISPLAY_H
# define GUILITE_CORE_INCLUDE_DISPLAY_H
2017-12-06 21:43:47 +08:00
2020-01-22 11:03:29 +08:00
# include "../core_include/api.h"
# include "../core_include/rect.h"
# include "../core_include/cmd_target.h"
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
2017-12-06 21:43:47 +08:00
# define SURFACE_CNT_MAX 6 //root + pages
2020-01-22 11:03:29 +08:00
typedef enum
{
Z_ORDER_LEVEL_0 , //view/wave/page
Z_ORDER_LEVEL_1 , //dialog
Z_ORDER_LEVEL_2 , //editbox/spinbox/listbox/keyboard
Z_ORDER_LEVEL_MAX
} Z_ORDER_LEVEL ;
struct EXTERNAL_GFX_OP
{
void ( * draw_pixel ) ( int x , int y , unsigned int rgb ) ;
void ( * fill_rect ) ( int x0 , int y0 , int x1 , int y1 , unsigned int rgb ) ;
} ;
2017-12-06 21:43:47 +08:00
2020-01-22 11:03:29 +08:00
class c_surface ;
2017-12-06 21:43:47 +08:00
class c_display {
2018-12-17 15:51:00 +08:00
friend class c_surface ;
2017-12-06 21:43:47 +08:00
public :
2020-03-14 10:58:01 +08:00
inline c_display ( void * phy_fb , int display_width , int display_height , int surface_width , int surface_height , unsigned int color_bytes , int surface_cnt , EXTERNAL_GFX_OP * gfx_op = 0 ) ; //multiple surface or surface_no_fb
inline c_display ( void * phy_fb , int display_width , int display_height , c_surface * surface ) ; //single custom surface
inline c_surface * alloc_surface ( Z_ORDER_LEVEL max_zorder ) ; //for multiple surfaces
2020-01-22 11:03:29 +08:00
inline int swipe_surface ( c_surface * s0 , c_surface * s1 , int x0 , int x1 , int y0 , int y1 , int offset ) ;
2019-12-17 10:45:15 +08:00
int get_width ( ) { return m_width ; }
int get_height ( ) { return m_height ; }
2017-12-06 21:43:47 +08:00
2020-01-22 11:03:29 +08:00
void * get_updated_fb ( int * width , int * height , bool force_update = false )
{
if ( width & & height )
{
* width = get_width ( ) ;
* height = get_height ( ) ;
}
if ( force_update )
{
return m_phy_fb ;
}
if ( m_phy_read_index = = m_phy_write_index )
{ //No update
return 0 ;
}
m_phy_read_index = m_phy_write_index ;
return m_phy_fb ;
}
int snap_shot ( const char * file_name )
{
if ( ! m_phy_fb )
{
return - 1 ;
}
int width = get_width ( ) ;
int height = get_height ( ) ;
//16 bits framebuffer
if ( m_color_bytes = = 2 )
{
return build_bmp ( file_name , width , height , ( unsigned char * ) m_phy_fb ) ;
}
//32 bits framebuffer
unsigned short * p_bmp565_data = new unsigned short [ width * height ] ;
unsigned int * p_raw_data = ( unsigned int * ) m_phy_fb ;
for ( int i = 0 ; i < width * height ; i + + )
{
unsigned int rgb = * p_raw_data + + ;
p_bmp565_data [ i ] = GL_RGB_32_to_16 ( rgb ) ;
}
int ret = build_bmp ( file_name , width , height , ( unsigned char * ) p_bmp565_data ) ;
delete [ ] p_bmp565_data ;
return ret ;
}
2017-12-06 21:43:47 +08:00
private :
2019-12-17 10:45:15 +08:00
int m_width ; //in pixels
int m_height ; //in pixels
int m_color_bytes ; //16 bits, 32 bits only
2020-03-14 10:58:01 +08:00
void * m_phy_fb ;
2018-12-17 15:51:00 +08:00
int m_phy_read_index ;
int m_phy_write_index ;
2020-03-14 10:58:01 +08:00
c_surface * m_surface_group [ SURFACE_CNT_MAX ] ;
2019-12-17 10:45:15 +08:00
int m_surface_cnt ;
int m_surface_index ;
2017-12-06 21:43:47 +08:00
} ;
2020-01-22 11:03:29 +08:00
class c_frame_layer
{
public :
c_frame_layer ( ) { fb = 0 ; }
2020-03-17 13:16:47 +08:00
void * fb ;
2020-01-22 11:03:29 +08:00
c_rect visible_rect ;
} ;
class c_surface {
friend class c_display ; friend class c_bitmap ;
public :
2020-03-14 10:58:01 +08:00
c_surface ( unsigned int width , unsigned int height , unsigned int color_bytes , Z_ORDER_LEVEL max_zorder = Z_ORDER_LEVEL_0 ) : m_width ( width ) , m_height ( height ) , m_color_bytes ( color_bytes ) , m_fb ( 0 ) , m_is_active ( false ) , m_top_zorder ( Z_ORDER_LEVEL_0 ) , m_phy_fb ( 0 ) , m_phy_write_index ( 0 ) , m_display ( 0 )
2020-02-13 20:16:32 +08:00
{
2020-03-15 17:38:36 +08:00
memset ( m_frame_layers , 0 , sizeof ( m_frame_layers ) ) ;
2020-02-13 20:16:32 +08:00
m_frame_layers [ Z_ORDER_LEVEL_0 ] . visible_rect = c_rect ( 0 , 0 , m_width , m_height ) ;
2020-03-15 17:38:36 +08:00
set_surface ( max_zorder ) ;
2020-02-13 20:16:32 +08:00
}
2020-01-22 11:03:29 +08:00
int get_width ( ) { return m_width ; }
int get_height ( ) { return m_height ; }
2020-02-13 20:16:32 +08:00
2020-01-22 11:03:29 +08:00
unsigned int get_pixel ( int x , int y , unsigned int z_order )
{
2020-03-17 13:16:47 +08:00
if ( x > = m_width | | y > = m_height | | x < 0 | | y < 0 | | z_order > = Z_ORDER_LEVEL_MAX )
2020-01-22 11:03:29 +08:00
{
ASSERT ( false ) ;
return 0 ;
}
2020-03-17 13:16:47 +08:00
if ( m_frame_layers [ z_order ] . fb )
2020-01-22 11:03:29 +08:00
{
2020-03-17 13:16:47 +08:00
return ( m_color_bytes = = 4 ) ? ( ( unsigned int * ) ( m_frame_layers [ z_order ] . fb ) ) [ y * m_width + x ] : GL_RGB_16_to_32 ( ( ( unsigned short * ) ( m_frame_layers [ z_order ] . fb ) ) [ y * m_width + x ] ) ;
2020-01-22 11:03:29 +08:00
}
2020-03-17 13:16:47 +08:00
else if ( m_fb )
{
return ( m_color_bytes = = 4 ) ? ( ( unsigned int * ) m_fb ) [ y * m_width + x ] : GL_RGB_16_to_32 ( ( ( unsigned short * ) m_fb ) [ y * m_width + x ] ) ;
}
else if ( m_phy_fb )
{
return ( m_color_bytes = = 4 ) ? ( ( unsigned int * ) m_phy_fb ) [ y * m_width + x ] : GL_RGB_16_to_32 ( ( ( unsigned short * ) m_phy_fb ) [ y * m_width + x ] ) ;
}
return 0 ;
2020-01-22 11:03:29 +08:00
}
2020-02-13 20:16:32 +08:00
virtual void draw_pixel ( int x , int y , unsigned int rgb , unsigned int z_order )
2020-01-22 11:03:29 +08:00
{
if ( x > = m_width | | y > = m_height | | x < 0 | | y < 0 )
{
return ;
}
if ( z_order > ( unsigned int ) m_max_zorder )
{
ASSERT ( false ) ;
return ;
}
2020-03-17 13:16:47 +08:00
if ( 0 = = m_frame_layers [ z_order ] . visible_rect . PtInRect ( x , y ) )
{
ASSERT ( false ) ;
return ;
}
2020-01-22 11:03:29 +08:00
if ( z_order = = m_max_zorder )
{
return draw_pixel_on_fb ( x , y , rgb ) ;
}
2020-03-17 13:16:47 +08:00
2020-01-22 11:03:29 +08:00
if ( z_order > ( unsigned int ) m_top_zorder )
{
m_top_zorder = ( Z_ORDER_LEVEL ) z_order ;
}
2020-03-17 13:16:47 +08:00
if ( m_color_bytes = = 4 )
2020-01-22 11:03:29 +08:00
{
2020-03-17 13:16:47 +08:00
( ( unsigned int * ) ( m_frame_layers [ z_order ] . fb ) ) [ x + y * m_width ] = rgb ;
}
else
{
( ( unsigned short * ) ( m_frame_layers [ z_order ] . fb ) ) [ x + y * m_width ] = GL_RGB_32_to_16 ( rgb ) ;
2020-01-22 11:03:29 +08:00
}
if ( z_order = = m_top_zorder )
{
return draw_pixel_on_fb ( x , y , rgb ) ;
}
bool is_covered = false ;
for ( unsigned int tmp_z_order = Z_ORDER_LEVEL_MAX - 1 ; tmp_z_order > z_order ; tmp_z_order - - )
{
if ( true = = m_frame_layers [ tmp_z_order ] . visible_rect . PtInRect ( x , y ) )
{
is_covered = true ;
break ;
}
}
if ( ! is_covered )
{
draw_pixel_on_fb ( x , y , rgb ) ;
}
}
2020-02-13 20:16:32 +08:00
virtual void fill_rect ( int x0 , int y0 , int x1 , int y1 , unsigned int rgb , unsigned int z_order )
2020-01-22 11:03:29 +08:00
{
x0 = ( x0 < 0 ) ? 0 : x0 ;
y0 = ( y0 < 0 ) ? 0 : y0 ;
x1 = ( x1 > ( m_width - 1 ) ) ? ( m_width - 1 ) : x1 ;
y1 = ( y1 > ( m_height - 1 ) ) ? ( m_height - 1 ) : y1 ;
if ( z_order = = m_max_zorder )
{
return fill_rect_on_fb ( x0 , y0 , x1 , y1 , rgb ) ;
}
if ( z_order = = m_top_zorder )
{
int x , y ;
2020-03-17 13:16:47 +08:00
unsigned short * mem_fb_16 = 0 ;
unsigned int * mem_fb_32 = 0 ;
2020-01-22 11:03:29 +08:00
unsigned int rgb_16 = GL_RGB_32_to_16 ( rgb ) ;
for ( y = y0 ; y < = y1 ; y + + )
{
x = x0 ;
2020-03-17 13:16:47 +08:00
if ( m_color_bytes = = 4 )
{
mem_fb_32 = & ( ( unsigned int * ) m_frame_layers [ z_order ] . fb ) [ y * m_width + x ] ;
}
else
{
mem_fb_16 = & ( ( unsigned short * ) m_frame_layers [ z_order ] . fb ) [ y * m_width + x ] ;
}
2020-01-22 11:03:29 +08:00
for ( ; x < = x1 ; x + + )
{
2020-03-17 13:16:47 +08:00
if ( m_color_bytes = = 4 )
{
* mem_fb_32 + + = rgb ;
}
else
{
* mem_fb_16 + + = rgb_16 ;
}
2020-01-22 11:03:29 +08:00
}
}
return fill_rect_on_fb ( x0 , y0 , x1 , y1 , rgb ) ;
}
for ( ; y0 < = y1 ; y0 + + )
{
draw_hline ( x0 , x1 , y0 , rgb , z_order ) ;
}
}
void draw_hline ( int x0 , int x1 , int y , unsigned int rgb , unsigned int z_order )
{
for ( ; x0 < = x1 ; x0 + + )
{
draw_pixel ( x0 , y , rgb , z_order ) ;
}
}
void draw_vline ( int x , int y0 , int y1 , unsigned int rgb , unsigned int z_order )
{
for ( ; y0 < = y1 ; y0 + + )
{
draw_pixel ( x , y0 , rgb , z_order ) ;
}
}
void draw_line ( int x1 , int y1 , int x2 , int y2 , unsigned int rgb , unsigned int z_order )
{
int dx , dy , e ;
dx = x2 - x1 ;
dy = y2 - y1 ;
if ( ( dx > = 0 ) & & ( dy > = 0 ) )
{
if ( dx > = dy )
{
e = dy - dx / 2 ;
for ( ; x1 < = x2 ; x1 + + , e + = dy )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { y1 + + ; e - = dx ; }
}
}
else
{
e = dx - dy / 2 ;
for ( ; y1 < = y2 ; y1 + + , e + = dx )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { x1 + + ; e - = dy ; }
}
}
}
else if ( ( dx > = 0 ) & & ( dy < 0 ) )
{
dy = - dy ;
if ( dx > = dy )
{
e = dy - dx / 2 ;
for ( ; x1 < = x2 ; x1 + + , e + = dy )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { y1 - - ; e - = dx ; }
}
}
else
{
e = dx - dy / 2 ;
for ( ; y1 > = y2 ; y1 - - , e + = dx )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { x1 + + ; e - = dy ; }
}
}
}
else if ( ( dx < 0 ) & & ( dy > = 0 ) )
{
dx = - dx ;
if ( dx > = dy )
{
e = dy - dx / 2 ;
for ( ; x1 > = x2 ; x1 - - , e + = dy )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { y1 + + ; e - = dx ; }
}
}
else
{
e = dx - dy / 2 ;
for ( ; y1 < = y2 ; y1 + + , e + = dx )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { x1 - - ; e - = dy ; }
}
}
}
else if ( ( dx < 0 ) & & ( dy < 0 ) )
{
dx = - dx ;
dy = - dy ;
if ( dx > = dy )
{
e = dy - dx / 2 ;
for ( ; x1 > = x2 ; x1 - - , e + = dy )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { y1 - - ; e - = dx ; }
}
}
else
{
e = dx - dy / 2 ;
for ( ; y1 > = y2 ; y1 - - , e + = dx )
{
draw_pixel ( x1 , y1 , rgb , z_order ) ;
if ( e > 0 ) { x1 - - ; e - = dy ; }
}
}
}
}
void draw_rect ( int x0 , int y0 , int x1 , int y1 , unsigned int rgb , unsigned int z_order , unsigned int size = 1 )
{
for ( unsigned int offset = 0 ; offset < size ; offset + + )
{
draw_hline ( x0 + offset , x1 - offset , y0 + offset , rgb , z_order ) ;
draw_hline ( x0 + offset , x1 - offset , y1 - offset , rgb , z_order ) ;
draw_vline ( x0 + offset , y0 + offset , y1 - offset , rgb , z_order ) ;
draw_vline ( x1 - offset , y0 + offset , y1 - offset , rgb , z_order ) ;
}
}
void draw_rect ( c_rect rect , unsigned int rgb , unsigned int size , unsigned int z_order )
{
draw_rect ( rect . m_left , rect . m_top , rect . m_right , rect . m_bottom , rgb , z_order , size ) ;
}
void fill_rect ( c_rect rect , unsigned int rgb , unsigned int z_order )
{
fill_rect ( rect . m_left , rect . m_top , rect . m_right , rect . m_bottom , rgb , z_order ) ;
}
int flush_screen ( int left , int top , int right , int bottom )
{
if ( left < 0 | | left > = m_width | | right < 0 | | right > = m_width | |
top < 0 | | top > = m_height | | bottom < 0 | | bottom > = m_height )
{
ASSERT ( false ) ;
}
if ( ! m_is_active | | ( 0 = = m_phy_fb ) | | ( 0 = = m_fb ) )
{
return - 1 ;
}
int display_width = m_display - > get_width ( ) ;
int display_height = m_display - > get_height ( ) ;
left = ( left > = display_width ) ? ( display_width - 1 ) : left ;
right = ( right > = display_width ) ? ( display_width - 1 ) : right ;
top = ( top > = display_height ) ? ( display_height - 1 ) : top ;
bottom = ( bottom > = display_height ) ? ( display_height - 1 ) : bottom ;
for ( int y = top ; y < bottom ; y + + )
{
void * s_addr = ( char * ) m_fb + ( ( y * m_width + left ) * m_color_bytes ) ;
void * d_addr = ( char * ) m_phy_fb + ( ( y * display_width + left ) * m_color_bytes ) ;
memcpy ( d_addr , s_addr , ( right - left ) * m_color_bytes ) ;
}
* m_phy_write_index = * m_phy_write_index + 1 ;
return 0 ;
}
bool is_active ( ) { return m_is_active ; }
c_display * get_display ( ) { return m_display ; }
int set_frame_layer_visible_rect ( c_rect & rect , unsigned int z_order )
{
if ( rect = = m_frame_layers [ z_order ] . visible_rect )
{
return 0 ;
}
if ( rect . m_left < 0 | | rect . m_left > = m_width | |
rect . m_right < 0 | | rect . m_right > = m_width | |
rect . m_top < 0 | | rect . m_top > = m_height | |
rect . m_bottom < 0 | | rect . m_bottom > = m_height )
{
ASSERT ( false ) ;
return - 1 ;
}
if ( ! ( z_order > Z_ORDER_LEVEL_0 & & z_order < Z_ORDER_LEVEL_MAX ) )
{
ASSERT ( false ) ;
return - 2 ;
}
if ( z_order < ( unsigned int ) m_top_zorder )
{
ASSERT ( false ) ;
return - 3 ;
}
m_top_zorder = ( Z_ORDER_LEVEL ) z_order ;
c_rect old_rect = m_frame_layers [ z_order ] . visible_rect ;
//Recover the lower layer
int src_zorder = ( Z_ORDER_LEVEL ) ( z_order - 1 ) ;
for ( int y = old_rect . m_top ; y < = old_rect . m_bottom ; y + + )
{
for ( int x = old_rect . m_left ; x < = old_rect . m_right ; x + + )
{
if ( ! rect . PtInRect ( x , y ) )
{
2020-03-17 13:16:47 +08:00
unsigned int rgb = ( m_color_bytes = = 4 ) ? ( ( unsigned int * ) ( m_frame_layers [ src_zorder ] . fb ) ) [ x + y * m_width ] : GL_RGB_16_to_32 ( ( ( unsigned short * ) ( m_frame_layers [ src_zorder ] . fb ) ) [ x + y * m_width ] ) ;
draw_pixel_on_fb ( x , y , rgb ) ;
2020-01-22 11:03:29 +08:00
}
}
}
m_frame_layers [ z_order ] . visible_rect = rect ;
if ( rect . IsEmpty ( ) )
{
m_top_zorder = ( Z_ORDER_LEVEL ) ( z_order - 1 ) ;
}
return 0 ;
}
void set_active ( bool flag ) { m_is_active = flag ; }
protected :
virtual void fill_rect_on_fb ( int x0 , int y0 , int x1 , int y1 , unsigned int rgb )
{
int display_width = m_display - > get_width ( ) ;
int display_height = m_display - > get_height ( ) ;
if ( m_color_bytes = = 4 )
{
int x ;
unsigned int * fb , * phy_fb ;
for ( ; y0 < = y1 ; y0 + + )
{
x = x0 ;
fb = m_fb ? & ( ( unsigned int * ) m_fb ) [ y0 * m_width + x ] : 0 ;
phy_fb = & ( ( unsigned int * ) m_phy_fb ) [ y0 * display_width + x ] ;
* m_phy_write_index = * m_phy_write_index + 1 ;
for ( ; x < = x1 ; x + + )
{
if ( fb )
{
* fb + + = rgb ;
}
if ( m_is_active & & ( x < display_width ) & & ( y0 < display_height ) )
{
* phy_fb + + = rgb ;
}
}
}
}
else if ( m_color_bytes = = 2 )
{
int x ;
unsigned short * fb , * phy_fb ;
rgb = GL_RGB_32_to_16 ( rgb ) ;
for ( ; y0 < = y1 ; y0 + + )
{
x = x0 ;
fb = m_fb ? & ( ( unsigned short * ) m_fb ) [ y0 * m_width + x ] : 0 ;
phy_fb = & ( ( unsigned short * ) m_phy_fb ) [ y0 * display_width + x ] ;
* m_phy_write_index = * m_phy_write_index + 1 ;
for ( ; x < = x1 ; x + + )
{
if ( fb )
{
* fb + + = rgb ;
}
if ( m_is_active & & ( x < display_width ) & & ( y0 < display_height ) )
{
* phy_fb + + = rgb ;
}
}
}
}
}
virtual void draw_pixel_on_fb ( int x , int y , unsigned int rgb )
{
if ( m_fb )
{
( m_color_bytes = = 4 ) ? ( ( unsigned int * ) m_fb ) [ y * m_width + x ] = rgb : ( ( unsigned short * ) m_fb ) [ y * m_width + x ] = GL_RGB_32_to_16 ( rgb ) ;
}
2020-03-14 10:58:01 +08:00
if ( m_is_active & & ( x < m_display - > get_width ( ) ) & & ( y < m_display - > get_height ( ) ) )
2020-01-22 11:03:29 +08:00
{
if ( m_color_bytes = = 4 )
{
( ( unsigned int * ) m_phy_fb ) [ y * ( m_display - > get_width ( ) ) + x ] = rgb ;
}
else
{
( ( unsigned short * ) m_phy_fb ) [ y * ( m_display - > get_width ( ) ) + x ] = GL_RGB_32_to_16 ( rgb ) ;
}
* m_phy_write_index = * m_phy_write_index + 1 ;
}
}
2020-03-14 10:58:01 +08:00
void attach_display ( c_display * display )
{
ASSERT ( display ) ;
m_display = display ;
m_phy_fb = display - > m_phy_fb ;
m_phy_write_index = & display - > m_phy_write_index ;
}
void set_surface ( Z_ORDER_LEVEL max_z_order )
{
m_max_zorder = max_z_order ;
if ( m_display & & ( m_display - > m_surface_cnt > 1 ) )
{
m_fb = calloc ( m_width * m_height , m_color_bytes ) ;
}
for ( int i = Z_ORDER_LEVEL_0 ; i < m_max_zorder ; i + + )
{ //Top layber fb always be 0
2020-03-15 17:38:36 +08:00
ASSERT ( ! m_frame_layers [ i ] . fb ) ;
2020-03-17 13:16:47 +08:00
m_frame_layers [ i ] . fb = calloc ( m_width * m_height , m_color_bytes ) ;
2020-03-14 10:58:01 +08:00
ASSERT ( m_frame_layers [ i ] . fb ) ;
}
}
2020-01-22 11:03:29 +08:00
int m_width ; //in pixels
int m_height ; //in pixels
int m_color_bytes ; //16 bits, 32 bits only
2020-03-14 10:58:01 +08:00
void * m_fb ; //frame buffer you could see
2020-01-22 11:03:29 +08:00
c_frame_layer m_frame_layers [ Z_ORDER_LEVEL_MAX ] ; //Top layber fb always be 0
bool m_is_active ;
Z_ORDER_LEVEL m_max_zorder ;
Z_ORDER_LEVEL m_top_zorder ;
2020-03-14 10:58:01 +08:00
void * m_phy_fb ;
int * m_phy_write_index ;
c_display * m_display ;
2020-01-22 11:03:29 +08:00
} ;
class c_surface_no_fb : public c_surface { //No physical framebuffer
friend class c_display ;
2020-03-14 10:58:01 +08:00
public :
c_surface_no_fb ( unsigned int width , unsigned int height , unsigned int color_bytes , struct EXTERNAL_GFX_OP * gfx_op , Z_ORDER_LEVEL max_zorder = Z_ORDER_LEVEL_0 ) : c_surface ( width , height , color_bytes , max_zorder ) , m_gfx_op ( gfx_op ) { }
2020-01-22 11:03:29 +08:00
protected :
virtual void fill_rect_on_fb ( int x0 , int y0 , int x1 , int y1 , unsigned int rgb )
{
if ( ! m_gfx_op )
{
return ;
}
if ( m_gfx_op - > fill_rect )
{
return m_gfx_op - > fill_rect ( x0 , y0 , x1 , y1 , rgb ) ;
}
if ( m_gfx_op - > draw_pixel & & m_is_active )
{
for ( int y = y0 ; y < = y1 ; y + + )
{
for ( int x = x0 ; x < = x1 ; x + + )
{
m_gfx_op - > draw_pixel ( x , y , rgb ) ;
}
}
}
if ( ! m_fb ) { return ; }
if ( m_color_bytes = = 4 )
{
unsigned int * fb ;
for ( int y = y0 ; y < = y1 ; y + + )
{
fb = & ( ( unsigned int * ) m_fb ) [ y0 * m_width + x0 ] ;
for ( int x = x0 ; x < = x1 ; x + + )
{
* fb + + = rgb ;
}
}
}
else if ( m_color_bytes = = 2 )
{
unsigned short * fb ;
rgb = GL_RGB_32_to_16 ( rgb ) ;
for ( int y = y0 ; y < = y1 ; y + + )
{
fb = & ( ( unsigned short * ) m_fb ) [ y0 * m_width + x0 ] ;
for ( int x = x0 ; x < = x1 ; x + + )
{
* fb + + = rgb ;
}
}
}
}
virtual void draw_pixel_on_fb ( int x , int y , unsigned int rgb )
{
if ( m_gfx_op & & m_gfx_op - > draw_pixel & & m_is_active )
{
m_gfx_op - > draw_pixel ( x , y , rgb ) ;
}
if ( ! m_fb ) { return ; }
if ( m_color_bytes = = 4 )
{
( ( unsigned int * ) m_fb ) [ y * m_width + x ] = rgb ;
}
else if ( m_color_bytes = = 2 )
{
( ( unsigned short * ) m_fb ) [ y * m_width + x ] = GL_RGB_32_to_16 ( rgb ) ;
}
}
struct EXTERNAL_GFX_OP * m_gfx_op ; //Rendering by external method
} ;
2020-01-23 16:12:18 +08:00
inline c_display : : c_display ( void * phy_fb , int display_width , int display_height , int surface_width , int surface_height , unsigned int color_bytes , int surface_cnt , EXTERNAL_GFX_OP * gfx_op ) : m_width ( display_width ) , m_height ( display_height ) , m_color_bytes ( color_bytes ) , m_phy_fb ( phy_fb ) , m_phy_read_index ( 0 ) , m_phy_write_index ( 0 ) , m_surface_cnt ( surface_cnt ) , m_surface_index ( 0 )
2020-01-22 11:03:29 +08:00
{
2020-03-14 10:58:01 +08:00
ASSERT ( color_bytes = = 2 | | color_bytes = = 4 ) ;
2020-01-22 11:03:29 +08:00
ASSERT ( m_surface_cnt < = SURFACE_CNT_MAX ) ;
2020-01-23 16:12:18 +08:00
memset ( m_surface_group , 0 , sizeof ( m_surface_group ) ) ;
2020-01-22 11:03:29 +08:00
for ( int i = 0 ; i < m_surface_cnt ; i + + )
2020-01-23 16:12:18 +08:00
{ // Avoid new operation, new operation maybe crash program on Keil platform sometimes.
if ( phy_fb )
{
2020-03-14 10:58:01 +08:00
c_surface tmp ( surface_width , surface_height , color_bytes ) ;
2020-01-23 16:12:18 +08:00
c_surface * surface = ( c_surface * ) malloc ( sizeof ( c_surface ) ) ;
ASSERT ( surface ) ;
memcpy ( surface , & tmp , sizeof ( tmp ) ) ;
m_surface_group [ i ] = surface ;
}
else
{
2020-03-14 10:58:01 +08:00
c_surface_no_fb tmp ( surface_width , surface_height , color_bytes , gfx_op ) ;
2020-01-23 16:12:18 +08:00
c_surface_no_fb * surface = ( c_surface_no_fb * ) malloc ( sizeof ( c_surface_no_fb ) ) ;
ASSERT ( surface ) ;
memcpy ( surface , & tmp , sizeof ( tmp ) ) ;
m_surface_group [ i ] = surface ;
}
2020-03-14 10:58:01 +08:00
m_surface_group [ i ] - > attach_display ( this ) ;
2020-01-22 11:03:29 +08:00
}
}
2020-03-14 10:58:01 +08:00
inline c_display : : c_display ( void * phy_fb , int display_width , int display_height , c_surface * surface ) : m_width ( display_width ) , m_height ( display_height ) , m_phy_fb ( phy_fb ) , m_phy_read_index ( 0 ) , m_phy_write_index ( 0 ) , m_surface_cnt ( 1 ) , m_surface_index ( 0 )
{
surface - > m_is_active = true ;
( m_surface_group [ 0 ] = surface ) - > attach_display ( this ) ;
}
2020-01-22 11:03:29 +08:00
inline c_surface * c_display : : alloc_surface ( Z_ORDER_LEVEL max_zorder )
{
2020-03-14 10:58:01 +08:00
ASSERT ( max_zorder < Z_ORDER_LEVEL_MAX & & m_surface_index < m_surface_cnt ) ;
m_surface_group [ m_surface_index ] - > set_surface ( max_zorder ) ;
return m_surface_group [ m_surface_index + + ] ;
2020-01-22 11:03:29 +08:00
}
inline int c_display : : swipe_surface ( c_surface * s0 , c_surface * s1 , int x0 , int x1 , int y0 , int y1 , int offset )
{
int surface_width = s0 - > get_width ( ) ;
int surface_height = s0 - > get_height ( ) ;
if ( offset < 0 | | offset > surface_width | | y0 < 0 | | y0 > = surface_height | |
y1 < 0 | | y1 > = surface_height | | x0 < 0 | | x0 > = surface_width | | x1 < 0 | | x1 > = surface_width )
{
ASSERT ( false ) ;
return - 1 ;
}
int width = ( x1 - x0 + 1 ) ;
if ( width < 0 | | width > surface_width | | width < offset )
{
ASSERT ( false ) ;
return - 1 ;
}
x0 = ( x0 > = m_width ) ? ( m_width - 1 ) : x0 ;
x1 = ( x1 > = m_width ) ? ( m_width - 1 ) : x1 ;
y0 = ( y0 > = m_height ) ? ( m_height - 1 ) : y0 ;
y1 = ( y1 > = m_height ) ? ( m_height - 1 ) : y1 ;
if ( m_phy_fb )
{
for ( int y = y0 ; y < = y1 ; y + + )
{
//Left surface
char * addr_s = ( ( char * ) ( s0 - > m_fb ) + ( y * ( s0 - > get_width ( ) ) + x0 + offset ) * m_color_bytes ) ;
char * addr_d = ( ( char * ) ( m_phy_fb ) + ( y * m_width + x0 ) * m_color_bytes ) ;
memcpy ( addr_d , addr_s , ( width - offset ) * m_color_bytes ) ;
//Right surface
addr_s = ( ( char * ) ( s1 - > m_fb ) + ( y * ( s1 - > get_width ( ) ) + x0 ) * m_color_bytes ) ;
addr_d = ( ( char * ) ( m_phy_fb ) + ( y * m_width + x0 + ( width - offset ) ) * m_color_bytes ) ;
memcpy ( addr_d , addr_s , offset * m_color_bytes ) ;
}
}
else if ( m_color_bytes = = 4 )
{
void ( * draw_pixel ) ( int x , int y , unsigned int rgb ) = ( ( c_surface_no_fb * ) s0 ) - > m_gfx_op - > draw_pixel ;
for ( int y = y0 ; y < = y1 ; y + + )
{
//Left surface
for ( int x = x0 ; x < = ( x1 - offset ) ; x + + )
{
draw_pixel ( x , y , ( ( unsigned int * ) s0 - > m_fb ) [ y * m_width + x + offset ] ) ;
}
//Right surface
for ( int x = x1 - offset ; x < = x1 ; x + + )
{
draw_pixel ( x , y , ( ( unsigned int * ) s1 - > m_fb ) [ y * m_width + x + offset - x1 + x0 ] ) ;
}
}
}
else if ( m_color_bytes = = 2 )
{
void ( * draw_pixel ) ( int x , int y , unsigned int rgb ) = ( ( c_surface_no_fb * ) s0 ) - > m_gfx_op - > draw_pixel ;
for ( int y = y0 ; y < = y1 ; y + + )
{
//Left surface
for ( int x = x0 ; x < = ( x1 - offset ) ; x + + )
{
draw_pixel ( x , y , GL_RGB_16_to_32 ( ( ( unsigned short * ) s0 - > m_fb ) [ y * m_width + x + offset ] ) ) ;
}
//Right surface
for ( int x = x1 - offset ; x < = x1 ; x + + )
{
draw_pixel ( x , y , GL_RGB_16_to_32 ( ( ( unsigned short * ) s1 - > m_fb ) [ y * m_width + x + offset - x1 + x0 ] ) ) ;
}
}
}
m_phy_write_index + + ;
return 0 ;
}
2019-02-02 11:30:40 +08:00
# endif