LCD 是對顯示設備的抽象,提供了基本的繪圖函數。本身去實現 LCD 接口雖然不難,可是須要花費很多功夫,AWTK 提供了幾種缺省的實現,利用這些缺省的實現,在移植到新的平臺時,通常只須要不多的代碼就好了。canvas
下面咱們介紹一下幾種常見的 LCD 實現方式:函數
在低端的嵌入式平臺上,內存只有幾十 KB,沒有足夠的內存使用 framebuffer,一般直接向寄存器中寫入座標和顏色數據。lcd_reg.inc 提供了基於寄存器實現的 LCD,用它實現不一樣平臺的 LCD 時,只須要提供兩個宏便可:性能
下面是 STMF103ze 上 LCD 的實現,這裏把 set_window_func 定義爲 TFT_SetWindow,把 write_data_func 定義爲 TFT_WriteData:動畫
#include "tftlcd.h" #include "tkc/mem.h" #include "lcd/lcd_reg.h" typedef uint16_t pixel_t; #define LCD_FORMAT BITMAP_FMT_BGR565 #define pixel_from_rgb(r, g, b) \ ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) #define pixel_to_rgba(p) \ { (0xff & ((p >> 11) << 3)), (0xff & ((p >> 5) << 2)), (0xff & (p << 3)) } #define set_window_func LCD_Set_Window #define write_data_func LCD_WriteData_Color #include "base/pixel.h" #include "blend/pixel_ops.inc" #include "lcd/lcd_reg.inc"
基於寄存器實現的實現有幾個限制:ui
在 AWTK 中,再也不推薦此方法,基於片斷幀緩衝實現的 LCD 是更好的選擇。code
在低端的嵌入式平臺上,內存只有幾十 KB,沒有足夠的內存建立一屏的幀緩衝,而使用基於寄存器的方式屏幕容易閃爍。orm
比較好的辦法是,建立一小塊幀緩衝,把屏幕分紅不少小塊,一次只繪製一小塊。因爲有髒矩形機制,除了打開新窗口時,在正常狀況下,繪製速度仍然很快,能夠有效的解決閃速問題。接口
lcd_mem_fragment.inc 提供了基於片斷幀緩衝實現的 LCD,用它實現不一樣平臺的 LCD 時,只須要提供兩個宏便可:內存
下面是 STMF103ze 上 LCD 的實現,這裏把 set_window_func 定義爲 TFT_SetWindow,把 write_data_func 定義爲 TFT_WriteData:it
#include "tftlcd.h" #include "tkc/mem.h" #include "lcd/lcd_mem_fragment.h" typedef uint16_t pixel_t; #define LCD_FORMAT BITMAP_FMT_BGR565 #define pixel_from_rgb(r, g, b) \ ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) #define pixel_to_rgba(p) \ { (0xff & ((p >> 11) << 3)), (0xff & ((p >> 5) << 2)), (0xff & (p << 3)) } #define set_window_func LCD_Set_Window #define write_data_func LCD_WriteData_Color #include "base/pixel.h" #include "blend/pixel_ops.inc" #include "lcd/lcd_mem_fragment.inc"
這是在嵌入式平臺上最多見的方式。通常有兩個 framebuffer,一個稱爲 online framebuffer,一個稱爲 offline framebuffer。online framebuffer 是當前現實的內容,offline framebuffer 是 GUI 當前正在繪製的內容。lcd_mem_rgb565 提供了 rgb565 格式的 LCD 實現,lcd_mem_rgba8888 提供了 rgba8888 格式的 LCD 實現,它們都是在 lcd_mem.inc 基礎上實現的,要增長新的格式也是很方便的。
下面是 STMF429 上 LCD 的實現:
extern u32 *ltdc_framebuf[2]; #define online_fb_addr (uint8_t*)ltdc_framebuf[0] #define offline_fb_addr (uint8_t*)ltdc_framebuf[1] lcd_t* platform_create_lcd(wh_t w, wh_t h) { return lcd_mem_rgb565_create_double_fb(w, h, online_fb_addr, offline_fb_addr); }
在支持 OpenGL 3D 硬件加速的平臺上(如 PC 和手機),咱們使用 nanovg 把 OpenGL 封裝成 vgcanvas 的接口,在 vgcanvas 基礎之上實現 LCD。lcd_vgcanvas.inc 將 vgcanvas 封裝成 LCD 的接口,這裏出於可移植性考慮,並無直接基於 nanovg 的函數,而是基於 vgcanvas 的接口,因此在沒有 GPU 時,若是 CPU 夠強大,也是能夠基於 agg/picasso 去實現的 LCD。
這種方式實現,通常不會在嵌入平臺上使用,讀者不須要關注它。
以上幾種實現方式,基本上涵蓋了最經常使用的場景,因此在移植 AWTK 到新的平臺時,並不須要在實現 LCD 接口上費多少功夫。