summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/ra_gl.c
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-08-05 22:29:48 +0200
committerNiklas Haas <git@haasn.xyz>2017-08-07 12:46:30 +0200
commit9581fbe56926c75e52bc015fa6146b7f11f3d6a3 (patch)
tree252ff1098cd07bc5ae56770eecf0a3c0549435a5 /video/out/opengl/ra_gl.c
parent207458c7a9b682185a82ee23910c1327a70d276b (diff)
downloadmpv-9581fbe56926c75e52bc015fa6146b7f11f3d6a3.tar.bz2
mpv-9581fbe56926c75e52bc015fa6146b7f11f3d6a3.tar.xz
vo_opengl: generalize ra_buf to support other buffer objects
This allows us to integrate PBOs and SSBOs into the same abstraction, with the potential to easily add UBOs if the need arises.
Diffstat (limited to 'video/out/opengl/ra_gl.c')
-rw-r--r--video/out/opengl/ra_gl.c107
1 files changed, 70 insertions, 37 deletions
diff --git a/video/out/opengl/ra_gl.c b/video/out/opengl/ra_gl.c
index 4c99fe0f59..3966afcebb 100644
--- a/video/out/opengl/ra_gl.c
+++ b/video/out/opengl/ra_gl.c
@@ -30,6 +30,8 @@ int ra_init_gl(struct ra *ra, GL *gl)
ra->caps |= RA_CAP_PBO;
if (gl->mpgl_caps & MPGL_CAP_NESTED_ARRAY)
ra->caps |= RA_CAP_NESTED_ARRAY;
+ if (gl->mpgl_caps & MPGL_CAP_SSBO)
+ ra->caps |= RA_CAP_BUF_RW;
ra->glsl_version = gl->glsl_version;
ra->glsl_es = gl->es > 0;
@@ -329,16 +331,16 @@ GL *ra_gl_get(struct ra *ra)
static void gl_tex_upload(struct ra *ra, struct ra_tex *tex,
const void *src, ptrdiff_t stride,
struct mp_rect *rc, uint64_t flags,
- struct ra_mapped_buffer *buf)
+ struct ra_buf *buf)
{
GL *gl = ra_gl_get(ra);
struct ra_tex_gl *tex_gl = tex->priv;
- struct ra_mapped_buffer_gl *buf_gl = NULL;
+ struct ra_buf_gl *buf_gl = NULL;
struct mp_rect full = {0, 0, tex->params.w, tex->params.h};
if (buf) {
buf_gl = buf->priv;
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->pbo);
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->buffer);
src = (void *)((uintptr_t)src - (uintptr_t)buf->data);
}
@@ -380,57 +382,87 @@ static void gl_tex_upload(struct ra *ra, struct ra_tex *tex,
}
}
-static void gl_destroy_mapped_buffer(struct ra *ra, struct ra_mapped_buffer *buf)
+static void gl_buf_destroy(struct ra *ra, struct ra_buf *buf)
{
+ if (!buf)
+ return;
+
GL *gl = ra_gl_get(ra);
- struct ra_mapped_buffer_gl *buf_gl = buf->priv;
+ struct ra_buf_gl *buf_gl = buf->priv;
gl->DeleteSync(buf_gl->fence);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->pbo);
- if (buf->data)
- gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- gl->DeleteBuffers(1, &buf_gl->pbo);
+ if (buf->data) {
+ // The target type used here doesn't matter at all to OpenGL
+ gl->BindBuffer(GL_ARRAY_BUFFER, buf_gl->buffer);
+ gl->UnmapBuffer(GL_ARRAY_BUFFER);
+ gl->BindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ gl->DeleteBuffers(1, &buf_gl->buffer);
talloc_free(buf_gl);
talloc_free(buf);
}
-static struct ra_mapped_buffer *gl_create_mapped_buffer(struct ra *ra,
- size_t size)
+static struct ra_buf *gl_buf_create(struct ra *ra,
+ const struct ra_buf_params *params)
{
GL *gl = ra_gl_get(ra);
- if (gl->version < 440)
+ if (params->host_mapped && gl->version < 440)
return NULL;
- struct ra_mapped_buffer *buf = talloc_zero(NULL, struct ra_mapped_buffer);
- buf->size = size;
+ struct ra_buf *buf = talloc_zero(NULL, struct ra_buf);
+ buf->params = *params;
+ buf->params.initial_data = NULL;
- struct ra_mapped_buffer_gl *buf_gl = buf->priv =
- talloc_zero(NULL, struct ra_mapped_buffer_gl);
+ struct ra_buf_gl *buf_gl = buf->priv = talloc_zero(NULL, struct ra_buf_gl);
+ gl->GenBuffers(1, &buf_gl->buffer);
- unsigned flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT |
- GL_MAP_COHERENT_BIT;
+ GLenum target;
+ switch (params->type) {
+ case RA_BUF_TYPE_TEX_UPLOAD: target = GL_PIXEL_UNPACK_BUFFER; break;
+ case RA_BUF_TYPE_SHADER_STORAGE: target = GL_SHADER_STORAGE_BUFFER; break;
+ default: abort();
+ };
- gl->GenBuffers(1, &buf_gl->pbo);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->pbo);
- gl->BufferStorage(GL_PIXEL_UNPACK_BUFFER, size, NULL, flags | GL_CLIENT_STORAGE_BIT);
- buf->data = gl->MapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, buf->size, flags);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- if (!buf->data) {
- gl_check_error(gl, ra->log, "mapping buffer");
- gl_destroy_mapped_buffer(ra, buf);
- return NULL;
+ gl->BindBuffer(target, buf_gl->buffer);
+
+ if (params->host_mapped) {
+ unsigned flags = GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT |
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+
+ unsigned storflags = flags;
+ if (params->type == RA_BUF_TYPE_TEX_UPLOAD)
+ storflags |= GL_CLIENT_STORAGE_BIT;
+
+ gl->BufferStorage(target, params->size, params->initial_data, storflags);
+ buf->data = gl->MapBufferRange(target, 0, params->size, flags);
+ if (!buf->data) {
+ gl_check_error(gl, ra->log, "mapping buffer");
+ gl_buf_destroy(ra, buf);
+ buf = NULL;
+ }
+ } else {
+ GLenum hint;
+ switch (params->type) {
+ case RA_BUF_TYPE_TEX_UPLOAD: hint = GL_STREAM_DRAW; break;
+ case RA_BUF_TYPE_SHADER_STORAGE: hint = GL_STREAM_COPY; break;
+ default: abort();
+ }
+
+ gl->BufferData(target, params->size, params->initial_data, hint);
}
+ gl->BindBuffer(target, 0);
return buf;
}
-static bool gl_poll_mapped_buffer(struct ra *ra, struct ra_mapped_buffer *buf)
+static bool gl_poll_mapped_buffer(struct ra *ra, struct ra_buf *buf)
{
+ assert(buf->data);
+
GL *gl = ra_gl_get(ra);
- struct ra_mapped_buffer_gl *buf_gl = buf->priv;
+ struct ra_buf_gl *buf_gl = buf->priv;
if (buf_gl->fence) {
GLenum res = gl->ClientWaitSync(buf_gl->fence, 0, 0); // non-blocking
@@ -743,9 +775,11 @@ static void update_uniform(struct ra *ra, struct ra_renderpass *pass,
}
break;
}
- case RA_VARTYPE_SSBO: {
- gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, input->binding,
- *(int *)val->data);
+ case RA_VARTYPE_BUF_RW: {
+ struct ra_buf *buf = *(struct ra_buf **)val->data;
+ struct ra_buf_gl *buf_gl = buf->priv;
+ gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, input->binding, buf_gl->buffer);
+ gl->MemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
break;
}
default:
@@ -775,11 +809,10 @@ static void disable_binding(struct ra *ra, struct ra_renderpass *pass,
}
break;
}
- case RA_VARTYPE_SSBO: {
+ case RA_VARTYPE_BUF_RW:
gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, input->binding, 0);
break;
}
- }
}
static void gl_renderpass_run(struct ra *ra,
@@ -915,8 +948,8 @@ static struct ra_fns ra_fns_gl = {
.tex_create = gl_tex_create,
.tex_destroy = gl_tex_destroy,
.tex_upload = gl_tex_upload,
- .create_mapped_buffer = gl_create_mapped_buffer,
- .destroy_mapped_buffer = gl_destroy_mapped_buffer,
+ .buf_create = gl_buf_create,
+ .buf_destroy = gl_buf_destroy,
.poll_mapped_buffer = gl_poll_mapped_buffer,
.clear = gl_clear,
.blit = gl_blit,