summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-09-02 22:45:07 +0200
committerwm4 <wm4@nowhere>2015-09-02 22:45:07 +0200
commit3f5715a0530f8c44ac00c8756805c47050251ef3 (patch)
tree778eaff0adec740b4e69b07fa8821f52808196c2 /video
parent418af6f0cb3a4716fcbf1edcabb771582283d350 (diff)
downloadmpv-3f5715a0530f8c44ac00c8756805c47050251ef3.tar.bz2
mpv-3f5715a0530f8c44ac00c8756805c47050251ef3.tar.xz
vo_opengl: improve robustness against PBO failure
If PBO upload fails, disable PBOs and revert to the normal codepath. In theory we should retry PBO upload on failure (because OpenGL specifies that it can sporadically fail), but since it normally doesn't happen, and the fallback will work, I'm not bothering. Some restructuring is needed, since glUnmapBuffer needs to be called earlier. In fact, the old code structure didn't make too much sense, and is a leftover from MPlayer's direct rendering support, which let the decoder decode to a PBO-mapped region. This means the buffer_ptr field can be dropped. Drop buffer_size as well, since it only had 2 possible values (0 or the size required for the current config).
Diffstat (limited to 'video')
-rw-r--r--video/out/gl_video.c69
1 files changed, 40 insertions, 29 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 15bedbd9c5..7d27c73eb6 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -102,8 +102,6 @@ struct texplane {
GLenum gl_type;
GLuint gl_texture;
int gl_buffer;
- int buffer_size;
- void *buffer_ptr;
};
struct video_image {
@@ -762,8 +760,6 @@ static void uninit_video(struct gl_video *p)
plane->gl_texture = 0;
gl->DeleteBuffers(1, &plane->gl_buffer);
plane->gl_buffer = 0;
- plane->buffer_ptr = NULL;
- plane->buffer_size = 0;
}
mp_image_unrefp(&vimg->mpi);
@@ -2254,6 +2250,21 @@ void gl_video_resize(struct gl_video *p, int vp_w, int vp_h,
gl_video_reset_surfaces(p);
}
+static bool unmap_image(struct gl_video *p, struct mp_image *mpi)
+{
+ GL *gl = p->gl;
+ bool ok = true;
+ struct video_image *vimg = &p->image;
+ for (int n = 0; n < p->plane_count; n++) {
+ struct texplane *plane = &vimg->planes[n];
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer);
+ ok = gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER) && ok;
+ mpi->planes[n] = NULL; // PBO offset 0
+ }
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ return ok;
+}
+
static bool map_image(struct gl_video *p, struct mp_image *mpi)
{
GL *gl = p->gl;
@@ -2266,20 +2277,20 @@ static bool map_image(struct gl_video *p, struct mp_image *mpi)
for (int n = 0; n < p->plane_count; n++) {
struct texplane *plane = &vimg->planes[n];
mpi->stride[n] = mp_image_plane_w(mpi, n) * p->image_desc.bytes[n];
- int needed_size = mp_image_plane_h(mpi, n) * mpi->stride[n];
- if (!plane->gl_buffer)
+ if (!plane->gl_buffer) {
gl->GenBuffers(1, &plane->gl_buffer);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer);
- if (needed_size > plane->buffer_size) {
- plane->buffer_size = needed_size;
- gl->BufferData(GL_PIXEL_UNPACK_BUFFER, plane->buffer_size,
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer);
+ size_t buffer_size = mp_image_plane_h(mpi, n) * mpi->stride[n];
+ gl->BufferData(GL_PIXEL_UNPACK_BUFFER, buffer_size,
NULL, GL_DYNAMIC_DRAW);
}
- if (!plane->buffer_ptr)
- plane->buffer_ptr = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER,
- GL_WRITE_ONLY);
- mpi->planes[n] = plane->buffer_ptr;
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer);
+ mpi->planes[n] = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ if (!mpi->planes[n]) {
+ unmap_image(p, mpi);
+ return false;
+ }
}
memset(mpi->bufs, 0, sizeof(mpi->bufs));
return true;
@@ -2309,28 +2320,28 @@ static void gl_video_upload_image(struct gl_video *p, struct mp_image *mpi)
assert(mpi->num_planes == p->plane_count);
- mp_image_t mpi2 = *mpi;
- bool pbo = false;
- if (!vimg->planes[0].buffer_ptr && map_image(p, &mpi2)) {
- mp_image_copy(&mpi2, mpi);
- pbo = true;
+ mp_image_t pbo_mpi = *mpi;
+ bool pbo = map_image(p, &pbo_mpi);
+ if (pbo) {
+ mp_image_copy(&pbo_mpi, mpi);
+ if (unmap_image(p, &pbo_mpi)) {
+ mpi = &pbo_mpi;
+ } else {
+ MP_FATAL(p, "Video PBO upload failed. Disabling PBOs.\n");
+ pbo = false;
+ p->opts.pbo = 0;
+ }
}
- vimg->image_flipped = mpi2.stride[0] < 0;
+
+ vimg->image_flipped = mpi->stride[0] < 0;
for (int n = 0; n < p->plane_count; n++) {
struct texplane *plane = &vimg->planes[n];
- void *plane_ptr = mpi2.planes[n];
- if (pbo) {
+ if (pbo)
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer);
- if (!gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER))
- MP_FATAL(p, "Video PBO upload failed. "
- "Remove the 'pbo' suboption.\n");
- plane->buffer_ptr = NULL;
- plane_ptr = NULL; // PBO offset 0
- }
gl->ActiveTexture(GL_TEXTURE0 + n);
gl->BindTexture(p->gl_target, plane->gl_texture);
glUploadTex(gl, p->gl_target, plane->gl_format, plane->gl_type,
- plane_ptr, mpi2.stride[n], 0, 0, plane->w, plane->h, 0);
+ mpi->planes[n], mpi->stride[n], 0, 0, plane->w, plane->h, 0);
}
gl->ActiveTexture(GL_TEXTURE0);
if (pbo)