support user call opengl to draw

This commit is contained in:
lixianjing 2024-09-05 11:47:37 +08:00
parent cb0f9f1e15
commit 6bec6f602a
6 changed files with 348 additions and 2 deletions

View File

@ -17,6 +17,7 @@ env.Program(os.path.join(BIN_DIR, 'demovg'), ['demo_vg_app.c']);
env.Program(os.path.join(BIN_DIR, 'demouiold'), ['demo_ui_old_app.c']);
env.Program(os.path.join(BIN_DIR, 'demotr'), ['demo_tr_app.c']);
env.Program(os.path.join(BIN_DIR, 'demo_basic'), ['demo_basic.c']);
env.Program(os.path.join(BIN_DIR, 'demo_opengl'), ['demo_opengl.c']);
env.Program(os.path.join(BIN_DIR, 'demo_thread'), ['demo_thread_app.c']);
env.Program(os.path.join(BIN_DIR, 'demo_animator'), ['demo_animator_app.c']);
env.Program(os.path.join(BIN_DIR, 'demo_window_animator'), ['demo_window_animator.c']);

235
demos/demo_opengl.c Normal file
View File

@ -0,0 +1,235 @@
/**
* File: demo1_app.c
* Author: AWTK Develop Team
* Brief: basic demo
*
* Copyright (c) 2018 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-02-16 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "awtk.h"
#if defined(WITH_GPU_GL)
#ifdef WITHOUT_GLAD
#include <SDL.h>
#define GL_GLEXT_PROTOTYPES 1
#ifdef IOS
#include <OpenGLES/gltypes.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#else
#include <SDL_opengl.h>
#include <SDL_opengl_glext.h>
#endif /*IOS*/
#else
#include "glad/glad.h"
#endif /*WITHOUT_GLAD*/
/*本示例中OpenGL代码源于https://learnopengl.com */
static const char* s_vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
static const char* s_fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
typedef struct _gl_info_t {
uint32_t program;
uint32_t fg_vao;
uint32_t bg_vao;
} gl_info_t;
static uint32_t glhelper_create_program(const char* vertexShaderSource,
const char* fragmentShaderSource) {
int success;
char infoLog[512];
uint32_t shaderProgram = 0;
uint32_t vertexShader = 0;
uint32_t fragmentShader = 0;
return_value_if_fail(vertexShaderSource != NULL && fragmentShaderSource != NULL, 0);
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
log_warn("ERROR::SHADER::VERTEX::COMPILATION_FAILED: %s\n", infoLog);
}
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
log_warn("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED: %s\n", infoLog);
}
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
log_warn("ERROR::SHADER::PROGRAM::COMPILATION_FAILED: %s\n", infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
static uint32_t glhelper_create_vao(void* vertices, uint32_t size) {
uint32_t VBO = 0, VAO = 0;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, size * 3 * sizeof(float), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, size, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return VAO;
}
static ret_t glview_init(gl_info_t* info) {
float fg_vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
float bg_vertices[] = {
-0.5f, -1.0f, 0.0f,
0.5f, -1.0f, 0.0f,
0.0f, -0.5f, 0.0f
};
info->program = glhelper_create_program(s_vertexShaderSource, s_fragmentShaderSource);
info->fg_vao = glhelper_create_vao(fg_vertices, 3);
info->bg_vao = glhelper_create_vao(bg_vertices, 3);
return RET_OK;
}
static ret_t glview_render(gl_info_t* info, uint32_t VAO) {
uint32_t shaderProgram = info->program;
if (shaderProgram) {
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(0);
glBindVertexArray(0);
}
return RET_OK;
}
static ret_t glview_render_bg(void* ctx) {
gl_info_t* info = (gl_info_t*)ctx;
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
return glview_render(info, info->bg_vao);
}
static ret_t glview_render_fg(void* ctx) {
gl_info_t* info = (gl_info_t*)ctx;
return glview_render(info, info->fg_vao);
}
static ret_t glview_deinit(gl_info_t* info) {
glDeleteProgram(info->program);
memset(info, 0x00, sizeof(*info));
return RET_OK;
}
static gl_info_t g_gl_info;
static ret_t on_close(void* ctx, event_t* e) {
tk_quit();
glview_deinit(&g_gl_info);
return RET_OK;
}
static vgcanvas_opengl_draw_t s_opengl_draw_bg = {
.ctx = &g_gl_info, .draw = glview_render_bg, .call_before_ui = TRUE, .next = NULL};
static vgcanvas_opengl_draw_t s_opengl_draw_fg = {
.ctx = &g_gl_info, .draw = glview_render_fg, .call_before_ui = FALSE, .next = NULL};
static ret_t on_paint(void* ctx, event_t* e) {
paint_event_t* evt = paint_event_cast(e);
vgcanvas_t* vg = canvas_get_vgcanvas(evt->c);
return_value_if_fail(vg != NULL, RET_BAD_PARAMS);
vgcanvas_append_opengl_draw(vg, &s_opengl_draw_bg);
vgcanvas_append_opengl_draw(vg, &s_opengl_draw_fg);
return RET_OK;
}
#endif/*WITH_GPU_GL*/
ret_t application_init() {
widget_t* system_bar = window_open("system_bar");
widget_t* win = window_create(NULL, 0, 0, 0, 0);
widget_t* close = button_create(win, 0, 0, 0, 0);
widget_set_text_utf8(close, "Close");
widget_set_self_layout_params(close, "c", "b:10", "60", "30");
/*将窗口的背景设置为透明glview_render_bg绘制的东西才不会被覆盖*/
widget_set_style_color(win, "normal:bg_color", 0);
#if defined(WITH_GPU_GL)
glview_init(&g_gl_info);
widget_on(win, EVT_PAINT, on_paint, win);
widget_on(close, EVT_CLICK, on_close, win);
#endif
return RET_OK;
}
ret_t application_exit() {
log_debug("application_exit\n");
return RET_OK;
}
#include "awtk_main.inc"

View File

@ -1,5 +1,8 @@
# 最新动态
2024/09/05
* 支持用户自己调用 OpenGL 绘制。
2024/09/04
* 完善event\_from\_name(感谢兆坤提供补丁)
* 修复tk_strncpy_s用法(感谢颖健提供补丁)

View File

@ -277,11 +277,11 @@ ret_t vgcanvas_set_text_align(vgcanvas_t* vg, const char* text_align) {
ret_t vgcanvas_set_text_baseline(vgcanvas_t* vg, const char* text_baseline) {
return_value_if_fail(vg != NULL && vg->vt->set_text_baseline != NULL && text_baseline != NULL,
RET_BAD_PARAMS);
#ifndef AWTK_WEB
#ifndef AWTK_WEB
if (tk_str_eq(vg->text_baseline, text_baseline)) {
return RET_OK;
}
#endif/*AWTK_WEB*/
#endif /*AWTK_WEB*/
vg->text_baseline = tk_str_copy(vg->text_baseline, text_baseline);
@ -653,3 +653,43 @@ ret_t vgcanvas_draw_circle(vgcanvas_t* vg, double x, double y, double r, color_t
return RET_OK;
}
ret_t vgcanvas_append_opengl_draw(vgcanvas_t* vg, vgcanvas_opengl_draw_t* call) {
return_value_if_fail(vg != NULL && call != NULL, RET_BAD_PARAMS);
call->next = NULL;
if (vg->opengl_draws == NULL) {
vg->opengl_draws = call;
} else {
vgcanvas_opengl_draw_t* iter = vg->opengl_draws;
while (iter->next != NULL) {
iter = iter->next;
}
iter->next = call;
}
return RET_OK;
}
ret_t vgcanvas_call_opengl_draws(vgcanvas_t* vg, bool_t before_ui) {
return_value_if_fail(vg != NULL, RET_BAD_PARAMS);
if (vg->opengl_draws != NULL) {
vgcanvas_opengl_draw_t* iter = vg->opengl_draws;
while (iter != NULL) {
if ((!!iter->call_before_ui) == (!!before_ui)) {
iter->draw(iter->ctx);
}
iter = iter->next;
}
}
return RET_OK;
}
ret_t vgcanvas_clear_opengl_draws(vgcanvas_t* vg) {
return_value_if_fail(vg != NULL, RET_BAD_PARAMS);
vg->opengl_draws = NULL;
return RET_OK;
}

View File

@ -239,6 +239,40 @@ typedef struct _vgcanvas_vtable_t {
vgcanvas_destroy_t destroy;
} vgcanvas_vtable_t;
struct _vgcanvas_opengl_draw_t;
typedef struct _vgcanvas_opengl_draw_t vgcanvas_opengl_draw_t;
/**
* @class vgcanvas_opengl_draw_t
* OpenGL绘制回调
*/
struct _vgcanvas_opengl_draw_t {
/**
* @property {void*} ctx
* @annotation ["readable"]
*
*/
void* ctx;
/**
* @property {tk_callback_t} draw
* @annotation ["readable"]
*
*/
tk_callback_t draw;
/**
* @property {bool_t} call_before_ui
* @annotation ["readable"]
* UI之前绘制
*/
bool_t call_before_ui;
/**
* @property {vgcanvas_opengl_draw_t*} next
* @annotation ["readable"]
*
*/
vgcanvas_opengl_draw_t* next;
};
/**
* @class vgcanvas_t
*
@ -413,6 +447,9 @@ struct _vgcanvas_t {
assets_manager_t* assets_manager;
/*确保begin_frame/end_frame配对使用*/
uint32_t began_frame;
/*用于开发者自己绘制 OpenGL */
vgcanvas_opengl_draw_t* opengl_draws;
};
/**
@ -1418,6 +1455,33 @@ ret_t vgcanvas_fbo_to_bitmap(vgcanvas_t* vg, framebuffer_object_t* fbo, bitmap_t
ret_t vgcanvas_draw_circle(vgcanvas_t* vg, double x, double y, double r, color_t color, bool_t fill,
bool_t stroke);
/**
* @method vgcanvas_append_opengl_draw
* (OpenGL模式下OpenGL进行绘制)
* > PAINT
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {vgcanvas_opengl_draw_t*} call (, next会被修改)
* @return {ret_t} RET_OK表示成功
*/
ret_t vgcanvas_append_opengl_draw(vgcanvas_t* vg, vgcanvas_opengl_draw_t* call);
/**
* @method vgcanvas_call_opengl_draws
* OpenGL绘制函数
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {bool_t} before_ui UI之前调用
* @return {ret_t} RET_OK表示成功
*/
ret_t vgcanvas_call_opengl_draws(vgcanvas_t* vg, bool_t before_ui);
/**
* @method vgcanvas_clear_opengl_draws
* OpenGL绘制函数
* @param {vgcanvas_t*} vg vgcanvas对象
* @return {ret_t} RET_OK表示成功
*/
ret_t vgcanvas_clear_opengl_draws(vgcanvas_t* vg);
ret_t fbo_to_img(framebuffer_object_t* fbo, bitmap_t* img);
ret_t vgcanvas_set_assets_manager(vgcanvas_t* vg, assets_manager_t* assets_manager);
ret_t vgcanvas_set_canvas(vgcanvas_t* vg, canvas_t* c);

View File

@ -59,7 +59,10 @@ static ret_t vgcanvas_nanovg_end_frame(vgcanvas_t* vgcanvas) {
vgcanvas_nanovg_t* canvas = (vgcanvas_nanovg_t*)vgcanvas;
NVGcontext* vg = canvas->vg;
vgcanvas_call_opengl_draws(vgcanvas, TRUE);
nvgEndFrame(vg);
vgcanvas_call_opengl_draws(vgcanvas, FALSE);
vgcanvas_clear_opengl_draws(vgcanvas);
native_window_swap_buffer(canvas->window);