From 34d3a27f28030a05830a775420cc692a2156bf7d Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 28 Jan 2015 22:22:29 +0100 Subject: vo_opengl: create abstraction for VAOs Handles stupid boilerplate OpenGL requires you to handle. It's the same code as in gl_video.c, although if no VAOs are available, the fallback code rebinds them on every draw call instead of just once. --- video/out/gl_utils.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ video/out/gl_utils.h | 23 ++++++++++++++ video/out/gl_video.c | 77 +++++++++------------------------------------- 3 files changed, 124 insertions(+), 62 deletions(-) diff --git a/video/out/gl_utils.c b/video/out/gl_utils.c index 4ab0479062..ad2baf442d 100644 --- a/video/out/gl_utils.c +++ b/video/out/gl_utils.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "common/common.h" #include "gl_utils.h" @@ -211,3 +212,88 @@ void mp_log_source(struct mp_log *log, int lev, const char *src) src = next; } } + +static void gl_vao_enable_attribs(struct gl_vao *vao) +{ + GL *gl = vao->gl; + + for (int n = 0; vao->entries[n].name; n++) { + const struct gl_vao_entry *e = &vao->entries[n]; + + gl->EnableVertexAttribArray(n); + gl->VertexAttribPointer(n, e->num_elems, e->type, e->normalized, + vao->stride, (void*)e->offset); + } +} + +void gl_vao_init(struct gl_vao *vao, GL *gl, int stride, + const struct gl_vao_entry *entries) +{ + assert(!vao->vao); + assert(!vao->buffer); + + *vao = (struct gl_vao){ + .gl = gl, + .stride = stride, + .entries = entries, + }; + + gl->GenBuffers(1, &vao->buffer); + + if (gl->BindVertexArray) { + gl->BindBuffer(GL_ARRAY_BUFFER, vao->buffer); + + gl->GenVertexArrays(1, &vao->vao); + gl->BindVertexArray(vao->vao); + gl_vao_enable_attribs(vao); + gl->BindVertexArray(0); + + gl->BindBuffer(GL_ARRAY_BUFFER, 0); + } +} + +void gl_vao_uninit(struct gl_vao *vao) +{ + GL *gl = vao->gl; + if (!gl) + return; + + if (gl->DeleteVertexArrays) + gl->DeleteVertexArrays(1, &vao->vao); + gl->DeleteBuffers(1, &vao->buffer); + + *vao = (struct gl_vao){0}; +} + +void gl_vao_bind(struct gl_vao *vao) +{ + GL *gl = vao->gl; + + if (gl->BindVertexArray) { + gl->BindVertexArray(vao->vao); + } else { + gl->BindBuffer(GL_ARRAY_BUFFER, vao->buffer); + gl_vao_enable_attribs(vao); + gl->BindBuffer(GL_ARRAY_BUFFER, 0); + } +} + +void gl_vao_unbind(struct gl_vao *vao) +{ + GL *gl = vao->gl; + + if (gl->BindVertexArray) { + gl->BindVertexArray(0); + } else { + for (int n = 0; vao->entries[n].name; n++) + gl->DisableVertexAttribArray(n); + } +} + +void gl_vao_bind_attribs(struct gl_vao *vao, GLuint program) +{ + GL *gl = vao->gl; + + for (int n = 0; vao->entries[n].name; n++) + gl->BindAttribLocation(program, n, vao->entries[n].name); +} diff --git a/video/out/gl_utils.h b/video/out/gl_utils.h index 4f32e5ff56..482c88a0fa 100644 --- a/video/out/gl_utils.h +++ b/video/out/gl_utils.h @@ -43,4 +43,27 @@ mp_image_t *glGetWindowScreenshot(GL *gl); // log, lev: module and log level, as in mp_msg() void mp_log_source(struct mp_log *log, int lev, const char *src); +struct gl_vao_entry { + const char *name; + int num_elems; + GLenum type; + bool normalized; + int offset; +}; + +struct gl_vao { + GL *gl; + GLuint vao; + GLuint buffer; + int stride; // always assuming interleaved elements + const struct gl_vao_entry *entries; +}; + +void gl_vao_init(struct gl_vao *vao, GL *gl, int stride, + const struct gl_vao_entry *entries); +void gl_vao_uninit(struct gl_vao *vao); +void gl_vao_bind(struct gl_vao *vao); +void gl_vao_unbind(struct gl_vao *vao); +void gl_vao_bind_attribs(struct gl_vao *vao, GLuint program); + #endif diff --git a/video/out/gl_video.c b/video/out/gl_video.c index e518a9233a..9617a13ca3 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -76,9 +76,12 @@ struct vertex { float texcoord[2]; }; -#define VERTEX_ATTRIB_POSITION 0 -#define VERTEX_ATTRIB_COLOR 1 -#define VERTEX_ATTRIB_TEXCOORD 2 +static const struct gl_vao_entry vertex_vao[] = { + {"vertex_position", 2, GL_FLOAT, false, offsetof(struct vertex, position)}, + {"vertex_color", 4, GL_UNSIGNED_BYTE, true, offsetof(struct vertex, color)}, + {"vertex_texcoord", 2, GL_FLOAT, false, offsetof(struct vertex, texcoord)}, + {0} +}; // 2 triangles primitives per quad = 6 vertices per quad // (GL_QUAD is deprecated, strips can't be used with OSD image lists) @@ -143,8 +146,7 @@ struct gl_video { GLenum gl_target; // texture target (GL_TEXTURE_2D, ...) for video and FBOs - GLuint vertex_buffer; - GLuint vao; + struct gl_vao vao; GLuint osd_programs[SUBBITMAP_COUNT]; GLuint indirect_program, scale_sep_program, final_program, inter_program; @@ -531,18 +533,16 @@ static void draw_triangles(struct gl_video *p, struct vertex *vb, int vert_count assert(vert_count % 3 == 0); - gl->BindBuffer(GL_ARRAY_BUFFER, p->vertex_buffer); + gl->BindBuffer(GL_ARRAY_BUFFER, p->vao.buffer); gl->BufferData(GL_ARRAY_BUFFER, vert_count * sizeof(struct vertex), vb, GL_DYNAMIC_DRAW); gl->BindBuffer(GL_ARRAY_BUFFER, 0); - if (gl->BindVertexArray) - gl->BindVertexArray(p->vao); + gl_vao_bind(&p->vao); gl->DrawArrays(GL_TRIANGLES, 0, vert_count); - if (gl->BindVertexArray) - gl->BindVertexArray(0); + gl_vao_unbind(&p->vao); debug_check_gl(p, "after rendering"); } @@ -956,13 +956,6 @@ static void link_shader(struct gl_video *p, GLuint program) } } -static void bind_attrib_locs(GL *gl, GLuint program) -{ - gl->BindAttribLocation(program, VERTEX_ATTRIB_POSITION, "vertex_position"); - gl->BindAttribLocation(program, VERTEX_ATTRIB_COLOR, "vertex_color"); - gl->BindAttribLocation(program, VERTEX_ATTRIB_TEXCOORD, "vertex_texcoord"); -} - #define PRELUDE_END "// -- prelude end\n" static GLuint create_program(struct gl_video *p, const char *name, @@ -977,7 +970,7 @@ static GLuint create_program(struct gl_video *p, const char *name, GLuint prog = gl->CreateProgram(); prog_create_shader(p, prog, GL_VERTEX_SHADER, header, vertex); prog_create_shader(p, prog, GL_FRAGMENT_SHADER, header, frag); - bind_attrib_locs(gl, prog); + gl_vao_bind_attribs(&p->vao, prog); link_shader(p, prog); return prog; } @@ -2384,23 +2377,6 @@ static void check_gl_features(struct gl_video *p) } } -static void setup_vertex_array(GL *gl) -{ - size_t stride = sizeof(struct vertex); - - gl->EnableVertexAttribArray(VERTEX_ATTRIB_POSITION); - gl->VertexAttribPointer(VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, - stride, (void*)offsetof(struct vertex, position)); - - gl->EnableVertexAttribArray(VERTEX_ATTRIB_COLOR); - gl->VertexAttribPointer(VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, - stride, (void*)offsetof(struct vertex, color)); - - gl->EnableVertexAttribArray(VERTEX_ATTRIB_TEXCOORD); - gl->VertexAttribPointer(VERTEX_ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, - stride, (void*)offsetof(struct vertex, texcoord)); -} - static int init_gl(struct gl_video *p) { GL *gl = p->gl; @@ -2411,17 +2387,7 @@ static int init_gl(struct gl_video *p) gl->Disable(GL_DITHER); - gl->GenBuffers(1, &p->vertex_buffer); - gl->BindBuffer(GL_ARRAY_BUFFER, p->vertex_buffer); - - if (gl->BindVertexArray) { - gl->GenVertexArrays(1, &p->vao); - gl->BindVertexArray(p->vao); - setup_vertex_array(gl); - gl->BindVertexArray(0); - } - - gl->BindBuffer(GL_ARRAY_BUFFER, 0); + gl_vao_init(&p->vao, gl, sizeof(struct vertex), vertex_vao); gl_video_set_gl_state(p); @@ -2462,9 +2428,8 @@ void gl_video_uninit(struct gl_video *p) uninit_video(p); - if (gl->DeleteVertexArrays) - gl->DeleteVertexArrays(1, &p->vao); - gl->DeleteBuffers(1, &p->vertex_buffer); + gl_vao_uninit(&p->vao); + gl->DeleteTextures(1, &p->lut_3d_texture); mpgl_osd_destroy(p->osd); @@ -2485,23 +2450,11 @@ void gl_video_set_gl_state(struct gl_video *p) if (gl->mpgl_caps & MPGL_CAP_ROW_LENGTH) gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0); gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4); - - if (!gl->BindVertexArray) { - gl->BindBuffer(GL_ARRAY_BUFFER, p->vertex_buffer); - setup_vertex_array(gl); - gl->BindBuffer(GL_ARRAY_BUFFER, 0); - } } void gl_video_unset_gl_state(struct gl_video *p) { - GL *gl = p->gl; - - if (!gl->BindVertexArray) { - gl->DisableVertexAttribArray(VERTEX_ATTRIB_POSITION); - gl->DisableVertexAttribArray(VERTEX_ATTRIB_COLOR); - gl->DisableVertexAttribArray(VERTEX_ATTRIB_TEXCOORD); - } + /* nop */ } void gl_video_reset(struct gl_video *p) -- cgit v1.2.3