From fea41fc576e28608434bc66922f97087518ab458 Mon Sep 17 00:00:00 2001 From: Jiajian Wu Date: Mon, 27 Nov 2023 14:24:59 +0800 Subject: [PATCH] sdl: Support opengl Signed-off-by: Jiajian Wu --- 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 +#include +#include +#include + +#if USE_SDL_OPENGL +#include + +#define SDL_MAIN_HANDLED +#include +#include +#include +#include +#include + +#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 +#include +#include +#include + +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 +#include +#include +#include + +#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 #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