diff options
Diffstat (limited to 'video/out/opengl')
-rw-r--r-- | video/out/opengl/osd.c | 77 | ||||
-rw-r--r-- | video/out/opengl/osd.h | 3 | ||||
-rw-r--r-- | video/out/opengl/ra.h | 21 | ||||
-rw-r--r-- | video/out/opengl/ra_gl.c | 16 | ||||
-rw-r--r-- | video/out/opengl/video.c | 5 |
5 files changed, 78 insertions, 44 deletions
diff --git a/video/out/opengl/osd.c b/video/out/opengl/osd.c index aa0791139d..8b178f212d 100644 --- a/video/out/opengl/osd.c +++ b/video/out/opengl/osd.c @@ -22,6 +22,7 @@ #include <libavutil/common.h> #include "formats.h" +#include "ra_gl.h" #include "osd.h" #define GLSL(x) gl_sc_add(sc, #x "\n"); @@ -50,7 +51,7 @@ static const struct gl_vao_entry vertex_vao[] = { struct mpgl_osd_part { enum sub_bitmap_format format; int change_id; - GLuint texture; + struct ra_tex *texture; int w, h; struct gl_pbo_upload pbo; int num_subparts; @@ -63,10 +64,11 @@ struct mpgl_osd_part { struct mpgl_osd { struct mp_log *log; struct osd_state *osd; + struct ra *ra; GL *gl; bool use_pbo; struct mpgl_osd_part *parts[MAX_OSD_PARTS]; - const struct gl_format *fmt_table[SUBBITMAP_COUNT]; + const struct ra_format *fmt_table[SUBBITMAP_COUNT]; bool formats[SUBBITMAP_COUNT]; int64_t change_counter; // temporary @@ -75,18 +77,22 @@ struct mpgl_osd { void *scratch; }; -struct mpgl_osd *mpgl_osd_init(GL *gl, struct mp_log *log, struct osd_state *osd) +struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log, + struct osd_state *osd) { + struct ra_gl *ra_gl = ra->priv; + struct mpgl_osd *ctx = talloc_ptrtype(NULL, ctx); *ctx = (struct mpgl_osd) { .log = log, .osd = osd, - .gl = gl, + .ra = ra, + .gl = ra_gl->gl, .scratch = talloc_zero_size(ctx, 1), }; - ctx->fmt_table[SUBBITMAP_LIBASS] = gl_find_unorm_format(gl, 1, 1); - ctx->fmt_table[SUBBITMAP_RGBA] = gl_find_unorm_format(gl, 1, 4); + ctx->fmt_table[SUBBITMAP_LIBASS] = ra_find_unorm_format(ra, 1, 1); + ctx->fmt_table[SUBBITMAP_RGBA] = ra_find_unorm_format(ra, 1, 4); for (int n = 0; n < MAX_OSD_PARTS; n++) ctx->parts[n] = talloc_zero(ctx, struct mpgl_osd_part); @@ -102,12 +108,9 @@ void mpgl_osd_destroy(struct mpgl_osd *ctx) if (!ctx) return; - GL *gl = ctx->gl; - for (int n = 0; n < MAX_OSD_PARTS; n++) { struct mpgl_osd_part *p = ctx->parts[n]; - gl->DeleteTextures(1, &p->texture); - gl_pbo_upload_uninit(&p->pbo); + ra_tex_free(ctx->ra, &p->texture); } talloc_free(ctx); } @@ -129,7 +132,7 @@ static int next_pow2(int v) static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd, struct sub_bitmaps *imgs) { - GL *gl = ctx->gl; + struct ra *ra = ctx->ra; bool ok = false; assert(imgs->packed); @@ -137,47 +140,51 @@ static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd, int req_w = next_pow2(imgs->packed_w); int req_h = next_pow2(imgs->packed_h); - const struct gl_format *fmt = ctx->fmt_table[imgs->format]; + const struct ra_format *fmt = ctx->fmt_table[imgs->format]; assert(fmt); - if (!osd->texture) - gl->GenTextures(1, &osd->texture); - - gl->BindTexture(GL_TEXTURE_2D, osd->texture); + if (!osd->texture || req_w > osd->w || req_h > osd->h || + osd->format != imgs->format) + { + ra_tex_free(ra, &osd->texture); - if (req_w > osd->w || req_h > osd->h || osd->format != imgs->format) { osd->format = imgs->format; osd->w = FFMAX(32, req_w); osd->h = FFMAX(32, req_h); MP_VERBOSE(ctx, "Reallocating OSD texture to %dx%d.\n", osd->w, osd->h); - GLint max_wh; - gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_wh); - - if (osd->w > max_wh || osd->h > max_wh) { + if (osd->w > ra->max_texture_wh || osd->h > ra->max_texture_wh) { MP_ERR(ctx, "OSD bitmaps do not fit on a surface with the maximum " - "supported size %dx%d.\n", max_wh, max_wh); + "supported size %dx%d.\n", ra->max_texture_wh, + ra->max_texture_wh); goto done; } - gl->TexImage2D(GL_TEXTURE_2D, 0, fmt->internal_format, osd->w, osd->h, - 0, fmt->format, fmt->type, NULL); - - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + struct ra_tex_params params = { + .dimensions = 2, + .w = osd->w, + .h = osd->h, + .d = 1, + .format = fmt, + .render_src = true, + .src_linear = true, + }; + osd->texture = ra_tex_create(ra, ¶ms); + if (!osd->texture) + goto done; } - gl_pbo_upload_tex(&osd->pbo, gl, ctx->use_pbo, GL_TEXTURE_2D, fmt->format, - fmt->type, osd->w, osd->h, imgs->packed->planes[0], - imgs->packed->stride[0], 0, 0, - imgs->packed_w, imgs->packed_h); + osd->texture->use_pbo = ctx->use_pbo; + + struct mp_rect rc = {0, 0, imgs->packed_w, imgs->packed_h}; + ra->fns->tex_upload(ra, osd->texture, imgs->packed->planes[0], + imgs->packed->stride[0], &rc, RA_TEX_UPLOAD_DISCARD, + NULL); + ok = true; done: - gl->BindTexture(GL_TEXTURE_2D, 0); return ok; } @@ -215,7 +222,7 @@ bool mpgl_osd_draw_prepare(struct mpgl_osd *ctx, int index, if (!fmt || !part->num_subparts) return false; - gl_sc_uniform_tex(sc, "osdtex", GL_TEXTURE_2D, part->texture); + gl_sc_uniform_texture(sc, "osdtex", part->texture); switch (fmt) { case SUBBITMAP_RGBA: { GLSL(color = texture(osdtex, texcoord).bgra;) diff --git a/video/out/opengl/osd.h b/video/out/opengl/osd.h index 36926f95f0..89d52f313e 100644 --- a/video/out/opengl/osd.h +++ b/video/out/opengl/osd.h @@ -9,7 +9,8 @@ #include "shader_cache.h" #include "sub/osd.h" -struct mpgl_osd *mpgl_osd_init(GL *gl, struct mp_log *log, struct osd_state *osd); +struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log, + struct osd_state *osd); void mpgl_osd_destroy(struct mpgl_osd *ctx); void mpgl_osd_set_options(struct mpgl_osd *ctx, bool pbo); diff --git a/video/out/opengl/ra.h b/video/out/opengl/ra.h index 21d9cf15d7..3249bc7448 100644 --- a/video/out/opengl/ra.h +++ b/video/out/opengl/ra.h @@ -13,6 +13,10 @@ struct ra { // time. uint64_t caps; + // Maximum supported width and height of a 2D texture. Set by the RA backend + // at init time. + int max_texture_wh; + // Set of supported texture formats. Must be added by RA backend at init time. struct ra_format **formats; int num_formats; @@ -101,6 +105,11 @@ struct ra_mapped_buffer { size_t size; // total size of the mapping, starting at data }; +enum { + // Flags for the texture_upload flags parameter. + RA_TEX_UPLOAD_DISCARD = 1 << 0, // discard pre-existing data not in the region +}; + // Rendering API entrypoints. (Note: there are some additional hidden features // you need to take care of. For example, hwdec mapping will be provided // separately from ra, but might need to call into ra private code.) @@ -120,10 +129,15 @@ struct ra_fns { // This is an extremely common operation. // Unlike with OpenGL, the src data has to have exactly the same format as // the texture, and no conversion is supported. - // tex->params.require_upload must be true. - // For 1D textures, stride is ignored. + // region can be NULL - if it's not NULL, then the provided pointer only + // contains data for the given region. Only part of the texture data is + // updated, and ptr points to the first pixel in the region. If + // RA_TEX_UPLOAD_DISCARD is set, data outside of the region can return to + // an uninitialized state. The region is always strictly within the texture + // and has a size >0 in both dimensions. 2D textures only. + // For 1D textures, stride is ignored, and region must be NULL. // For 3D textures, stride is not supported. All data is fully packed with - // no padding, and stride is ignored. + // no padding, and stride is ignored, and region must be NULL. // If buf is not NULL, then src must be within the provided buffer. The // operation is implied to have dramatically better performance, but // requires correct flushing and fencing operations by the caller to deal @@ -131,6 +145,7 @@ struct ra_fns { // met, undefined behavior will result. void (*tex_upload)(struct ra *ra, struct ra_tex *tex, const void *src, ptrdiff_t stride, + struct mp_rect *region, uint64_t flags, struct ra_mapped_buffer *buf); // Create a persistently mapped buffer for tex_upload. diff --git a/video/out/opengl/ra_gl.c b/video/out/opengl/ra_gl.c index 62d16cbdbc..411adddec6 100644 --- a/video/out/opengl/ra_gl.c +++ b/video/out/opengl/ra_gl.c @@ -88,6 +88,10 @@ int ra_init_gl(struct ra *ra, GL *gl) MP_TARRAY_APPEND(ra, ra->formats, ra->num_formats, fmt); } + GLint max_wh; + gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_wh); + ra->max_texture_wh = max_wh; + gl->Disable(GL_DITHER); return 0; @@ -307,13 +311,15 @@ struct ra_tex *ra_create_wrapped_fb(struct ra *ra, GLuint gl_fbo, int w, int h) } static void gl_tex_upload(struct ra *ra, struct ra_tex *tex, - const void *src, ptrdiff_t stride, - struct ra_mapped_buffer *buf) + const void *src, ptrdiff_t stride, + struct mp_rect *rc, uint64_t flags, + struct ra_mapped_buffer *buf) { struct ra_gl *p = ra->priv; GL *gl = p->gl; struct ra_tex_gl *tex_gl = tex->priv; struct ra_mapped_buffer_gl *buf_gl = NULL; + struct mp_rect full = {0, 0, tex->params.w, tex->params.h}; if (buf) { buf_gl = buf->priv; @@ -325,16 +331,20 @@ static void gl_tex_upload(struct ra *ra, struct ra_tex *tex, switch (tex->params.dimensions) { case 1: + assert(!rc); gl->TexImage1D(tex_gl->target, 0, tex_gl->internal_format, tex->params.w, 0, tex_gl->format, tex_gl->type, src); break; case 2: + if (!rc) + rc = &full; gl_pbo_upload_tex(&tex_gl->pbo, gl, tex->use_pbo && !buf, tex_gl->target, tex_gl->format, tex_gl->type, tex->params.w, tex->params.h, src, stride, - 0, 0, tex->params.w, tex->params.h); + rc->x0, rc->y0, rc->x1 - rc->x0, rc->y1 - rc->y0); break; case 3: + assert(!rc); gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1); gl->TexImage3D(GL_TEXTURE_3D, 0, tex_gl->internal_format, tex->params.w, tex->params.h, tex->params.d, 0, tex_gl->format, diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 1274cc6e3c..3442e9fb59 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -506,7 +506,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->gl, p->log, p->osd_state); + p->osd = mpgl_osd_init(p->ra, p->log, p->osd_state); mpgl_osd_set_options(p->osd, p->opts.pbo); } } @@ -3326,7 +3326,8 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t struct dr_buffer *mapped = gl_find_dr_buffer(p, mpi->planes[n]); p->ra->fns->tex_upload(p->ra, plane->tex, mpi->planes[n], - mpi->stride[n], mapped ? mapped->buffer : NULL); + mpi->stride[n], NULL, 0, + mapped ? mapped->buffer : NULL); if (mapped && !mapped->mpi) mapped->mpi = mp_image_new_ref(mpi); |