added framebuffer objects to render_backend

added rb_sync / rb_wait
rename vertex2d / surface2d to vertex2 / surface2
This commit is contained in:
Anthony Pesch 2017-04-13 23:37:10 -04:00
parent 20e3a0b8ae
commit bcdddec36c
5 changed files with 208 additions and 89 deletions

View File

@ -29,9 +29,9 @@ struct microprofile {
struct render_backend *rb;
struct window_listener listener;
texture_handle_t font_texture;
struct surface2d surfs[MAX_2D_SURFACES];
struct surface2 surfs[MAX_2D_SURFACES];
int num_surfs;
struct vertex2d verts[MAX_2D_VERTICES];
struct vertex2 verts[MAX_2D_VERTICES];
int num_verts;
};
@ -65,16 +65,15 @@ static void mp_mousemove(void *data, int x, int y) {
MicroProfileMousePosition(x, y, 0);
}
static struct vertex2d *mp_alloc_verts(struct microprofile *mp,
const struct surface2d &desc,
int count) {
static struct vertex2 *mp_alloc_verts(struct microprofile *mp,
const struct surface2 &desc, int count) {
CHECK(mp->num_verts + count <= MAX_2D_VERTICES);
uint32_t first_vert = mp->num_verts;
mp->num_verts += count;
/* try to batch with the last surface if possible */
if (mp->num_surfs) {
struct surface2d &last_surf = mp->surfs[mp->num_surfs - 1];
struct surface2 &last_surf = mp->surfs[mp->num_surfs - 1];
if (last_surf.prim_type == desc.prim_type &&
last_surf.texture == desc.texture &&
@ -87,7 +86,7 @@ static struct vertex2d *mp_alloc_verts(struct microprofile *mp,
/* else, allocate a new surface */
CHECK(mp->num_surfs < MAX_2D_SURFACES);
struct surface2d &next_surf = mp->surfs[mp->num_surfs];
struct surface2 &next_surf = mp->surfs[mp->num_surfs];
next_surf.prim_type = desc.prim_type;
next_surf.texture = desc.texture;
next_surf.src_blend = desc.src_blend;
@ -106,15 +105,16 @@ static void mp_draw_text(struct microprofile *mp, int x, int y, uint32_t color,
float fy2 = fy + (MICROPROFILE_TEXT_HEIGHT + 1);
int text_len = static_cast<int>(strlen(text));
struct vertex2d *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
mp->font_texture,
BLEND_SRC_ALPHA,
BLEND_ONE_MINUS_SRC_ALPHA,
false,
{0.0f, 0.0f, 0.0f, 0.0f},
0,
0},
6 * text_len);
struct vertex2 *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
0,
mp->font_texture,
BLEND_SRC_ALPHA,
BLEND_ONE_MINUS_SRC_ALPHA,
false,
{0.0f, 0.0f, 0.0f, 0.0f},
0,
0},
6 * text_len);
for (int i = 0; i < text_len; i++) {
float fx2 = fx + MICROPROFILE_TEXT_WIDTH;
@ -154,15 +154,16 @@ static void mp_draw_text(struct microprofile *mp, int x, int y, uint32_t color,
static void mp_draw_box(struct microprofile *mp, int x0, int y0, int x1, int y1,
uint32_t color, enum box_type type) {
struct vertex2d *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
0,
BLEND_SRC_ALPHA,
BLEND_ONE_MINUS_SRC_ALPHA,
false,
{0.0f, 0.0f, 0.0f, 0.0f},
0,
0},
6);
struct vertex2 *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
0,
0,
BLEND_SRC_ALPHA,
BLEND_ONE_MINUS_SRC_ALPHA,
false,
{0.0f, 0.0f, 0.0f, 0.0f},
0,
0},
6);
if (type == BOX_FLAT) {
Q0(vertex, xy[0], (float)x0);
@ -213,15 +214,16 @@ static void mp_draw_line(struct microprofile *mp, float *verts, int num_verts,
uint32_t color) {
CHECK(num_verts);
struct vertex2d *vertex = mp_alloc_verts(mp, {PRIM_LINES,
0,
BLEND_SRC_ALPHA,
BLEND_ONE_MINUS_SRC_ALPHA,
false,
{0.0f, 0.0f, 0.0f, 0.0f},
0,
0},
2 * (num_verts - 1));
struct vertex2 *vertex = mp_alloc_verts(mp, {PRIM_LINES,
0,
0,
BLEND_SRC_ALPHA,
BLEND_ONE_MINUS_SRC_ALPHA,
false,
{0.0f, 0.0f, 0.0f, 0.0f},
0,
0},
2 * (num_verts - 1));
for (int i = 0; i < num_verts - 1; ++i) {
vertex[0].xy[0] = verts[i * 2];
@ -242,14 +244,14 @@ void mp_end_frame(struct microprofile *mp) {
/* render the surfaces */
rb_begin_ortho(mp->rb);
rb_begin_surfaces2d(mp->rb, mp->verts, mp->num_verts, nullptr, 0);
rb_begin_surfaces2(mp->rb, mp->verts, mp->num_verts, nullptr, 0);
for (int i = 0; i < mp->num_surfs; i++) {
struct surface2d *surf = &mp->surfs[i];
rb_draw_surface2d(mp->rb, surf);
struct surface2 *surf = &mp->surfs[i];
rb_draw_surface2(mp->rb, surf);
}
rb_end_surfaces2d(mp->rb);
rb_end_surfaces2(mp->rb);
rb_end_ortho(mp->rb);
/* reset surfaces */

View File

@ -53,10 +53,9 @@ static void nk_mousemove(void *data, int x, int y) {
void nk_end_frame(struct nuklear *nk) {
/* convert draw list into vertex / element buffers */
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct vertex2d, xy)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct vertex2d, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8,
NK_OFFSETOF(struct vertex2d, color)},
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct vertex2, xy)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct vertex2, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct vertex2, color)},
{NK_VERTEX_LAYOUT_END}};
struct nk_buffer vbuf, ebuf;
@ -65,8 +64,8 @@ void nk_end_frame(struct nuklear *nk) {
struct nk_convert_config config = {0};
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct vertex2d);
config.vertex_alignment = NK_ALIGNOF(struct vertex2d);
config.vertex_size = sizeof(struct vertex2);
config.vertex_alignment = NK_ALIGNOF(struct vertex2);
config.null = nk->null;
config.global_alpha = 1.0f;
config.shape_AA = NK_ANTI_ALIASING_OFF;
@ -76,14 +75,14 @@ void nk_end_frame(struct nuklear *nk) {
/* bind buffers */
rb_begin_ortho(nk->rb);
rb_begin_surfaces2d(nk->rb, nk->vertices, nk->ctx.draw_list.vertex_count,
nk->elements, nk->ctx.draw_list.element_count);
rb_begin_surfaces2(nk->rb, nk->vertices, nk->ctx.draw_list.vertex_count,
nk->elements, nk->ctx.draw_list.element_count);
/* pass each draw command off to the render backend */
const struct nk_draw_command *cmd = NULL;
int offset = 0;
struct surface2d surf = {0};
struct surface2 surf = {0};
surf.prim_type = PRIM_TRIANGLES;
surf.src_blend = BLEND_SRC_ALPHA;
surf.dst_blend = BLEND_ONE_MINUS_SRC_ALPHA;
@ -103,13 +102,13 @@ void nk_end_frame(struct nuklear *nk) {
surf.first_vert = offset;
surf.num_verts = cmd->elem_count;
rb_draw_surface2d(nk->rb, &surf);
rb_draw_surface2(nk->rb, &surf);
offset += cmd->elem_count;
}
nk_clear(&nk->ctx);
rb_end_surfaces2d(nk->rb);
rb_end_surfaces2(nk->rb);
rb_end_ortho(nk->rb);
/* reset mouse wheel state as it won't be reset through any event */

View File

@ -30,7 +30,7 @@ struct nuklear {
texture_handle_t font_texture;
/* render buffers */
struct vertex2d vertices[NK_MAX_VERTICES];
struct vertex2 vertices[NK_MAX_VERTICES];
uint16_t elements[NK_MAX_ELEMENTS];
/* input state */

View File

@ -8,6 +8,7 @@
#include "ui/window.h"
#include "video/render_backend.h"
#define MAX_FRAMEBUFFERS 8
#define MAX_TEXTURES 8192
enum texture_map {
@ -39,7 +40,6 @@ enum shader_attr {
ATTR_OFFSET_COLOR = 0x20,
ATTR_PT_ALPHA_TEST = 0x40,
ATTR_COUNT = 0x80
};
struct shader_program {
@ -50,6 +50,16 @@ struct shader_program {
uint64_t uniform_token;
};
struct framebuffer {
GLuint fbo;
GLuint color_component;
GLuint depth_component;
};
struct texture {
GLuint texture;
};
struct render_backend {
struct window *window;
@ -57,8 +67,9 @@ struct render_backend {
int debug_wireframe;
/* resources */
GLuint textures[MAX_TEXTURES];
GLuint white_tex;
struct framebuffer framebuffers[MAX_FRAMEBUFFERS];
struct texture textures[MAX_TEXTURES];
struct texture white;
struct shader_program ta_programs[ATTR_COUNT];
struct shader_program ui_program;
@ -355,13 +366,16 @@ static void rb_destroy_textures(struct render_backend *rb) {
return;
}
glDeleteTextures(1, &rb->white_tex);
glDeleteTextures(1, &rb->white.texture);
for (int i = 1; i < MAX_TEXTURES; i++) {
if (!rb->textures[i]) {
struct texture *tex = &rb->textures[i];
if (!tex->texture) {
continue;
}
glDeleteTextures(1, &rb->textures[i]);
glDeleteTextures(1, &tex->texture);
}
}
@ -369,8 +383,8 @@ static void rb_create_textures(struct render_backend *rb) {
uint8_t pixels[64 * 64 * 4];
memset(pixels, 0xff, sizeof(pixels));
glGenTextures(1, &rb->white_tex);
glBindTexture(GL_TEXTURE_2D, rb->white_tex);
glGenTextures(1, &rb->white.texture);
glBindTexture(GL_TEXTURE_2D, rb->white.texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE,
@ -470,19 +484,19 @@ static void rb_create_vertex_buffers(struct render_backend *rb) {
/* xy */
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex2d),
(void *)offsetof(struct vertex2d, xy));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex2),
(void *)offsetof(struct vertex2, xy));
/* texcoord */
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex2d),
(void *)offsetof(struct vertex2d, uv));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex2),
(void *)offsetof(struct vertex2, uv));
/* color */
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE,
sizeof(struct vertex2d),
(void *)offsetof(struct vertex2d, color));
sizeof(struct vertex2),
(void *)offsetof(struct vertex2, color));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -578,7 +592,8 @@ void rb_draw_surface(struct render_backend *rb, const struct surface *surf) {
}
if (surf->texture) {
rb_bind_texture(rb, MAP_DIFFUSE, rb->textures[surf->texture]);
struct texture *tex = &rb->textures[surf->texture];
rb_bind_texture(rb, MAP_DIFFUSE, tex->texture);
}
glDrawArrays(GL_TRIANGLE_STRIP, surf->first_vert, surf->num_verts);
@ -601,10 +616,9 @@ void rb_begin_surfaces(struct render_backend *rb, const float *projection,
}
}
void rb_end_surfaces2d(struct render_backend *rb) {}
void rb_end_surfaces2(struct render_backend *rb) {}
void rb_draw_surface2d(struct render_backend *rb,
const struct surface2d *surf) {
void rb_draw_surface2(struct render_backend *rb, const struct surface2 *surf) {
if (surf->scissor) {
rb_set_scissor_test(rb, 1);
rb_set_scissor_clip(rb, (int)surf->scissor_rect[0],
@ -615,8 +629,16 @@ void rb_draw_surface2d(struct render_backend *rb,
}
rb_set_blend_func(rb, surf->src_blend, surf->dst_blend);
rb_bind_texture(rb, MAP_DIFFUSE,
surf->texture ? rb->textures[surf->texture] : rb->white_tex);
if (surf->framebuffer) {
struct framebuffer *fb = &rb->framebuffers[surf->framebuffer];
rb_bind_texture(rb, MAP_DIFFUSE, fb->color_component);
} else if (surf->texture) {
struct texture *tex = &rb->textures[surf->texture];
rb_bind_texture(rb, MAP_DIFFUSE, tex->texture);
} else {
rb_bind_texture(rb, MAP_DIFFUSE, rb->white.texture);
}
if (rb->ui_use_ibo) {
glDrawElements(prim_types[surf->prim_type], surf->num_verts,
@ -628,11 +650,10 @@ void rb_draw_surface2d(struct render_backend *rb,
}
}
void rb_begin_surfaces2d(struct render_backend *rb,
const struct vertex2d *verts, int num_verts,
uint16_t *indices, int num_indices) {
void rb_begin_surfaces2(struct render_backend *rb, const struct vertex2 *verts,
int num_verts, uint16_t *indices, int num_indices) {
glBindBuffer(GL_ARRAY_BUFFER, rb->ui_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(struct vertex2d) * num_verts, verts,
glBufferData(GL_ARRAY_BUFFER, sizeof(struct vertex2) * num_verts, verts,
GL_DYNAMIC_DRAW);
if (indices) {
@ -690,15 +711,29 @@ void rb_begin_frame(struct render_backend *rb) {
rb_set_depth_mask(rb, 1);
glViewport(0, 0, rb->window->width, rb->window->height);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void rb_wait(sync_handle_t on) {
GLsync sync = on;
CHECK(glIsSync(sync));
GLenum res = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, UINT64_MAX);
CHECK(res == GL_ALREADY_SIGNALED || res == GL_CONDITION_SATISFIED);
glDeleteSync(sync);
}
sync_handle_t rb_sync(struct render_backend *rb) {
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
return sync;
}
void rb_destroy_texture(struct render_backend *rb, texture_handle_t handle) {
GLuint *gltex = &rb->textures[handle];
glDeleteTextures(1, gltex);
*gltex = 0;
struct texture *tex = &rb->textures[handle];
glDeleteTextures(1, &tex->texture);
tex->texture = 0;
}
texture_handle_t rb_create_texture(struct render_backend *rb,
@ -710,7 +745,8 @@ texture_handle_t rb_create_texture(struct render_backend *rb,
/* find next open texture handle */
texture_handle_t handle;
for (handle = 1; handle < MAX_TEXTURES; handle++) {
if (!rb->textures[handle]) {
struct texture *tex = &rb->textures[handle];
if (!tex->texture) {
break;
}
}
@ -744,9 +780,9 @@ texture_handle_t rb_create_texture(struct render_backend *rb,
break;
}
GLuint *gltex = &rb->textures[handle];
glGenTextures(1, gltex);
glBindTexture(GL_TEXTURE_2D, *gltex);
struct texture *tex = &rb->textures[handle];
glGenTextures(1, &tex->texture);
glBindTexture(GL_TEXTURE_2D, tex->texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
filter_funcs[mipmaps * NUM_FILTER_MODES + filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_funcs[filter]);
@ -764,6 +800,73 @@ texture_handle_t rb_create_texture(struct render_backend *rb,
return handle;
}
void rb_destroy_framebuffer(struct render_backend *rb,
framebuffer_handle_t handle) {
struct framebuffer *fb = &rb->framebuffers[handle];
glDeleteTextures(1, &fb->color_component);
fb->color_component = 0;
glDeleteRenderbuffers(1, &fb->depth_component);
fb->depth_component = 0;
glDeleteFramebuffers(1, &fb->fbo);
fb->fbo = 0;
}
void rb_bind_framebuffer(struct render_backend *rb,
framebuffer_handle_t handle) {
struct framebuffer *fb = &rb->framebuffers[handle];
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
}
framebuffer_handle_t rb_create_framebuffer(struct render_backend *rb) {
/* find next open framebuffer handle */
framebuffer_handle_t handle;
for (handle = 1; handle < MAX_FRAMEBUFFERS; handle++) {
struct framebuffer *fb = &rb->framebuffers[handle];
if (!fb->fbo) {
break;
}
}
CHECK_LT(handle, MAX_FRAMEBUFFERS);
struct framebuffer *fb = &rb->framebuffers[handle];
/* create color component */
glGenTextures(1, &fb->color_component);
glBindTexture(GL_TEXTURE_2D, fb->color_component);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rb->window->width, rb->window->height,
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
/* create depth component */
glGenRenderbuffers(1, &fb->depth_component);
glBindRenderbuffer(GL_RENDERBUFFER, fb->depth_component);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, rb->window->width,
rb->window->height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
/* create fbo */
glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
fb->color_component, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, fb->depth_component);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
CHECK_EQ(status, GL_FRAMEBUFFER_COMPLETE);
/* switch back to default framebuffer */
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return handle;
}
void rb_destroy(struct render_backend *rb) {
rb_destroy_vertex_buffers(rb);
rb_destroy_shaders(rb);

View File

@ -5,7 +5,9 @@
struct window;
typedef int framebuffer_handle_t;
typedef int texture_handle_t;
typedef void *sync_handle_t;
enum pxl_format {
PXL_INVALID,
@ -103,19 +105,24 @@ struct surface {
int num_verts;
};
struct vertex2d {
struct vertex2 {
float xy[2];
float uv[2];
uint32_t color;
};
struct surface2d {
struct surface2 {
enum prim_type prim_type;
framebuffer_handle_t framebuffer;
texture_handle_t texture;
enum blend_func src_blend;
enum blend_func dst_blend;
int scissor;
float scissor_rect[4];
int first_vert;
int num_verts;
};
@ -125,6 +132,12 @@ struct render_backend;
struct render_backend *rb_create(struct window *window);
void rb_destroy(struct render_backend *rb);
framebuffer_handle_t rb_create_framebuffer(struct render_backend *rb);
void rb_bind_framebuffer(struct render_backend *rb,
framebuffer_handle_t handle);
void rb_destroy_framebuffer(struct render_backend *rb,
framebuffer_handle_t handle);
texture_handle_t rb_create_texture(struct render_backend *rb,
enum pxl_format format,
enum filter_mode filter,
@ -133,6 +146,9 @@ texture_handle_t rb_create_texture(struct render_backend *rb,
const uint8_t *buffer);
void rb_destroy_texture(struct render_backend *rb, texture_handle_t handle);
sync_handle_t rb_sync(struct render_backend *rb);
void rb_wait(sync_handle_t on);
void rb_begin_frame(struct render_backend *rb);
void rb_end_frame(struct render_backend *rb);
@ -144,10 +160,9 @@ void rb_begin_surfaces(struct render_backend *rb, const float *projection,
void rb_draw_surface(struct render_backend *rb, const struct surface *surf);
void rb_end_surfaces(struct render_backend *rb);
void rb_begin_surfaces2d(struct render_backend *rb,
const struct vertex2d *verts, int num_verts,
uint16_t *indices, int num_indices);
void rb_draw_surface2d(struct render_backend *rb, const struct surface2d *surf);
void rb_end_surfaces2d(struct render_backend *rb);
void rb_begin_surfaces2(struct render_backend *rb, const struct vertex2 *verts,
int num_verts, uint16_t *indices, int num_indices);
void rb_draw_surface2(struct render_backend *rb, const struct surface2 *surf);
void rb_end_surfaces2(struct render_backend *rb);
#endif