mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-11-30 02:58:26 +08:00
opengl support dirty rect
This commit is contained in:
parent
d464305472
commit
b3ccb6a77d
@ -7,6 +7,7 @@
|
||||
* 修改动态设置 default_paint 属性为 auto 时没有效果的问题(感谢大恒提供补丁)。
|
||||
* slide_view 增加/删除,或者改变位置/大小时,没有同步更新的问题(感谢朝泽提供补丁)。
|
||||
* auto_hide 动画时间设置错误,以及 auto_hide 之后设置 visible 不能显示的问题(感谢朝泽提供补丁)。
|
||||
* OpenGL 模式支持脏矩形(感谢智明提供补丁)。
|
||||
|
||||
* 2019/11/06
|
||||
* 修改 emitter 中的错误(感谢朝泽提供补丁)。
|
||||
|
@ -290,7 +290,7 @@ lcd_t* lcd_vgcanvas_init(wh_t w, wh_t h, vgcanvas_t* canvas) {
|
||||
base->h = (wh_t)h;
|
||||
base->ratio = canvas->ratio;
|
||||
base->type = LCD_VGCANVAS;
|
||||
base->support_dirty_rect = FALSE;
|
||||
base->support_dirty_rect = TRUE;
|
||||
|
||||
system_info_set_lcd_w(info, base->w);
|
||||
system_info_set_lcd_h(info, base->h);
|
||||
|
@ -45,6 +45,25 @@
|
||||
#include "nanovg_gl.h"
|
||||
#include "nanovg_gl_utils.h"
|
||||
|
||||
typedef struct _vgcanvas_nanovg_screen_shader_info_t {
|
||||
GLuint program_object;
|
||||
GLuint coord_loc;
|
||||
GLuint position_loc;
|
||||
GLuint screentexture_loc;
|
||||
GLuint indexs[6];
|
||||
GLuint vboIds[3];
|
||||
} vgcanvas_nanovg_screen_shader_info_t;
|
||||
|
||||
typedef struct _vgcanvas_nanovg_offline_fb_t {
|
||||
GLuint fbo;
|
||||
GLuint last_fbo;
|
||||
GLuint rbo;
|
||||
GLuint textureId;
|
||||
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} vgcanvas_nanovg_offline_fb_t;
|
||||
|
||||
typedef struct _vgcanvas_nanovg_t {
|
||||
vgcanvas_t base;
|
||||
|
||||
@ -53,9 +72,242 @@ typedef struct _vgcanvas_nanovg_t {
|
||||
uint32_t text_align_v;
|
||||
uint32_t text_align_h;
|
||||
|
||||
vgcanvas_nanovg_offline_fb_t* offline_fb;
|
||||
vgcanvas_nanovg_screen_shader_info_t* shader_program;
|
||||
|
||||
native_window_t* window;
|
||||
} vgcanvas_nanovg_t;
|
||||
|
||||
static const char* vgcanvas_nanovg_shader_header =
|
||||
#if defined NANOVG_GL2
|
||||
" #define NANOVG_GL2 1 \n"
|
||||
#elif defined NANOVG_GL3
|
||||
" #version 150 core \n"
|
||||
" #define NANOVG_GL3 1 \n"
|
||||
#elif defined NANOVG_GLES2
|
||||
" #version 100 \n"
|
||||
" #define NANOVG_GL2 1 \n"
|
||||
#elif defined NANOVG_GLES3
|
||||
" #version 300 es \n"
|
||||
" #define NANOVG_GL3 1 \n"
|
||||
#endif
|
||||
;
|
||||
|
||||
static inline GLuint vgcanvas_create_LoadShader(const char* g_strShaderHeader,
|
||||
const char* g_strVertexShader,
|
||||
const char* g_strFragmentShader) {
|
||||
#define INFO_LOG_CHAR_LENGTH 512
|
||||
|
||||
GLint is_Success = 0;
|
||||
GLint vertex_shader = 0;
|
||||
GLint shader_program = 0;
|
||||
GLint framgent_shader = 0;
|
||||
const char* strShaders[2] = {0};
|
||||
char log[INFO_LOG_CHAR_LENGTH] = {0};
|
||||
|
||||
strShaders[0] = g_strShaderHeader != NULL ? g_strShaderHeader : "";
|
||||
strShaders[1] = g_strVertexShader;
|
||||
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 2, (const GLchar* const*)&strShaders, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
|
||||
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &is_Success);
|
||||
if (is_Success == 0) {
|
||||
memset(log, 0, INFO_LOG_CHAR_LENGTH);
|
||||
glGetShaderInfoLog(vertex_shader, INFO_LOG_CHAR_LENGTH, NULL, log);
|
||||
log_debug("Compile Vertex Shager fail message : %s \r\n", log);
|
||||
}
|
||||
|
||||
strShaders[1] = g_strFragmentShader;
|
||||
framgent_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(framgent_shader, 2, (const GLchar* const*)&strShaders, NULL);
|
||||
glCompileShader(framgent_shader);
|
||||
|
||||
glGetShaderiv(framgent_shader, GL_COMPILE_STATUS, &is_Success);
|
||||
if (is_Success == 0) {
|
||||
memset(log, 0, INFO_LOG_CHAR_LENGTH);
|
||||
glGetShaderInfoLog(framgent_shader, INFO_LOG_CHAR_LENGTH, NULL, log);
|
||||
log_debug("Compile Framgent Shader fail message : %s \r\n", log);
|
||||
}
|
||||
|
||||
shader_program = glCreateProgram();
|
||||
glAttachShader(shader_program, vertex_shader);
|
||||
glAttachShader(shader_program, framgent_shader);
|
||||
|
||||
glLinkProgram(shader_program);
|
||||
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(framgent_shader);
|
||||
|
||||
glGetProgramiv(shader_program, GL_LINK_STATUS, &is_Success);
|
||||
if (is_Success == 0) {
|
||||
memset(log, 0, INFO_LOG_CHAR_LENGTH);
|
||||
glGetProgramInfoLog(shader_program, INFO_LOG_CHAR_LENGTH, NULL, log);
|
||||
log_debug("Link Program fail message : %s \r\n", log);
|
||||
glDeleteProgram(shader_program);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shader_program;
|
||||
}
|
||||
|
||||
vgcanvas_nanovg_screen_shader_info_t* vgcanvas_create_init_screen_shader() {
|
||||
const GLuint indexs[] = {0, 1, 3, 1, 2, 3};
|
||||
|
||||
const GLfloat vertexs[] = {
|
||||
// Position
|
||||
1.0f, 1.0f, 0.0f, // top right
|
||||
1.0f, -1.0f, 0.0f, // bottm right
|
||||
-1.0f, -1.0f, 0.0f, // bottm left
|
||||
-1.0f, 1.0f, 0.0f // top left
|
||||
};
|
||||
|
||||
const GLfloat tcoords[] = {
|
||||
// texture coords
|
||||
1.0f, 1.0f, // top right
|
||||
1.0f, 0.0f, // bottm right
|
||||
0.0f, 0.0f, // bottm left
|
||||
0.0f, 1.0f // top left
|
||||
};
|
||||
|
||||
const char* vertex_shader =
|
||||
" #ifdef NANOVG_GL3 \n"
|
||||
" in vec2 vertex; \n"
|
||||
" in vec2 tcoord; \n"
|
||||
" out vec2 ftcoord; \n"
|
||||
" #else \n"
|
||||
" attribute vec3 g_vPosition; \n"
|
||||
" attribute vec2 tcoord; \n"
|
||||
" varying vec2 ftcoord; \n"
|
||||
" #endif \n"
|
||||
" void main(void) { \n"
|
||||
" ftcoord = tcoord; \n"
|
||||
" gl_Position = vec4(g_vPosition.x, g_vPosition.y, g_vPosition.z, 1.0); \n"
|
||||
// " gl_Position = vec4(g_vPosition.x, -g_vPosition.y, g_vPosition.z, 1.0); \n"
|
||||
// " gl_Position = vec4(-g_vPosition.x, g_vPosition.y, g_vPosition.z, 1.0); \n"
|
||||
// " gl_Position = vec4(-g_vPosition.x, -g_vPosition.y, g_vPosition.z, 1.0); \n"
|
||||
" } \n";
|
||||
|
||||
const char* fragment_shader =
|
||||
" #ifdef NANOVG_GL3 \n"
|
||||
" out vec4 outColor; \n"
|
||||
" #endif \n"
|
||||
" uniform sampler2D screentexture; \n"
|
||||
" varying vec2 ftcoord; \n"
|
||||
" void main() { \n"
|
||||
" #ifdef NANOVG_GL3 \n"
|
||||
" outColor = texture(screentexture, ftcoord); \n"
|
||||
" #else \n"
|
||||
" gl_FragColor = texture2D(screentexture, ftcoord); \n"
|
||||
" #endif \n"
|
||||
" } \n";
|
||||
vgcanvas_nanovg_screen_shader_info_t* shader_info =
|
||||
(vgcanvas_nanovg_screen_shader_info_t*)TKMEM_ZALLOC(vgcanvas_nanovg_screen_shader_info_t);
|
||||
return_value_if_fail(shader_info != NULL, NULL);
|
||||
|
||||
memcpy(shader_info->indexs, indexs, sizeof(indexs));
|
||||
|
||||
shader_info->program_object =
|
||||
vgcanvas_create_LoadShader(vgcanvas_nanovg_shader_header, vertex_shader, fragment_shader);
|
||||
|
||||
if (shader_info->program_object == 0) {
|
||||
TKMEM_FREE(shader_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
shader_info->coord_loc = glGetAttribLocation(shader_info->program_object, "tcoord");
|
||||
shader_info->position_loc = glGetAttribLocation(shader_info->program_object, "g_vPosition");
|
||||
shader_info->screentexture_loc =
|
||||
glGetUniformLocation(shader_info->program_object, "screentexture");
|
||||
|
||||
glGenBuffers(sizeof(shader_info->vboIds) / sizeof(GLuint), shader_info->vboIds);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, shader_info->vboIds[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, shader_info->vboIds[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(tcoords), tcoords, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, shader_info->vboIds[2]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(shader_info->indexs), shader_info->indexs, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
return shader_info;
|
||||
}
|
||||
|
||||
static void vgcanvas_destroy_shader(vgcanvas_nanovg_screen_shader_info_t* shader_info) {
|
||||
glDeleteBuffers(sizeof(shader_info->vboIds) / sizeof(GLuint), shader_info->vboIds);
|
||||
glDeleteShader(shader_info->program_object);
|
||||
TKMEM_FREE(shader_info);
|
||||
}
|
||||
|
||||
static void vgcanvas_destroy_offline_fb(vgcanvas_nanovg_offline_fb_t* offline_fb) {
|
||||
glDeleteFramebuffers(1, &offline_fb->fbo);
|
||||
glDeleteRenderbuffers(1, &offline_fb->rbo);
|
||||
glDeleteTextures(1, &offline_fb->textureId);
|
||||
TKMEM_FREE(offline_fb);
|
||||
}
|
||||
|
||||
static vgcanvas_nanovg_offline_fb_t* vgcanvas_create_offline_fb(uint32_t width, uint32_t height) {
|
||||
GLenum status = 0;
|
||||
GLint default_fbo = 0;
|
||||
GLint default_rbo = 0;
|
||||
GLint max_render_buffer_size = 0;
|
||||
vgcanvas_nanovg_offline_fb_t* offline_fb =
|
||||
(vgcanvas_nanovg_offline_fb_t*)TKMEM_ZALLOC(vgcanvas_nanovg_offline_fb_t);
|
||||
|
||||
return_value_if_fail(offline_fb != NULL, NULL);
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &default_fbo);
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING, &default_rbo);
|
||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_render_buffer_size);
|
||||
|
||||
if ((max_render_buffer_size <= width) || (max_render_buffer_size <= height)) {
|
||||
log_debug("Cannot use framebuffer objects! \r\n");
|
||||
TKMEM_FREE(offline_fb);
|
||||
return NULL;
|
||||
}
|
||||
offline_fb->width = width;
|
||||
offline_fb->height = height;
|
||||
|
||||
glGenFramebuffers(1, &offline_fb->fbo);
|
||||
glGenRenderbuffers(1, &offline_fb->rbo);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, offline_fb->rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
|
||||
|
||||
glGenTextures(1, &offline_fb->textureId);
|
||||
glBindTexture(GL_TEXTURE_2D, offline_fb->textureId);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, offline_fb->fbo);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, offline_fb->textureId,
|
||||
0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||
offline_fb->rbo);
|
||||
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
log_debug("Framebuffer object is not complete! \r\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, default_rbo);
|
||||
|
||||
return offline_fb;
|
||||
}
|
||||
|
||||
#include "texture.inc"
|
||||
#include "vgcanvas_nanovg_gl.inc"
|
||||
#include "vgcanvas_nanovg.inc"
|
||||
@ -88,5 +340,8 @@ vgcanvas_t* vgcanvas_create(uint32_t w, uint32_t h, uint32_t stride, bitmap_form
|
||||
assert(!"OpenGL is not supported!");
|
||||
}
|
||||
|
||||
nanovg->shader_program = vgcanvas_create_init_screen_shader();
|
||||
nanovg->offline_fb = vgcanvas_create_offline_fb(w * info.ratio, h * info.ratio);
|
||||
|
||||
return &(nanovg->base);
|
||||
}
|
||||
|
@ -8,6 +8,60 @@ static ret_t vgcanvas_nanovg_reinit(vgcanvas_t* vg, uint32_t w, uint32_t h, uint
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static inline void vgcanvas_nanovg_set_offline_fb(vgcanvas_nanovg_t* canvas, float w, float h) {
|
||||
vgcanvas_nanovg_offline_fb_t* offline_fb = canvas->offline_fb;
|
||||
if (offline_fb != NULL) {
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &offline_fb->last_fbo);
|
||||
|
||||
if (offline_fb->width != w || offline_fb->height != h) {
|
||||
vgcanvas_destroy_offline_fb(canvas->offline_fb);
|
||||
canvas->offline_fb = vgcanvas_create_offline_fb(w, h);
|
||||
offline_fb = canvas->offline_fb;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, offline_fb->fbo);
|
||||
glViewport(0, 0, w, h);
|
||||
// glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void vgcanvas_nanovg_offline_fb_flush(vgcanvas_nanovg_t* canvas) {
|
||||
system_info_t* info = system_info();
|
||||
vgcanvas_nanovg_offline_fb_t* offline_fb = canvas->offline_fb;
|
||||
vgcanvas_nanovg_screen_shader_info_t* shader_info = canvas->shader_program;
|
||||
if (offline_fb != NULL && shader_info != NULL) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, offline_fb->last_fbo);
|
||||
|
||||
glViewport(0, 0, info->lcd_w * info->device_pixel_ratio,
|
||||
info->lcd_h * info->device_pixel_ratio);
|
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glUseProgram(shader_info->program_object);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, shader_info->vboIds[0]);
|
||||
glVertexAttribPointer(shader_info->position_loc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
|
||||
glEnableVertexAttribArray(shader_info->position_loc);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, shader_info->vboIds[1]);
|
||||
glVertexAttribPointer(shader_info->coord_loc, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
|
||||
glEnableVertexAttribArray(shader_info->coord_loc);
|
||||
|
||||
// Bind the texture
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, offline_fb->textureId);
|
||||
glUniform1i(shader_info->screentexture_loc, 0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shader_info->vboIds[2]);
|
||||
glDrawElements(GL_TRIANGLES, sizeof(shader_info->indexs) / sizeof(GLuint), GL_UNSIGNED_INT, 0);
|
||||
|
||||
glDisableVertexAttribArray(shader_info->position_loc);
|
||||
glDisableVertexAttribArray(shader_info->coord_loc);
|
||||
}
|
||||
}
|
||||
|
||||
static ret_t vgcanvas_nanovg_begin_frame(vgcanvas_t* vgcanvas, rect_t* dirty_rect) {
|
||||
float_t angle = 0.0f;
|
||||
float_t anchor_x = 0.0f;
|
||||
@ -18,6 +72,9 @@ static ret_t vgcanvas_nanovg_begin_frame(vgcanvas_t* vgcanvas, rect_t* dirty_rec
|
||||
|
||||
native_window_gl_make_current(canvas->window);
|
||||
|
||||
vgcanvas_nanovg_set_offline_fb(canvas, info->lcd_w * info->device_pixel_ratio,
|
||||
info->lcd_h * info->device_pixel_ratio);
|
||||
|
||||
nvgBeginFrame(canvas->vg, info->lcd_w, info->lcd_h, info->device_pixel_ratio);
|
||||
|
||||
switch (info->lcd_orientation) {
|
||||
@ -59,6 +116,9 @@ static ret_t vgcanvas_nanovg_end_frame(vgcanvas_t* vgcanvas) {
|
||||
|
||||
nvgRestore(vg);
|
||||
nvgEndFrame(vg);
|
||||
|
||||
vgcanvas_nanovg_offline_fb_flush(canvas);
|
||||
|
||||
native_window_swap_buffer(canvas->window);
|
||||
|
||||
return RET_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user