void say_buffer_bind(say_buffer *buf) { say_context_ensure(); if (say_has_vao()) say_vao_make_current(say_buffer_get_vao(buf)); else say_buffer_make_current(buf); }
void say_buffer_resize(say_buffer *buf, size_t size) { mo_array_resize(&buf->buffer, size); say_context_ensure(); say_vbo_make_current(buf->vbo); glBufferData(GL_ARRAY_BUFFER, size * buf->buffer.el_size, say_buffer_get_vertex(buf, 0), buf->type); }
void say_image_target_free(say_image_target *target) { say_context_ensure(); say_image_target_will_delete(target->fbo, target->rbo); glDeleteRenderbuffersEXT(1, &(target->rbo)); glDeleteFramebuffersEXT(1, &(target->fbo)); say_target_free(target->target); free(target); }
void say_buffer_resize_instance(say_buffer *buf, size_t size) { mo_array_resize(buf->instance_buffer, size); say_context_ensure(); say_vbo_make_current(buf->instance_vbo); glBufferData(GL_ARRAY_BUFFER, size * buf->instance_buffer->el_size, say_buffer_get_instance(buf, 0), buf->type); }
void say_buffer_update_part(say_buffer *buf, size_t id, size_t size) { if (size == 0) return; say_context_ensure(); size_t byte_size = buf->buffer.el_size; say_vbo_make_current(buf->vbo); glBufferSubData(GL_ARRAY_BUFFER, byte_size * id, byte_size * size, say_buffer_get_vertex(buf, id)); }
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)); return target; }
/* * @overload draw_arrays_instanced(primitive, first, count, instance_count) * @param [Symbol] primitive (see #draw_arrays) * @param [Integer] first (see #draw_arrays) * @param [Integer] count (see #draw_arrays) * @param [Integer] instance_count Amount of instances to draw */ static VALUE ray_gl_draw_arrays_instanced(VALUE self, VALUE primitive, VALUE first, VALUE count, VALUE instance_count) { say_context_ensure(); if (glDrawArraysInstanced) { glDrawArraysInstanced(NUM2INT(rb_hash_aref(ray_gl_primitives, primitive)), NUM2ULONG(first), NUM2ULONG(count), NUM2ULONG(instance_count)); } else rb_raise(rb_eRuntimeError, "GL_ARB_draw_instanced is not supported"); return Qnil; }
/* * @overload callback=(proc) * Sets the proc called by OpenGL for debugging purpose * @param [Proc, nil] proc A proc, or nil to disable debugging * * The given proc will be called upon some events (errors or warnings about * performance and undifined behaviors) with the following arguments: * * 1. A source (:api, :window_system, :shader_compiler, :third_party, * :application, :other). * 2. A type (:error, :depreacted_behavior, :undefined_behavior, :portability, * :performance, :other). * 3. An integer identifier. * 4. A severity (:high, :medium, :low). * 5. A human-readable message. * * Notice the debugging proc is only called if the context has been created * in debug mode. * * @example * Ray::GL.debug = true # required * * Ray::GL.callback = proc do |source, type, _, severity, msg| * puts "[#{source}][#{type}][#{severity}] #{msg}" * end * * @see debug? */ static VALUE ray_gl_set_callback(VALUE self, VALUE proc) { say_context_ensure(); if (!glDebugMessageCallbackARB) rb_raise(rb_eRuntimeError, "setting the debug proc isn't supported"); rb_iv_set(rb_path2class("Ray::GL"), "@callback", proc); if (RTEST(proc)) glDebugMessageCallbackARB(ray_gl_debug_proc, NULL); else glDebugMessageCallbackARB(NULL, NULL); return proc; }
/* * @overload draw_elements_instanced(primitive, count, index, instance_count) * @param primitive (see #draw_arrays) * @param count (see #draw_arrays) * @param index (see #draw_elements) * @param instance_count (see #draw_arrays_instanced) */ static VALUE ray_gl_draw_elements_instanced(VALUE self, VALUE primitive, VALUE count, VALUE index, VALUE instance_count) { say_context_ensure(); if (glDrawElementsInstanced) { glDrawElementsInstanced(NUM2INT(rb_hash_aref(ray_gl_primitives, primitive)), NUM2ULONG(count), GL_UNSIGNED_INT, (void*)NUM2ULONG(index), NUM2ULONG(instance_count)); } else rb_raise(rb_eRuntimeError, "GL_ARB_draw_instanced is not supported"); return Qnil; }
void say_buffer_unbind() { say_context_ensure(); if (say_has_vao()) say_vao_make_current(0); else { /* disable vertex attribs */ for (size_t i = 1; i < GL_MAX_VERTEX_ATTRIBS; i++) { GLint enabled; glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled); if (enabled) glDisableVertexAttribArray(i); else break; } } }
say_buffer *say_buffer_create(size_t vtype, GLenum type, size_t size) { say_context_ensure(); say_buffer *buf = (say_buffer*)malloc(sizeof(say_buffer)); if (say_has_vao()) { buf->vaos = mo_hash_create(sizeof(say_context*), sizeof(say_vao_pair)); buf->vaos->release = (say_destructor)say_buffer_delete_vao_pair; buf->vaos->hash_of = mo_hash_of_pointer; buf->vaos->key_cmp = mo_hash_pointer_cmp; } else buf->vaos = NULL; buf->vtype = vtype; glGenBuffers(1, &buf->vbo); say_vbo_make_current(buf->vbo); buf->type = type; say_vertex_type *vtype_ref = say_get_vertex_type(vtype); size_t byte_size = say_vertex_type_get_size(vtype_ref); mo_array_init(&buf->buffer, byte_size); mo_array_resize(&buf->buffer, size); glBufferData(GL_ARRAY_BUFFER, size * byte_size, NULL, type); buf->instance_vbo = 0; buf->instance_buffer = NULL; if (say_vertex_type_has_instance_data(vtype_ref)) { glGenBuffers(1, &buf->instance_vbo); say_vbo_make_current(buf->instance_vbo); byte_size = say_vertex_type_get_instance_size(vtype_ref); buf->instance_buffer = mo_array_create(byte_size); } return buf; }
void say_buffer_free(say_buffer *buf) { say_context_ensure(); if (buf->vaos) mo_hash_free(buf->vaos); else say_buffer_will_delete(buf); say_vbo_will_delete(buf->vbo); glDeleteBuffers(1, &buf->vbo); if (buf->instance_vbo) { say_vbo_will_delete(buf->instance_vbo); glDeleteBuffers(1, &buf->instance_vbo); mo_array_free(buf->instance_buffer); } mo_array_release(&buf->buffer); free(buf); }
void say_image_target_set_image(say_image_target *target, say_image *image) { 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); } }
void say_image_target_bind(say_image_target *target) { say_context_ensure(); say_fbo_make_current(target->fbo); glClear(GL_DEPTH_BUFFER_BIT); }
/* @return [True, False] True if a callback proc can be set */ static VALUE ray_gl_has_callback(VALUE self) { say_context_ensure(); return glDebugMessageCallbackARB ? Qtrue : Qfalse; }
void say_buffer_unbind_vbo() { say_context_ensure(); say_vbo_make_current(0); }
void say_buffer_bind_instance_vbo(say_buffer *buf) { say_context_ensure(); say_vbo_make_current(buf->instance_vbo); }
/* * Ensures an OpenGL context is active for the current thread */ static VALUE ray_gl_ensure_context(VALUE self) { say_context_ensure(); return Qnil; }
bool say_image_target_is_available() { say_context_ensure(); return __GLEW_EXT_framebuffer_object != 0; }