ext/say_image_target.c in ray-0.1.1 vs ext/say_image_target.c in ray-0.2.0
- old
+ new
@@ -1,11 +1,51 @@
#include "say.h"
+typedef struct {
+ GLuint id;
+ say_image *img;
+ say_context *ctxt;
+} say_fbo;
+
static say_context *say_image_target_make_context(void *data) {
return say_context_create();
}
+static void say_fbo_delete_current(void *data) {
+ say_fbo *fbo = (say_fbo*)data;
+
+ if (fbo->ctxt == say_context_current() && fbo->id) {
+ glDeleteFramebuffers(1, &fbo->id);
+ }
+}
+
+void say_fbo_make_current(GLuint fbo);
+void say_rbo_make_current(GLuint rbo);
+
+static void say_fbo_build(say_image_target *target, say_fbo *fbo) {
+ if (!fbo->id)
+ glGenFramebuffers(1, &fbo->id);
+
+ say_fbo_make_current(fbo->id);
+
+ say_image_bind(target->img);
+ glGenerateMipmap(GL_TEXTURE_2D);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, target->img->texture, 0);
+
+ say_rbo_make_current(target->rbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
+ say_image_get_width(target->img),
+ say_image_get_height(target->img));
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, target->rbo);
+
+ fbo->img = target->img;
+}
+
static GLuint say_current_fbo = 0;
static say_context *say_fbo_last_context = NULL;
void say_fbo_make_current(GLuint fbo) {
say_context *context = say_context_current();
@@ -13,11 +53,11 @@
if (context != say_fbo_last_context ||
fbo != say_current_fbo) {
say_current_fbo = fbo;
say_fbo_last_context = context;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
}
static GLuint say_current_rbo = 0;
static say_context *say_rbo_last_context = NULL;
@@ -28,46 +68,56 @@
if (context != say_rbo_last_context ||
rbo != say_current_rbo) {
say_current_rbo = rbo;
say_rbo_last_context = context;
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo);
}
}
-void say_image_target_will_delete(GLuint fbo, GLuint rbo) {
- if (say_current_fbo == fbo)
- say_current_fbo = 0;
+void say_image_target_will_delete(mo_hash *fbos, GLuint rbo) {
+ mo_hash_it it = mo_hash_begin(fbos);
+ for (; !mo_hash_it_is_end(&it); mo_hash_it_next(&it)) {
+ say_fbo *fbo = mo_hash_it_val_ptr(&it, say_fbo);
+ if (fbo->id == say_current_fbo) {
+ say_current_fbo = 0;
+ break;
+ }
+ }
if (say_current_rbo == rbo)
say_current_rbo = 0;
}
bool say_image_target_is_available() {
say_context_ensure();
- return __GLEW_EXT_framebuffer_object != 0;
+ return GLEW_EXT_framebuffer_object || GLEW_VERSION_3_0;
}
say_image_target *say_image_target_create() {
say_context_ensure();
say_image_target *target = malloc(sizeof(say_image_target));
target->target = say_target_create();
target->img = NULL;
- glGenFramebuffersEXT(1, &(target->fbo));
- glGenRenderbuffersEXT(1, &(target->rbo));
+ target->fbos = mo_hash_create(sizeof(say_context*), sizeof(say_fbo));
+ target->fbos->release = say_fbo_delete_current;
+ target->fbos->hash_of = mo_hash_of_pointer;
+ target->fbos->key_cmp = mo_hash_pointer_cmp;
+ glGenRenderbuffers(1, &target->rbo);
+
return target;
}
void say_image_target_free(say_image_target *target) {
say_context_ensure();
- say_image_target_will_delete(target->fbo, target->rbo);
+ say_image_target_will_delete(target->fbos, target->rbo);
- glDeleteRenderbuffersEXT(1, &(target->rbo));
- glDeleteFramebuffersEXT(1, &(target->fbo));
+ glDeleteRenderbuffers(1, &target->rbo);
+ mo_hash_free(target->fbos);
say_target_free(target->target);
free(target);
}
@@ -75,57 +125,61 @@
say_context_ensure();
target->img = image;
if (target->img) {
say_target_set_custom_data(target->target, target);
- //say_target_need_own_contxt(target->target, 0);
say_target_set_context_proc(target->target, say_image_target_make_context);
say_target_set_bind_hook(target->target, (say_bind_hook)say_image_target_bind);
say_vector2 size = say_image_get_size(image);
say_target_set_size(target->target, size);
say_view_set_size(target->target->view, size);
say_view_set_center(target->target->view, say_make_vector2(size.x / 2.0,
size.y / 2.0));
- say_view_flip_y(target->target->view, 0);
- say_fbo_make_current(target->fbo);
-
- say_image_bind(image);
- glGenerateMipmapEXT(GL_TEXTURE_2D);
-
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, image->texture, 0);
-
- say_rbo_make_current(target->rbo);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
- say_image_get_width(image),
- say_image_get_height(image));
-
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, target->rbo);
-
+ say_target_make_current(target->target);
}
}
say_image *say_image_target_get_image(say_image_target *target) {
return target->img;
}
void say_image_target_update(say_image_target *target) {
if (target->img) {
say_target_update(target->target);
-
- say_image_bind(target->img);
- glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- say_image_get_buffer(target->img));
+ say_image_mark_out_of_date(target->img);
}
}
void say_image_target_bind(say_image_target *target) {
say_context_ensure();
- say_fbo_make_current(target->fbo);
+
+ /*
+ * As FBOs aren't shared, we need to fetch the FBO for the current context. If
+ * we don't find one, we need to build it.
+ */
+ say_context *ctxt = say_context_current();
+
+ if (!mo_hash_has_key(target->fbos, &ctxt)) {
+ say_fbo tmp = {0, NULL, NULL};
+ mo_hash_set(target->fbos, &ctxt, &tmp);
+
+ say_fbo_build(target, mo_hash_get(target->fbos, &ctxt));
+ }
+ else {
+ say_fbo *fbo = mo_hash_get(target->fbos, &ctxt);
+
+ if (fbo->img != target->img && target->img)
+ say_fbo_build(target, fbo);
+ else
+ say_fbo_make_current(fbo->id);
+ }
+
+ /*
+ * Needed to avoid having garbage data there.
+ */
glClear(GL_DEPTH_BUFFER_BIT);
}
void say_image_target_unbind() {
if (say_image_target_is_available())