summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-09-23 09:54:42 +0200
committerNiklas Haas <git@haasn.xyz>2017-09-23 09:58:27 +0200
commitb0ba193b66b402c5417aa5c0863cc357139e528d (patch)
tree8e97f4e4a26311a28fa3c94d2c2f4349f83b8a1a /video
parentf3ec4946137a29e0b2c2bb181b369a3a770bf4bc (diff)
downloadmpv-b0ba193b66b402c5417aa5c0863cc357139e528d.tar.bz2
mpv-b0ba193b66b402c5417aa5c0863cc357139e528d.tar.xz
vo_gpu: handle texture initialization errors gracefully
Tested by making the ra_tex_resize function always fail (apart from the initial FBO check). This required a few changes: 1. reset shaders on failed dispatch 2. reset cleanup binds on failed dispatch 3. fall back to initializing the struct image to 1x1 on failure 4. handle output_fbo_valid gracefully
Diffstat (limited to 'video')
-rw-r--r--video/out/gpu/shader_cache.c6
-rw-r--r--video/out/gpu/shader_cache.h3
-rw-r--r--video/out/gpu/video.c37
3 files changed, 27 insertions, 19 deletions
diff --git a/video/out/gpu/shader_cache.c b/video/out/gpu/shader_cache.c
index ead759d931..86939083db 100644
--- a/video/out/gpu/shader_cache.c
+++ b/video/out/gpu/shader_cache.c
@@ -104,8 +104,6 @@ struct gl_shader_cache {
struct mpv_global *global; // can be NULL
};
-static void gl_sc_reset(struct gl_shader_cache *sc);
-
struct gl_shader_cache *gl_sc_create(struct ra *ra, struct mpv_global *global,
struct mp_log *log)
{
@@ -120,8 +118,8 @@ struct gl_shader_cache *gl_sc_create(struct ra *ra, struct mpv_global *global,
}
// Reset the previous pass. This must be called after gl_sc_generate and before
-// starting a new shader.
-static void gl_sc_reset(struct gl_shader_cache *sc)
+// starting a new shader. It may also be called on errors.
+void gl_sc_reset(struct gl_shader_cache *sc)
{
sc->prelude_text.len = 0;
sc->header_text.len = 0;
diff --git a/video/out/gpu/shader_cache.h b/video/out/gpu/shader_cache.h
index 82a078079b..377293391c 100644
--- a/video/out/gpu/shader_cache.h
+++ b/video/out/gpu/shader_cache.h
@@ -53,4 +53,7 @@ struct mp_pass_perf gl_sc_dispatch_draw(struct gl_shader_cache *sc,
void *ptr, size_t num);
struct mp_pass_perf gl_sc_dispatch_compute(struct gl_shader_cache *sc,
int w, int h, int d);
+// The application can call this on errors, to reset the current shader. This
+// is normally done implicitly by gl_sc_dispatch_*
+void gl_sc_reset(struct gl_shader_cache *sc);
void gl_sc_set_cache_dir(struct gl_shader_cache *sc, const char *dir);
diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c
index ae847b1782..4cc6114c52 100644
--- a/video/out/gpu/video.c
+++ b/video/out/gpu/video.c
@@ -622,8 +622,8 @@ static struct image image_wrap(struct ra_tex *tex, enum plane_type type,
.type = type,
.tex = tex,
.multiplier = 1.0,
- .w = tex->params.w,
- .h = tex->params.h,
+ .w = tex ? tex->params.w : 1,
+ .h = tex ? tex->params.h : 1,
.transform = identity_trans,
.components = components,
};
@@ -1096,6 +1096,12 @@ static void pass_is_compute(struct gl_video *p, int bw, int bh)
};
}
+static void cleanup_binds(struct gl_video *p)
+{
+ memset(&p->pass_img, 0, sizeof(p->pass_img));
+ p->pass_img_num = 0;
+}
+
// w/h: the width/height of the compute shader's operating domain (e.g. the
// target target that needs to be written, or the source texture that needs to
// be reduced)
@@ -1140,9 +1146,7 @@ static void dispatch_compute(struct gl_video *p, int w, int h,
num_y = info.block_h > 0 ? (h + info.block_h - 1) / info.block_h : 1;
pass_record(p, gl_sc_dispatch_compute(p->sc, num_x, num_y, 1));
-
- memset(&p->pass_img, 0, sizeof(p->pass_img));
- p->pass_img_num = 0;
+ cleanup_binds(p);
}
static struct mp_pass_perf render_pass_quad(struct gl_video *p,
@@ -1184,14 +1188,13 @@ static struct mp_pass_perf render_pass_quad(struct gl_video *p,
}
static void finish_pass_fbo(struct gl_video *p, struct ra_fbo fbo,
- const struct mp_rect *dst)
+ const struct mp_rect *dst)
{
pass_prepare_src_tex(p);
gl_sc_set_vertex_format(p->sc, vertex_vao, sizeof(struct vertex));
pass_record(p, render_pass_quad(p, fbo, dst));
debug_check_gl(p, "after rendering");
- memset(&p->pass_img, 0, sizeof(p->pass_img));
- p->pass_img_num = 0;
+ cleanup_binds(p);
}
// dst_fbo: this will be used for rendering; possibly reallocating the whole
@@ -1201,8 +1204,11 @@ static void finish_pass_fbo(struct gl_video *p, struct ra_fbo fbo,
static void finish_pass_tex(struct gl_video *p, struct ra_tex **dst_tex,
int w, int h)
{
- if (!ra_tex_resize(p->ra, p->log, dst_tex, w, h, p->fbo_format))
+ if (!ra_tex_resize(p->ra, p->log, dst_tex, w, h, p->fbo_format)) {
+ cleanup_binds(p);
+ gl_sc_reset(p->sc);
return;
+ }
if (p->pass_compute.active) {
gl_sc_uniform_image2D_wo(p->sc, "out_image", *dst_tex);
@@ -3044,12 +3050,13 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame,
if (frame->num_vsyncs > 1 && frame->display_synced &&
!p->dumb_mode && (p->ra->caps & RA_CAP_BLIT))
{
- ra_tex_resize(p->ra, p->log, &p->output_tex,
- fbo.tex->params.w, fbo.tex->params.h,
- p->fbo_format);
-
- dest_fbo = (struct ra_fbo) { p->output_tex };
- p->output_tex_valid = true;
+ bool r = ra_tex_resize(p->ra, p->log, &p->output_tex,
+ fbo.tex->params.w, fbo.tex->params.h,
+ p->fbo_format);
+ if (r) {
+ dest_fbo = (struct ra_fbo) { p->output_tex };
+ p->output_tex_valid = true;
+ }
}
pass_draw_to_screen(p, dest_fbo);
}