From 77071fadd799a7cba13b18c31273ed3c217f82f5 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Fri, 25 Jan 2013 01:01:45 +0200 Subject: [PATCH] VO: fix X display depth handling (makes depth 30 work) vo_vdpau and vo_xv had code that selected output window depth by checking X root window depth, using that value if it was one of the values 15, 16, 24, 32, and otherwise using 24. This broke displays set in 30-bit mode (at least NVIDIA supports such 10 bits per component mode), as it tried to use 24 which is not supported in that mode. Simply remove the list of allowed modes and use whatever the root window depth is. The list of allowed modes was originally added for displays that used 8 bits for the root window but allowed creating higher-depth windows (such displays should not be relevant any more). That it listed specific modes instead of a simple greater-than comparison is likely because it was written for vo_x11 which cares about the exact format. Probably this code was then blindly copied to other VOs. The same questionable logic was also used in the shared X11 vo_init() function, but there the result depth wasn't used for anything except printing verbose-level output and setting the "depthonscreen" variable that is only used in vo_x11. Move this logic from x11_common.c to vo_x11.c. --- libvo/vo_vdpau.c | 7 +--- libvo/vo_x11.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++ libvo/vo_xv.c | 7 +--- libvo/x11_common.c | 114 ++--------------------------------------------------- libvo/x11_common.h | 3 -- 5 files changed, 108 insertions(+), 124 deletions(-) diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index 0c99f5dfb2..6102714408 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -870,7 +870,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, XSetWindowAttributes xswa; XWindowAttributes attribs; unsigned long xswamask; - int depth; #ifdef CONFIG_XF86VM int vm = flags & VOFLAG_MODESWITCHING; @@ -898,10 +897,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, #endif XGetWindowAttributes(x11->display, DefaultRootWindow(x11->display), &attribs); - depth = attribs.depth; - if (depth != 15 && depth != 16 && depth != 24 && depth != 32) - depth = 24; - XMatchVisualInfo(x11->display, x11->screen, depth, TrueColor, &vinfo); + XMatchVisualInfo(x11->display, x11->screen, attribs.depth, TrueColor, + &vinfo); xswa.background_pixel = 0; xswa.border_pixel = 0; diff --git a/libvo/vo_x11.c b/libvo/vo_x11.c index 03f73debe0..4a641fbdae 100644 --- a/libvo/vo_x11.c +++ b/libvo/vo_x11.c @@ -77,6 +77,7 @@ static unsigned char *ImageDataOrig; static XImage *myximage = NULL; static int depth, bpp; static XWindowAttributes attribs; +int vo_depthonscreen; static int int_pause; @@ -152,6 +153,58 @@ extern int sws_flags; static XVisualInfo vinfo; +/* + * 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 vo_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(void) { #ifdef HAVE_SHM @@ -634,6 +687,54 @@ static int preinit(const char *arg) if (!vo_init()) return -1; // Can't open X11 + + XWindowAttributes attribs; + XGetWindowAttributes(mDisplay, mRootWin, &attribs); + depth = attribs.depth; + XImage *mXImage = NULL; + if (depth != 15 && depth != 16 && depth != 24 && depth != 32) { + Visual *visual; + + depth = vo_find_depth_from_visuals(mDisplay, mScreen, &visual); + if (depth != -1) + mXImage = XCreateImage(mDisplay, visual, depth, ZPixmap, + 0, NULL, 1, 1, 8, 1); + } else + mXImage = + XGetImage(mDisplay, mRootWin, 0, 0, 1, 1, AllPlanes, ZPixmap); + + vo_depthonscreen = depth; // display depth on screen + + // get bits/pixel from XImage structure: + unsigned int mask; + if (mXImage == NULL) { + mask = 0; + } else { + /* + * for the depth==24 case, the XImage structures might use + * 24 or 32 bits of data per pixel. The vo_depthonscreen + * field stores the amount of data per pixel in the + * XImage structure! + * + * Maybe we should rename vo_depthonscreen to (or add) vo_bpp? + */ + bpp = mXImage->bits_per_pixel; + if ((vo_depthonscreen + 7) / 8 != (bpp + 7) / 8) + vo_depthonscreen = 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 (((vo_depthonscreen + 7) / 8) == 2) + { + if (mask == 0x7FFF) + vo_depthonscreen = 15; + else if (mask == 0xFFFF) + vo_depthonscreen = 16; + } return 0; } diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c index e737754726..2300cc6fb5 100644 --- a/libvo/vo_xv.c +++ b/libvo/vo_xv.c @@ -186,7 +186,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, XSetWindowAttributes xswa; XWindowAttributes attribs; unsigned long xswamask; - int depth; struct xvctx *ctx = vo->priv; int i; @@ -230,10 +229,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, #endif XGetWindowAttributes(x11->display, DefaultRootWindow(x11->display), &attribs); - depth = attribs.depth; - if (depth != 15 && depth != 16 && depth != 24 && depth != 32) - depth = 24; - XMatchVisualInfo(x11->display, x11->screen, depth, TrueColor, &vinfo); + XMatchVisualInfo(x11->display, x11->screen, attribs.depth, TrueColor, + &vinfo); xswa.border_pixel = 0; xswamask = CWBorderPixel; diff --git a/libvo/x11_common.c b/libvo/x11_common.c index b41e30e07b..7caa5c6a90 100644 --- a/libvo/x11_common.c +++ b/libvo/x11_common.c @@ -381,16 +381,7 @@ void update_xinerama_info(struct vo *vo) { int vo_init(struct vo *vo) { struct MPOpts *opts = vo->opts; -// int mScreen; - int depth, bpp; - unsigned int mask; -// char * DisplayName = ":0.0"; -// Display * mDisplay; - XImage *mXImage = NULL; - -// Window mRootWin; - XWindowAttributes attribs; char *dispName; assert(vo->x11 == NULL); @@ -447,54 +438,9 @@ int vo_init(struct vo *vo) opts->vo_screenheight = DisplayHeight(x11->display, x11->screen); } // get color depth (from root window, or the best visual): + XWindowAttributes attribs; XGetWindowAttributes(x11->display, x11->rootwin, &attribs); - depth = attribs.depth; - - if (depth != 15 && depth != 16 && depth != 24 && depth != 32) - { - Visual *visual; - - depth = vo_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); - - x11->depthonscreen = 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. The x11->depthonscreen - * field stores the amount of data per pixel in the - * XImage structure! - * - * Maybe we should rename vo_depthonscreen to (or add) vo_bpp? - */ - bpp = mXImage->bits_per_pixel; - if ((x11->depthonscreen + 7) / 8 != (bpp + 7) / 8) - x11->depthonscreen = 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 (((x11->depthonscreen + 7) / 8) == 2) - { - if (mask == 0x7FFF) - x11->depthonscreen = 15; - else if (mask == 0xFFFF) - x11->depthonscreen = 16; - } // XCloseDisplay( mDisplay ); /* slightly improved local display detection AST */ if (strncmp(dispName, "unix:", 5) == 0) @@ -506,8 +452,8 @@ int vo_init(struct vo *vo) else x11->display_is_local = 0; mp_msg(MSGT_VO, MSGL_V, - "vo: X11 running at %dx%d with depth %d and %d bpp (\"%s\" => %s display)\n", - opts->vo_screenwidth, opts->vo_screenheight, depth, x11->depthonscreen, + "vo: X11 running at %dx%d with depth %d (\"%s\" => %s display)\n", + opts->vo_screenwidth, opts->vo_screenheight, attribs.depth, dispName, x11->display_is_local ? "local" : "remote"); x11->wm_type = vo_wm_detect(vo); @@ -534,7 +480,6 @@ void vo_uninit(struct vo_x11_state *x11) XCloseIM(x11->xim); XSetErrorHandler(NULL); XCloseDisplay(x11->display); - x11->depthonscreen = 0; x11->display = NULL; } talloc_free(x11); @@ -1741,59 +1686,6 @@ double vo_vm_get_fps(struct vo *vo) #endif -/* - * 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. - */ -int vo_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 Colormap cmap = None; static XColor cols[256]; static int cm_size, red_mask, green_mask, blue_mask; diff --git a/libvo/x11_common.h b/libvo/x11_common.h index 57353e418e..e0292c5e77 100644 --- a/libvo/x11_common.h +++ b/libvo/x11_common.h @@ -34,7 +34,6 @@ struct vo_x11_state { Window rootwin; int screen; int display_is_local; - int depthonscreen; XIM xim; XIC xic; @@ -178,7 +177,6 @@ double vo_vm_get_fps(struct vo *vo); void update_xinerama_info(struct vo *vo); -int vo_find_depth_from_visuals(Display *dpy, int screen, Visual **visual_return); void xscreensaver_heartbeat(struct vo_x11_state *x11); // Old VOs use incompatible function calls, translate them to new @@ -213,7 +211,6 @@ void xscreensaver_heartbeat(struct vo_x11_state *x11); #define vo_x11_border() vo_x11_border(global_vo) #define mDisplay global_vo->x11->display -#define vo_depthonscreen global_vo->x11->depthonscreen #define vo_window global_vo->x11->window #define xv_ck_info global_vo->x11->xv_ck_info #define xv_colorkey global_vo->x11->xv_colorkey -- 2.11.4.GIT