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 */
|
||||
@@ -6,23 +6,22 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_glfw_window.h"
|
||||
#include "lv_glfw_mouse_private.h"
|
||||
#include "lv_glfw_window_private.h"
|
||||
#if LV_USE_OPENGLES
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <memory.h>
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
#include "../../lv_init.h"
|
||||
#include "../../misc/lv_area_private.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "lv_opengles_driver.h"
|
||||
#include "lv_opengles_texture.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -31,45 +30,34 @@
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
GLFWwindow * window;
|
||||
|
||||
uint8_t * fb1;
|
||||
uint8_t * fb2;
|
||||
uint8_t * fb_act;
|
||||
uint8_t * buf1;
|
||||
uint8_t * buf2;
|
||||
uint8_t * rotated_buf;
|
||||
size_t rotated_buf_size;
|
||||
|
||||
uint8_t zoom;
|
||||
uint8_t ignore_size_chg;
|
||||
} lv_glfw_window_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p);
|
||||
static int window_create(lv_display_t * disp);
|
||||
static void window_update(lv_display_t * disp);
|
||||
static void texture_resize(lv_display_t * disp);
|
||||
static void window_update_handler(lv_timer_t * t);
|
||||
static void window_event_handler(lv_timer_t * t);
|
||||
static void release_disp_cb(lv_event_t * e);
|
||||
static void res_chg_event_cb(lv_event_t * e);
|
||||
static uint32_t lv_glfw_tick_count_callback(void);
|
||||
|
||||
/***********************
|
||||
* GLOBAL PROTOTYPES
|
||||
***********************/
|
||||
static bool inited = false;
|
||||
bool deiniting = false;
|
||||
static lv_glfw_window_t * lv_glfw_get_lv_window_from_window(GLFWwindow * window);
|
||||
static void glfw_error_cb(int error, const char * description);
|
||||
static int lv_glfw_init(void);
|
||||
static int lv_glew_init(void);
|
||||
static void lv_glfw_timer_init(void);
|
||||
static void lv_glfw_window_config(GLFWwindow * window, bool use_mouse_indev);
|
||||
static void lv_glfw_window_quit(void);
|
||||
static void window_close_callback(GLFWwindow * window);
|
||||
static void key_callback(GLFWwindow * window, int key, int scancode, int action, int mods);
|
||||
static void mouse_button_callback(GLFWwindow * window, int button, int action, int mods);
|
||||
static void mouse_move_callback(GLFWwindow * window, double xpos, double ypos);
|
||||
static void proc_mouse(lv_glfw_window_t * window);
|
||||
static void indev_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static void framebuffer_size_callback(GLFWwindow * window, int width, int height);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool glfw_inited;
|
||||
static bool glew_inited;
|
||||
static lv_timer_t * update_handler_timer;
|
||||
static lv_timer_t * event_handler_timer;
|
||||
static lv_ll_t glfw_window_ll;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@@ -79,301 +67,325 @@ static lv_timer_t * event_handler_timer;
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_display_t * lv_glfw_window_create(int32_t hor_res, int32_t ver_res)
|
||||
lv_glfw_window_t * lv_glfw_window_create(int32_t hor_res, int32_t ver_res, bool use_mouse_indev)
|
||||
{
|
||||
if(!inited) {
|
||||
update_handler_timer = lv_timer_create(window_update_handler, 5, NULL);
|
||||
event_handler_timer = lv_timer_create(window_event_handler, 5, NULL);
|
||||
|
||||
lv_tick_set_cb(lv_glfw_tick_count_callback);
|
||||
|
||||
inited = true;
|
||||
}
|
||||
|
||||
lv_glfw_window_t * dsc = lv_malloc_zeroed(sizeof(lv_glfw_window_t));
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
if(dsc == NULL) return NULL;
|
||||
|
||||
lv_display_t * disp = lv_display_create(hor_res, ver_res);
|
||||
if(disp == NULL) {
|
||||
lv_free(dsc);
|
||||
if(lv_glfw_init() != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
|
||||
lv_glfw_window_t * window = lv_ll_ins_tail(&glfw_window_ll);
|
||||
LV_ASSERT_MALLOC(window);
|
||||
if(window == NULL) return NULL;
|
||||
lv_memzero(window, sizeof(*window));
|
||||
|
||||
lv_display_set_driver_data(disp, dsc);
|
||||
|
||||
int ret = window_create(disp);
|
||||
if(ret != 0) {
|
||||
lv_display_send_event(disp, LV_EVENT_DELETE, NULL);
|
||||
/* Create window with graphics context */
|
||||
lv_glfw_window_t * existing_window = lv_ll_get_head(&glfw_window_ll);
|
||||
window->window = glfwCreateWindow(hor_res, ver_res, "LVGL Simulator", NULL,
|
||||
existing_window ? existing_window->window : NULL);
|
||||
if(window->window == NULL) {
|
||||
LV_LOG_ERROR("glfwCreateWindow fail.");
|
||||
lv_ll_remove(&glfw_window_ll, window);
|
||||
lv_free(window);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_display_set_flush_cb(disp, flush_cb);
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(lv_display_get_horizontal_resolution(disp),
|
||||
lv_display_get_color_format(disp));
|
||||
lv_display_set_buffers(disp, dsc->fb1, dsc->fb2, stride * disp->ver_res,
|
||||
LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
|
||||
window->hor_res = hor_res;
|
||||
window->ver_res = ver_res;
|
||||
lv_ll_init(&window->textures, sizeof(lv_glfw_texture_t));
|
||||
window->use_indev = use_mouse_indev;
|
||||
|
||||
lv_opengles_init(dsc->fb1, hor_res, ver_res);
|
||||
glfwSetWindowUserPointer(window->window, window);
|
||||
lv_glfw_timer_init();
|
||||
lv_glfw_window_config(window->window, use_mouse_indev);
|
||||
lv_glew_init();
|
||||
glfwMakeContextCurrent(window->window);
|
||||
lv_opengles_init();
|
||||
|
||||
return disp;
|
||||
return window;
|
||||
}
|
||||
|
||||
void lv_glfw_window_delete(lv_glfw_window_t * window)
|
||||
{
|
||||
glfwDestroyWindow(window->window);
|
||||
if(window->use_indev) {
|
||||
lv_glfw_texture_t * texture;
|
||||
LV_LL_READ(&window->textures, texture) {
|
||||
lv_indev_delete(texture->indev);
|
||||
}
|
||||
}
|
||||
lv_ll_clear(&window->textures);
|
||||
lv_ll_remove(&glfw_window_ll, window);
|
||||
lv_free(window);
|
||||
|
||||
if(lv_ll_is_empty(&glfw_window_ll)) {
|
||||
lv_glfw_window_quit();
|
||||
}
|
||||
}
|
||||
|
||||
lv_glfw_texture_t * lv_glfw_window_add_texture(lv_glfw_window_t * window, unsigned int texture_id, int32_t w, int32_t h)
|
||||
{
|
||||
lv_glfw_texture_t * texture = lv_ll_ins_tail(&window->textures);
|
||||
LV_ASSERT_MALLOC(texture);
|
||||
if(texture == NULL) return NULL;
|
||||
lv_memzero(texture, sizeof(*texture));
|
||||
texture->window = window;
|
||||
texture->texture_id = texture_id;
|
||||
lv_area_set(&texture->area, 0, 0, w - 1, h - 1);
|
||||
texture->opa = LV_OPA_COVER;
|
||||
|
||||
if(window->use_indev) {
|
||||
lv_display_t * texture_disp = lv_opengles_texture_get_from_texture_id(texture_id);
|
||||
if(texture_disp != NULL) {
|
||||
lv_indev_t * indev = lv_indev_create();
|
||||
if(indev == NULL) {
|
||||
lv_ll_remove(&window->textures, texture);
|
||||
lv_free(texture);
|
||||
return NULL;
|
||||
}
|
||||
texture->indev = indev;
|
||||
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(indev, indev_read_cb);
|
||||
lv_indev_set_driver_data(indev, texture);
|
||||
lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT);
|
||||
lv_indev_set_display(indev, texture_disp);
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void lv_glfw_texture_remove(lv_glfw_texture_t * texture)
|
||||
{
|
||||
if(texture->indev != NULL) {
|
||||
lv_indev_delete(texture->indev);
|
||||
}
|
||||
lv_ll_remove(&texture->window->textures, texture);
|
||||
lv_free(texture);
|
||||
}
|
||||
|
||||
void lv_glfw_texture_set_x(lv_glfw_texture_t * texture, int32_t x)
|
||||
{
|
||||
lv_area_set_pos(&texture->area, x, texture->area.y1);
|
||||
}
|
||||
|
||||
void lv_glfw_texture_set_y(lv_glfw_texture_t * texture, int32_t y)
|
||||
{
|
||||
lv_area_set_pos(&texture->area, texture->area.x1, y);
|
||||
}
|
||||
|
||||
void lv_glfw_texture_set_opa(lv_glfw_texture_t * texture, lv_opa_t opa)
|
||||
{
|
||||
texture->opa = opa;
|
||||
}
|
||||
|
||||
lv_indev_t * lv_glfw_texture_get_mouse_indev(lv_glfw_texture_t * texture)
|
||||
{
|
||||
return texture->indev;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_glfw_window_quit(lv_display_t * disp)
|
||||
static int lv_glfw_init(void)
|
||||
{
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
if(inited) {
|
||||
lv_timer_delete(update_handler_timer);
|
||||
update_handler_timer = NULL;
|
||||
if(glfw_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
glfwDestroyWindow(dsc->window);
|
||||
glfwTerminate();
|
||||
glfwSetErrorCallback(glfw_error_cb);
|
||||
|
||||
inited = false;
|
||||
int ret = glfwInit();
|
||||
if(ret == 0) {
|
||||
LV_LOG_ERROR("glfwInit fail.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
lv_ll_init(&glfw_window_ll, sizeof(lv_glfw_window_t));
|
||||
|
||||
glfw_inited = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lv_glew_init(void)
|
||||
{
|
||||
if(glew_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLenum ret = glewInit();
|
||||
if(ret != GLEW_OK) {
|
||||
LV_LOG_ERROR("glewInit fail: %d.", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("GL version: %s", glGetString(GL_VERSION));
|
||||
LV_LOG_INFO("GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
glew_inited = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lv_glfw_timer_init(void)
|
||||
{
|
||||
if(update_handler_timer == NULL) {
|
||||
update_handler_timer = lv_timer_create(window_update_handler, LV_DEF_REFR_PERIOD, NULL);
|
||||
lv_tick_set_cb(lv_glfw_tick_count_callback);
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||
static void lv_glfw_window_config(GLFWwindow * window, bool use_mouse_indev)
|
||||
{
|
||||
LV_UNUSED(area);
|
||||
LV_UNUSED(px_map);
|
||||
if(lv_display_flush_is_last(disp)) {
|
||||
window_update(disp);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
glfwSwapInterval(1);
|
||||
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
|
||||
if(use_mouse_indev) {
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_move_callback);
|
||||
}
|
||||
|
||||
/*IMPORTANT! It must be called to tell the system the flush is ready*/
|
||||
lv_display_flush_ready(disp);
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
|
||||
glfwSetWindowCloseCallback(window, window_close_callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for glfw events
|
||||
*/
|
||||
static void window_event_handler(lv_timer_t * t)
|
||||
static void lv_glfw_window_quit(void)
|
||||
{
|
||||
LV_UNUSED(t);
|
||||
if(deiniting == false) {
|
||||
return;
|
||||
}
|
||||
lv_timer_delete(update_handler_timer);
|
||||
update_handler_timer = NULL;
|
||||
|
||||
lv_display_t * disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
return;
|
||||
}
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
if(dsc == NULL) {
|
||||
return;
|
||||
}
|
||||
glfwTerminate();
|
||||
glfw_inited = false;
|
||||
|
||||
glfwSetWindowShouldClose(dsc->window, GLFW_TRUE);
|
||||
lv_display_send_event(disp, LV_EVENT_DELETE, NULL);
|
||||
lv_deinit();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler to update texture
|
||||
*/
|
||||
static void window_update_handler(lv_timer_t * t)
|
||||
{
|
||||
LV_UNUSED(t);
|
||||
lv_display_t * disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
return;
|
||||
}
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
if(dsc == NULL) {
|
||||
return;
|
||||
|
||||
lv_glfw_window_t * window;
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
/* delete windows that are ready to close */
|
||||
window = lv_ll_get_head(&glfw_window_ll);
|
||||
while(window) {
|
||||
lv_glfw_window_t * window_to_delete = window->closing ? window : NULL;
|
||||
window = lv_ll_get_next(&glfw_window_ll, window);
|
||||
if(window_to_delete) {
|
||||
glfwSetWindowShouldClose(window_to_delete->window, GLFW_TRUE);
|
||||
lv_glfw_window_delete(window_to_delete);
|
||||
}
|
||||
}
|
||||
|
||||
if(!glfwWindowShouldClose(dsc->window)) {
|
||||
lv_opengles_update(dsc->fb1, disp->hor_res, disp->ver_res);
|
||||
/* render each window */
|
||||
LV_LL_READ(&glfw_window_ll, window) {
|
||||
glfwMakeContextCurrent(window->window);
|
||||
lv_opengles_viewport(0, 0, window->hor_res, window->ver_res);
|
||||
lv_opengles_render_clear();
|
||||
|
||||
/* render each texture in the window */
|
||||
lv_glfw_texture_t * texture;
|
||||
LV_LL_READ(&window->textures, texture) {
|
||||
/* if the added texture is an LVGL opengles texture display, refresh it before rendering it */
|
||||
lv_display_t * texture_disp = lv_opengles_texture_get_from_texture_id(texture->texture_id);
|
||||
if(texture_disp != NULL) {
|
||||
lv_refr_now(texture_disp);
|
||||
}
|
||||
|
||||
lv_opengles_render_texture(texture->texture_id, &texture->area, texture->opa, window->hor_res, window->ver_res);
|
||||
}
|
||||
|
||||
/* Swap front and back buffers */
|
||||
glfwSwapBuffers(dsc->window);
|
||||
|
||||
glfwPollEvents();
|
||||
glfwSwapBuffers(window->window);
|
||||
}
|
||||
}
|
||||
|
||||
static void glfw_error_cb(int error, const char * description)
|
||||
{
|
||||
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
|
||||
LV_LOG_ERROR("GLFW Error %d: %s", error, description);
|
||||
}
|
||||
|
||||
static lv_glfw_window_t * lv_glfw_get_lv_window_from_window(GLFWwindow * window)
|
||||
{
|
||||
return glfwGetWindowUserPointer(window);
|
||||
}
|
||||
|
||||
static void window_close_callback(GLFWwindow * window)
|
||||
{
|
||||
LV_UNUSED(window);
|
||||
deiniting = true;
|
||||
lv_glfw_window_t * lv_window = lv_glfw_get_lv_window_from_window(window);
|
||||
lv_window->closing = 1;
|
||||
}
|
||||
|
||||
static void key_callback(GLFWwindow * window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
LV_UNUSED(window);
|
||||
LV_UNUSED(scancode);
|
||||
LV_UNUSED(mods);
|
||||
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
|
||||
deiniting = true;
|
||||
lv_glfw_window_t * lv_window = lv_glfw_get_lv_window_from_window(window);
|
||||
lv_window->closing = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void mouse_button_callback(GLFWwindow * window, int button, int action, int mods)
|
||||
{
|
||||
LV_UNUSED(window);
|
||||
LV_UNUSED(mods);
|
||||
if(button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||
lv_display_t * disp = lv_display_get_default();
|
||||
if(action == GLFW_PRESS) {
|
||||
lv_glfw_mouse_btn_handler(disp, 1);
|
||||
}
|
||||
else if(action == GLFW_RELEASE) {
|
||||
lv_glfw_mouse_btn_handler(disp, 0);
|
||||
}
|
||||
lv_glfw_window_t * lv_window = lv_glfw_get_lv_window_from_window(window);
|
||||
lv_window->mouse_last_state = action == GLFW_PRESS ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||
proc_mouse(lv_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void mouse_move_callback(GLFWwindow * window, double xpos, double ypos)
|
||||
{
|
||||
LV_UNUSED(window);
|
||||
lv_display_t * disp = lv_display_get_default();
|
||||
lv_glfw_mouse_move_handler(disp, (int)xpos, (int)ypos);
|
||||
lv_glfw_window_t * lv_window = lv_glfw_get_lv_window_from_window(window);
|
||||
lv_window->mouse_last_point.x = (int32_t)xpos;
|
||||
lv_window->mouse_last_point.y = (int32_t)ypos;
|
||||
proc_mouse(lv_window);
|
||||
}
|
||||
|
||||
static void proc_mouse(lv_glfw_window_t * window)
|
||||
{
|
||||
/* mouse activity will affect the topmost LVGL display texture */
|
||||
lv_glfw_texture_t * texture;
|
||||
LV_LL_READ_BACK(&window->textures, texture) {
|
||||
if(lv_area_is_point_on(&texture->area, &window->mouse_last_point, 0)) {
|
||||
/* adjust the mouse pointer coordinates so that they are relative to the texture */
|
||||
texture->indev_last_point.x = window->mouse_last_point.x - texture->area.x1;
|
||||
texture->indev_last_point.y = window->mouse_last_point.y - texture->area.y1;
|
||||
texture->indev_last_state = window->mouse_last_state;
|
||||
lv_indev_read(texture->indev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void indev_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
lv_glfw_texture_t * texture = lv_indev_get_driver_data(indev);
|
||||
data->point = texture->indev_last_point;
|
||||
data->state = texture->indev_last_state;
|
||||
}
|
||||
|
||||
static void framebuffer_size_callback(GLFWwindow * window, int width, int height)
|
||||
{
|
||||
LV_UNUSED(window);
|
||||
glViewport(0, 0, width, height);
|
||||
lv_display_t * disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
return;
|
||||
}
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
dsc->ignore_size_chg = 1;
|
||||
lv_display_set_resolution(disp, width / dsc->zoom, height / dsc->zoom);
|
||||
dsc->ignore_size_chg = 0;
|
||||
lv_refr_now(disp);
|
||||
}
|
||||
|
||||
static void texture_resize(lv_display_t * disp)
|
||||
{
|
||||
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
||||
int32_t ver_res = lv_display_get_vertical_resolution(disp);
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp));
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
|
||||
dsc->fb1 = realloc(dsc->fb1, stride * ver_res);
|
||||
lv_memzero(dsc->fb1, stride * ver_res);
|
||||
|
||||
lv_display_set_buffers(disp, dsc->fb1, dsc->fb2, stride * ver_res, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
}
|
||||
|
||||
static int window_create(lv_display_t * disp)
|
||||
{
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
dsc->zoom = 1;
|
||||
|
||||
glfwSetErrorCallback(glfw_error_cb);
|
||||
if(!glfwInit()) {
|
||||
LV_LOG_ERROR("glfwInit fail.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
|
||||
int32_t hor_res = disp->hor_res;
|
||||
int32_t ver_res = disp->ver_res;
|
||||
|
||||
/* Create window with graphics context */
|
||||
dsc->window = glfwCreateWindow(hor_res * dsc->zoom, ver_res * dsc->zoom, "LVGL Simulator", NULL, NULL);
|
||||
if(dsc->window == NULL) {
|
||||
LV_LOG_ERROR("glfwCreateWindow fail.\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(dsc->window);
|
||||
if(glewInit() != GLEW_OK) {
|
||||
LV_LOG_ERROR("glewInit fail.\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("GL version: %s\n", glGetString(GL_VERSION));
|
||||
LV_LOG_INFO("GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
glfwSwapInterval(1);
|
||||
|
||||
glfwSetFramebufferSizeCallback(dsc->window, framebuffer_size_callback);
|
||||
|
||||
glfwSetMouseButtonCallback(dsc->window, mouse_button_callback);
|
||||
glfwSetCursorPosCallback(dsc->window, mouse_move_callback);
|
||||
|
||||
glfwSetKeyCallback(dsc->window, key_callback);
|
||||
|
||||
glfwSetWindowCloseCallback(dsc->window, window_close_callback);
|
||||
|
||||
texture_resize(disp);
|
||||
|
||||
uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp));
|
||||
lv_memset(dsc->fb1, 0xff, hor_res * ver_res * px_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void window_update(lv_display_t * disp)
|
||||
{
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
if(dsc->fb_act) {
|
||||
LV_LOG_INFO("current pixel: %d\n", ((uint16_t *)(dsc->fb_act))[0]);
|
||||
}
|
||||
if(dsc->fb1) {
|
||||
LV_LOG_INFO("fb1 pixel: %d\n", ((uint16_t *)(dsc->fb1))[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static void res_chg_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = lv_event_get_current_target(e);
|
||||
texture_resize(disp);
|
||||
}
|
||||
|
||||
static void release_disp_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = (lv_display_t *) lv_event_get_user_data(e);
|
||||
lv_glfw_window_t * dsc = lv_display_get_driver_data(disp);
|
||||
|
||||
lv_glfw_window_quit(disp);
|
||||
|
||||
if(dsc->fb1) {
|
||||
free(dsc->fb1);
|
||||
dsc->fb1 = NULL;
|
||||
}
|
||||
if(dsc->fb2) {
|
||||
free(dsc->fb2);
|
||||
dsc->fb2 = NULL;
|
||||
}
|
||||
if(dsc->buf1) {
|
||||
free(dsc->buf1);
|
||||
dsc->buf1 = NULL;
|
||||
}
|
||||
if(dsc->buf2) {
|
||||
free(dsc->buf2);
|
||||
dsc->buf2 = NULL;
|
||||
}
|
||||
|
||||
lv_deinit();
|
||||
lv_free(dsc);
|
||||
|
||||
exit(0);
|
||||
lv_glfw_window_t * lv_window = lv_glfw_get_lv_window_from_window(window);
|
||||
lv_window->hor_res = width;
|
||||
lv_window->ver_res = height;
|
||||
}
|
||||
|
||||
static uint32_t lv_glfw_tick_count_callback(void)
|
||||
{
|
||||
int milliseconds = (int)(glfwGetTime() * 1000);
|
||||
return milliseconds;
|
||||
double tick = glfwGetTime() * 1000.0;
|
||||
return (uint32_t)tick;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
@@ -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
|
||||
|
||||
70
src/drivers/glfw/lv_glfw_window_private.h
Normal file
70
src/drivers/glfw/lv_glfw_window_private.h
Normal file
@@ -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
|
||||
|
||||
151
src/drivers/glfw/lv_opengles_texture.c
Normal file
151
src/drivers/glfw/lv_opengles_texture.c
Normal file
@@ -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*/
|
||||
66
src/drivers/glfw/lv_opengles_texture.h
Normal file
66
src/drivers/glfw/lv_opengles_texture.h
Normal file
@@ -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