1 /**
2  * @file lv_opengles_texture.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "lv_opengles_texture.h"
11 #if LV_USE_OPENGLES
12 
13 #include "lv_opengles_debug.h"
14 #include "../../display/lv_display_private.h"
15 #include <stdlib.h>
16 #include <GL/glew.h>
17 #include <GLFW/glfw3.h>
18 
19 /*********************
20  *      DEFINES
21  *********************/
22 
23 /**********************
24  *      TYPEDEFS
25  **********************/
26 
27 typedef struct {
28     unsigned int texture_id;
29     uint8_t * fb1;
30 } lv_opengles_texture_t;
31 
32 /**********************
33  *  STATIC PROTOTYPES
34  **********************/
35 
36 static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
37 static void release_disp_cb(lv_event_t * e);
38 
39 /**********************
40  *  STATIC VARIABLES
41  **********************/
42 
43 /**********************
44  *      MACROS
45  **********************/
46 
47 /**********************
48  *   GLOBAL FUNCTIONS
49  **********************/
50 
lv_opengles_texture_create(int32_t w,int32_t h)51 lv_display_t * lv_opengles_texture_create(int32_t w, int32_t h)
52 {
53     lv_display_t * disp = lv_display_create(w, h);
54     if(disp == NULL) {
55         return NULL;
56     }
57     lv_opengles_texture_t * dsc = lv_malloc_zeroed(sizeof(lv_opengles_texture_t));
58     LV_ASSERT_MALLOC(dsc);
59     if(dsc == NULL) {
60         lv_display_delete(disp);
61         return NULL;
62     }
63     uint32_t stride = lv_draw_buf_width_to_stride(w, lv_display_get_color_format(disp));
64     uint32_t buf_size = stride * h;
65     dsc->fb1 = malloc(buf_size);
66     if(dsc->fb1 == NULL) {
67         lv_free(dsc);
68         lv_display_delete(disp);
69         return NULL;
70     }
71 
72     GL_CALL(glGenTextures(1, &dsc->texture_id));
73     GL_CALL(glBindTexture(GL_TEXTURE_2D, dsc->texture_id));
74     GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
75     GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
76     GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
77     GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
78     GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
79 
80     /* set the dimensions and format to complete the texture */
81     /* Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888) */
82 #if LV_COLOR_DEPTH == 8
83     GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, disp->hor_res, disp->ver_res, 0, GL_RED, GL_UNSIGNED_BYTE, NULL));
84 #elif LV_COLOR_DEPTH == 16
85     GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, disp->hor_res, disp->ver_res, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
86                          NULL));
87 #elif LV_COLOR_DEPTH == 24
88     GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, disp->hor_res, disp->ver_res, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL));
89 #elif LV_COLOR_DEPTH == 32
90     GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, disp->hor_res, disp->ver_res, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
91 #else
92 #error("Unsupported color format")
93 #endif
94 
95     glGenerateMipmap(GL_TEXTURE_2D);
96     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20);
97     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
98     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
99 
100     lv_display_set_buffers(disp, dsc->fb1, NULL, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
101     lv_display_set_flush_cb(disp, flush_cb);
102     lv_display_set_driver_data(disp, dsc);
103     lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
104 
105     return disp;
106 }
107 
lv_opengles_texture_get_texture_id(lv_display_t * disp)108 unsigned int lv_opengles_texture_get_texture_id(lv_display_t * disp)
109 {
110     if(disp->flush_cb != flush_cb) {
111         return 0;
112     }
113     lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
114     return dsc->texture_id;
115 }
116 
lv_opengles_texture_get_from_texture_id(unsigned int texture_id)117 lv_display_t * lv_opengles_texture_get_from_texture_id(unsigned int texture_id)
118 {
119     lv_display_t * disp = NULL;
120     while(NULL != (disp = lv_display_get_next(disp))) {
121         unsigned int disp_texture_id = lv_opengles_texture_get_texture_id(disp);
122         if(disp_texture_id == texture_id) {
123             return disp;
124         }
125     }
126     return NULL;
127 }
128 
129 /**********************
130  *   STATIC FUNCTIONS
131  **********************/
132 
flush_cb(lv_display_t * disp,const lv_area_t * area,uint8_t * px_map)133 static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
134 {
135     LV_UNUSED(area);
136     LV_UNUSED(px_map);
137 
138 #if !LV_USE_DRAW_OPENGLES
139     if(lv_display_flush_is_last(disp)) {
140 
141         lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
142         lv_color_format_t cf = lv_display_get_color_format(disp);
143         uint32_t stride = lv_draw_buf_width_to_stride(lv_display_get_horizontal_resolution(disp), cf);
144 
145         GL_CALL(glBindTexture(GL_TEXTURE_2D, dsc->texture_id));
146 
147         GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
148         GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / lv_color_format_get_size(cf)));
149         /*Color depth: 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
150 #if LV_COLOR_DEPTH == 8
151         GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, disp->hor_res, disp->ver_res, 0, GL_RED, GL_UNSIGNED_BYTE, dsc->fb1));
152 #elif LV_COLOR_DEPTH == 16
153         GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, disp->hor_res, disp->ver_res, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
154                              dsc->fb1));
155 #elif LV_COLOR_DEPTH == 24
156         GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, disp->hor_res, disp->ver_res, 0, GL_BGR, GL_UNSIGNED_BYTE, dsc->fb1));
157 #elif LV_COLOR_DEPTH == 32
158         GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, disp->hor_res, disp->ver_res, 0, GL_BGRA, GL_UNSIGNED_BYTE, dsc->fb1));
159 #else
160 #error("Unsupported color format")
161 #endif
162     }
163 #endif /* !LV_USE_DRAW_OPENGLES */
164 
165     lv_display_flush_ready(disp);
166 }
167 
release_disp_cb(lv_event_t * e)168 static void release_disp_cb(lv_event_t * e)
169 {
170     lv_display_t * disp = lv_event_get_user_data(e);
171     lv_opengles_texture_t * dsc = lv_display_get_driver_data(disp);
172     free(dsc->fb1);
173     GL_CALL(glDeleteTextures(1, &dsc->texture_id));
174     lv_free(dsc);
175 }
176 
177 #endif /*LV_USE_OPENGLES*/
178