linuxOS_AP06/buildroot/package/lvgl/lv_drivers/0015-sdl-Support-opengl.patch
2025-06-03 12:28:32 +08:00

2177 lines
53 KiB
Diff

From fea41fc576e28608434bc66922f97087518ab458 Mon Sep 17 00:00:00 2001
From: Jiajian Wu <jair.wu@rock-chips.com>
Date: Mon, 27 Nov 2023 14:24:59 +0800
Subject: [PATCH] sdl: Support opengl
Signed-off-by: Jiajian Wu <jair.wu@rock-chips.com>
---
CMakeLists.txt | 7 +
lv_drv_conf.h | 4 +
sdl/gl/gl.c | 1117 +++++++++++++++++++++++++++++++++
sdl/gl/gl.h | 161 +++++
sdl/gl/mat.c | 369 +++++++++++
sdl/gl/mat.h | 23 +
sdl/gl/shaders.c | 106 ++++
sdl/gl/shaders/bgra.frag | 12 +
sdl/gl/shaders/bgra_cube.frag | 10 +
sdl/gl/shaders/common.vert | 54 ++
sdl/gl/shaders/cube.vert | 17 +
sdl/gl/shaders/default.vert | 22 +
sdl/gl/shaders/fold.vert | 21 +
sdl/gl/shaders/rgba.frag | 12 +
sdl/gl/shaders/rgba_cube.frag | 10 +
sdl/sdl_gpu.c | 34 +-
16 files changed, 1978 insertions(+), 1 deletion(-)
create mode 100644 sdl/gl/gl.c
create mode 100644 sdl/gl/gl.h
create mode 100644 sdl/gl/mat.c
create mode 100644 sdl/gl/mat.h
create mode 100644 sdl/gl/shaders.c
create mode 100644 sdl/gl/shaders/bgra.frag
create mode 100644 sdl/gl/shaders/bgra_cube.frag
create mode 100644 sdl/gl/shaders/common.vert
create mode 100644 sdl/gl/shaders/cube.vert
create mode 100644 sdl/gl/shaders/default.vert
create mode 100644 sdl/gl/shaders/fold.vert
create mode 100644 sdl/gl/shaders/rgba.frag
create mode 100644 sdl/gl/shaders/rgba_cube.frag
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 48500e97..14912180 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,13 @@ add_library(lvgl::drivers ALIAS lv_drivers)
if (LV_DRV_USE_SDL_GPU)
add_definitions(-DUSE_SDL_GPU=1)
add_definitions(-DLV_USE_GPU_SDL=1)
+if (LV_DRV_SDL_DIS_FULLSCREEN)
+ add_definitions(-DSDL_DIS_FULLSCREEN)
+endif()
+endif()
+if (LV_DRV_USE_OPENGL)
+ add_definitions(-DUSE_SDL_OPENGL=1)
+ install(DIRECTORY sdl/gl/shaders DESTINATION /usr/share/lv_drivers)
endif()
if (LV_DRV_USE_DRM)
add_definitions(-DUSE_DRM=1)
diff --git a/lv_drv_conf.h b/lv_drv_conf.h
index 345762aa..d6f10ee5 100644
--- a/lv_drv_conf.h
+++ b/lv_drv_conf.h
@@ -94,6 +94,10 @@
# define USE_SDL_GPU 0
#endif
+#ifndef USE_SDL_OPENGL
+# define USE_SDL_OPENGL 0
+#endif
+
#if USE_SDL || USE_SDL_GPU
//# define SDL_HOR_RES 720
//# define SDL_VER_RES 1280
diff --git a/sdl/gl/gl.c b/sdl/gl/gl.c
new file mode 100644
index 00000000..09e68b78
--- /dev/null
+++ b/sdl/gl/gl.c
@@ -0,0 +1,1117 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#if USE_SDL_OPENGL
+#include <lvgl/lvgl.h>
+
+#define SDL_MAIN_HANDLED
+#include <GLES3/gl3.h>
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_egl.h>
+#include <SDL2/SDL_opengl.h>
+#include <SDL2/SDL_opengles2.h>
+
+#include "gl.h"
+
+#define LOGD //printf
+
+#define DATA_PATH "/usr/share/lv_drivers/shaders"
+
+static char *_common = DATA_PATH"/common.vert";
+static char *_vert = DATA_PATH"/default.vert";
+static char *_vert_cube = DATA_PATH"/cube.vert";
+static char *_frag_bgra = DATA_PATH"/bgra.frag";
+static char *_frag_rgba = DATA_PATH"/rgba.frag";
+static char *_frag_bgra_cube = DATA_PATH"/bgra_cube.frag";
+static char *_frag_rgba_cube = DATA_PATH"/rgba_cube.frag";
+
+static const lv_gl_vec_t default_vec[4] = {
+ /* bottom left */
+ {-1.0, -1.0, 0.0},
+ /* bottom right */
+ { 1.0, -1.0, 0.0},
+ /* top left */
+ {-1.0, 1.0, 0.0},
+ /* top right */
+ { 1.0, 1.0, 0.0},
+};
+
+static const GLfloat verts_2d[] = {
+ /* bottom left */
+ -1.0, -1.0, 0.0, 1.0, 0.0, 1.0,
+ /* bottom right */
+ 1.0, -1.0, 0.0, 1.0, 1.0, 1.0,
+ /* top left */
+ -1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
+ /* top right */
+ 1.0, 1.0, 0.0, 1.0, 1.0, 0.0,
+};
+
+static const GLfloat verts_cube[] = {
+ /* Front */
+ -1.0, -1.0, 1.0, 1.0, 0.0, 0.0,
+ 1.0, -1.0, 1.0, 1.0, 1.0, 0.0,
+ -1.0, 1.0, 1.0, 1.0, 0.0, 1.0,
+ -1.0, 1.0, 1.0, 1.0, 0.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, -1.0, 1.0, 1.0, 0.0, 1.0,
+
+ /* Left */
+ -1.0, -1.0, -1.0, 1.0, 0.0, 0.0,
+ -1.0, -1.0, 1.0, 1.0, 1.0, 0.0,
+ -1.0, 1.0, -1.0, 1.0, 0.0, 1.0,
+ -1.0, 1.0, -1.0, 1.0, 0.0, 1.0,
+ -1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+ -1.0, -1.0, 1.0, 1.0, 0.0, 1.0,
+
+ /* Right */
+ 1.0, -1.0, -1.0, 1.0, 0.0, 0.0,
+ 1.0, -1.0, 1.0, 1.0, 1.0, 0.0,
+ 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,
+ 1.0, 1.0, -1.0, 1.0, 1.0, 1.0,
+ 1.0, -1.0, -1.0, 1.0, 0.0, 1.0,
+
+ /* Back */
+ -1.0, 1.0, -1.0, 1.0, 0.0, 0.0,
+ -1.0, -1.0, -1.0, 1.0, 1.0, 0.0,
+ 1.0, -1.0, -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, -1.0, 1.0, 0.0, 1.0,
+ 1.0, 1.0, -1.0, 1.0, 1.0, 1.0,
+ -1.0, 1.0, -1.0, 1.0, 0.0, 1.0,
+
+ /* Top */
+ -1.0, 1.0, 1.0, 1.0, 0.0, 0.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0, 0.0,
+ -1.0, 1.0, -1.0, 1.0, 0.0, 1.0,
+ -1.0, 1.0, -1.0, 1.0, 0.0, 1.0,
+ 1.0, 1.0, -1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,
+
+ /* Bottom */
+ -1.0, -1.0, -1.0, 1.0, 0.0, 0.0,
+ -1.0, -1.0, 1.0, 1.0, 1.0, 0.0,
+ 1.0, -1.0, -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 1.0, 1.0, 1.0, 1.0,
+ -1.0, -1.0, 1.0, 1.0, 0.0, 1.0,
+};
+
+enum {
+ VERTEX_DEFAULT,
+ VERTEX_CUBE,
+};
+
+enum {
+ IMAGESOURCE_RGBA,
+ IMAGESOURCE_BGRA,
+};
+
+typedef struct {
+ GLuint program;
+ GLuint vert;
+ GLuint frag;
+ GLuint VAO;
+ GLuint VBO;
+} lv_gl_prog_t;
+
+typedef struct {
+ lv_gl_base_t base;
+ lv_gl_base_t * fb;
+ int inited;
+ int clear_depth;
+ lv_gl_prog_t * cur_prog;
+ lv_gl_prog_t * progs[6];
+ SDL_Window * window;
+ SDL_GLContext context;
+} lv_gl_ctx_t;
+
+static lv_gl_ctx_t gl_ctx = {
+ .inited = 0,
+};
+
+static GLuint gl_pos = 0;
+static GLuint gl_tex = 1;
+
+static void reset_crop(lv_gl_base_t *base);
+static void reset_viewport(lv_gl_base_t *base);
+static void update_crop_viewport(lv_gl_base_t *base);
+
+static lv_gl_render_cb_t user_cb = NULL;
+
+void lv_gl_set_render_cb(lv_gl_render_cb_t cb)
+{
+ user_cb = cb;
+}
+
+static inline lv_gl_tex_t *tex_ref(lv_gl_tex_t *tex)
+{
+ tex->ref_cnt++;
+
+ return tex;
+}
+
+static inline lv_gl_tex_t *tex_unref(lv_gl_tex_t *tex)
+{
+ if ((--tex->ref_cnt) > 0)
+ return tex;
+
+ lv_gl_tex_del(tex);
+
+ return NULL;
+}
+
+static SDL_GLContext enter_critical(void)
+{
+ SDL_GLContext ctx;
+
+ ctx = SDL_GL_GetCurrentContext();
+ if (ctx != gl_ctx.context)
+ SDL_GL_MakeCurrent(gl_ctx.window, gl_ctx.context);
+}
+
+static void exit_critical(SDL_GLContext ctx)
+{
+ if (ctx != gl_ctx.context)
+ SDL_GL_MakeCurrent(gl_ctx.window, ctx);
+}
+
+static GLuint create_shader(const char *source_path, GLenum shader_type)
+{
+ GLuint shader;
+ GLint status;
+ FILE *fd;
+ FILE *fd_common;
+ int size;
+ int size_common = 0;
+ char *source;
+
+ fd = fopen(source_path, "rb");
+ fseek(fd, 0, SEEK_END);
+ size = ftell(fd);
+ fseek(fd, 0, SEEK_SET);
+
+ if (shader_type == GL_VERTEX_SHADER)
+ {
+ fd_common = fopen(_common, "rb");
+ fseek(fd_common, 0, SEEK_END);
+ size_common = ftell(fd_common);
+ fseek(fd_common, 0, SEEK_SET);
+ }
+
+ source = malloc(size + size_common + 1);
+ memset(source, 0x0, size + size_common + 1);
+ if (shader_type == GL_VERTEX_SHADER)
+ {
+ fread(source, 1, size_common, fd_common);
+ fclose(fd_common);
+ }
+ fread(source + size_common, 1, size, fd);
+ fclose(fd);
+
+ shader = glCreateShader(shader_type);
+ if (!shader)
+ exit(1);
+
+ glShaderSource(shader, 1, (const char **) &source, NULL);
+ glCompileShader(shader);
+
+ free(source);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (!status) {
+ char log[1000];
+ GLsizei len;
+ glGetShaderInfoLog(shader, 1000, &len, log);
+ fprintf(stderr, "Error: compiling %s: %.*s\n",
+ shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
+ len, log);
+ exit(1);
+ }
+
+ return shader;
+}
+
+static lv_gl_prog_t * create_program(int vert_type, int frag_type)
+{
+ lv_gl_prog_t * prog;
+ const char *vert_text;
+ const char *frag_text;
+ GLuint program;
+ GLuint vert;
+ GLuint frag;
+ GLint status;
+
+ switch (vert_type)
+ {
+ case VERTEX_DEFAULT:
+ vert_text = _vert;
+ break;
+ default:
+ printf("Invalid vert type\n");
+ break;
+ }
+ switch(frag_type)
+ {
+ case IMAGESOURCE_BGRA:
+ frag_text = _frag_bgra;
+ break;
+ case IMAGESOURCE_RGBA:
+ frag_text = _frag_rgba;
+ break;
+ default:
+ printf("Invalid frag type\n");
+ break;
+ }
+
+ prog = malloc(sizeof(lv_gl_prog_t));
+
+ frag = create_shader(frag_text, GL_FRAGMENT_SHADER);
+ vert = create_shader(vert_text, GL_VERTEX_SHADER);
+
+ program = glCreateProgram();
+ glAttachShader(program, frag);
+ glAttachShader(program, vert);
+ glLinkProgram(program);
+
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (!status) {
+ char log[1000];
+ GLsizei len;
+ glGetProgramInfoLog(program, 1000, &len, log);
+ fprintf(stderr, "Error: linking:\n%.*s\n", len, log);
+ exit(1);
+ }
+ glUseProgram(program);
+
+ glBindAttribLocation(program, gl_pos, "pos");
+ glBindAttribLocation(program, gl_tex, "tex");
+ glLinkProgram(program);
+
+ glGenVertexArrays(1, &prog->VAO);
+ glGenBuffers(1, &prog->VBO);
+ glBindVertexArray(prog->VAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, prog->VBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(verts_2d),
+ &verts_2d, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(gl_pos);
+ glVertexAttribPointer(gl_pos, 4, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
+ glEnableVertexAttribArray(gl_tex);
+ glVertexAttribPointer(gl_tex, 2, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat),
+ (GLvoid *)(4 * sizeof(GLfloat)));
+
+ glBindVertexArray(0);
+
+ prog->program = program;
+ prog->frag = frag;
+ prog->vert = vert;
+
+ return prog;
+}
+
+static lv_gl_prog_t * create_cube_program(int type)
+{
+ lv_gl_prog_t * prog;
+ const char *vert_text;
+ const char *frag_text;
+ GLuint program;
+ GLuint vert;
+ GLuint frag;
+ GLint status;
+
+ switch(type)
+ {
+ case IMAGESOURCE_BGRA:
+ vert_text = _vert_cube;
+ frag_text = _frag_bgra_cube;
+ break;
+ case IMAGESOURCE_RGBA:
+ vert_text = _vert_cube;
+ frag_text = _frag_rgba_cube;
+ break;
+ }
+
+ prog = malloc(sizeof(lv_gl_prog_t));
+
+ frag = create_shader(frag_text, GL_FRAGMENT_SHADER);
+ vert = create_shader(vert_text, GL_VERTEX_SHADER);
+
+ program = glCreateProgram();
+ glAttachShader(program, frag);
+ glAttachShader(program, vert);
+ glLinkProgram(program);
+
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (!status) {
+ char log[1000];
+ GLsizei len;
+ glGetProgramInfoLog(program, 1000, &len, log);
+ fprintf(stderr, "Error: linking:\n%.*s\n", len, log);
+ exit(1);
+ }
+ glUseProgram(program);
+
+ glBindAttribLocation(program, gl_pos, "pos");
+ glLinkProgram(program);
+
+ glGenVertexArrays(1, &prog->VAO);
+ glGenBuffers(1, &prog->VBO);
+ glBindVertexArray(prog->VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, prog->VBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(verts_cube),
+ &verts_cube, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(gl_pos);
+ glVertexAttribPointer(gl_pos, 4, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
+ glBindVertexArray(0);
+
+ prog->program = program;
+ prog->frag = frag;
+ prog->vert = vert;
+
+ return prog;
+}
+
+int lv_gl_ctx_init(void)
+{
+ printf("%s\n", glGetString(GL_RENDERER));
+ printf("%s\n", glGetString(GL_VENDOR));
+ printf("%s\n", glGetString(GL_VERSION));
+ printf("%s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
+
+ memset(&gl_ctx, 0x0, sizeof(gl_ctx));
+
+ gl_ctx.progs[GL_TEX_TYPE_2D * 2 + 0] =
+ create_program(VERTEX_DEFAULT, IMAGESOURCE_RGBA);
+ gl_ctx.progs[GL_TEX_TYPE_2D * 2 + 1] =
+ create_program(VERTEX_DEFAULT, IMAGESOURCE_BGRA);
+ gl_ctx.progs[GL_TEX_TYPE_CUBE * 2 + 0] =
+ create_cube_program(IMAGESOURCE_RGBA);
+ gl_ctx.progs[GL_TEX_TYPE_CUBE * 2 + 1] =
+ create_cube_program(IMAGESOURCE_BGRA);
+
+ gl_ctx.window = SDL_GL_GetCurrentWindow();
+ gl_ctx.context = SDL_GL_GetCurrentContext();
+ SDL_GetWindowSize(gl_ctx.window, &gl_ctx.base.w,
+ &gl_ctx.base.h);
+
+ gl_ctx.base.reverse_y = 1;
+ reset_viewport(&gl_ctx.base);
+ reset_crop(&gl_ctx.base);
+
+ gl_ctx.fb = &gl_ctx.base;
+ gl_ctx.inited = 1;
+}
+
+void lv_gl_set_fb(lv_gl_obj_t *obj)
+{
+ lv_gl_base_t *fb;
+
+ if (obj)
+ fb = &obj->base;
+ else
+ fb = &gl_ctx.base;
+
+ if (gl_ctx.fb == fb)
+ return;
+
+ gl_ctx.fb = fb;
+ gl_ctx.clear_depth = 1;
+}
+
+void lv_gl_read_pixels(void *ptr, SDL_Rect *r, int type)
+{
+ SDL_GLContext previousContext;
+ GLenum status;
+ lv_gl_base_t *fb;
+
+ previousContext = enter_critical();
+ fb = gl_ctx.fb;
+ if (fb->tex == NULL)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+ else
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->tex->FBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ type ? type : GL_TEXTURE_2D, fb->tex->gl_tex, 0);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ printf("bind framebuffer error\n");
+ return;
+ }
+ }
+
+ glReadPixels(r->x, r->y, r->w, r->h, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
+
+ exit_critical(previousContext);
+}
+
+lv_gl_tex_t *lv_gl_tex_create(int type, int w, int h, lv_gl_img_t *img)
+{
+ SDL_GLContext previousContext;
+ lv_gl_tex_t *new;
+ int count = 1;
+
+ if (!gl_ctx.inited) {
+ printf("call lv_gl_ctx_init first\n");
+ return NULL;
+ }
+
+ previousContext = enter_critical();
+
+ new = lv_mem_alloc(sizeof(*new));
+ memset(new, 0, sizeof(*new));
+ new->type = type;
+ glGenFramebuffers(1, &new->FBO);
+ glGenTextures(1, &new->gl_tex);
+
+ if (type == GL_TEX_TYPE_2D)
+ {
+ glBindTexture(GL_TEXTURE_2D, new->gl_tex);
+ if (img && img->pixels)
+ {
+ new->size[0].w = img->w;
+ new->size[0].h = img->h;
+ new->format = img->format;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->w, img->h,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, img->pixels);
+ }
+ else
+ {
+ new->size[0].w = w;
+ new->size[0].h = h;
+ new->format = LV_GL_FMT_BGRA;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ if (type == GL_TEX_TYPE_CUBE)
+ {
+ glBindTexture(GL_TEXTURE_CUBE_MAP, new->gl_tex);
+ for (int i = CUBE_LEFT; i <= CUBE_BACK; i++)
+ {
+ if (img && img[i].pixels)
+ {
+ new->size[0].w = img[i].w;
+ new->size[0].h = img[i].h;
+ new->format = img->format;
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
+ 0, GL_RGBA, img[i].w, img[i].h,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, img[i].pixels);
+ }
+ else
+ {
+ new->size[0].w = w;
+ new->size[0].h = h;
+ new->format = LV_GL_FMT_RGBA;
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
+ 0, GL_RGBA, w, h,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ }
+ glTexParameteri(GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ }
+
+ exit_critical(previousContext);
+
+ return new;
+}
+
+void lv_gl_tex_del(lv_gl_tex_t *tex)
+{
+ SDL_GLContext previousContext;
+
+ previousContext = enter_critical();
+
+ glDeleteFramebuffers(1, &tex->FBO);
+ glDeleteTextures(1, &tex->gl_tex);
+ lv_mem_free(tex);
+
+ exit_critical(previousContext);
+}
+
+static void import_img_cube(lv_gl_tex_t *tex,
+ lv_gl_img_t *img)
+{
+ SDL_GLContext previousContext;
+
+ previousContext = enter_critical();
+
+ glBindTexture(GL_TEXTURE_CUBE_MAP, tex->gl_tex);
+ for (int i = CUBE_LEFT; i <= CUBE_BACK; i++)
+ {
+ if (!img[i].pixels)
+ continue;
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
+ 0, GL_RGBA, img[i].w, img[i].h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ img[i].pixels);
+ }
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ tex->format = img->format;
+
+ exit_critical(previousContext);
+}
+
+static void import_img_2d(lv_gl_tex_t *tex, lv_gl_img_t *img)
+{
+ SDL_GLContext previousContext;
+
+ previousContext = enter_critical();
+
+ glBindTexture(GL_TEXTURE_2D, tex->gl_tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+ img->w, img->h, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, img->pixels);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ tex->format = img->format;
+
+ exit_critical(previousContext);
+}
+
+void lv_gl_tex_import_img(lv_gl_tex_t *tex, lv_gl_img_t *img)
+{
+ switch (tex->type)
+ {
+ case GL_TEX_TYPE_2D:
+ import_img_2d(tex, img);
+ break;
+ case GL_TEX_TYPE_CUBE:
+ import_img_cube(tex, img);
+ break;
+ }
+}
+
+void lv_gl_tex_clear(lv_gl_tex_t *tex, float r, float g, float b, float a)
+{
+ SDL_GLContext previousContext;
+ GLenum status;
+
+ previousContext = enter_critical();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, tex->FBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex->gl_tex, 0);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ printf("bind framebuffer error\n");
+ exit_critical(previousContext);
+ return;
+ }
+
+ glClearColor(r, g, b, a);
+ glClear(GL_COLOR_BUFFER_BIT);
+ exit_critical(previousContext);
+}
+
+lv_gl_obj_t *lv_gl_obj_create(int w, int h)
+{
+ lv_gl_obj_t *new;
+
+ new = lv_mem_alloc(sizeof(*new));
+ if (!new)
+ return NULL;
+ memset(new, 0, sizeof(*new));
+ new->base.w = w;
+ new->base.h = h;
+ new->alpha = 1.0;
+ new->scale.x = 1.0;
+ new->scale.y = 1.0;
+ new->scale.z = 1.0;
+ new->tp.w = w;
+ new->tp.h = h;
+ reset_crop(&new->base);
+ reset_viewport(&new->base);
+ lv_gl_obj_reset_points(new);
+
+ return new;
+}
+
+void lv_gl_obj_del(lv_gl_obj_t *obj)
+{
+ lv_gl_tex_t *tex;
+
+ tex = obj->base.tex;
+ if (tex)
+ tex_unref(tex);
+ lv_mem_free(obj);
+}
+
+void lv_gl_obj_resize(lv_gl_obj_t *obj, lv_gl_obj_t *parent)
+{
+ SDL_Rect r;
+
+ lv_gl_obj_get_viewport(parent, &r);
+
+ obj->scale.x = (float)obj->base.w / r.w;
+ obj->scale.y = (float)obj->base.h / r.h;
+ obj->scale.z = 1.0;
+}
+
+void lv_gl_obj_move(lv_gl_obj_t *obj, lv_gl_obj_t *parent)
+{
+ SDL_Rect r;
+
+ lv_gl_obj_get_viewport(parent, &r);
+
+ obj->move.x = obj->scale.x + ((float)obj->base.r.x / r.w * 2.0 - 1.0);
+ obj->move.y = obj->scale.y + ((float)obj->base.r.y / r.h * 2.0 - 1.0);
+}
+
+void lv_gl_obj_bind_tex(lv_gl_obj_t *obj, lv_gl_tex_t *tex)
+{
+ if (obj->base.tex)
+ tex_unref(obj->base.tex);
+
+ obj->base.tex = tex_ref(tex);
+ lv_gl_obj_reset_tex_points(obj);
+}
+
+void lv_gl_obj_update_vao(lv_gl_obj_t *obj)
+{
+ SDL_GLContext previousContext;
+ SDL_Rect *r;
+ lv_gl_tex_t *tex;
+ lv_gl_base_t *fb = gl_ctx.fb;
+ GLuint swap;
+ int format;
+ GLfloat x1, x2, y1, y2;
+ GLfloat verts[] = {
+ -1.0, -1.0, 0.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0, 1.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
+ 1.0, 1.0, 0.0, 1.0, 1.0, 0.0,
+ };
+
+ if (!obj || !obj->base.tex)
+ return;
+ tex = obj->base.tex;
+
+ previousContext = enter_critical();
+
+ if (fb->tex == NULL)
+ format = LV_GL_FMT_RGBA;
+ else
+ format = fb->tex->format;
+
+ if (!obj->VAO)
+ {
+ glGenVertexArrays(1, &obj->VAO);
+ glGenBuffers(1, &obj->VBO);
+ }
+
+ r = &obj->tp;
+ x1 = (float)r->x / lv_gl_tex_get_w(tex, 0);
+ x2 = (float)(r->x + r->w) / lv_gl_tex_get_w(tex, 0);
+ y1 = (float)r->y / lv_gl_tex_get_h(tex, 0);
+ y2 = (float)(r->y + r->h) / lv_gl_tex_get_h(tex, 0);
+
+ verts[6 * 0 + 4] = x1;
+ verts[6 * 0 + 5] = y2;
+ verts[6 * 1 + 4] = x2;
+ verts[6 * 1 + 5] = y2;
+ verts[6 * 2 + 4] = x1;
+ verts[6 * 2 + 5] = y1;
+ verts[6 * 3 + 4] = x2;
+ verts[6 * 3 + 5] = y1;
+
+ memcpy(&verts[0], &obj->p[0], sizeof(lv_gl_vec_t));
+ memcpy(&verts[6], &obj->p[1], sizeof(lv_gl_vec_t));
+ memcpy(&verts[12], &obj->p[2], sizeof(lv_gl_vec_t));
+ memcpy(&verts[18], &obj->p[3], sizeof(lv_gl_vec_t));
+
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < 6; j++)
+ {
+ LOGD("%f ", verts[i * 6 + j]);
+ }
+ LOGD("\n");
+ }
+ LOGD("\n");
+
+ swap = (obj->base.tex->format != format);
+ glUseProgram(gl_ctx.progs[tex->type * 2 + swap]->program);
+ glBindVertexArray(obj->VAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, obj->VBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(gl_pos);
+ glVertexAttribPointer(gl_pos, 4, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
+ glEnableVertexAttribArray(gl_tex);
+ glVertexAttribPointer(gl_tex, 2, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat),
+ (GLvoid *)(4 * sizeof(GLfloat)));
+
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ exit_critical(previousContext);
+}
+
+void lv_gl_obj_release_vao(lv_gl_obj_t *obj)
+{
+ SDL_GLContext previousContext;
+
+ if (!obj || !obj->VAO)
+ return;
+
+ previousContext = enter_critical();
+
+ glDeleteVertexArrays(1, &obj->VAO);
+ glDeleteBuffers(1, &obj->VBO);
+ obj->VAO = 0;
+ obj->VBO = 0;
+
+ exit_critical(previousContext);
+}
+
+void lv_gl_obj_reset_points(lv_gl_obj_t *obj)
+{
+ memcpy(obj->p, default_vec, sizeof(default_vec));
+}
+
+void lv_gl_obj_reset_tex_points(lv_gl_obj_t *obj)
+{
+ int w, h;
+
+ if (!obj->base.tex)
+ return;
+
+ w = lv_gl_tex_get_w(obj->base.tex, 0);
+ h = lv_gl_tex_get_h(obj->base.tex, 0);
+
+ obj->tp.x = 0;
+ obj->tp.y = 0;
+ obj->tp.w = w;
+ obj->tp.h = h;
+}
+
+#define load_1f(x, f0) \
+ do { \
+ LOGD(#x" "#f0"=%f\n", f0); \
+ uniform = \
+ glGetUniformLocation(program, #x); \
+ glUniform1f(uniform, f0); \
+ } while (0);
+#define load_vec3(x, f0, f1, f2) \
+ do { \
+ LOGD(#x" "#f0"=%f "#f1"=%f "#f2"=%f\n", f0, f1, f2); \
+ uniform = \
+ glGetUniformLocation(program, #x); \
+ glUniform3f(uniform, f0, f1, f2); \
+ } while (0);
+
+static void render_cube(lv_gl_obj_t *obj, GLuint program)
+{
+ lv_gl_tex_t *tex;
+ GLuint uniform;
+
+ tex = obj->base.tex;
+
+ load_vec3(scale, obj->scale.x, obj->scale.y, obj->scale.z);
+ load_vec3(rot, obj->self_rot.x, obj->self_rot.y, obj->self_rot.z);
+ load_vec3(vrot, obj->view_rot.x, obj->view_rot.y, obj->view_rot.z);
+ load_vec3(move, obj->move.x, obj->move.y, obj->move.z);
+
+ glBindTexture(GL_TEXTURE_CUBE_MAP, tex->gl_tex);
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+}
+
+static void render_2d(lv_gl_obj_t *obj, GLuint program)
+{
+ lv_gl_tex_t *tex;
+ GLuint uniform;
+
+ tex = obj->base.tex;
+
+ load_1f(alpha, obj->alpha);
+ load_vec3(offset, obj->offset.x, obj->offset.y, obj->offset.z);
+ load_vec3(scale, obj->scale.x, obj->scale.y, obj->scale.z);
+ load_vec3(rot, obj->self_rot.x, obj->self_rot.y, obj->self_rot.z);
+ load_vec3(vrot, obj->view_rot.x, obj->view_rot.y, obj->view_rot.z);
+ load_vec3(move, obj->move.x, obj->move.y, obj->move.z);
+
+ glBindTexture(GL_TEXTURE_2D, tex->gl_tex);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glBindVertexArray(0);
+}
+#undef load_vec3
+#undef load_1f
+
+static void reset_crop(lv_gl_base_t *base)
+{
+ base->crop.x = 0;
+ base->crop.y = 0;
+ base->crop.w = base->w;
+ base->crop.h = base->h;
+ base->crop_dirty = 1;
+}
+
+static void reset_viewport(lv_gl_base_t *base)
+{
+ base->view.x = 0;
+ base->view.y = 0;
+ base->view.w = base->w;
+ base->view.h = base->h;
+ base->view_dirty = 1;
+}
+
+static void update_crop_viewport(lv_gl_base_t *base)
+{
+ if (1 || base->crop_dirty)
+ {
+ if (base->crop_en)
+ {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(base->crop.x, base->crop.y,
+ base->crop.w, base->crop.h);
+ }
+ else
+ {
+ glDisable(GL_SCISSOR_TEST);
+ }
+ base->crop_dirty = 0;
+ }
+
+ if (1 || base->view_dirty)
+ {
+ LOGD("%s %d %d %d %d\n", __func__, base->view.x, base->view.y,
+ base->view.w, base->view.h);
+ glViewport(base->view.x, base->view.y,
+ base->view.w, base->view.h);
+ base->view_dirty = 0;
+ }
+}
+
+static void render(lv_gl_obj_t *obj)
+{
+ lv_gl_tex_t *tex;
+ lv_gl_base_t *fb;
+ lv_gl_prog_t *prog;
+ GLuint swap;
+ GLenum status;
+ int format;
+
+ if (!obj || !obj->base.tex)
+ return;
+ tex = obj->base.tex;
+
+ fb = gl_ctx.fb;
+ if (fb->tex == NULL)
+ {
+ format = LV_GL_FMT_RGBA;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+ else
+ {
+ format = fb->tex->format;
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->tex->FBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ obj->out_type ? obj->out_type : GL_TEXTURE_2D,
+ fb->tex->gl_tex, 0);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ printf("bind framebuffer error\n");
+ return;
+ }
+ }
+ update_crop_viewport(fb);
+
+ swap = (obj->base.tex->format != format);
+ prog = gl_ctx.progs[tex->type * 2 + swap];
+
+ glUseProgram(prog->program);
+
+ if (obj->VAO)
+ {
+ LOGD("Use obj->VAO\n");
+ glBindVertexArray(obj->VAO);
+ }
+ else
+ {
+ LOGD("Use prog->VAO\n");
+ glBindVertexArray(prog->VAO);
+ }
+
+ if (gl_ctx.clear_depth)
+ {
+ glEnable(GL_DEPTH_TEST);
+ glClearDepthf(0.0);
+ glDepthFunc(GL_GREATER);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ gl_ctx.clear_depth = 0;
+ }
+
+ if (tex->type == GL_TEX_TYPE_2D)
+ render_2d(obj, prog->program);
+ else
+ render_cube(obj, prog->program);
+
+ glBindVertexArray(0);
+}
+
+void lv_gl_obj_render(lv_gl_obj_t *obj)
+{
+ SDL_GLContext previousContext;
+ previousContext = enter_critical();
+ render(obj);
+ exit_critical(previousContext);
+}
+
+void lv_gl_obj_set_viewport(lv_gl_obj_t *obj, SDL_Rect *r)
+{
+ lv_gl_base_t *base;
+
+ if (!obj)
+ {
+ if (!gl_ctx.inited) {
+ printf("call lv_gl_ctx_init first\n");
+ return;
+ }
+ base = &gl_ctx.base;
+ }
+ else
+ {
+ base = &obj->base;
+ }
+
+ if (r)
+ {
+ base->view.x = r->x;
+ base->view.y = r->y;
+ base->view.w = r->w;
+ base->view.h = r->h;
+ }
+ else
+ {
+ reset_viewport(base);
+ }
+ base->view_dirty = 1;
+}
+
+void lv_gl_obj_get_viewport(lv_gl_obj_t *obj, SDL_Rect *r)
+{
+ lv_gl_base_t *base;
+
+ if (!obj)
+ {
+ if (!gl_ctx.inited) {
+ printf("call lv_gl_ctx_init first\n");
+ return;
+ }
+ base = &gl_ctx.base;
+ }
+ else
+ {
+ base = &obj->base;
+ }
+
+ if (r)
+ {
+ r->x = base->view.x;
+ r->y = base->view.y;
+ r->w = base->view.w;
+ r->h = base->view.h;
+ }
+}
+
+void lv_gl_obj_set_crop(lv_gl_obj_t *obj, SDL_Rect *r, int en)
+{
+ lv_gl_base_t *base;
+
+ if (!obj)
+ {
+ if (!gl_ctx.inited) {
+ printf("call lv_gl_ctx_init first\n");
+ return;
+ }
+ base = &gl_ctx.base;
+ }
+ else
+ {
+ base = &obj->base;
+ }
+
+ if (r)
+ {
+ base->crop.x = r->x;
+ base->crop.y = r->y;
+ base->crop.w = r->w;
+ base->crop.h = r->h;
+ }
+ else
+ {
+ reset_crop(base);
+ }
+ base->crop_en = en;
+ base->crop_dirty = 1;
+}
+
+void lv_gl_obj_get_crop(lv_gl_obj_t *obj, SDL_Rect *r)
+{
+ lv_gl_base_t *base;
+
+ if (!obj)
+ {
+ if (!gl_ctx.inited) {
+ printf("call lv_gl_ctx_init first\n");
+ return;
+ }
+ base = &gl_ctx.base;
+ }
+ else
+ {
+ base = &obj->base;
+ }
+
+ if (r)
+ {
+ r->x = base->crop.x;
+ r->y = base->crop.y;
+ r->w = base->crop.w;
+ r->h = base->crop.h;
+ }
+}
+
+void lv_gl_render(void)
+{
+ glEnable(GL_MULTISAMPLE);
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+ GL_ZERO, GL_ONE);
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
+
+ gl_ctx.clear_depth = 1;
+ if (user_cb)
+ user_cb();
+ glFinish();
+}
+#endif
+
diff --git a/sdl/gl/gl.h b/sdl/gl/gl.h
new file mode 100644
index 00000000..6f054e37
--- /dev/null
+++ b/sdl/gl/gl.h
@@ -0,0 +1,161 @@
+#ifndef __GL_H__
+#define __GL_H__
+
+#include <lvgl/lvgl.h>
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_opengl.h>
+#include <SDL2/SDL_opengles2.h>
+
+enum {
+ LV_GL_FMT_ALPHA,
+ LV_GL_FMT_LUMINANCE,
+ LV_GL_FMT_LUMINANCE_ALPHA,
+ LV_GL_FMT_INTENSITY,
+ LV_GL_FMT_RGB,
+ LV_GL_FMT_RGBA,
+ LV_GL_FMT_BGRA,
+};
+
+enum {
+ GL_TEX_TYPE_2D,
+ GL_TEX_TYPE_CUBE,
+};
+
+enum {
+ CUBE_LEFT,
+ CUBE_RIGHT,
+ CUBE_TOP,
+ CUBE_BOTTOM,
+ CUBE_FRONT,
+ CUBE_BACK,
+};
+
+typedef void (*lv_gl_render_cb_t)(void);
+
+typedef struct {
+ const void *pixels;
+ int format;
+ int w;
+ int h;
+} lv_gl_img_t;
+
+typedef struct {
+ int w;
+ int h;
+} lv_gl_size_t;
+
+typedef struct {
+ GLuint gl_tex;
+ GLuint FBO;
+ lv_gl_size_t size[6];
+ int format;
+ int type;
+ int ref_cnt;
+} lv_gl_tex_t;
+
+typedef struct {
+ float x, y, z;
+} lv_gl_vec_t;
+
+typedef struct {
+ int w;
+ int h;
+ int reverse_y;
+ lv_gl_tex_t *tex;
+ SDL_Rect r;
+ SDL_Rect view;
+ SDL_Rect crop;
+ int view_dirty;
+ int crop_dirty;
+ int crop_en;
+} lv_gl_base_t;
+
+typedef struct {
+ lv_gl_base_t base;
+ GLuint VAO;
+ GLuint VBO;
+ int out_type;
+ lv_gl_vec_t p[4];
+ SDL_Rect tp;
+
+ float alpha;
+ lv_gl_vec_t scale;
+ lv_gl_vec_t offset;
+ lv_gl_vec_t self_rot;
+ lv_gl_vec_t view_rot;
+ lv_gl_vec_t move;
+ int steps;
+ int pos;
+} lv_gl_obj_t;
+
+static inline int lv_gl_tex_get_w(lv_gl_tex_t *tex, int index)
+{
+ if (tex->type == GL_TEX_TYPE_2D)
+ return tex->size[0].w;
+
+ if (index > CUBE_BACK || index < 0)
+ return 0;
+
+ return tex->size[index].w;
+}
+
+static inline int lv_gl_tex_get_h(lv_gl_tex_t *tex, int index)
+{
+ if (tex->type == GL_TEX_TYPE_2D)
+ return tex->size[0].w;
+
+ if (index > CUBE_BACK || index < 0)
+ return 0;
+
+ return tex->size[index].w;
+}
+
+static inline void lv_gl_obj_set_angle(lv_gl_obj_t *obj,
+ float x, float y, float z)
+{
+ obj->self_rot.x = x;
+ obj->self_rot.y = y;
+ obj->self_rot.z = z;
+}
+
+static inline void lv_gl_obj_set_view_angle(lv_gl_obj_t *obj,
+ float x, float y, float z)
+{
+ obj->view_rot.x = x;
+ obj->view_rot.y = y;
+ obj->view_rot.z = z;
+}
+
+/* Called by sdl_gpu.c */
+int lv_gl_ctx_init(void);
+void lv_gl_render(void);
+
+/* Called by application */
+void lv_gl_set_render_cb(lv_gl_render_cb_t cb);
+void lv_gl_set_fb(lv_gl_obj_t *obj);
+void lv_gl_read_pixels(void *ptr, SDL_Rect *r, int type);
+
+lv_gl_tex_t *lv_gl_tex_create(int type, int w, int h, lv_gl_img_t *img);
+void lv_gl_tex_del(lv_gl_tex_t *tex);
+void lv_gl_tex_import_img(lv_gl_tex_t *tex, lv_gl_img_t *img);
+void lv_gl_tex_clear(lv_gl_tex_t *tex, float r, float g, float b, float a);
+
+lv_gl_obj_t *lv_gl_obj_create(int w, int h);
+void lv_gl_obj_del(lv_gl_obj_t *obj);
+void lv_gl_obj_resize(lv_gl_obj_t *obj, lv_gl_obj_t *parent);
+void lv_gl_obj_move(lv_gl_obj_t *obj, lv_gl_obj_t *parent);
+void lv_gl_obj_reset_points(lv_gl_obj_t *obj);
+void lv_gl_obj_reset_tex_points(lv_gl_obj_t *obj);
+void lv_gl_obj_update_vao(lv_gl_obj_t *obj);
+void lv_gl_obj_release_vao(lv_gl_obj_t *obj);
+void lv_gl_obj_bind_tex(lv_gl_obj_t *obj, lv_gl_tex_t *tex);
+void lv_gl_obj_set_crop(lv_gl_obj_t *obj, SDL_Rect *r, int en);
+void lv_gl_obj_get_crop(lv_gl_obj_t *obj, SDL_Rect *r);
+void lv_gl_obj_set_viewport(lv_gl_obj_t *obj, SDL_Rect *r);
+void lv_gl_obj_get_viewport(lv_gl_obj_t *obj, SDL_Rect *r);
+
+/* Must called in render cb */
+void lv_gl_obj_render(lv_gl_obj_t *obj);
+
+#endif
+
diff --git a/sdl/gl/mat.c b/sdl/gl/mat.c
new file mode 100644
index 00000000..97282588
--- /dev/null
+++ b/sdl/gl/mat.c
@@ -0,0 +1,369 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "mat.h"
+
+#define PI 3.14159265358979f
+
+#define radToDeg(x) ((x) * 180.f / PI)
+#define degToRad(x) ((x) * PI / 180.f)
+
+void mat_multiply_to(float *c, float *a, float *b)
+{
+ float x, y, z, w;
+ for (int i = 0; i < 4; i++)
+ {
+ x = a[0];
+ y = a[1];
+ z = a[2];
+ w = a[3];
+ c[0] = x * b[0] + y * b[1] + z * b[2] + w * b[3];
+ c[1] = x * b[4] + y * b[5] + z * b[6] + w * b[7];
+ c[2] = x * b[8] + y * b[9] + z * b[10] + w * b[11];
+ c[3] = x * b[12] + y * b[13] + z * b[14] + w * b[15];
+ c += 4;
+ a += 4;
+ }
+}
+
+void mat_multiply(float *dst, float *src)
+{
+ float x, y, z, w;
+ for (int i = 0; i < 4; i++)
+ {
+ x = dst[0];
+ y = dst[1];
+ z = dst[2];
+ w = dst[3];
+ dst[0] = x * src[0] + y * src[1]
+ + z * src[2] + w * src[3];
+ dst[1] = x * src[4] + y * src[5]
+ + z * src[6] + w * src[7];
+ dst[2] = x * src[8] + y * src[9]
+ + z * src[10] + w * src[11];
+ dst[3] = x * src[12] + y * src[13]
+ + z * src[14] + w * src[15];
+ dst += 4;
+ }
+}
+
+void move_xyz(float *m, float x, float y, float z)
+{
+ m[0] = 1.0f;
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = x;
+
+ m[4] = 0.0f;
+ m[5] = 1.0f;
+ m[6] = 0.0f;
+ m[7] = y;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = 1.0f;
+ m[11] = z;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+void scale_xyz(float *m, float x, float y, float z)
+{
+ m[0] = x;
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = y;
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = z;
+ m[11] = 0.0f;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+void rotate(float *m, float x, float y, float z)
+{
+ float rad;
+ float sinx, cosx;
+ float siny, cosy;
+ float sinz, cosz;
+
+ rad = degToRad(x);
+ sinx = sin(x);
+ cosx = cos(x);
+ rad = degToRad(y);
+ siny = sin(y);
+ cosy = cos(y);
+ rad = degToRad(z);
+ sinz = sin(z);
+ cosz = cos(z);
+
+ m[0] = cosz * cosy;
+ m[1] = -sinz * cosy;
+ m[2] = -siny;
+ m[3] = 0.0f;
+
+ m[4] = sinz * cosx - cosz * siny * sinx;
+ m[5] = cosz * cosy + sinz * siny * sinx;
+ m[6] = -sinx * cosy;
+ m[7] = 0.0f;
+
+ m[8] = cosz * siny * cosx + sinz * sinx;
+ m[9] = cosz * sinx - sinz * siny * cosx;
+ m[10] = cosy * cosx;
+ m[11] = 0.0f;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+void rotate_x(float *m, float degree)
+{
+ float rad = degToRad(degree);
+
+ m[0] = 1.0f;
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = cos(rad);
+ m[6] = -sin(rad);
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = sin(rad);
+ m[10] = cos(rad);
+ m[11] = 0.0f;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+void rotate_y(float *m, float degree)
+{
+ float rad = degToRad(degree);
+
+ m[0] = cos(rad);
+ m[1] = 0.0f;
+ m[2] = -sin(rad);
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = 1.0f;
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = sin(rad);
+ m[9] = 0.0f;
+ m[10] = cos(rad);
+ m[11] = 0.0f;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+void rotate_z(float *m, float degree)
+{
+ float rad = degToRad(degree);
+
+ m[0] = cos(rad);
+ m[1] = -sin(rad);
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = sin(rad);
+ m[5] = cos(rad);
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = 1.0f;
+ m[11] = 0.0f;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+void frustumM(float *m,
+ int w, int h,
+ int near, int far)
+{
+ float r_width = 1.0f / w;
+ float r_height = 1.0f / h;
+ float r_depth = 1.0f / (near - far);
+ float x = 2.0f * (near * r_width);
+ float y = 2.0f * (near * r_height);
+ float A = w * r_width;
+ float B = h * r_height;
+ float C = (far + near) * r_depth;
+ float D = 2.0f * (far * near * r_depth);
+ m[0] = x;
+ m[5] = y;
+ m[8] = A;
+ m[ 9] = B;
+ m[10] = C;
+ m[14] = D;
+ m[11] = -1.0f;
+ m[ 1] = 0.0f;
+ m[ 2] = 0.0f;
+ m[ 3] = 0.0f;
+ m[ 4] = 0.0f;
+ m[ 6] = 0.0f;
+ m[ 7] = 0.0f;
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[15] = 0.0f;
+}
+
+void perspectiveM(float *m, float fovy,
+ float aspect, float zNear, float zFar)
+{
+ float f;
+ float _tan = (float) tan(fovy * (1 * PI / 360.0));
+ float rangeReciprocal = 1.0f / (zNear - zFar);
+
+ if (_tan == 0.0)
+ f = 1.0f;
+ else
+ f = 1.0f / _tan;
+
+ m[0] = f / aspect;
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = f;
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = (zFar + zNear) * rangeReciprocal;
+ m[11] = 2.0f * zFar * zNear * rangeReciprocal;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = -1.0f;
+ m[15] = 1.0f; // HACK, w should not be 0.0f
+}
+
+void RA4(float *m, float u, float v, float w, float degree)
+{
+ float rad = degToRad(degree);
+ float _cos = cos(rad);
+ float _sin = sin(rad);
+ float u2 = u * u;
+ float v2 = v * v;
+ float w2 = w * w;
+ float uv = u * v;
+ float uw = v * w;
+ float vw = v * w;
+
+ m[0] = u2 + (1 - u2) * _cos;
+ m[1] = uv * (1 - _cos) - w * _sin;
+ m[2] = uw * (1 - _cos) + v * _sin;
+ m[3] = 0.0f;
+
+ m[4] = uv * (1 - _cos) + w * _sin;
+ m[5] = v2 + (1 - v2) * _cos;
+ m[6] = vw * (1 - _cos) - u * _sin;
+ m[7] = 0.0f;
+
+ m[8] = uw * (1 - _cos) - v * _sin;
+ m[9] = vw * (1 - _cos) + u * _sin;
+ m[10] = w2 + (1 - w2) * _cos;
+ m[11] = 0.0f;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+void mat_test(float *m, float x, float y, float z,
+ float degree)
+{
+ float rad = degToRad(degree);
+ float A, B, C, L, V;
+
+ A = x;
+ B = y;
+ C = z;
+
+ L = sqrt(A * A + B * B + C * C);
+ V = sqrt(B * B + C * C);
+
+ float Mrx[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, C/V, -B/V, 0.0,
+ 0.0, B/V, C/V, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+ float Mry[16] = {
+ V/L, 0.0, -A/L, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ A/L, 0.0, V/L, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+ float Mrz[16] = {
+ cos(rad), -sin(rad), 0.0, 0.0,
+ sin(rad), cos(rad), 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+ float Mrry[16] = {
+ V/L, 0.0, A/L, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ -A/L, 0.0, V/L, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+ float Mrrx[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, C/V, B/V, 0.0,
+ 0.0, -B/V, C/V, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+ memcpy(m, Mrx, sizeof(Mrx));
+ mat_multiply(m, Mry);
+ mat_multiply(m, Mrz);
+ mat_multiply(m, Mrry);
+ mat_multiply(m, Mrrx);
+}
+
+void init_mat(float *m)
+{
+ static const float mat[] = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+
+ memcpy(m, &mat, sizeof(mat));
+}
+
diff --git a/sdl/gl/mat.h b/sdl/gl/mat.h
new file mode 100644
index 00000000..0e6405ea
--- /dev/null
+++ b/sdl/gl/mat.h
@@ -0,0 +1,23 @@
+#ifndef __MAT_H__
+#define __MAT_H__
+
+void init_mat(float *m);
+void mat_multiply_to(float *c, float *a, float *b);
+void mat_multiply(float *dst, float *src);
+void move_xyz(float *m, float x, float y, float z);
+void scale_xyz(float *m, float x, float y, float z);
+void rotate_x(float *m, float degree);
+void rotate_y(float *m, float degree);
+void rotate_z(float *m, float degree);
+void frustumM(float *m,
+ int w, int h,
+ int near, int far);
+void perspectiveM(float *m, float fovy,
+ float aspect, float zNear, float zFar);
+void RA4(float *m, float u, float v, float w, float degree);
+void mat_test(float *m, float x, float y, float z,
+ float degree);
+void rotate(float *m, float x, float y, float z);
+
+#endif
+
diff --git a/sdl/gl/shaders.c b/sdl/gl/shaders.c
new file mode 100644
index 00000000..e7aef8a1
--- /dev/null
+++ b/sdl/gl/shaders.c
@@ -0,0 +1,106 @@
+static const char *_vert =
+ "#version 300 es\n"
+ "in vec4 pos;\n"
+ "in vec2 tex;\n"
+ "uniform mat4 view;\n"
+ "uniform mat4 scale;\n"
+ "uniform mat4 move;\n"
+ "uniform mat4 perspective;\n"
+ "out vec2 v_tex;\n"
+ "void main() {\n"
+ " gl_Position = pos * scale * view * move;\n"
+ " v_tex = tex;\n"
+ "}\n";
+
+static const char *_vert_cube =
+ "#version 300 es\n"
+ "in vec4 pos;\n"
+ "in vec3 tex;\n"
+ "uniform mat4 view;\n"
+ "uniform mat4 scale;\n"
+ "uniform mat4 move;\n"
+ "uniform mat4 perspective;\n"
+ "out vec3 v_tex;\n"
+ "void main() {\n"
+ " gl_Position = pos * scale * view * move;\n"
+ " v_tex = vec3(-pos.x, pos.y, pos.z);\n"
+ "}\n";
+#if 0
+ "attribute vec4 pos;\n"
+ "attribute vec2 tex;\n"
+ "varying vec2 v_tex;\n"
+ "void main() {\n"
+ " gl_Position = pos;\n"
+ " v_tex = tex;\n"
+ "}\n";
+#endif
+static const char *_vert_fold =
+ "#version 300 es\n"
+ "in vec4 pos;\n"
+ "in vec2 tex;\n"
+ "uniform mat4 rotate;\n"
+ "uniform mat4 scale;\n"
+ "uniform mat4 move;\n"
+ "uniform mat4 offset;\n"
+ "uniform mat4 t_move;\n"
+ "uniform mat4 view;\n"
+ "out vec2 v_tex;\n"
+ "void main() {\n"
+ " gl_Position = pos * scale * offset * rotate * move * view;\n"
+ " vec4 _tex = vec4(tex, 1.0, 1.0) * scale * t_move;"
+ " v_tex = _tex.xy;\n"
+ "}\n";
+
+static const char *_frag_rgba =
+ "#version 300 es\n"
+ "precision mediump float;\n"
+ "in vec2 v_tex;\n"
+ "out vec4 color;\n"
+ "uniform sampler2D tex_in;\n"
+ "void main() {\n"
+ " vec2 tex_fix = vec2(v_tex.x, 1.0 - v_tex.y);\n"
+ " vec4 rgba = texture2D(tex_in, tex_fix);\n"
+ " color = rgba;\n"
+ "}\n";
+static const char *_frag_bgra =
+ "#version 300 es\n"
+ "precision mediump float;\n"
+ "in vec2 v_tex;\n"
+ "out vec4 color;\n"
+ "uniform sampler2D tex_in;\n"
+ "void main() {\n"
+ " vec2 tex_fix = vec2(v_tex.x, 1.0 - v_tex.y);\n"
+ " vec4 rgba = texture2D(tex_in, v_tex);\n"
+ " color = rgba.bgra;\n"
+ "}\n";
+static const char *_frag_rgba_cube =
+ "#version 300 es\n"
+ "precision mediump float;\n"
+ "in vec3 v_tex;\n"
+ "out vec4 color;\n"
+ "uniform samplerCube tex_in;\n"
+ "void main() {\n"
+ " vec4 rgba = texture(tex_in, v_tex);\n"
+ " color = rgba;\n"
+ "}\n";
+static const char *_frag_bgra_cube =
+ "#version 300 es\n"
+ "precision mediump float;\n"
+ "in vec3 v_tex;\n"
+ "out vec4 color;\n"
+ "uniform samplerCube tex_in;\n"
+ "void main() {\n"
+ " vec4 rgba = texture(tex_in, v_tex);\n"
+ " color = rgba.bgra;\n"
+ "}\n";
+#if 0
+ "precision mediump float;\n"
+ "varying vec2 v_tex;\n"
+ "uniform sampler2D ourTexture;\n"
+ "void main() {\n"
+ " vec4 rgba = texture2D(ourTexture, v_tex);\n"
+ " gl_FragColor = rgba;\n"
+ " gl_FragColor.r = rgba.b;\n"
+ " gl_FragColor.b = rgba.r;\n"
+ "}\n";
+#endif
diff --git a/sdl/gl/shaders/bgra.frag b/sdl/gl/shaders/bgra.frag
new file mode 100644
index 00000000..0934f8cf
--- /dev/null
+++ b/sdl/gl/shaders/bgra.frag
@@ -0,0 +1,12 @@
+#version 300 es
+precision mediump float;
+in float v_alpha;
+in vec2 v_tex;
+out vec4 color;
+uniform sampler2D tex_in;
+void main() {
+ vec4 rgba = texture(tex_in, v_tex);
+ color = rgba.bgra;
+ color.a = rgba.a * v_alpha;
+}
+
diff --git a/sdl/gl/shaders/bgra_cube.frag b/sdl/gl/shaders/bgra_cube.frag
new file mode 100644
index 00000000..5cdaf08b
--- /dev/null
+++ b/sdl/gl/shaders/bgra_cube.frag
@@ -0,0 +1,10 @@
+#version 300 es
+precision mediump float;
+in vec3 v_tex;
+out vec4 color;
+uniform samplerCube tex_in;
+void main() {
+ vec4 rgba = texture(tex_in, v_tex);
+ color = rgba.bgra;
+}
+
diff --git a/sdl/gl/shaders/common.vert b/sdl/gl/shaders/common.vert
new file mode 100644
index 00000000..b436c6bf
--- /dev/null
+++ b/sdl/gl/shaders/common.vert
@@ -0,0 +1,54 @@
+#version 300 es
+const
+float glPI = 3.14159265358979;
+
+/* The simplest way to make z affect w */
+const
+mat4 perspective = mat4(1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, -1.0, 1.0);
+
+mat4 rotatex(float deg)
+{
+ float rad = deg * glPI / 180.f;
+ return mat4(1.0, 0.0, 0.0, 0.0,
+ 0.0, cos(rad), -sin(rad), 0.0,
+ 0.0, sin(rad), cos(rad), 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
+mat4 rotatey(float deg)
+{
+ float rad = deg * glPI / 180.f;
+ return mat4(cos(rad), 0.0, -sin(rad), 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ sin(rad), 0.0, cos(rad), 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
+mat4 rotatez(float deg)
+{
+ float rad = deg * glPI / 180.f;
+ return mat4(cos(rad), -sin(rad), 0.0, 0.0,
+ sin(rad), cos(rad), 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
+mat4 move_xyz(vec3 m)
+{
+ return mat4(1.0, 0.0, 0.0, m.x,
+ 0.0, 1.0, 0.0, m.y,
+ 0.0, 0.0, 1.0, m.z,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
+mat4 scale_xyz(vec3 s)
+{
+ return mat4(s.x, 0.0, 0.0, 0.0,
+ 0.0, s.y, 0.0, 0.0,
+ 0.0, 0.0, s.z, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
diff --git a/sdl/gl/shaders/cube.vert b/sdl/gl/shaders/cube.vert
new file mode 100644
index 00000000..8ceb9975
--- /dev/null
+++ b/sdl/gl/shaders/cube.vert
@@ -0,0 +1,17 @@
+in vec4 pos;
+in vec3 tex;
+uniform vec3 rot;
+uniform vec3 vrot;
+uniform vec3 scale;
+uniform vec3 move;
+out vec3 v_tex;
+
+void main() {
+ mat4 rotate = rotatex(rot.x) * rotatey(rot.y)
+ * rotatez(rot.z);
+ mat4 view = rotatex(vrot.x) * rotatey(vrot.y)
+ * rotatez(vrot.z);
+ gl_Position = pos * scale_xyz(scale) * rotate
+ * view * move_xyz(move);
+ v_tex = vec3(pos.x, pos.y, pos.z);
+}
diff --git a/sdl/gl/shaders/default.vert b/sdl/gl/shaders/default.vert
new file mode 100644
index 00000000..79f9b861
--- /dev/null
+++ b/sdl/gl/shaders/default.vert
@@ -0,0 +1,22 @@
+in vec4 pos;
+in vec2 tex;
+uniform vec3 offset;
+uniform vec3 rot;
+uniform vec3 vrot;
+uniform vec3 scale;
+uniform vec3 move;
+uniform float alpha;
+out vec2 v_tex;
+out float v_alpha;
+
+void main() {
+ mat4 rotate = rotatex(rot.x) * rotatey(rot.y)
+ * rotatez(rot.z);
+ mat4 view = rotatex(vrot.x) * rotatey(vrot.y)
+ * rotatez(vrot.z);
+ gl_Position = pos * move_xyz(offset) * scale_xyz(scale)
+ * rotate * view * perspective * move_xyz(move);
+ v_tex = tex;
+ v_alpha = alpha;
+}
+
diff --git a/sdl/gl/shaders/fold.vert b/sdl/gl/shaders/fold.vert
new file mode 100644
index 00000000..860eabb2
--- /dev/null
+++ b/sdl/gl/shaders/fold.vert
@@ -0,0 +1,21 @@
+in vec4 pos;
+in vec2 tex;
+uniform vec3 scale;
+uniform vec3 offset;
+uniform vec3 rot;
+uniform vec3 move;
+uniform vec3 t_scale;
+uniform vec3 t_move;
+uniform float alpha;
+out vec2 v_tex;
+out float v_alpha;
+void main() {
+ mat4 rotate = rotatey(rot.y);
+ gl_Position = pos * move_xyz(offset)
+ * scale_xyz(scale) * rotate * move_xyz(move);
+ vec4 _tex = vec4(tex, 1.0, 1.0) * scale_xyz(t_scale)
+ * move_xyz(t_move);
+ v_tex = _tex.xy;
+ v_alpha = alpha;
+}
+
diff --git a/sdl/gl/shaders/rgba.frag b/sdl/gl/shaders/rgba.frag
new file mode 100644
index 00000000..a40a5476
--- /dev/null
+++ b/sdl/gl/shaders/rgba.frag
@@ -0,0 +1,12 @@
+#version 300 es
+precision mediump float;
+in float v_alpha;
+in vec2 v_tex;
+out vec4 color;
+uniform sampler2D tex_in;
+void main() {
+ vec2 tex_fix = vec2(v_tex.x, 1.0 - v_tex.y);
+ vec4 rgba = texture(tex_in, tex_fix);
+ color = rgba;
+ color.a = rgba.a * v_alpha;
+}
diff --git a/sdl/gl/shaders/rgba_cube.frag b/sdl/gl/shaders/rgba_cube.frag
new file mode 100644
index 00000000..5e68893c
--- /dev/null
+++ b/sdl/gl/shaders/rgba_cube.frag
@@ -0,0 +1,10 @@
+#version 300 es
+precision mediump float;
+in vec3 v_tex;
+out vec4 color;
+uniform samplerCube tex_in;
+void main() {
+ vec4 rgba = texture(tex_in, v_tex);
+ color = rgba;
+}
+
diff --git a/sdl/sdl_gpu.c b/sdl/sdl_gpu.c
index 4ced2a48..cccb621a 100644
--- a/sdl/sdl_gpu.c
+++ b/sdl/sdl_gpu.c
@@ -35,6 +35,8 @@
#include <lvgl/src/draw/sdl/lv_draw_sdl.h>
#include SDL_INCLUDE_PATH
+#include "gl/gl.h"
+
/*********************
* DEFINES
*********************/
@@ -53,6 +55,9 @@ typedef struct {
lv_coord_t d_ver_res;
SDL_Window * window;
SDL_Texture * texture;
+#if USE_SDL_OPENGL
+ SDL_GLContext context;
+#endif
int rotated;
}monitor_t;
@@ -279,6 +284,9 @@ static void monitor_sdl_clean_up(void)
static void window_create(monitor_t * m)
{
+#if USE_SDL_OPENGL
+ SDL_GLContext previousContext;
+#endif
// SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1");
SDL_Rect rect;
@@ -300,21 +308,36 @@ static void window_create(monitor_t * m)
m->window = SDL_CreateWindow("TFT Simulator",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
m->hor_res * SDL_ZOOM, m->ver_res * SDL_ZOOM,
- SDL_WINDOW_FULLSCREEN);
+#ifndef SDL_DIS_FULLSCREEN
+ SDL_WINDOW_FULLSCREEN |
+#endif
+ SDL_WINDOW_OPENGL);
m->drv_param.renderer = SDL_CreateRenderer(m->window, -1, SDL_RENDERER_ACCELERATED);
m->texture = lv_draw_sdl_create_screen_texture(m->drv_param.renderer, m->d_hor_res, m->d_ver_res);
/* For first frame */
SDL_SetRenderTarget(m->drv_param.renderer, m->texture);
+
+#if USE_SDL_OPENGL
+ previousContext = SDL_GL_GetCurrentContext();
+ m->context = SDL_GL_CreateContext(m->window);
+ SDL_GL_MakeCurrent(m->window, m->context);
+ lv_gl_ctx_init();
+ SDL_GL_MakeCurrent(m->window, previousContext);
+#endif
}
static void window_update(lv_disp_drv_t *disp_drv, void * buf)
{
+#if USE_SDL_OPENGL
+ SDL_GLContext previousContext;
+#endif
SDL_Renderer *renderer = ((lv_draw_sdl_drv_param_t *) disp_drv->user_data)->renderer;
monitor_t *m = (monitor_t *)disp_drv->user_data;
SDL_Texture *texture = buf;
SDL_Rect dst;
+
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderClear(renderer);
#if LV_COLOR_SCREEN_TRANSP
@@ -329,9 +352,18 @@ static void window_update(lv_disp_drv_t *disp_drv, void * buf)
dst.w = m->d_hor_res;
dst.h = m->d_ver_res;
/*Update the renderer with the texture containing the rendered image*/
+
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_RenderSetClipRect(renderer, NULL);
SDL_RenderCopyEx(renderer, texture, NULL, &dst, 90.0 * m->rotated, NULL, SDL_FLIP_NONE);
+#if USE_SDL_OPENGL
+ SDL_RenderFlush(renderer);
+
+ previousContext = SDL_GL_GetCurrentContext();
+ SDL_GL_MakeCurrent(m->window, m->context);
+ lv_gl_render();
+ SDL_GL_MakeCurrent(m->window, previousContext);
+#endif
SDL_RenderPresent(renderer);
SDL_SetRenderTarget(renderer, texture);
}
--
2.25.1