summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/opengl/osd.c77
-rw-r--r--video/out/opengl/osd.h3
-rw-r--r--video/out/opengl/ra.h21
-rw-r--r--video/out/opengl/ra_gl.c16
-rw-r--r--video/out/opengl/video.c5
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, &params);
+ 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);