From 66079048eaebdb03caea81d610fd1457ceaaa507 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 23 May 2016 19:57:29 +0200 Subject: 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.) --- video/out/opengl/osd.c | 89 +++++++++++++++++++++++++----------------------- video/out/opengl/utils.c | 25 -------------- video/out/opengl/utils.h | 2 -- 3 files changed, 47 insertions(+), 69 deletions(-) (limited to 'video') 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); -- cgit v1.2.3