mirror of https://github.com/inolen/redream.git
support sharing render_backend / OpenGL contexts
This commit is contained in:
parent
f4f8393ded
commit
5fae12ddaa
|
@ -29,6 +29,15 @@ int cond_timedwait(cond_t cond, mutex_t mutex, int ms);
|
|||
void cond_signal(cond_t cond);
|
||||
void cond_destroy(cond_t cond);
|
||||
|
||||
/*
|
||||
* tls
|
||||
*/
|
||||
#if PLATFORM_WINDOWS
|
||||
#define _Thread_local __declspec(thread)
|
||||
#else
|
||||
#define _Thread_local __thread
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sleeping
|
||||
*/
|
||||
|
|
|
@ -106,7 +106,6 @@ static void mp_draw_text(struct microprofile *mp, int x, int y, uint32_t color,
|
|||
int text_len = static_cast<int>(strlen(text));
|
||||
|
||||
struct vertex2 *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
|
||||
0,
|
||||
mp->font_texture,
|
||||
BLEND_SRC_ALPHA,
|
||||
BLEND_ONE_MINUS_SRC_ALPHA,
|
||||
|
@ -155,7 +154,6 @@ 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 vertex2 *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
|
||||
0,
|
||||
0,
|
||||
BLEND_SRC_ALPHA,
|
||||
BLEND_ONE_MINUS_SRC_ALPHA,
|
||||
|
@ -215,7 +213,6 @@ static void mp_draw_line(struct microprofile *mp, float *verts, int num_verts,
|
|||
CHECK(num_verts);
|
||||
|
||||
struct vertex2 *vertex = mp_alloc_verts(mp, {PRIM_LINES,
|
||||
0,
|
||||
0,
|
||||
BLEND_SRC_ALPHA,
|
||||
BLEND_ONE_MINUS_SRC_ALPHA,
|
||||
|
|
|
@ -835,27 +835,24 @@ void win_gl_make_current(struct window *win, glcontext_t ctx) {
|
|||
SDL_GL_MakeCurrent(win->handle, ctx);
|
||||
}
|
||||
|
||||
glcontext_t win_gl_create_context_from(struct window *win, glcontext_t from) {
|
||||
/* bind default context at this point to make sure a context is available to
|
||||
be shared from */
|
||||
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
|
||||
SDL_GL_MakeCurrent(win->handle, from);
|
||||
|
||||
return win_gl_create_context(win);
|
||||
}
|
||||
|
||||
glcontext_t win_gl_create_context(struct window *win) {
|
||||
/* need at least a 3.3 core context for our shaders */
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
|
||||
/* bind default context at this point to make sure a context is available to
|
||||
be shared from */
|
||||
if (win->default_ctx) {
|
||||
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
|
||||
SDL_GL_MakeCurrent(win->handle, win->default_ctx);
|
||||
}
|
||||
|
||||
SDL_GLContext ctx = SDL_GL_CreateContext(win->handle);
|
||||
CHECK_NOTNULL(ctx, "OpenGL context creation failed: %s", SDL_GetError());
|
||||
|
||||
/* track default context for future sharing */
|
||||
if (!win->default_ctx) {
|
||||
win->default_ctx = ctx;
|
||||
}
|
||||
|
||||
/* link in gl functions at runtime */
|
||||
glewExperimental = GL_TRUE;
|
||||
GLenum err = glewInit();
|
||||
|
|
|
@ -42,7 +42,6 @@ struct window_listener {
|
|||
struct window {
|
||||
/* public */
|
||||
struct SDL_Window *handle;
|
||||
glcontext_t default_ctx;
|
||||
|
||||
/* read only */
|
||||
int width;
|
||||
|
@ -60,6 +59,7 @@ struct window *win_create();
|
|||
void win_destroy(struct window *win);
|
||||
|
||||
glcontext_t win_gl_create_context(struct window *win);
|
||||
glcontext_t win_gl_create_context_from(struct window *win, glcontext_t other);
|
||||
void win_gl_make_current(struct window *win, glcontext_t ctx);
|
||||
void win_gl_destroy_context(struct window *win, glcontext_t ctx);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/assert.h"
|
||||
#include "core/profiler.h"
|
||||
#include "core/string.h"
|
||||
#include "sys/thread.h"
|
||||
#include "ui/nuklear.h"
|
||||
#include "ui/window.h"
|
||||
#include "video/render_backend.h"
|
||||
|
@ -61,18 +62,30 @@ struct texture {
|
|||
};
|
||||
|
||||
struct render_backend {
|
||||
struct window *window;
|
||||
|
||||
struct window *win;
|
||||
glcontext_t ctx;
|
||||
|
||||
/* resources */
|
||||
struct framebuffer framebuffers[MAX_FRAMEBUFFERS];
|
||||
struct texture textures[MAX_TEXTURES];
|
||||
struct texture white;
|
||||
|
||||
/* default assets created during intitialization */
|
||||
GLuint white_texture;
|
||||
struct shader_program ta_programs[ATTR_COUNT];
|
||||
struct shader_program ui_program;
|
||||
|
||||
/* note, in this backend framebuffer_handle_t and texture_handle_t are the
|
||||
OpenGL object handles, not indexes into these arrays. this lets OpenGL
|
||||
handle generating unique IDs across multiple contexts, with no additional
|
||||
synchronization on our part. however, to delete an object a reverse lookup
|
||||
must be performed to match the handle to an index in these arrays
|
||||
|
||||
note note, due to this dumbed down design, textures can be shared across
|
||||
multiple backends for rendering purposes, but can only be deleted on the
|
||||
backend that created them
|
||||
|
||||
TODO the textures / framebuffers arrays exist purely for cleanup purposes,
|
||||
it'd be nice to replace with a hashtable to avoid O(n) reverse lookup */
|
||||
struct texture textures[MAX_TEXTURES];
|
||||
struct framebuffer framebuffers[MAX_FRAMEBUFFERS];
|
||||
|
||||
/* surface render state */
|
||||
GLuint ta_vao;
|
||||
GLuint ta_vbo;
|
||||
GLuint ui_vao;
|
||||
|
@ -80,10 +93,6 @@ struct render_backend {
|
|||
GLuint ui_ibo;
|
||||
int ui_use_ibo;
|
||||
|
||||
/* begin_surfaces / draw_surfaces / end_surfaces uniform state */
|
||||
uint64_t uniform_token;
|
||||
const float *uniform_mvp;
|
||||
|
||||
/* current gl state */
|
||||
int scissor_test;
|
||||
int depth_mask;
|
||||
|
@ -92,8 +101,9 @@ struct render_backend {
|
|||
enum blend_func src_blend;
|
||||
enum blend_func dst_blend;
|
||||
GLuint current_vao;
|
||||
int vertex_attribs;
|
||||
struct shader_program *current_program;
|
||||
uint64_t uniform_token;
|
||||
const float *uniform_mvp;
|
||||
};
|
||||
|
||||
#include "video/ta.glsl"
|
||||
|
@ -360,42 +370,7 @@ static int r_compile_program(struct render_backend *r,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void r_destroy_textures(struct render_backend *r) {
|
||||
if (!r->ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &r->white.texture);
|
||||
|
||||
for (int i = 1; i < MAX_TEXTURES; i++) {
|
||||
struct texture *tex = &r->textures[i];
|
||||
|
||||
if (!tex->texture) {
|
||||
continue;
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &tex->texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_create_textures(struct render_backend *r) {
|
||||
uint8_t pixels[64 * 64 * 4];
|
||||
|
||||
memset(pixels, 0xff, sizeof(pixels));
|
||||
glGenTextures(1, &r->white.texture);
|
||||
glBindTexture(GL_TEXTURE_2D, r->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,
|
||||
pixels);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
static void r_destroy_shaders(struct render_backend *r) {
|
||||
if (!r->ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ATTR_COUNT; i++) {
|
||||
r_destroy_program(&r->ta_programs[i]);
|
||||
}
|
||||
|
@ -456,11 +431,35 @@ static void r_create_shaders(struct render_backend *r) {
|
|||
}
|
||||
}
|
||||
|
||||
static void r_destroy_vertex_buffers(struct render_backend *r) {
|
||||
if (!r->ctx) {
|
||||
return;
|
||||
}
|
||||
static void r_destroy_textures(struct render_backend *r) {
|
||||
glDeleteTextures(1, &r->white_texture);
|
||||
|
||||
for (int i = 0; i < MAX_TEXTURES; i++) {
|
||||
struct texture *tex = &r->textures[i];
|
||||
|
||||
if (!tex->texture) {
|
||||
continue;
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &tex->texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_create_textures(struct render_backend *r) {
|
||||
/* create default all white texture */
|
||||
uint8_t pixels[64 * 64 * 4];
|
||||
memset(pixels, 0xff, sizeof(pixels));
|
||||
|
||||
glGenTextures(1, &r->white_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, r->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,
|
||||
pixels);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
static void r_destroy_vertex_arrays(struct render_backend *r) {
|
||||
glDeleteBuffers(1, &r->ui_ibo);
|
||||
glDeleteBuffers(1, &r->ui_vbo);
|
||||
glDeleteVertexArrays(1, &r->ui_vao);
|
||||
|
@ -469,7 +468,7 @@ static void r_destroy_vertex_buffers(struct render_backend *r) {
|
|||
glDeleteVertexArrays(1, &r->ta_vao);
|
||||
}
|
||||
|
||||
static void r_create_vertex_buffers(struct render_backend *r) {
|
||||
static void r_create_vertex_arrays(struct render_backend *r) {
|
||||
/* ui vao */
|
||||
{
|
||||
glGenVertexArrays(1, &r->ui_vao);
|
||||
|
@ -587,8 +586,7 @@ void r_draw_surface(struct render_backend *r, const struct surface *surf) {
|
|||
}
|
||||
|
||||
if (surf->texture) {
|
||||
struct texture *tex = &r->textures[surf->texture];
|
||||
r_bind_texture(r, MAP_DIFFUSE, tex->texture);
|
||||
r_bind_texture(r, MAP_DIFFUSE, surf->texture);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, surf->first_vert, surf->num_verts);
|
||||
|
@ -621,14 +619,10 @@ void r_draw_surface2(struct render_backend *r, const struct surface2 *surf) {
|
|||
|
||||
r_set_blend_func(r, surf->src_blend, surf->dst_blend);
|
||||
|
||||
if (surf->framebuffer) {
|
||||
struct framebuffer *fb = &r->framebuffers[surf->framebuffer];
|
||||
r_bind_texture(r, MAP_DIFFUSE, fb->color_component);
|
||||
} else if (surf->texture) {
|
||||
struct texture *tex = &r->textures[surf->texture];
|
||||
r_bind_texture(r, MAP_DIFFUSE, tex->texture);
|
||||
if (surf->texture) {
|
||||
r_bind_texture(r, MAP_DIFFUSE, surf->texture);
|
||||
} else {
|
||||
r_bind_texture(r, MAP_DIFFUSE, r->white.texture);
|
||||
r_bind_texture(r, MAP_DIFFUSE, r->white_texture);
|
||||
}
|
||||
|
||||
if (r->ui_use_ibo) {
|
||||
|
@ -665,13 +659,13 @@ void r_end_ortho(struct render_backend *r) {
|
|||
void r_begin_ortho(struct render_backend *r) {
|
||||
float ortho[16];
|
||||
|
||||
ortho[0] = 2.0f / (float)r->window->width;
|
||||
ortho[0] = 2.0f / (float)r->win->width;
|
||||
ortho[4] = 0.0f;
|
||||
ortho[8] = 0.0f;
|
||||
ortho[12] = -1.0f;
|
||||
|
||||
ortho[1] = 0.0f;
|
||||
ortho[5] = -2.0f / (float)r->window->height;
|
||||
ortho[5] = -2.0f / (float)r->win->height;
|
||||
ortho[9] = 0.0f;
|
||||
ortho[13] = 1.0f;
|
||||
|
||||
|
@ -695,13 +689,13 @@ void r_begin_ortho(struct render_backend *r) {
|
|||
}
|
||||
|
||||
void r_end_frame(struct render_backend *r) {
|
||||
SDL_GL_SwapWindow(r->window->handle);
|
||||
SDL_GL_SwapWindow(r->win->handle);
|
||||
}
|
||||
|
||||
void r_begin_frame(struct render_backend *r) {
|
||||
r_set_depth_mask(r, 1);
|
||||
|
||||
glViewport(0, 0, r->window->width, r->window->height);
|
||||
glViewport(0, 0, r->win->width, r->win->height);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
@ -722,7 +716,17 @@ sync_handle_t r_sync(struct render_backend *r) {
|
|||
}
|
||||
|
||||
void r_destroy_texture(struct render_backend *r, texture_handle_t handle) {
|
||||
struct texture *tex = &r->textures[handle];
|
||||
/* lookup texture entry */
|
||||
int entry;
|
||||
for (entry = 0; entry < MAX_TEXTURES; entry++) {
|
||||
struct texture *tex = &r->textures[entry];
|
||||
if (tex->texture == handle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK_LT(entry, MAX_TEXTURES);
|
||||
|
||||
struct texture *tex = &r->textures[entry];
|
||||
glDeleteTextures(1, &tex->texture);
|
||||
tex->texture = 0;
|
||||
}
|
||||
|
@ -733,15 +737,15 @@ texture_handle_t r_create_texture(struct render_backend *r,
|
|||
enum wrap_mode wrap_u, enum wrap_mode wrap_v,
|
||||
int mipmaps, int width, int height,
|
||||
const uint8_t *buffer) {
|
||||
/* find next open texture handle */
|
||||
texture_handle_t handle;
|
||||
for (handle = 1; handle < MAX_TEXTURES; handle++) {
|
||||
struct texture *tex = &r->textures[handle];
|
||||
/* find next open texture entry */
|
||||
int entry;
|
||||
for (entry = 0; entry < MAX_TEXTURES; entry++) {
|
||||
struct texture *tex = &r->textures[entry];
|
||||
if (!tex->texture) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK_LT(handle, MAX_TEXTURES);
|
||||
CHECK_LT(entry, MAX_TEXTURES);
|
||||
|
||||
GLuint internal_fmt;
|
||||
GLuint pixel_fmt;
|
||||
|
@ -771,7 +775,7 @@ texture_handle_t r_create_texture(struct render_backend *r,
|
|||
break;
|
||||
}
|
||||
|
||||
struct texture *tex = &r->textures[handle];
|
||||
struct texture *tex = &r->textures[entry];
|
||||
glGenTextures(1, &tex->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, tex->texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
|
@ -788,12 +792,22 @@ texture_handle_t r_create_texture(struct render_backend *r,
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return handle;
|
||||
return tex->texture;
|
||||
}
|
||||
|
||||
void r_destroy_framebuffer(struct render_backend *r,
|
||||
framebuffer_handle_t handle) {
|
||||
struct framebuffer *fb = &r->framebuffers[handle];
|
||||
/* lookup framebuffer entry */
|
||||
int entry;
|
||||
for (entry = 0; entry < MAX_FRAMEBUFFERS; entry++) {
|
||||
struct framebuffer *fb = &r->framebuffers[entry];
|
||||
if (fb->fbo == handle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK_LT(entry, MAX_FRAMEBUFFERS);
|
||||
|
||||
struct framebuffer *fb = &r->framebuffers[entry];
|
||||
|
||||
glDeleteTextures(1, &fb->color_component);
|
||||
fb->color_component = 0;
|
||||
|
@ -806,29 +820,28 @@ void r_destroy_framebuffer(struct render_backend *r,
|
|||
}
|
||||
|
||||
void r_bind_framebuffer(struct render_backend *r, framebuffer_handle_t handle) {
|
||||
struct framebuffer *fb = &r->framebuffers[handle];
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, handle);
|
||||
}
|
||||
|
||||
framebuffer_handle_t r_create_framebuffer(struct render_backend *r) {
|
||||
framebuffer_handle_t r_create_framebuffer(struct render_backend *r,
|
||||
texture_handle_t *color_component) {
|
||||
/* find next open framebuffer handle */
|
||||
framebuffer_handle_t handle;
|
||||
for (handle = 1; handle < MAX_FRAMEBUFFERS; handle++) {
|
||||
struct framebuffer *fb = &r->framebuffers[handle];
|
||||
int entry;
|
||||
for (entry = 0; entry < MAX_FRAMEBUFFERS; entry++) {
|
||||
struct framebuffer *fb = &r->framebuffers[entry];
|
||||
if (!fb->fbo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK_LT(handle, MAX_FRAMEBUFFERS);
|
||||
CHECK_LT(entry, MAX_FRAMEBUFFERS);
|
||||
|
||||
struct framebuffer *fb = &r->framebuffers[handle];
|
||||
struct framebuffer *fb = &r->framebuffers[entry];
|
||||
|
||||
/* create color component */
|
||||
glGenTextures(1, &fb->color_component);
|
||||
glBindTexture(GL_TEXTURE_2D, fb->color_component);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r->window->width, r->window->height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r->win->width, r->win->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);
|
||||
|
@ -836,8 +849,8 @@ framebuffer_handle_t r_create_framebuffer(struct render_backend *r) {
|
|||
/* create depth component */
|
||||
glGenRenderbuffers(1, &fb->depth_component);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fb->depth_component);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, r->window->width,
|
||||
r->window->height);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, r->win->width,
|
||||
r->win->height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
/* create fbo */
|
||||
|
@ -854,30 +867,58 @@ framebuffer_handle_t r_create_framebuffer(struct render_backend *r) {
|
|||
/* switch back to default framebuffer */
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
return handle;
|
||||
*color_component = fb->color_component;
|
||||
|
||||
return fb->fbo;
|
||||
}
|
||||
|
||||
static void r_check_one_per_thread() {
|
||||
/* to keep things simple, don't allow more than one gl backend per thread.
|
||||
this avoids providing interfaces to manage the current gl context */
|
||||
static _Thread_local int initialized;
|
||||
CHECK_EQ(initialized, 0);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
void r_destroy(struct render_backend *r) {
|
||||
r_destroy_vertex_buffers(r);
|
||||
r_destroy_vertex_arrays(r);
|
||||
r_destroy_shaders(r);
|
||||
r_destroy_textures(r);
|
||||
|
||||
win_gl_destroy_context(r->window, r->ctx);
|
||||
win_gl_destroy_context(r->win, r->ctx);
|
||||
|
||||
free(r);
|
||||
}
|
||||
|
||||
struct render_backend *r_create(struct window *window) {
|
||||
struct render_backend *r_create_from(struct render_backend *from) {
|
||||
r_check_one_per_thread();
|
||||
|
||||
struct render_backend *r = calloc(1, sizeof(struct render_backend));
|
||||
|
||||
r->window = window;
|
||||
|
||||
/* setup gl context */
|
||||
r->ctx = win_gl_create_context(r->window);
|
||||
r->win = from->win;
|
||||
r->ctx = win_gl_create_context_from(r->win, from->ctx);
|
||||
|
||||
r_create_textures(r);
|
||||
r_create_shaders(r);
|
||||
r_create_vertex_buffers(r);
|
||||
r_create_vertex_arrays(r);
|
||||
|
||||
r_set_initial_state(r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
struct render_backend *r_create(struct window *win) {
|
||||
r_check_one_per_thread();
|
||||
|
||||
struct render_backend *r = calloc(1, sizeof(struct render_backend));
|
||||
|
||||
r->win = win;
|
||||
r->ctx = win_gl_create_context(win);
|
||||
|
||||
r_create_textures(r);
|
||||
r_create_shaders(r);
|
||||
r_create_vertex_arrays(r);
|
||||
|
||||
r_set_initial_state(r);
|
||||
|
||||
return r;
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
struct window;
|
||||
|
||||
typedef int framebuffer_handle_t;
|
||||
typedef int texture_handle_t;
|
||||
typedef unsigned framebuffer_handle_t;
|
||||
typedef unsigned texture_handle_t;
|
||||
typedef void *sync_handle_t;
|
||||
|
||||
enum pxl_format {
|
||||
|
@ -114,7 +114,6 @@ struct vertex2 {
|
|||
struct surface2 {
|
||||
enum prim_type prim_type;
|
||||
|
||||
framebuffer_handle_t framebuffer;
|
||||
texture_handle_t texture;
|
||||
|
||||
enum blend_func src_blend;
|
||||
|
@ -130,9 +129,11 @@ struct surface2 {
|
|||
struct render_backend;
|
||||
|
||||
struct render_backend *r_create(struct window *window);
|
||||
void r_destroy(struct render_backend *r);
|
||||
struct render_backend *r_create_from(struct render_backend *other);
|
||||
void r_destroy(struct render_backend *rc);
|
||||
|
||||
framebuffer_handle_t r_create_framebuffer(struct render_backend *r);
|
||||
framebuffer_handle_t r_create_framebuffer(struct render_backend *r,
|
||||
texture_handle_t *color_componet);
|
||||
void r_bind_framebuffer(struct render_backend *r, framebuffer_handle_t handle);
|
||||
void r_destroy_framebuffer(struct render_backend *r,
|
||||
framebuffer_handle_t handle);
|
||||
|
|
Loading…
Reference in New Issue