mirror of
https://github.com/lvgl/lvgl.git
synced 2026-02-05 05:20:04 +08:00
feat(opengl): add matrix transformations to opengles rendering (#9654)
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
1
Kconfig
1
Kconfig
@@ -2231,6 +2231,7 @@ menu "LVGL configuration"
|
||||
|
||||
config LV_USE_OPENGLES
|
||||
bool "Use GLFW and OpenGL to open window on PC and handle mouse and keyboard"
|
||||
depends on LV_USE_MATRIX
|
||||
default n
|
||||
|
||||
config LV_USE_OPENGLES_DEBUG
|
||||
|
||||
@@ -1408,7 +1408,9 @@
|
||||
#define LV_UEFI_USE_MEMORY_SERVICES 0 /**< Use the memory functions from the boot services table */
|
||||
#endif
|
||||
|
||||
/** Use a generic OpenGL driver that can be used to embed in other applications or used with GLFW/EGL */
|
||||
/** Use a generic OpenGL driver that can be used to embed in other applications or used with GLFW/EGL
|
||||
* - Requires LV_USE_MATRIX.
|
||||
*/
|
||||
#define LV_USE_OPENGLES 0
|
||||
#if LV_USE_OPENGLES
|
||||
#define LV_USE_OPENGLES_DEBUG 1 /**< Enable or disable debug for opengles */
|
||||
|
||||
@@ -69,8 +69,22 @@ void lv_draw_nanovg_3d(lv_draw_task_t * t, const lv_draw_3d_dsc_t * dsc, const l
|
||||
|
||||
/* Use LVGL's OpenGL ES rendering infrastructure */
|
||||
lv_opengles_viewport(0, 0, layer_w, layer_h);
|
||||
lv_opengles_render_texture_rbswap(dsc->tex_id, &dest_area, dsc->opa, layer_w, layer_h,
|
||||
&clip_area, dsc->h_flip, !dsc->v_flip);
|
||||
|
||||
lv_opengles_render_params_t params;
|
||||
lv_opengles_render_params_init(¶ms);
|
||||
params.texture = dsc->tex_id;
|
||||
params.texture_area = &dest_area;
|
||||
params.opa = dsc->opa;
|
||||
params.disp_w = layer_w;
|
||||
params.disp_h = layer_h;
|
||||
params.texture_clip_area = &clip_area;
|
||||
params.h_flip = dsc->h_flip;
|
||||
params.v_flip = dsc->v_flip;
|
||||
params.rb_swap = true;
|
||||
#if LV_DRAW_TRANSFORM_USE_MATRIX
|
||||
params.matrix = &layer->matrix;
|
||||
#endif
|
||||
lv_opengles_render(¶ms);
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
@@ -678,8 +678,18 @@ static void lv_draw_opengles_3d(lv_draw_task_t * t, const lv_draw_3d_dsc_t * dsc
|
||||
lv_area_t clip_area = t->clip_area;
|
||||
lv_area_move(&clip_area, -dest_layer->buf_area.x1, -dest_layer->buf_area.y1);
|
||||
|
||||
lv_opengles_render(dsc->tex_id, coords, dsc->opa, targ_tex_w, targ_tex_h, &clip_area, dsc->h_flip, !dsc->v_flip,
|
||||
lv_color_black(), true, false);
|
||||
lv_opengles_render_params_t params;
|
||||
lv_opengles_render_params_init(¶ms);
|
||||
params.texture = dsc->tex_id;
|
||||
params.texture_area = coords;
|
||||
params.opa = dsc->opa;
|
||||
params.disp_w = targ_tex_w;
|
||||
params.disp_h = targ_tex_h;
|
||||
params.texture_clip_area = &clip_area;
|
||||
params.h_flip = dsc->h_flip;
|
||||
params.v_flip = !dsc->v_flip;
|
||||
params.blend_opt = true;
|
||||
lv_opengles_render(¶ms);
|
||||
|
||||
if(target_texture) {
|
||||
GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../misc/lv_profiler.h"
|
||||
#include "../../misc/lv_matrix.h"
|
||||
#include "lv_opengles_debug.h"
|
||||
#include "lv_opengles_private.h"
|
||||
|
||||
@@ -146,12 +147,27 @@ void lv_opengles_deinit(void)
|
||||
is_init = false;
|
||||
}
|
||||
|
||||
void lv_opengles_render_params_init(lv_opengles_render_params_t * params)
|
||||
{
|
||||
LV_ASSERT_NULL(params);
|
||||
lv_memzero(params, sizeof(lv_opengles_render_params_t));
|
||||
}
|
||||
|
||||
void lv_opengles_render_texture(unsigned int texture, const lv_area_t * texture_area, lv_opa_t opa, int32_t disp_w,
|
||||
int32_t disp_h, const lv_area_t * texture_clip_area, bool h_flip, bool v_flip)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
lv_opengles_render(texture, texture_area, opa, disp_w, disp_h, texture_clip_area, h_flip, v_flip,
|
||||
lv_color_black(), false, false);
|
||||
lv_opengles_render_params_t params;
|
||||
lv_opengles_render_params_init(¶ms);
|
||||
params.texture = texture;
|
||||
params.texture_area = texture_area;
|
||||
params.opa = opa;
|
||||
params.disp_w = disp_w;
|
||||
params.disp_h = disp_h;
|
||||
params.texture_clip_area = texture_clip_area;
|
||||
params.h_flip = h_flip;
|
||||
params.v_flip = v_flip;
|
||||
lv_opengles_render(¶ms);
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
@@ -160,15 +176,34 @@ void lv_opengles_render_texture_rbswap(unsigned int texture, const lv_area_t * t
|
||||
int32_t disp_h, const lv_area_t * texture_clip_area, bool h_flip, bool v_flip)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
lv_opengles_render(texture, texture_area, opa, disp_w, disp_h, texture_clip_area, h_flip, v_flip,
|
||||
lv_color_black(), false, true);
|
||||
lv_opengles_render_params_t params;
|
||||
lv_opengles_render_params_init(¶ms);
|
||||
params.texture = texture;
|
||||
params.texture_area = texture_area;
|
||||
params.opa = opa;
|
||||
params.disp_w = disp_w;
|
||||
params.disp_h = disp_h;
|
||||
params.texture_clip_area = texture_clip_area;
|
||||
params.h_flip = h_flip;
|
||||
params.v_flip = v_flip;
|
||||
params.rb_swap = true;
|
||||
lv_opengles_render(¶ms);
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_opengles_render_fill(lv_color_t color, const lv_area_t * area, lv_opa_t opa, int32_t disp_w, int32_t disp_h)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
lv_opengles_render(0, area, opa, disp_w, disp_h, area, false, false, color, false, true);
|
||||
lv_opengles_render_params_t params;
|
||||
lv_opengles_render_params_init(¶ms);
|
||||
params.texture_area = area;
|
||||
params.opa = opa;
|
||||
params.disp_w = disp_w;
|
||||
params.disp_h = disp_h;
|
||||
params.texture_clip_area = area;
|
||||
params.fill_color = color;
|
||||
params.rb_swap = true;
|
||||
lv_opengles_render(¶ms);
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
@@ -257,41 +292,44 @@ void lv_opengles_reinit_state(void)
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_opengles_render(unsigned int texture, const lv_area_t * texture_area, lv_opa_t opa,
|
||||
int32_t disp_w, int32_t disp_h, const lv_area_t * texture_clip_area,
|
||||
bool h_flip, bool v_flip, lv_color_t fill_color, bool blend_opt, bool swap_red_blue)
|
||||
void lv_opengles_render(const lv_opengles_render_params_t * params)
|
||||
{
|
||||
LV_ASSERT_NULL(params);
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
lv_area_t intersection;
|
||||
if(!lv_area_intersect(&intersection, texture_area, texture_clip_area)) {
|
||||
if(!lv_area_intersect(&intersection, params->texture_area, params->texture_clip_area)) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, params->texture));
|
||||
|
||||
float tex_w = (float)lv_area_get_width(&intersection);
|
||||
float tex_h = (float)lv_area_get_height(&intersection);
|
||||
|
||||
float hor_scale = tex_w / (float)disp_w;
|
||||
float ver_scale = tex_h / (float)disp_h;
|
||||
float hor_translate = (float)intersection.x1 / (float)disp_w * 2.0f - (1.0f - hor_scale);
|
||||
float ver_translate = -((float)intersection.y1 / (float)disp_h * 2.0f - (1.0f - ver_scale));
|
||||
hor_scale = h_flip ? -hor_scale : hor_scale;
|
||||
ver_scale = v_flip ? ver_scale : -ver_scale;
|
||||
float hor_scale = tex_w / (float)params->disp_w;
|
||||
float ver_scale = tex_h / (float)params->disp_h;
|
||||
float hor_translate = (float)intersection.x1 / (float)params->disp_w * 2.0f - (1.0f - hor_scale);
|
||||
float ver_translate = -((float)intersection.y1 / (float)params->disp_h * 2.0f - (1.0f - ver_scale));
|
||||
hor_scale = params->h_flip ? -hor_scale : hor_scale;
|
||||
ver_scale = params->v_flip ? ver_scale : -ver_scale;
|
||||
|
||||
if(texture != 0) {
|
||||
float clip_x1 = h_flip ? lv_opengles_map_float(texture_clip_area->x2, texture_area->x2, texture_area->x1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(texture_clip_area->x1, texture_area->x1, texture_area->x2, 0.f, 1.f);
|
||||
float clip_x2 = h_flip ? lv_opengles_map_float(texture_clip_area->x1, texture_area->x2, texture_area->x1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(texture_clip_area->x2, texture_area->x1, texture_area->x2, 0.f, 1.f);
|
||||
float clip_y1 = v_flip ? lv_opengles_map_float(texture_clip_area->y2, texture_area->y2, texture_area->y1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(texture_clip_area->y1, texture_area->y1, texture_area->y2, 0.f, 1.f);
|
||||
float clip_y2 = v_flip ? lv_opengles_map_float(texture_clip_area->y1, texture_area->y2, texture_area->y1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(texture_clip_area->y2, texture_area->y1, texture_area->y2, 0.f, 1.f);
|
||||
if(params->texture != 0) {
|
||||
float clip_x1 = params->h_flip ? lv_opengles_map_float(params->texture_clip_area->x2, params->texture_area->x2,
|
||||
params->texture_area->x1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(params->texture_clip_area->x1, params->texture_area->x1, params->texture_area->x2, 0.f, 1.f);
|
||||
float clip_x2 = params->h_flip ? lv_opengles_map_float(params->texture_clip_area->x1, params->texture_area->x2,
|
||||
params->texture_area->x1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(params->texture_clip_area->x2, params->texture_area->x1, params->texture_area->x2, 0.f, 1.f);
|
||||
float clip_y1 = params->v_flip ? lv_opengles_map_float(params->texture_clip_area->y2, params->texture_area->y2,
|
||||
params->texture_area->y1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(params->texture_clip_area->y1, params->texture_area->y1, params->texture_area->y2, 0.f, 1.f);
|
||||
float clip_y2 = params->v_flip ? lv_opengles_map_float(params->texture_clip_area->y1, params->texture_area->y2,
|
||||
params->texture_area->y1, 0.f, 1.f)
|
||||
: lv_opengles_map_float(params->texture_clip_area->y2, params->texture_area->y1, params->texture_area->y2, 0.f, 1.f);
|
||||
|
||||
float positions[LV_OPENGLES_VERTEX_BUFFER_LEN] = {
|
||||
const float positions[LV_OPENGLES_VERTEX_BUFFER_LEN] = {
|
||||
-1.f, 1.0f, clip_x1, clip_y2,
|
||||
1.0f, 1.0f, clip_x2, clip_y2,
|
||||
1.0f, -1.0f, clip_x2, clip_y1,
|
||||
@@ -300,23 +338,27 @@ void lv_opengles_render(unsigned int texture, const lv_area_t * texture_area, lv
|
||||
lv_opengles_vertex_buffer_init(positions, sizeof(positions));
|
||||
}
|
||||
|
||||
const float transposed_matrix[9] = {
|
||||
hor_scale, 0.0f, 0.0f,
|
||||
0.0f, ver_scale, 0.0f,
|
||||
hor_translate, ver_translate, 1.0f
|
||||
};
|
||||
|
||||
lv_matrix_t matrix;
|
||||
lv_matrix_identity(&matrix);
|
||||
if(params->matrix) {
|
||||
lv_matrix_multiply(&matrix, params->matrix);
|
||||
}
|
||||
else {
|
||||
lv_matrix_translate(&matrix, hor_translate, ver_translate);
|
||||
lv_matrix_scale(&matrix, hor_scale, ver_scale);
|
||||
}
|
||||
|
||||
lv_opengles_shader_bind();
|
||||
lv_opengles_enable_blending(blend_opt);
|
||||
lv_opengles_enable_blending(params->blend_opt);
|
||||
lv_opengles_shader_set_uniform1f("u_ColorDepth", LV_COLOR_DEPTH);
|
||||
lv_opengles_shader_set_uniform1i("u_Texture", 0);
|
||||
lv_opengles_shader_set_uniformmatrix3fv("u_VertexTransform", 1, transposed_matrix);
|
||||
lv_opengles_shader_set_uniform1f("u_Opa", (float)opa / (float)LV_OPA_100);
|
||||
lv_opengles_shader_set_uniform1i("u_IsFill", texture == 0);
|
||||
lv_opengles_shader_set_uniform3f("u_FillColor", (float)fill_color.red / 255.0f, (float)fill_color.green / 255.0f,
|
||||
(float)fill_color.blue / 255.0f);
|
||||
lv_opengles_shader_set_uniform1i("u_SwapRB", swap_red_blue ? 1 : 0);
|
||||
lv_opengles_shader_set_uniformmatrix3fv("u_VertexTransform", 1, (const float *)&matrix);
|
||||
lv_opengles_shader_set_uniform1f("u_Opa", (float)params->opa / (float)LV_OPA_100);
|
||||
lv_opengles_shader_set_uniform1i("u_IsFill", params->texture == 0);
|
||||
lv_opengles_shader_set_uniform3f("u_FillColor", (float)params->fill_color.red / 255.0f,
|
||||
(float)params->fill_color.green / 255.0f,
|
||||
(float)params->fill_color.blue / 255.0f);
|
||||
lv_opengles_shader_set_uniform1i("u_SwapRB", params->rb_swap ? 1 : 0);
|
||||
|
||||
lv_opengles_render_draw();
|
||||
lv_opengles_disable_blending();
|
||||
|
||||
@@ -21,6 +21,10 @@ extern "C" {
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
#if !LV_USE_MATRIX
|
||||
#error "LV_USE_OPENGLES requires LV_USE_MATRIX"
|
||||
#endif
|
||||
|
||||
#if LV_USE_EGL
|
||||
#include "glad/include/glad/gles2.h"
|
||||
#include "glad/include/glad/egl.h"
|
||||
@@ -111,19 +115,35 @@ extern "C" {
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
unsigned int texture;
|
||||
const lv_area_t * texture_area;
|
||||
lv_opa_t opa;
|
||||
int32_t disp_w;
|
||||
int32_t disp_h;
|
||||
const lv_area_t * texture_clip_area;
|
||||
bool h_flip;
|
||||
bool v_flip;
|
||||
bool rb_swap;
|
||||
lv_color_t fill_color;
|
||||
bool blend_opt;
|
||||
const lv_matrix_t * matrix;
|
||||
} lv_opengles_render_params_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_opengles_render(unsigned int texture, const lv_area_t * texture_area, lv_opa_t opa,
|
||||
int32_t disp_w, int32_t disp_h, const lv_area_t * texture_clip_area,
|
||||
bool h_flip, bool v_flip, lv_color_t fill_color, bool blend_opt, bool flipRB);
|
||||
/**
|
||||
* Initialize the render parameters with default values
|
||||
* @param params pointer to an initialized `lv_opengles_render_params_t` struct
|
||||
*/
|
||||
void lv_opengles_render_params_init(lv_opengles_render_params_t * params);
|
||||
|
||||
/**
|
||||
* Render the content of the window/framebuffer using OpenGL
|
||||
* @param params pointer to an initialized `lv_opengles_render_params_t` struct
|
||||
*/
|
||||
void lv_opengles_render(const lv_opengles_render_params_t * params);
|
||||
|
||||
/**
|
||||
* Render a texture using alternate blending mode, with red and blue channels flipped in the shader.
|
||||
|
||||
@@ -4515,7 +4515,9 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Use a generic OpenGL driver that can be used to embed in other applications or used with GLFW/EGL */
|
||||
/** Use a generic OpenGL driver that can be used to embed in other applications or used with GLFW/EGL
|
||||
* - Requires LV_USE_MATRIX.
|
||||
*/
|
||||
#ifndef LV_USE_OPENGLES
|
||||
#ifdef CONFIG_LV_USE_OPENGLES
|
||||
#define LV_USE_OPENGLES CONFIG_LV_USE_OPENGLES
|
||||
|
||||
Reference in New Issue
Block a user