mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-11-29 18:48:09 +08:00
support user call opengl to draw
This commit is contained in:
parent
cb0f9f1e15
commit
6bec6f602a
@ -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
235
demos/demo_opengl.c
Normal 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"
|
@ -1,5 +1,8 @@
|
||||
# 最新动态
|
||||
|
||||
2024/09/05
|
||||
* 支持用户自己调用 OpenGL 绘制。
|
||||
|
||||
2024/09/04
|
||||
* 完善event\_from\_name(感谢兆坤提供补丁)
|
||||
* 修复tk_strncpy_s用法(感谢颖健提供补丁)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user