summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-01-28 22:22:29 +0100
committerwm4 <wm4@nowhere>2015-01-28 22:22:29 +0100
commit34d3a27f28030a05830a775420cc692a2156bf7d (patch)
treeac0733ed43569ce1ab471773dbbe342b239741a5
parent616481ad290b3bc43d551d946dd5c0fe7423f8b2 (diff)
downloadmpv-34d3a27f28030a05830a775420cc692a2156bf7d.tar.bz2
mpv-34d3a27f28030a05830a775420cc692a2156bf7d.tar.xz
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.
-rw-r--r--video/out/gl_utils.c86
-rw-r--r--video/out/gl_utils.h23
-rw-r--r--video/out/gl_video.c77
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 <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);
+}
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)