mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-21 14:32:44 +08:00
feat(opengles): multiple windows and embed user opengl textures (#6600)
Co-authored-by: Dany Liu <dany.yang.liu@email.com>
This commit is contained in:
@@ -26,8 +26,8 @@ Configure OpenGL driver
|
||||
|
||||
#define LV_USE_OPENGLES 1
|
||||
|
||||
Usage
|
||||
-----
|
||||
Basic usage
|
||||
-----------
|
||||
|
||||
.. code:: c
|
||||
|
||||
@@ -35,31 +35,163 @@ Usage
|
||||
#include "lvgl/examples/lv_examples.h"
|
||||
#include "lvgl/demos/lv_demos.h"
|
||||
|
||||
#define WIDTH 640
|
||||
#define HEIGHT 480
|
||||
|
||||
int main()
|
||||
{
|
||||
/* initialize lvgl */
|
||||
lv_init();
|
||||
|
||||
lv_display_t * disp = lv_glfw_window_create(480, 272);
|
||||
/* create a window and initialize OpenGL */
|
||||
lv_glfw_window_t * window = lv_glfw_window_create(WIDTH, HEIGHT, true);
|
||||
|
||||
lv_indev_t * mouse = lv_glfw_mouse_create();
|
||||
lv_indev_set_group(mouse, lv_group_get_default());
|
||||
lv_indev_set_display(mouse, disp);
|
||||
/* create a display that flushes to a texture */
|
||||
lv_display_t * texture = lv_opengles_texture_create(WIDTH, HEIGHT);
|
||||
lv_display_set_default(texture);
|
||||
|
||||
lv_display_set_default(disp);
|
||||
/* add the texture to the window */
|
||||
unsigned int texture_id = lv_opengles_texture_get_texture_id(texture);
|
||||
lv_glfw_texture_t * window_texture = lv_glfw_window_add_texture(window, texture_id, WIDTH, HEIGHT);
|
||||
|
||||
LV_IMAGE_DECLARE(mouse_cursor_icon); /*Declare the image file.*/
|
||||
lv_obj_t * cursor_obj;
|
||||
cursor_obj = lv_image_create(lv_screen_active()); /*Create an image object for the cursor */
|
||||
lv_image_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/
|
||||
lv_indev_set_cursor(mouse, cursor_obj); /*Connect the image object to the driver*/
|
||||
/* get the mouse indev of the window texture */
|
||||
lv_indev_t * mouse = lv_glfw_texture_get_mouse_indev(window_texture);
|
||||
|
||||
/* add a cursor to the mouse indev */
|
||||
LV_IMAGE_DECLARE(mouse_cursor_icon);
|
||||
lv_obj_t * cursor_obj = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(cursor_obj, &mouse_cursor_icon);
|
||||
lv_indev_set_cursor(mouse, cursor_obj);
|
||||
|
||||
/* create objects on the screen */
|
||||
lv_demo_widgets();
|
||||
|
||||
while (1)
|
||||
{
|
||||
uint32_t time_till_next = lv_timer_handler();
|
||||
lv_delay_ms(time_till_next);
|
||||
uint32_t time_until_next = lv_timer_handler();
|
||||
lv_delay_ms(time_until_next);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Advanced usage
|
||||
--------------
|
||||
|
||||
The OpenGL driver can draw textures from the user. A third-party library could be
|
||||
used to add content to a texture and the driver will draw the texture in the window.
|
||||
|
||||
.. code:: c
|
||||
|
||||
#include "lvgl/lvgl.h"
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define WIDTH 640
|
||||
#define HEIGHT 480
|
||||
|
||||
void custom_texture_example(void)
|
||||
{
|
||||
/*****************
|
||||
* MAIN WINDOW
|
||||
*****************/
|
||||
|
||||
/* create a window and initialize OpenGL */
|
||||
/* multiple windows can be created */
|
||||
lv_glfw_window_t * window = lv_glfw_window_create(WIDTH, HEIGHT, true);
|
||||
|
||||
/****************************
|
||||
* OPTIONAL MAIN TEXTURE
|
||||
****************************/
|
||||
|
||||
/* create a main display that flushes to a texture */
|
||||
lv_display_t * main_texture = lv_opengles_texture_create(WIDTH, HEIGHT);
|
||||
lv_display_set_default(main_texture);
|
||||
|
||||
/* add the main texture to the window */
|
||||
unsigned int main_texture_id = lv_opengles_texture_get_texture_id(main_texture);
|
||||
lv_glfw_texture_t * window_main_texture = lv_glfw_window_add_texture(window, main_texture_id, WIDTH, HEIGHT);
|
||||
|
||||
/* get the mouse indev of this main texture */
|
||||
lv_indev_t * main_texture_mouse = lv_glfw_texture_get_mouse_indev(window_main_texture);
|
||||
|
||||
/* add a cursor to the mouse indev */
|
||||
LV_IMAGE_DECLARE(mouse_cursor_icon);
|
||||
lv_obj_t * cursor_obj = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(cursor_obj, &mouse_cursor_icon);
|
||||
lv_indev_set_cursor(main_texture_mouse, cursor_obj);
|
||||
|
||||
/* create objects on the screen of the main texture */
|
||||
lv_demo_widgets();
|
||||
|
||||
/**********************
|
||||
* ANOTHER TEXTURE
|
||||
**********************/
|
||||
|
||||
/* create a sub display that flushes to a texture */
|
||||
const int32_t sub_texture_w = 300;
|
||||
const int32_t sub_texture_h = 300;
|
||||
lv_display_t * sub_texture = lv_opengles_texture_create(sub_texture_w, sub_texture_h);
|
||||
|
||||
/* add the sub texture to the window */
|
||||
unsigned int sub_texture_id = lv_opengles_texture_get_texture_id(sub_texture);
|
||||
lv_glfw_texture_t * window_sub_texture = lv_glfw_window_add_texture(window, sub_texture_id, sub_texture_w, sub_texture_h);
|
||||
|
||||
/* create objects on the screen of the sub texture */
|
||||
lv_display_set_default(sub_texture);
|
||||
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_black(), 0);
|
||||
lv_example_anim_2();
|
||||
lv_display_set_default(main_texture);
|
||||
|
||||
/* position the sub texture within the window */
|
||||
lv_glfw_texture_set_x(window_sub_texture, 250);
|
||||
lv_glfw_texture_set_y(window_sub_texture, 150);
|
||||
|
||||
/* optionally change the opacity of the sub texture */
|
||||
lv_glfw_texture_set_opa(window_sub_texture, LV_OPA_80);
|
||||
|
||||
/*********************************************
|
||||
* USE AN EXTERNAL OPENGL TEXTURE IN LVGL
|
||||
*********************************************/
|
||||
|
||||
unsigned int external_texture_id;
|
||||
glGenTextures(1, &external_texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, external_texture_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
LV_IMAGE_DECLARE(img_cogwheel_argb);
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
const int texture_format = GL_R8;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
const int texture_format = GL_RGB565;
|
||||
#elif LV_COLOR_DEPTH == 24
|
||||
const int texture_format = GL_RGB;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
const int texture_format = GL_RGBA;
|
||||
#else
|
||||
#error("Unsupported color format")
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, texture_format, img_cogwheel_argb.header.w, img_cogwheel_argb.header.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, img_cogwheel_argb.data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
/* add the external texture to the window */
|
||||
lv_glfw_texture_t * window_external_texture = lv_glfw_window_add_texture(window, external_texture_id, img_cogwheel_argb.header.w, img_cogwheel_argb.header.h);
|
||||
|
||||
/* set the position and opacity of the external texture within the window */
|
||||
lv_glfw_texture_set_x(window_external_texture, 20);
|
||||
lv_glfw_texture_set_y(window_external_texture, 20);
|
||||
lv_glfw_texture_set_opa(window_external_texture, LV_OPA_70);
|
||||
|
||||
/*********************************************
|
||||
* USE AN LVGL TEXTURE IN ANOTHER LIBRARY
|
||||
*********************************************/
|
||||
|
||||
lv_refr_now(sub_texture);
|
||||
|
||||
/* the texture is drawn on by LVGL and can be used by anything that uses OpenGL textures */
|
||||
third_party_lib_use_texture(sub_texture_id);
|
||||
}
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* @file lv_glfw_mouse.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_glfw_mouse.h"
|
||||
#include "lv_glfw_mouse_private.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../core/lv_group.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void opengles_mouse_read(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static void release_indev_cb(lv_event_t * e);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_indev_t * lv_glfw_mouse_create(void)
|
||||
{
|
||||
lv_glfw_mouse_t * dsc = lv_malloc_zeroed(sizeof(lv_glfw_mouse_t));
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
if(dsc == NULL) return NULL;
|
||||
|
||||
lv_indev_t * indev = lv_indev_create();
|
||||
LV_ASSERT_MALLOC(indev);
|
||||
if(indev == NULL) {
|
||||
lv_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(indev, opengles_mouse_read);
|
||||
lv_indev_set_driver_data(indev, dsc);
|
||||
|
||||
lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT);
|
||||
lv_indev_add_event_cb(indev, release_indev_cb, LV_EVENT_DELETE, indev);
|
||||
|
||||
return indev;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void opengles_mouse_read(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
lv_glfw_mouse_t * dsc = lv_indev_get_driver_data(indev);
|
||||
|
||||
/*Store the collected data*/
|
||||
data->point.x = dsc->last_x;
|
||||
data->point.y = dsc->last_y;
|
||||
data->state = dsc->left_button_down ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||
data->enc_diff = dsc->diff;
|
||||
dsc->diff = 0;
|
||||
}
|
||||
|
||||
static void release_indev_cb(lv_event_t * e)
|
||||
{
|
||||
lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e);
|
||||
lv_glfw_mouse_t * dsc = lv_indev_get_driver_data(indev);
|
||||
if(dsc) {
|
||||
lv_indev_set_driver_data(indev, NULL);
|
||||
lv_indev_set_read_cb(indev, NULL);
|
||||
lv_free(dsc);
|
||||
LV_LOG_INFO("done");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LV_USE_OPENGLES */
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* @file lv_glfw_mouse.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GLFW_MOUSE_H
|
||||
#define LV_GLFW_MOUSE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_glfw_window.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_indev_t * lv_glfw_mouse_create(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LV_GLFW_MOUSE_H */
|
||||
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* @file lv_glfw_mouse_private.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../display/lv_display.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
|
||||
#include "lv_glfw_mouse_private.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../core/lv_group.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_glfw_mouse_move_handler(lv_display_t * disp, int x, int y)
|
||||
{
|
||||
if(disp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*Find a suitable indev*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(lv_indev_get_display(indev) == disp && lv_indev_get_type(indev) == LV_INDEV_TYPE_POINTER) {
|
||||
break;
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
if(indev == NULL) return;
|
||||
lv_glfw_mouse_t * indev_dev = lv_indev_get_driver_data(indev);
|
||||
if(indev_dev == NULL) return;
|
||||
|
||||
indev_dev->last_x = x;
|
||||
indev_dev->last_y = y;
|
||||
|
||||
lv_indev_read(indev);
|
||||
}
|
||||
|
||||
void lv_glfw_mouse_btn_handler(lv_display_t * disp, int btn_down)
|
||||
{
|
||||
if(disp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*Find a suitable indev*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(lv_indev_get_display(indev) == disp && lv_indev_get_type(indev) == LV_INDEV_TYPE_POINTER) {
|
||||
break;
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
if(indev == NULL) return;
|
||||
lv_glfw_mouse_t * indev_dev = lv_indev_get_driver_data(indev);
|
||||
if(indev_dev == NULL) return;
|
||||
|
||||
indev_dev->left_button_down = btn_down;
|
||||
|
||||
lv_indev_read(indev);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_OPENGLES */
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* @file lv_glfw_mouse_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GLFW_MOUSE_PRIVATE_H
|
||||
#define LV_GLFW_MOUSE_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
int16_t last_x;
|
||||
int16_t last_y;
|
||||
bool left_button_down;
|
||||
int32_t diff;
|
||||
} lv_glfw_mouse_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_glfw_mouse_move_handler(lv_display_t * disp, int x, int y);
|
||||
|
||||
void lv_glfw_mouse_btn_handler(lv_display_t * disp, int btn_down);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LV_GLFW_MOUSE_PRIVATE_H */
|
||||
+265
-253
File diff suppressed because it is too large
Load Diff
@@ -14,11 +14,12 @@ extern "C" {
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../display/lv_display.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../display/lv_display.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
@@ -31,7 +32,68 @@ extern "C" {
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_display_t * lv_glfw_window_create(int32_t hor_res, int32_t ver_res);
|
||||
/**
|
||||
* Create a GLFW window with no textures and initialize OpenGL
|
||||
* @param hor_res width in pixels of the window
|
||||
* @param ver_res height in pixels of the window
|
||||
* @param use_mouse_indev send pointer indev input to LVGL display textures
|
||||
* @return the new GLFW window handle
|
||||
*/
|
||||
lv_glfw_window_t * lv_glfw_window_create(int32_t hor_res, int32_t ver_res, bool use_mouse_indev);
|
||||
|
||||
/**
|
||||
* Delete a GLFW window. If it is the last one, the process will exit
|
||||
* @param window GLFW window to delete
|
||||
*/
|
||||
void lv_glfw_window_delete(lv_glfw_window_t * window);
|
||||
|
||||
/**
|
||||
* Add a texture to the GLFW window. It can be an LVGL display texture, or any OpenGL texture
|
||||
* @param window GLFW window
|
||||
* @param texture_id OpenGL texture ID
|
||||
* @param w width in pixels of the texture
|
||||
* @param h height in pixels of the texture
|
||||
* @return the new texture handle
|
||||
*/
|
||||
lv_glfw_texture_t * lv_glfw_window_add_texture(lv_glfw_window_t * window, unsigned int texture_id, int32_t w,
|
||||
int32_t h);
|
||||
|
||||
/**
|
||||
* Remove a texture from its GLFW window and delete it
|
||||
* @param texture handle of a GLFW window texture
|
||||
*/
|
||||
void lv_glfw_texture_remove(lv_glfw_texture_t * texture);
|
||||
|
||||
/**
|
||||
* Set the x position of a texture within its GLFW window
|
||||
* @param texture handle of a GLFW window texture
|
||||
* @param x new x position of the texture
|
||||
*/
|
||||
void lv_glfw_texture_set_x(lv_glfw_texture_t * texture, int32_t x);
|
||||
|
||||
/**
|
||||
* Set the y position of a texture within its GLFW window
|
||||
* @param texture handle of a GLFW window texture
|
||||
* @param y new y position of the texture
|
||||
*/
|
||||
void lv_glfw_texture_set_y(lv_glfw_texture_t * texture, int32_t y);
|
||||
|
||||
/**
|
||||
* Set the opacity of a texture in a GLFW window
|
||||
* @param texture handle of a GLFW window texture
|
||||
* @param opa new opacity of the texture
|
||||
*/
|
||||
void lv_glfw_texture_set_opa(lv_glfw_texture_t * texture, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Get the mouse indev associated with a texture in a GLFW window, if it exists
|
||||
* @param texture handle of a GLFW window texture
|
||||
* @return the indev or `NULL`
|
||||
* @note there will only be an indev if the texture is based on an
|
||||
* LVGL display texture and the window was created with
|
||||
* `use_mouse_indev` as `true`
|
||||
*/
|
||||
lv_indev_t * lv_glfw_texture_get_mouse_indev(lv_glfw_texture_t * texture);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file lv_glfw_window_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GLFW_WINDOW_PRIVATE_H
|
||||
#define LV_GLFW_WINDOW_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_glfw_window.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../display/lv_display.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct lv_glfw_window_t {
|
||||
GLFWwindow * window;
|
||||
int32_t hor_res;
|
||||
int32_t ver_res;
|
||||
lv_ll_t textures;
|
||||
lv_point_t mouse_last_point;
|
||||
lv_indev_state_t mouse_last_state;
|
||||
uint8_t use_indev : 1;
|
||||
uint8_t closing : 1;
|
||||
};
|
||||
|
||||
struct lv_glfw_texture_t {
|
||||
lv_glfw_window_t * window;
|
||||
unsigned int texture_id;
|
||||
lv_area_t area;
|
||||
lv_opa_t opa;
|
||||
lv_indev_t * indev;
|
||||
lv_point_t indev_last_point;
|
||||
lv_indev_state_t indev_last_state;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GLFW_WINDOW_PRIVATE_H*/
|
||||
@@ -6,11 +6,12 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../display/lv_display.h"
|
||||
#include "lv_opengles_debug.h"
|
||||
|
||||
#include "lv_opengles_debug.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include "../../misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
@@ -23,10 +24,6 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/***********************
|
||||
* GLOBAL PROTOTYPES
|
||||
***********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
@@ -48,10 +45,14 @@ bool GLLogCall(const char * function, const char * file, int line)
|
||||
{
|
||||
GLenum error;
|
||||
while((error = glGetError()) != GL_NO_ERROR) {
|
||||
LV_LOG_ERROR("[OpenGL Error] (%d) %s %s:%d\n", error, function, file, line);
|
||||
LV_LOG_ERROR("[OpenGL Error] (%d) %s %s:%d", error, function, file, line);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_OPENGLES */
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "lv_opengles_debug.h"
|
||||
#include "lv_opengles_driver.h"
|
||||
|
||||
@@ -28,6 +24,7 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_opengles_enable_blending(void);
|
||||
static void lv_opengles_vertex_buffer_init(const void * data, unsigned int size);
|
||||
static void lv_opengles_vertex_buffer_deinit(void);
|
||||
static void lv_opengles_vertex_buffer_bind(void);
|
||||
@@ -42,7 +39,6 @@ static void lv_opengles_index_buffer_deinit(void);
|
||||
static unsigned int lv_opengles_index_buffer_get_count(void);
|
||||
static void lv_opengles_index_buffer_bind(void);
|
||||
static void lv_opengles_index_buffer_unbind(void);
|
||||
static void lv_opengles_render_clear(void);
|
||||
static unsigned int lv_opengles_shader_compile(unsigned int type, const char * source);
|
||||
static unsigned int lv_opengles_shader_create(const char * vertexShader, const char * fragmentShader);
|
||||
static void lv_opengles_shader_init(void);
|
||||
@@ -51,12 +47,9 @@ static void lv_opengles_shader_bind(void);
|
||||
static void lv_opengles_shader_unbind(void);
|
||||
static int lv_opengles_shader_get_uniform_location(const char * name);
|
||||
static void lv_opengles_shader_set_uniform1i(const char * name, int value);
|
||||
static void lv_opengles_shader_set_uniform4f(const char * name, float v0, float v1, float v2, float v3);
|
||||
static void lv_opengles_shader_set_uniformmatrix3fv(const char * name, int count, bool transpose, const float * values);
|
||||
static void lv_opengles_shader_set_uniform1f(const char * name, float value);
|
||||
static void lv_opengles_render_draw(void);
|
||||
static void lv_opengles_texture_init(void * buffer, int width, int height);
|
||||
static void lv_opengles_texture_deinit(void);
|
||||
static void lv_opengles_texture_bind(unsigned int slot);
|
||||
static void lv_opengles_texture_update(void * buffer, int width, int height);
|
||||
|
||||
/***********************
|
||||
* GLOBAL PROTOTYPES
|
||||
@@ -65,6 +58,8 @@ static void lv_opengles_texture_update(void * buffer, int width, int height);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool is_init;
|
||||
|
||||
static unsigned int vertex_buffer_id = 0;
|
||||
|
||||
static unsigned int vertex_array_id = 0;
|
||||
@@ -72,12 +67,10 @@ static unsigned int vertex_array_id = 0;
|
||||
static unsigned int index_buffer_id = 0;
|
||||
static unsigned int index_buffer_count = 0;
|
||||
|
||||
static unsigned int texture_id = 0;
|
||||
|
||||
static unsigned int shader_id;
|
||||
|
||||
static const char * shader_names[] = { "u_Color", "u_Texture", "u_ColorDepth" };
|
||||
static int shader_location[] = { 0, 0, 0 };
|
||||
static const char * shader_names[] = { "u_Texture", "u_ColorDepth", "u_VertexTransform", "u_Opa" };
|
||||
static int shader_location[] = { 0, 0, 0, 0 };
|
||||
|
||||
static const char * vertex_shader =
|
||||
"#version 300 es\n"
|
||||
@@ -87,9 +80,11 @@ static const char * vertex_shader =
|
||||
"\n"
|
||||
"out vec2 v_TexCoord;\n"
|
||||
"\n"
|
||||
"uniform mat3 u_VertexTransform;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = position;\n"
|
||||
" gl_Position = vec4((u_VertexTransform * vec3(position.xy, 1)).xy, position.zw);\n"
|
||||
" v_TexCoord = texCoord;\n"
|
||||
"};\n";
|
||||
|
||||
@@ -102,18 +97,18 @@ static const char * fragment_shader =
|
||||
"\n"
|
||||
"in vec2 v_TexCoord;\n"
|
||||
"\n"
|
||||
"uniform vec4 u_Color;\n"
|
||||
"uniform sampler2D u_Texture;\n"
|
||||
"uniform int u_ColorDepth;\n"
|
||||
"uniform float u_Opa;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 texColor = texture(u_Texture, v_TexCoord);\n"
|
||||
" if (u_ColorDepth == 8) {\n"
|
||||
" float gray = texColor.r;\n"
|
||||
" color = vec4(gray, gray, gray, 1.0);\n"
|
||||
" color = vec4(gray, gray, gray, u_Opa);\n"
|
||||
" } else {\n"
|
||||
" color = texColor;\n"
|
||||
" color = vec4(texColor.rgb, texColor.a * u_Opa);\n"
|
||||
" }\n"
|
||||
"};\n";
|
||||
|
||||
@@ -125,8 +120,12 @@ static const char * fragment_shader =
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_opengles_init(uint8_t * frame_buffer, int32_t hor, int32_t ver)
|
||||
void lv_opengles_init(void)
|
||||
{
|
||||
if(is_init) return;
|
||||
|
||||
lv_opengles_enable_blending();
|
||||
|
||||
float positions[] = {
|
||||
-1.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 1.0f, 0.0f,
|
||||
@@ -139,7 +138,7 @@ void lv_opengles_init(uint8_t * frame_buffer, int32_t hor, int32_t ver)
|
||||
2, 3, 0
|
||||
};
|
||||
|
||||
lv_opengles_vertex_buffer_init(positions, 4 * 4 * sizeof(float));
|
||||
lv_opengles_vertex_buffer_init(positions, sizeof(positions));
|
||||
|
||||
lv_opengles_vertex_array_init();
|
||||
lv_opengles_vertex_array_add_buffer();
|
||||
@@ -148,46 +147,72 @@ void lv_opengles_init(uint8_t * frame_buffer, int32_t hor, int32_t ver)
|
||||
|
||||
lv_opengles_shader_init();
|
||||
lv_opengles_shader_bind();
|
||||
lv_opengles_shader_set_uniform1i("u_ColorDepth", LV_COLOR_DEPTH);
|
||||
lv_opengles_shader_set_uniform4f("u_Color", 0.8f, 0.3f, 0.8f, 1.0f);
|
||||
|
||||
int slot = 0;
|
||||
lv_opengles_texture_init(frame_buffer, hor, ver);
|
||||
lv_opengles_texture_bind(slot);
|
||||
|
||||
lv_opengles_shader_set_uniform1i("u_Texture", slot);
|
||||
|
||||
/* unbound everything */
|
||||
/* unbind everything */
|
||||
lv_opengles_vertex_array_unbind();
|
||||
lv_opengles_vertex_buffer_unbind();
|
||||
lv_opengles_index_buffer_unbind();
|
||||
lv_opengles_shader_unbind();
|
||||
|
||||
is_init = true;
|
||||
}
|
||||
|
||||
void lv_opengles_deinit(void)
|
||||
{
|
||||
lv_opengles_texture_deinit();
|
||||
if(!is_init) return;
|
||||
|
||||
lv_opengles_shader_deinit();
|
||||
lv_opengles_index_buffer_deinit();
|
||||
lv_opengles_vertex_buffer_deinit();
|
||||
lv_opengles_vertex_array_deinit();
|
||||
|
||||
is_init = false;
|
||||
}
|
||||
|
||||
void lv_opengles_update(uint8_t * frame_buffer, int32_t hor, int32_t ver)
|
||||
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)
|
||||
{
|
||||
lv_opengles_render_clear();
|
||||
lv_opengles_texture_update(frame_buffer, hor, ver);
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture));
|
||||
|
||||
float hor_scale = (float)lv_area_get_width(texture_area) / (float)disp_w;
|
||||
float ver_scale = (float)lv_area_get_height(texture_area) / (float)disp_h;
|
||||
float hor_translate = (float)texture_area->x1 / (float)disp_w * 2.0f - (1.0f - hor_scale);
|
||||
float ver_translate = -((float)texture_area->y1 / (float)disp_h * 2.0f - (1.0f - ver_scale));
|
||||
float matrix[9] = {
|
||||
hor_scale, 0.0f, hor_translate,
|
||||
0.0f, ver_scale, ver_translate,
|
||||
0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
lv_opengles_shader_bind();
|
||||
lv_opengles_shader_set_uniform1i("u_ColorDepth", LV_COLOR_DEPTH);
|
||||
lv_opengles_shader_set_uniform4f("u_Color", 0.0f, 0.3f, 0.8f, 1.0f);
|
||||
lv_opengles_shader_set_uniform1i("u_Texture", 0);
|
||||
lv_opengles_shader_set_uniformmatrix3fv("u_VertexTransform", 1, true, matrix);
|
||||
lv_opengles_shader_set_uniform1f("u_Opa", (float)opa / (float)LV_OPA_100);
|
||||
lv_opengles_render_draw();
|
||||
}
|
||||
|
||||
void lv_opengles_render_clear(void)
|
||||
{
|
||||
GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
|
||||
}
|
||||
|
||||
void lv_opengles_viewport(int32_t x, int32_t y, int32_t w, int32_t h)
|
||||
{
|
||||
glViewport(x, y, w, h);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_opengles_enable_blending(void)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_buffer_init(const void * data, unsigned int size)
|
||||
{
|
||||
GL_CALL(glGenBuffers(1, &vertex_buffer_id));
|
||||
@@ -195,42 +220,42 @@ static void lv_opengles_vertex_buffer_init(const void * data, unsigned int size)
|
||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_buffer_deinit()
|
||||
static void lv_opengles_vertex_buffer_deinit(void)
|
||||
{
|
||||
GL_CALL(glDeleteBuffers(1, &vertex_buffer_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_buffer_bind()
|
||||
static void lv_opengles_vertex_buffer_bind(void)
|
||||
{
|
||||
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_buffer_unbind()
|
||||
static void lv_opengles_vertex_buffer_unbind(void)
|
||||
{
|
||||
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_array_init()
|
||||
static void lv_opengles_vertex_array_init(void)
|
||||
{
|
||||
GL_CALL(glGenVertexArrays(1, &vertex_array_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_array_deinit()
|
||||
static void lv_opengles_vertex_array_deinit(void)
|
||||
{
|
||||
GL_CALL(glDeleteVertexArrays(1, &vertex_array_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_array_bind()
|
||||
static void lv_opengles_vertex_array_bind(void)
|
||||
{
|
||||
GL_CALL(glBindVertexArray(vertex_array_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_array_unbind()
|
||||
static void lv_opengles_vertex_array_unbind(void)
|
||||
{
|
||||
GL_CALL(glBindVertexArray(0));
|
||||
}
|
||||
|
||||
static void lv_opengles_vertex_array_add_buffer()
|
||||
static void lv_opengles_vertex_array_add_buffer(void)
|
||||
{
|
||||
lv_opengles_vertex_buffer_bind();
|
||||
intptr_t offset = 0;
|
||||
@@ -253,31 +278,26 @@ static void lv_opengles_index_buffer_init(const unsigned int * data, unsigned in
|
||||
GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLuint), data, GL_STATIC_DRAW));
|
||||
}
|
||||
|
||||
static void lv_opengles_index_buffer_deinit()
|
||||
static void lv_opengles_index_buffer_deinit(void)
|
||||
{
|
||||
GL_CALL(glDeleteBuffers(1, &index_buffer_id));
|
||||
}
|
||||
|
||||
static unsigned int lv_opengles_index_buffer_get_count()
|
||||
static unsigned int lv_opengles_index_buffer_get_count(void)
|
||||
{
|
||||
return index_buffer_count;
|
||||
}
|
||||
|
||||
static void lv_opengles_index_buffer_bind()
|
||||
static void lv_opengles_index_buffer_bind(void)
|
||||
{
|
||||
GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_index_buffer_unbind()
|
||||
static void lv_opengles_index_buffer_unbind(void)
|
||||
{
|
||||
GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
static void lv_opengles_render_clear()
|
||||
{
|
||||
GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
|
||||
}
|
||||
|
||||
static unsigned int lv_opengles_shader_compile(unsigned int type, const char * source)
|
||||
{
|
||||
GL_CALL(unsigned int id = glCreateShader(type));
|
||||
@@ -292,8 +312,8 @@ static unsigned int lv_opengles_shader_compile(unsigned int type, const char * s
|
||||
GL_CALL(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
|
||||
char * message = lv_malloc_zeroed(length * sizeof(char));
|
||||
GL_CALL(glGetShaderInfoLog(id, length, &length, message));
|
||||
LV_LOG_ERROR("Failed to compile %s shader!\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment");
|
||||
LV_LOG_ERROR("%s\n", message);
|
||||
LV_LOG_ERROR("Failed to compile %s shader!", type == GL_VERTEX_SHADER ? "vertex" : "fragment");
|
||||
LV_LOG_ERROR("%s", message);
|
||||
GL_CALL(glDeleteShader(id));
|
||||
return 0;
|
||||
}
|
||||
@@ -318,22 +338,22 @@ static unsigned int lv_opengles_shader_create(const char * vertexShader, const c
|
||||
return program;
|
||||
}
|
||||
|
||||
static void lv_opengles_shader_init()
|
||||
static void lv_opengles_shader_init(void)
|
||||
{
|
||||
shader_id = lv_opengles_shader_create(vertex_shader, fragment_shader);
|
||||
}
|
||||
|
||||
static void lv_opengles_shader_deinit()
|
||||
static void lv_opengles_shader_deinit(void)
|
||||
{
|
||||
GL_CALL(glDeleteProgram(shader_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_shader_bind()
|
||||
static void lv_opengles_shader_bind(void)
|
||||
{
|
||||
GL_CALL(glUseProgram(shader_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_shader_unbind()
|
||||
static void lv_opengles_shader_unbind(void)
|
||||
{
|
||||
GL_CALL(glUseProgram(0));
|
||||
}
|
||||
@@ -342,7 +362,7 @@ static int lv_opengles_shader_get_uniform_location(const char * name)
|
||||
{
|
||||
int id = -1;
|
||||
for(size_t i = 0; i < sizeof(shader_location) / sizeof(int); i++) {
|
||||
if(strcmp(shader_names[i], name) == 0) {
|
||||
if(lv_strcmp(shader_names[i], name) == 0) {
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
@@ -356,7 +376,7 @@ static int lv_opengles_shader_get_uniform_location(const char * name)
|
||||
|
||||
GL_CALL(int location = glGetUniformLocation(shader_id, name));
|
||||
if(location == -1)
|
||||
LV_LOG_WARN("Warning: uniform '%s' doesn't exist!\n", name);
|
||||
LV_LOG_WARN("Warning: uniform '%s' doesn't exist!", name);
|
||||
|
||||
shader_location[id] = location;
|
||||
return location;
|
||||
@@ -367,12 +387,17 @@ static void lv_opengles_shader_set_uniform1i(const char * name, int value)
|
||||
GL_CALL(glUniform1i(lv_opengles_shader_get_uniform_location(name), value));
|
||||
}
|
||||
|
||||
static void lv_opengles_shader_set_uniform4f(const char * name, float v0, float v1, float v2, float v3)
|
||||
static void lv_opengles_shader_set_uniformmatrix3fv(const char * name, int count, bool transpose, const float * values)
|
||||
{
|
||||
GL_CALL(glUniform4f(lv_opengles_shader_get_uniform_location(name), v0, v1, v2, v3));
|
||||
GL_CALL(glUniformMatrix3fv(lv_opengles_shader_get_uniform_location(name), count, transpose, values));
|
||||
}
|
||||
|
||||
static void lv_opengles_render_draw()
|
||||
static void lv_opengles_shader_set_uniform1f(const char * name, float value)
|
||||
{
|
||||
GL_CALL(glUniform1f(lv_opengles_shader_get_uniform_location(name), value));
|
||||
}
|
||||
|
||||
static void lv_opengles_render_draw(void)
|
||||
{
|
||||
lv_opengles_shader_bind();
|
||||
lv_opengles_vertex_array_bind();
|
||||
@@ -381,67 +406,4 @@ static void lv_opengles_render_draw()
|
||||
GL_CALL(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, NULL));
|
||||
}
|
||||
|
||||
static void lv_opengles_texture_init(void * buffer, int width, int height)
|
||||
{
|
||||
if(buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CALL(glGenTextures(1, &texture_id));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture_id));
|
||||
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
|
||||
/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, buffer));
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer));
|
||||
#elif LV_COLOR_DEPTH == 24
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, buffer));
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer));
|
||||
#else
|
||||
#error("Unsupported color format")
|
||||
#endif
|
||||
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
}
|
||||
|
||||
static void lv_opengles_texture_deinit()
|
||||
{
|
||||
GL_CALL(glDeleteTextures(1, &texture_id));
|
||||
texture_id = 0;
|
||||
}
|
||||
|
||||
static void lv_opengles_texture_bind(unsigned int slot)
|
||||
{
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0 + slot));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture_id));
|
||||
}
|
||||
|
||||
static void lv_opengles_texture_update(void * buffer, int width, int height)
|
||||
{
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture_id));
|
||||
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, buffer));
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer));
|
||||
#elif LV_COLOR_DEPTH == 24
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, buffer));
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer));
|
||||
#else
|
||||
#error("Unsupported color format")
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* LV_USE_OPENGLES */
|
||||
|
||||
@@ -10,14 +10,69 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
void lv_opengles_init(uint8_t * frame_buffer, int32_t hor, int32_t ver);
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
void lv_opengles_update(uint8_t * frame_buffer, int32_t hor, int32_t ver);
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize OpenGL
|
||||
* @note it is not necessary to call this if you use `lv_glfw_window_create`
|
||||
*/
|
||||
void lv_opengles_init(void);
|
||||
|
||||
/**
|
||||
* Deinitialize OpenGL
|
||||
* @note it is not necessary to call this if you use `lv_glfw_window_create`
|
||||
*/
|
||||
void lv_opengles_deinit(void);
|
||||
|
||||
/**
|
||||
* Render a texture
|
||||
* @param texture OpenGL texture ID
|
||||
* @param texture_area the area in the window to render the texture in
|
||||
* @param opa opacity to blend the texture with existing contents
|
||||
* @param disp_w width of the window being rendered to
|
||||
* @param disp_h height of the window being rendered to
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Clear the window/display
|
||||
*/
|
||||
void lv_opengles_render_clear(void);
|
||||
|
||||
/**
|
||||
* Set the OpenGL viewport
|
||||
* @param x x position of the viewport
|
||||
* @param y y position of the viewport
|
||||
* @param w width of the viewport
|
||||
* @param h height of the viewport
|
||||
*/
|
||||
void lv_opengles_viewport(int32_t x, int32_t y, int32_t w, int32_t h);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_OPENGLES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @file lv_opengles_texture.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_opengles_texture.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include "lv_opengles_debug.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include <stdlib.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
unsigned int texture_id;
|
||||
uint8_t * fb1;
|
||||
} lv_opengles_texture_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||
static void release_disp_cb(lv_event_t * e);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h)
|
||||
{
|
||||
lv_display_t * disp = lv_display_create(w, h);
|
||||
if(disp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
lv_opengles_texture_t * dsc = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
if(dsc == NULL) {
|
||||
lv_display_delete(disp);
|
||||
return NULL;
|
||||
}
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(w, lv_display_get_color_format(disp));
|
||||
uint32_t buf_size = stride * w;
|
||||
dsc->fb1 = malloc(buf_size);
|
||||
if(dsc->fb1 == NULL) {
|
||||
lv_free(dsc);
|
||||
lv_display_delete(disp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GL_CALL(glGenTextures(1, &dsc->texture_id));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, dsc->texture_id));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
|
||||
lv_display_set_buffers(disp, dsc->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
lv_display_set_flush_cb(disp, flush_cb);
|
||||
lv_display_set_driver_data(disp, dsc);
|
||||
lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
unsigned int lv_opengles_texture_get_texture_id(lv_display_t * disp)
|
||||
{
|
||||
if(disp->flush_cb != flush_cb) {
|
||||
return 0;
|
||||
}
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
return dsc->texture_id;
|
||||
}
|
||||
|
||||
lv_display_t * lv_opengles_texture_get_from_texture_id(unsigned int texture_id)
|
||||
{
|
||||
lv_display_t * disp = NULL;
|
||||
while(NULL != (disp = lv_display_get_next(disp))) {
|
||||
unsigned int disp_texture_id = lv_opengles_texture_get_texture_id(disp);
|
||||
if(disp_texture_id == texture_id) {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||
{
|
||||
LV_UNUSED(area);
|
||||
LV_UNUSED(px_map);
|
||||
|
||||
if(lv_display_flush_is_last(disp)) {
|
||||
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, dsc->texture_id));
|
||||
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
/*Color depth: 8 (A8), 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
|
||||
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
|
||||
#error("Unsupported color format")
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_display_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void release_disp_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = lv_event_get_user_data(e);
|
||||
lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
|
||||
free(dsc->fb1);
|
||||
lv_free(dsc);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file lv_opengles_texture.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OPENGLES_TEXTURE_H
|
||||
#define LV_OPENGLES_TEXTURE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_OPENGLES
|
||||
|
||||
#include "../../display/lv_display.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a display that flushes to an OpenGL texture
|
||||
* @param w width in pixels of the texture
|
||||
* @param h height in pixels of the texture
|
||||
* @return the new display
|
||||
*/
|
||||
lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h);
|
||||
|
||||
/**
|
||||
* Get the OpenGL texture ID of the display
|
||||
* @param disp display
|
||||
* @return texture ID
|
||||
*/
|
||||
unsigned int lv_opengles_texture_get_texture_id(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the display of an OpenGL texture if it is associated with one
|
||||
* @param texture_id OpenGL texture ID
|
||||
* @return display or `NULL` if there no display with that texture ID
|
||||
*/
|
||||
lv_display_t * lv_opengles_texture_get_from_texture_id(unsigned int texture_id);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_OPENGLES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OPENGLES_TEXTURE_H*/
|
||||
@@ -38,7 +38,8 @@ extern "C" {
|
||||
#include "windows/lv_windows_display.h"
|
||||
|
||||
#include "glfw/lv_glfw_window.h"
|
||||
#include "glfw/lv_glfw_mouse.h"
|
||||
#include "glfw/lv_opengles_texture.h"
|
||||
#include "glfw/lv_opengles_driver.h"
|
||||
|
||||
#include "qnx/lv_qnx.h"
|
||||
|
||||
|
||||
@@ -321,6 +321,9 @@ typedef struct lv_rlottie_t lv_rlottie_t;
|
||||
|
||||
typedef struct lv_ffmpeg_player_t lv_ffmpeg_player_t;
|
||||
|
||||
typedef struct lv_glfw_window_t lv_glfw_window_t;
|
||||
typedef struct lv_glfw_texture_t lv_glfw_texture_t;
|
||||
|
||||
typedef uint32_t lv_prop_id_t;
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
|
||||
Reference in New Issue
Block a user