#include "twn_gl_any_rendering_c.h" #include "twn_draw_c.h" #include "twn_engine_context_c.h" #include #ifdef EMSCRIPTEN #include #else #include #endif void setup_viewport(int x, int y, int width, int height) { glViewport(x, y, width, height); } VertexBuffer create_vertex_buffer(void) { GLuint result; glGenBuffers(1, &result); return result; } void delete_vertex_buffer(VertexBuffer buffer) { glDeleteBuffers(1, &buffer); } void specify_vertex_buffer(VertexBuffer buffer, void const *data, size_t bytes) { glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, bytes, data, GL_STREAM_DRAW); } VertexBuffer get_quad_element_buffer(void) { static VertexBuffer buffer = 0; /* it's only generated once at runtime */ /* TODO: use builder interface, not direct calls (glMapBuffer isn't portable) */ if (buffer == 0) { buffer = create_vertex_buffer(); VertexBufferBuilder builder = build_vertex_buffer(buffer, sizeof (GLshort) * QUAD_ELEMENT_BUFFER_LENGTH * 6 ); for (size_t i = 0; i < QUAD_ELEMENT_BUFFER_LENGTH; ++i) { GLshort indices[6]; indices[0] = (GLshort)(i * 4 + 0); indices[1] = (GLshort)(i * 4 + 1); indices[2] = (GLshort)(i * 4 + 2); indices[3] = (GLshort)(i * 4 + 2); indices[4] = (GLshort)(i * 4 + 3); indices[5] = (GLshort)(i * 4 + 0); push_to_vertex_buffer_builder(&builder, indices, sizeof indices); } } SDL_assert_always(buffer); return buffer; } VertexBuffer get_circle_element_buffer(void) { static VertexBuffer buffer = 0; if (buffer == 0) { buffer = create_vertex_buffer(); VertexBufferBuilder builder = build_vertex_buffer(buffer, sizeof (GLshort) * (CIRCLE_VERTICES_MAX - 2) * 3); for (size_t i = 1; i < CIRCLE_VERTICES_MAX - 1; ++i) { /* first one is center point index, always zero */ GLshort indices[3]; indices[0] = 0; /* generated point index */ indices[1] = (GLshort)i; indices[2] = (GLshort)i + 1; push_to_vertex_buffer_builder(&builder, indices, sizeof indices); } } SDL_assert_always(buffer); return buffer; } /* potentially double buffered array of vertex array handles */ /* we assume they will be refilled fully each frame */ static size_t scratch_va_front_used, scratch_va_back_used; static GLuint *front_scratch_vertex_arrays, *back_scratch_vertex_arrays; static GLuint **current_scratch_vertex_array = &front_scratch_vertex_arrays; void restart_scratch_vertex_arrays(void) { scratch_va_front_used = 0; scratch_va_back_used = 0; if (ctx.render_double_buffered) { current_scratch_vertex_array = current_scratch_vertex_array == &front_scratch_vertex_arrays ? &back_scratch_vertex_arrays : &front_scratch_vertex_arrays; } } GLuint get_scratch_vertex_array(void) { size_t *used = current_scratch_vertex_array == &front_scratch_vertex_arrays ? &scratch_va_front_used : &scratch_va_back_used; if (arrlenu(*current_scratch_vertex_array) <= *used) { GLuint handle; glGenBuffers(1, &handle); arrpush(*current_scratch_vertex_array, handle); } (*used)++; return (*current_scratch_vertex_array)[*used - 1]; }