perf(egl): improve egl performance (#8966)

Co-authored-by: Matt Kimball <greyworld@gmail.com>
This commit is contained in:
André Costa
2025-09-30 12:50:29 +02:00
committed by GitHub
parent 94c23a76d2
commit 73874ca3bf
27 changed files with 5169 additions and 1057 deletions
@@ -96,6 +96,19 @@ Notes
- DRM requires proper modesetting. By default, LVGL will select a preferred display mode.
In order to avoid hard codding the device card path, you can ask LVGL to find a connected one for you using :cpp:func:`lv_linux_drm_find_device_path`.
It will return the first connected card it can find.
.. code-block:: c
lv_display_t * disp = lv_linux_drm_create();
/* Find the first connected card in /sys/class/drm */
char * device = lv_linux_drm_find_device_path();
lv_linux_drm_set_file(disp, device, -1);
/* Free the path pointer */
lv_free(device);
Using DRM with GBM
------------------
@@ -43,19 +43,6 @@ This API is currently private and experimental, and people should expect breakin
This allows you to use EGL with your own context management or other platforms, but the API may change
without notice in future versions.
Render Direct to Window
-----------------------
.. warning::
This feature is incomplete and has bugs.
Performance can be improved if the LVGL OpenGL driver renders its cached textures directly to the window
(and :c:macro:`LV_USE_DRAW_OPENGLES` is enabled). This can be done by creating the display with
:cpp:func:`lv_opengles_window_display_create` instead of :cpp:func:`lv_opengles_texture_create` +
:cpp:func:`lv_opengles_texture_get_texture_id` + :cpp:func:`lv_opengles_window_add_texture`.
Performance should be better with GLFW than EGL. EGL currently has issues when used this way.
Improving Performance
---------------------
+1
View File
@@ -50,6 +50,7 @@
--exclude=../src/libs/expat
--exclude=../src/libs/lz4
--exclude=../src/libs/FT800-FT813
--exclude=../src/drivers/opengles/glad
--exclude=../src/others/vg_lite_tvg/vg_lite.h
--exclude=../demos/high_res/fonts
--exclude=../tests/unity/unity.c
+5 -3
View File
@@ -552,7 +552,6 @@ static void execute_drawing(lv_draw_opengles_unit_t * u)
t->draw_unit = (lv_draw_unit_t *)u;
/* the shader-based fill is not working reliably with EGL. */
#if !LV_USE_EGL
if(t->type == LV_DRAW_TASK_TYPE_FILL) {
lv_draw_fill_dsc_t * fill_dsc = t->draw_dsc;
if(fill_dsc->radius == 0 && fill_dsc->grad.dir == LV_GRAD_DIR_NONE) {
@@ -581,7 +580,6 @@ static void execute_drawing(lv_draw_opengles_unit_t * u)
return;
}
}
#endif /*!LV_USE_EGL*/
if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
blend_texture_layer(t);
@@ -621,13 +619,17 @@ static unsigned int create_texture(int32_t w, int32_t h, const void * data)
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
/* LV_COLOR_DEPTH 32, 24, 16 are supported but the cached textures will always
/* LV_COLOR_DEPTH 32, 16 are supported but the cached textures will always
* have full ARGB pixels since the alpha channel is required for blending.
*/
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data));
#if 0
GL_CALL(glGenerateMipmap(GL_TEXTURE_2D));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
#endif
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(glBindTexture(GL_TEXTURE_2D, 0));
+12 -323
View File
@@ -7,7 +7,7 @@
* INCLUDES
*********************/
#include "lv_linux_drm.h"
#if LV_USE_LINUX_DRM
#if LV_USE_LINUX_DRM && !LV_LINUX_DRM_USE_EGL
#include <errno.h>
#include <fcntl.h>
@@ -25,10 +25,6 @@
#include "../../../stdlib/lv_sprintf.h"
#include "../../../draw/lv_draw_buf.h"
#if LV_LINUX_DRM_USE_EGL && !LV_USE_LINUX_DRM_GBM_BUFFERS
#error LV_USE_LINUX_DRM_GBM_BUFFERS is required to use LV_LINUX_DRM_USE_EGL
#endif
#if LV_USE_LINUX_DRM_GBM_BUFFERS
#include <gbm.h>
@@ -37,17 +33,6 @@
#endif
#if LV_LINUX_DRM_USE_EGL
#include "../../opengles/lv_opengles_egl.h"
#include "../../opengles/lv_opengles_texture.h"
#include "../../opengles/lv_opengles_window.h"
#include "../../opengles/lv_opengles_private.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif
/*********************
* DEFINES
*********************/
@@ -61,8 +46,6 @@
#define BUFFER_CNT 2
#define USE_EGL_EXPERIMENTAL_DIRECT_WINDOW_RENDER 0
/**********************
* TYPEDEFS
**********************/
@@ -73,19 +56,8 @@ typedef struct {
unsigned long int size;
uint8_t * map;
uint32_t fb_handle;
#if LV_LINUX_DRM_USE_EGL
uint32_t fb_id;
#endif
} drm_buffer_t;
#if LV_LINUX_DRM_USE_EGL
typedef EGLint(*egl_wait_sync_khr_t)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
typedef EGLint(*egl_dup_native_fence_fd_android_t)(EGLDisplay dpy, EGLSyncKHR sync);
typedef EGLSyncKHR(*egl_create_sync_khr_t)(EGLDisplay dpy, EGLenum type, const EGLint * attrib_list);
typedef EGLBoolean(*egl_destroy_sync_khr_t)(EGLDisplay dpy, EGLSyncKHR sync);
typedef EGLint(*egl_client_wait_sync_khr_t)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
#endif
typedef struct {
int fd;
uint32_t conn_id, enc_id, crtc_id, plane_id, crtc_idx;
@@ -111,20 +83,6 @@ typedef struct {
#if LV_USE_LINUX_DRM_GBM_BUFFERS
struct gbm_device * gbm_device;
#endif
#if LV_LINUX_DRM_USE_EGL
struct gbm_surface * surface;
int kms_in_fence_fd;
int kms_out_fence_fd;
EGLSyncKHR kms_fence;
EGLSyncKHR gpu_fence;
struct gbm_bo * bo;
egl_wait_sync_khr_t egl_wait_sync_khr;
egl_dup_native_fence_fd_android_t egl_dup_native_fence_fd_android;
egl_create_sync_khr_t egl_create_sync_khr;
egl_destroy_sync_khr_t egl_destroy_sync_khr;
egl_client_wait_sync_khr_t egl_client_wait_sync_khr;
#endif
} drm_dev_t;
/**********************
@@ -151,26 +109,15 @@ static uint32_t tick_get_cb(void);
#if !LV_USE_LINUX_DRM_GBM_BUFFERS
static int drm_allocate_dumb(drm_dev_t * drm_dev, drm_buffer_t * buf);
#elif LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL
#elif LV_USE_LINUX_DRM_GBM_BUFFERS
static int create_gbm_buffer(drm_dev_t * drm_dev, drm_buffer_t * buf);
#endif
#if LV_LINUX_DRM_USE_EGL
static drm_buffer_t * drm_fb_get_from_bo(struct gbm_bo * bo);
static void drm_fb_destroy_callback(struct gbm_bo * bo, void * data);
static void drm_gbm_egl_pre(lv_opengles_window_t * window);
static void drm_gbm_egl_post1(lv_opengles_window_t * window);
static void drm_gbm_egl_post2(lv_opengles_window_t * window);
static int drm_atomic_commit(drm_dev_t * drm_dev, uint32_t fb_id, uint32_t flags);
static EGLSyncKHR create_fence(drm_dev_t * drm_dev, EGLDisplay display, int fd);
#else
static int drm_setup_buffers(drm_dev_t * drm_dev);
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf);
static void drm_flush_wait(lv_display_t * drm_dev);
static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
static void drm_dmabuf_set_active_buf(lv_event_t * event);
#endif
static int drm_setup_buffers(drm_dev_t * drm_dev);
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf);
static void drm_flush_wait(lv_display_t * drm_dev);
static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
static void drm_dmabuf_set_active_buf(lv_event_t * event);
/**********************
* STATIC VARIABLES
@@ -198,7 +145,7 @@ lv_display_t * lv_linux_drm_create(void)
if(drm_dev == NULL) return NULL;
drm_dev->fd = -1;
#if !LV_LINUX_DRM_USE_EGL
disp = lv_display_create(800, 480);
if(disp == NULL) {
lv_free(drm_dev);
@@ -208,18 +155,9 @@ lv_display_t * lv_linux_drm_create(void)
lv_display_set_flush_wait_cb(disp, drm_flush_wait);
lv_display_set_flush_cb(disp, drm_flush);
#else /*LV_LINUX_DRM_USE_EGL*/
disp = (lv_display_t *) drm_dev;
drm_dev->kms_in_fence_fd = -1;
drm_dev->kms_out_fence_fd = -1;
#endif
return disp;
}
#if !LV_LINUX_DRM_USE_EGL
/* Called by LVGL when there is something that needs redrawing
* it sets the active buffer. if GBM buffers are used, it issues a DMA_BUF_SYNC
* ioctl call to lock the buffer for CPU access, the buffer is unlocked just
@@ -265,17 +203,12 @@ static void drm_dmabuf_set_active_buf(lv_event_t * event)
}
}
#endif /*!LV_LINUX_DRM_USE_EGL*/
void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t connector_id)
{
int ret;
#if !LV_LINUX_DRM_USE_EGL
drm_dev_t * drm_dev = lv_display_get_driver_data(disp);
#else
drm_dev_t * drm_dev = (drm_dev_t *) disp;
#endif
ret = drm_setup(drm_dev, file, connector_id, DRM_FOURCC);
if(ret) {
@@ -285,7 +218,6 @@ void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t conne
int32_t hor_res = drm_dev->width;
int32_t ver_res = drm_dev->height;
#if !LV_LINUX_DRM_USE_EGL
ret = drm_setup_buffers(drm_dev);
if(ret) {
LV_LOG_ERROR("DRM buffer allocation failed");
@@ -317,34 +249,6 @@ void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t conne
LV_LOG_INFO("Resolution is set to %" LV_PRId32 "x%" LV_PRId32 " at %" LV_PRId32 "dpi",
hor_res, ver_res, lv_display_get_dpi(disp));
#else /*LV_LINUX_DRM_USE_EGL*/
lv_opengles_window_t * window = lv_opengles_egl_window_create(hor_res, ver_res, drm_dev->surface, drm_dev->gbm_device,
drm_gbm_egl_pre, drm_gbm_egl_post1, drm_gbm_egl_post2);
lv_opengles_egl_window_set_user_data(window, drm_dev);
#if !USE_EGL_EXPERIMENTAL_DIRECT_WINDOW_RENDER
/* create a display that flushes to a texture */
lv_display_t * texture = lv_opengles_texture_create(hor_res, ver_res);
lv_display_set_default(texture);
#if LV_USE_DRAW_OPENGLES
lv_display_delete_refr_timer(texture);
#endif
/* add the texture to the window */
unsigned int texture_id = lv_opengles_texture_get_texture_id(texture);
lv_opengles_window_add_texture(window, texture_id, hor_res, ver_res);
#else
/* render directly to the window */
lv_opengles_window_display_create(window, hor_res, ver_res);
#endif
drm_dev->egl_wait_sync_khr = (egl_wait_sync_khr_t) eglGetProcAddress("eglWaitSyncKHR");
drm_dev->egl_dup_native_fence_fd_android = (egl_dup_native_fence_fd_android_t)
eglGetProcAddress("eglDupNativeFenceFDANDROID");
drm_dev->egl_create_sync_khr = (egl_create_sync_khr_t) eglGetProcAddress("eglCreateSyncKHR");
drm_dev->egl_destroy_sync_khr = (egl_destroy_sync_khr_t) eglGetProcAddress("eglDestroySyncKHR");
drm_dev->egl_client_wait_sync_khr = (egl_client_wait_sync_khr_t) eglGetProcAddress("eglClientWaitSyncKHR");
#endif
}
/**********************
@@ -531,14 +435,13 @@ static int drm_add_conn_property(drm_dev_t * drm_dev, const char * name, uint64_
return 0;
}
#if !LV_LINUX_DRM_USE_EGL
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf)
{
int ret;
static int first = 1;
uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
#if LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL
#if LV_USE_LINUX_DRM_GBM_BUFFERS
struct dma_buf_sync sync_req;
@@ -583,7 +486,6 @@ static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf)
return 0;
}
#endif /*!LV_LINUX_DRM_USE_EGL*/
static int find_plane(drm_dev_t * drm_dev, unsigned int fourcc, uint32_t * plane_id, uint32_t crtc_id,
uint32_t crtc_idx)
@@ -917,20 +819,6 @@ static int drm_setup(drm_dev_t * drm_dev, const char * device_path, int64_t conn
LV_LOG_INFO("GBM device backend: %s", gbm_device_get_backend_name(drm_dev->gbm_device));
#endif
#if LV_LINUX_DRM_USE_EGL
/* Add support to create a surface with modifiers */
drm_dev->surface = gbm_surface_create(drm_dev->gbm_device,
drm_dev->width, drm_dev->height, GBM_BO_FORMAT_ARGB8888,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if(!drm_dev->surface) {
LV_LOG_ERROR("failed to create gbm surface");
gbm_device_destroy(drm_dev->gbm_device);
goto err;
}
#endif
return 0;
err:
@@ -998,7 +886,7 @@ static int drm_allocate_dumb(drm_dev_t * drm_dev, drm_buffer_t * buf)
}
#endif /*!LV_USE_LINUX_DRM_GBM_BUFFERS*/
#if LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL
#if LV_USE_LINUX_DRM_GBM_BUFFERS
static int create_gbm_buffer(drm_dev_t * drm_dev, drm_buffer_t * buf)
{
@@ -1082,9 +970,8 @@ static int create_gbm_buffer(drm_dev_t * drm_dev, drm_buffer_t * buf)
}
#endif /* LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL*/
#endif /* LV_USE_LINUX_DRM_GBM_BUFFERS */
#if !LV_LINUX_DRM_USE_EGL
static int drm_setup_buffers(drm_dev_t * drm_dev)
{
int ret;
@@ -1159,204 +1046,6 @@ static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_
drm_dev->act_buf = NULL;
}
#endif /*!LV_LINUX_DRM_USE_EGL*/
#if LV_LINUX_DRM_USE_EGL
static void drm_gbm_egl_pre(lv_opengles_window_t * window)
{
drm_dev_t * drm_dev = lv_opengles_egl_window_get_user_data(window);
if(drm_dev->kms_out_fence_fd != -1) {
EGLDisplay display = lv_opengles_egl_window_get_display(window);
drm_dev->kms_fence = create_fence(drm_dev, display, drm_dev->kms_out_fence_fd);
LV_ASSERT_NULL(drm_dev->kms_fence);
drm_dev->kms_out_fence_fd = -1;
int result = drm_dev->egl_wait_sync_khr(display, drm_dev->kms_fence, 0);
LV_ASSERT(result == 1);
}
}
static void drm_gbm_egl_post1(lv_opengles_window_t * window)
{
drm_dev_t * drm_dev = lv_opengles_egl_window_get_user_data(window);
EGLDisplay display = lv_opengles_egl_window_get_display(window);
drm_dev->gpu_fence = create_fence(drm_dev, display, EGL_NO_NATIVE_FENCE_FD_ANDROID);
LV_ASSERT_NULL(drm_dev->gpu_fence);
}
static void drm_gbm_egl_post2(lv_opengles_window_t * window)
{
drm_dev_t * drm_dev = lv_opengles_egl_window_get_user_data(window);
EGLDisplay display = lv_opengles_egl_window_get_display(window);
drm_dev->kms_in_fence_fd = drm_dev->egl_dup_native_fence_fd_android(display, drm_dev->gpu_fence);
bool res = drm_dev->egl_destroy_sync_khr(display, drm_dev->gpu_fence);
LV_ASSERT(res);
drm_dev->gpu_fence = NULL;
LV_ASSERT(drm_dev->kms_in_fence_fd != -1);
drm_buffer_t * fb;
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
int ret;
/* Get the next bo to display */
struct gbm_bo * next_bo = gbm_surface_lock_front_buffer(drm_dev->surface);
if(!next_bo) {
LV_LOG_ERROR("Failed to lock frontbuffer");
}
fb = drm_fb_get_from_bo(next_bo);
if(!fb) {
LV_LOG_ERROR("Failed to get a new framebuffer BO");
}
if(drm_dev->kms_fence) {
EGLint status;
do {
status = drm_dev->egl_client_wait_sync_khr(display,
drm_dev->kms_fence,
0,
EGL_FOREVER_KHR);
} while(status != EGL_CONDITION_SATISFIED_KHR);
bool res = drm_dev->egl_destroy_sync_khr(display, drm_dev->kms_fence);
LV_ASSERT(res);
drm_dev->kms_fence = NULL;
}
ret = drm_atomic_commit(drm_dev, fb->fb_id, flags);
if(ret) {
LV_LOG_ERROR("failed to commit: %s", strerror(errno));
}
/* release last buffer to render on again: */
if(drm_dev->bo)
gbm_surface_release_buffer(drm_dev->surface, drm_dev->bo);
drm_dev->bo = next_bo;
}
static drm_buffer_t * drm_fb_get_from_bo(struct gbm_bo * bo)
{
int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo));
drm_buffer_t * fb = gbm_bo_get_user_data(bo);
uint32_t width, height, format, strides[4] = {0}, handles[4] = {0}, offsets[4] = {0};
int ret = -1;
if(fb)
return fb;
fb = lv_malloc_zeroed(sizeof(drm_buffer_t));
width = gbm_bo_get_width(bo);
height = gbm_bo_get_height(bo);
format = gbm_bo_get_format(bo);
const int num_planes = gbm_bo_get_plane_count(bo);
for(int i = 0; i < num_planes; i++) {
handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
strides[i] = gbm_bo_get_stride_for_plane(bo, i);
offsets[i] = gbm_bo_get_offset(bo, i);
}
memcpy(handles, (uint32_t [4]) {
gbm_bo_get_handle(bo).u32, 0, 0, 0
}, 16);
memcpy(strides, (uint32_t [4]) {
gbm_bo_get_stride(bo), 0, 0, 0
}, 16);
memset(offsets, 0, 16);
ret = drmModeAddFB2(drm_fd, width, height, format,
handles, strides, offsets, &fb->fb_id, 0);
fb->fb_handle = fb->fb_id;
if(ret) {
LV_LOG_ERROR("failed to create fb: %s", strerror(errno));
lv_free(fb);
return NULL;
}
gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
return fb;
}
static void drm_fb_destroy_callback(struct gbm_bo * bo, void * data)
{
int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo));
drm_buffer_t * fb = data;
if(fb->fb_id)
drmModeRmFB(drm_fd, fb->fb_id);
lv_free(fb);
}
static int drm_atomic_commit(drm_dev_t * drm_dev, uint32_t fb_id, uint32_t flags)
{
int ret;
static int first = 1;
drm_dev->req = drmModeAtomicAlloc();
/* On first Atomic commit, do a modeset */
if(first) {
drm_add_conn_property(drm_dev, "CRTC_ID", drm_dev->crtc_id);
drm_add_crtc_property(drm_dev, "MODE_ID", drm_dev->blob_id);
drm_add_crtc_property(drm_dev, "ACTIVE", 1);
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
first = 0;
}
drm_add_plane_property(drm_dev, "FB_ID", fb_id);
drm_add_plane_property(drm_dev, "CRTC_ID", drm_dev->crtc_id);
drm_add_plane_property(drm_dev, "SRC_X", 0);
drm_add_plane_property(drm_dev, "SRC_Y", 0);
drm_add_plane_property(drm_dev, "SRC_W", drm_dev->width << 16);
drm_add_plane_property(drm_dev, "SRC_H", drm_dev->height << 16);
drm_add_plane_property(drm_dev, "CRTC_X", 0);
drm_add_plane_property(drm_dev, "CRTC_Y", 0);
drm_add_plane_property(drm_dev, "CRTC_W", drm_dev->width);
drm_add_plane_property(drm_dev, "CRTC_H", drm_dev->height);
if(drm_dev->kms_in_fence_fd != -1) {
drm_add_crtc_property(drm_dev, "OUT_FENCE_PTR", (uintptr_t) &drm_dev->kms_out_fence_fd);
drm_add_plane_property(drm_dev, "IN_FENCE_FD", drm_dev->kms_in_fence_fd);
}
ret = drmModeAtomicCommit(drm_dev->fd, drm_dev->req, flags, NULL);
if(ret) {
LV_LOG_ERROR("drmModeAtomicCommit failed: %s (%d)", strerror(errno), errno);
drmModeAtomicFree(drm_dev->req);
return ret;
}
if(drm_dev->kms_in_fence_fd != -1) {
close(drm_dev->kms_in_fence_fd);
drm_dev->kms_in_fence_fd = -1;
}
return 0;
}
static EGLSyncKHR create_fence(drm_dev_t * drm_dev, EGLDisplay display, int fd)
{
EGLint attrib_list[] = {
EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd,
EGL_NONE,
};
EGLSyncKHR fence = drm_dev->egl_create_sync_khr(display, EGL_SYNC_NATIVE_FENCE_ANDROID, attrib_list);
LV_ASSERT_NULL(fence);
return fence;
}
#endif /*LV_LINUX_DRM_USE_EGL*/
static uint32_t tick_get_cb(void)
{
@@ -1366,4 +1055,4 @@ static uint32_t tick_get_cb(void)
return time_ms;
}
#endif /*LV_USE_LINUX_DRM*/
#endif /*LV_USE_LINUX_DRM && !LV_LINUX_DRM_USE_EGL*/
+31
View File
@@ -29,10 +29,41 @@ extern "C" {
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* @brief Create a new Linux DRM display
*
* Creates and initializes a new LVGL display using the Linux DRM (Direct Rendering Manager)
* subsystem for hardware-accelerated graphics output.
*
* @return Pointer to the created display object, or NULL on failure
*/
lv_display_t * lv_linux_drm_create(void);
/**
* @brief Configure the DRM device file and connector for a display
*
* Sets the DRM device file path and connector ID to use for the specified display.
* The DRM device file is typically located at /dev/dri/cardN where N is the card number.
* The connector ID specifies which physical output (HDMI, VGA, etc.) to use.
*
* @param disp Pointer to the display object created with lv_linux_drm_create()
* @param file Path to the DRM device file (e.g., "/dev/dri/card0")
* @param connector_id ID of the DRM connector to use, or -1 to auto-select the first available
*/
void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t connector_id);
/**
* @brief Automatically find a suitable DRM device path
*
* Scans the system for available DRM devices and returns the path to a suitable
* device file that can be used with lv_linux_drm_set_file().
*
* @return Dynamically allocated string containing the device path (must be freed with lv_free()),
* or NULL if no suitable device is found
*/
char * lv_linux_drm_find_device_path(void);
/**********************
* MACROS
**********************/
@@ -0,0 +1,95 @@
/**
* @file lv_linux_drm_common.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_linux_drm.h"
#if LV_USE_LINUX_DRM
#include <dirent.h>
#include "lv_linux_drm.h"
#include "../../../stdlib/lv_sprintf.h"
/*********************
* DEFINES
*********************/
#define LV_DRM_CLASS_DIR "/sys/class/drm"
#define LV_DRM_CARD_PATH "/dev/dri/card"
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static char * find_by_class(void);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
char * lv_linux_drm_find_device_path(void)
{
return find_by_class();
}
/**********************
* STATIC FUNCTIONS
**********************/
static char * find_by_class(void)
{
DIR * d = opendir(LV_DRM_CLASS_DIR);
if(!d) {
return NULL;
}
struct dirent * ent;
while((ent = readdir(d)) != NULL) {
if(lv_strcmp(ent->d_name, ".") == 0 || lv_strcmp(ent->d_name, "..") == 0) {
continue;
}
/* connector dirs look like card0-HDMI-A-1, card0-eDP-1, etc. */
bool is_card = lv_strncmp(ent->d_name, "card", 4) == 0;
bool is_connected = lv_strchr(ent->d_name, '-') != NULL;
if(!is_card || !is_connected) {
continue;
}
const size_t buf_size = lv_strlen(LV_DRM_CARD_PATH) + 3;
char * card_path = lv_zalloc(buf_size);
if(ent->d_name[5] != '-') {
/* Double digit card*/
lv_snprintf(card_path, buf_size, LV_DRM_CARD_PATH "%c%c", ent->d_name[4], ent->d_name[5]);
}
else {
lv_snprintf(card_path, buf_size, LV_DRM_CARD_PATH "%c", ent->d_name[4]);
}
closedir(d);
return card_path;
}
closedir(d);
return NULL;
}
#endif /*LV_USE_LINUX_DRM*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,74 @@
/**
* @file lv_linux_drm_egl_private.h
*
*/
#ifndef LV_LINUX_DRM_EGL_PRIVATE_H
#define LV_LINUX_DRM_EGL_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_LINUX_DRM && LV_LINUX_DRM_USE_EGL
#include <xf86drmMode.h>
#include "../../opengles/lv_opengles_texture_private.h"
#include "../../opengles/lv_opengles_egl.h"
#include "../../opengles/lv_opengles_egl_private.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_opengles_texture_t texture;
lv_display_t * display;
lv_opengles_egl_t * egl_ctx;
lv_egl_interface_t egl_interface;
drmModeRes * drm_resources;
drmModeConnector * drm_connector;
drmModeEncoder * drm_encoder;
drmModeCrtc * drm_crtc;
drmModeModeInfo * drm_mode;
struct gbm_device * gbm_dev;
struct gbm_surface * gbm_surface;
struct gbm_bo * gbm_bo_pending;
struct gbm_bo * gbm_bo_flipped;
struct gbm_bo * gbm_bo_presented;
int fd;
bool crtc_isset;
} lv_drm_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#endif /*LV_USE_LINUX_DRM && LV_LINUX_DRM_USE_EGL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_LINUX_DRM_EGL_PRIVATE_H*/
@@ -6,40 +6,28 @@
#include <string.h>
static const lv_opengl_shader_t src_includes[] = {
{ "hsv_adjust.glsl", R"(
{
"hsv_adjust.glsl", R"(
uniform float u_Hue;
uniform float u_Saturation;
uniform float u_Value;
vec3 rgb2hsv(vec3 c){
float M = max(max(c.r,c.g),c.b);
float m = min(min(c.r,c.g),c.b);
float d = M - m;
float h = 0.0;
if(d > 0.00001){
if(M == c.r) h = mod((c.g - c.b)/d, 6.0);
else if(M == c.g) h = (c.b - c.r)/d + 2.0;
else h = (c.r - c.g)/d + 4.0;
h /= 6.0;
}
float s = (M <= 0.00001) ? 0.0 : d / M;
return vec3(h, s, M);
// Convert RGB to HSV
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c){
float h = c.x * 6.0;
float i = floor(h);
float f = h - i;
float p = c.z * (1.0 - c.y);
float q = c.z * (1.0 - c.y * f);
float t = c.z * (1.0 - c.y * (1.0 - f));
if(i == 0.0) return vec3(c.z, t, p);
if(i == 1.0) return vec3(q, c.z, p);
if(i == 2.0) return vec3(p, c.z, t);
if(i == 3.0) return vec3(p, q, c.z);
if(i == 4.0) return vec3(t, p, c.z);
return vec3(c.z, p, q);
// Convert HSV to RGB
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
vec3 adjustHSV(vec3 color){
@@ -49,23 +37,28 @@ static const lv_opengl_shader_t src_includes[] = {
hsv.z = clamp(hsv.z * u_Value, 0.0, 1.0);
return hsv2rgb(hsv);
}
)" },
{ "brightness_adjust.glsl", R"(
)"
},
{
"brightness_adjust.glsl", R"(
uniform float u_Brightness; // add/subtract in [ -1.0 .. +1.0 ], 0.0 = no change
vec3 adjustBrightness(vec3 color){
return clamp(color + vec3(u_Brightness), 0.0, 1.0);
}
)" },
{ "contrast_adjust.glsl", R"(
)"
},
{
"contrast_adjust.glsl", R"(
uniform float u_Contrast; // 0.0 = mid-gray, 1.0 = no change, >1.0 increases contrast
vec3 adjustContrast(vec3 color){
// shift to [-0.5..0.5], scale, shift back
return clamp(((color - 0.5) * u_Contrast) + 0.5, 0.0, 1.0);
}
)" },
)"
},
};
static const char * src_vertex_shader = R"(
@@ -98,13 +91,18 @@ static const char *src_fragment_shader = R"(
uniform bool u_IsFill;
uniform vec3 u_FillColor;
#ifdef HSV_ADJUST
#include <hsv_adjust.glsl>
#endif
void main()
{
vec4 texColor;
if (u_IsFill) {
texColor = vec4(u_FillColor, 1.0);
} else {
texColor = texture(u_Texture, v_TexCoord);
//texColor = texture(u_Texture, v_TexCoord);
texColor = textureLod(u_Texture, v_TexCoord, 0.0); // If the vertices have been transformed, and mipmaps have not been generated, some rotation angles (notably 90 and 270) require using textureLod() to mitigate derivative calculation errors from increments flipping direction
}
if (abs(u_ColorDepth - 8.0) < 0.1) {
float gray = texColor.r;
@@ -113,6 +111,9 @@ static const char *src_fragment_shader = R"(
float combinedAlpha = texColor.a * u_Opa;
color = vec4(texColor.rgb * combinedAlpha, combinedAlpha);
}
#ifdef HSV_ADJUST
color.rgb = adjustHSV(color.rgb);
#endif
}
)";
@@ -132,8 +133,8 @@ char* lv_opengles_standard_shader_get_fragment(void) {
void lv_opengles_standard_shader_get_src(lv_opengl_shader_portions_t *portions)
{
portions->all = src_includes;
portions->count = sizeof(src_includes) / sizeof(src_includes[0]);
portions->all = src_includes;
portions->count = sizeof(src_includes) / sizeof(src_includes[0]);
}
#endif /*LV_USE_OPENGLES*/
+5
View File
@@ -0,0 +1,5 @@
# glad
GLAD source files are generated using GLAD's online generator.
[Permalink](https://gen.glad.sh/#generator=c&api=egl%3D1.5%2Cgles2%3D2.0&profile=gl%3Dcompatibility%2Cgles1%3Dcommon&extensions=EGL_EXT_image_dma_buf_import%2CEGL_EXT_image_dma_buf_import_modifiers%2CEGL_EXT_platform_base%2CEGL_EXT_platform_wayland%2CEGL_KHR_fence_sync%2CEGL_KHR_image_base%2CEGL_KHR_platform_gbm%2CEGL_KHR_platform_wayland%2CGL_APPLE_texture_max_level%2CGL_EXT_texture_format_BGRA8888%2CGL_EXT_unpack_subimage%2CGL_OES_mapbuffer%2CGL_OES_vertex_array_object)
@@ -0,0 +1,181 @@
#ifndef __eglplatform_h_
#define __eglplatform_h_
#include "../../../lv_opengles_egl.h"
#if LV_USE_EGL
/*
** Copyright 2007-2020 The Khronos Group Inc.
** SPDX-License-Identifier: Apache-2.0
*/
/* Platform-specific types and definitions for egl.h
*
* Adopters may modify khrplatform.h and this file to suit their platform.
* You are encouraged to submit all modifications to the Khronos group so that
* they can be included in future versions of this file. Please submit changes
* by filing an issue or pull request on the public Khronos EGL Registry, at
* https://www.github.com/KhronosGroup/EGL-Registry/
*/
#include <KHR/khrplatform.h>
/* Macros used in EGL function prototype declarations.
*
* EGL functions should be prototyped as:
*
* EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
* typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
*
* KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
*/
#ifndef EGLAPI
#define EGLAPI KHRONOS_APICALL
#endif
#ifndef EGLAPIENTRY
#define EGLAPIENTRY KHRONOS_APIENTRY
#endif
#define EGLAPIENTRYP EGLAPIENTRY*
/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
* are aliases of window-system-dependent types, such as X Display * or
* Windows Device Context. They must be defined in platform-specific
* code below. The EGL-prefixed versions of Native*Type are the same
* types, renamed in EGL 1.3 so all types in the API start with "EGL".
*
* Khronos STRONGLY RECOMMENDS that you use the default definitions
* provided below, since these changes affect both binary and source
* portability of applications using EGL running on different EGL
* implementations.
*/
#if defined(EGL_NO_PLATFORM_SPECIFIC_TYPES)
typedef void *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND EGLNativeWindowType;
#elif defined(__QNX__)
typedef khronos_uintptr_t EGLNativeDisplayType;
typedef struct _screen_pixmap* EGLNativePixmapType; /* screen_pixmap_t */
typedef struct _screen_window* EGLNativeWindowType; /* screen_window_t */
#elif defined(__EMSCRIPTEN__)
typedef int EGLNativeDisplayType;
typedef int EGLNativePixmapType;
typedef int EGLNativeWindowType;
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
typedef int EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(WL_EGL_PLATFORM)
typedef struct wl_display *EGLNativeDisplayType;
typedef struct wl_egl_pixmap *EGLNativePixmapType;
typedef struct wl_egl_window *EGLNativeWindowType;
#elif defined(__GBM__)
typedef struct gbm_device *EGLNativeDisplayType;
typedef struct gbm_bo *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(__ANDROID__) || defined(ANDROID)
struct ANativeWindow;
struct egl_native_pixmap_t;
typedef void* EGLNativeDisplayType;
typedef struct egl_native_pixmap_t* EGLNativePixmapType;
typedef struct ANativeWindow* EGLNativeWindowType;
#elif defined(USE_OZONE)
typedef intptr_t EGLNativeDisplayType;
typedef intptr_t EGLNativePixmapType;
typedef intptr_t EGLNativeWindowType;
#elif defined(USE_X11)
/* X11 (tentative) */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
typedef Display *EGLNativeDisplayType;
typedef Pixmap EGLNativePixmapType;
typedef Window EGLNativeWindowType;
#elif defined(__unix__)
typedef void *EGLNativeDisplayType;
typedef khronos_uintptr_t EGLNativePixmapType;
typedef khronos_uintptr_t EGLNativeWindowType;
#elif defined(__APPLE__)
typedef int EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(__HAIKU__)
#include <kernel/image.h>
typedef void *EGLNativeDisplayType;
typedef khronos_uintptr_t EGLNativePixmapType;
typedef khronos_uintptr_t EGLNativeWindowType;
#elif defined(__Fuchsia__)
typedef void *EGLNativeDisplayType;
typedef khronos_uintptr_t EGLNativePixmapType;
typedef khronos_uintptr_t EGLNativeWindowType;
#else
#error "Platform not recognized"
#endif
/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
typedef EGLNativeDisplayType NativeDisplayType;
typedef EGLNativePixmapType NativePixmapType;
typedef EGLNativeWindowType NativeWindowType;
/* Define EGLint. This must be a signed integral type large enough to contain
* all legal attribute names and values passed into and out of EGL, whether
* their type is boolean, bitmask, enumerant (symbolic constant), integer,
* handle, or other. While in general a 32-bit integer will suffice, if
* handles are 64 bit types, then EGLint should be defined as a signed 64-bit
* integer type.
*/
typedef khronos_int32_t EGLint;
/* C++ / C typecast macros for special EGL handle values */
#if defined(__cplusplus)
#define EGL_CAST(type, value) (static_cast<type>(value))
#else
#define EGL_CAST(type, value) ((type) (value))
#endif
#endif /*LV_USE_EGL*/
#endif /* __eglplatform_h */
@@ -0,0 +1,317 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
#include "../../../lv_opengles_egl.h"
#if LV_USE_EGL
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */
#endif /*LV_USE_EGL*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+333
View File
@@ -0,0 +1,333 @@
/**
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
*/
#include "../../lv_opengles_egl.h"
#if LV_USE_EGL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../include/glad/egl.h"
#ifndef GLAD_IMPL_UTIL_C_
#define GLAD_IMPL_UTIL_C_
#ifdef _MSC_VER
#define GLAD_IMPL_UTIL_SSCANF sscanf_s
#else
#define GLAD_IMPL_UTIL_SSCANF sscanf
#endif
#endif /* GLAD_IMPL_UTIL_C_ */
#ifdef __cplusplus
extern "C" {
#endif
int GLAD_EGL_VERSION_1_0 = 0;
int GLAD_EGL_VERSION_1_1 = 0;
int GLAD_EGL_VERSION_1_2 = 0;
int GLAD_EGL_VERSION_1_3 = 0;
int GLAD_EGL_VERSION_1_4 = 0;
int GLAD_EGL_VERSION_1_5 = 0;
int GLAD_EGL_EXT_image_dma_buf_import = 0;
int GLAD_EGL_EXT_image_dma_buf_import_modifiers = 0;
int GLAD_EGL_EXT_platform_base = 0;
int GLAD_EGL_EXT_platform_wayland = 0;
int GLAD_EGL_KHR_fence_sync = 0;
int GLAD_EGL_KHR_image_base = 0;
int GLAD_EGL_KHR_platform_gbm = 0;
int GLAD_EGL_KHR_platform_wayland = 0;
PFNEGLBINDAPIPROC glad_eglBindAPI = NULL;
PFNEGLBINDTEXIMAGEPROC glad_eglBindTexImage = NULL;
PFNEGLCHOOSECONFIGPROC glad_eglChooseConfig = NULL;
PFNEGLCLIENTWAITSYNCPROC glad_eglClientWaitSync = NULL;
PFNEGLCLIENTWAITSYNCKHRPROC glad_eglClientWaitSyncKHR = NULL;
PFNEGLCOPYBUFFERSPROC glad_eglCopyBuffers = NULL;
PFNEGLCREATECONTEXTPROC glad_eglCreateContext = NULL;
PFNEGLCREATEIMAGEPROC glad_eglCreateImage = NULL;
PFNEGLCREATEIMAGEKHRPROC glad_eglCreateImageKHR = NULL;
PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC glad_eglCreatePbufferFromClientBuffer = NULL;
PFNEGLCREATEPBUFFERSURFACEPROC glad_eglCreatePbufferSurface = NULL;
PFNEGLCREATEPIXMAPSURFACEPROC glad_eglCreatePixmapSurface = NULL;
PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC glad_eglCreatePlatformPixmapSurface = NULL;
PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC glad_eglCreatePlatformPixmapSurfaceEXT = NULL;
PFNEGLCREATEPLATFORMWINDOWSURFACEPROC glad_eglCreatePlatformWindowSurface = NULL;
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC glad_eglCreatePlatformWindowSurfaceEXT = NULL;
PFNEGLCREATESYNCPROC glad_eglCreateSync = NULL;
PFNEGLCREATESYNCKHRPROC glad_eglCreateSyncKHR = NULL;
PFNEGLCREATEWINDOWSURFACEPROC glad_eglCreateWindowSurface = NULL;
PFNEGLDESTROYCONTEXTPROC glad_eglDestroyContext = NULL;
PFNEGLDESTROYIMAGEPROC glad_eglDestroyImage = NULL;
PFNEGLDESTROYIMAGEKHRPROC glad_eglDestroyImageKHR = NULL;
PFNEGLDESTROYSURFACEPROC glad_eglDestroySurface = NULL;
PFNEGLDESTROYSYNCPROC glad_eglDestroySync = NULL;
PFNEGLDESTROYSYNCKHRPROC glad_eglDestroySyncKHR = NULL;
PFNEGLGETCONFIGATTRIBPROC glad_eglGetConfigAttrib = NULL;
PFNEGLGETCONFIGSPROC glad_eglGetConfigs = NULL;
PFNEGLGETCURRENTCONTEXTPROC glad_eglGetCurrentContext = NULL;
PFNEGLGETCURRENTDISPLAYPROC glad_eglGetCurrentDisplay = NULL;
PFNEGLGETCURRENTSURFACEPROC glad_eglGetCurrentSurface = NULL;
PFNEGLGETDISPLAYPROC glad_eglGetDisplay = NULL;
PFNEGLGETERRORPROC glad_eglGetError = NULL;
PFNEGLGETPLATFORMDISPLAYPROC glad_eglGetPlatformDisplay = NULL;
PFNEGLGETPLATFORMDISPLAYEXTPROC glad_eglGetPlatformDisplayEXT = NULL;
PFNEGLGETPROCADDRESSPROC glad_eglGetProcAddress = NULL;
PFNEGLGETSYNCATTRIBPROC glad_eglGetSyncAttrib = NULL;
PFNEGLGETSYNCATTRIBKHRPROC glad_eglGetSyncAttribKHR = NULL;
PFNEGLINITIALIZEPROC glad_eglInitialize = NULL;
PFNEGLMAKECURRENTPROC glad_eglMakeCurrent = NULL;
PFNEGLQUERYAPIPROC glad_eglQueryAPI = NULL;
PFNEGLQUERYCONTEXTPROC glad_eglQueryContext = NULL;
PFNEGLQUERYDMABUFFORMATSEXTPROC glad_eglQueryDmaBufFormatsEXT = NULL;
PFNEGLQUERYDMABUFMODIFIERSEXTPROC glad_eglQueryDmaBufModifiersEXT = NULL;
PFNEGLQUERYSTRINGPROC glad_eglQueryString = NULL;
PFNEGLQUERYSURFACEPROC glad_eglQuerySurface = NULL;
PFNEGLRELEASETEXIMAGEPROC glad_eglReleaseTexImage = NULL;
PFNEGLRELEASETHREADPROC glad_eglReleaseThread = NULL;
PFNEGLSURFACEATTRIBPROC glad_eglSurfaceAttrib = NULL;
PFNEGLSWAPBUFFERSPROC glad_eglSwapBuffers = NULL;
PFNEGLSWAPINTERVALPROC glad_eglSwapInterval = NULL;
PFNEGLTERMINATEPROC glad_eglTerminate = NULL;
PFNEGLWAITCLIENTPROC glad_eglWaitClient = NULL;
PFNEGLWAITGLPROC glad_eglWaitGL = NULL;
PFNEGLWAITNATIVEPROC glad_eglWaitNative = NULL;
PFNEGLWAITSYNCPROC glad_eglWaitSync = NULL;
static void glad_egl_load_EGL_VERSION_1_0(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_VERSION_1_0) return;
glad_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) load(userptr, "eglChooseConfig");
glad_eglCopyBuffers = (PFNEGLCOPYBUFFERSPROC) load(userptr, "eglCopyBuffers");
glad_eglCreateContext = (PFNEGLCREATECONTEXTPROC) load(userptr, "eglCreateContext");
glad_eglCreatePbufferSurface = (PFNEGLCREATEPBUFFERSURFACEPROC) load(userptr, "eglCreatePbufferSurface");
glad_eglCreatePixmapSurface = (PFNEGLCREATEPIXMAPSURFACEPROC) load(userptr, "eglCreatePixmapSurface");
glad_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) load(userptr, "eglCreateWindowSurface");
glad_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) load(userptr, "eglDestroyContext");
glad_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) load(userptr, "eglDestroySurface");
glad_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) load(userptr, "eglGetConfigAttrib");
glad_eglGetConfigs = (PFNEGLGETCONFIGSPROC) load(userptr, "eglGetConfigs");
glad_eglGetCurrentDisplay = (PFNEGLGETCURRENTDISPLAYPROC) load(userptr, "eglGetCurrentDisplay");
glad_eglGetCurrentSurface = (PFNEGLGETCURRENTSURFACEPROC) load(userptr, "eglGetCurrentSurface");
glad_eglGetDisplay = (PFNEGLGETDISPLAYPROC) load(userptr, "eglGetDisplay");
glad_eglGetError = (PFNEGLGETERRORPROC) load(userptr, "eglGetError");
glad_eglGetProcAddress = (PFNEGLGETPROCADDRESSPROC) load(userptr, "eglGetProcAddress");
glad_eglInitialize = (PFNEGLINITIALIZEPROC) load(userptr, "eglInitialize");
glad_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) load(userptr, "eglMakeCurrent");
glad_eglQueryContext = (PFNEGLQUERYCONTEXTPROC) load(userptr, "eglQueryContext");
glad_eglQueryString = (PFNEGLQUERYSTRINGPROC) load(userptr, "eglQueryString");
glad_eglQuerySurface = (PFNEGLQUERYSURFACEPROC) load(userptr, "eglQuerySurface");
glad_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) load(userptr, "eglSwapBuffers");
glad_eglTerminate = (PFNEGLTERMINATEPROC) load(userptr, "eglTerminate");
glad_eglWaitGL = (PFNEGLWAITGLPROC) load(userptr, "eglWaitGL");
glad_eglWaitNative = (PFNEGLWAITNATIVEPROC) load(userptr, "eglWaitNative");
}
static void glad_egl_load_EGL_VERSION_1_1(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_VERSION_1_1) return;
glad_eglBindTexImage = (PFNEGLBINDTEXIMAGEPROC) load(userptr, "eglBindTexImage");
glad_eglReleaseTexImage = (PFNEGLRELEASETEXIMAGEPROC) load(userptr, "eglReleaseTexImage");
glad_eglSurfaceAttrib = (PFNEGLSURFACEATTRIBPROC) load(userptr, "eglSurfaceAttrib");
glad_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) load(userptr, "eglSwapInterval");
}
static void glad_egl_load_EGL_VERSION_1_2(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_VERSION_1_2) return;
glad_eglBindAPI = (PFNEGLBINDAPIPROC) load(userptr, "eglBindAPI");
glad_eglCreatePbufferFromClientBuffer = (PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC) load(userptr,
"eglCreatePbufferFromClientBuffer");
glad_eglQueryAPI = (PFNEGLQUERYAPIPROC) load(userptr, "eglQueryAPI");
glad_eglReleaseThread = (PFNEGLRELEASETHREADPROC) load(userptr, "eglReleaseThread");
glad_eglWaitClient = (PFNEGLWAITCLIENTPROC) load(userptr, "eglWaitClient");
}
static void glad_egl_load_EGL_VERSION_1_4(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_VERSION_1_4) return;
glad_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) load(userptr, "eglGetCurrentContext");
}
static void glad_egl_load_EGL_VERSION_1_5(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_VERSION_1_5) return;
glad_eglClientWaitSync = (PFNEGLCLIENTWAITSYNCPROC) load(userptr, "eglClientWaitSync");
glad_eglCreateImage = (PFNEGLCREATEIMAGEPROC) load(userptr, "eglCreateImage");
glad_eglCreatePlatformPixmapSurface = (PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC) load(userptr,
"eglCreatePlatformPixmapSurface");
glad_eglCreatePlatformWindowSurface = (PFNEGLCREATEPLATFORMWINDOWSURFACEPROC) load(userptr,
"eglCreatePlatformWindowSurface");
glad_eglCreateSync = (PFNEGLCREATESYNCPROC) load(userptr, "eglCreateSync");
glad_eglDestroyImage = (PFNEGLDESTROYIMAGEPROC) load(userptr, "eglDestroyImage");
glad_eglDestroySync = (PFNEGLDESTROYSYNCPROC) load(userptr, "eglDestroySync");
glad_eglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYPROC) load(userptr, "eglGetPlatformDisplay");
glad_eglGetSyncAttrib = (PFNEGLGETSYNCATTRIBPROC) load(userptr, "eglGetSyncAttrib");
glad_eglWaitSync = (PFNEGLWAITSYNCPROC) load(userptr, "eglWaitSync");
}
static void glad_egl_load_EGL_EXT_image_dma_buf_import_modifiers(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_EXT_image_dma_buf_import_modifiers) return;
glad_eglQueryDmaBufFormatsEXT = (PFNEGLQUERYDMABUFFORMATSEXTPROC) load(userptr, "eglQueryDmaBufFormatsEXT");
glad_eglQueryDmaBufModifiersEXT = (PFNEGLQUERYDMABUFMODIFIERSEXTPROC) load(userptr, "eglQueryDmaBufModifiersEXT");
}
static void glad_egl_load_EGL_EXT_platform_base(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_EXT_platform_base) return;
glad_eglCreatePlatformPixmapSurfaceEXT = (PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) load(userptr,
"eglCreatePlatformPixmapSurfaceEXT");
glad_eglCreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) load(userptr,
"eglCreatePlatformWindowSurfaceEXT");
glad_eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC) load(userptr, "eglGetPlatformDisplayEXT");
}
static void glad_egl_load_EGL_KHR_fence_sync(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_KHR_fence_sync) return;
glad_eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC) load(userptr, "eglClientWaitSyncKHR");
glad_eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) load(userptr, "eglCreateSyncKHR");
glad_eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) load(userptr, "eglDestroySyncKHR");
glad_eglGetSyncAttribKHR = (PFNEGLGETSYNCATTRIBKHRPROC) load(userptr, "eglGetSyncAttribKHR");
}
static void glad_egl_load_EGL_KHR_image_base(GLADuserptrloadfunc load, void * userptr)
{
if(!GLAD_EGL_KHR_image_base) return;
glad_eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) load(userptr, "eglCreateImageKHR");
glad_eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) load(userptr, "eglDestroyImageKHR");
}
static int glad_egl_get_extensions(EGLDisplay display, const char ** extensions)
{
*extensions = eglQueryString(display, EGL_EXTENSIONS);
return extensions != NULL;
}
static int glad_egl_has_extension(const char * extensions, const char * ext)
{
const char * loc;
const char * terminator;
if(extensions == NULL) {
return 0;
}
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL) {
return 0;
}
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\0')) {
return 1;
}
extensions = terminator;
}
}
static GLADapiproc glad_egl_get_proc_from_userptr(void * userptr, const char * name)
{
return (GLAD_GNUC_EXTENSION(GLADapiproc(*)(const char * name)) userptr)(name);
}
static int glad_egl_find_extensions_egl(EGLDisplay display)
{
const char * extensions;
if(!glad_egl_get_extensions(display, &extensions)) return 0;
GLAD_EGL_EXT_image_dma_buf_import = glad_egl_has_extension(extensions, "EGL_EXT_image_dma_buf_import");
GLAD_EGL_EXT_image_dma_buf_import_modifiers = glad_egl_has_extension(extensions,
"EGL_EXT_image_dma_buf_import_modifiers");
GLAD_EGL_EXT_platform_base = glad_egl_has_extension(extensions, "EGL_EXT_platform_base");
GLAD_EGL_EXT_platform_wayland = glad_egl_has_extension(extensions, "EGL_EXT_platform_wayland");
GLAD_EGL_KHR_fence_sync = glad_egl_has_extension(extensions, "EGL_KHR_fence_sync");
GLAD_EGL_KHR_image_base = glad_egl_has_extension(extensions, "EGL_KHR_image_base");
GLAD_EGL_KHR_platform_gbm = glad_egl_has_extension(extensions, "EGL_KHR_platform_gbm");
GLAD_EGL_KHR_platform_wayland = glad_egl_has_extension(extensions, "EGL_KHR_platform_wayland");
return 1;
}
static int glad_egl_find_core_egl(EGLDisplay display)
{
int major, minor;
const char * version;
if(display == NULL) {
display = EGL_NO_DISPLAY; /* this is usually NULL, better safe than sorry */
}
if(display == EGL_NO_DISPLAY) {
display = eglGetCurrentDisplay();
}
#ifdef EGL_VERSION_1_4
if(display == EGL_NO_DISPLAY) {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
#endif
#ifndef EGL_VERSION_1_5
if(display == EGL_NO_DISPLAY) {
return 0;
}
#endif
version = eglQueryString(display, EGL_VERSION);
(void) eglGetError();
if(version == NULL) {
major = 1;
minor = 0;
}
else {
GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
}
GLAD_EGL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
GLAD_EGL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
GLAD_EGL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
GLAD_EGL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
GLAD_EGL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
GLAD_EGL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
return GLAD_MAKE_VERSION(major, minor);
}
int gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void * userptr)
{
int version;
eglGetDisplay = (PFNEGLGETDISPLAYPROC) load(userptr, "eglGetDisplay");
eglGetCurrentDisplay = (PFNEGLGETCURRENTDISPLAYPROC) load(userptr, "eglGetCurrentDisplay");
eglQueryString = (PFNEGLQUERYSTRINGPROC) load(userptr, "eglQueryString");
eglGetError = (PFNEGLGETERRORPROC) load(userptr, "eglGetError");
if(eglGetDisplay == NULL || eglGetCurrentDisplay == NULL || eglQueryString == NULL || eglGetError == NULL) return 0;
version = glad_egl_find_core_egl(display);
if(!version) return 0;
glad_egl_load_EGL_VERSION_1_0(load, userptr);
glad_egl_load_EGL_VERSION_1_1(load, userptr);
glad_egl_load_EGL_VERSION_1_2(load, userptr);
glad_egl_load_EGL_VERSION_1_4(load, userptr);
glad_egl_load_EGL_VERSION_1_5(load, userptr);
if(!glad_egl_find_extensions_egl(display)) return 0;
glad_egl_load_EGL_EXT_image_dma_buf_import_modifiers(load, userptr);
glad_egl_load_EGL_EXT_platform_base(load, userptr);
glad_egl_load_EGL_KHR_fence_sync(load, userptr);
glad_egl_load_EGL_KHR_image_base(load, userptr);
return version;
}
int gladLoadEGL(EGLDisplay display, GLADloadfunc load)
{
return gladLoadEGLUserPtr(display, glad_egl_get_proc_from_userptr, GLAD_GNUC_EXTENSION(void *) load);
}
#ifdef __cplusplus
}
#endif
#endif /*LV_USE_EGL*/
File diff suppressed because it is too large Load Diff
+136 -6
View File
@@ -64,6 +64,9 @@ 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);
static void populate_vertex_buffer(float vertex_buffer[LV_OPENGLES_VERTEX_BUFFER_LEN],
lv_display_rotation_t rotation, bool * h_flip, bool * v_flip,
float clip_x1, float clip_y1, float clip_x2, float clip_y2);
/***********************
* GLOBAL PROTOTYPES
@@ -85,8 +88,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", "u_IsFill", "u_FillColor" };
static int shader_location[] = { 0, 0, 0, 0, 0, 0 };
static const char * shader_names[] = { "u_Texture", "u_ColorDepth", "u_VertexTransform", "u_Opa", "u_IsFill", "u_FillColor", "u_Hue", "u_Saturation", "u_Value" };
static int shader_location[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/**********************
* MACROS
@@ -154,6 +157,44 @@ void lv_opengles_render_fill(lv_color_t color, const lv_area_t * area, lv_opa_t
LV_PROFILER_DRAW_END;
}
void lv_opengles_render_display_texture(lv_display_t * display, bool h_flip, bool v_flip)
{
LV_PROFILER_DRAW_BEGIN;
unsigned int texture = *(unsigned int *)lv_display_get_driver_data(display);
GL_CALL(glActiveTexture(GL_TEXTURE0));
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture));
lv_display_rotation_t rotation = lv_display_get_rotation(display);
float vert_buffer[LV_OPENGLES_VERTEX_BUFFER_LEN];
populate_vertex_buffer(vert_buffer, rotation, &h_flip, &v_flip, 0.f, 0.f, 1.f, 1.f);
lv_opengles_vertex_buffer_init(vert_buffer, sizeof(vert_buffer));
float hor_scale = 1.0f;
float ver_scale = 1.0f;
float hor_translate = 0.0f;
float ver_translate = 0.0f;
hor_scale = h_flip ? -hor_scale : hor_scale;
ver_scale = v_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
};
lv_opengles_shader_bind();
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, true, matrix);
lv_opengles_shader_set_uniform1f("u_Opa", 1);
lv_opengles_shader_set_uniform1i("u_IsFill", 0);
lv_opengles_shader_set_uniform3f("u_FillColor", 1.0f, 1.0f, 1.0f);
lv_opengles_render_draw();
LV_PROFILER_DRAW_END;
}
void lv_opengles_render_clear(void)
{
LV_PROFILER_DRAW_BEGIN;
@@ -341,14 +382,10 @@ static void lv_opengles_shader_manager_init(void)
static unsigned int lv_opengles_shader_program_init(void)
{
/* To add defines: lv_opengl_shader_define_t frag_defs[1] = { { "PLACEHOLDER", NULL, false} }; */
uint32_t frag_shader_hash = lv_opengl_shader_manager_select_shader(&shader_manager, "__MAIN__.frag", NULL, 0);
uint32_t vert_shader_hash = lv_opengl_shader_manager_select_shader(&shader_manager, "__MAIN__.vert", NULL, 0);
lv_opengl_shader_program_t * program = lv_opengl_shader_manager_get_program(&shader_manager, frag_shader_hash,
vert_shader_hash);
return lv_opengl_shader_program_get_id(program);
}
@@ -466,4 +503,97 @@ static float lv_opengles_map_float(float x, float min_in, float max_in, float mi
return ((x - min_in) * delta_out) / delta_in + min_out;
}
static void populate_vertex_buffer(float vertex_buffer[LV_OPENGLES_VERTEX_BUFFER_LEN],
lv_display_rotation_t rotation, bool * h_flip, bool * v_flip, float clip_x1, float clip_y1, float clip_x2,
float clip_y2)
{
#if !LV_USE_DRAW_OPENGLES
LV_UNUSED(h_flip);
LV_UNUSED(v_flip);
#endif
switch(rotation) {
case LV_DISPLAY_ROTATION_0:
vertex_buffer[0] = -1.f;
vertex_buffer[1] = 1.0f;
vertex_buffer[2] = clip_x1;
vertex_buffer[3] = clip_y2;
vertex_buffer[4] = 1.0f;
vertex_buffer[5] = 1.0f;
vertex_buffer[6] = clip_x2;
vertex_buffer[7] = clip_y2;
vertex_buffer[8] = 1.0f;
vertex_buffer[9] = -1.0f;
vertex_buffer[10] = clip_x2;
vertex_buffer[11] = clip_y1;
vertex_buffer[12] = -1.f;
vertex_buffer[13] = -1.0f;
vertex_buffer[14] = clip_x1;
vertex_buffer[15] = clip_y1;
break;
case LV_DISPLAY_ROTATION_270:
#if LV_USE_DRAW_OPENGLES
*h_flip = !*h_flip;
*v_flip = !*v_flip;
#endif
vertex_buffer[0] = 1.0f;
vertex_buffer[1] = 1.0f;
vertex_buffer[2] = clip_x1;
vertex_buffer[3] = clip_y2;
vertex_buffer[4] = 1.0f;
vertex_buffer[5] = -1.0f;
vertex_buffer[6] = clip_x2;
vertex_buffer[7] = clip_y2;
vertex_buffer[8] = -1.f;
vertex_buffer[9] = -1.0f;
vertex_buffer[10] = clip_x2;
vertex_buffer[11] = clip_y1;
vertex_buffer[12] = -1.f;
vertex_buffer[13] = 1.0f;
vertex_buffer[14] = clip_x1;
vertex_buffer[15] = clip_y1;
break;
case LV_DISPLAY_ROTATION_180:
vertex_buffer[0] = 1.0f;
vertex_buffer[1] = -1.0f;
vertex_buffer[2] = clip_x1;
vertex_buffer[3] = clip_y2;
vertex_buffer[4] = -1.f;
vertex_buffer[5] = -1.0f;
vertex_buffer[6] = clip_x2;
vertex_buffer[7] = clip_y2;
vertex_buffer[8] = -1.f;
vertex_buffer[9] = 1.0f;
vertex_buffer[10] = clip_x2;
vertex_buffer[11] = clip_y1;
vertex_buffer[12] = 1.0f;
vertex_buffer[13] = 1.0f;
vertex_buffer[14] = clip_x1;
vertex_buffer[15] = clip_y1;
break;
case LV_DISPLAY_ROTATION_90:
#if LV_USE_DRAW_OPENGLES
*h_flip = !*h_flip;
*v_flip = !*v_flip;
#endif
vertex_buffer[0] = -1.f;
vertex_buffer[1] = -1.0f;
vertex_buffer[2] = clip_x1;
vertex_buffer[3] = clip_y2;
vertex_buffer[4] = -1.f;
vertex_buffer[5] = 1.0f;
vertex_buffer[6] = clip_x2;
vertex_buffer[7] = clip_y2;
vertex_buffer[8] = 1.0f;
vertex_buffer[9] = 1.0f;
vertex_buffer[10] = clip_x2;
vertex_buffer[11] = clip_y1;
vertex_buffer[12] = 1.0f;
vertex_buffer[13] = -1.0f;
vertex_buffer[14] = clip_x1;
vertex_buffer[15] = clip_y1;
break;
}
}
#endif /* LV_USE_OPENGLES */
@@ -57,6 +57,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, const lv_area_t * texture_clip_area, bool h_flip, bool v_flip);
/**
* Render a display texture - Supports rotation
* @param display LVGL Texture display. Created with the `lv_opengles_texture` module
* @param h_flip horizontal flip
* @param v_flip vertical flip
*/
void lv_opengles_render_display_texture(lv_display_t * display, bool h_flip, bool v_flip);
/**
* Render a fill
* @param color the color of the fill
File diff suppressed because it is too large Load Diff
+12 -26
View File
@@ -10,16 +10,16 @@
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_EGL
#include "../../misc/lv_types.h"
#include "../../misc/lv_color.h"
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
@@ -29,40 +29,26 @@ extern "C" {
* TYPEDEFS
**********************/
typedef void (*lv_opengles_egl_window_cb_t)(lv_opengles_window_t * window);
typedef struct _lv_opengles_egl lv_opengles_egl_t;
typedef struct _lv_egl_interface lv_egl_interface_t;
typedef struct _lv_egl_config lv_egl_config_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create an EGL OpenGL window with no textures. OpenGL should be initialized beforehand.
* @param hor_res width in pixels of the window
* @param ver_res height in pixels of the window
* @param native_window_handle a handle to a native window for the platform
* @param device a `EGLNativeDisplayType`
* @param pre called before rendering
* @param post1 called after rendering, before swapping
* @param post2 called after swapping
* @return the new EGL OpenGL window handle
*/
lv_opengles_window_t * lv_opengles_egl_window_create(int32_t hor_res, int32_t ver_res, void * native_window_handle,
void * device,
lv_opengles_egl_window_cb_t pre,
lv_opengles_egl_window_cb_t post1,
lv_opengles_egl_window_cb_t post2);
lv_opengles_egl_t * lv_opengles_egl_context_create(const lv_egl_interface_t * interface);
lv_color_format_t lv_opengles_egl_color_format_from_egl_config(const lv_egl_config_t * config);
void * lv_opengles_egl_window_get_surface(lv_opengles_window_t * window);
void * lv_opengles_egl_window_get_display(lv_opengles_window_t * window);
void lv_opengles_egl_window_set_user_data(lv_opengles_window_t * window, void * user_data);
void * lv_opengles_egl_window_get_user_data(lv_opengles_window_t * window);
void lv_opengles_egl_update(lv_opengles_egl_t * ctx);
void lv_opengles_egl_clear(lv_opengles_egl_t * ctx);
void lv_opengles_egl_context_destroy(lv_opengles_egl_t * ctx);
/**********************
* MACROS
**********************/
#endif /*LV_USE_EGL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
@@ -0,0 +1,102 @@
/**
* @file lv_opengles_egl_private.h
*
*/
#ifndef LV_OPENGLES_EGL_PRIVATE_H
#define LV_OPENGLES_EGL_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_EGL
#include "../../misc/lv_types.h"
#include "../../misc/lv_color.h"
#include "lv_opengles_private.h"
#include "lv_opengles_egl.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_egl_config {
EGLint id;
EGLint max_width;
EGLint max_height;
EGLint buffer_size;
EGLint depth;
EGLint stencil;
EGLint samples;
EGLint surface_type;
EGLint r_bits;
EGLint g_bits;
EGLint b_bits;
EGLint a_bits;
};
typedef struct {
EGLint visual_id;
} lv_egl_native_window_properties_t;
typedef void * (*lv_egl_init_display_t)(void * driver_data, int32_t width, int32_t height);
typedef void * (*lv_egl_get_display_t)(void * driver_data);
typedef void * (*lv_create_window_t)(void * driver_data, const lv_egl_native_window_properties_t * props);
typedef void (*lv_destroy_window_t)(void * driver_data, void * native_window);
typedef void (*lv_egl_set_visible_t)(void * driver_data, bool v);
typedef void (*lv_egl_flip_t)(void * driver_data, bool vsync);
typedef void (*lv_egl_native_state_deinit_t)(void ** driver_data);
typedef size_t (*lv_egl_select_config_t)(void * driver_data, const lv_egl_config_t * configs,
size_t config_count);
struct _lv_egl_interface {
lv_egl_select_config_t select_config;
void * driver_data;
void * native_display;
uint16_t egl_platform;
lv_create_window_t create_window_cb;
lv_destroy_window_t destroy_window_cb;
lv_egl_flip_t flip_cb;
};
struct _lv_opengles_egl {
EGLNativeWindowType native_window;
EGLDisplay egl_display;
EGLConfig egl_config;
EGLContext egl_context;
EGLSurface egl_surface;
void * egl_lib_handle;
void * opengl_lib_handle;
lv_egl_interface_t interface;
int32_t width;
int32_t height;
bool vsync;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#endif /*LV_USE_EGL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OPENGLES_EGL_PRIVATE_H*/
+21 -8
View File
@@ -18,11 +18,8 @@ extern "C" {
#if LV_USE_OPENGLES
#if LV_USE_EGL
#include <GLES/gl.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <GLES/glext.h>
#include <GLES2/gl2ext.h>
#include "glad/include/glad/gles2.h"
#include "glad/include/glad/egl.h"
#else
/* For now, by default we add glew and glfw.
In the future we need to consider adding a config for setting these includes*/
@@ -40,9 +37,25 @@ extern "C" {
#define GL_BGRA GL_BGRA_EXT
#endif /*GL_BGRA*/
#ifndef GL_BGR
#define GL_BGR GL_BGR_EXT
#endif /*GL_BGR*/
#ifndef GL_TEXTURE_MAX_LEVEL
#define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE
#endif /*GL_TEXTURE_MAX_LEVEL*/
#ifndef GL_UNPACK_ROW_LENGTH
#define GL_UNPACK_ROW_LENGTH GL_UNPACK_ROW_LENGTH_EXT
#endif /*GL_UNPACK_ROW_LENGTH*/
#ifndef glGenVertexArrays
#define glGenVertexArrays glGenVertexArraysOES
#endif
#ifndef glBindVertexArray
#define glBindVertexArray glBindVertexArrayOES
#endif
#ifndef glDeleteVertexArrays
#define glDeleteVertexArrays glDeleteVertexArraysOES
#endif
/**********************
* TYPEDEFS
+98 -51
View File
@@ -11,9 +11,12 @@
#if LV_USE_OPENGLES
#include "lv_opengles_debug.h"
#include "lv_opengles_private.h"
#include "lv_opengles_driver.h"
#include "../../misc/lv_types.h"
#include "../../stdlib/lv_mem.h"
#include "lv_opengles_private.h"
#include "lv_opengles_texture_private.h"
#include "../../display/lv_display_private.h"
#include <stdlib.h>
@@ -26,14 +29,6 @@
* TYPEDEFS
**********************/
typedef struct {
unsigned int texture_id;
#if !LV_USE_DRAW_OPENGLES
uint8_t * fb1;
#endif /*!LV_USE_DRAW_OPENGLES*/
bool is_texture_owner;
} lv_opengles_texture_t;
/**********************
* STATIC PROTOTYPES
**********************/
@@ -55,11 +50,11 @@ static void release_disp_cb(lv_event_t * e);
* GLOBAL FUNCTIONS
**********************/
lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h)
{
lv_display_t * disp = lv_opengles_texture_create_common(w, h);
if(!disp) {
LV_LOG_ERROR("Failed to create display");
return NULL;
}
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
@@ -73,6 +68,7 @@ lv_display_t * lv_opengles_texture_create_from_texture_id(int32_t w, int32_t h,
{
lv_display_t * disp = lv_opengles_texture_create_common(w, h);
if(!disp) {
LV_LOG_ERROR("Failed to create display");
return NULL;
}
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
@@ -81,6 +77,66 @@ lv_display_t * lv_opengles_texture_create_from_texture_id(int32_t w, int32_t h,
return disp;
}
void lv_opengles_texture_reshape(lv_display_t * disp, int32_t width, int32_t height)
{
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
unsigned int new_texture = create_texture(width, height);
if(new_texture == GL_NONE) {
LV_LOG_ERROR("Failed to reshape texture. Couldn't acquire new texture from GPU");
return;
}
#if !LV_USE_DRAW_OPENGLES
uint32_t stride = lv_draw_buf_width_to_stride(width, lv_display_get_color_format(disp));
uint32_t buf_size = stride * height;
uint8_t * buffer = lv_realloc(dsc->fb1, buf_size);
LV_ASSERT_MALLOC(buffer);
if(!buffer) {
GL_CALL(glDeleteTextures(1, &new_texture));
LV_LOG_ERROR("Failed to reshape texture. Couldn't resize buffer");
return;
}
dsc->fb1 = buffer;
#endif /*!LV_USE_DRAW_OPENGLES*/
if(dsc->is_texture_owner && dsc->texture_id != 0) {
GL_CALL(glDeleteTextures(1, &dsc->texture_id));
}
dsc->texture_id = new_texture;
}
lv_result_t lv_opengles_texture_create_draw_buffers(lv_opengles_texture_t * texture, lv_display_t * display)
{
int32_t w = lv_display_get_horizontal_resolution(display);
int32_t h = lv_display_get_vertical_resolution(display);
#if LV_USE_DRAW_OPENGLES
LV_UNUSED(texture);
static size_t LV_ATTRIBUTE_MEM_ALIGN dummy_buf;
lv_display_set_buffers(display, &dummy_buf, NULL, w * h * 4, LV_DISPLAY_RENDER_MODE_DIRECT);
#else
uint32_t stride = lv_draw_buf_width_to_stride(w, lv_display_get_color_format(display));
uint32_t buf_size = stride * h;
texture->fb1 = lv_malloc(buf_size);
LV_ASSERT_MALLOC(texture->fb1);
if(!texture->fb1) {
return LV_RESULT_INVALID;
}
lv_display_set_buffers(display, texture->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
#endif
return LV_RESULT_OK;
}
void lv_opengles_texture_deinit(lv_opengles_texture_t * texture)
{
#if !LV_USE_DRAW_OPENGLES
lv_free(texture->fb1);
#endif /*!LV_USE_DRAW_OPENGLES*/
if(texture->is_texture_owner && texture->texture_id != 0) {
GL_CALL(glDeleteTextures(1, &texture->texture_id));
}
}
unsigned int lv_opengles_texture_get_texture_id(lv_display_t * disp)
{
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
@@ -106,34 +162,29 @@ lv_display_t * lv_opengles_texture_get_from_texture_id(unsigned int texture_id)
static lv_display_t * lv_opengles_texture_create_common(int32_t w, int32_t h)
{
lv_display_t * disp = lv_display_create(w, h);
if(disp == NULL) {
if(!disp) {
LV_LOG_ERROR("Failed to create display");
return NULL;
}
lv_opengles_texture_t * dsc = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
LV_ASSERT_MALLOC(dsc);
if(dsc == NULL) {
lv_opengles_texture_t * texture = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
LV_ASSERT_MALLOC(texture);
if(!texture) {
LV_LOG_ERROR("Failed to create texture");
lv_display_delete(disp);
return NULL;
}
#if LV_USE_DRAW_OPENGLES
static size_t LV_ATTRIBUTE_MEM_ALIGN dummy_buf;
lv_display_set_buffers(disp, &dummy_buf, NULL, w * h * 4, LV_DISPLAY_RENDER_MODE_DIRECT);
#else
uint32_t stride = lv_draw_buf_width_to_stride(w, lv_display_get_color_format(disp));
uint32_t buf_size = stride * h;
dsc->fb1 = malloc(buf_size);
LV_ASSERT_MALLOC(dsc->fb1);
if(dsc->fb1 == NULL) {
lv_free(dsc);
lv_result_t res = lv_opengles_texture_create_draw_buffers(texture, disp);
if(res != LV_RESULT_OK) {
LV_LOG_ERROR("Failed to create draw buffers");
lv_free(texture);
lv_display_delete(disp);
return NULL;
}
lv_display_set_buffers(disp, dsc->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
#endif
lv_display_set_resolution(disp, w, h);
lv_display_set_flush_cb(disp, flush_cb);
lv_display_set_driver_data(disp, dsc);
lv_display_set_driver_data(disp, texture);
lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
lv_opengles_init();
return disp;
}
@@ -150,27 +201,32 @@ static unsigned int create_texture(int32_t w, int32_t h)
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, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, NULL));
#elif LV_COLOR_DEPTH == 16
/* Color depth: 16 (RGB565), 32 (XRGB8888) */
#if LV_COLOR_DEPTH == 16
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
NULL));
#elif LV_COLOR_DEPTH == 24
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL));
#elif LV_COLOR_DEPTH == 32
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
#else
#error("Unsupported color format")
#endif
#if 0
GL_CALL(glGenerateMipmap(GL_TEXTURE_2D));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
return texture;
#endif
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(glBindTexture(GL_TEXTURE_2D, GL_NONE));
return texture;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
{
LV_UNUSED(area);
@@ -187,14 +243,10 @@ 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 (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
/*Color depth: 16 (RGB565), 32 (XRGB8888)*/
#if 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,
dsc->fb1));
#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, dsc->fb1));
#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, dsc->fb1));
#else
@@ -209,14 +261,9 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
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);
#if !LV_USE_DRAW_OPENGLES
free(dsc->fb1);
#endif /*!LV_USE_DRAW_OPENGLES*/
if(dsc->is_texture_owner) {
GL_CALL(glDeleteTextures(1, &dsc->texture_id));
}
lv_free(dsc);
lv_opengles_texture_t * texture = lv_display_get_driver_data(disp);
lv_opengles_texture_deinit(texture);
lv_free(texture);
}
#endif /*LV_USE_OPENGLES*/
@@ -0,0 +1,57 @@
/**
* @file lv_opengles_texture_private.h
*
*/
#ifndef LV_OPENGLES_TEXTURE_PRIVATE_H
#define LV_OPENGLES_TEXTURE_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_OPENGLES
#include "lv_opengles_texture.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
unsigned int texture_id;
#if !LV_USE_DRAW_OPENGLES
uint8_t * fb1;
#endif /*!LV_USE_DRAW_OPENGLES*/
bool is_texture_owner;
} lv_opengles_texture_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_result_t lv_opengles_texture_create_draw_buffers(lv_opengles_texture_t * texture, lv_display_t * display);
void lv_opengles_texture_reshape(lv_display_t * disp, int32_t width, int32_t height);
void lv_opengles_texture_deinit(lv_opengles_texture_t * texture);
/**********************
* MACROS
**********************/
#endif /*LV_USE_OPENGLES*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* LV_OPENGLES_TEXTURE_PRIVATE_H */
@@ -19,6 +19,8 @@
* DEFINES
*********************/
#define INVALID_LOCATION 0xFFFFFFFFu
/**********************
* TYPEDEFS
**********************/
@@ -87,14 +89,15 @@ GLuint lv_opengl_shader_program_get_id(lv_opengl_shader_program_t * program)
* STATIC FUNCTIONS
**********************/
static void update_uniform_1i(lv_opengl_shader_program_t * program, const char * prop,
int value)
{
GLuint location = glGetUniformLocation(program->id, prop);
LV_ASSERT_FORMAT_MSG(location != GL_INVALID_INDEX,
LV_ASSERT_FORMAT_MSG(location != INVALID_LOCATION,
"Uniform '%s' not found in program %d",
prop, program->id);
if(location == GL_INVALID_INDEX) {
if(location == INVALID_LOCATION) {
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
program->id);
return;
@@ -107,10 +110,10 @@ static void update_uniform_1f(lv_opengl_shader_program_t * program, const char *
{
GLuint location = glGetUniformLocation(program->id, prop);
LV_ASSERT_FORMAT_MSG(location != GL_INVALID_INDEX,
LV_ASSERT_FORMAT_MSG(location != INVALID_LOCATION,
"Uniform '%s' not found in program %d",
prop, program->id);
if(location == GL_INVALID_INDEX) {
if(location == INVALID_LOCATION) {
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
program->id);
return;
File diff suppressed because it is too large Load Diff