summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authorarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-10-29 20:27:47 +0000
committerarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-10-29 20:27:47 +0000
commite5947d8b27b073c78ab3efa9fdde3cc3b0c04e86 (patch)
treeb701474234709c16b62f7a0403b6b5959aad9439 /libvo
parentde382c1b8c5b393963f9abc4c4f781f6f311c759 (diff)
downloadmpv-e5947d8b27b073c78ab3efa9fdde3cc3b0c04e86.tar.bz2
mpv-e5947d8b27b073c78ab3efa9fdde3cc3b0c04e86.tar.xz
here is a somewhat generic equalizer implementation for the X11 vo drivers
using the window's colormap (DirectColor). this method is using the video card's hardware gamma ramp so it involves no performance penalties at all. patch by lucho <lucho@haemimont.bg> git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7965 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libvo')
-rw-r--r--libvo/vo_gl2.c70
-rw-r--r--libvo/vo_x11.c23
-rw-r--r--libvo/x11_common.c133
-rw-r--r--libvo/x11_common.h3
4 files changed, 224 insertions, 5 deletions
diff --git a/libvo/vo_gl2.c b/libvo/vo_gl2.c
index 12e8e27881..a10567ed84 100644
--- a/libvo/vo_gl2.c
+++ b/libvo/vo_gl2.c
@@ -598,6 +598,50 @@ static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsign
static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
}
+static int choose_glx_visual(Display *dpy, int scr, XVisualInfo *res_vi)
+{
+ XVisualInfo template, *vi_list;
+ int vi_num, i, best_i, best_weight;
+
+ template.screen = scr;
+ vi_list = XGetVisualInfo(dpy, VisualScreenMask, &template, &vi_num);
+ if (!vi_list) return -1;
+ best_weight = 1000000;
+ for (i = 0; i < vi_num; i++) {
+ int val, res, w = 0;
+ /* of course, the visual must support OpenGL rendering... */
+ res = glXGetConfig(dpy, vi_list + i, GLX_USE_GL, &val);
+ if (res || val == False) continue;
+ /* also it must be doublebuffered ... */
+ res = glXGetConfig(dpy, vi_list + i, GLX_DOUBLEBUFFER, &val);
+ if (res || val == False) continue;
+ /* furthermore it must be RGBA (not color indexed) ... */
+ res = glXGetConfig(dpy, vi_list + i, GLX_RGBA, &val);
+ if (res || val == False) continue;
+ /* prefer less depth buffer size, */
+ res = glXGetConfig(dpy, vi_list + i, GLX_DEPTH_SIZE, &val);
+ if (res) continue;
+ w += val*2;
+ /* stencil buffer size */
+ res = glXGetConfig(dpy, vi_list + i, GLX_STENCIL_SIZE, &val);
+ if (res) continue;
+ w += val*2;
+ /* and colorbuffer alpha size */
+ res = glXGetConfig(dpy, vi_list + i, GLX_ALPHA_SIZE, &val);
+ if (res) continue;
+ w += val;
+ /* and finally, prefer DirectColor-ed visuals to allow color corrections */
+ if (vi_list[i].class != DirectColor) w += 100;
+ if (w < best_weight) {
+ best_weight = w;
+ best_i = i;
+ }
+ }
+ if (best_weight < 1000000) *res_vi = vi_list[best_i];
+ XFree(vi_list);
+ return (best_weight < 1000000) ? 0 : -1;
+}
+
/* connect to server, create and map window,
* allocate colors and (shared) memory
*/
@@ -609,7 +653,7 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
char *hello = (title == NULL) ? "OpenGL rulez" : title;
// char *name = ":0.0";
XSizeHints hint;
- XVisualInfo *vinfo;
+ XVisualInfo *vinfo, vinfo_buf;
XEvent xev;
// XGCValues xgcv;
@@ -655,7 +699,7 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
// XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &attribs);
// XMatchVisualInfo(mDisplay, screen, depth, TrueColor, &vinfo);
- vinfo=glXChooseVisual( mDisplay,mScreen,wsGLXAttrib );
+ vinfo = choose_glx_visual(mDisplay,mScreen,&vinfo_buf) < 0 ? NULL : &vinfo_buf;
if (vinfo == NULL)
{
printf("[gl2] no GLX support present\n");
@@ -664,7 +708,7 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
xswa.background_pixel = 0;
xswa.border_pixel = 1;
- xswa.colormap = XCreateColormap(mDisplay, mRootWin, vinfo->visual, AllocNone);
+ xswa.colormap = vo_x11_create_colormap(vinfo);
xswamask = CWBackPixel | CWBorderPixel | CWColormap;
if ( vo_window == None )
@@ -1115,6 +1159,26 @@ static uint32_t control(uint32_t request, void *data, ...)
switch (request) {
case VOCTRL_QUERY_FORMAT:
return query_format(*((uint32_t*)data));
+ case VOCTRL_SET_EQUALIZER:
+ {
+ va_list ap;
+ int value;
+
+ va_start(ap, data);
+ value = va_arg(ap, int);
+ va_end(ap);
+ return vo_x11_set_equalizer(data, value);
+ }
+ case VOCTRL_GET_EQUALIZER:
+ {
+ va_list ap;
+ int *value;
+
+ va_start(ap, data);
+ value = va_arg(ap, int *);
+ va_end(ap);
+ return vo_x11_get_equalizer(data, value);
+ }
}
return VO_NOTIMPL;
}
diff --git a/libvo/vo_x11.c b/libvo/vo_x11.c
index c164c3067b..2ef8a871e7 100644
--- a/libvo/vo_x11.c
+++ b/libvo/vo_x11.c
@@ -260,7 +260,8 @@ static uint32_t config( uint32_t width,uint32_t height,uint32_t d_width,uint32_t
Visual *visual;
depth = vo_find_depth_from_visuals(mDisplay, mScreen, &visual);
}
- XMatchVisualInfo( mDisplay,mScreen,depth,TrueColor,&vinfo );
+ if ( !XMatchVisualInfo( mDisplay,mScreen,depth,DirectColor,&vinfo ))
+ XMatchVisualInfo( mDisplay,mScreen,depth,TrueColor,&vinfo );
/* set image size (which is indeed neither the input nor output size),
if zoom is on it will be changed during draw_slice anyway so we dont dupplicate the aspect code here
@@ -292,7 +293,7 @@ static uint32_t config( uint32_t width,uint32_t height,uint32_t d_width,uint32_t
bg=WhitePixel( mDisplay,mScreen );
fg=BlackPixel( mDisplay,mScreen );
- theCmap=XCreateColormap( mDisplay,mRootWin,vinfo.visual,AllocNone );
+ theCmap=vo_x11_create_colormap(&vinfo);
xswa.background_pixel=0;
xswa.border_pixel=0;
@@ -633,6 +634,24 @@ static uint32_t control(uint32_t request, void *data, ...)
return VO_TRUE;
case VOCTRL_GET_IMAGE:
return get_image(data);
+ case VOCTRL_SET_EQUALIZER:
+ {
+ va_list ap;
+ int value;
+ va_start(ap, data);
+ value = va_arg(ap, int);
+ va_end(ap);
+ return vo_x11_set_equalizer(data, value);
+ }
+ case VOCTRL_GET_EQUALIZER:
+ {
+ va_list ap;
+ int *value;
+ va_start(ap, data);
+ value = va_arg(ap, int *);
+ va_end(ap);
+ return vo_x11_get_equalizer(data, value);
+ }
case VOCTRL_FULLSCREEN:
vo_x11_fullscreen();
return VO_TRUE;
diff --git a/libvo/x11_common.c b/libvo/x11_common.c
index 5bdfc35abc..2e4f7c6300 100644
--- a/libvo/x11_common.c
+++ b/libvo/x11_common.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <math.h>
#include <inttypes.h>
#include "config.h"
@@ -969,3 +970,135 @@ int vo_find_depth_from_visuals(Display *dpy, int screen, Visual **visual_return)
return bestvisual_depth;
}
+
+static Colormap cmap = None;
+static XColor cols[256];
+static int cm_size, red_mask, green_mask, blue_mask;
+
+
+Colormap vo_x11_create_colormap(XVisualInfo *vinfo)
+{
+ unsigned k, r, g, b, ru, gu, bu, m, rv, gv, bv, rvu, gvu, bvu;
+
+ if (vinfo->class != DirectColor)
+ return XCreateColormap(mDisplay, mRootWin, vinfo->visual, AllocNone);
+
+ /* can this function get called twice or more? */
+ if (cmap) return cmap;
+ cm_size = vinfo->colormap_size;
+ red_mask = vinfo->red_mask;
+ green_mask = vinfo->green_mask;
+ blue_mask = vinfo->blue_mask;
+ ru = (red_mask&(red_mask-1))^red_mask;
+ gu = (green_mask&(green_mask-1))^green_mask;
+ bu = (blue_mask&(blue_mask-1))^blue_mask;
+ rvu = 65536ull*ru/(red_mask + ru);
+ gvu = 65536ull*gu/(green_mask + gu);
+ bvu = 65536ull*bu/(blue_mask + bu);
+ r = g = b = 0;
+ rv = gv = bv = 0;
+ m = DoRed|DoGreen|DoBlue;
+ for (k = 0; k < cm_size; k++) {
+ int t;
+ cols[k].pixel = r|g|b;
+ cols[k].red = rv;
+ cols[k].green = gv;
+ cols[k].blue = bv;
+ cols[k].flags = m;
+ t = (r + ru) & red_mask; if (t < r) m &= ~DoRed; r = t;
+ t = (g + gu) & green_mask; if (t < g) m &= ~DoGreen; g = t;
+ t = (b + bu) & blue_mask; if (t < b) m &= ~DoBlue; b = t;
+ rv += rvu;
+ gv += gvu;
+ bv += bvu;
+ }
+ cmap = XCreateColormap(mDisplay, mRootWin, vinfo->visual, AllocAll);
+ XStoreColors(mDisplay, cmap, cols, cm_size);
+ return cmap;
+}
+
+/*
+ * Via colormaps/gamma ramps we can do gamma, brightness, contrast,
+ * hue and red/green/blue intensity, but we cannot do saturation.
+ * Currently only gamma, brightness and contrast are implemented.
+ * Is there sufficient interest for hue and/or red/green/blue intensity?
+ */
+/* these values have range [-100,100] and are initially 0 */
+static int vo_gamma = 0;
+static int vo_brightness = 0;
+static int vo_contrast = 0;
+
+
+uint32_t vo_x11_set_equalizer(char *name, int value)
+{
+ float gamma, brightness, contrast;
+ float rf, gf, bf;
+ int k;
+
+ /*
+ * IMPLEMENTME: consider using XF86VidModeSetGammaRamp in the case
+ * of TrueColor-ed window but be careful:
+ * unlike the colormaps, which are private for the X client
+ * who created them and thus automatically destroyed on client
+ * disconnect, this gamma ramp is a system-wide (X-server-wide)
+ * setting and _must_ be restored before the process exit.
+ * Unforunately when the process crashes (or get killed
+ * for some reason) it is impossible to restore the setting,
+ * and such behaviour could be rather annoying for the users.
+ */
+ if (cmap == None) return VO_NOTAVAIL;
+
+ if (!strcasecmp(name, "brightness")) vo_brightness = value;
+ else if (!strcasecmp(name, "contrast")) vo_contrast = value;
+ else if (!strcasecmp(name, "gamma")) vo_gamma = value;
+ else return VO_NOTIMPL;
+
+ brightness = 0.01*vo_brightness;
+ contrast = tan(0.0095*(vo_contrast+100)*M_PI/4);
+ gamma = pow(2, -0.02*vo_gamma);
+
+ rf = (float)((red_mask & (red_mask - 1)) ^ red_mask)/red_mask;
+ gf = (float)((green_mask & (green_mask - 1)) ^ green_mask)/green_mask;
+ bf = (float)((blue_mask & (blue_mask - 1)) ^ blue_mask)/blue_mask;
+
+ /* now recalculate the colormap using the newly set value */
+ for (k = 0; k < cm_size; k++) {
+ float s;
+
+ s = pow(rf*k, gamma);
+ s = (s - 0.5)*contrast + 0.5;
+ s += brightness;
+ if (s < 0) s = 0;
+ if (s > 1) s = 1;
+ cols[k].red = (unsigned short)(s * 65535);
+
+ s = pow(gf*k, gamma);
+ s = (s - 0.5)*contrast + 0.5;
+ s += brightness;
+ if (s < 0) s = 0;
+ if (s > 1) s = 1;
+ cols[k].green = (unsigned short)(s * 65535);
+
+ s = pow(bf*k, gamma);
+ s = (s - 0.5)*contrast + 0.5;
+ s += brightness;
+ if (s < 0) s = 0;
+ if (s > 1) s = 1;
+ cols[k].blue = (unsigned short)(s * 65535);
+ }
+
+ XStoreColors(mDisplay, cmap, cols, cm_size);
+ XFlush(mDisplay);
+ return VO_TRUE;
+}
+
+uint32_t vo_x11_get_equalizer(char *name, int *value)
+{
+ if (cmap == None) return VO_NOTAVAIL;
+ if (!strcasecmp(name, "brightness")) *value = vo_brightness;
+ else if (!strcasecmp(name, "contrast")) *value = vo_contrast;
+ else if (!strcasecmp(name, "gamma")) *value = vo_gamma;
+ else return VO_NOTIMPL;
+}
+
+
diff --git a/libvo/x11_common.h b/libvo/x11_common.h
index c016a04de5..ad6d09b97d 100644
--- a/libvo/x11_common.h
+++ b/libvo/x11_common.h
@@ -36,6 +36,9 @@ extern int vo_x11_check_events(Display *mydisplay);
extern void vo_x11_selectinput_witherr(Display *display, Window w, long event_mask);
extern void vo_x11_fullscreen( void );
extern void vo_x11_uninit();
+extern Colormap vo_x11_create_colormap(XVisualInfo *vinfo);
+extern uint32_t vo_x11_set_equalizer(char *name, int value);
+extern uint32_t vo_x11_get_equalizer(char *name, int *value);
#endif