summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-05-22 14:24:16 +0200
committerwm4 <wm4@nowhere>2020-05-22 14:24:16 +0200
commitd62131d3aeda6f3b4c255ca06e70573433a8f16a (patch)
tree8a902caabc1887810172611b67360ece06d505b4
parent77f730f63c340fc88e8c3db0cb73cff1807d7432 (diff)
downloadmpv-d62131d3aeda6f3b4c255ca06e70573433a8f16a.tar.bz2
mpv-d62131d3aeda6f3b4c255ca06e70573433a8f16a.tar.xz
vo_x11: allow OSD rendering outside of video region
I'm not sure why it only rendered OSD inside the video. Since OSD rendering was always done on the X image (after software scaling and color conversion), there was no technical reason for this. Maybe it was because the code started out this way, and it was annoying to change it. Possibly, one reason was that it didn't normally have to clear the black bars in every frame (if video didn't cover the entire window). Anyway, simply render OSD to the full window. This gets rid of some rather weird stuff. It seems to look mostly like vo_wlshm now. The uncovered regions are cleared every frame, which could probably be avoided by being clever with the OSD renderer code, but this is where I'm decidedly losing interest. There was some mysterious code for aligning the image width to 8 pixels. Replace that by attempting to align it to SIMD alignment (might matter for libswscale, or if repack.c gets SIMD). Why are there apparently 4 different ways representing a pixel format (depth, VisualID, Visual, XVisualInfo), but none of them seem to provide the XImage.bits_per_pixel value (the actual size of a pixel, including padding)? Even after 33 years, X11 still seems overengineered, confusing, and inconvenient. So just call X11 a heap of shit, and assume the worst case for alignment.
-rw-r--r--video/out/vo_x11.c117
1 files changed, 52 insertions, 65 deletions
diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c
index 1cd8bdbe96..bda0f5c100 100644
--- a/video/out/vo_x11.c
+++ b/video/out/vo_x11.c
@@ -57,6 +57,7 @@ struct priv {
struct mp_image *original_image;
XImage *myximage[2];
+ struct mp_image mp_ximages[2];
int depth;
GC gc;
@@ -65,8 +66,6 @@ struct priv {
struct mp_rect src;
struct mp_rect dst;
- int src_w, src_h;
- int dst_w, dst_h;
struct mp_osd_res osd;
struct mp_sws_context *sws;
@@ -74,7 +73,6 @@ struct priv {
XVisualInfo vinfo;
int current_buf;
- bool reset_view;
int Shmem_Flag;
XShmSegmentInfo Shminfo[2];
@@ -167,8 +165,6 @@ static int reconfig(struct vo *vo, struct mp_image_params *fmt)
mp_image_unrefp(&p->original_image);
- p->sws->src = *fmt;
-
vo_x11_config_vo_window(vo);
if (!resize(vo))
@@ -181,34 +177,25 @@ static bool resize(struct vo *vo)
{
struct priv *p = vo->priv;
- for (int i = 0; i < 2; i++)
- freeMyXImage(p, i);
-
- vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd);
-
- p->src_w = p->src.x1 - p->src.x0;
- p->src_h = p->src.y1 - p->src.y0;
- p->dst_w = p->dst.x1 - p->dst.x0;
- p->dst_h = p->dst.y1 - p->dst.y0;
+ // Attempt to align. We don't know the size in bytes yet (????), so just
+ // assume worst case (1 byte per pixel).
+ int nw = MPMAX(1, MP_ALIGN_UP(vo->dwidth, MP_IMAGE_BYTE_ALIGN));
+ int nh = MPMAX(1, vo->dheight);
- // p->osd contains the parameters assuming OSD rendering in window
- // coordinates, but OSD can only be rendered in the intersection
- // between window and video rectangle (i.e. not into panscan borders).
- p->osd.w = p->dst_w;
- p->osd.h = p->dst_h;
- p->osd.mt = MPMIN(0, p->osd.mt);
- p->osd.mb = MPMIN(0, p->osd.mb);
- p->osd.mr = MPMIN(0, p->osd.mr);
- p->osd.ml = MPMIN(0, p->osd.ml);
+ if (nw > p->image_width || nh > p->image_height) {
+ for (int i = 0; i < 2; i++)
+ freeMyXImage(p, i);
- mp_input_set_mouse_transform(vo->input_ctx, &p->dst, NULL);
+ p->image_width = nw;
+ p->image_height = nh;
- p->image_width = (p->dst_w + 7) & (~7);
- p->image_height = p->dst_h;
-
- for (int i = 0; i < 2; i++) {
- if (!getMyXImage(p, i))
- return false;
+ for (int i = 0; i < 2; i++) {
+ if (!getMyXImage(p, i)) {
+ p->image_width = 0;
+ p->image_height = 0;
+ return false;
+ }
+ }
}
int mpfmt = 0;
@@ -236,19 +223,32 @@ static bool resize(struct vo *vo)
}
MP_VERBOSE(vo, "Using mp format: %s\n", mp_imgfmt_to_name(mpfmt));
- p->sws->dst = (struct mp_image_params) {
- .imgfmt = mpfmt,
- .w = p->dst_w,
- .h = p->dst_h,
- .p_w = 1,
- .p_h = 1,
- };
- mp_image_params_guess_csp(&p->sws->dst);
+ for (int i = 0; i < 2; i++) {
+ struct mp_image *img = &p->mp_ximages[i];
+ *img = (struct mp_image){0};
+ mp_image_setfmt(img, mpfmt);
+ mp_image_set_size(img, p->image_width, p->image_height);
+ img->planes[0] = p->myximage[i]->data;
+ img->stride[0] = p->myximage[i]->bytes_per_line;
+
+ mp_image_params_guess_csp(&img->params);
+ }
- if (mp_sws_reinit(p->sws) < 0)
- return false;
+ vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd);
+
+ if (vo->params) {
+ p->sws->src = *vo->params;
+ p->sws->src.w = mp_rect_w(p->src);
+ p->sws->src.h = mp_rect_h(p->src);
+
+ p->sws->dst = p->mp_ximages[0].params;
+ p->sws->dst.w = mp_rect_w(p->dst);
+ p->sws->dst.h = mp_rect_h(p->dst);
+
+ if (mp_sws_reinit(p->sws) < 0)
+ return false;
+ }
- p->reset_view = true;
vo->want_redraw = true;
return true;
}
@@ -259,34 +259,16 @@ static void Display_Image(struct priv *p, XImage *myximage)
XImage *x_image = p->myximage[p->current_buf];
- if (p->reset_view) {
- XFillRectangle(vo->x11->display, vo->x11->window, p->gc, 0, 0, vo->dwidth, vo->dheight);
- p->reset_view = false;
- }
-
if (p->Shmem_Flag) {
XShmPutImage(vo->x11->display, vo->x11->window, p->gc, x_image,
- 0, 0, p->dst.x0, p->dst.y0, p->dst_w, p->dst_h,
- True);
+ 0, 0, 0, 0, vo->dwidth, vo->dheight, True);
vo->x11->ShmCompletionWaitCount++;
} else {
XPutImage(vo->x11->display, vo->x11->window, p->gc, x_image,
- 0, 0, p->dst.x0, p->dst.y0, p->dst_w, p->dst_h);
+ 0, 0, 0, 0, vo->dwidth, vo->dheight);
}
}
-static struct mp_image get_x_buffer(struct priv *p, int buf_index)
-{
- struct mp_image img = {0};
- mp_image_set_params(&img, &p->sws->dst);
-
- img.planes[0] = p->myximage[buf_index]->data;
- img.stride[0] =
- p->image_width * ((p->myximage[buf_index]->bits_per_pixel + 7) / 8);
-
- return img;
-}
-
static void wait_for_completion(struct vo *vo, int max_outstanding)
{
struct priv *ctx = vo->priv;
@@ -318,21 +300,26 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
wait_for_completion(vo, 1);
- struct mp_image img = get_x_buffer(p, p->current_buf);
+ struct mp_image *img = &p->mp_ximages[p->current_buf];
if (mpi) {
+ mp_image_clear_rc_inv(img, p->dst);
+
struct mp_image src = *mpi;
struct mp_rect src_rc = p->src;
src_rc.x0 = MP_ALIGN_DOWN(src_rc.x0, src.fmt.align_x);
src_rc.y0 = MP_ALIGN_DOWN(src_rc.y0, src.fmt.align_y);
mp_image_crop_rc(&src, src_rc);
- mp_sws_scale(p->sws, &img, &src);
+ struct mp_image dst = *img;
+ mp_image_crop_rc(&dst, p->dst);
+
+ mp_sws_scale(p->sws, &dst, &src);
} else {
- mp_image_clear(&img, 0, 0, img.w, img.h);
+ mp_image_clear(img, 0, 0, img->w, img->h);
}
- osd_draw_on_image(vo->osd, p->osd, mpi ? mpi->pts : 0, 0, &img);
+ osd_draw_on_image(vo->osd, p->osd, mpi ? mpi->pts : 0, 0, img);
if (mpi != p->original_image) {
talloc_free(p->original_image);