Просмотр исходного кода

add: lcd库对接SDL2, 实现对其的仿真, 并添加辅助的pin库, 实现demo/lcd直接跑

Wendal Chen 4 лет назад
Родитель
Сommit
f7fa218786

+ 202 - 0
bsp/sysp/build/index.html

@@ -0,0 +1,202 @@
+<!doctypehtml>
+  <html lang=en-us>
+
+  <head>
+    <meta charset=utf-8>
+    <meta content="text/html; charset=utf-8" http-equiv=Content-Type>
+    <title>Emscripten-Generated Code</title>
+    <script src="https://cdn.jsdelivr.net/npm/jquery@3.2"></script>
+    <style>
+      body {
+        font-family: arial;
+        margin: 0;
+        padding: none
+      }
+
+      .emscripten {
+        padding-right: 0;
+        margin-left: auto;
+        margin-right: auto;
+        display: block
+      }
+
+      div.emscripten {
+        text-align: center
+      }
+
+      div.emscripten_border {
+        border: 1px solid #000
+      }
+
+      canvas.emscripten {
+        border: 0 none;
+        background-color: #000
+      }
+
+      #title_logo {
+        display: inline-block;
+        margin: 0
+      }
+
+      .spinner {
+        height: 30px;
+        width: 30px;
+        margin: 0;
+        margin-top: 20px;
+        margin-left: 20px;
+        display: inline-block;
+        vertical-align: top;
+        -webkit-animation: rotation .8s linear infinite;
+        -moz-animation: rotation .8s linear infinite;
+        -o-animation: rotation .8s linear infinite;
+        animation: rotation .8s linear infinite;
+        border-left: 5px solid #ebebeb;
+        border-right: 5px solid #ebebeb;
+        border-bottom: 5px solid #ebebeb;
+        border-top: 5px solid #787878;
+        border-radius: 100%;
+        background-color: #bdd72e
+      }
+
+      @-webkit-keyframes rotation {
+        from {
+          -webkit-transform: rotate(0)
+        }
+
+        to {
+          -webkit-transform: rotate(360deg)
+        }
+      }
+
+      @-moz-keyframes rotation {
+        from {
+          -moz-transform: rotate(0)
+        }
+
+        to {
+          -moz-transform: rotate(360deg)
+        }
+      }
+
+      @-o-keyframes rotation {
+        from {
+          -o-transform: rotate(0)
+        }
+
+        to {
+          -o-transform: rotate(360deg)
+        }
+      }
+
+      @keyframes rotation {
+        from {
+          transform: rotate(0)
+        }
+
+        to {
+          transform: rotate(360deg)
+        }
+      }
+
+      #status {
+        display: inline-block;
+        vertical-align: top;
+        margin-top: 30px;
+        margin-left: 20px;
+        font-weight: 700;
+        color: #787878
+      }
+
+      #progress {
+        height: 20px;
+        width: 300px
+      }
+
+      #controls {
+        display: inline-block;
+        float: right;
+        vertical-align: top;
+        margin-top: 30px;
+        margin-right: 20px
+      }
+
+      #output {
+        width: 100%;
+        height: 200px;
+        margin: 0 auto;
+        margin-top: 10px;
+        border-left: 0;
+        border-right: 0px;
+        padding-left: 0;
+        padding-right: 0;
+        display: block;
+        background-color: #000;
+        color: #fff;
+        font-family: 'Lucida Console', Monaco, monospace;
+        outline: 0
+      }
+
+      .luat-os {
+        margin: 10px 0;
+        padding: 10px 20px;
+      }
+
+      .luat-os textarea {
+        display: block;
+        width: 100%;
+        margin-bottom: 10px;
+      }
+
+      .luat-os button {
+        display: block;
+        width: 200px;
+        margin: 0 auto;
+        padding: 5px 20px;
+      }
+    </style>
+  </head>
+
+  <body>
+    <a href="https://luatos.com" class="title-logo">
+      <img src="https://luatos.com/img/footer-logo.png" alt="">
+    </a>
+    <div class=spinner id=spinner></div>
+    <div class=emscripten id=status>Downloading...</div><span id=controls><span><input type=checkbox id=resize>Resize
+        canvas</span><span><input type=checkbox id=pointerLock checked>Lock/hide mouse pointer    </span><span><input
+          type=button
+          onclick='Module.requestFullscreen(document.getElementById("pointerLock").checked,document.getElementById("resize").checked)'
+          value=Fullscreen></span></span>
+    <div class=emscripten><progress hidden id=progress max=100 value=0></progress></div>
+    <div class=emscripten_border><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault()
+        tabindex=-1></canvas></div><textarea id=output rows=8></textarea>
+    <script>var statusElement = document.getElementById("status"), progressElement = document.getElementById("progress"), spinnerElement = document.getElementById("spinner"), Module = { preRun: [], postRun: [], print: function () { var e = document.getElementById("output"); return e && (e.value = ""), function (t) { arguments.length > 1 && (t = Array.prototype.slice.call(arguments).join(" ")), console.log(t), e && (e.value += t + "\n", e.scrollTop = e.scrollHeight) } }(), canvas: function () { var e = document.getElementById("canvas"); return e.addEventListener("webglcontextlost", (function (e) { alert("WebGL context lost. You will need to reload the page."), e.preventDefault() }), !1), e }(), setStatus: function (e) { if (Module.setStatus.last || (Module.setStatus.last = { time: Date.now(), text: "" }), e !== Module.setStatus.last.text) { var t = e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/), n = Date.now(); t && n - Module.setStatus.last.time < 30 || (Module.setStatus.last.time = n, Module.setStatus.last.text = e, t ? (e = t[1], progressElement.value = 100 * parseInt(t[2]), progressElement.max = 100 * parseInt(t[4]), progressElement.hidden = !1, spinnerElement.hidden = !1) : (progressElement.value = null, progressElement.max = null, progressElement.hidden = !0, e || (spinnerElement.style.display = "none")), statusElement.innerHTML = e) } }, totalDependencies: 0, monitorRunDependencies: function (e) { this.totalDependencies = Math.max(this.totalDependencies, e), Module.setStatus(e ? "Preparing... (" + (this.totalDependencies - e) + "/" + this.totalDependencies + ")" : "All downloads complete.") } }; Module.setStatus("Downloading..."), window.onerror = function (e) { Module.setStatus("Exception thrown, see JavaScript console"), spinnerElement.style.display = "none", Module.setStatus = function (e) { e && console.error("[post-exception status] " + e) } }</script>
+    <script async src=luatos.js></script>
+
+    <div class="luat-os">
+      <textarea cols="30" rows="10" id="run-code" placeholder="请写入要执行的 lua 代码"></textarea>
+      <button id="run-btn">执行代码</button>
+    </div>
+
+    <script>
+      var $code = $('#run-code')
+      var $btn = $('#run-btn')
+
+      $btn.on('click', function () {
+
+
+        var codeText = $code.val() || "";
+        console.log("code:\n" + codeText)
+        if (codeText.length == 0) {
+          alert("执行内容不能为空")
+          return;
+        }
+
+        // 第一步, 注入main.lua文件
+        Module.ccall("luat_fs_append_onefile", "int", ["string", "string", "number"], ["/main.lua", codeText, 0])
+        // 第二步, 启动虚拟机
+        Module.ccall("luat_sysp_start", "int", [], [])
+      })
+    </script>
+  </body>
+
+  </html>

+ 3 - 1
bsp/sysp/include/luat_conf_bsp.h

@@ -39,7 +39,7 @@
 /**********U8G2&LCD FONT*************/
 /**********U8G2&LCD FONT*************/
 // #define USE_U8G2_UNIFONT_SYMBOLS
 // #define USE_U8G2_UNIFONT_SYMBOLS
 #define USE_U8G2_OPPOSANSM12_CHINESE
 #define USE_U8G2_OPPOSANSM12_CHINESE
-// #define USE_U8G2_OPPOSANSM16_CHINESE
+#define USE_U8G2_OPPOSANSM16_CHINESE
 // #define USE_U8G2_OPPOSANSM24_CHINESE
 // #define USE_U8G2_OPPOSANSM24_CHINESE
 // #define USE_U8G2_OPPOSANSM32_CHINESE
 // #define USE_U8G2_OPPOSANSM32_CHINESE
 
 
@@ -58,6 +58,8 @@ unsigned int get_timestamp(void);
 #define LV_COLOR_DEPTH 16
 #define LV_COLOR_DEPTH 16
 
 
 #define LUAT_USE_LVGL_SDL2 1
 #define LUAT_USE_LVGL_SDL2 1
+#define LUAT_USE_LCD_SDL2 1
+#define LUAT_USE_LCD_CUSTOM_DRAW 1
 
 
 #define LUAT_USE_LVGL 1
 #define LUAT_USE_LVGL 1
 #define LV_MEM_CUSTOM 1
 #define LV_MEM_CUSTOM 1

+ 1 - 0
bsp/sysp/port/luat_base_sysp.c

@@ -33,6 +33,7 @@ static const luaL_Reg loadedlibs[] = {
   {"libcoap", luaopen_libcoap},        // 
   {"libcoap", luaopen_libcoap},        // 
   {"crypto", luaopen_crypto},
   {"crypto", luaopen_crypto},
   {"lvgl", luaopen_lvgl},
   {"lvgl", luaopen_lvgl},
+  {"pin",  luaopen_pin},
 //------------------------------------------------
 //------------------------------------------------
 // 这部分是外设, 只能模拟
 // 这部分是外设, 只能模拟
   {"gpio", luaopen_gpio},
   {"gpio", luaopen_gpio},

+ 14 - 0
bsp/sysp/port/luat_pin_sysp.c

@@ -0,0 +1,14 @@
+#include "luat_base.h"
+#include "luat_pin.h"
+
+int luat_pin_to_gpio(const char* pin_name) {
+    int zone = 0;
+    int index = 0;
+    int re = 0;
+    re = luat_pin_parse(pin_name, &zone, &index);
+    if (re < 0) {
+        return -1;
+    }
+    return zone * 16 + index;
+}
+

+ 2 - 0
components/lcd/luat_lcd.c

@@ -174,6 +174,7 @@ int luat_lcd_set_color(luat_color_t back, luat_color_t fore){
     return 0;
     return 0;
 }
 }
 
 
+#ifndef LUAT_USE_LCD_CUSTOM_DRAW
 int luat_lcd_draw(luat_lcd_conf_t* conf, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, luat_color_t* color) {
 int luat_lcd_draw(luat_lcd_conf_t* conf, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, luat_color_t* color) {
     uint32_t size = (x2 - x1 + 1) * (y2 - y1 + 1) * 2;
     uint32_t size = (x2 - x1 + 1) * (y2 - y1 + 1) * 2;
     luat_lcd_set_address(conf, x1, y1, x2, y2);
     luat_lcd_set_address(conf, x1, y1, x2, y2);
@@ -184,6 +185,7 @@ int luat_lcd_draw(luat_lcd_conf_t* conf, uint16_t x1, uint16_t y1, uint16_t x2,
 	}
 	}
     return 0;
     return 0;
 }
 }
+#endif
 
 
 int luat_lcd_clear(luat_lcd_conf_t* conf, luat_color_t color){
 int luat_lcd_clear(luat_lcd_conf_t* conf, luat_color_t color){
     luat_lcd_draw_fill(conf, 0, 0, conf->w, conf->h, color);
     luat_lcd_draw_fill(conf, 0, 0, conf->w, conf->h, color);

+ 1 - 1
components/lcd/luat_lcd_custom.c

@@ -20,7 +20,7 @@ static int custom_init(luat_lcd_conf_t* conf) {
         conf->h = LCD_H;
         conf->h = LCD_H;
     if (conf->direction == 0)
     if (conf->direction == 0)
         conf->direction = LCD_DIRECTION;
         conf->direction = LCD_DIRECTION;
-        
+
     if (conf->pin_pwr != 255)
     if (conf->pin_pwr != 255)
         luat_gpio_mode(conf->pin_pwr, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_LOW); // POWER
         luat_gpio_mode(conf->pin_pwr, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_LOW); // POWER
     luat_gpio_mode(conf->pin_dc, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_HIGH); // DC
     luat_gpio_mode(conf->pin_dc, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_HIGH); // DC

+ 4 - 0
components/lcd/luat_lib_lcd.c

@@ -219,6 +219,10 @@ static int l_lcd_init(lua_State* L) {
             lua_pop(L, 1);
             lua_pop(L, 1);
             conf->userdata = cst;
             conf->userdata = cst;
         }
         }
+#ifdef LUAT_USE_LCD_SDL2
+        extern const luat_lcd_opts_t lcd_opts_sdl2;
+        conf->opts = &lcd_opts_sdl2;
+#endif
         int ret = luat_lcd_init(conf);
         int ret = luat_lcd_init(conf);
         if (ret == 0) {
         if (ret == 0) {
             if (dft_conf_lua_ref) {
             if (dft_conf_lua_ref) {

+ 15 - 4
components/lvgl/binding/luat_lib_lvgl7.c

@@ -34,6 +34,7 @@ static luat_lv_t LV = {0};
 int luat_lv_init(lua_State *L);
 int luat_lv_init(lua_State *L);
 
 
 #ifdef LUAT_USE_LVGL_SDL2
 #ifdef LUAT_USE_LVGL_SDL2
+#include "luat_lcd.h"
 // SDL2 模式
 // SDL2 模式
 extern lv_disp_t *lv_sdl_init_display(const char* win_name, int width, int height);
 extern lv_disp_t *lv_sdl_init_display(const char* win_name, int width, int height);
 extern lv_indev_t *lv_sdl_init_input(void);
 extern lv_indev_t *lv_sdl_init_input(void);
@@ -41,13 +42,23 @@ int luat_lv_init(lua_State *L) {
     int w = 480;
     int w = 480;
     int h = 320;
     int h = 320;
 
 
+    luat_lcd_conf_t *lcd_conf = NULL;
+    if (lua_isuserdata(L, 3)) {
+        lcd_conf = lua_touserdata(L, 3);
+    }
+    else {
+        lcd_conf = luat_lcd_get_default();
+    }
+
     if (lua_isnumber(L, 1) && lua_isnumber(L, 2)) {
     if (lua_isnumber(L, 1) && lua_isnumber(L, 2)) {
         w = luaL_checkinteger(L, 1);
         w = luaL_checkinteger(L, 1);
         h = luaL_checkinteger(L, 2);
         h = luaL_checkinteger(L, 2);
     }
     }
-    lv_sdl_init_display("LVGL@LuatOS", w, h);
+    if (lcd_conf == NULL)
+        lv_sdl_init_display("LuatOS", w, h);
     lv_sdl_init_input();
     lv_sdl_init_input();
-    return 0;
+    lua_pushboolean(L, 1);
+    return 1;
 }
 }
 #elif defined(LUAT_EMULATOR_MODE)
 #elif defined(LUAT_EMULATOR_MODE)
 // 模拟器模式
 // 模拟器模式
@@ -126,12 +137,12 @@ int luat_lv_init(lua_State *L) {
     else {
     else {
         lcd_conf = luat_lcd_get_default();
         lcd_conf = luat_lcd_get_default();
     }
     }
+
     if (lcd_conf == NULL) {
     if (lcd_conf == NULL) {
         LLOGE("setup lcd first!!");
         LLOGE("setup lcd first!!");
         return 0;
         return 0;
     }
     }
-
-    if (w == 0 || h == 0) {
+    else if (w == 0 || h == 0) {
         w = lcd_conf->w;
         w = lcd_conf->w;
         h = lcd_conf->h;
         h = lcd_conf->h;
     }
     }

+ 75 - 63
components/lvgl/sdl2/lv_sdl_drv_display.c

@@ -22,6 +22,9 @@
  */
  */
 
 
 #include "luat_base.h"
 #include "luat_base.h"
+#include "luat_malloc.h"
+#define LUAT_LOG_TAG "sdl2"
+#include "luat_log.h"
 #ifdef LUAT_USE_LVGL_SDL2
 #ifdef LUAT_USE_LVGL_SDL2
 #include <stdio.h>
 #include <stdio.h>
 #include <assert.h>
 #include <assert.h>
@@ -32,37 +35,34 @@
 static lv_disp_buf_t disp_buf;
 static lv_disp_buf_t disp_buf;
 static lv_color_t *pixels;
 static lv_color_t *pixels;
 static uint32_t *fb;
 static uint32_t *fb;
-#ifdef NXDK
-#include <hal/video.h>
-void *framebuffer;
-#else
-#include <SDL2/SDL.h>
-static lv_task_t *sdl_present_task;
-
-SDL_Window *window = NULL;
-SDL_Renderer *renderer = NULL;
-SDL_Texture *framebuffer = NULL;
-#endif
+#include "luat_sdl2.h"
+// #ifdef NXDK
+// #include <hal/video.h>
+// void *framebuffer;
+// #else
+// #include <SDL2/SDL.h>
+// static lv_task_t *sdl_present_task;
+
+// SDL_Window *window = NULL;
+// SDL_Renderer *renderer = NULL;
+// SDL_Texture *framebuffer = NULL;
+// #endif
 static void sdl_fb_flush(lv_disp_drv_t *disp_drv,
 static void sdl_fb_flush(lv_disp_drv_t *disp_drv,
                          const lv_area_t *area,
                          const lv_area_t *area,
                          lv_color_t *color_p)
                          lv_color_t *color_p)
 {
 {
     //printf("disp flush %d %d %d %d\n", area->x1, area->y1, area->x2, area->y2);
     //printf("disp flush %d %d %d %d\n", area->x1, area->y1, area->x2, area->y2);
-    if(area->x2 < 0 || area->y2 < 0 ||
-       area->x1 > disp_drv->hor_res - 1 || area->y1 > disp_drv->ver_res - 1) {
+    if(area->x2 < 0 || area->y2 < 0 || area->x1 > disp_drv->hor_res - 1 || area->y1 > disp_drv->ver_res - 1) {
         lv_disp_flush_ready(disp_drv);
         lv_disp_flush_ready(disp_drv);
         return;
         return;
     }
     }
-    SDL_Rect r;
-    r.x = area->x1;
-    r.y = area->y1;
-    r.w = area->x2 - area->x1 + 1;
-    r.h = area->y2 - area->y1 + 1;
+    size_t rw = area->x2 - area->x1 + 1;
+    size_t rh = area->y2 - area->y1 + 1;
 
 
     uint32_t *tmp = fb;
     uint32_t *tmp = fb;
-    for (size_t i = 0; i < r.h; i++)
+    for (size_t i = 0; i < rh; i++)
     {
     {
-        for (size_t j = 0; j < r.w; j++)
+        for (size_t j = 0; j < rw; j++)
         {
         {
             *tmp = lv_color_to32(*color_p);
             *tmp = lv_color_to32(*color_p);
             tmp ++;
             tmp ++;
@@ -70,27 +70,33 @@ static void sdl_fb_flush(lv_disp_drv_t *disp_drv,
         }
         }
     }
     }
 
 
-    SDL_UpdateTexture(framebuffer, &r, fb, r.w * 4);
+    luat_sdl2_draw(area->x1, area->y1, area->x2, area->y2, fb);
+    //SDL_UpdateTexture(framebuffer, &r, fb, r.w * 4);
+    if (disp_drv->buffer->flushing_last) {
+        //SDL_RenderCopy(renderer, framebuffer, NULL, NULL);
+        //SDL_RenderPresent(renderer);
+        luat_sdl2_flush();
+    }
     lv_disp_flush_ready(disp_drv);
     lv_disp_flush_ready(disp_drv);
 }
 }
 
 
-#ifndef NXDK
-static void sdl_present(lv_task_t *task)
-{
-    if (renderer && framebuffer)
-    {
-        SDL_RenderCopy(renderer, framebuffer, NULL, NULL);
-        SDL_RenderPresent(renderer);
-    }
-}
-#endif
+// #ifndef NXDK
+// static void sdl_present(lv_task_t *task)
+// {
+//     if (renderer && framebuffer)
+//     {
+//         SDL_RenderCopy(renderer, framebuffer, NULL, NULL);
+//         SDL_RenderPresent(renderer);
+//     }
+// }
+// #endif
 
 
-__attribute__((weak)) void display_wait_cb(lv_disp_drv_t *disp_drv)
-{
-    (void)disp_drv;
+// __attribute__((weak)) void display_wait_cb(lv_disp_drv_t *disp_drv)
+// {
+    // (void)disp_drv;
     //OPTIONAL: Called periodically while lvgl waits for an operation to be completed
     //OPTIONAL: Called periodically while lvgl waits for an operation to be completed
     //          User can execute very simple tasks here or yield the task
     //          User can execute very simple tasks here or yield the task
-}
+// }
 
 
 lv_disp_t *lv_sdl_init_display(const char *win_name, int width, int height)
 lv_disp_t *lv_sdl_init_display(const char *win_name, int width, int height)
 {
 {
@@ -100,49 +106,55 @@ lv_disp_t *lv_sdl_init_display(const char *win_name, int width, int height)
     if (height > LV_VER_RES_MAX)
     if (height > LV_VER_RES_MAX)
         height = LV_VER_RES_MAX;
         height = LV_VER_RES_MAX;
     size_t buff_line = 16;
     size_t buff_line = 16;
-    pixels = malloc(sizeof(lv_color_t) * width * buff_line);
-    fb = malloc(sizeof(uint32_t) * width * buff_line);
+    pixels = luat_heap_malloc(sizeof(lv_color_t) * width * buff_line);
+    fb = luat_heap_malloc(sizeof(uint32_t) * width * buff_line);
     //printf("pixels %p\n", pixels);
     //printf("pixels %p\n", pixels);
     lv_disp_buf_init(&disp_buf, pixels, NULL, width * buff_line);
     lv_disp_buf_init(&disp_buf, pixels, NULL, width * buff_line);
     lv_disp_drv_t disp_drv;
     lv_disp_drv_t disp_drv;
     lv_disp_drv_init(&disp_drv);
     lv_disp_drv_init(&disp_drv);
     disp_drv.buffer = &disp_buf;
     disp_drv.buffer = &disp_buf;
-    disp_drv.wait_cb = display_wait_cb;
+    // disp_drv.wait_cb = display_wait_cb;
     disp_drv.flush_cb = sdl_fb_flush;
     disp_drv.flush_cb = sdl_fb_flush;
     disp_drv.hor_res = width;
     disp_drv.hor_res = width;
     disp_drv.ver_res = height;
     disp_drv.ver_res = height;
 
 
-    if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0)
-        printf("SDL_InitSubSystem failed: %s\n", SDL_GetError());
+    luat_sdl2_conf_t conf = {
+        .width = width,
+        .height = height
+    };
+    luat_sdl2_init(&conf);
 
 
-    window = SDL_CreateWindow(win_name,
-                              SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
-                              width, height, 0);
+    // if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0)
+    //     printf("SDL_InitSubSystem failed: %s\n", SDL_GetError());
 
 
-    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
-    framebuffer = SDL_CreateTexture(renderer,
-                                    SDL_PIXELFORMAT_ARGB8888,
-                                    SDL_TEXTUREACCESS_STREAMING,
-                                    width,
-                                    height);
+    // window = SDL_CreateWindow(win_name,
+    //                           SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+    //                           width, height, 0);
 
 
-    sdl_present_task = lv_task_create(sdl_present, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_HIGHEST, NULL);
+    // renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+    // framebuffer = SDL_CreateTexture(renderer,
+    //                                 SDL_PIXELFORMAT_ARGB8888,
+    //                                 SDL_TEXTUREACCESS_STREAMING,
+    //                                 width,
+    //                                 height);
+
+    //sdl_present_task = lv_task_create(sdl_present, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_HIGHEST, NULL);
 
 
     return lv_disp_drv_register(&disp_drv);
     return lv_disp_drv_register(&disp_drv);
 }
 }
 
 
-void lv_sdl_deinit_display(void)
-{
-    #ifdef NXDK
-    XVideoFlushFB();
-    MmFreeContiguousMemory(framebuffer);
-    #else
-    lv_task_del(sdl_present_task);
-    SDL_DestroyTexture(framebuffer);
-    SDL_DestroyRenderer(renderer);
-    SDL_DestroyWindow(window);
-    SDL_QuitSubSystem(SDL_INIT_VIDEO);
-    #endif
-}
+// void lv_sdl_deinit_display(void)
+// {
+//     #ifdef NXDK
+//     XVideoFlushFB();
+//     MmFreeContiguousMemory(framebuffer);
+//     #else
+//     lv_task_del(sdl_present_task);
+//     SDL_DestroyTexture(framebuffer);
+//     SDL_DestroyRenderer(renderer);
+//     SDL_DestroyWindow(window);
+//     SDL_QuitSubSystem(SDL_INIT_VIDEO);
+//     #endif
+// }
 
 
 #endif
 #endif

+ 74 - 0
components/ui/sdl2/luat_lcd_sdl2.c

@@ -0,0 +1,74 @@
+#include "luat_base.h"
+
+#include "luat_lcd.h"
+#include "luat_sdl2.h"
+#include "luat_malloc.h"
+
+static uint32_t* fb;
+
+static int sdl2_init(luat_lcd_conf_t* conf) {
+    luat_sdl2_conf_t sdl2_conf = {
+        .width = conf->w,
+        .height = conf->h
+    };
+    luat_sdl2_init(&sdl2_conf);
+    fb = luat_heap_malloc(sizeof(uint32_t) * conf->w * conf->h);
+    return 0;
+}
+
+const luat_lcd_opts_t lcd_opts_sdl2 = {
+    .name = "sdl2",
+    .init = sdl2_init,
+};
+
+typedef struct luat_color_rgb565swap
+{
+    uint16_t blue : 5;
+    uint16_t green : 6;
+    uint16_t red : 5;
+}luat_color_rgb565swap_t;
+
+typedef struct luat_color_argb8888
+{
+    uint8_t blue;
+    uint8_t green;
+    uint8_t red;
+    uint8_t alpha;
+}luat_color_argb8888_t;
+
+
+static inline uint32_t luat_color_565to8888(luat_color_t color) {
+    luat_color_rgb565swap_t tmp;
+    memcpy(&tmp, &color, sizeof(luat_color_rgb565swap_t));
+    luat_color_argb8888_t dst = {
+        .alpha = 0xFF,
+        .blue = (tmp.blue * 259 + 3) >> 6,
+        .green = (tmp.green * 263 + 7) >> 5,
+        .red = (tmp.red * 263 + 7) >> 5
+    };
+    uint32_t t;
+    memcpy(&t, &dst, sizeof(luat_color_argb8888_t));
+    return t;
+}
+
+int luat_lcd_draw(luat_lcd_conf_t* conf, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, luat_color_t* color_p) {
+    size_t rw = x2 - x1 + 1;
+    size_t rh = y2 - y1 + 1;
+
+    uint32_t *tmp = fb;
+    for (size_t i = 0; i < rh; i++)
+    {
+        for (size_t j = 0; j < rw; j++)
+        {
+            *tmp = luat_color_565to8888(*color_p);
+            tmp ++;
+            color_p ++;
+        }
+    }
+    
+    luat_sdl2_draw(x1, y1, x2, y2, fb);
+    luat_sdl2_flush();
+    return 0;
+}
+
+

+ 70 - 0
components/ui/sdl2/luat_sdl2.c

@@ -0,0 +1,70 @@
+#include "luat_base.h"
+#include "luat_sdl2.h"
+
+#include "SDL2/SDL.h"
+
+#define LUAT_LOG_TAG "sdl2"
+#include "luat_log.h"
+
+static SDL_Window *window = NULL;
+static SDL_Renderer *renderer = NULL;
+static SDL_Texture *framebuffer = NULL;
+
+static uint32_t* fb;
+static luat_sdl2_conf_t sdl_conf;
+
+int luat_sdl2_init(luat_sdl2_conf_t *conf) {
+    if (framebuffer != NULL) {
+        LLOGD("SDL2 aready inited");
+        return -1;
+    }
+    if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
+        LLOGE("SDL_InitSubSystem failed: %s\n", SDL_GetError());
+        return -1;
+    }
+    memcpy(&sdl_conf, conf, sizeof(luat_sdl2_conf_t));
+
+    window = SDL_CreateWindow(conf->title == NULL ? "LuatOS" : conf->title,
+                              SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+                              conf->width, conf->height, 0);
+
+    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+    framebuffer = SDL_CreateTexture(renderer,
+                                    SDL_PIXELFORMAT_ARGB8888,
+                                    SDL_TEXTUREACCESS_STREAMING,
+                                    conf->width,
+                                    conf->height);
+    // fb = luat_heap_malloc(sizeof(uint32_t) * conf->width * conf->height);
+    return 0;
+}
+
+int luat_sdl2_deinit(luat_sdl2_conf_t *conf) {
+    SDL_DestroyTexture(framebuffer);
+    SDL_DestroyRenderer(renderer);
+    SDL_DestroyWindow(window);
+    SDL_QuitSubSystem(SDL_INIT_VIDEO);
+    // free(fb);
+    framebuffer = NULL;
+    renderer = NULL;
+    window = NULL;
+    // fb = NULL;
+    return 0;
+}
+
+void luat_sdl2_draw(size_t x1, size_t y1, size_t x2, size_t y2, uint32_t* data) {
+    SDL_Rect r;
+    r.x = x1;
+    r.y = y1;
+    r.w = x2 - x1 + 1;
+    r.h = y2 - y1 + 1;
+
+    SDL_UpdateTexture(framebuffer, &r, data, r.w * 4);
+}
+
+void luat_sdl2_flush(void) {
+    if (renderer && framebuffer)
+    {
+        SDL_RenderCopy(renderer, framebuffer, NULL, NULL);
+        SDL_RenderPresent(renderer);
+    }
+}

+ 21 - 0
components/ui/sdl2/luat_sdl2.h

@@ -0,0 +1,21 @@
+
+#ifndef LUAT_SDL2_H
+#define LUAT_SDL2_H
+#include "luat_base.h"
+
+typedef struct luat_sdl2_conf
+{
+    size_t width;
+    size_t height;
+    const char* title;
+    // uint32_t color_space;
+}luat_sdl2_conf_t;
+
+int luat_sdl2_init(luat_sdl2_conf_t *conf);
+int luat_sdl2_deinit(luat_sdl2_conf_t *conf);
+
+void luat_sdl2_draw(size_t x1, size_t y1, size_t x2, size_t y2, uint32_t* data);
+void luat_sdl2_flush(void);
+
+#endif
+