PDA

View Full Version : change gamma ramp in video card



hvengel
6th April 2007, 01:53
In my app I need to be able to get and set the video card gamma ramp. In X11 this turned out to be fairly simple with code that looked like this:

gamma_ramp.h


class gamma_ramp
{
public:
int screen;
int size;
unsigned short *red, *green, *blue;

gamma_ramp(int);
~gamma_ramp();
void getGammaRamp();
void setGammaRamp();
void setLinearGammaRamp();

private:
int getGammaRampSize(int);
};

gamma_ramp-x11.cpp


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>

// X11 stuff
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlibint.h>
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/extensions/dpms.h>
#include <X11/extensions/Xinerama.h>
#include "gamma_ramp.h"

gamma_ramp::gamma_ramp(int Screen)
{
screen = Screen;
size = getGammaRampSize(screen);
// now allocate the arrays
red = new unsigned short[size];
green = new unsigned short[size];
blue = new unsigned short[size];
}

gamma_ramp::~gamma_ramp()
{
delete[] red;
delete[] green;
delete[] blue;
}

int gamma_ramp::getGammaRampSize(int Screen)
{
int size = 0;
int event_base;
int error_base;
Display *dpy;

if ((dpy = XOpenDisplay(":0.0")) == NULL)
{
printf("failed to open display :0.0\n");
}
else
{
if (XF86VidModeQueryExtension(dpy, &event_base, &error_base) ==0)
{
printf("XF86VidModeQueryExtension failed\n");
}
else
{
if (!XF86VidModeGetGammaRampSize(dpy, Screen, &size))
{
printf("failed to get XF86VidModeGetGammaRampSize\n");
}
}
}
return size; // will be 0 if failed
}

void gamma_ramp::getGammaRamp()
{
int event_base;
int error_base;
Display *dpy;

if ((dpy = XOpenDisplay(":0.0")) == NULL)
{
printf("failed to open display :0.0\n");
}
else
{
if (XF86VidModeQueryExtension(dpy, &event_base, &error_base) ==0)
{
printf("XF86VidModeQueryExtension failed\n");
}
else
{
XF86VidModeGetGammaRamp(dpy, screen, size,
red, green, blue);

}
}
}

void gamma_ramp::setGammaRamp()
{
int event_base;
int error_base;
Display *dpy;

if ((dpy = XOpenDisplay(":0.0")) == NULL)
{
printf("failed to open display :0.0\n");
}
else
{
if (XF86VidModeQueryExtension(dpy, &event_base, &error_base) ==0)
{
printf("XF86VidModeQueryExtension failed\n");
}
else
{
XF86VidModeSetGammaRamp(dpy, screen, size,
red, green, blue);
}
}
}

void gamma_ramp::setLinearGammaRamp()
{
int event_base;
int error_base;
Display *dpy;
gamma_ramp* temp;

temp = new gamma_ramp(screen);

for (int i=0; i< temp -> size; i++)
{
temp -> red[i] = temp -> green[i] = temp -> blue[i] = i * 256;
}

if ((dpy = XOpenDisplay(":0.0")) == NULL)
{
printf("failed to open display :0.0\n");
}
else
{
if (XF86VidModeQueryExtension(dpy, &event_base, &error_base) ==0)
{
printf("XF86VidModeQueryExtension failed\n");
}
else
{
temp -> setGammaRamp();
}
}
delete temp;
}

and to get the gamma table I would use code like this:


QDesktopWidget* desktop;
desktop = new QDesktopWidget();
screen = desktop -> screenNumber(this);
gamma_ramp* gammaRamp = new gamma_ramp(screen);
gammaRamp -> getGammaRamp();

Now I need to do this same type of thing for windows. Windows has has an API for this:


BOOL WINAPI SetDeviceGammaRamp(
HDC hDC,
LPVOID lpRamp
);

and


BOOL WINAPI GetDeviceGammaRamp(
HDC hDC,
LPVOID lpRamp
);


How do I get the hDC value so that I am working with the correct gamma table for the monitor where the current widget is located? In Qt I can locate that screen with QDesktopWidget::screenNumber(QWdiget*) can I use that information to somehow get a Windows handle to that device?

jacek
6th April 2007, 11:53
Maybe QWidget::getDC() will help?

hvengel
6th April 2007, 17:56
I don't see this for Qt3. But perhaps I can look in the Qt4 code and create my own version of this based on it.

jacek
6th April 2007, 18:27
I don't see this for Qt3. But perhaps I can look in the Qt4 code and create my own version of this based on it.
Sorry, I haven't noticed that you are using Qt3. AFAIR QWidget::winId() returns HWND on windows. Once you have it, you can get HDC through win API.

hvengel
6th April 2007, 23:12
OK now I have the same basic question about OS/X. OS/X has these functions for setting the gamma ramp:

CGDisplayErr CGSetDisplayTransferByTable (
CGDirectDisplayID display,
CGTableCount tableSize,
const CGGammaValue * redTable,
const CGGammaValue * greenTable,
const CGGammaValue * blueTable
);

and

CGDisplayErr CGGetDisplayTransferByTable (
CGDirectDisplayID display,
CGTableCount capacity,
CGGammaValue * redTable,
CGGammaValue * greenTable,
CGGammaValue * blueTable,
CGTableCount * sampleCount
);

Which are similar to X11 and Windows functions for the same thing but there are some differences. Like the gamma table values are floats in the range of 0.0 through 1.0 instead of unsigned shorts in the range of 0 to 2^16 on the other platforms. OK not a big deal. But how do I get from QDesktopWidget::screenNumber() to a CGDirectDisplayID so that I can make these calls? Are these the same thing or are they different? If they are different are there some functions for getting the CGDirectDisplayID available? I can't seem to find any docs about this.

hvengel
10th April 2007, 01:26
OK I didn't mean to stump the band. So I will bump this to see if perhaps a new set of eyes might have an idea about how to get this working on a Mac.