mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-28 05:26:18 +08:00
perf(egl): improve egl performance (#8966)
Co-authored-by: Matt Kimball <greyworld@gmail.com>
This commit is contained in:
@@ -96,6 +96,19 @@ Notes
|
|||||||
- DRM requires proper modesetting. By default, LVGL will select a preferred display mode.
|
- 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
|
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
|
This allows you to use EGL with your own context management or other platforms, but the API may change
|
||||||
without notice in future versions.
|
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
|
Improving Performance
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
--exclude=../src/libs/expat
|
--exclude=../src/libs/expat
|
||||||
--exclude=../src/libs/lz4
|
--exclude=../src/libs/lz4
|
||||||
--exclude=../src/libs/FT800-FT813
|
--exclude=../src/libs/FT800-FT813
|
||||||
|
--exclude=../src/drivers/opengles/glad
|
||||||
--exclude=../src/others/vg_lite_tvg/vg_lite.h
|
--exclude=../src/others/vg_lite_tvg/vg_lite.h
|
||||||
--exclude=../demos/high_res/fonts
|
--exclude=../demos/high_res/fonts
|
||||||
--exclude=../tests/unity/unity.c
|
--exclude=../tests/unity/unity.c
|
||||||
|
|||||||
@@ -552,7 +552,6 @@ static void execute_drawing(lv_draw_opengles_unit_t * u)
|
|||||||
t->draw_unit = (lv_draw_unit_t *)u;
|
t->draw_unit = (lv_draw_unit_t *)u;
|
||||||
|
|
||||||
/* the shader-based fill is not working reliably with EGL. */
|
/* the shader-based fill is not working reliably with EGL. */
|
||||||
#if !LV_USE_EGL
|
|
||||||
if(t->type == LV_DRAW_TASK_TYPE_FILL) {
|
if(t->type == LV_DRAW_TASK_TYPE_FILL) {
|
||||||
lv_draw_fill_dsc_t * fill_dsc = t->draw_dsc;
|
lv_draw_fill_dsc_t * fill_dsc = t->draw_dsc;
|
||||||
if(fill_dsc->radius == 0 && fill_dsc->grad.dir == LV_GRAD_DIR_NONE) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /*!LV_USE_EGL*/
|
|
||||||
|
|
||||||
if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
|
if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
|
||||||
blend_texture_layer(t);
|
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(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
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.
|
* 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));
|
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(glGenerateMipmap(GL_TEXTURE_2D));
|
||||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20));
|
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_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(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
|
GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* INCLUDES
|
* INCLUDES
|
||||||
*********************/
|
*********************/
|
||||||
#include "lv_linux_drm.h"
|
#include "lv_linux_drm.h"
|
||||||
#if LV_USE_LINUX_DRM
|
#if LV_USE_LINUX_DRM && !LV_LINUX_DRM_USE_EGL
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -25,10 +25,6 @@
|
|||||||
#include "../../../stdlib/lv_sprintf.h"
|
#include "../../../stdlib/lv_sprintf.h"
|
||||||
#include "../../../draw/lv_draw_buf.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
|
#if LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||||
|
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
@@ -37,17 +33,6 @@
|
|||||||
|
|
||||||
#endif
|
#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
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
@@ -61,8 +46,6 @@
|
|||||||
|
|
||||||
#define BUFFER_CNT 2
|
#define BUFFER_CNT 2
|
||||||
|
|
||||||
#define USE_EGL_EXPERIMENTAL_DIRECT_WINDOW_RENDER 0
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
@@ -73,19 +56,8 @@ typedef struct {
|
|||||||
unsigned long int size;
|
unsigned long int size;
|
||||||
uint8_t * map;
|
uint8_t * map;
|
||||||
uint32_t fb_handle;
|
uint32_t fb_handle;
|
||||||
#if LV_LINUX_DRM_USE_EGL
|
|
||||||
uint32_t fb_id;
|
|
||||||
#endif
|
|
||||||
} drm_buffer_t;
|
} 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 {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
uint32_t conn_id, enc_id, crtc_id, plane_id, crtc_idx;
|
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
|
#if LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||||
struct gbm_device * gbm_device;
|
struct gbm_device * gbm_device;
|
||||||
#endif
|
#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;
|
} drm_dev_t;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@@ -151,26 +109,15 @@ static uint32_t tick_get_cb(void);
|
|||||||
|
|
||||||
#if !LV_USE_LINUX_DRM_GBM_BUFFERS
|
#if !LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||||
static int drm_allocate_dumb(drm_dev_t * drm_dev, drm_buffer_t * buf);
|
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);
|
static int create_gbm_buffer(drm_dev_t * drm_dev, drm_buffer_t * buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_LINUX_DRM_USE_EGL
|
static int drm_setup_buffers(drm_dev_t * drm_dev);
|
||||||
static drm_buffer_t * drm_fb_get_from_bo(struct gbm_bo * bo);
|
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf);
|
||||||
static void drm_fb_destroy_callback(struct gbm_bo * bo, void * data);
|
static void drm_flush_wait(lv_display_t * drm_dev);
|
||||||
static void drm_gbm_egl_pre(lv_opengles_window_t * window);
|
static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||||
static void drm_gbm_egl_post1(lv_opengles_window_t * window);
|
static void drm_dmabuf_set_active_buf(lv_event_t * event);
|
||||||
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 VARIABLES
|
* STATIC VARIABLES
|
||||||
@@ -198,7 +145,7 @@ lv_display_t * lv_linux_drm_create(void)
|
|||||||
if(drm_dev == NULL) return NULL;
|
if(drm_dev == NULL) return NULL;
|
||||||
|
|
||||||
drm_dev->fd = -1;
|
drm_dev->fd = -1;
|
||||||
#if !LV_LINUX_DRM_USE_EGL
|
|
||||||
disp = lv_display_create(800, 480);
|
disp = lv_display_create(800, 480);
|
||||||
if(disp == NULL) {
|
if(disp == NULL) {
|
||||||
lv_free(drm_dev);
|
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_wait_cb(disp, drm_flush_wait);
|
||||||
lv_display_set_flush_cb(disp, drm_flush);
|
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;
|
return disp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !LV_LINUX_DRM_USE_EGL
|
|
||||||
/* Called by LVGL when there is something that needs redrawing
|
/* 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
|
* 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
|
* 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)
|
void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t connector_id)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#if !LV_LINUX_DRM_USE_EGL
|
|
||||||
drm_dev_t * drm_dev = lv_display_get_driver_data(disp);
|
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);
|
ret = drm_setup(drm_dev, file, connector_id, DRM_FOURCC);
|
||||||
if(ret) {
|
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 hor_res = drm_dev->width;
|
||||||
int32_t ver_res = drm_dev->height;
|
int32_t ver_res = drm_dev->height;
|
||||||
|
|
||||||
#if !LV_LINUX_DRM_USE_EGL
|
|
||||||
ret = drm_setup_buffers(drm_dev);
|
ret = drm_setup_buffers(drm_dev);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
LV_LOG_ERROR("DRM buffer allocation failed");
|
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",
|
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));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !LV_LINUX_DRM_USE_EGL
|
|
||||||
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf)
|
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
static int first = 1;
|
static int first = 1;
|
||||||
uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
|
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;
|
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;
|
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,
|
static int find_plane(drm_dev_t * drm_dev, unsigned int fourcc, uint32_t * plane_id, uint32_t crtc_id,
|
||||||
uint32_t crtc_idx)
|
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));
|
LV_LOG_INFO("GBM device backend: %s", gbm_device_get_backend_name(drm_dev->gbm_device));
|
||||||
#endif
|
#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;
|
return 0;
|
||||||
|
|
||||||
err:
|
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*/
|
#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)
|
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)
|
static int drm_setup_buffers(drm_dev_t * drm_dev)
|
||||||
{
|
{
|
||||||
int ret;
|
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;
|
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)
|
static uint32_t tick_get_cb(void)
|
||||||
{
|
{
|
||||||
@@ -1366,4 +1055,4 @@ static uint32_t tick_get_cb(void)
|
|||||||
return time_ms;
|
return time_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_LINUX_DRM*/
|
#endif /*LV_USE_LINUX_DRM && !LV_LINUX_DRM_USE_EGL*/
|
||||||
|
|||||||
@@ -29,10 +29,41 @@ extern "C" {
|
|||||||
/**********************
|
/**********************
|
||||||
* GLOBAL PROTOTYPES
|
* 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);
|
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);
|
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
|
* 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>
|
#include <string.h>
|
||||||
|
|
||||||
static const lv_opengl_shader_t src_includes[] = {
|
static const lv_opengl_shader_t src_includes[] = {
|
||||||
{ "hsv_adjust.glsl", R"(
|
{
|
||||||
|
"hsv_adjust.glsl", R"(
|
||||||
|
|
||||||
uniform float u_Hue;
|
uniform float u_Hue;
|
||||||
uniform float u_Saturation;
|
uniform float u_Saturation;
|
||||||
uniform float u_Value;
|
uniform float u_Value;
|
||||||
|
|
||||||
vec3 rgb2hsv(vec3 c){
|
// Convert RGB to HSV
|
||||||
float M = max(max(c.r,c.g),c.b);
|
vec3 rgb2hsv(vec3 c) {
|
||||||
float m = min(min(c.r,c.g),c.b);
|
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||||
float d = M - m;
|
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||||
float h = 0.0;
|
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||||
if(d > 0.00001){
|
float d = q.x - min(q.w, q.y);
|
||||||
if(M == c.r) h = mod((c.g - c.b)/d, 6.0);
|
float e = 1.0e-10;
|
||||||
else if(M == c.g) h = (c.b - c.r)/d + 2.0;
|
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 hsv2rgb(vec3 c){
|
// Convert HSV to RGB
|
||||||
float h = c.x * 6.0;
|
vec3 hsv2rgb(vec3 c) {
|
||||||
float i = floor(h);
|
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||||
float f = h - i;
|
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||||
float p = c.z * (1.0 - c.y);
|
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 adjustHSV(vec3 color){
|
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);
|
hsv.z = clamp(hsv.z * u_Value, 0.0, 1.0);
|
||||||
return hsv2rgb(hsv);
|
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
|
uniform float u_Brightness; // add/subtract in [ -1.0 .. +1.0 ], 0.0 = no change
|
||||||
|
|
||||||
vec3 adjustBrightness(vec3 color){
|
vec3 adjustBrightness(vec3 color){
|
||||||
return clamp(color + vec3(u_Brightness), 0.0, 1.0);
|
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
|
uniform float u_Contrast; // 0.0 = mid-gray, 1.0 = no change, >1.0 increases contrast
|
||||||
|
|
||||||
vec3 adjustContrast(vec3 color){
|
vec3 adjustContrast(vec3 color){
|
||||||
// shift to [-0.5..0.5], scale, shift back
|
// shift to [-0.5..0.5], scale, shift back
|
||||||
return clamp(((color - 0.5) * u_Contrast) + 0.5, 0.0, 1.0);
|
return clamp(((color - 0.5) * u_Contrast) + 0.5, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
)" },
|
)"
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * src_vertex_shader = R"(
|
static const char * src_vertex_shader = R"(
|
||||||
@@ -98,13 +91,18 @@ static const char *src_fragment_shader = R"(
|
|||||||
uniform bool u_IsFill;
|
uniform bool u_IsFill;
|
||||||
uniform vec3 u_FillColor;
|
uniform vec3 u_FillColor;
|
||||||
|
|
||||||
|
#ifdef HSV_ADJUST
|
||||||
|
#include <hsv_adjust.glsl>
|
||||||
|
#endif
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 texColor;
|
vec4 texColor;
|
||||||
if (u_IsFill) {
|
if (u_IsFill) {
|
||||||
texColor = vec4(u_FillColor, 1.0);
|
texColor = vec4(u_FillColor, 1.0);
|
||||||
} else {
|
} 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) {
|
if (abs(u_ColorDepth - 8.0) < 0.1) {
|
||||||
float gray = texColor.r;
|
float gray = texColor.r;
|
||||||
@@ -113,6 +111,9 @@ static const char *src_fragment_shader = R"(
|
|||||||
float combinedAlpha = texColor.a * u_Opa;
|
float combinedAlpha = texColor.a * u_Opa;
|
||||||
color = vec4(texColor.rgb * combinedAlpha, combinedAlpha);
|
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)
|
void lv_opengles_standard_shader_get_src(lv_opengl_shader_portions_t *portions)
|
||||||
{
|
{
|
||||||
portions->all = src_includes;
|
portions->all = src_includes;
|
||||||
portions->count = sizeof(src_includes) / sizeof(src_includes[0]);
|
portions->count = sizeof(src_includes) / sizeof(src_includes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_OPENGLES*/
|
#endif /*LV_USE_OPENGLES*/
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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_shader_set_uniform3f(const char * name, float value_0, float value_1, float value_2);
|
||||||
static void lv_opengles_render_draw(void);
|
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 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
|
* GLOBAL PROTOTYPES
|
||||||
@@ -85,8 +88,8 @@ static unsigned int index_buffer_count = 0;
|
|||||||
|
|
||||||
static unsigned int shader_id;
|
static unsigned int shader_id;
|
||||||
|
|
||||||
static const char * shader_names[] = { "u_Texture", "u_ColorDepth", "u_VertexTransform", "u_Opa", "u_IsFill", "u_FillColor" };
|
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 };
|
static int shader_location[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* 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;
|
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)
|
void lv_opengles_render_clear(void)
|
||||||
{
|
{
|
||||||
LV_PROFILER_DRAW_BEGIN;
|
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)
|
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 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);
|
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,
|
lv_opengl_shader_program_t * program = lv_opengl_shader_manager_get_program(&shader_manager, frag_shader_hash,
|
||||||
vert_shader_hash);
|
vert_shader_hash);
|
||||||
|
|
||||||
return lv_opengl_shader_program_get_id(program);
|
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;
|
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 */
|
#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,
|
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);
|
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
|
* Render a fill
|
||||||
* @param color the color of the fill
|
* @param color the color of the fill
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,16 +10,16 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
#include "../../lv_conf_internal.h"
|
#include "../../lv_conf_internal.h"
|
||||||
|
|
||||||
|
|
||||||
#if LV_USE_EGL
|
#if LV_USE_EGL
|
||||||
|
|
||||||
#include "../../misc/lv_types.h"
|
#include "../../misc/lv_types.h"
|
||||||
|
#include "../../misc/lv_color.h"
|
||||||
|
|
||||||
/*********************
|
|
||||||
* INCLUDES
|
|
||||||
*********************/
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
@@ -29,40 +29,26 @@ extern "C" {
|
|||||||
* TYPEDEFS
|
* 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
|
* GLOBAL PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
lv_opengles_egl_t * lv_opengles_egl_context_create(const lv_egl_interface_t * interface);
|
||||||
* Create an EGL OpenGL window with no textures. OpenGL should be initialized beforehand.
|
lv_color_format_t lv_opengles_egl_color_format_from_egl_config(const lv_egl_config_t * config);
|
||||||
* @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);
|
|
||||||
|
|
||||||
void * lv_opengles_egl_window_get_surface(lv_opengles_window_t * window);
|
void lv_opengles_egl_update(lv_opengles_egl_t * ctx);
|
||||||
void * lv_opengles_egl_window_get_display(lv_opengles_window_t * window);
|
void lv_opengles_egl_clear(lv_opengles_egl_t * ctx);
|
||||||
void lv_opengles_egl_window_set_user_data(lv_opengles_window_t * window, void * user_data);
|
void lv_opengles_egl_context_destroy(lv_opengles_egl_t * ctx);
|
||||||
void * lv_opengles_egl_window_get_user_data(lv_opengles_window_t * window);
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
#endif /*LV_USE_EGL*/
|
#endif /*LV_USE_EGL*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /*extern "C"*/
|
} /*extern "C"*/
|
||||||
#endif
|
#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*/
|
||||||
@@ -18,11 +18,8 @@ extern "C" {
|
|||||||
#if LV_USE_OPENGLES
|
#if LV_USE_OPENGLES
|
||||||
|
|
||||||
#if LV_USE_EGL
|
#if LV_USE_EGL
|
||||||
#include <GLES/gl.h>
|
#include "glad/include/glad/gles2.h"
|
||||||
#include <EGL/egl.h>
|
#include "glad/include/glad/egl.h"
|
||||||
#include <GLES3/gl3.h>
|
|
||||||
#include <GLES/glext.h>
|
|
||||||
#include <GLES2/gl2ext.h>
|
|
||||||
#else
|
#else
|
||||||
/* For now, by default we add glew and glfw.
|
/* For now, by default we add glew and glfw.
|
||||||
In the future we need to consider adding a config for setting these includes*/
|
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
|
#define GL_BGRA GL_BGRA_EXT
|
||||||
#endif /*GL_BGRA*/
|
#endif /*GL_BGRA*/
|
||||||
|
|
||||||
#ifndef GL_BGR
|
#ifndef GL_TEXTURE_MAX_LEVEL
|
||||||
#define GL_BGR GL_BGR_EXT
|
#define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE
|
||||||
#endif /*GL_BGR*/
|
#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
|
* TYPEDEFS
|
||||||
|
|||||||
@@ -11,9 +11,12 @@
|
|||||||
#if LV_USE_OPENGLES
|
#if LV_USE_OPENGLES
|
||||||
|
|
||||||
#include "lv_opengles_debug.h"
|
#include "lv_opengles_debug.h"
|
||||||
#include "lv_opengles_private.h"
|
|
||||||
|
|
||||||
#include "lv_opengles_driver.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 "../../display/lv_display_private.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -26,14 +29,6 @@
|
|||||||
* TYPEDEFS
|
* 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
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
@@ -55,11 +50,11 @@ static void release_disp_cb(lv_event_t * e);
|
|||||||
* GLOBAL FUNCTIONS
|
* GLOBAL FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
|
||||||
lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h)
|
lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h)
|
||||||
{
|
{
|
||||||
lv_display_t * disp = lv_opengles_texture_create_common(w, h);
|
lv_display_t * disp = lv_opengles_texture_create_common(w, h);
|
||||||
if(!disp) {
|
if(!disp) {
|
||||||
|
LV_LOG_ERROR("Failed to create display");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
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);
|
lv_display_t * disp = lv_opengles_texture_create_common(w, h);
|
||||||
if(!disp) {
|
if(!disp) {
|
||||||
|
LV_LOG_ERROR("Failed to create display");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
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;
|
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)
|
unsigned int lv_opengles_texture_get_texture_id(lv_display_t * disp)
|
||||||
{
|
{
|
||||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(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)
|
static lv_display_t * lv_opengles_texture_create_common(int32_t w, int32_t h)
|
||||||
{
|
{
|
||||||
lv_display_t * disp = lv_display_create(w, h);
|
lv_display_t * disp = lv_display_create(w, h);
|
||||||
if(disp == NULL) {
|
if(!disp) {
|
||||||
|
LV_LOG_ERROR("Failed to create display");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
lv_opengles_texture_t * dsc = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
|
lv_opengles_texture_t * texture = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
|
||||||
LV_ASSERT_MALLOC(dsc);
|
LV_ASSERT_MALLOC(texture);
|
||||||
if(dsc == NULL) {
|
if(!texture) {
|
||||||
|
LV_LOG_ERROR("Failed to create texture");
|
||||||
lv_display_delete(disp);
|
lv_display_delete(disp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
lv_result_t res = lv_opengles_texture_create_draw_buffers(texture, disp);
|
||||||
#if LV_USE_DRAW_OPENGLES
|
if(res != LV_RESULT_OK) {
|
||||||
static size_t LV_ATTRIBUTE_MEM_ALIGN dummy_buf;
|
LV_LOG_ERROR("Failed to create draw buffers");
|
||||||
lv_display_set_buffers(disp, &dummy_buf, NULL, w * h * 4, LV_DISPLAY_RENDER_MODE_DIRECT);
|
lv_free(texture);
|
||||||
#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_display_delete(disp);
|
lv_display_delete(disp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
lv_display_set_buffers(disp, dsc->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
|
lv_display_set_resolution(disp, w, h);
|
||||||
#endif
|
|
||||||
lv_display_set_flush_cb(disp, flush_cb);
|
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_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
|
||||||
|
|
||||||
lv_opengles_init();
|
lv_opengles_init();
|
||||||
return disp;
|
return disp;
|
||||||
}
|
}
|
||||||
@@ -150,27 +201,32 @@ static unsigned int create_texture(int32_t w, int32_t h)
|
|||||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||||
|
|
||||||
/* set the dimensions and format to complete the texture */
|
/* set the dimensions and format to complete the texture */
|
||||||
/* Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888) */
|
/* Color depth: 16 (RGB565), 32 (XRGB8888) */
|
||||||
#if LV_COLOR_DEPTH == 8
|
#if LV_COLOR_DEPTH == 16
|
||||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, NULL));
|
|
||||||
#elif LV_COLOR_DEPTH == 16
|
|
||||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||||
NULL));
|
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
|
#elif LV_COLOR_DEPTH == 32
|
||||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
|
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
|
||||||
#else
|
#else
|
||||||
#error("Unsupported color format")
|
#error("Unsupported color format")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
GL_CALL(glGenerateMipmap(GL_TEXTURE_2D));
|
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_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_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
|
||||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
#endif
|
||||||
return texture;
|
|
||||||
|
|
||||||
|
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)
|
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||||
{
|
{
|
||||||
LV_UNUSED(area);
|
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_ALIGNMENT, 1));
|
||||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / lv_color_format_get_size(cf)));
|
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / lv_color_format_get_size(cf)));
|
||||||
/*Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
|
/*Color depth: 16 (RGB565), 32 (XRGB8888)*/
|
||||||
#if LV_COLOR_DEPTH == 8
|
#if LV_COLOR_DEPTH == 16
|
||||||
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
|
|
||||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, disp->hor_res, disp->ver_res, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
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));
|
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
|
#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));
|
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, disp->hor_res, disp->ver_res, 0, GL_BGRA, GL_UNSIGNED_BYTE, dsc->fb1));
|
||||||
#else
|
#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)
|
static void release_disp_cb(lv_event_t * e)
|
||||||
{
|
{
|
||||||
lv_display_t * disp = lv_event_get_user_data(e);
|
lv_display_t * disp = lv_event_get_user_data(e);
|
||||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
lv_opengles_texture_t * texture = lv_display_get_driver_data(disp);
|
||||||
#if !LV_USE_DRAW_OPENGLES
|
lv_opengles_texture_deinit(texture);
|
||||||
free(dsc->fb1);
|
lv_free(texture);
|
||||||
#endif /*!LV_USE_DRAW_OPENGLES*/
|
|
||||||
if(dsc->is_texture_owner) {
|
|
||||||
GL_CALL(glDeleteTextures(1, &dsc->texture_id));
|
|
||||||
}
|
|
||||||
lv_free(dsc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_OPENGLES*/
|
#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
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
|
#define INVALID_LOCATION 0xFFFFFFFFu
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
@@ -87,14 +89,15 @@ GLuint lv_opengl_shader_program_get_id(lv_opengl_shader_program_t * program)
|
|||||||
* STATIC FUNCTIONS
|
* STATIC FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
|
||||||
static void update_uniform_1i(lv_opengl_shader_program_t * program, const char * prop,
|
static void update_uniform_1i(lv_opengl_shader_program_t * program, const char * prop,
|
||||||
int value)
|
int value)
|
||||||
{
|
{
|
||||||
GLuint location = glGetUniformLocation(program->id, prop);
|
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",
|
"Uniform '%s' not found in program %d",
|
||||||
prop, program->id);
|
prop, program->id);
|
||||||
if(location == GL_INVALID_INDEX) {
|
if(location == INVALID_LOCATION) {
|
||||||
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
|
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
|
||||||
program->id);
|
program->id);
|
||||||
return;
|
return;
|
||||||
@@ -107,10 +110,10 @@ static void update_uniform_1f(lv_opengl_shader_program_t * program, const char *
|
|||||||
{
|
{
|
||||||
GLuint location = glGetUniformLocation(program->id, prop);
|
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",
|
"Uniform '%s' not found in program %d",
|
||||||
prop, program->id);
|
prop, program->id);
|
||||||
if(location == GL_INVALID_INDEX) {
|
if(location == INVALID_LOCATION) {
|
||||||
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
|
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
|
||||||
program->id);
|
program->id);
|
||||||
return;
|
return;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user