summaryrefslogtreecommitdiffstats
path: root/video/out/vo_x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/vo_x11.c')
-rw-r--r--video/out/vo_x11.c134
1 files changed, 126 insertions, 8 deletions
diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c
index 72ae992eac..9b13ae2893 100644
--- a/video/out/vo_x11.c
+++ b/video/out/vo_x11.c
@@ -88,6 +88,7 @@ struct priv {
int dst_width;
XVisualInfo vinfo;
+ int ximage_depth;
int firstTime;
@@ -123,6 +124,56 @@ static void check_events(struct vo *vo)
flip_page(vo);
}
+/* Scan the available visuals on this Display/Screen. Try to find
+ * the 'best' available TrueColor visual that has a decent color
+ * depth (at least 15bit). If there are multiple visuals with depth
+ * >= 15bit, we prefer visuals with a smaller color depth. */
+static int find_depth_from_visuals(Display * dpy, int screen,
+ Visual ** visual_return)
+{
+ XVisualInfo visual_tmpl;
+ XVisualInfo *visuals;
+ int nvisuals, i;
+ int bestvisual = -1;
+ int bestvisual_depth = -1;
+
+ visual_tmpl.screen = screen;
+ visual_tmpl.class = TrueColor;
+ visuals = XGetVisualInfo(dpy,
+ VisualScreenMask | VisualClassMask,
+ &visual_tmpl, &nvisuals);
+ if (visuals != NULL)
+ {
+ for (i = 0; i < nvisuals; i++)
+ {
+ mp_msg(MSGT_VO, MSGL_V,
+ "vo: X11 truecolor visual %#lx, depth %d, R:%lX G:%lX B:%lX\n",
+ visuals[i].visualid, visuals[i].depth,
+ visuals[i].red_mask, visuals[i].green_mask,
+ visuals[i].blue_mask);
+ /*
+ * Save the visual index and its depth, if this is the first
+ * truecolor visul, or a visual that is 'preferred' over the
+ * previous 'best' visual.
+ */
+ if (bestvisual_depth == -1
+ || (visuals[i].depth >= 15
+ && (visuals[i].depth < bestvisual_depth
+ || bestvisual_depth < 15)))
+ {
+ bestvisual = i;
+ bestvisual_depth = visuals[i].depth;
+ }
+ }
+
+ if (bestvisual != -1 && visual_return != NULL)
+ *visual_return = visuals[bestvisual].visual;
+
+ XFree(visuals);
+ }
+ return bestvisual_depth;
+}
+
static void getMyXImage(struct priv *p, int foo)
{
struct vo *vo = p->vo;
@@ -298,8 +349,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
if (p->depth != 15 && p->depth != 16 && p->depth != 24 && p->depth != 32) {
Visual *visual;
- p->depth = vo_find_depth_from_visuals(vo->x11->display, vo->x11->screen,
- &visual);
+ p->depth = find_depth_from_visuals(vo->x11->display, vo->x11->screen,
+ &visual);
}
if (!XMatchVisualInfo(vo->x11->display, vo->x11->screen, p->depth,
DirectColor, &p->vinfo)
@@ -327,8 +378,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
vo_x11_create_vo_window(vo, &p->vinfo, vo->dx, vo->dy, vo->dwidth,
vo->dheight, flags, theCmap, "x11");
- if (WinID > 0)
- p->depth = vo_x11_update_geometry(vo, true);
#ifdef CONFIG_XF86VM
if (vm) {
@@ -343,6 +392,15 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
#endif
}
+ if (WinID > 0) {
+ unsigned depth, dummy_uint;
+ int dummy_int;
+ Window dummy_win;
+ XGetGeometry(vo->x11->display, vo->x11->window, &dummy_win, &dummy_int,
+ &dummy_int, &dummy_uint, &dummy_uint, &dummy_uint, &depth);
+ p->depth = depth;
+ }
+
int i;
for (i = 0; i < p->total_buffers; i++)
freeMyXImage(p, i);
@@ -570,13 +628,14 @@ static int redraw_frame(struct vo *vo)
static int query_format(struct vo *vo, uint32_t format)
{
+ struct priv *p = vo->priv;
mp_msg(MSGT_VO, MSGL_DBG2,
"vo_x11: query_format was called: %x (%s)\n", format,
vo_format_name(format));
if (IMGFMT_IS_RGB(format)) {
for (int n = 0; fmt2Xfmt[n].mpfmt; n++) {
if (fmt2Xfmt[n].mpfmt == format) {
- if (IMGFMT_RGB_DEPTH(format) == vo->x11->depthonscreen) {
+ if (IMGFMT_RGB_DEPTH(format) == p->ximage_depth) {
return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
VFCAP_OSD | VFCAP_FLIP;
} else {
@@ -593,6 +652,64 @@ static int query_format(struct vo *vo, uint32_t format)
return 0;
}
+static void find_x11_depth(struct vo *vo)
+{
+ struct vo_x11_state *x11 = vo->x11;
+ struct priv *p = vo->priv;
+ XImage *mXImage = NULL;
+ int depth, bpp, ximage_depth;
+ unsigned int mask;
+ XWindowAttributes attribs;
+
+ // get color depth (from root window, or the best visual):
+ XGetWindowAttributes(x11->display, x11->rootwin, &attribs);
+ depth = attribs.depth;
+
+ if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
+ {
+ Visual *visual;
+
+ depth = find_depth_from_visuals(x11->display, x11->screen, &visual);
+ if (depth != -1)
+ mXImage = XCreateImage(x11->display, visual, depth, ZPixmap,
+ 0, NULL, 1, 1, 8, 1);
+ } else
+ mXImage =
+ XGetImage(x11->display, x11->rootwin, 0, 0, 1, 1, AllPlanes, ZPixmap);
+
+ ximage_depth = depth; // display depth on screen
+
+ // get bits/pixel from XImage structure:
+ if (mXImage == NULL)
+ {
+ mask = 0;
+ } else
+ {
+ /* for the depth==24 case, the XImage structures might use
+ * 24 or 32 bits of data per pixel. */
+ bpp = mXImage->bits_per_pixel;
+ if ((ximage_depth + 7) / 8 != (bpp + 7) / 8)
+ ximage_depth = bpp; // by A'rpi
+ mask =
+ mXImage->red_mask | mXImage->green_mask | mXImage->blue_mask;
+ mp_msg(MSGT_VO, MSGL_V,
+ "vo: X11 color mask: %X (R:%lX G:%lX B:%lX)\n", mask,
+ mXImage->red_mask, mXImage->green_mask, mXImage->blue_mask);
+ XDestroyImage(mXImage);
+ }
+ if (((ximage_depth + 7) / 8) == 2)
+ {
+ if (mask == 0x7FFF)
+ ximage_depth = 15;
+ else if (mask == 0xFFFF)
+ ximage_depth = 16;
+ }
+
+ mp_msg(MSGT_VO, MSGL_V, "vo: X11 depth %d and %d bpp.\n", depth,
+ ximage_depth);
+
+ p->ximage_depth = ximage_depth;
+}
static void uninit(struct vo *vo)
{
@@ -624,8 +741,9 @@ static int preinit(struct vo *vo, const char *arg)
return ENOSYS;
}
- if (!vo_init(vo))
+ if (!vo_x11_init(vo))
return -1; // Can't open X11
+ find_x11_depth(vo);
return 0;
}
@@ -649,13 +767,13 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_GET_EQUALIZER:
{
struct voctrl_get_equalizer_args *args = data;
- return vo_x11_get_equalizer(args->name, args->valueptr);
+ return vo_x11_get_equalizer(vo, args->name, args->valueptr);
}
case VOCTRL_ONTOP:
vo_x11_ontop(vo);
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
- update_xinerama_info(vo);
+ vo_x11_update_screeninfo(vo);
return VO_TRUE;
case VOCTRL_REDRAW_FRAME:
return redraw_frame(vo);