summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-05-23 19:57:29 +0200
committerwm4 <wm4@nowhere>2016-05-23 21:27:18 +0200
commit66079048eaebdb03caea81d610fd1457ceaaa507 (patch)
treedf657c0c3446df45040ba276d68b47674834dad6 /video
parent049e3ccb6551ad37beb091c72a9ef70920cdea80 (diff)
downloadmpv-66079048eaebdb03caea81d610fd1457ceaaa507.tar.bz2
mpv-66079048eaebdb03caea81d610fd1457ceaaa507.tar.xz
vo_opengl: unify PBO and normal OSD texture upload path
The main change is actually that e first copy to a "staging" memory frame, and then upload this at once. The old non-PBO code called glTexsubImage2D for each OSD sub-bitmap. The new non-PBO code path is a bit faster now if there are many small sub-bitmaps (on Linux/nVidia). It's also a bit simpler, so this is a win. (Although I don't particularly appreciate the mixed normal/PBO texture code.)
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/osd.c89
-rw-r--r--video/out/opengl/utils.c25
-rw-r--r--video/out/opengl/utils.h2
3 files changed, 47 insertions, 69 deletions
diff --git a/video/out/opengl/osd.c b/video/out/opengl/osd.c
index d8059166be..e28bafa75e 100644
--- a/video/out/opengl/osd.c
+++ b/video/out/opengl/osd.c
@@ -57,6 +57,7 @@ struct mpgl_osd_part {
struct sub_bitmap *subparts;
struct vertex *vertices;
struct bitmap_packer *packer;
+ void *upload;
};
struct mpgl_osd {
@@ -124,6 +125,7 @@ void mpgl_osd_destroy(struct mpgl_osd *ctx)
gl->DeleteTextures(1, &p->texture);
if (gl->DeleteBuffers)
gl->DeleteBuffers(1, &p->buffer);
+ talloc_free(p->upload);
}
talloc_free(ctx);
}
@@ -133,8 +135,8 @@ void mpgl_osd_set_options(struct mpgl_osd *ctx, bool pbo)
ctx->use_pbo = pbo;
}
-static bool upload_pbo(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
- struct sub_bitmaps *imgs)
+static bool upload(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
+ struct sub_bitmaps *imgs, bool pbo)
{
GL *gl = ctx->gl;
bool success = true;
@@ -142,30 +144,50 @@ static bool upload_pbo(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
size_t pix_stride = gl_bytes_per_pixel(fmt->format, fmt->type);
size_t buffer_size = pix_stride * osd->h * osd->w;
- if (!osd->buffer) {
- gl->GenBuffers(1, &osd->buffer);
+ char *data = NULL;
+ void *texdata = NULL;
+
+ if (pbo) {
+ if (!osd->buffer) {
+ gl->GenBuffers(1, &osd->buffer);
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, osd->buffer);
+ gl->BufferData(GL_PIXEL_UNPACK_BUFFER, buffer_size, NULL,
+ GL_DYNAMIC_COPY);
+ }
+
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, osd->buffer);
- gl->BufferData(GL_PIXEL_UNPACK_BUFFER, buffer_size, NULL, GL_DYNAMIC_COPY);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ data = gl->MapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, buffer_size,
+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
+ if (!data) {
+ success = false;
+ goto done;
+ }
+ } else {
+ if (!osd->upload)
+ osd->upload = talloc_size(NULL, buffer_size);
+ data = osd->upload;
+ texdata = data;
}
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, osd->buffer);
- char *data = gl->MapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, buffer_size,
- GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
- if (!data) {
- success = false;
- } else {
- struct pos bb[2];
- packer_get_bb(osd->packer, bb);
- size_t stride = osd->w * pix_stride;
- packer_copy_subbitmaps(osd->packer, imgs, data, pix_stride, stride);
- if (!gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER))
+ struct pos bb[2];
+ packer_get_bb(osd->packer, bb);
+ size_t stride = osd->w * pix_stride;
+ packer_copy_subbitmaps(osd->packer, imgs, data, pix_stride, stride);
+
+ if (pbo) {
+ if (!gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER)) {
success = false;
- glUploadTex(gl, GL_TEXTURE_2D, fmt->format, fmt->type, NULL, stride,
- bb[0].x, bb[0].y, bb[1].x - bb[0].x, bb[1].y - bb[0].y, 0);
+ goto done;
+ }
}
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ glUploadTex(gl, GL_TEXTURE_2D, fmt->format, fmt->type, texdata, stride,
+ bb[0].x, bb[0].y, bb[1].x - bb[0].x, bb[1].y - bb[0].y, 0);
+
+ if (pbo)
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+done:
if (!success) {
MP_FATAL(ctx, "Error: can't upload subtitles! "
"Remove the 'pbo' suboption.\n");
@@ -174,26 +196,6 @@ static bool upload_pbo(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
return success;
}
-static void upload_tex(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
- struct sub_bitmaps *imgs)
-{
- const struct gl_format *fmt = ctx->fmt_table[imgs->format];
- if (osd->packer->padding) {
- struct pos bb[2];
- packer_get_bb(osd->packer, bb);
- glClearTex(ctx->gl, GL_TEXTURE_2D, fmt->format, fmt->type,
- bb[0].x, bb[0].y, bb[1].x - bb[0].y, bb[1].y - bb[0].y,
- 0, &ctx->scratch);
- }
- for (int n = 0; n < osd->packer->count; n++) {
- struct sub_bitmap *s = &imgs->parts[n];
- struct pos p = osd->packer->result[n];
-
- glUploadTex(ctx->gl, GL_TEXTURE_2D, fmt->format, fmt->type,
- s->bitmap, s->stride, p.x, p.y, s->w, s->h, 0);
- }
-}
-
static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
struct sub_bitmaps *imgs)
{
@@ -234,13 +236,16 @@ static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
if (gl->DeleteBuffers)
gl->DeleteBuffers(1, &osd->buffer);
osd->buffer = 0;
+
+ talloc_free(osd->upload);
+ osd->upload = NULL;
}
bool uploaded = false;
if (ctx->use_pbo)
- uploaded = upload_pbo(ctx, osd, imgs);
+ uploaded = upload(ctx, osd, imgs, true);
if (!uploaded)
- upload_tex(ctx, osd, imgs);
+ upload(ctx, osd, imgs, false);
gl->BindTexture(GL_TEXTURE_2D, 0);
diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c
index f8ed6eebaf..76e119b8f7 100644
--- a/video/out/opengl/utils.c
+++ b/video/out/opengl/utils.c
@@ -103,31 +103,6 @@ void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
-// Like glUploadTex, but upload a byte array with all elements set to val.
-// If scratch is not NULL, points to a resizeable talloc memory block than can
-// be freely used by the function (for avoiding temporary memory allocations).
-void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type,
- int x, int y, int w, int h, uint8_t val, void **scratch)
-{
- int bpp = gl_bytes_per_pixel(format, type);
- int stride = w * bpp;
- int size = h * stride;
- if (size < 1 || !bpp)
- return;
- void *data = scratch ? *scratch : NULL;
- if (talloc_get_size(data) < size)
- data = talloc_realloc(NULL, data, char *, size);
- memset(data, val, size);
- gl->PixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(stride));
- gl->TexSubImage2D(target, 0, x, y, w, h, format, type, data);
- gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4);
- if (scratch) {
- *scratch = data;
- } else {
- talloc_free(data);
- }
-}
-
mp_image_t *glGetWindowScreenshot(GL *gl)
{
if (gl->es)
diff --git a/video/out/opengl/utils.h b/video/out/opengl/utils.h
index 569ec0f23c..ef1cc8bbc0 100644
--- a/video/out/opengl/utils.h
+++ b/video/out/opengl/utils.h
@@ -29,8 +29,6 @@ void glCheckError(GL *gl, struct mp_log *log, const char *info);
void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
const void *dataptr, int stride,
int x, int y, int w, int h, int slice);
-void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type,
- int x, int y, int w, int h, uint8_t val, void **scratch);
mp_image_t *glGetWindowScreenshot(GL *gl);