summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-08-19 04:33:40 +0200
committerNiklas Haas <git@haasn.xyz>2017-08-22 09:55:49 +0200
commit09c501a40eed7cb05c73fc30ea814d1d256ac0eb (patch)
tree2508bf03c8a22b098d955ddc7b3abc328d089296 /video
parent371000108acb40a99412316fe1bba2883441c38a (diff)
downloadmpv-09c501a40eed7cb05c73fc30ea814d1d256ac0eb.tar.bz2
mpv-09c501a40eed7cb05c73fc30ea814d1d256ac0eb.tar.xz
vo_opengl: refactor tex_upload to ra_buf_pool
Also refactors the usage of tex_upload to make ra_tex_upload_pbo a RA-internal thing again. ra_buf_pool has the main advantage of being dynamically sized depending on buf_poll, so for OpenGL we'll end up only using one buffer (when not persistently mapping) - while for vulkan we'll use as many as necessary, which depends on the swapchain depth anyway.
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/osd.c8
-rw-r--r--video/out/opengl/osd.h2
-rw-r--r--video/out/opengl/ra.h5
-rw-r--r--video/out/opengl/ra_gl.c6
-rw-r--r--video/out/opengl/utils.c142
-rw-r--r--video/out/opengl/utils.h34
-rw-r--r--video/out/opengl/video.c11
7 files changed, 124 insertions, 84 deletions
diff --git a/video/out/opengl/osd.c b/video/out/opengl/osd.c
index 967b81e535..f7c325d1db 100644
--- a/video/out/opengl/osd.c
+++ b/video/out/opengl/osd.c
@@ -54,7 +54,6 @@ struct mpgl_osd_part {
enum sub_bitmap_format format;
int change_id;
struct ra_tex *texture;
- struct tex_upload pbo;
int w, h;
int num_subparts;
int prev_num_subparts;
@@ -71,7 +70,6 @@ struct mpgl_osd {
const struct ra_format *fmt_table[SUBBITMAP_COUNT];
bool formats[SUBBITMAP_COUNT];
bool change_flag; // for reporting to API user only
- bool want_pbo;
// temporary
int stereo_mode;
struct mp_osd_res osd_res;
@@ -79,7 +77,7 @@ struct mpgl_osd {
};
struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log,
- struct osd_state *osd, bool want_pbo)
+ struct osd_state *osd)
{
struct mpgl_osd *ctx = talloc_ptrtype(NULL, ctx);
*ctx = (struct mpgl_osd) {
@@ -88,7 +86,6 @@ struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log,
.ra = ra,
.change_flag = true,
.scratch = talloc_zero_size(ctx, 1),
- .want_pbo = want_pbo,
};
ctx->fmt_table[SUBBITMAP_LIBASS] = ra_find_unorm_format(ra, 1, 1);
@@ -111,7 +108,6 @@ void mpgl_osd_destroy(struct mpgl_osd *ctx)
for (int n = 0; n < MAX_OSD_PARTS; n++) {
struct mpgl_osd_part *p = ctx->parts[n];
ra_tex_free(ctx->ra, &p->texture);
- tex_upload_uninit(ctx->ra, &p->pbo);
}
talloc_free(ctx);
}
@@ -180,7 +176,7 @@ static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
.stride = imgs->packed->stride[0],
};
- ok = tex_upload(ra, &osd->pbo, ctx->want_pbo, &params);
+ ok = ra->fns->tex_upload(ra, &params);
done:
return ok;
diff --git a/video/out/opengl/osd.h b/video/out/opengl/osd.h
index b5618ce5f0..6c2b886de3 100644
--- a/video/out/opengl/osd.h
+++ b/video/out/opengl/osd.h
@@ -9,7 +9,7 @@
#include "sub/osd.h"
struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log,
- struct osd_state *osd, bool want_pbo);
+ struct osd_state *osd);
void mpgl_osd_destroy(struct mpgl_osd *ctx);
void mpgl_osd_generate(struct mpgl_osd *ctx, struct mp_osd_res res, double pts,
diff --git a/video/out/opengl/ra.h b/video/out/opengl/ra.h
index eee1728bba..8658a0737c 100644
--- a/video/out/opengl/ra.h
+++ b/video/out/opengl/ra.h
@@ -30,6 +30,11 @@ struct ra {
// formats should have a lower index. (E.g. GLES3 should put rg8 before la.)
struct ra_format **formats;
int num_formats;
+
+ // Accelerate texture uploads via an extra PBO even when
+ // RA_CAP_DIRECT_UPLOAD is supported. This is basically only relevant for
+ // OpenGL. Set by the RA user.
+ bool use_pbo;
};
enum {
diff --git a/video/out/opengl/ra_gl.c b/video/out/opengl/ra_gl.c
index f63bbe3ea5..e31948c2b1 100644
--- a/video/out/opengl/ra_gl.c
+++ b/video/out/opengl/ra_gl.c
@@ -15,6 +15,7 @@ struct ra_gl {
// For ra_tex.priv
struct ra_tex_gl {
+ struct ra_buf_pool pbo; // for ra.use_pbo
bool own_objects;
GLenum target;
GLuint texture; // 0 if no texture data associated
@@ -218,6 +219,8 @@ static void gl_tex_destroy(struct ra *ra, struct ra_tex *tex)
GL *gl = ra_gl_get(ra);
struct ra_tex_gl *tex_gl = tex->priv;
+ ra_buf_pool_uninit(ra, &tex_gl->pbo);
+
if (tex_gl->own_objects) {
if (tex_gl->fbo)
gl->DeleteFramebuffers(1, &tex_gl->fbo);
@@ -435,6 +438,9 @@ static bool gl_tex_upload(struct ra *ra,
assert(tex->params.host_mutable);
assert(!params->buf || !params->src);
+ if (ra->use_pbo && !params->buf)
+ return ra_tex_upload_pbo(ra, &tex_gl->pbo, params);
+
const void *src = params->src;
if (buf) {
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->buffer);
diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c
index 5ef4349fff..e7fce62662 100644
--- a/video/out/opengl/utils.c
+++ b/video/out/opengl/utils.c
@@ -39,6 +39,91 @@ void gl_transform_ortho_fbodst(struct gl_transform *t, struct fbodst fbo)
gl_transform_ortho(t, 0, fbo.tex->params.w, 0, fbo.tex->params.h * y_dir);
}
+void ra_buf_pool_uninit(struct ra *ra, struct ra_buf_pool *pool)
+{
+ for (int i = 0; i < pool->num_buffers; i++)
+ ra_buf_free(ra, &pool->buffers[i]);
+
+ talloc_free(pool->buffers);
+ *pool = (struct ra_buf_pool){0};
+}
+
+static bool ra_buf_params_compatible(const struct ra_buf_params *new,
+ const struct ra_buf_params *old)
+{
+ return new->type == old->type &&
+ new->size <= old->size &&
+ new->host_mapped == old->host_mapped &&
+ new->host_mutable == old->host_mutable;
+}
+
+static bool ra_buf_pool_grow(struct ra *ra, struct ra_buf_pool *pool)
+{
+ struct ra_buf *buf = ra_buf_create(ra, &pool->current_params);
+ if (!buf)
+ return false;
+
+ MP_TARRAY_INSERT_AT(NULL, pool->buffers, pool->num_buffers, pool->index, buf);
+ MP_VERBOSE(ra, "Resized buffer pool to size %d\n", pool->num_buffers);
+ return true;
+}
+
+struct ra_buf *ra_buf_pool_get(struct ra *ra, struct ra_buf_pool *pool,
+ const struct ra_buf_params *params)
+{
+ assert(!params->initial_data);
+
+ if (!ra_buf_params_compatible(params, &pool->current_params)) {
+ ra_buf_pool_uninit(ra, pool);
+ pool->current_params = *params;
+ }
+
+ // Make sure we have at least one buffer available
+ if (!pool->buffers && !ra_buf_pool_grow(ra, pool))
+ return NULL;
+
+ // Make sure the next buffer is available for use
+ if (!ra->fns->buf_poll(ra, pool->buffers[pool->index]) &&
+ !ra_buf_pool_grow(ra, pool))
+ {
+ return NULL;
+ }
+
+ struct ra_buf *buf = pool->buffers[pool->index++];
+ pool->index %= pool->num_buffers;
+
+ return buf;
+}
+
+bool ra_tex_upload_pbo(struct ra *ra, struct ra_buf_pool *pbo,
+ const struct ra_tex_upload_params *params)
+{
+ if (params->buf)
+ return ra->fns->tex_upload(ra, params);
+
+ struct ra_tex *tex = params->tex;
+ size_t row_size = tex->params.dimensions == 2 ? params->stride :
+ tex->params.w * tex->params.format->pixel_size;
+
+ struct ra_buf_params bufparams = {
+ .type = RA_BUF_TYPE_TEX_UPLOAD,
+ .size = row_size * tex->params.h * tex->params.d,
+ .host_mutable = true,
+ };
+
+ struct ra_buf *buf = ra_buf_pool_get(ra, pbo, &bufparams);
+ if (!buf)
+ return false;
+
+ ra->fns->buf_update(ra, buf, 0, params->src, bufparams.size);
+
+ struct ra_tex_upload_params newparams = *params;
+ newparams.buf = buf;
+ newparams.src = NULL;
+
+ return ra->fns->tex_upload(ra, &newparams);
+}
+
// Create a texture and a FBO using the texture as color attachments.
// fmt: texture internal format
// If the parameters are the same as the previous call, do not touch it.
@@ -120,63 +205,6 @@ void fbotex_uninit(struct fbotex *fbo)
}
}
-bool tex_upload(struct ra *ra, struct tex_upload *pbo, bool want_pbo,
- const struct ra_tex_upload_params *params)
-{
- if (!(ra->caps & RA_CAP_DIRECT_UPLOAD))
- want_pbo = true;
-
- if (!want_pbo || params->buf)
- return ra->fns->tex_upload(ra, params);
-
- struct ra_tex *tex = params->tex;
- size_t row_size = tex->params.dimensions == 2 ? params->stride :
- tex->params.w * tex->params.format->pixel_size;
- size_t needed_size = row_size * tex->params.h * tex->params.d;
-
- if (needed_size > pbo->buffer_size)
- tex_upload_uninit(ra, pbo);
-
- if (!pbo->buffers[0]) {
- struct ra_buf_params bufparams = {
- .type = RA_BUF_TYPE_TEX_UPLOAD,
- .size = needed_size,
- .host_mutable = true,
- };
-
- pbo->buffer_size = bufparams.size;
- for (int i = 0; i < NUM_PBO_BUFFERS; i++) {
- pbo->buffers[i] = ra_buf_create(ra, &bufparams);
- if (!pbo->buffers[i])
- return false;
- }
- }
-
- struct ra_buf *buf = pbo->buffers[pbo->index++];
- pbo->index %= NUM_PBO_BUFFERS;
-
- if (!ra->fns->buf_poll(ra, buf)) {
- MP_WARN(ra, "Texture upload buffer was not free to use! Try "
- "increasing NUM_PBO_BUFFERS.\n");
- return false;
- }
-
- ra->fns->buf_update(ra, buf, 0, params->src, needed_size);
-
- struct ra_tex_upload_params newparams = *params;
- newparams.buf = buf;
- newparams.src = NULL;
-
- return ra->fns->tex_upload(ra, &newparams);
-}
-
-void tex_upload_uninit(struct ra *ra, struct tex_upload *pbo)
-{
- for (int i = 0; i < NUM_PBO_BUFFERS; i++)
- ra_buf_free(ra, &pbo->buffers[i]);
- *pbo = (struct tex_upload){0};
-}
-
struct timer_pool {
struct ra *ra;
ra_timer *timer;
diff --git a/video/out/opengl/utils.h b/video/out/opengl/utils.h
index aaaf4bd12e..8c52680f14 100644
--- a/video/out/opengl/utils.h
+++ b/video/out/opengl/utils.h
@@ -69,6 +69,25 @@ struct fbodst {
void gl_transform_ortho_fbodst(struct gl_transform *t, struct fbodst fbo);
+// A pool of buffers, which can grow as needed
+struct ra_buf_pool {
+ struct ra_buf_params current_params;
+ struct ra_buf **buffers;
+ int num_buffers;
+ int index;
+};
+
+void ra_buf_pool_uninit(struct ra *ra, struct ra_buf_pool *pool);
+
+// Note: params->initial_data is *not* supported
+struct ra_buf *ra_buf_pool_get(struct ra *ra, struct ra_buf_pool *pool,
+ const struct ra_buf_params *params);
+
+// Helper that wraps ra_tex_upload using texture upload buffers to ensure that
+// params->buf is always set. This is intended for RA-internal usage.
+bool ra_tex_upload_pbo(struct ra *ra, struct ra_buf_pool *pbo,
+ const struct ra_tex_upload_params *params);
+
struct fbotex {
struct ra *ra;
struct ra_tex *tex;
@@ -83,21 +102,6 @@ bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log,
#define FBOTEX_FUZZY_H 2
#define FBOTEX_FUZZY (FBOTEX_FUZZY_W | FBOTEX_FUZZY_H)
-#define NUM_PBO_BUFFERS 3
-
-// A wrapper around tex_upload that uses PBOs internally if requested or
-// required
-struct tex_upload {
- size_t buffer_size;
- struct ra_buf *buffers[NUM_PBO_BUFFERS];
- int index;
-};
-
-bool tex_upload(struct ra *ra, struct tex_upload *pbo, bool want_pbo,
- const struct ra_tex_upload_params *params);
-
-void tex_upload_uninit(struct ra *ra, struct tex_upload *pbo);
-
// A wrapper around ra_timer that does result pooling, averaging etc.
struct timer_pool;
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index e8ff23f2b4..bb3730022a 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -84,7 +84,6 @@ static const struct ra_renderpass_input vertex_vao[] = {
struct texplane {
struct ra_tex *tex;
- struct tex_upload pbo;
int w, h;
bool flipped;
};
@@ -494,7 +493,7 @@ static void reinit_osd(struct gl_video *p)
mpgl_osd_destroy(p->osd);
p->osd = NULL;
if (p->osd_state)
- p->osd = mpgl_osd_init(p->ra, p->log, p->osd_state, p->opts.pbo);
+ p->osd = mpgl_osd_init(p->ra, p->log, p->osd_state);
}
static void uninit_rendering(struct gl_video *p)
@@ -987,7 +986,6 @@ static void uninit_video(struct gl_video *p)
for (int n = 0; n < p->plane_count; n++) {
struct texplane *plane = &vimg->planes[n];
ra_tex_free(p->ra, &plane->tex);
- tex_upload_uninit(p->ra, &plane->pbo);
}
*vimg = (struct video_image){0};
@@ -3291,7 +3289,7 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t
MP_VERBOSE(p, "DR enabled: %s\n", p->using_dr_path ? "yes" : "no");
}
- if (!tex_upload(p->ra, &plane->pbo, p->opts.pbo, &params)) {
+ if (!p->ra->fns->tex_upload(p->ra, &params)) {
timer_pool_stop(p->upload_timer);
goto error;
}
@@ -3300,7 +3298,9 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t
mapped->mpi = mp_image_new_ref(mpi);
}
timer_pool_stop(p->upload_timer);
- const char *mode = p->using_dr_path ? "DR" : p->opts.pbo ? "PBO" : "naive";
+
+ bool using_pbo = p->ra->use_pbo || !(p->ra->caps & RA_CAP_DIRECT_UPLOAD);
+ const char *mode = p->using_dr_path ? "DR" : using_pbo ? "PBO" : "naive";
pass_describe(p, "upload frame (%s)", mode);
pass_record(p, timer_pool_measure(p->upload_timer));
@@ -3639,6 +3639,7 @@ static void reinit_from_options(struct gl_video *p)
check_gl_features(p);
uninit_rendering(p);
gl_sc_set_cache_dir(p->sc, p->opts.shader_cache_dir);
+ p->ra->use_pbo = p->opts.pbo;
gl_video_setup_hooks(p);
reinit_osd(p);