mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-10 04:37:55 +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.
|
||||
|
||||
|
||||
In order to avoid hard codding the device card path, you can ask LVGL to find a connected one for you using :cpp:func:`lv_linux_drm_find_device_path`.
|
||||
It will return the first connected card it can find.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_display_t * disp = lv_linux_drm_create();
|
||||
|
||||
/* Find the first connected card in /sys/class/drm */
|
||||
char * device = lv_linux_drm_find_device_path();
|
||||
lv_linux_drm_set_file(disp, device, -1);
|
||||
/* Free the path pointer */
|
||||
lv_free(device);
|
||||
|
||||
|
||||
Using DRM with GBM
|
||||
------------------
|
||||
|
||||
@@ -43,19 +43,6 @@ This API is currently private and experimental, and people should expect breakin
|
||||
This allows you to use EGL with your own context management or other platforms, but the API may change
|
||||
without notice in future versions.
|
||||
|
||||
Render Direct to Window
|
||||
-----------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This feature is incomplete and has bugs.
|
||||
|
||||
Performance can be improved if the LVGL OpenGL driver renders its cached textures directly to the window
|
||||
(and :c:macro:`LV_USE_DRAW_OPENGLES` is enabled). This can be done by creating the display with
|
||||
:cpp:func:`lv_opengles_window_display_create` instead of :cpp:func:`lv_opengles_texture_create` +
|
||||
:cpp:func:`lv_opengles_texture_get_texture_id` + :cpp:func:`lv_opengles_window_add_texture`.
|
||||
Performance should be better with GLFW than EGL. EGL currently has issues when used this way.
|
||||
|
||||
Improving Performance
|
||||
---------------------
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
--exclude=../src/libs/expat
|
||||
--exclude=../src/libs/lz4
|
||||
--exclude=../src/libs/FT800-FT813
|
||||
--exclude=../src/drivers/opengles/glad
|
||||
--exclude=../src/others/vg_lite_tvg/vg_lite.h
|
||||
--exclude=../demos/high_res/fonts
|
||||
--exclude=../tests/unity/unity.c
|
||||
|
||||
@@ -552,7 +552,6 @@ static void execute_drawing(lv_draw_opengles_unit_t * u)
|
||||
t->draw_unit = (lv_draw_unit_t *)u;
|
||||
|
||||
/* the shader-based fill is not working reliably with EGL. */
|
||||
#if !LV_USE_EGL
|
||||
if(t->type == LV_DRAW_TASK_TYPE_FILL) {
|
||||
lv_draw_fill_dsc_t * fill_dsc = t->draw_dsc;
|
||||
if(fill_dsc->radius == 0 && fill_dsc->grad.dir == LV_GRAD_DIR_NONE) {
|
||||
@@ -581,7 +580,6 @@ static void execute_drawing(lv_draw_opengles_unit_t * u)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /*!LV_USE_EGL*/
|
||||
|
||||
if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
|
||||
blend_texture_layer(t);
|
||||
@@ -621,13 +619,17 @@ static unsigned int create_texture(int32_t w, int32_t h, const void * data)
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
|
||||
/* LV_COLOR_DEPTH 32, 24, 16 are supported but the cached textures will always
|
||||
/* LV_COLOR_DEPTH 32, 16 are supported but the cached textures will always
|
||||
* have full ARGB pixels since the alpha channel is required for blending.
|
||||
*/
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data));
|
||||
#if 0
|
||||
GL_CALL(glGenerateMipmap(GL_TEXTURE_2D));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
|
||||
#endif
|
||||
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_linux_drm.h"
|
||||
#if LV_USE_LINUX_DRM
|
||||
#if LV_USE_LINUX_DRM && !LV_LINUX_DRM_USE_EGL
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -25,10 +25,6 @@
|
||||
#include "../../../stdlib/lv_sprintf.h"
|
||||
#include "../../../draw/lv_draw_buf.h"
|
||||
|
||||
#if LV_LINUX_DRM_USE_EGL && !LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||
#error LV_USE_LINUX_DRM_GBM_BUFFERS is required to use LV_LINUX_DRM_USE_EGL
|
||||
#endif
|
||||
|
||||
#if LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||
|
||||
#include <gbm.h>
|
||||
@@ -37,17 +33,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_LINUX_DRM_USE_EGL
|
||||
|
||||
#include "../../opengles/lv_opengles_egl.h"
|
||||
#include "../../opengles/lv_opengles_texture.h"
|
||||
#include "../../opengles/lv_opengles_window.h"
|
||||
#include "../../opengles/lv_opengles_private.h"
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
@@ -61,8 +46,6 @@
|
||||
|
||||
#define BUFFER_CNT 2
|
||||
|
||||
#define USE_EGL_EXPERIMENTAL_DIRECT_WINDOW_RENDER 0
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -73,19 +56,8 @@ typedef struct {
|
||||
unsigned long int size;
|
||||
uint8_t * map;
|
||||
uint32_t fb_handle;
|
||||
#if LV_LINUX_DRM_USE_EGL
|
||||
uint32_t fb_id;
|
||||
#endif
|
||||
} drm_buffer_t;
|
||||
|
||||
#if LV_LINUX_DRM_USE_EGL
|
||||
typedef EGLint(*egl_wait_sync_khr_t)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
|
||||
typedef EGLint(*egl_dup_native_fence_fd_android_t)(EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLSyncKHR(*egl_create_sync_khr_t)(EGLDisplay dpy, EGLenum type, const EGLint * attrib_list);
|
||||
typedef EGLBoolean(*egl_destroy_sync_khr_t)(EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLint(*egl_client_wait_sync_khr_t)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
uint32_t conn_id, enc_id, crtc_id, plane_id, crtc_idx;
|
||||
@@ -111,20 +83,6 @@ typedef struct {
|
||||
#if LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||
struct gbm_device * gbm_device;
|
||||
#endif
|
||||
#if LV_LINUX_DRM_USE_EGL
|
||||
struct gbm_surface * surface;
|
||||
int kms_in_fence_fd;
|
||||
int kms_out_fence_fd;
|
||||
EGLSyncKHR kms_fence;
|
||||
EGLSyncKHR gpu_fence;
|
||||
struct gbm_bo * bo;
|
||||
|
||||
egl_wait_sync_khr_t egl_wait_sync_khr;
|
||||
egl_dup_native_fence_fd_android_t egl_dup_native_fence_fd_android;
|
||||
egl_create_sync_khr_t egl_create_sync_khr;
|
||||
egl_destroy_sync_khr_t egl_destroy_sync_khr;
|
||||
egl_client_wait_sync_khr_t egl_client_wait_sync_khr;
|
||||
#endif
|
||||
} drm_dev_t;
|
||||
|
||||
/**********************
|
||||
@@ -151,26 +109,15 @@ static uint32_t tick_get_cb(void);
|
||||
|
||||
#if !LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||
static int drm_allocate_dumb(drm_dev_t * drm_dev, drm_buffer_t * buf);
|
||||
#elif LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL
|
||||
#elif LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||
static int create_gbm_buffer(drm_dev_t * drm_dev, drm_buffer_t * buf);
|
||||
#endif
|
||||
|
||||
#if LV_LINUX_DRM_USE_EGL
|
||||
static drm_buffer_t * drm_fb_get_from_bo(struct gbm_bo * bo);
|
||||
static void drm_fb_destroy_callback(struct gbm_bo * bo, void * data);
|
||||
static void drm_gbm_egl_pre(lv_opengles_window_t * window);
|
||||
static void drm_gbm_egl_post1(lv_opengles_window_t * window);
|
||||
static void drm_gbm_egl_post2(lv_opengles_window_t * window);
|
||||
static int drm_atomic_commit(drm_dev_t * drm_dev, uint32_t fb_id, uint32_t flags);
|
||||
static EGLSyncKHR create_fence(drm_dev_t * drm_dev, EGLDisplay display, int fd);
|
||||
#else
|
||||
static int drm_setup_buffers(drm_dev_t * drm_dev);
|
||||
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf);
|
||||
static void drm_flush_wait(lv_display_t * drm_dev);
|
||||
static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||
static void drm_dmabuf_set_active_buf(lv_event_t * event);
|
||||
#endif
|
||||
|
||||
static int drm_setup_buffers(drm_dev_t * drm_dev);
|
||||
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf);
|
||||
static void drm_flush_wait(lv_display_t * drm_dev);
|
||||
static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||
static void drm_dmabuf_set_active_buf(lv_event_t * event);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -198,7 +145,7 @@ lv_display_t * lv_linux_drm_create(void)
|
||||
if(drm_dev == NULL) return NULL;
|
||||
|
||||
drm_dev->fd = -1;
|
||||
#if !LV_LINUX_DRM_USE_EGL
|
||||
|
||||
disp = lv_display_create(800, 480);
|
||||
if(disp == NULL) {
|
||||
lv_free(drm_dev);
|
||||
@@ -208,18 +155,9 @@ lv_display_t * lv_linux_drm_create(void)
|
||||
lv_display_set_flush_wait_cb(disp, drm_flush_wait);
|
||||
lv_display_set_flush_cb(disp, drm_flush);
|
||||
|
||||
#else /*LV_LINUX_DRM_USE_EGL*/
|
||||
disp = (lv_display_t *) drm_dev;
|
||||
|
||||
drm_dev->kms_in_fence_fd = -1;
|
||||
drm_dev->kms_out_fence_fd = -1;
|
||||
|
||||
#endif
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
#if !LV_LINUX_DRM_USE_EGL
|
||||
/* Called by LVGL when there is something that needs redrawing
|
||||
* it sets the active buffer. if GBM buffers are used, it issues a DMA_BUF_SYNC
|
||||
* ioctl call to lock the buffer for CPU access, the buffer is unlocked just
|
||||
@@ -265,17 +203,12 @@ static void drm_dmabuf_set_active_buf(lv_event_t * event)
|
||||
}
|
||||
|
||||
}
|
||||
#endif /*!LV_LINUX_DRM_USE_EGL*/
|
||||
|
||||
void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t connector_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if !LV_LINUX_DRM_USE_EGL
|
||||
drm_dev_t * drm_dev = lv_display_get_driver_data(disp);
|
||||
#else
|
||||
drm_dev_t * drm_dev = (drm_dev_t *) disp;
|
||||
#endif
|
||||
|
||||
ret = drm_setup(drm_dev, file, connector_id, DRM_FOURCC);
|
||||
if(ret) {
|
||||
@@ -285,7 +218,6 @@ void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t conne
|
||||
int32_t hor_res = drm_dev->width;
|
||||
int32_t ver_res = drm_dev->height;
|
||||
|
||||
#if !LV_LINUX_DRM_USE_EGL
|
||||
ret = drm_setup_buffers(drm_dev);
|
||||
if(ret) {
|
||||
LV_LOG_ERROR("DRM buffer allocation failed");
|
||||
@@ -317,34 +249,6 @@ void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t conne
|
||||
|
||||
LV_LOG_INFO("Resolution is set to %" LV_PRId32 "x%" LV_PRId32 " at %" LV_PRId32 "dpi",
|
||||
hor_res, ver_res, lv_display_get_dpi(disp));
|
||||
|
||||
#else /*LV_LINUX_DRM_USE_EGL*/
|
||||
lv_opengles_window_t * window = lv_opengles_egl_window_create(hor_res, ver_res, drm_dev->surface, drm_dev->gbm_device,
|
||||
drm_gbm_egl_pre, drm_gbm_egl_post1, drm_gbm_egl_post2);
|
||||
lv_opengles_egl_window_set_user_data(window, drm_dev);
|
||||
|
||||
#if !USE_EGL_EXPERIMENTAL_DIRECT_WINDOW_RENDER
|
||||
/* create a display that flushes to a texture */
|
||||
lv_display_t * texture = lv_opengles_texture_create(hor_res, ver_res);
|
||||
lv_display_set_default(texture);
|
||||
#if LV_USE_DRAW_OPENGLES
|
||||
lv_display_delete_refr_timer(texture);
|
||||
#endif
|
||||
/* add the texture to the window */
|
||||
unsigned int texture_id = lv_opengles_texture_get_texture_id(texture);
|
||||
lv_opengles_window_add_texture(window, texture_id, hor_res, ver_res);
|
||||
#else
|
||||
/* render directly to the window */
|
||||
lv_opengles_window_display_create(window, hor_res, ver_res);
|
||||
#endif
|
||||
|
||||
drm_dev->egl_wait_sync_khr = (egl_wait_sync_khr_t) eglGetProcAddress("eglWaitSyncKHR");
|
||||
drm_dev->egl_dup_native_fence_fd_android = (egl_dup_native_fence_fd_android_t)
|
||||
eglGetProcAddress("eglDupNativeFenceFDANDROID");
|
||||
drm_dev->egl_create_sync_khr = (egl_create_sync_khr_t) eglGetProcAddress("eglCreateSyncKHR");
|
||||
drm_dev->egl_destroy_sync_khr = (egl_destroy_sync_khr_t) eglGetProcAddress("eglDestroySyncKHR");
|
||||
drm_dev->egl_client_wait_sync_khr = (egl_client_wait_sync_khr_t) eglGetProcAddress("eglClientWaitSyncKHR");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -531,14 +435,13 @@ static int drm_add_conn_property(drm_dev_t * drm_dev, const char * name, uint64_
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !LV_LINUX_DRM_USE_EGL
|
||||
static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf)
|
||||
{
|
||||
int ret;
|
||||
static int first = 1;
|
||||
uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
|
||||
|
||||
#if LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL
|
||||
#if LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||
|
||||
struct dma_buf_sync sync_req;
|
||||
|
||||
@@ -583,7 +486,6 @@ static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /*!LV_LINUX_DRM_USE_EGL*/
|
||||
|
||||
static int find_plane(drm_dev_t * drm_dev, unsigned int fourcc, uint32_t * plane_id, uint32_t crtc_id,
|
||||
uint32_t crtc_idx)
|
||||
@@ -917,20 +819,6 @@ static int drm_setup(drm_dev_t * drm_dev, const char * device_path, int64_t conn
|
||||
LV_LOG_INFO("GBM device backend: %s", gbm_device_get_backend_name(drm_dev->gbm_device));
|
||||
#endif
|
||||
|
||||
#if LV_LINUX_DRM_USE_EGL
|
||||
|
||||
/* Add support to create a surface with modifiers */
|
||||
drm_dev->surface = gbm_surface_create(drm_dev->gbm_device,
|
||||
drm_dev->width, drm_dev->height, GBM_BO_FORMAT_ARGB8888,
|
||||
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
||||
if(!drm_dev->surface) {
|
||||
LV_LOG_ERROR("failed to create gbm surface");
|
||||
gbm_device_destroy(drm_dev->gbm_device);
|
||||
goto err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -998,7 +886,7 @@ static int drm_allocate_dumb(drm_dev_t * drm_dev, drm_buffer_t * buf)
|
||||
}
|
||||
#endif /*!LV_USE_LINUX_DRM_GBM_BUFFERS*/
|
||||
|
||||
#if LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL
|
||||
#if LV_USE_LINUX_DRM_GBM_BUFFERS
|
||||
|
||||
static int create_gbm_buffer(drm_dev_t * drm_dev, drm_buffer_t * buf)
|
||||
{
|
||||
@@ -1082,9 +970,8 @@ static int create_gbm_buffer(drm_dev_t * drm_dev, drm_buffer_t * buf)
|
||||
|
||||
}
|
||||
|
||||
#endif /* LV_USE_LINUX_DRM_GBM_BUFFERS && !LV_LINUX_DRM_USE_EGL*/
|
||||
#endif /* LV_USE_LINUX_DRM_GBM_BUFFERS */
|
||||
|
||||
#if !LV_LINUX_DRM_USE_EGL
|
||||
static int drm_setup_buffers(drm_dev_t * drm_dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1159,204 +1046,6 @@ static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_
|
||||
drm_dev->act_buf = NULL;
|
||||
|
||||
}
|
||||
#endif /*!LV_LINUX_DRM_USE_EGL*/
|
||||
|
||||
#if LV_LINUX_DRM_USE_EGL
|
||||
|
||||
static void drm_gbm_egl_pre(lv_opengles_window_t * window)
|
||||
{
|
||||
drm_dev_t * drm_dev = lv_opengles_egl_window_get_user_data(window);
|
||||
if(drm_dev->kms_out_fence_fd != -1) {
|
||||
EGLDisplay display = lv_opengles_egl_window_get_display(window);
|
||||
drm_dev->kms_fence = create_fence(drm_dev, display, drm_dev->kms_out_fence_fd);
|
||||
LV_ASSERT_NULL(drm_dev->kms_fence);
|
||||
|
||||
drm_dev->kms_out_fence_fd = -1;
|
||||
|
||||
int result = drm_dev->egl_wait_sync_khr(display, drm_dev->kms_fence, 0);
|
||||
LV_ASSERT(result == 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_gbm_egl_post1(lv_opengles_window_t * window)
|
||||
{
|
||||
drm_dev_t * drm_dev = lv_opengles_egl_window_get_user_data(window);
|
||||
EGLDisplay display = lv_opengles_egl_window_get_display(window);
|
||||
drm_dev->gpu_fence = create_fence(drm_dev, display, EGL_NO_NATIVE_FENCE_FD_ANDROID);
|
||||
LV_ASSERT_NULL(drm_dev->gpu_fence);
|
||||
}
|
||||
|
||||
static void drm_gbm_egl_post2(lv_opengles_window_t * window)
|
||||
{
|
||||
drm_dev_t * drm_dev = lv_opengles_egl_window_get_user_data(window);
|
||||
EGLDisplay display = lv_opengles_egl_window_get_display(window);
|
||||
|
||||
drm_dev->kms_in_fence_fd = drm_dev->egl_dup_native_fence_fd_android(display, drm_dev->gpu_fence);
|
||||
bool res = drm_dev->egl_destroy_sync_khr(display, drm_dev->gpu_fence);
|
||||
LV_ASSERT(res);
|
||||
drm_dev->gpu_fence = NULL;
|
||||
LV_ASSERT(drm_dev->kms_in_fence_fd != -1);
|
||||
|
||||
drm_buffer_t * fb;
|
||||
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
|
||||
int ret;
|
||||
|
||||
/* Get the next bo to display */
|
||||
struct gbm_bo * next_bo = gbm_surface_lock_front_buffer(drm_dev->surface);
|
||||
if(!next_bo) {
|
||||
LV_LOG_ERROR("Failed to lock frontbuffer");
|
||||
}
|
||||
|
||||
fb = drm_fb_get_from_bo(next_bo);
|
||||
if(!fb) {
|
||||
LV_LOG_ERROR("Failed to get a new framebuffer BO");
|
||||
}
|
||||
|
||||
if(drm_dev->kms_fence) {
|
||||
EGLint status;
|
||||
|
||||
do {
|
||||
status = drm_dev->egl_client_wait_sync_khr(display,
|
||||
drm_dev->kms_fence,
|
||||
0,
|
||||
EGL_FOREVER_KHR);
|
||||
} while(status != EGL_CONDITION_SATISFIED_KHR);
|
||||
|
||||
bool res = drm_dev->egl_destroy_sync_khr(display, drm_dev->kms_fence);
|
||||
LV_ASSERT(res);
|
||||
drm_dev->kms_fence = NULL;
|
||||
}
|
||||
|
||||
ret = drm_atomic_commit(drm_dev, fb->fb_id, flags);
|
||||
if(ret) {
|
||||
LV_LOG_ERROR("failed to commit: %s", strerror(errno));
|
||||
}
|
||||
|
||||
/* release last buffer to render on again: */
|
||||
if(drm_dev->bo)
|
||||
gbm_surface_release_buffer(drm_dev->surface, drm_dev->bo);
|
||||
drm_dev->bo = next_bo;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static drm_buffer_t * drm_fb_get_from_bo(struct gbm_bo * bo)
|
||||
{
|
||||
int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo));
|
||||
drm_buffer_t * fb = gbm_bo_get_user_data(bo);
|
||||
uint32_t width, height, format, strides[4] = {0}, handles[4] = {0}, offsets[4] = {0};
|
||||
int ret = -1;
|
||||
|
||||
if(fb)
|
||||
return fb;
|
||||
|
||||
fb = lv_malloc_zeroed(sizeof(drm_buffer_t));
|
||||
|
||||
width = gbm_bo_get_width(bo);
|
||||
height = gbm_bo_get_height(bo);
|
||||
format = gbm_bo_get_format(bo);
|
||||
const int num_planes = gbm_bo_get_plane_count(bo);
|
||||
for(int i = 0; i < num_planes; i++) {
|
||||
handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
|
||||
strides[i] = gbm_bo_get_stride_for_plane(bo, i);
|
||||
offsets[i] = gbm_bo_get_offset(bo, i);
|
||||
}
|
||||
|
||||
memcpy(handles, (uint32_t [4]) {
|
||||
gbm_bo_get_handle(bo).u32, 0, 0, 0
|
||||
}, 16);
|
||||
memcpy(strides, (uint32_t [4]) {
|
||||
gbm_bo_get_stride(bo), 0, 0, 0
|
||||
}, 16);
|
||||
memset(offsets, 0, 16);
|
||||
ret = drmModeAddFB2(drm_fd, width, height, format,
|
||||
handles, strides, offsets, &fb->fb_id, 0);
|
||||
fb->fb_handle = fb->fb_id;
|
||||
|
||||
if(ret) {
|
||||
LV_LOG_ERROR("failed to create fb: %s", strerror(errno));
|
||||
lv_free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
static void drm_fb_destroy_callback(struct gbm_bo * bo, void * data)
|
||||
{
|
||||
int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo));
|
||||
drm_buffer_t * fb = data;
|
||||
|
||||
if(fb->fb_id)
|
||||
drmModeRmFB(drm_fd, fb->fb_id);
|
||||
|
||||
lv_free(fb);
|
||||
}
|
||||
|
||||
static int drm_atomic_commit(drm_dev_t * drm_dev, uint32_t fb_id, uint32_t flags)
|
||||
{
|
||||
int ret;
|
||||
static int first = 1;
|
||||
|
||||
drm_dev->req = drmModeAtomicAlloc();
|
||||
|
||||
/* On first Atomic commit, do a modeset */
|
||||
if(first) {
|
||||
drm_add_conn_property(drm_dev, "CRTC_ID", drm_dev->crtc_id);
|
||||
|
||||
drm_add_crtc_property(drm_dev, "MODE_ID", drm_dev->blob_id);
|
||||
drm_add_crtc_property(drm_dev, "ACTIVE", 1);
|
||||
|
||||
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
|
||||
first = 0;
|
||||
}
|
||||
|
||||
drm_add_plane_property(drm_dev, "FB_ID", fb_id);
|
||||
drm_add_plane_property(drm_dev, "CRTC_ID", drm_dev->crtc_id);
|
||||
drm_add_plane_property(drm_dev, "SRC_X", 0);
|
||||
drm_add_plane_property(drm_dev, "SRC_Y", 0);
|
||||
drm_add_plane_property(drm_dev, "SRC_W", drm_dev->width << 16);
|
||||
drm_add_plane_property(drm_dev, "SRC_H", drm_dev->height << 16);
|
||||
drm_add_plane_property(drm_dev, "CRTC_X", 0);
|
||||
drm_add_plane_property(drm_dev, "CRTC_Y", 0);
|
||||
drm_add_plane_property(drm_dev, "CRTC_W", drm_dev->width);
|
||||
drm_add_plane_property(drm_dev, "CRTC_H", drm_dev->height);
|
||||
|
||||
if(drm_dev->kms_in_fence_fd != -1) {
|
||||
drm_add_crtc_property(drm_dev, "OUT_FENCE_PTR", (uintptr_t) &drm_dev->kms_out_fence_fd);
|
||||
drm_add_plane_property(drm_dev, "IN_FENCE_FD", drm_dev->kms_in_fence_fd);
|
||||
}
|
||||
|
||||
ret = drmModeAtomicCommit(drm_dev->fd, drm_dev->req, flags, NULL);
|
||||
if(ret) {
|
||||
LV_LOG_ERROR("drmModeAtomicCommit failed: %s (%d)", strerror(errno), errno);
|
||||
drmModeAtomicFree(drm_dev->req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(drm_dev->kms_in_fence_fd != -1) {
|
||||
close(drm_dev->kms_in_fence_fd);
|
||||
drm_dev->kms_in_fence_fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static EGLSyncKHR create_fence(drm_dev_t * drm_dev, EGLDisplay display, int fd)
|
||||
{
|
||||
EGLint attrib_list[] = {
|
||||
EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd,
|
||||
EGL_NONE,
|
||||
};
|
||||
EGLSyncKHR fence = drm_dev->egl_create_sync_khr(display, EGL_SYNC_NATIVE_FENCE_ANDROID, attrib_list);
|
||||
LV_ASSERT_NULL(fence);
|
||||
return fence;
|
||||
}
|
||||
|
||||
#endif /*LV_LINUX_DRM_USE_EGL*/
|
||||
|
||||
static uint32_t tick_get_cb(void)
|
||||
{
|
||||
@@ -1366,4 +1055,4 @@ static uint32_t tick_get_cb(void)
|
||||
return time_ms;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_LINUX_DRM*/
|
||||
#endif /*LV_USE_LINUX_DRM && !LV_LINUX_DRM_USE_EGL*/
|
||||
|
||||
@@ -29,10 +29,41 @@ extern "C" {
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Create a new Linux DRM display
|
||||
*
|
||||
* Creates and initializes a new LVGL display using the Linux DRM (Direct Rendering Manager)
|
||||
* subsystem for hardware-accelerated graphics output.
|
||||
*
|
||||
* @return Pointer to the created display object, or NULL on failure
|
||||
*/
|
||||
lv_display_t * lv_linux_drm_create(void);
|
||||
|
||||
/**
|
||||
* @brief Configure the DRM device file and connector for a display
|
||||
*
|
||||
* Sets the DRM device file path and connector ID to use for the specified display.
|
||||
* The DRM device file is typically located at /dev/dri/cardN where N is the card number.
|
||||
* The connector ID specifies which physical output (HDMI, VGA, etc.) to use.
|
||||
*
|
||||
* @param disp Pointer to the display object created with lv_linux_drm_create()
|
||||
* @param file Path to the DRM device file (e.g., "/dev/dri/card0")
|
||||
* @param connector_id ID of the DRM connector to use, or -1 to auto-select the first available
|
||||
*/
|
||||
void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t connector_id);
|
||||
|
||||
/**
|
||||
* @brief Automatically find a suitable DRM device path
|
||||
*
|
||||
* Scans the system for available DRM devices and returns the path to a suitable
|
||||
* device file that can be used with lv_linux_drm_set_file().
|
||||
*
|
||||
* @return Dynamically allocated string containing the device path (must be freed with lv_free()),
|
||||
* or NULL if no suitable device is found
|
||||
*/
|
||||
char * lv_linux_drm_find_device_path(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @file lv_linux_drm_common.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_linux_drm.h"
|
||||
|
||||
#if LV_USE_LINUX_DRM
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#include "lv_linux_drm.h"
|
||||
#include "../../../stdlib/lv_sprintf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_DRM_CLASS_DIR "/sys/class/drm"
|
||||
#define LV_DRM_CARD_PATH "/dev/dri/card"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static char * find_by_class(void);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
char * lv_linux_drm_find_device_path(void)
|
||||
{
|
||||
return find_by_class();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static char * find_by_class(void)
|
||||
{
|
||||
DIR * d = opendir(LV_DRM_CLASS_DIR);
|
||||
if(!d) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dirent * ent;
|
||||
while((ent = readdir(d)) != NULL) {
|
||||
if(lv_strcmp(ent->d_name, ".") == 0 || lv_strcmp(ent->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
/* connector dirs look like card0-HDMI-A-1, card0-eDP-1, etc. */
|
||||
bool is_card = lv_strncmp(ent->d_name, "card", 4) == 0;
|
||||
bool is_connected = lv_strchr(ent->d_name, '-') != NULL;
|
||||
|
||||
if(!is_card || !is_connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t buf_size = lv_strlen(LV_DRM_CARD_PATH) + 3;
|
||||
char * card_path = lv_zalloc(buf_size);
|
||||
if(ent->d_name[5] != '-') {
|
||||
/* Double digit card*/
|
||||
lv_snprintf(card_path, buf_size, LV_DRM_CARD_PATH "%c%c", ent->d_name[4], ent->d_name[5]);
|
||||
}
|
||||
else {
|
||||
lv_snprintf(card_path, buf_size, LV_DRM_CARD_PATH "%c", ent->d_name[4]);
|
||||
}
|
||||
closedir(d);
|
||||
return card_path;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
#endif /*LV_USE_LINUX_DRM*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @file lv_linux_drm_egl_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LINUX_DRM_EGL_PRIVATE_H
|
||||
#define LV_LINUX_DRM_EGL_PRIVATE_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_LINUX_DRM && LV_LINUX_DRM_USE_EGL
|
||||
|
||||
#include <xf86drmMode.h>
|
||||
#include "../../opengles/lv_opengles_texture_private.h"
|
||||
#include "../../opengles/lv_opengles_egl.h"
|
||||
#include "../../opengles/lv_opengles_egl_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_opengles_texture_t texture;
|
||||
lv_display_t * display;
|
||||
lv_opengles_egl_t * egl_ctx;
|
||||
lv_egl_interface_t egl_interface;
|
||||
|
||||
drmModeRes * drm_resources;
|
||||
drmModeConnector * drm_connector;
|
||||
drmModeEncoder * drm_encoder;
|
||||
drmModeCrtc * drm_crtc;
|
||||
drmModeModeInfo * drm_mode;
|
||||
|
||||
struct gbm_device * gbm_dev;
|
||||
struct gbm_surface * gbm_surface;
|
||||
struct gbm_bo * gbm_bo_pending;
|
||||
struct gbm_bo * gbm_bo_flipped;
|
||||
struct gbm_bo * gbm_bo_presented;
|
||||
|
||||
int fd;
|
||||
bool crtc_isset;
|
||||
} lv_drm_ctx_t;
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_LINUX_DRM && LV_LINUX_DRM_USE_EGL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*LV_LINUX_DRM_EGL_PRIVATE_H*/
|
||||
@@ -6,40 +6,28 @@
|
||||
#include <string.h>
|
||||
|
||||
static const lv_opengl_shader_t src_includes[] = {
|
||||
{ "hsv_adjust.glsl", R"(
|
||||
{
|
||||
"hsv_adjust.glsl", R"(
|
||||
|
||||
uniform float u_Hue;
|
||||
uniform float u_Saturation;
|
||||
uniform float u_Value;
|
||||
|
||||
vec3 rgb2hsv(vec3 c){
|
||||
float M = max(max(c.r,c.g),c.b);
|
||||
float m = min(min(c.r,c.g),c.b);
|
||||
float d = M - m;
|
||||
float h = 0.0;
|
||||
if(d > 0.00001){
|
||||
if(M == c.r) h = mod((c.g - c.b)/d, 6.0);
|
||||
else if(M == c.g) h = (c.b - c.r)/d + 2.0;
|
||||
else h = (c.r - c.g)/d + 4.0;
|
||||
h /= 6.0;
|
||||
}
|
||||
float s = (M <= 0.00001) ? 0.0 : d / M;
|
||||
return vec3(h, s, M);
|
||||
// Convert RGB to HSV
|
||||
vec3 rgb2hsv(vec3 c) {
|
||||
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(vec3 c){
|
||||
float h = c.x * 6.0;
|
||||
float i = floor(h);
|
||||
float f = h - i;
|
||||
float p = c.z * (1.0 - c.y);
|
||||
float q = c.z * (1.0 - c.y * f);
|
||||
float t = c.z * (1.0 - c.y * (1.0 - f));
|
||||
if(i == 0.0) return vec3(c.z, t, p);
|
||||
if(i == 1.0) return vec3(q, c.z, p);
|
||||
if(i == 2.0) return vec3(p, c.z, t);
|
||||
if(i == 3.0) return vec3(p, q, c.z);
|
||||
if(i == 4.0) return vec3(t, p, c.z);
|
||||
return vec3(c.z, p, q);
|
||||
// Convert HSV to RGB
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
vec3 adjustHSV(vec3 color){
|
||||
@@ -49,23 +37,28 @@ static const lv_opengl_shader_t src_includes[] = {
|
||||
hsv.z = clamp(hsv.z * u_Value, 0.0, 1.0);
|
||||
return hsv2rgb(hsv);
|
||||
}
|
||||
)" },
|
||||
{ "brightness_adjust.glsl", R"(
|
||||
)"
|
||||
},
|
||||
{
|
||||
"brightness_adjust.glsl", R"(
|
||||
uniform float u_Brightness; // add/subtract in [ -1.0 .. +1.0 ], 0.0 = no change
|
||||
|
||||
vec3 adjustBrightness(vec3 color){
|
||||
return clamp(color + vec3(u_Brightness), 0.0, 1.0);
|
||||
}
|
||||
|
||||
)" },
|
||||
{ "contrast_adjust.glsl", R"(
|
||||
)"
|
||||
},
|
||||
{
|
||||
"contrast_adjust.glsl", R"(
|
||||
uniform float u_Contrast; // 0.0 = mid-gray, 1.0 = no change, >1.0 increases contrast
|
||||
|
||||
vec3 adjustContrast(vec3 color){
|
||||
// shift to [-0.5..0.5], scale, shift back
|
||||
return clamp(((color - 0.5) * u_Contrast) + 0.5, 0.0, 1.0);
|
||||
}
|
||||
)" },
|
||||
)"
|
||||
},
|
||||
};
|
||||
|
||||
static const char * src_vertex_shader = R"(
|
||||
@@ -98,13 +91,18 @@ static const char *src_fragment_shader = R"(
|
||||
uniform bool u_IsFill;
|
||||
uniform vec3 u_FillColor;
|
||||
|
||||
#ifdef HSV_ADJUST
|
||||
#include <hsv_adjust.glsl>
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texColor;
|
||||
if (u_IsFill) {
|
||||
texColor = vec4(u_FillColor, 1.0);
|
||||
} else {
|
||||
texColor = texture(u_Texture, v_TexCoord);
|
||||
//texColor = texture(u_Texture, v_TexCoord);
|
||||
texColor = textureLod(u_Texture, v_TexCoord, 0.0); // If the vertices have been transformed, and mipmaps have not been generated, some rotation angles (notably 90 and 270) require using textureLod() to mitigate derivative calculation errors from increments flipping direction
|
||||
}
|
||||
if (abs(u_ColorDepth - 8.0) < 0.1) {
|
||||
float gray = texColor.r;
|
||||
@@ -113,6 +111,9 @@ static const char *src_fragment_shader = R"(
|
||||
float combinedAlpha = texColor.a * u_Opa;
|
||||
color = vec4(texColor.rgb * combinedAlpha, combinedAlpha);
|
||||
}
|
||||
#ifdef HSV_ADJUST
|
||||
color.rgb = adjustHSV(color.rgb);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -132,8 +133,8 @@ char* lv_opengles_standard_shader_get_fragment(void) {
|
||||
|
||||
void lv_opengles_standard_shader_get_src(lv_opengl_shader_portions_t *portions)
|
||||
{
|
||||
portions->all = src_includes;
|
||||
portions->count = sizeof(src_includes) / sizeof(src_includes[0]);
|
||||
portions->all = src_includes;
|
||||
portions->count = sizeof(src_includes) / sizeof(src_includes[0]);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
@@ -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_render_draw(void);
|
||||
static float lv_opengles_map_float(float x, float min_in, float max_in, float min_out, float max_out);
|
||||
static void populate_vertex_buffer(float vertex_buffer[LV_OPENGLES_VERTEX_BUFFER_LEN],
|
||||
lv_display_rotation_t rotation, bool * h_flip, bool * v_flip,
|
||||
float clip_x1, float clip_y1, float clip_x2, float clip_y2);
|
||||
|
||||
/***********************
|
||||
* GLOBAL PROTOTYPES
|
||||
@@ -85,8 +88,8 @@ static unsigned int index_buffer_count = 0;
|
||||
|
||||
static unsigned int shader_id;
|
||||
|
||||
static const char * shader_names[] = { "u_Texture", "u_ColorDepth", "u_VertexTransform", "u_Opa", "u_IsFill", "u_FillColor" };
|
||||
static int shader_location[] = { 0, 0, 0, 0, 0, 0 };
|
||||
static const char * shader_names[] = { "u_Texture", "u_ColorDepth", "u_VertexTransform", "u_Opa", "u_IsFill", "u_FillColor", "u_Hue", "u_Saturation", "u_Value" };
|
||||
static int shader_location[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@@ -154,6 +157,44 @@ void lv_opengles_render_fill(lv_color_t color, const lv_area_t * area, lv_opa_t
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_opengles_render_display_texture(lv_display_t * display, bool h_flip, bool v_flip)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
unsigned int texture = *(unsigned int *)lv_display_get_driver_data(display);
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture));
|
||||
|
||||
lv_display_rotation_t rotation = lv_display_get_rotation(display);
|
||||
|
||||
float vert_buffer[LV_OPENGLES_VERTEX_BUFFER_LEN];
|
||||
populate_vertex_buffer(vert_buffer, rotation, &h_flip, &v_flip, 0.f, 0.f, 1.f, 1.f);
|
||||
lv_opengles_vertex_buffer_init(vert_buffer, sizeof(vert_buffer));
|
||||
|
||||
float hor_scale = 1.0f;
|
||||
float ver_scale = 1.0f;
|
||||
float hor_translate = 0.0f;
|
||||
float ver_translate = 0.0f;
|
||||
hor_scale = h_flip ? -hor_scale : hor_scale;
|
||||
ver_scale = v_flip ? ver_scale : -ver_scale;
|
||||
|
||||
float matrix[9] = {
|
||||
hor_scale, 0.0f, hor_translate,
|
||||
0.0f, ver_scale, ver_translate,
|
||||
0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
lv_opengles_shader_bind();
|
||||
lv_opengles_shader_set_uniform1f("u_ColorDepth", LV_COLOR_DEPTH);
|
||||
lv_opengles_shader_set_uniform1i("u_Texture", 0);
|
||||
lv_opengles_shader_set_uniformmatrix3fv("u_VertexTransform", 1, true, matrix);
|
||||
lv_opengles_shader_set_uniform1f("u_Opa", 1);
|
||||
lv_opengles_shader_set_uniform1i("u_IsFill", 0);
|
||||
lv_opengles_shader_set_uniform3f("u_FillColor", 1.0f, 1.0f, 1.0f);
|
||||
|
||||
lv_opengles_render_draw();
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_opengles_render_clear(void)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
@@ -341,14 +382,10 @@ static void lv_opengles_shader_manager_init(void)
|
||||
|
||||
static unsigned int lv_opengles_shader_program_init(void)
|
||||
{
|
||||
/* To add defines: lv_opengl_shader_define_t frag_defs[1] = { { "PLACEHOLDER", NULL, false} }; */
|
||||
|
||||
uint32_t frag_shader_hash = lv_opengl_shader_manager_select_shader(&shader_manager, "__MAIN__.frag", NULL, 0);
|
||||
uint32_t vert_shader_hash = lv_opengl_shader_manager_select_shader(&shader_manager, "__MAIN__.vert", NULL, 0);
|
||||
|
||||
lv_opengl_shader_program_t * program = lv_opengl_shader_manager_get_program(&shader_manager, frag_shader_hash,
|
||||
vert_shader_hash);
|
||||
|
||||
return lv_opengl_shader_program_get_id(program);
|
||||
}
|
||||
|
||||
@@ -466,4 +503,97 @@ static float lv_opengles_map_float(float x, float min_in, float max_in, float mi
|
||||
return ((x - min_in) * delta_out) / delta_in + min_out;
|
||||
}
|
||||
|
||||
static void populate_vertex_buffer(float vertex_buffer[LV_OPENGLES_VERTEX_BUFFER_LEN],
|
||||
lv_display_rotation_t rotation, bool * h_flip, bool * v_flip, float clip_x1, float clip_y1, float clip_x2,
|
||||
float clip_y2)
|
||||
{
|
||||
#if !LV_USE_DRAW_OPENGLES
|
||||
LV_UNUSED(h_flip);
|
||||
LV_UNUSED(v_flip);
|
||||
#endif
|
||||
switch(rotation) {
|
||||
case LV_DISPLAY_ROTATION_0:
|
||||
vertex_buffer[0] = -1.f;
|
||||
vertex_buffer[1] = 1.0f;
|
||||
vertex_buffer[2] = clip_x1;
|
||||
vertex_buffer[3] = clip_y2;
|
||||
vertex_buffer[4] = 1.0f;
|
||||
vertex_buffer[5] = 1.0f;
|
||||
vertex_buffer[6] = clip_x2;
|
||||
vertex_buffer[7] = clip_y2;
|
||||
vertex_buffer[8] = 1.0f;
|
||||
vertex_buffer[9] = -1.0f;
|
||||
vertex_buffer[10] = clip_x2;
|
||||
vertex_buffer[11] = clip_y1;
|
||||
vertex_buffer[12] = -1.f;
|
||||
vertex_buffer[13] = -1.0f;
|
||||
vertex_buffer[14] = clip_x1;
|
||||
vertex_buffer[15] = clip_y1;
|
||||
break;
|
||||
|
||||
case LV_DISPLAY_ROTATION_270:
|
||||
#if LV_USE_DRAW_OPENGLES
|
||||
*h_flip = !*h_flip;
|
||||
*v_flip = !*v_flip;
|
||||
#endif
|
||||
vertex_buffer[0] = 1.0f;
|
||||
vertex_buffer[1] = 1.0f;
|
||||
vertex_buffer[2] = clip_x1;
|
||||
vertex_buffer[3] = clip_y2;
|
||||
vertex_buffer[4] = 1.0f;
|
||||
vertex_buffer[5] = -1.0f;
|
||||
vertex_buffer[6] = clip_x2;
|
||||
vertex_buffer[7] = clip_y2;
|
||||
vertex_buffer[8] = -1.f;
|
||||
vertex_buffer[9] = -1.0f;
|
||||
vertex_buffer[10] = clip_x2;
|
||||
vertex_buffer[11] = clip_y1;
|
||||
vertex_buffer[12] = -1.f;
|
||||
vertex_buffer[13] = 1.0f;
|
||||
vertex_buffer[14] = clip_x1;
|
||||
vertex_buffer[15] = clip_y1;
|
||||
break;
|
||||
|
||||
case LV_DISPLAY_ROTATION_180:
|
||||
vertex_buffer[0] = 1.0f;
|
||||
vertex_buffer[1] = -1.0f;
|
||||
vertex_buffer[2] = clip_x1;
|
||||
vertex_buffer[3] = clip_y2;
|
||||
vertex_buffer[4] = -1.f;
|
||||
vertex_buffer[5] = -1.0f;
|
||||
vertex_buffer[6] = clip_x2;
|
||||
vertex_buffer[7] = clip_y2;
|
||||
vertex_buffer[8] = -1.f;
|
||||
vertex_buffer[9] = 1.0f;
|
||||
vertex_buffer[10] = clip_x2;
|
||||
vertex_buffer[11] = clip_y1;
|
||||
vertex_buffer[12] = 1.0f;
|
||||
vertex_buffer[13] = 1.0f;
|
||||
vertex_buffer[14] = clip_x1;
|
||||
vertex_buffer[15] = clip_y1;
|
||||
break;
|
||||
case LV_DISPLAY_ROTATION_90:
|
||||
#if LV_USE_DRAW_OPENGLES
|
||||
*h_flip = !*h_flip;
|
||||
*v_flip = !*v_flip;
|
||||
#endif
|
||||
vertex_buffer[0] = -1.f;
|
||||
vertex_buffer[1] = -1.0f;
|
||||
vertex_buffer[2] = clip_x1;
|
||||
vertex_buffer[3] = clip_y2;
|
||||
vertex_buffer[4] = -1.f;
|
||||
vertex_buffer[5] = 1.0f;
|
||||
vertex_buffer[6] = clip_x2;
|
||||
vertex_buffer[7] = clip_y2;
|
||||
vertex_buffer[8] = 1.0f;
|
||||
vertex_buffer[9] = 1.0f;
|
||||
vertex_buffer[10] = clip_x2;
|
||||
vertex_buffer[11] = clip_y1;
|
||||
vertex_buffer[12] = 1.0f;
|
||||
vertex_buffer[13] = -1.0f;
|
||||
vertex_buffer[14] = clip_x1;
|
||||
vertex_buffer[15] = clip_y1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* LV_USE_OPENGLES */
|
||||
|
||||
@@ -57,6 +57,14 @@ void lv_opengles_deinit(void);
|
||||
void lv_opengles_render_texture(unsigned int texture, const lv_area_t * texture_area, lv_opa_t opa, int32_t disp_w,
|
||||
int32_t disp_h, const lv_area_t * texture_clip_area, bool h_flip, bool v_flip);
|
||||
|
||||
/**
|
||||
* Render a display texture - Supports rotation
|
||||
* @param display LVGL Texture display. Created with the `lv_opengles_texture` module
|
||||
* @param h_flip horizontal flip
|
||||
* @param v_flip vertical flip
|
||||
*/
|
||||
void lv_opengles_render_display_texture(lv_display_t * display, bool h_flip, bool v_flip);
|
||||
|
||||
/**
|
||||
* Render a fill
|
||||
* @param color the color of the fill
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,16 +10,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
|
||||
#if LV_USE_EGL
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -29,40 +29,26 @@ extern "C" {
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef void (*lv_opengles_egl_window_cb_t)(lv_opengles_window_t * window);
|
||||
typedef struct _lv_opengles_egl lv_opengles_egl_t;
|
||||
typedef struct _lv_egl_interface lv_egl_interface_t;
|
||||
typedef struct _lv_egl_config lv_egl_config_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create an EGL OpenGL window with no textures. OpenGL should be initialized beforehand.
|
||||
* @param hor_res width in pixels of the window
|
||||
* @param ver_res height in pixels of the window
|
||||
* @param native_window_handle a handle to a native window for the platform
|
||||
* @param device a `EGLNativeDisplayType`
|
||||
* @param pre called before rendering
|
||||
* @param post1 called after rendering, before swapping
|
||||
* @param post2 called after swapping
|
||||
* @return the new EGL OpenGL window handle
|
||||
*/
|
||||
lv_opengles_window_t * lv_opengles_egl_window_create(int32_t hor_res, int32_t ver_res, void * native_window_handle,
|
||||
void * device,
|
||||
lv_opengles_egl_window_cb_t pre,
|
||||
lv_opengles_egl_window_cb_t post1,
|
||||
lv_opengles_egl_window_cb_t post2);
|
||||
lv_opengles_egl_t * lv_opengles_egl_context_create(const lv_egl_interface_t * interface);
|
||||
lv_color_format_t lv_opengles_egl_color_format_from_egl_config(const lv_egl_config_t * config);
|
||||
|
||||
void * lv_opengles_egl_window_get_surface(lv_opengles_window_t * window);
|
||||
void * lv_opengles_egl_window_get_display(lv_opengles_window_t * window);
|
||||
void lv_opengles_egl_window_set_user_data(lv_opengles_window_t * window, void * user_data);
|
||||
void * lv_opengles_egl_window_get_user_data(lv_opengles_window_t * window);
|
||||
void lv_opengles_egl_update(lv_opengles_egl_t * ctx);
|
||||
void lv_opengles_egl_clear(lv_opengles_egl_t * ctx);
|
||||
void lv_opengles_egl_context_destroy(lv_opengles_egl_t * ctx);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_EGL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @file lv_opengles_egl_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OPENGLES_EGL_PRIVATE_H
|
||||
#define LV_OPENGLES_EGL_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_EGL
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "lv_opengles_private.h"
|
||||
#include "lv_opengles_egl.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_egl_config {
|
||||
EGLint id;
|
||||
EGLint max_width;
|
||||
EGLint max_height;
|
||||
EGLint buffer_size;
|
||||
EGLint depth;
|
||||
EGLint stencil;
|
||||
EGLint samples;
|
||||
EGLint surface_type;
|
||||
EGLint r_bits;
|
||||
EGLint g_bits;
|
||||
EGLint b_bits;
|
||||
EGLint a_bits;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EGLint visual_id;
|
||||
} lv_egl_native_window_properties_t;
|
||||
|
||||
typedef void * (*lv_egl_init_display_t)(void * driver_data, int32_t width, int32_t height);
|
||||
typedef void * (*lv_egl_get_display_t)(void * driver_data);
|
||||
typedef void * (*lv_create_window_t)(void * driver_data, const lv_egl_native_window_properties_t * props);
|
||||
typedef void (*lv_destroy_window_t)(void * driver_data, void * native_window);
|
||||
|
||||
typedef void (*lv_egl_set_visible_t)(void * driver_data, bool v);
|
||||
typedef void (*lv_egl_flip_t)(void * driver_data, bool vsync);
|
||||
typedef void (*lv_egl_native_state_deinit_t)(void ** driver_data);
|
||||
typedef size_t (*lv_egl_select_config_t)(void * driver_data, const lv_egl_config_t * configs,
|
||||
size_t config_count);
|
||||
|
||||
struct _lv_egl_interface {
|
||||
lv_egl_select_config_t select_config;
|
||||
void * driver_data;
|
||||
void * native_display;
|
||||
uint16_t egl_platform;
|
||||
lv_create_window_t create_window_cb;
|
||||
lv_destroy_window_t destroy_window_cb;
|
||||
lv_egl_flip_t flip_cb;
|
||||
};
|
||||
|
||||
|
||||
struct _lv_opengles_egl {
|
||||
EGLNativeWindowType native_window;
|
||||
EGLDisplay egl_display;
|
||||
EGLConfig egl_config;
|
||||
EGLContext egl_context;
|
||||
EGLSurface egl_surface;
|
||||
void * egl_lib_handle;
|
||||
void * opengl_lib_handle;
|
||||
lv_egl_interface_t interface;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
bool vsync;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_EGL*/
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OPENGLES_EGL_PRIVATE_H*/
|
||||
@@ -18,11 +18,8 @@ extern "C" {
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#if LV_USE_EGL
|
||||
#include <GLES/gl.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#include "glad/include/glad/gles2.h"
|
||||
#include "glad/include/glad/egl.h"
|
||||
#else
|
||||
/* For now, by default we add glew and glfw.
|
||||
In the future we need to consider adding a config for setting these includes*/
|
||||
@@ -40,9 +37,25 @@ extern "C" {
|
||||
#define GL_BGRA GL_BGRA_EXT
|
||||
#endif /*GL_BGRA*/
|
||||
|
||||
#ifndef GL_BGR
|
||||
#define GL_BGR GL_BGR_EXT
|
||||
#endif /*GL_BGR*/
|
||||
#ifndef GL_TEXTURE_MAX_LEVEL
|
||||
#define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE
|
||||
#endif /*GL_TEXTURE_MAX_LEVEL*/
|
||||
|
||||
#ifndef GL_UNPACK_ROW_LENGTH
|
||||
#define GL_UNPACK_ROW_LENGTH GL_UNPACK_ROW_LENGTH_EXT
|
||||
#endif /*GL_UNPACK_ROW_LENGTH*/
|
||||
|
||||
#ifndef glGenVertexArrays
|
||||
#define glGenVertexArrays glGenVertexArraysOES
|
||||
#endif
|
||||
|
||||
#ifndef glBindVertexArray
|
||||
#define glBindVertexArray glBindVertexArrayOES
|
||||
#endif
|
||||
|
||||
#ifndef glDeleteVertexArrays
|
||||
#define glDeleteVertexArrays glDeleteVertexArraysOES
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include "lv_opengles_debug.h"
|
||||
#include "lv_opengles_private.h"
|
||||
|
||||
#include "lv_opengles_driver.h"
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
#include "lv_opengles_private.h"
|
||||
#include "lv_opengles_texture_private.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -26,14 +29,6 @@
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
unsigned int texture_id;
|
||||
#if !LV_USE_DRAW_OPENGLES
|
||||
uint8_t * fb1;
|
||||
#endif /*!LV_USE_DRAW_OPENGLES*/
|
||||
bool is_texture_owner;
|
||||
} lv_opengles_texture_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
@@ -55,11 +50,11 @@ static void release_disp_cb(lv_event_t * e);
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h)
|
||||
{
|
||||
lv_display_t * disp = lv_opengles_texture_create_common(w, h);
|
||||
if(!disp) {
|
||||
LV_LOG_ERROR("Failed to create display");
|
||||
return NULL;
|
||||
}
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
@@ -73,6 +68,7 @@ lv_display_t * lv_opengles_texture_create_from_texture_id(int32_t w, int32_t h,
|
||||
{
|
||||
lv_display_t * disp = lv_opengles_texture_create_common(w, h);
|
||||
if(!disp) {
|
||||
LV_LOG_ERROR("Failed to create display");
|
||||
return NULL;
|
||||
}
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
@@ -81,6 +77,66 @@ lv_display_t * lv_opengles_texture_create_from_texture_id(int32_t w, int32_t h,
|
||||
return disp;
|
||||
}
|
||||
|
||||
void lv_opengles_texture_reshape(lv_display_t * disp, int32_t width, int32_t height)
|
||||
{
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
unsigned int new_texture = create_texture(width, height);
|
||||
if(new_texture == GL_NONE) {
|
||||
LV_LOG_ERROR("Failed to reshape texture. Couldn't acquire new texture from GPU");
|
||||
return;
|
||||
}
|
||||
#if !LV_USE_DRAW_OPENGLES
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(width, lv_display_get_color_format(disp));
|
||||
uint32_t buf_size = stride * height;
|
||||
uint8_t * buffer = lv_realloc(dsc->fb1, buf_size);
|
||||
LV_ASSERT_MALLOC(buffer);
|
||||
if(!buffer) {
|
||||
GL_CALL(glDeleteTextures(1, &new_texture));
|
||||
LV_LOG_ERROR("Failed to reshape texture. Couldn't resize buffer");
|
||||
return;
|
||||
}
|
||||
dsc->fb1 = buffer;
|
||||
#endif /*!LV_USE_DRAW_OPENGLES*/
|
||||
|
||||
if(dsc->is_texture_owner && dsc->texture_id != 0) {
|
||||
GL_CALL(glDeleteTextures(1, &dsc->texture_id));
|
||||
}
|
||||
dsc->texture_id = new_texture;
|
||||
}
|
||||
|
||||
lv_result_t lv_opengles_texture_create_draw_buffers(lv_opengles_texture_t * texture, lv_display_t * display)
|
||||
{
|
||||
int32_t w = lv_display_get_horizontal_resolution(display);
|
||||
int32_t h = lv_display_get_vertical_resolution(display);
|
||||
|
||||
#if LV_USE_DRAW_OPENGLES
|
||||
LV_UNUSED(texture);
|
||||
static size_t LV_ATTRIBUTE_MEM_ALIGN dummy_buf;
|
||||
lv_display_set_buffers(display, &dummy_buf, NULL, w * h * 4, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
#else
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(w, lv_display_get_color_format(display));
|
||||
uint32_t buf_size = stride * h;
|
||||
texture->fb1 = lv_malloc(buf_size);
|
||||
LV_ASSERT_MALLOC(texture->fb1);
|
||||
if(!texture->fb1) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
lv_display_set_buffers(display, texture->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
#endif
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
void lv_opengles_texture_deinit(lv_opengles_texture_t * texture)
|
||||
{
|
||||
#if !LV_USE_DRAW_OPENGLES
|
||||
lv_free(texture->fb1);
|
||||
#endif /*!LV_USE_DRAW_OPENGLES*/
|
||||
|
||||
if(texture->is_texture_owner && texture->texture_id != 0) {
|
||||
GL_CALL(glDeleteTextures(1, &texture->texture_id));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int lv_opengles_texture_get_texture_id(lv_display_t * disp)
|
||||
{
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
@@ -106,34 +162,29 @@ lv_display_t * lv_opengles_texture_get_from_texture_id(unsigned int texture_id)
|
||||
static lv_display_t * lv_opengles_texture_create_common(int32_t w, int32_t h)
|
||||
{
|
||||
lv_display_t * disp = lv_display_create(w, h);
|
||||
if(disp == NULL) {
|
||||
if(!disp) {
|
||||
LV_LOG_ERROR("Failed to create display");
|
||||
return NULL;
|
||||
}
|
||||
lv_opengles_texture_t * dsc = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
if(dsc == NULL) {
|
||||
lv_opengles_texture_t * texture = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
|
||||
LV_ASSERT_MALLOC(texture);
|
||||
if(!texture) {
|
||||
LV_LOG_ERROR("Failed to create texture");
|
||||
lv_display_delete(disp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_USE_DRAW_OPENGLES
|
||||
static size_t LV_ATTRIBUTE_MEM_ALIGN dummy_buf;
|
||||
lv_display_set_buffers(disp, &dummy_buf, NULL, w * h * 4, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
#else
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(w, lv_display_get_color_format(disp));
|
||||
uint32_t buf_size = stride * h;
|
||||
dsc->fb1 = malloc(buf_size);
|
||||
LV_ASSERT_MALLOC(dsc->fb1);
|
||||
if(dsc->fb1 == NULL) {
|
||||
lv_free(dsc);
|
||||
lv_result_t res = lv_opengles_texture_create_draw_buffers(texture, disp);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Failed to create draw buffers");
|
||||
lv_free(texture);
|
||||
lv_display_delete(disp);
|
||||
return NULL;
|
||||
}
|
||||
lv_display_set_buffers(disp, dsc->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
#endif
|
||||
lv_display_set_resolution(disp, w, h);
|
||||
lv_display_set_flush_cb(disp, flush_cb);
|
||||
lv_display_set_driver_data(disp, dsc);
|
||||
lv_display_set_driver_data(disp, texture);
|
||||
lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
|
||||
|
||||
lv_opengles_init();
|
||||
return disp;
|
||||
}
|
||||
@@ -150,27 +201,32 @@ static unsigned int create_texture(int32_t w, int32_t h)
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
|
||||
/* set the dimensions and format to complete the texture */
|
||||
/* Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888) */
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, NULL));
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/* Color depth: 16 (RGB565), 32 (XRGB8888) */
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
NULL));
|
||||
#elif LV_COLOR_DEPTH == 24
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL));
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
|
||||
#else
|
||||
#error("Unsupported color format")
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
GL_CALL(glGenerateMipmap(GL_TEXTURE_2D));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
return texture;
|
||||
#endif
|
||||
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, GL_NONE));
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||
{
|
||||
LV_UNUSED(area);
|
||||
@@ -187,14 +243,10 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
|
||||
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / lv_color_format_get_size(cf)));
|
||||
/*Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, disp->hor_res, disp->ver_res, 0, GL_RED, GL_UNSIGNED_BYTE, dsc->fb1));
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Color depth: 16 (RGB565), 32 (XRGB8888)*/
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, disp->hor_res, disp->ver_res, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
dsc->fb1));
|
||||
#elif LV_COLOR_DEPTH == 24
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, disp->hor_res, disp->ver_res, 0, GL_BGR, GL_UNSIGNED_BYTE, dsc->fb1));
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, disp->hor_res, disp->ver_res, 0, GL_BGRA, GL_UNSIGNED_BYTE, dsc->fb1));
|
||||
#else
|
||||
@@ -209,14 +261,9 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
|
||||
static void release_disp_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = lv_event_get_user_data(e);
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
#if !LV_USE_DRAW_OPENGLES
|
||||
free(dsc->fb1);
|
||||
#endif /*!LV_USE_DRAW_OPENGLES*/
|
||||
if(dsc->is_texture_owner) {
|
||||
GL_CALL(glDeleteTextures(1, &dsc->texture_id));
|
||||
}
|
||||
lv_free(dsc);
|
||||
lv_opengles_texture_t * texture = lv_display_get_driver_data(disp);
|
||||
lv_opengles_texture_deinit(texture);
|
||||
lv_free(texture);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file lv_opengles_texture_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_OPENGLES_TEXTURE_PRIVATE_H
|
||||
#define LV_OPENGLES_TEXTURE_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include "lv_opengles_texture.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
unsigned int texture_id;
|
||||
#if !LV_USE_DRAW_OPENGLES
|
||||
uint8_t * fb1;
|
||||
#endif /*!LV_USE_DRAW_OPENGLES*/
|
||||
bool is_texture_owner;
|
||||
} lv_opengles_texture_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_result_t lv_opengles_texture_create_draw_buffers(lv_opengles_texture_t * texture, lv_display_t * display);
|
||||
void lv_opengles_texture_reshape(lv_display_t * disp, int32_t width, int32_t height);
|
||||
void lv_opengles_texture_deinit(lv_opengles_texture_t * texture);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_OPENGLES_TEXTURE_PRIVATE_H */
|
||||
@@ -19,6 +19,8 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define INVALID_LOCATION 0xFFFFFFFFu
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -87,14 +89,15 @@ GLuint lv_opengl_shader_program_get_id(lv_opengl_shader_program_t * program)
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void update_uniform_1i(lv_opengl_shader_program_t * program, const char * prop,
|
||||
int value)
|
||||
{
|
||||
GLuint location = glGetUniformLocation(program->id, prop);
|
||||
LV_ASSERT_FORMAT_MSG(location != GL_INVALID_INDEX,
|
||||
LV_ASSERT_FORMAT_MSG(location != INVALID_LOCATION,
|
||||
"Uniform '%s' not found in program %d",
|
||||
prop, program->id);
|
||||
if(location == GL_INVALID_INDEX) {
|
||||
if(location == INVALID_LOCATION) {
|
||||
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
|
||||
program->id);
|
||||
return;
|
||||
@@ -107,10 +110,10 @@ static void update_uniform_1f(lv_opengl_shader_program_t * program, const char *
|
||||
{
|
||||
GLuint location = glGetUniformLocation(program->id, prop);
|
||||
|
||||
LV_ASSERT_FORMAT_MSG(location != GL_INVALID_INDEX,
|
||||
LV_ASSERT_FORMAT_MSG(location != INVALID_LOCATION,
|
||||
"Uniform '%s' not found in program %d",
|
||||
prop, program->id);
|
||||
if(location == GL_INVALID_INDEX) {
|
||||
if(location == INVALID_LOCATION) {
|
||||
LV_LOG_ERROR("Uniform '%s' not found in program %d", prop,
|
||||
program->id);
|
||||
return;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user