summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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