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.
This commit is contained in:
wm4
2015-01-28 22:22:29 +01:00
parent 616481ad29
commit 34d3a27f28
3 changed files with 124 additions and 62 deletions
+86
View File
@@ -25,6 +25,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#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);
}
+23
View File
@@ -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
+15 -62
View File
@@ -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)