feat(opengl): texture caching (#6861)

Co-authored-by: JWBverheesen <31246830+JWBverheesen@users.noreply.github.com>
This commit is contained in:
Liam
2024-10-13 08:17:12 +02:00
committed by GitHub
parent 30193c1035
commit 0efa5f3758
14 changed files with 882 additions and 66 deletions
+5
View File
@@ -476,6 +476,11 @@ menu "LVGL configuration"
if enabled, the user is required to call
`lv_draw_dma2d_transfer_complete_interrupt_handler`
upon receiving the DMA2D global interrupt
config LV_USE_DRAW_OPENGLES
bool "Draw using cached OpenGLES textures"
default n
depends on LV_USE_OPENGLES
endmenu
menu "Feature Configuration"
+28 -7
View File
@@ -1,5 +1,5 @@
===============================
OpenGL ES Display/Inputs driver
OpenGL ES Display/Inputs Driver
===============================
Overview
@@ -17,7 +17,7 @@ The OpenGL driver uses GLEW GLFW to access the OpenGL window manager.
1. Install GLEW and GLFW: ``sudo apt-get install libglew-dev libglfw3-dev``
Configure OpenGL driver
Configure OpenGL Driver
-----------------------
1. Required linked libraries: -lGL -lGLEW -lglfw
@@ -26,7 +26,7 @@ Configure OpenGL driver
#define LV_USE_OPENGLES 1
Basic usage
Basic Usage
-----------
.. code-block:: c
@@ -75,13 +75,13 @@ Basic usage
return 0;
}
Advanced usage
Advanced Usage
--------------
The OpenGL driver can draw textures from the user. A third-party library could be
used to add content to a texture and the driver will draw the texture in the window.
.. code:: c
.. code-block:: c
#include "lvgl/lvgl.h"
#include <GL/glew.h>
@@ -139,8 +139,7 @@ used to add content to a texture and the driver will draw the texture in the win
/* create objects on the screen of the sub texture */
lv_display_set_default(sub_texture);
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_black(), 0);
lv_example_anim_2();
lv_example_keyboard_2();
lv_display_set_default(main_texture);
/* position the sub texture within the window */
@@ -195,3 +194,25 @@ used to add content to a texture and the driver will draw the texture in the win
/* the texture is drawn on by LVGL and can be used by anything that uses OpenGL textures */
third_party_lib_use_texture(sub_texture_id);
}
OpenGL Texture Caching Renderer
-------------------------------
There is a renderer in LVGL which caches software-rendered areas as OpenGL textures.
The textures are retrieved from the cache and reused when there is a match.
The performance will be drastically improved in most cases.
.. code-block:: c
#define LV_USE_DRAW_OPENGLES 1
Known Limitations
~~~~~~~~~~~~~~~~~
- Performance will be the same or slightly worse if the drawn areas are never found in the cache
due to objects with continuously varying colors or shapes. One example is a label whose color
is set to a random value every frame, as in the "Multiple labels" scene of the benchmark demo.
- Layers with transparent pixels and an overall layer transparency will not blend correctly.
The effect can be observed in the "Containers with opa_layer" scene of the benchmark demo
in the border corners.
- Layers with rotation are not currently supported. Images with rotation are fine.
+4 -1
View File
@@ -294,7 +294,7 @@
#define LV_VG_LITE_STROKE_CACHE_CNT 32
#endif
/* Accelerate blends, fills, etc. with STM32 DMA2D */
/** Accelerate blends, fills, etc. with STM32 DMA2D */
#define LV_USE_DRAW_DMA2D 0
#if LV_USE_DRAW_DMA2D
@@ -306,6 +306,9 @@
#define LV_USE_DRAW_DMA2D_INTERRUPT 0
#endif
/** Draw using cached OpenGLES textures */
#define LV_USE_DRAW_OPENGLES 0
/*=======================
* FEATURE CONFIGURATION
*=======================*/
File diff suppressed because it is too large Load Diff
+45
View File
@@ -0,0 +1,45 @@
/**
* @file lv_draw_opengles.h
*
*/
#ifndef LV_DRAW_OPENGLES_H
#define LV_DRAW_OPENGLES_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_DRAW_OPENGLES
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_opengles_init(void);
void lv_draw_opengles_deinit(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_OPENGLES*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_OPENGLES_H*/
-1
View File
@@ -40,7 +40,6 @@ extern "C" {
typedef struct {
lv_draw_unit_t base_unit;
lv_draw_task_t * task_act;
uint32_t texture_cache_data_type;
lv_cache_t * texture_cache;
} lv_draw_sdl_unit_t;
+9 -2
View File
@@ -110,7 +110,7 @@ void lv_glfw_window_delete(lv_glfw_window_t * window)
if(window->use_indev) {
lv_glfw_texture_t * texture;
LV_LL_READ(&window->textures, texture) {
lv_indev_delete(texture->indev);
if(texture->indev != NULL) lv_indev_delete(texture->indev);
}
}
lv_ll_clear(&window->textures);
@@ -300,7 +300,14 @@ static void window_update_handler(lv_timer_t * t)
lv_refr_now(texture_disp);
}
lv_opengles_render_texture(texture->texture_id, &texture->area, texture->opa, window->hor_res, window->ver_res);
lv_area_t clip_area = texture->area;
#if LV_USE_DRAW_OPENGLES
lv_opengles_render_texture(texture->texture_id, &texture->area, texture->opa, window->hor_res, window->ver_res,
&clip_area, texture_disp == NULL);
#else
lv_opengles_render_texture(texture->texture_id, &texture->area, texture->opa, window->hor_res, window->ver_res,
&clip_area, true);
#endif
}
/* Swap front and back buffers */
+1 -3
View File
@@ -41,14 +41,12 @@ void GLClearError()
while(glGetError() != GL_NO_ERROR);
}
bool GLLogCall(const char * function, const char * file, int line)
void GLLogCall(const char * function, const char * file, int line)
{
GLenum error;
while((error = glGetError()) != GL_NO_ERROR) {
LV_LOG_ERROR("[OpenGL Error] (%d) %s %s:%d", error, function, file, line);
return false;
}
return true;
}
/**********************
+6 -4
View File
@@ -19,12 +19,14 @@ extern "C" {
void GLClearError(void);
bool GLLogCall(const char * function, const char * file, int line);
void GLLogCall(const char * function, const char * file, int line);
#if LV_USE_OPENGLES_DEBUG
#define GL_CALL(x) GLClearError();\
x;\
GLLogCall(#x, __FILE__, __LINE__)
#define GL_CALL(x) do {\
GLClearError();\
x;\
GLLogCall(#x, __FILE__, __LINE__);\
} while(0)
#else
#define GL_CALL(x) x
#endif
+131 -41
View File
@@ -7,6 +7,7 @@
* INCLUDES
*********************/
#include "../../display/lv_display.h"
#include "../../misc/lv_area_private.h"
#if LV_USE_OPENGLES
@@ -17,6 +18,8 @@
* DEFINES
*********************/
#define LV_OPENGLES_VERTEX_BUFFER_LEN 16
/**********************
* TYPEDEFS
**********************/
@@ -24,6 +27,8 @@
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_opengles_render_internal(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 flip, lv_color_t fill_color);
static void lv_opengles_enable_blending(void);
static void lv_opengles_vertex_buffer_init(const void * data, unsigned int size);
static void lv_opengles_vertex_buffer_deinit(void);
@@ -49,7 +54,9 @@ static int lv_opengles_shader_get_uniform_location(const char * name);
static void lv_opengles_shader_set_uniform1i(const char * name, int value);
static void lv_opengles_shader_set_uniformmatrix3fv(const char * name, int count, bool transpose, const float * values);
static void lv_opengles_shader_set_uniform1f(const char * name, float value);
static void lv_opengles_shader_set_uniform3f(const char * name, float value_0, float value_1, float value_2);
static void lv_opengles_render_draw(void);
static float lv_opengles_map_float(float x, float min_in, float max_in, float min_out, float max_out);
/***********************
* GLOBAL PROTOTYPES
@@ -69,8 +76,8 @@ static unsigned int index_buffer_count = 0;
static unsigned int shader_id;
static const char * shader_names[] = { "u_Texture", "u_ColorDepth", "u_VertexTransform", "u_Opa" };
static int shader_location[] = { 0, 0, 0, 0 };
static const char * shader_names[] = { "u_Texture", "u_ColorDepth", "u_VertexTransform", "u_Opa", "u_IsFill", "u_FillColor" };
static int shader_location[] = { 0, 0, 0, 0, 0, 0 };
static const char * vertex_shader =
"#version 300 es\n"
@@ -91,7 +98,7 @@ static const char * vertex_shader =
static const char * fragment_shader =
"#version 300 es\n"
"\n"
"precision mediump float;\n"
"precision lowp float;\n"
"\n"
"layout(location = 0) out vec4 color;\n"
"\n"
@@ -100,15 +107,23 @@ static const char * fragment_shader =
"uniform sampler2D u_Texture;\n"
"uniform int u_ColorDepth;\n"
"uniform float u_Opa;\n"
"uniform bool u_IsFill;\n"
"uniform vec3 u_FillColor;\n"
"\n"
"void main()\n"
"{\n"
" vec4 texColor = texture(u_Texture, v_TexCoord);\n"
" vec4 texColor;\n"
" if (u_IsFill) {\n"
" texColor = vec4(u_FillColor, 1.0f);\n"
" } else {\n"
" texColor = texture(u_Texture, v_TexCoord);\n"
" }\n"
" if (u_ColorDepth == 8) {\n"
" float gray = texColor.r;\n"
" color = vec4(gray, gray, gray, u_Opa);\n"
" } else {\n"
" color = vec4(texColor.rgb, texColor.a * u_Opa);\n"
" float combinedAlpha = texColor.a * u_Opa;\n"
" color = vec4(texColor.rgb * combinedAlpha, combinedAlpha);\n"
" }\n"
"};\n";
@@ -126,19 +141,12 @@ void lv_opengles_init(void)
lv_opengles_enable_blending();
float positions[] = {
-1.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
lv_opengles_vertex_buffer_init(positions, sizeof(positions));
lv_opengles_vertex_buffer_init(NULL, sizeof(float) * LV_OPENGLES_VERTEX_BUFFER_LEN);
lv_opengles_vertex_array_init();
lv_opengles_vertex_array_add_buffer();
@@ -170,27 +178,14 @@ void lv_opengles_deinit(void)
}
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)
int32_t disp_h, const lv_area_t * texture_clip_area, bool flip)
{
GL_CALL(glActiveTexture(GL_TEXTURE0));
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture));
lv_opengles_render_internal(texture, texture_area, opa, disp_w, disp_h, texture_clip_area, flip, lv_color_black());
}
float hor_scale = (float)lv_area_get_width(texture_area) / (float)disp_w;
float ver_scale = (float)lv_area_get_height(texture_area) / (float)disp_h;
float hor_translate = (float)texture_area->x1 / (float)disp_w * 2.0f - (1.0f - hor_scale);
float ver_translate = -((float)texture_area->y1 / (float)disp_h * 2.0f - (1.0f - ver_scale));
float matrix[9] = {
hor_scale, 0.0f, hor_translate,
0.0f, ver_scale, ver_translate,
0.0f, 0.0f, 1.0f
};
lv_opengles_shader_bind();
lv_opengles_shader_set_uniform1i("u_ColorDepth", LV_COLOR_DEPTH);
lv_opengles_shader_set_uniform1i("u_Texture", 0);
lv_opengles_shader_set_uniformmatrix3fv("u_VertexTransform", 1, true, matrix);
lv_opengles_shader_set_uniform1f("u_Opa", (float)opa / (float)LV_OPA_100);
lv_opengles_render_draw();
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_opengles_render_internal(0, area, opa, disp_w, disp_h, area, false, color);
}
void lv_opengles_render_clear(void)
@@ -207,22 +202,79 @@ void lv_opengles_viewport(int32_t x, int32_t y, int32_t w, int32_t h)
* STATIC FUNCTIONS
**********************/
static void lv_opengles_render_internal(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 flip, lv_color_t fill_color)
{
lv_area_t intersection;
if(!lv_area_intersect(&intersection, texture_area, texture_clip_area)) return;
GL_CALL(glActiveTexture(GL_TEXTURE0));
GL_CALL(glBindTexture(GL_TEXTURE_2D, 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));
if(flip) ver_scale = -ver_scale;
float matrix[9] = {
hor_scale, 0.0f, hor_translate,
0.0f, ver_scale, ver_translate,
0.0f, 0.0f, 1.0f
};
if(texture != 0) {
float x_coef = 1.0f / (float)(2 * lv_area_get_width(texture_area));
float y_coef = 1.0f / (float)(2 * lv_area_get_height(texture_area));
float tex_clip_x1 = lv_opengles_map_float(texture_clip_area->x1, texture_area->x1, texture_area->x2, x_coef,
1.0f - x_coef);
float tex_clip_x2 = lv_opengles_map_float(texture_clip_area->x2, texture_area->x1, texture_area->x2, x_coef,
1.0f - x_coef);
float tex_clip_y1 = lv_opengles_map_float(texture_clip_area->y1, texture_area->y1, texture_area->y2, y_coef,
1.0f - y_coef);
float tex_clip_y2 = lv_opengles_map_float(texture_clip_area->y2, texture_area->y1, texture_area->y2, y_coef,
1.0f - y_coef);
float positions[LV_OPENGLES_VERTEX_BUFFER_LEN] = {
-1.0f, 1.0f, tex_clip_x1, tex_clip_y2,
1.0f, 1.0f, tex_clip_x2, tex_clip_y2,
1.0f, -1.0f, tex_clip_x2, tex_clip_y1,
-1.0f, -1.0f, tex_clip_x1, tex_clip_y1
};
lv_opengles_vertex_buffer_init(positions, sizeof(positions));
}
lv_opengles_shader_bind();
lv_opengles_shader_set_uniform1i("u_ColorDepth", LV_COLOR_DEPTH);
lv_opengles_shader_set_uniform1i("u_Texture", 0);
lv_opengles_shader_set_uniformmatrix3fv("u_VertexTransform", 1, true, 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_render_draw();
}
static void lv_opengles_enable_blending(void)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
static void lv_opengles_vertex_buffer_init(const void * data, unsigned int size)
{
GL_CALL(glGenBuffers(1, &vertex_buffer_id));
if(vertex_buffer_id == 0) GL_CALL(glGenBuffers(1, &vertex_buffer_id));
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id));
GL_CALL(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW));
GL_CALL(glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW));
}
static void lv_opengles_vertex_buffer_deinit(void)
{
if(vertex_buffer_id == 0) return;
GL_CALL(glDeleteBuffers(1, &vertex_buffer_id));
vertex_buffer_id = 0;
}
static void lv_opengles_vertex_buffer_bind(void)
@@ -237,12 +289,14 @@ static void lv_opengles_vertex_buffer_unbind(void)
static void lv_opengles_vertex_array_init(void)
{
GL_CALL(glGenVertexArrays(1, &vertex_array_id));
if(vertex_array_id == 0) GL_CALL(glGenVertexArrays(1, &vertex_array_id));
}
static void lv_opengles_vertex_array_deinit(void)
{
if(vertex_array_id == 0) return;
GL_CALL(glDeleteVertexArrays(1, &vertex_array_id));
vertex_array_id = 0;
}
static void lv_opengles_vertex_array_bind(void)
@@ -271,7 +325,7 @@ static void lv_opengles_vertex_array_add_buffer(void)
static void lv_opengles_index_buffer_init(const unsigned int * data, unsigned int count)
{
index_buffer_count = count;
GL_CALL(glGenBuffers(1, &index_buffer_id));
if(index_buffer_id == 0) GL_CALL(glGenBuffers(1, &index_buffer_id));
GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id));
@@ -280,7 +334,9 @@ static void lv_opengles_index_buffer_init(const unsigned int * data, unsigned in
static void lv_opengles_index_buffer_deinit(void)
{
if(index_buffer_id == 0) return;
GL_CALL(glDeleteBuffers(1, &index_buffer_id));
index_buffer_id = 0;
}
static unsigned int lv_opengles_index_buffer_get_count(void)
@@ -300,7 +356,8 @@ static void lv_opengles_index_buffer_unbind(void)
static unsigned int lv_opengles_shader_compile(unsigned int type, const char * source)
{
GL_CALL(unsigned int id = glCreateShader(type));
unsigned int id;
GL_CALL(id = glCreateShader(type));
const char * src = source;
GL_CALL(glShaderSource(id, 1, &src, NULL));
GL_CALL(glCompileShader(id));
@@ -323,7 +380,8 @@ static unsigned int lv_opengles_shader_compile(unsigned int type, const char * s
static unsigned int lv_opengles_shader_create(const char * vertexShader, const char * fragmentShader)
{
GL_CALL(unsigned int program = glCreateProgram());
unsigned int program;
GL_CALL(program = glCreateProgram());
unsigned int vs = lv_opengles_shader_compile(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = lv_opengles_shader_compile(GL_FRAGMENT_SHADER, fragmentShader);
@@ -340,12 +398,14 @@ static unsigned int lv_opengles_shader_create(const char * vertexShader, const c
static void lv_opengles_shader_init(void)
{
shader_id = lv_opengles_shader_create(vertex_shader, fragment_shader);
if(shader_id == 0) shader_id = lv_opengles_shader_create(vertex_shader, fragment_shader);
}
static void lv_opengles_shader_deinit(void)
{
if(shader_id == 0) return;
GL_CALL(glDeleteProgram(shader_id));
shader_id = 0;
}
static void lv_opengles_shader_bind(void)
@@ -374,7 +434,8 @@ static int lv_opengles_shader_get_uniform_location(const char * name)
return shader_location[id];
}
GL_CALL(int location = glGetUniformLocation(shader_id, name));
int location;
GL_CALL(location = glGetUniformLocation(shader_id, name));
if(location == -1)
LV_LOG_WARN("Warning: uniform '%s' doesn't exist!", name);
@@ -397,6 +458,11 @@ static void lv_opengles_shader_set_uniform1f(const char * name, float value)
GL_CALL(glUniform1f(lv_opengles_shader_get_uniform_location(name), value));
}
static void lv_opengles_shader_set_uniform3f(const char * name, float value_0, float value_1, float value_2)
{
GL_CALL(glUniform3f(lv_opengles_shader_get_uniform_location(name), value_0, value_1, value_2));
}
static void lv_opengles_render_draw(void)
{
lv_opengles_shader_bind();
@@ -406,4 +472,28 @@ static void lv_opengles_render_draw(void)
GL_CALL(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, NULL));
}
/**
* Copied from `lv_map` in lv_math.h to operate on floats
*/
static float lv_opengles_map_float(float x, float min_in, float max_in, float min_out, float max_out)
{
if(max_in >= min_in && x >= max_in) return max_out;
if(max_in >= min_in && x <= min_in) return min_out;
if(max_in <= min_in && x <= max_in) return max_out;
if(max_in <= min_in && x >= min_in) return min_out;
/**
* The equation should be:
* ((x - min_in) * delta_out) / delta in) + min_out
* To avoid rounding error reorder the operations:
* (x - min_in) * (delta_out / delta_min) + min_out
*/
float delta_in = max_in - min_in;
float delta_out = max_out - min_out;
return ((x - min_in) * delta_out) / delta_in + min_out;
}
#endif /* LV_USE_OPENGLES */
+13 -3
View File
@@ -49,11 +49,21 @@ void lv_opengles_deinit(void);
* @param texture OpenGL texture ID
* @param texture_area the area in the window to render the texture in
* @param opa opacity to blend the texture with existing contents
* @param disp_w width of the window being rendered to
* @param disp_h height of the window being rendered to
* @param disp_w width of the window/framebuffer being rendered to
* @param disp_h height of the window/framebuffer being rendered to
*/
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);
int32_t disp_h, const lv_area_t * texture_clip_area, bool flip);
/**
* Render a fill
* @param color the color of the fill
* @param area the area in the window to render the fill
* @param opa opacity to blend the fill with existing contents
* @param disp_w width of the window/framebuffer being rendered to
* @param disp_h height of the window/framebuffer being rendered to
*/
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);
/**
* Clear the window/display
+26 -3
View File
@@ -71,12 +71,32 @@ lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h)
GL_CALL(glGenTextures(1, &dsc->texture_id));
GL_CALL(glBindTexture(GL_TEXTURE_2D, dsc->texture_id));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
/* set the dimensions and format to complete the texture */
/* Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888) */
#if LV_COLOR_DEPTH == 8
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, disp->hor_res, disp->ver_res, 0, GL_RED, GL_UNSIGNED_BYTE, NULL));
#elif LV_COLOR_DEPTH == 16
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, disp->hor_res, disp->ver_res, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
NULL));
#elif LV_COLOR_DEPTH == 24
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, disp->hor_res, disp->ver_res, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL));
#elif LV_COLOR_DEPTH == 32
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, disp->hor_res, disp->ver_res, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
#else
#error("Unsupported color format")
#endif
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
lv_display_set_buffers(disp, dsc->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
lv_display_set_flush_cb(disp, flush_cb);
lv_display_set_driver_data(disp, dsc);
@@ -115,6 +135,7 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
LV_UNUSED(area);
LV_UNUSED(px_map);
#if !LV_USE_DRAW_OPENGLES
if(lv_display_flush_is_last(disp)) {
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
@@ -125,7 +146,7 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / lv_color_format_get_size(cf)));
/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
/*Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
#if LV_COLOR_DEPTH == 8
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, disp->hor_res, disp->ver_res, 0, GL_RED, GL_UNSIGNED_BYTE, dsc->fb1));
#elif LV_COLOR_DEPTH == 16
@@ -139,6 +160,7 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
#error("Unsupported color format")
#endif
}
#endif /* !LV_USE_DRAW_OPENGLES */
lv_display_flush_ready(disp);
}
@@ -148,6 +170,7 @@ static void release_disp_cb(lv_event_t * e)
lv_display_t * disp = lv_event_get_user_data(e);
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
free(dsc->fb1);
GL_CALL(glDeleteTextures(1, &dsc->texture_id));
lv_free(dsc);
}
+10 -1
View File
@@ -831,7 +831,7 @@
#endif
#endif
/* Accelerate blends, fills, etc. with STM32 DMA2D */
/** Accelerate blends, fills, etc. with STM32 DMA2D */
#ifndef LV_USE_DRAW_DMA2D
#ifdef CONFIG_LV_USE_DRAW_DMA2D
#define LV_USE_DRAW_DMA2D CONFIG_LV_USE_DRAW_DMA2D
@@ -861,6 +861,15 @@
#endif
#endif
/** Draw using cached OpenGLES textures */
#ifndef LV_USE_DRAW_OPENGLES
#ifdef CONFIG_LV_USE_DRAW_OPENGLES
#define LV_USE_DRAW_OPENGLES CONFIG_LV_USE_DRAW_OPENGLES
#else
#define LV_USE_DRAW_OPENGLES 0
#endif
#endif
/*=======================
* FEATURE CONFIGURATION
*=======================*/
+11
View File
@@ -63,6 +63,9 @@
#if LV_USE_DRAW_DMA2D
#include "draw/dma2d/lv_draw_dma2d.h"
#endif
#if LV_USE_DRAW_OPENGLES
#include "draw/opengles/lv_draw_opengles.h"
#endif
#if LV_USE_WINDOWS
#include "drivers/windows/lv_windows_context.h"
#endif
@@ -228,6 +231,10 @@ void lv_init(void)
lv_draw_dma2d_init();
#endif
#if LV_USE_DRAW_OPENGLES
lv_draw_opengles_init();
#endif
#if LV_USE_WINDOWS
lv_windows_platform_init();
#endif
@@ -421,6 +428,10 @@ void lv_deinit(void)
lv_draw_dma2d_deinit();
#endif
#if LV_USE_DRAW_OPENGLES
lv_draw_opengles_deinit();
#endif
#if LV_USE_DRAW_SW
lv_draw_sw_deinit();
#endif