mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-24 16:37:18 +08:00
feat(sdl): add EGL support (#9462)
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ src/draw/nxp/g2d @AndreCostaaa
|
||||
src/draw/nxp/pxp @uLipe
|
||||
src/draw/opengles @AndreCostaaa @kisvegabor
|
||||
src/draw/renesas/dave2d @uLipe
|
||||
src/draw/sdl @kisvegabor
|
||||
src/draw/sdl @kisvegabor @AndreCostaaa
|
||||
src/draw/vg_lite @uLipe @FASTSHIFT
|
||||
src/drivers/display/drm @AndreCostaaa
|
||||
src/drivers/display/fb @AndreCostaaa
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
.. _opengles_draw_unit:
|
||||
|
||||
=====================
|
||||
OpenGL ES Draw Unit
|
||||
=====================
|
||||
|
||||
************
|
||||
Introduction
|
||||
************
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The OpenGL ES Draw Unit provides a hardware-accelerated rendering backend for LVGL that leverages OpenGL ES capabilities.
|
||||
|
||||
OpenGL ES (OpenGL for Embedded Systems) is a subset of OpenGL designed for embedded devices, mobile phones, and other resource-constrained platforms.
|
||||
The OpenGL ES Draw Unit brings GPU-accelerated rendering to LVGL applications on these platforms.
|
||||
|
||||
Key Features
|
||||
------------
|
||||
|
||||
- **Hardware Acceleration**: Direct GPU acceleration via OpenGL ES 2.0+
|
||||
- **Texture Caching**: Rendered elements are cached as OpenGL textures for efficient reuse
|
||||
- **GPU Blending**: Hardware-accelerated texture composition and blending
|
||||
- **Embedded-Friendly**: Optimized for resource-constrained embedded systems
|
||||
- **Wide Platform Support**: Works on mobile, embedded Linux, and other OpenGL ES-compatible platforms
|
||||
|
||||
Performance Characteristics
|
||||
----------------------------
|
||||
|
||||
The OpenGL ES Draw Unit provides excellent performance for:
|
||||
|
||||
- **Best Performance**: Static UI elements that benefit from texture caching
|
||||
- **Good Performance**: UIs with moderate animation and dynamic content
|
||||
- **Embedded Optimization**: Efficient memory usage suitable for embedded systems
|
||||
|
||||
|
||||
|
||||
*************
|
||||
Prerequisites
|
||||
*************
|
||||
|
||||
- OpenGL ES 2.0 or higher support on your platform
|
||||
- A driver which supports OpenGL configured (see :ref:`OpenGL Overview <opengl_overview>`)
|
||||
|
||||
|
||||
|
||||
*************
|
||||
Configuration
|
||||
*************
|
||||
|
||||
Enable in lv_conf.h
|
||||
===================
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define LV_USE_OPENGLES 1
|
||||
|
||||
#define LV_USE_DRAW_OPENGLES 1
|
||||
|
||||
/* Configurable cache count. Bigger cache will improve performance */
|
||||
#define LV_DRAW_OPENGLES_TEXTURE_CACHE_COUNT 64
|
||||
|
||||
|
||||
|
||||
********
|
||||
See Also
|
||||
********
|
||||
|
||||
- :ref:`opengl_overview` - Complete OpenGL integration overview
|
||||
- :ref:`egl_driver` - EGL Display Driver documentation
|
||||
- :ref:`nanovg_draw_unit` - Vector graphics rendering option
|
||||
@@ -0,0 +1,58 @@
|
||||
.. _sdl_draw_unit:
|
||||
|
||||
==============
|
||||
SDL Draw Unit
|
||||
==============
|
||||
|
||||
************
|
||||
Introduction
|
||||
************
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The SDL Draw Unit provides a hardware-accelerated rendering backend for LVGL that leverages SDL2's texture system.
|
||||
It uses software rendering to create SDL textures which are then cached and efficiently blended together by the GPU to compose the final UI.
|
||||
This approach combines the flexibility of software rendering with the performance benefits of hardware-accelerated texture blending.
|
||||
|
||||
Key Features
|
||||
------------
|
||||
|
||||
- **Texture Caching**: Rendered elements are cached as SDL textures, reducing redundant rendering operations
|
||||
- **Hardware Blending**: SDL's GPU-accelerated texture blending provides smooth compositing
|
||||
- **Cross-Platform**: Works on any platform that supports SDL2
|
||||
- **Easy Integration**: Seamless integration with SDL-based LVGL applications
|
||||
|
||||
Performance Characteristics
|
||||
----------------------------
|
||||
|
||||
The SDL Draw Unit excels in scenarios with:
|
||||
|
||||
- **Best Performance**: Static or infrequently changing UI elements that benefit from texture caching
|
||||
- **Good Performance**: UIs with moderate animation and updates
|
||||
- **Consider Alternatives**: Heavily dynamic content that changes every frame may not benefit as much from caching
|
||||
|
||||
|
||||
|
||||
*************
|
||||
Prerequisites
|
||||
*************
|
||||
|
||||
- SDL2 library installed (see :ref:`SDL Driver <sdl_driver>` for installation instructions)
|
||||
- LVGL configured with SDL support (``LV_USE_SDL 1``)
|
||||
|
||||
|
||||
|
||||
*************
|
||||
Configuration
|
||||
*************
|
||||
|
||||
Enable in lv_conf.h
|
||||
===================
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define LV_USE_SDL 1
|
||||
#define LV_USE_DRAW_SDL 1
|
||||
|
||||
The SDL Draw Unit automatically integrates with the SDL display driver when both are enabled.
|
||||
@@ -7,6 +7,8 @@ Running under Embedded Linux
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
draw_opengl
|
||||
draw_sdl
|
||||
overview
|
||||
opengl
|
||||
nanovg
|
||||
|
||||
@@ -19,7 +19,7 @@ OpenGL Support in LVGL
|
||||
The OpenGL integration consists of two main components:
|
||||
|
||||
- OpenGL Display Drivers: Handle output by showing the LVGL rendered content on the display, window, or texture in OpenGL-based environments
|
||||
- OpenGL Draw Unit: When enabled, LVGL uses OpenGL for hardware-accelerated rendering operations, including texture caching for improved performance
|
||||
- OpenGL Draw Unit (see :ref:`OpenGL Draw Unit <opengles_draw_unit>`): When enabled, LVGL uses OpenGL for hardware-accelerated rendering operations, including texture caching for improved performance
|
||||
|
||||
OpenGL support addresses several key use cases:
|
||||
|
||||
@@ -39,34 +39,21 @@ The OpenGL implementation provides significant performance benefits in most scen
|
||||
OpenGL Driver Options
|
||||
======================
|
||||
|
||||
LVGL provides three OpenGL drivers to suit different application needs and platforms:
|
||||
|
||||
The following drivers can be used with OpenGL
|
||||
|
||||
1. GLFW Driver
|
||||
--------------
|
||||
The following drivers can be used and will automatically create and maintain an OpenGL context.
|
||||
|
||||
The GLFW display/input driver offers support for creating
|
||||
LVGL displays and keyboard/mouse inputs that can be used in an OpenGL context.
|
||||
The GLFW driver provides automatic window creation and context management with comprehensive input handling for rapid development on PC-like platforms.
|
||||
- :ref:`SDL driver <sdl_driver>`
|
||||
- :ref:`Wayland driver <wayland_driver>`
|
||||
- :ref:`DRM driver <linux_drm>`
|
||||
- :ref:`GLFW driver <glfw_driver>`
|
||||
|
||||
For complete implementation details, see :ref:`GLFW driver <glfw_driver>`.
|
||||
All drivers except the GLFW driver use EGL (Embedded-System Graphics Library) under the hood.
|
||||
|
||||
2. EGL Driver
|
||||
-------------
|
||||
|
||||
The EGL display driver offers support for creating
|
||||
LVGL displays using the EGL (Embedded-System Graphics Library) API that can be used in an OpenGL context.
|
||||
This driver provides lower-level hardware integration with direct driver access, supporting both DRM-based systems and standalone implementations for embedded platforms.
|
||||
|
||||
For complete implementation details, see :ref:`EGL driver <egl_driver>`.
|
||||
|
||||
3. Generic OpenGL Driver
|
||||
------------------------
|
||||
|
||||
The generic OpenGL driver offers support for creating
|
||||
LVGL displays as OpenGL textures that can be embedded in existing OpenGL applications.
|
||||
This driver assumes an existing OpenGL context and generates textures with hardware acceleration
|
||||
for integration into custom graphics pipelines.
|
||||
Additionally, LVGL provides a generic OpenGL driver which the user may use to embed
|
||||
OpenGL textures in existing OpenGL applications. This driver assumes an existing OpenGL context
|
||||
and generates textures with hardware acceleration for integration into custom graphics pipelines.
|
||||
|
||||
For complete implementation details, see :ref:`OpenGL driver <opengl_driver>`.
|
||||
|
||||
|
||||
@@ -82,3 +82,73 @@ When building for 32-bit architecture, add the following workaround at the begin
|
||||
#ifndef WIN32
|
||||
setenv("DBUS_FATAL_WARNINGS", "0", 1);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
******************
|
||||
Rendering Backends
|
||||
******************
|
||||
|
||||
The SDL driver supports multiple rendering backends that determine how LVGL renders content to the screen.
|
||||
Each backend offers different performance characteristics and use cases.
|
||||
|
||||
|
||||
Standard Software Rendering (Default)
|
||||
======================================
|
||||
|
||||
By default, the SDL driver uses pure software rendering with no additional configuration required.
|
||||
|
||||
**Configuration:**
|
||||
|
||||
No additional configuration needed - this is the default when only ``LV_USE_SDL 1`` is enabled.
|
||||
|
||||
SDL Draw Unit
|
||||
=============
|
||||
|
||||
The SDL Draw Unit uses software rendering to create SDL textures which are then cached and blended together by the GPU,
|
||||
providing a hybrid approach that combines software rendering flexibility with hardware-accelerated texture composition.
|
||||
|
||||
**Configuration:**
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define LV_USE_SDL 1
|
||||
#define LV_USE_DRAW_SDL 1
|
||||
|
||||
For complete details, see :ref:`sdl_draw_unit`.
|
||||
|
||||
|
||||
OpenGL-Based Rendering
|
||||
=======================
|
||||
|
||||
The SDL driver can leverage OpenGL for hardware-accelerated rendering. LVGL provides two OpenGL-based rendering options:
|
||||
|
||||
- :ref:`NanoVG Draw Unit <nanovg_draw_unit>`
|
||||
- :ref:`OpenGL Draw Unit <opengles_draw_unit>`
|
||||
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define LV_USE_SDL 1
|
||||
#define LV_USE_OPENGLES 1
|
||||
|
||||
/* For NanoVG Draw Unit*/
|
||||
#define LV_USE_DRAW_NANOVG 1
|
||||
#define LV_USE_NANOVG 1
|
||||
|
||||
/* For OpenGL Draw Unit */
|
||||
#define LV_USE_DRAW_OPENGLES 1
|
||||
|
||||
See the :ref:`Complete OpenGL overview <opengl_overview>` for more information.
|
||||
|
||||
|
||||
|
||||
********
|
||||
See Also
|
||||
********
|
||||
|
||||
- :ref:`sdl_draw_unit` - SDL texture-based rendering
|
||||
- :ref:`opengl_overview` - Complete OpenGL integration overview
|
||||
- :ref:`nanovg_draw_unit` - NanoVG vector graphics rendering
|
||||
- :ref:`opengles_draw_unit` - OpenGL ES for embedded systems
|
||||
|
||||
|
||||
@@ -291,14 +291,21 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_SDL && LV_USE_OPENGLES && (LV_USE_DRAW_OPENGLES || LV_USE_DRAW_NANOVG)
|
||||
#define LV_SDL_USE_EGL 1
|
||||
#else
|
||||
#define LV_SDL_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#ifndef LV_USE_EGL
|
||||
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL
|
||||
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL || LV_SDL_USE_EGL
|
||||
#define LV_USE_EGL 1
|
||||
#else
|
||||
#define LV_USE_EGL 0
|
||||
#endif
|
||||
#endif /* LV_USE_EGL */
|
||||
|
||||
|
||||
#if LV_USE_OS
|
||||
#if (LV_USE_FREETYPE || LV_USE_THORVG) && LV_DRAW_THREAD_STACK_SIZE < (32 * 1024)
|
||||
#error "Increase LV_DRAW_THREAD_STACK_SIZE to at least 32KB for FreeType or ThorVG."
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @file lv_sdl_egl.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_SDL_USE_EGL
|
||||
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
#include "lv_sdl_private.h"
|
||||
#include "../opengles/lv_opengles_egl_private.h"
|
||||
#include "../opengles/lv_opengles_driver.h"
|
||||
#include "../../draw/lv_draw_buf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_opengles_egl_t * egl_ctx;
|
||||
lv_opengles_texture_t opengles_texture;
|
||||
} lv_sdl_egl_display_data_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void * create_window_cb(void * driver_data, const lv_egl_native_window_properties_t * props);
|
||||
static void destroy_window_cb(void * driver_data, void * native_window);
|
||||
static void flip_cb(void * driver_data, bool vsync);
|
||||
static size_t select_config_cb(void * driver_data, const lv_egl_config_t * configs, size_t config_count);
|
||||
static lv_egl_interface_t lv_sdl_get_egl_interface(lv_display_t * display);
|
||||
static void flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map);
|
||||
|
||||
static lv_result_t init_display(lv_display_t * display);
|
||||
static lv_result_t resize_display(lv_display_t * display);
|
||||
static void deinit_display(lv_display_t * display);
|
||||
static SDL_Renderer * get_renderer(lv_display_t * display);
|
||||
static lv_result_t redraw(lv_display_t * display);
|
||||
|
||||
const lv_sdl_backend_ops_t lv_sdl_backend_ops = {
|
||||
.init_display = init_display,
|
||||
.resize_display = resize_display,
|
||||
.deinit_display = deinit_display,
|
||||
.redraw = redraw,
|
||||
.get_renderer = get_renderer,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_result_t init_display(lv_display_t * display)
|
||||
{
|
||||
lv_egl_interface_t ifc = lv_sdl_get_egl_interface(display);
|
||||
lv_sdl_egl_display_data_t * ddata = lv_malloc_zeroed(sizeof(*ddata));
|
||||
if(!ddata) {
|
||||
LV_LOG_WARN("Failed to allocate memory for display data");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
ddata->egl_ctx = lv_opengles_egl_context_create(&ifc);
|
||||
if(!ddata->egl_ctx) {
|
||||
LV_LOG_ERROR("Failed to initialize EGL context");
|
||||
lv_free(ddata);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_sdl_backend_set_display_data(display, ddata);
|
||||
|
||||
if(LV_USE_DRAW_NANOVG) {
|
||||
static lv_draw_buf_t draw_buf;
|
||||
static uint8_t dummy_buf;
|
||||
lv_draw_buf_init(&draw_buf, 4096, 4096, LV_COLOR_FORMAT_ARGB8888, 4096 * 4, &dummy_buf, 4096 * 4096 * 4);
|
||||
|
||||
lv_display_set_draw_buffers(display, &draw_buf, NULL);
|
||||
lv_display_set_render_mode(display, LV_DISPLAY_RENDER_MODE_FULL);
|
||||
}
|
||||
else {
|
||||
lv_result_t res = resize_display(display);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Failed to create draw buffers");
|
||||
lv_opengles_egl_context_destroy(ddata->egl_ctx);
|
||||
lv_free(ddata);
|
||||
lv_sdl_backend_set_display_data(display, NULL);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
lv_display_set_render_mode(display, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
}
|
||||
lv_display_set_flush_cb(display, flush_cb);
|
||||
|
||||
return LV_RESULT_OK;
|
||||
|
||||
}
|
||||
static lv_result_t resize_display(lv_display_t * display)
|
||||
{
|
||||
if(!LV_USE_DRAW_OPENGLES) {
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
lv_sdl_egl_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
LV_ASSERT_NULL(ddata);
|
||||
|
||||
int32_t hor_res = lv_sdl_window_get_horizontal_resolution(display);
|
||||
int32_t ver_res = lv_sdl_window_get_vertical_resolution(display);
|
||||
ddata->opengles_texture.is_texture_owner = true;
|
||||
return lv_opengles_texture_reshape(&ddata->opengles_texture, display, hor_res, ver_res);
|
||||
|
||||
}
|
||||
static void deinit_display(lv_display_t * display)
|
||||
{
|
||||
lv_sdl_egl_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
if(ddata->egl_ctx) {
|
||||
lv_opengles_egl_context_destroy(ddata->egl_ctx);
|
||||
ddata->egl_ctx = NULL;
|
||||
}
|
||||
|
||||
if(LV_USE_DRAW_OPENGLES) {
|
||||
lv_opengles_texture_deinit(&ddata->opengles_texture);
|
||||
}
|
||||
|
||||
lv_free(ddata);
|
||||
lv_sdl_backend_set_display_data(display, NULL);
|
||||
}
|
||||
|
||||
|
||||
static lv_egl_interface_t lv_sdl_get_egl_interface(lv_display_t * display)
|
||||
{
|
||||
return (lv_egl_interface_t) {
|
||||
.driver_data = display,
|
||||
.create_window_cb = create_window_cb,
|
||||
.destroy_window_cb = destroy_window_cb,
|
||||
.egl_platform = 0,
|
||||
.native_display = EGL_DEFAULT_DISPLAY,
|
||||
.flip_cb = flip_cb,
|
||||
.select_config = select_config_cb,
|
||||
};
|
||||
|
||||
}
|
||||
static void * create_window_cb(void * driver_data, const lv_egl_native_window_properties_t * props)
|
||||
{
|
||||
LV_UNUSED(props);
|
||||
lv_display_t * display = (lv_display_t *)driver_data;
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
SDL_GetWindowWMInfo(lv_sdl_window_get_window(display), &wmInfo);
|
||||
|
||||
EGLNativeWindowType native_window;
|
||||
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
|
||||
native_window = wmInfo.info.win.window;
|
||||
#elif defined(SDL_VIDEO_DRIVER_X11)
|
||||
native_window = wmInfo.info.x11.window;
|
||||
#elif defined(SDL_VIDEO_DRIVER_WAYLAND)
|
||||
native_window = wmInfo.info.wl.surface;
|
||||
#else
|
||||
LV_LOG_ERROR("Unsupported platform for EGL");
|
||||
return NULL;
|
||||
#endif
|
||||
return (void *)native_window;
|
||||
}
|
||||
|
||||
static void flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map)
|
||||
{
|
||||
|
||||
LV_UNUSED(area);
|
||||
LV_UNUSED(px_map);
|
||||
lv_sdl_egl_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
LV_ASSERT_NULL(ddata);
|
||||
|
||||
if(lv_display_flush_is_last(display)) {
|
||||
#if LV_USE_DRAW_OPENGLES
|
||||
lv_opengles_viewport(0, 0,
|
||||
lv_display_get_original_horizontal_resolution(display),
|
||||
lv_display_get_original_vertical_resolution(display));
|
||||
lv_opengles_render_display_texture(display, false, true);
|
||||
#endif /*LV_USE_DRAW_OPENGLES*/
|
||||
lv_opengles_egl_update(ddata->egl_ctx);
|
||||
}
|
||||
lv_display_flush_ready(display);
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t select_config_cb(void * driver_data, const lv_egl_config_t * configs, size_t config_count)
|
||||
{
|
||||
lv_display_t * display = (lv_display_t *)driver_data;
|
||||
int32_t target_w = lv_display_get_horizontal_resolution(display);
|
||||
int32_t target_h = lv_display_get_vertical_resolution(display);
|
||||
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
lv_color_format_t target_cf = LV_COLOR_FORMAT_RGB565;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
lv_color_format_t target_cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
#else
|
||||
#error "Unsupported color format"
|
||||
#endif
|
||||
|
||||
|
||||
for(size_t i = 0; i < config_count; ++i) {
|
||||
LV_LOG_TRACE("Got config %zu %#x %dx%d %d %d %d %d buffer size %d depth %d samples %d stencil %d surface type %d renderable type %d",
|
||||
i, configs[i].id,
|
||||
configs[i].max_width, configs[i].max_height, configs[i].r_bits, configs[i].g_bits, configs[i].b_bits, configs[i].a_bits,
|
||||
configs[i].buffer_size, configs[i].depth, configs[i].samples, configs[i].stencil,
|
||||
configs[i].surface_type & EGL_WINDOW_BIT, configs[i].renderable_type & EGL_OPENGL_ES2_BIT);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < config_count; ++i) {
|
||||
lv_color_format_t config_cf = lv_opengles_egl_color_format_from_egl_config(&configs[i]);
|
||||
const bool resolution_matches = configs[i].max_width >= target_w &&
|
||||
configs[i].max_height >= target_h;
|
||||
const bool is_nanovg_compatible = (configs[i].renderable_type & EGL_OPENGL_ES2_BIT) != 0 &&
|
||||
configs[i].stencil == 8 && configs[i].samples == 4;
|
||||
const bool is_window = (configs[i].surface_type & EGL_WINDOW_BIT) != 0;
|
||||
const bool is_compatible_with_draw_unit = is_nanovg_compatible || !LV_USE_DRAW_NANOVG;
|
||||
|
||||
if(is_window && resolution_matches && config_cf == target_cf && is_compatible_with_draw_unit) {
|
||||
LV_LOG_INFO("Choosing config %zu", i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return config_count;
|
||||
}
|
||||
static void destroy_window_cb(void * driver_data, void * native_window)
|
||||
{
|
||||
LV_UNUSED(driver_data);
|
||||
LV_UNUSED(native_window);
|
||||
}
|
||||
|
||||
static void flip_cb(void * driver_data, bool vsync)
|
||||
{
|
||||
|
||||
LV_UNUSED(driver_data);
|
||||
LV_UNUSED(vsync);
|
||||
}
|
||||
|
||||
|
||||
static SDL_Renderer * get_renderer(lv_display_t * display)
|
||||
{
|
||||
LV_UNUSED(display);
|
||||
return NULL;
|
||||
}
|
||||
static lv_result_t redraw(lv_display_t * display)
|
||||
{
|
||||
LV_UNUSED(display);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
#endif /*LV_SDL_USE_EGL*/
|
||||
@@ -14,9 +14,13 @@ extern "C" {
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "lv_sdl_window.h"
|
||||
|
||||
#if LV_USE_SDL
|
||||
|
||||
#include "../opengles/lv_opengles_egl_private.h"
|
||||
#include "../opengles/lv_opengles_texture_private.h"
|
||||
|
||||
#include LV_SDL_INCLUDE_PATH
|
||||
|
||||
/*********************
|
||||
@@ -27,6 +31,35 @@ extern "C" {
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
void * backend_data;
|
||||
SDL_Window * window;
|
||||
float zoom;
|
||||
uint8_t ignore_size_chg;
|
||||
} lv_sdl_window_t;
|
||||
|
||||
void lv_sdl_backend_set_display_data(lv_display_t * display, void * backend_display_data);
|
||||
void * lv_sdl_backend_get_display_data(lv_display_t * display);
|
||||
|
||||
int32_t lv_sdl_window_get_horizontal_resolution(lv_display_t * display);
|
||||
int32_t lv_sdl_window_get_vertical_resolution(lv_display_t * display);
|
||||
|
||||
typedef lv_result_t (*lv_sdl_backend_init_display_t)(lv_display_t * disp);
|
||||
typedef lv_result_t (*lv_sdl_backend_resize_display_t)(lv_display_t * disp);
|
||||
typedef lv_result_t (*lv_sdl_backend_redraw_t)(lv_display_t * disp);
|
||||
typedef SDL_Renderer * (*lv_sdl_backend_get_renderer_t)(lv_display_t * disp);
|
||||
typedef void (*lv_sdl_backend_deinit_display_t)(lv_display_t * disp);
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_backend_init_display_t init_display;
|
||||
lv_sdl_backend_resize_display_t resize_display;
|
||||
lv_sdl_backend_deinit_display_t deinit_display;
|
||||
lv_sdl_backend_redraw_t redraw;
|
||||
lv_sdl_backend_get_renderer_t get_renderer;
|
||||
} lv_sdl_backend_ops_t;
|
||||
|
||||
extern const lv_sdl_backend_ops_t lv_sdl_backend_ops;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@@ -36,6 +69,21 @@ void lv_sdl_mouse_handler(SDL_Event * event);
|
||||
void lv_sdl_mousewheel_handler(SDL_Event * event);
|
||||
lv_display_t * lv_sdl_get_disp_from_win_id(uint32_t win_id);
|
||||
|
||||
|
||||
#if LV_SDL_USE_EGL
|
||||
lv_result_t lv_sdl_egl_init(lv_display_t * disp);
|
||||
lv_result_t lv_sdl_egl_resize(lv_display_t * disp);
|
||||
void lv_sdl_egl_deinit(lv_display_t * disp);
|
||||
#elif LV_USE_DRAW_SDL
|
||||
lv_result_t lv_sdl_texture_init(lv_display_t * disp);
|
||||
lv_result_t lv_sdl_texture_resize(lv_display_t * disp);
|
||||
void lv_sdl_texture_deinit(lv_display_t * disp);
|
||||
#else
|
||||
lv_result_t lv_sdl_sw_init(lv_display_t * disp);
|
||||
lv_result_t lv_sdl_sw_resize(lv_display_t * disp);
|
||||
void lv_sdl_sw_deinit(lv_display_t * disp);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* @file lv_sdl_sw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/* for aligned_alloc */
|
||||
#ifndef __USE_ISOC11
|
||||
#define _ISOC11_SOURCE
|
||||
#endif
|
||||
|
||||
#include "lv_sdl_private.h"
|
||||
|
||||
#if LV_USE_SDL && !LV_SDL_USE_EGL && !LV_USE_DRAW_SDL
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../draw/sw/lv_draw_sw_utils.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
SDL_Texture * texture;
|
||||
SDL_Renderer * renderer;
|
||||
uint8_t * fb1;
|
||||
uint8_t * fb2;
|
||||
uint8_t * fb_act;
|
||||
uint8_t * buf1;
|
||||
uint8_t * buf2;
|
||||
uint8_t * rotated_buf;
|
||||
size_t rotated_buf_size;
|
||||
} lv_sdl_sw_display_data_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void * sdl_draw_buf_realloc_aligned(void * ptr, size_t new_size);
|
||||
static void sdl_draw_buf_free(void * ptr);
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||
static lv_result_t window_update(lv_display_t * disp);
|
||||
|
||||
static inline int sdl_render_mode(void)
|
||||
{
|
||||
return LV_SDL_RENDER_MODE;
|
||||
}
|
||||
|
||||
static lv_result_t init_display(lv_display_t * display);
|
||||
static lv_result_t resize_display(lv_display_t * display);
|
||||
static void deinit_display(lv_display_t * display);
|
||||
static SDL_Renderer * get_renderer(lv_display_t * display);
|
||||
|
||||
const lv_sdl_backend_ops_t lv_sdl_backend_ops = {
|
||||
.init_display = init_display,
|
||||
.resize_display = resize_display,
|
||||
.deinit_display = deinit_display,
|
||||
.redraw = window_update,
|
||||
.get_renderer = get_renderer,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_result_t init_display(lv_display_t * display)
|
||||
{
|
||||
lv_sdl_sw_display_data_t * ddata = lv_malloc_zeroed(sizeof(*ddata));
|
||||
if(!ddata) {
|
||||
LV_LOG_WARN("No memory for display data");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
ddata->renderer = SDL_CreateRenderer(lv_sdl_window_get_window(display), -1,
|
||||
LV_SDL_ACCELERATED ? SDL_RENDERER_ACCELERATED : SDL_RENDERER_SOFTWARE);
|
||||
if(!ddata->renderer) {
|
||||
LV_LOG_ERROR("Failed to create SDL renderer '%s'", SDL_GetError());
|
||||
lv_free(ddata);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
lv_sdl_backend_set_display_data(display, ddata);
|
||||
|
||||
int32_t hor_res = lv_sdl_window_get_horizontal_resolution(display);
|
||||
int32_t ver_res = lv_sdl_window_get_vertical_resolution(display);
|
||||
|
||||
resize_display(display);
|
||||
|
||||
uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(display));
|
||||
lv_memset(ddata->fb1, 0xff, hor_res * ver_res * px_size);
|
||||
if(ddata->fb2) lv_memset(ddata->fb2, 0xff, hor_res * ver_res * px_size);
|
||||
|
||||
lv_display_set_flush_cb(display, flush_cb);
|
||||
|
||||
if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(lv_display_get_color_format(display)) * 4;
|
||||
uint32_t buffer_size_bytes = 32 * 1024 + palette_size;
|
||||
ddata->buf1 = sdl_draw_buf_realloc_aligned(NULL, buffer_size_bytes);
|
||||
if(LV_SDL_BUF_COUNT == 2) {
|
||||
ddata->buf2 = sdl_draw_buf_realloc_aligned(NULL, buffer_size_bytes);
|
||||
}
|
||||
lv_display_set_buffers(display, ddata->buf1, ddata->buf2, buffer_size_bytes, LV_SDL_RENDER_MODE);
|
||||
}
|
||||
else {
|
||||
/*LV_DISPLAY_RENDER_MODE_DIRECT or FULL */
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(display->hor_res,
|
||||
lv_display_get_color_format(display));
|
||||
lv_display_set_buffers(display, ddata->fb1, ddata->fb2, stride * display->ver_res,
|
||||
LV_SDL_RENDER_MODE);
|
||||
}
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
static lv_result_t resize_display(lv_display_t * display)
|
||||
{
|
||||
lv_color_format_t cf = lv_display_get_color_format(display);
|
||||
/*In some cases SDL stride might be different than LVGL render stride, like in I1 format.
|
||||
SDL still uses ARGB8888 as the color format, but LVGL renders in I1, thus causing a mismatch
|
||||
This ensures correct stride for SDL buffers in this case.*/
|
||||
if(cf == LV_COLOR_FORMAT_I1) {
|
||||
cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
}
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(display->hor_res, cf);
|
||||
lv_sdl_sw_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
|
||||
ddata->fb1 = sdl_draw_buf_realloc_aligned(ddata->fb1, stride * display->ver_res);
|
||||
LV_ASSERT_MALLOC(ddata->fb1);
|
||||
lv_memzero(ddata->fb1, stride * display->ver_res);
|
||||
|
||||
if(sdl_render_mode() == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
ddata->fb_act = ddata->fb1;
|
||||
}
|
||||
else {
|
||||
if(LV_SDL_BUF_COUNT == 2) {
|
||||
ddata->fb2 = sdl_draw_buf_realloc_aligned(ddata->fb2, stride * display->ver_res);
|
||||
lv_memset(ddata->fb2, 0x00, stride * display->ver_res);
|
||||
}
|
||||
lv_display_set_buffers(display, ddata->fb1, ddata->fb2, stride * display->ver_res, LV_SDL_RENDER_MODE);
|
||||
}
|
||||
if(ddata->texture) SDL_DestroyTexture(ddata->texture);
|
||||
|
||||
#if LV_COLOR_DEPTH == 32 || LV_COLOR_DEPTH == 1
|
||||
SDL_PixelFormatEnum px_format =
|
||||
SDL_PIXELFORMAT_RGB888; /*same as SDL_PIXELFORMAT_RGB888, but it's not supported in older versions*/
|
||||
#elif LV_COLOR_DEPTH == 24
|
||||
SDL_PixelFormatEnum px_format = SDL_PIXELFORMAT_BGR24;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
SDL_PixelFormatEnum px_format = SDL_PIXELFORMAT_RGB565;
|
||||
#else
|
||||
#error("Unsupported color format")
|
||||
#endif
|
||||
|
||||
ddata->texture = SDL_CreateTexture(ddata->renderer, px_format,
|
||||
SDL_TEXTUREACCESS_STATIC, display->hor_res, display->ver_res);
|
||||
SDL_SetTextureBlendMode(ddata->texture, SDL_BLENDMODE_BLEND);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
static void deinit_display(lv_display_t * display)
|
||||
{
|
||||
|
||||
lv_sdl_sw_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
LV_ASSERT_NULL(ddata);
|
||||
if(ddata->texture) {
|
||||
SDL_DestroyTexture(ddata->texture);
|
||||
ddata->texture = NULL;
|
||||
}
|
||||
if(ddata->renderer) {
|
||||
SDL_DestroyRenderer(ddata->renderer);
|
||||
ddata->renderer = NULL;
|
||||
}
|
||||
|
||||
if(ddata->fb1) {
|
||||
sdl_draw_buf_free(ddata->fb1);
|
||||
ddata->fb1 = NULL;
|
||||
}
|
||||
if(ddata->fb2) {
|
||||
sdl_draw_buf_free(ddata->fb2);
|
||||
ddata->fb2 = NULL;
|
||||
}
|
||||
|
||||
if(ddata->buf1) {
|
||||
sdl_draw_buf_free(ddata->buf1);
|
||||
ddata->buf1 = NULL;
|
||||
}
|
||||
if(ddata->buf2) {
|
||||
sdl_draw_buf_free(ddata->buf2);
|
||||
ddata->buf2 = NULL;
|
||||
}
|
||||
|
||||
lv_free(ddata);
|
||||
lv_sdl_backend_set_display_data(display, NULL);
|
||||
}
|
||||
|
||||
static SDL_Renderer * get_renderer(lv_display_t * display)
|
||||
{
|
||||
lv_sdl_sw_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
LV_ASSERT_NULL(ddata);
|
||||
return ddata->renderer;
|
||||
}
|
||||
|
||||
|
||||
static void * sdl_draw_buf_realloc_aligned(void * ptr, size_t new_size)
|
||||
{
|
||||
if(ptr) {
|
||||
sdl_draw_buf_free(ptr);
|
||||
}
|
||||
|
||||
/* No need copy for drawing buffer */
|
||||
#ifndef _WIN32
|
||||
/* Size must be multiple of align, See: https://en.cppreference.com/w/c/memory/aligned_alloc */
|
||||
#define BUF_ALIGN (LV_DRAW_BUF_ALIGN < sizeof(void *) ? sizeof(void *) : LV_DRAW_BUF_ALIGN)
|
||||
return aligned_alloc(BUF_ALIGN, LV_ALIGN_UP(new_size, BUF_ALIGN));
|
||||
#else
|
||||
return _aligned_malloc(LV_ALIGN_UP(new_size, LV_DRAW_BUF_ALIGN), LV_DRAW_BUF_ALIGN);
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
static void sdl_draw_buf_free(void * ptr)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
free(ptr);
|
||||
#else
|
||||
_aligned_free(ptr);
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
static void flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map)
|
||||
{
|
||||
lv_color_format_t cf = lv_display_get_color_format(display);
|
||||
lv_sdl_sw_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
uint32_t * argb_px_map = NULL;
|
||||
|
||||
if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
if(cf == LV_COLOR_FORMAT_RGB565_SWAPPED) {
|
||||
uint32_t width = lv_area_get_width(area);
|
||||
uint32_t height = lv_area_get_height(area);
|
||||
lv_draw_sw_rgb565_swap(px_map, width * height);
|
||||
}
|
||||
/*Update values in a special OLED I1 --> ARGB8888 case
|
||||
We render everything in I1, but display it in ARGB8888*/
|
||||
if(cf == LV_COLOR_FORMAT_I1) {
|
||||
/*I1 uses 1 bit wide pixels, ARGB8888 uses 4 byte wide pixels*/
|
||||
cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
uint32_t width = lv_area_get_width(area);
|
||||
uint32_t height = lv_area_get_height(area);
|
||||
uint32_t argb_px_map_size = width * height * 4;
|
||||
argb_px_map = malloc(argb_px_map_size);
|
||||
if(argb_px_map == NULL) {
|
||||
LV_LOG_ERROR("malloc failed");
|
||||
lv_display_flush_ready(display);
|
||||
return;
|
||||
}
|
||||
/* skip the palette */
|
||||
px_map += LV_COLOR_INDEXED_PALETTE_SIZE(LV_COLOR_FORMAT_I1) * 4;
|
||||
const uint32_t i1_stride = lv_draw_buf_width_to_stride(width, LV_COLOR_FORMAT_I1);
|
||||
const uint32_t argb8888_stride = lv_draw_buf_width_to_stride(width, LV_COLOR_FORMAT_ARGB8888);
|
||||
lv_draw_sw_i1_to_argb8888(px_map, argb_px_map, width, height, i1_stride, argb8888_stride, 0xFF000000u, 0xFFFFFFFFu);
|
||||
px_map = (uint8_t *)argb_px_map;
|
||||
}
|
||||
|
||||
lv_area_t rotated_area = *area;
|
||||
lv_display_rotate_area(display, &rotated_area);
|
||||
|
||||
int32_t px_map_w = lv_area_get_width(area);
|
||||
int32_t px_map_h = lv_area_get_height(area);
|
||||
uint32_t px_map_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), cf);
|
||||
uint32_t px_size = lv_color_format_get_size(cf);
|
||||
|
||||
int32_t fb_stride = lv_draw_buf_width_to_stride(display->hor_res, cf);
|
||||
uint8_t * fb_start = ddata->fb_act;
|
||||
fb_start += rotated_area.y1 * fb_stride + rotated_area.x1 * px_size;
|
||||
lv_display_rotation_t rotation = lv_display_get_rotation(display);
|
||||
|
||||
if(rotation == LV_DISPLAY_ROTATION_0) {
|
||||
uint32_t px_map_line_bytes = lv_area_get_width(area) * px_size;
|
||||
|
||||
int32_t y;
|
||||
for(y = area->y1; y <= area->y2; y++) {
|
||||
lv_memcpy(fb_start, px_map, px_map_line_bytes);
|
||||
px_map += px_map_stride;
|
||||
fb_start += fb_stride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_draw_sw_rotate(px_map, fb_start, px_map_w, px_map_h, px_map_stride, fb_stride, rotation, cf);
|
||||
}
|
||||
}
|
||||
|
||||
if(lv_display_flush_is_last(display)) {
|
||||
if(sdl_render_mode() != LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
ddata->fb_act = px_map;
|
||||
}
|
||||
window_update(display);
|
||||
}
|
||||
free(argb_px_map);
|
||||
lv_display_flush_ready(display);
|
||||
}
|
||||
|
||||
static lv_result_t window_update(lv_display_t * display)
|
||||
{
|
||||
lv_color_format_t cf = lv_display_get_color_format(display);
|
||||
lv_sdl_sw_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
if(cf == LV_COLOR_FORMAT_I1) {
|
||||
cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
}
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(display->hor_res, cf);
|
||||
SDL_UpdateTexture(ddata->texture, NULL, ddata->fb_act, stride);
|
||||
|
||||
SDL_RenderClear(ddata->renderer);
|
||||
|
||||
/*Update the renderer with the texture containing the rendered image*/
|
||||
SDL_RenderCopy(ddata->renderer, ddata->texture, NULL, NULL);
|
||||
SDL_RenderPresent(ddata->renderer);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_SDL && !LV_SDL_USE_EGL && !LV_USE_DRAW_SDL*/
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* @file lv_sdl_texture.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_sdl_private.h"
|
||||
|
||||
#if LV_USE_SDL && !LV_SDL_USE_EGL && LV_USE_DRAW_SDL
|
||||
|
||||
#include "../../draw/lv_draw_buf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
SDL_Renderer * renderer;
|
||||
} lv_sdl_texture_display_data_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||
|
||||
static lv_result_t init_display(lv_display_t * display);
|
||||
static lv_result_t resize(lv_display_t * display);
|
||||
static void deinit_display(lv_display_t * display);
|
||||
static SDL_Renderer * get_renderer(lv_display_t * display);
|
||||
static lv_result_t redraw(lv_display_t * display);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
const lv_sdl_backend_ops_t lv_sdl_backend_ops = {
|
||||
.init_display = init_display,
|
||||
.resize_display = resize,
|
||||
.deinit_display = deinit_display,
|
||||
.get_renderer = get_renderer,
|
||||
.redraw = redraw,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_result_t init_display(lv_display_t * display)
|
||||
{
|
||||
lv_sdl_texture_display_data_t * ddata = lv_malloc_zeroed(sizeof(*ddata));
|
||||
if(!ddata) {
|
||||
LV_LOG_WARN("No memory for display data");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
ddata->renderer = SDL_CreateRenderer(lv_sdl_window_get_window(display), -1,
|
||||
LV_SDL_ACCELERATED ? SDL_RENDERER_ACCELERATED : SDL_RENDERER_SOFTWARE);
|
||||
if(!ddata->renderer) {
|
||||
LV_LOG_ERROR("Failed to create SDL renderer '%s'", SDL_GetError());
|
||||
lv_free(ddata);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
lv_sdl_backend_set_display_data(display, ddata);
|
||||
|
||||
/*It will render directly to default Texture, so the buffer is not used, so just set something*/
|
||||
static lv_draw_buf_t draw_buf;
|
||||
static uint8_t dummy_buf; /*It won't be used as it will render to the SDL textures directly*/
|
||||
lv_draw_buf_init(&draw_buf, 4096, 4096, LV_COLOR_FORMAT_ARGB8888, 4096 * 4, &dummy_buf, 4096 * 4096 * 4);
|
||||
|
||||
lv_display_set_draw_buffers(display, &draw_buf, NULL);
|
||||
lv_display_set_render_mode(display, LV_DISPLAY_RENDER_MODE_FULL);
|
||||
lv_display_set_flush_cb(display, flush_cb);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
static lv_result_t resize(lv_display_t * display)
|
||||
{
|
||||
LV_UNUSED(display);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
static void deinit_display(lv_display_t * display)
|
||||
{
|
||||
lv_sdl_texture_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
LV_ASSERT_NULL(ddata);
|
||||
|
||||
if(ddata->renderer) {
|
||||
SDL_DestroyRenderer(ddata->renderer);
|
||||
}
|
||||
|
||||
lv_free(ddata);
|
||||
lv_sdl_backend_set_display_data(display, NULL);
|
||||
}
|
||||
|
||||
static void flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map)
|
||||
{
|
||||
LV_UNUSED(area);
|
||||
LV_UNUSED(px_map);
|
||||
lv_sdl_texture_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
if(lv_display_flush_is_last(display)) {
|
||||
SDL_RenderPresent(ddata->renderer);
|
||||
}
|
||||
lv_display_flush_ready(display);
|
||||
}
|
||||
|
||||
static SDL_Renderer * get_renderer(lv_display_t * display)
|
||||
{
|
||||
lv_sdl_texture_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
LV_ASSERT_NULL(ddata);
|
||||
return ddata->renderer;
|
||||
}
|
||||
static lv_result_t redraw(lv_display_t * display)
|
||||
{
|
||||
|
||||
lv_sdl_texture_display_data_t * ddata = lv_sdl_backend_get_display_data(display);
|
||||
LV_ASSERT_NULL(ddata);
|
||||
SDL_RenderPresent(ddata->renderer);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_SDL && !LV_SDL_USE_EGL && LV_USE_DRAW_SDL*/
|
||||
+75
-278
@@ -14,21 +14,9 @@
|
||||
#if LV_USE_SDL
|
||||
#include <stdbool.h>
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include "../../lv_init.h"
|
||||
#include "../../draw/lv_draw_buf.h"
|
||||
|
||||
/* for aligned_alloc */
|
||||
#ifndef __USE_ISOC11
|
||||
#define __USE_ISOC11
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/
|
||||
#include "lv_sdl_private.h"
|
||||
@@ -45,35 +33,12 @@
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
SDL_Window * window;
|
||||
SDL_Renderer * renderer;
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
SDL_Texture * texture;
|
||||
uint8_t * fb1;
|
||||
uint8_t * fb2;
|
||||
uint8_t * fb_act;
|
||||
uint8_t * buf1;
|
||||
uint8_t * buf2;
|
||||
uint8_t * rotated_buf;
|
||||
size_t rotated_buf_size;
|
||||
#endif
|
||||
float zoom;
|
||||
uint8_t ignore_size_chg;
|
||||
} lv_sdl_window_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static inline int sdl_render_mode(void);
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p);
|
||||
static void window_create(lv_display_t * disp);
|
||||
static void window_update(lv_display_t * disp);
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
static void texture_resize(lv_display_t * disp);
|
||||
static void * sdl_draw_buf_realloc_aligned(void * ptr, size_t new_size);
|
||||
static void sdl_draw_buf_free(void * ptr);
|
||||
#endif
|
||||
static lv_result_t window_create(lv_display_t * disp);
|
||||
static void sdl_event_handler(lv_timer_t * t);
|
||||
static void release_disp_cb(lv_event_t * e);
|
||||
static void res_chg_event_cb(lv_event_t * e);
|
||||
@@ -95,6 +60,10 @@ static lv_timer_t * event_handler_timer;
|
||||
lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res)
|
||||
{
|
||||
if(!inited) {
|
||||
#if LV_SDL_USE_EGL && defined(SDL_VIDEO_DRIVER_X11)
|
||||
SDL_SetHintWithPriority("SDL_VIDEODRIVER", "x11", SDL_HINT_OVERRIDE);
|
||||
SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "1");
|
||||
#endif
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_StartTextInput();
|
||||
event_handler_timer = lv_timer_create(sdl_event_handler, 5, NULL);
|
||||
@@ -113,39 +82,18 @@ lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res)
|
||||
lv_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
|
||||
lv_display_set_driver_data(disp, dsc);
|
||||
window_create(disp);
|
||||
|
||||
lv_display_set_flush_cb(disp, flush_cb);
|
||||
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
if(sdl_render_mode() == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(lv_display_get_color_format(disp)) * 4;
|
||||
uint32_t buffer_size_bytes = 32 * 1024 + palette_size;
|
||||
dsc->buf1 = sdl_draw_buf_realloc_aligned(NULL, buffer_size_bytes);
|
||||
#if LV_SDL_BUF_COUNT == 2
|
||||
dsc->buf2 = sdl_draw_buf_realloc_aligned(NULL, buffer_size_bytes);
|
||||
#endif
|
||||
lv_display_set_buffers(disp, dsc->buf1, dsc->buf2, buffer_size_bytes, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
lv_result_t res = window_create(disp);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Failed to initialize window");
|
||||
lv_free(dsc);
|
||||
lv_display_delete(disp);
|
||||
return NULL;
|
||||
}
|
||||
/*LV_DISPLAY_RENDER_MODE_DIRECT or FULL */
|
||||
else {
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(disp->hor_res,
|
||||
lv_display_get_color_format(disp));
|
||||
lv_display_set_buffers(disp, dsc->fb1, dsc->fb2, stride * disp->ver_res,
|
||||
LV_SDL_RENDER_MODE);
|
||||
}
|
||||
#else /*LV_USE_DRAW_SDL == 1*/
|
||||
/*It will render directly to default Texture, so the buffer is not used, so just set something*/
|
||||
static lv_draw_buf_t draw_buf;
|
||||
static uint8_t dummy_buf; /*It won't be used as it will render to the SDL textures directly*/
|
||||
lv_draw_buf_init(&draw_buf, 4096, 4096, LV_COLOR_FORMAT_ARGB8888, 4096 * 4, &dummy_buf, 4096 * 4096 * 4);
|
||||
|
||||
lv_display_set_draw_buffers(disp, &draw_buf, NULL);
|
||||
lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
#endif /*LV_USE_DRAW_SDL == 0*/
|
||||
lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
|
||||
lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
|
||||
|
||||
/*Process the initial events*/
|
||||
sdl_event_handler(NULL);
|
||||
|
||||
@@ -208,10 +156,12 @@ void lv_sdl_window_set_icon(lv_display_t * disp, void * icon, int32_t width, int
|
||||
SDL_FreeSurface(iconSurface);
|
||||
}
|
||||
|
||||
void * lv_sdl_window_get_renderer(lv_display_t * disp)
|
||||
void * lv_sdl_window_get_renderer(lv_display_t * display)
|
||||
{
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
return dsc->renderer;
|
||||
if(!display) {
|
||||
return NULL;
|
||||
}
|
||||
return lv_sdl_backend_ops.get_renderer(display);
|
||||
}
|
||||
|
||||
struct SDL_Window * lv_sdl_window_get_window(lv_display_t * disp)
|
||||
@@ -238,6 +188,36 @@ void lv_sdl_quit(void)
|
||||
}
|
||||
}
|
||||
|
||||
void lv_sdl_backend_set_display_data(lv_display_t * display, void * backend_display_data)
|
||||
{
|
||||
LV_ASSERT_NULL(display);
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(display);
|
||||
dsc->backend_data = backend_display_data;
|
||||
}
|
||||
void * lv_sdl_backend_get_display_data(lv_display_t * display)
|
||||
{
|
||||
LV_ASSERT_NULL(display);
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(display);
|
||||
return dsc->backend_data;
|
||||
}
|
||||
|
||||
int32_t lv_sdl_window_get_horizontal_resolution(lv_display_t * display)
|
||||
{
|
||||
/* Private function, fine to assert here*/
|
||||
LV_ASSERT_NULL(display);
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(display);
|
||||
LV_ASSERT_NULL(dsc);
|
||||
return (int32_t)((float)(display->hor_res) * dsc->zoom);
|
||||
}
|
||||
int32_t lv_sdl_window_get_vertical_resolution(lv_display_t * display)
|
||||
{
|
||||
/* Private function, fine to assert here*/
|
||||
LV_ASSERT_NULL(display);
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(display);
|
||||
LV_ASSERT_NULL(dsc);
|
||||
return (int32_t)((float)(display->ver_res) * dsc->zoom);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -247,88 +227,6 @@ static inline int sdl_render_mode(void)
|
||||
return LV_SDL_RENDER_MODE;
|
||||
}
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||
{
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
lv_color_format_t cf = lv_display_get_color_format(disp);
|
||||
uint32_t * argb_px_map = NULL;
|
||||
|
||||
if(sdl_render_mode() == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
|
||||
if(cf == LV_COLOR_FORMAT_RGB565_SWAPPED) {
|
||||
uint32_t width = lv_area_get_width(area);
|
||||
uint32_t height = lv_area_get_height(area);
|
||||
lv_draw_sw_rgb565_swap(px_map, width * height);
|
||||
}
|
||||
/*Update values in a special OLED I1 --> ARGB8888 case
|
||||
We render everything in I1, but display it in ARGB8888*/
|
||||
if(cf == LV_COLOR_FORMAT_I1) {
|
||||
/*I1 uses 1 bit wide pixels, ARGB8888 uses 4 byte wide pixels*/
|
||||
cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
uint32_t width = lv_area_get_width(area);
|
||||
uint32_t height = lv_area_get_height(area);
|
||||
uint32_t argb_px_map_size = width * height * 4;
|
||||
argb_px_map = malloc(argb_px_map_size);
|
||||
if(argb_px_map == NULL) {
|
||||
LV_LOG_ERROR("malloc failed");
|
||||
lv_display_flush_ready(disp);
|
||||
return;
|
||||
}
|
||||
/* skip the palette */
|
||||
px_map += LV_COLOR_INDEXED_PALETTE_SIZE(LV_COLOR_FORMAT_I1) * 4;
|
||||
lv_draw_sw_i1_to_argb8888(px_map, argb_px_map, width, height, width / 8, width * 4, 0xFF000000u, 0xFFFFFFFFu);
|
||||
px_map = (uint8_t *)argb_px_map;
|
||||
}
|
||||
|
||||
lv_area_t rotated_area = *area;
|
||||
lv_display_rotate_area(disp, &rotated_area);
|
||||
|
||||
int32_t px_map_w = lv_area_get_width(area);
|
||||
int32_t px_map_h = lv_area_get_height(area);
|
||||
uint32_t px_map_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), cf);
|
||||
uint32_t px_size = lv_color_format_get_size(cf);
|
||||
|
||||
int32_t fb_stride = lv_draw_buf_width_to_stride(disp->hor_res, cf);
|
||||
uint8_t * fb_start = dsc->fb_act;
|
||||
fb_start += rotated_area.y1 * fb_stride + rotated_area.x1 * px_size;
|
||||
lv_display_rotation_t rotation = lv_display_get_rotation(disp);
|
||||
|
||||
if(rotation == LV_DISPLAY_ROTATION_0) {
|
||||
uint32_t px_map_line_bytes = lv_area_get_width(area) * px_size;
|
||||
|
||||
int32_t y;
|
||||
for(y = area->y1; y <= area->y2; y++) {
|
||||
lv_memcpy(fb_start, px_map, px_map_line_bytes);
|
||||
px_map += px_map_stride;
|
||||
fb_start += fb_stride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_draw_sw_rotate(px_map, fb_start, px_map_w, px_map_h, px_map_stride, fb_stride, rotation, cf);
|
||||
}
|
||||
}
|
||||
|
||||
if(lv_display_flush_is_last(disp)) {
|
||||
if(sdl_render_mode() != LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
dsc->fb_act = px_map;
|
||||
}
|
||||
|
||||
window_update(disp);
|
||||
}
|
||||
free(argb_px_map);
|
||||
#else
|
||||
LV_UNUSED(area);
|
||||
LV_UNUSED(px_map);
|
||||
if(lv_display_flush_is_last(disp)) {
|
||||
window_update(disp);
|
||||
}
|
||||
#endif /*LV_USE_DRAW_SDL == 0*/
|
||||
|
||||
/*IMPORTANT! It must be called to tell the system the flush is ready*/
|
||||
lv_display_flush_ready(disp);
|
||||
}
|
||||
|
||||
/**
|
||||
* SDL main thread. All SDL related task have to be handled here!
|
||||
* It initializes SDL, handles drawing and the mouse.
|
||||
@@ -355,7 +253,7 @@ static void sdl_event_handler(lv_timer_t * t)
|
||||
case SDL_WINDOWEVENT_TAKE_FOCUS:
|
||||
#endif
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
window_update(disp);
|
||||
lv_sdl_backend_ops.redraw(disp);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
dsc->ignore_size_chg = 1;
|
||||
@@ -383,12 +281,16 @@ static void sdl_event_handler(lv_timer_t * t)
|
||||
}
|
||||
}
|
||||
|
||||
static void window_create(lv_display_t * disp)
|
||||
static lv_result_t window_create(lv_display_t * disp)
|
||||
{
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
dsc->zoom = 1.0;
|
||||
|
||||
int flag = 0;
|
||||
#if LV_SDL_USE_EGL
|
||||
flag |= SDL_WINDOW_OPENGL;
|
||||
#endif
|
||||
|
||||
#if LV_SDL_FULLSCREEN
|
||||
flag |= SDL_WINDOW_FULLSCREEN;
|
||||
#endif
|
||||
@@ -398,130 +300,35 @@ static void window_create(lv_display_t * disp)
|
||||
dsc->window = SDL_CreateWindow("LVGL Simulator",
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
hor_res, ver_res, flag); /*last param. SDL_WINDOW_BORDERLESS to hide borders*/
|
||||
if(!dsc->window) {
|
||||
LV_LOG_ERROR("Failed to create SDL window");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
if(lv_sdl_backend_ops.init_display(disp) != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Failed to initialize SDL backend");
|
||||
SDL_DestroyWindow(dsc->window);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
dsc->renderer = SDL_CreateRenderer(dsc->window, -1,
|
||||
LV_SDL_ACCELERATED ? SDL_RENDERER_ACCELERATED : SDL_RENDERER_SOFTWARE);
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
texture_resize(disp);
|
||||
|
||||
uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp));
|
||||
lv_memset(dsc->fb1, 0xff, hor_res * ver_res * px_size);
|
||||
if(dsc->fb2) lv_memset(dsc->fb2, 0xff, hor_res * ver_res * px_size);
|
||||
|
||||
#endif /*LV_USE_DRAW_SDL == 0*/
|
||||
/*Some platforms (e.g. Emscripten) seem to require setting the size again */
|
||||
SDL_SetWindowSize(dsc->window, hor_res, ver_res);
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
texture_resize(disp);
|
||||
#endif /*LV_USE_DRAW_SDL == 0*/
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
static void window_update(lv_display_t * disp)
|
||||
{
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
int32_t hor_res = disp->hor_res;
|
||||
lv_color_format_t cf = lv_display_get_color_format(disp);
|
||||
if(cf == LV_COLOR_FORMAT_I1) {
|
||||
cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
}
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(hor_res, cf);
|
||||
SDL_UpdateTexture(dsc->texture, NULL, dsc->fb_act, stride);
|
||||
|
||||
SDL_RenderClear(dsc->renderer);
|
||||
|
||||
/*Update the renderer with the texture containing the rendered image*/
|
||||
SDL_RenderCopy(dsc->renderer, dsc->texture, NULL, NULL);
|
||||
#endif
|
||||
SDL_RenderPresent(dsc->renderer);
|
||||
}
|
||||
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
static void texture_resize(lv_display_t * disp)
|
||||
{
|
||||
lv_color_format_t cf = lv_display_get_color_format(disp);
|
||||
/*In some cases SDL stride might be different than LVGL render stride, like in I1 format.
|
||||
SDL still uses ARGB8888 as the color format, but LVGL renders in I1, thus causing a mismatch
|
||||
This ensures correct stride for SDL buffers in this case.*/
|
||||
if(cf == LV_COLOR_FORMAT_I1) {
|
||||
cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
}
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(disp->hor_res, cf);
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
|
||||
dsc->fb1 = sdl_draw_buf_realloc_aligned(dsc->fb1, stride * disp->ver_res);
|
||||
LV_ASSERT_MALLOC(dsc->fb1);
|
||||
lv_memzero(dsc->fb1, stride * disp->ver_res);
|
||||
|
||||
if(sdl_render_mode() == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
dsc->fb_act = dsc->fb1;
|
||||
}
|
||||
else {
|
||||
#if LV_SDL_BUF_COUNT == 2
|
||||
dsc->fb2 = sdl_draw_buf_realloc_aligned(dsc->fb2, stride * disp->ver_res);
|
||||
memset(dsc->fb2, 0x00, stride * disp->ver_res);
|
||||
#endif
|
||||
lv_display_set_buffers(disp, dsc->fb1, dsc->fb2, stride * disp->ver_res, LV_SDL_RENDER_MODE);
|
||||
}
|
||||
if(dsc->texture) SDL_DestroyTexture(dsc->texture);
|
||||
|
||||
#if LV_COLOR_DEPTH == 32 || LV_COLOR_DEPTH == 1
|
||||
SDL_PixelFormatEnum px_format =
|
||||
SDL_PIXELFORMAT_RGB888; /*same as SDL_PIXELFORMAT_RGB888, but it's not supported in older versions*/
|
||||
#elif LV_COLOR_DEPTH == 24
|
||||
SDL_PixelFormatEnum px_format = SDL_PIXELFORMAT_BGR24;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
SDL_PixelFormatEnum px_format = SDL_PIXELFORMAT_RGB565;
|
||||
#else
|
||||
#error("Unsupported color format")
|
||||
#endif
|
||||
|
||||
dsc->texture = SDL_CreateTexture(dsc->renderer, px_format,
|
||||
SDL_TEXTUREACCESS_STATIC, disp->hor_res, disp->ver_res);
|
||||
SDL_SetTextureBlendMode(dsc->texture, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
static void * sdl_draw_buf_realloc_aligned(void * ptr, size_t new_size)
|
||||
{
|
||||
if(ptr) {
|
||||
sdl_draw_buf_free(ptr);
|
||||
}
|
||||
|
||||
/* No need copy for drawing buffer */
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Size must be multiple of align, See: https://en.cppreference.com/w/c/memory/aligned_alloc */
|
||||
|
||||
#define BUF_ALIGN (LV_DRAW_BUF_ALIGN < sizeof(void *) ? sizeof(void *) : LV_DRAW_BUF_ALIGN)
|
||||
return aligned_alloc(BUF_ALIGN, LV_ALIGN_UP(new_size, BUF_ALIGN));
|
||||
#else
|
||||
return _aligned_malloc(LV_ALIGN_UP(new_size, LV_DRAW_BUF_ALIGN), LV_DRAW_BUF_ALIGN);
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
static void sdl_draw_buf_free(void * ptr)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
free(ptr);
|
||||
#else
|
||||
_aligned_free(ptr);
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void res_chg_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = lv_event_get_current_target(e);
|
||||
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
if(dsc->ignore_size_chg == false) {
|
||||
SDL_SetWindowSize(dsc->window,
|
||||
(int)((float)(disp->hor_res)*dsc->zoom), (int)((float)(disp->ver_res)*dsc->zoom));
|
||||
if(lv_sdl_backend_ops.resize_display(disp) != LV_RESULT_OK) {
|
||||
LV_LOG_WARN("Failed to resize display");
|
||||
return;
|
||||
}
|
||||
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
texture_resize(disp);
|
||||
#endif
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
if(!dsc->ignore_size_chg) {
|
||||
SDL_SetWindowSize(dsc->window,
|
||||
lv_sdl_window_get_horizontal_resolution(disp),
|
||||
lv_sdl_window_get_vertical_resolution(disp));
|
||||
}
|
||||
}
|
||||
|
||||
static void release_disp_cb(lv_event_t * e)
|
||||
@@ -529,21 +336,11 @@ static void release_disp_cb(lv_event_t * e)
|
||||
if(lv_deinit_in_progress) {
|
||||
lv_sdl_quit();
|
||||
}
|
||||
|
||||
lv_display_t * disp = (lv_display_t *) lv_event_get_user_data(e);
|
||||
|
||||
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
SDL_DestroyTexture(dsc->texture);
|
||||
#endif
|
||||
SDL_DestroyRenderer(dsc->renderer);
|
||||
|
||||
lv_sdl_backend_ops.deinit_display(disp);
|
||||
SDL_DestroyWindow(dsc->window);
|
||||
#if LV_USE_DRAW_SDL == 0
|
||||
if(dsc->fb1) sdl_draw_buf_free(dsc->fb1);
|
||||
if(dsc->fb2) sdl_draw_buf_free(dsc->fb2);
|
||||
if(dsc->buf1) sdl_draw_buf_free(dsc->buf1);
|
||||
if(dsc->buf2) sdl_draw_buf_free(dsc->buf2);
|
||||
#endif
|
||||
lv_free(dsc);
|
||||
lv_display_set_driver_data(disp, NULL);
|
||||
}
|
||||
|
||||
@@ -4901,14 +4901,21 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_SDL && LV_USE_OPENGLES && (LV_USE_DRAW_OPENGLES || LV_USE_DRAW_NANOVG)
|
||||
#define LV_SDL_USE_EGL 1
|
||||
#else
|
||||
#define LV_SDL_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#ifndef LV_USE_EGL
|
||||
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL
|
||||
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL || LV_SDL_USE_EGL
|
||||
#define LV_USE_EGL 1
|
||||
#else
|
||||
#define LV_USE_EGL 0
|
||||
#endif
|
||||
#endif /* LV_USE_EGL */
|
||||
|
||||
|
||||
#if LV_USE_OS
|
||||
#if (LV_USE_FREETYPE || LV_USE_THORVG) && LV_DRAW_THREAD_STACK_SIZE < (32 * 1024)
|
||||
#error "Increase LV_DRAW_THREAD_STACK_SIZE to at least 32KB for FreeType or ThorVG."
|
||||
|
||||
Reference in New Issue
Block a user