diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-08-25 00:35:24 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-08-25 00:35:24 +0000 |
commit | 7d5dd09ee26381b6a41d01fbe7ab04e9b5bddc2a (patch) | |
tree | ae358b258db3074b40460908a26d02960d2b4072 | |
parent | 4fba67867725a9c869f48e1d98355867ff23cbde (diff) | |
download | tdelibs-7d5dd09ee26381b6a41d01fbe7ab04e9b5bddc2a.tar.gz tdelibs-7d5dd09ee26381b6a41d01fbe7ab04e9b5bddc2a.zip |
Add gamma support to libkrandr
Fix primary display detect
Fix memory leak
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1249376 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
-rw-r--r-- | krandr/libkrandr.cc | 135 | ||||
-rw-r--r-- | krandr/libkrandr.h | 11 | ||||
-rw-r--r-- | krandr/randr.h | 4 |
3 files changed, 142 insertions, 8 deletions
diff --git a/krandr/libkrandr.cc b/krandr/libkrandr.cc index 0a8e5e571..90049c13e 100644 --- a/krandr/libkrandr.cc +++ b/krandr/libkrandr.cc @@ -29,6 +29,7 @@ #include <kapplication.h> #include <stdlib.h> +#include <cmath> #include "libkrandr.h" @@ -115,7 +116,7 @@ TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) { if (isValid() == true) { screenNumber = -1; - randr_display = XOpenDisplay(NULL); + randr_display = qt_xdisplay(); randr_screen_info = read_screen_info(randr_display); if (randr_screen_info == NULL) { return ""; @@ -136,6 +137,7 @@ TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) { } j++; } + freeScreenInfoStructure(randr_screen_info); } if (screenNumber >= 0) { @@ -179,7 +181,7 @@ TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) { if (isValid() == true) { screenNumber = -1; - randr_display = XOpenDisplay(NULL); + randr_display = qt_xdisplay(); randr_screen_info = read_screen_info(randr_display); if (randr_screen_info == NULL) { return ""; @@ -200,6 +202,7 @@ TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) { } j++; } + freeScreenInfoStructure(randr_screen_info); } if (screenNumber >= 0) { @@ -247,7 +250,7 @@ TQString KRandrSimpleAPI::applyIccConfiguration(TQString profileName, TQString k // Find all screens if (isValid() == true) { - randr_display = XOpenDisplay(NULL); + randr_display = qt_xdisplay(); randr_screen_info = read_screen_info(randr_display); if (randr_screen_info == NULL) { return ""; @@ -259,6 +262,7 @@ TQString KRandrSimpleAPI::applyIccConfiguration(TQString profileName, TQString k return errorstr; } } + freeScreenInfoStructure(randr_screen_info); } else { return applyIccFile(getIccFileName(profileName, "Default", kde_confdir), "Default"); @@ -417,6 +421,9 @@ void KRandrSimpleAPI::saveSystemwideDisplayConfiguration(bool enable, TQString p display_config->writeEntry("CurrentColorDepth", screendata->current_color_depth_index); display_config->writeEntry("CurrentRotation", screendata->current_rotation_index); display_config->writeEntry("CurrentOrientiation", screendata->current_orientation_mask); + display_config->writeEntry("GammaRed", screendata->gamma_red); + display_config->writeEntry("GammaGreen", screendata->gamma_green); + display_config->writeEntry("GammaBlue", screendata->gamma_blue); display_config->writeEntry("CurrentXFlip", screendata->has_x_flip); display_config->writeEntry("CurrentYFlip", screendata->has_y_flip); display_config->writeEntry("SupportsTransformation", screendata->supports_transformations); @@ -491,6 +498,9 @@ TQPtrList<SingleScreenData> KRandrSimpleAPI::loadSystemwideDisplayConfiguration( screendata->current_color_depth_index = display_config->readNumEntry("CurrentColorDepth"); screendata->current_rotation_index = display_config->readNumEntry("CurrentRotation"); screendata->current_orientation_mask = display_config->readNumEntry("CurrentOrientiation"); + screendata->gamma_red = display_config->readDoubleNumEntry("GammaRed"); + screendata->gamma_green = display_config->readDoubleNumEntry("GammaGreen"); + screendata->gamma_blue = display_config->readDoubleNumEntry("GammaBlue"); screendata->has_x_flip = display_config->readBoolEntry("CurrentXFlip"); screendata->has_y_flip = display_config->readBoolEntry("CurrentYFlip"); screendata->supports_transformations = display_config->readBoolEntry("SupportsTransformation"); @@ -555,7 +565,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen TQString command; command = "xrandr"; - randr_display = XOpenDisplay(NULL); + randr_display = qt_xdisplay(); randr_screen_info = read_screen_info(randr_display); for (i = 0; i < randr_screen_info->n_output; i++) { screendata = screenInfoArray.at(i); @@ -565,6 +575,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen command.append(TQString(" --mode %1x%2").arg(screendata->current_x_pixel_count).arg(screendata->current_y_pixel_count)); command.append(TQString(" --pos %1x%2").arg(screendata->absolute_x_position).arg(screendata->absolute_y_position)); command.append(TQString(" --refresh %1").arg((*screendata->refresh_rates.at(screendata->current_refresh_rate_index)).replace("Hz", ""))); + command.append(TQString(" --gamma %1:%2:%3").arg(screendata->gamma_red).arg(screendata->gamma_green).arg(screendata->gamma_blue)); if (screendata->current_rotation_index == 0) command.append(" --rotate ").append("normal"); if (screendata->current_rotation_index == 1) command.append(" --rotate ").append("left"); if (screendata->current_rotation_index == 2) command.append(" --rotate ").append("inverted"); @@ -581,6 +592,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen command.append(" --off"); } } + freeScreenInfoStructure(randr_screen_info); system(command.ascii()); @@ -599,7 +611,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen } } #else - randr_display = XOpenDisplay(NULL); + randr_display = qt_xdisplay(); randr_screen_info = read_screen_info(randr_display); // Turn off all displays for (i = 0; i < randr_screen_info->n_output; i++) { @@ -613,6 +625,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen output_off (randr_screen_info, randr_screen_info->cur_output); j=main_low_apply(randr_screen_info); } + freeScreenInfoStructure(randr_screen_info); randr_screen_info = read_screen_info(randr_display); // Turn on the primary display for (i = 0; i < randr_screen_info->n_output; i++) { @@ -628,6 +641,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen j=main_low_apply(randr_screen_info); } } + freeScreenInfoStructure(randr_screen_info); // Handle the remaining displays randr_screen_info = read_screen_info(randr_display); for (i = 0; i < randr_screen_info->n_output; i++) { @@ -652,6 +666,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen } } } + freeScreenInfoStructure(randr_screen_info); randr_screen_info = read_screen_info(randr_display); for (i = 0; i < randr_screen_info->n_output; i++) { screendata = screenInfoArray.at(i); @@ -679,9 +694,12 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreen } } } + freeScreenInfoStructure(randr_screen_info); #endif } + applySystemwideDisplayGamma(screenInfoArray); + if (test == TRUE) { int ret = showTestConfigurationDialog(); if (!ret) { @@ -807,6 +825,69 @@ TQPoint KRandrSimpleAPI::primaryScreenOffsetFromTLC(TQPtrList<SingleScreenData> return TQPoint(primary_offset_x, primary_offset_y); } +void KRandrSimpleAPI::applySystemwideDisplayGamma(TQPtrList<SingleScreenData> screenInfoArray) { + int i; + Display *randr_display; + XRROutputInfo *output_info; + ScreenInfo *randr_screen_info; + XRRCrtcGamma *gamma; + + SingleScreenData *screendata; + + if (isValid() == true) { + randr_display = qt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + for (i = 0; i < randr_screen_info->n_output; i++) { + screendata = screenInfoArray.at(i); + output_info = randr_screen_info->outputs[i]->info; + CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc; + // vvvvvvvvv This chunk of code is borrowed from xrandr vvvvvvvvvv + int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id); + if (!size) { + continue; + } + gamma = XRRAllocGamma(size); + if (!gamma) { + continue; + } + for (i = 0; i < size; i++) { + if (screendata->gamma_red == 1.0) + gamma->red[i] = i << 8; + else + gamma->red[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_red) * (double)(size-1)*256); + + if (screendata->gamma_green == 1.0) + gamma->green[i] = i << 8; + else + gamma->green[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_green) * (double)(size-1)*256); + + if (screendata->gamma_blue == 1.0) + gamma->blue[i] = i << 8; + else + gamma->blue[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_blue) * (double)(size-1)*256); + } + XRRSetCrtcGamma(randr_display, current_crtc->id, gamma); + free(gamma); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } + freeScreenInfoStructure(randr_screen_info); + } +} + +void KRandrSimpleAPI::freeScreenInfoStructure(ScreenInfo* screen_info) { + int i; + + for (i=0; i<screen_info->n_crtc; i++) { + free(screen_info->crtcs[i]); + } + for (i=0; i<screen_info->n_output; i++) { + free(screen_info->outputs[i]); + } + free(screen_info->outputs); + free(screen_info->crtcs); + free(screen_info); +} + TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() { // Discover display information int i; @@ -824,7 +905,7 @@ TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() { int numberOfScreens = 0; if (isValid() == true) { - randr_display = XOpenDisplay(NULL); + randr_display = qt_xdisplay(); randr_screen_info = read_screen_info(randr_display); for (i = 0; i < randr_screen_info->n_output; i++) { output_info = randr_screen_info->outputs[i]->info; @@ -923,8 +1004,11 @@ TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() { screendata->supports_transformations = (cur_screen->rotations() != RandRScreen::Rotate0); // Determine if this display is primary and/or extended - // [FIXME] - screendata->is_primary = false; + RROutput primaryoutput = XRRGetOutputPrimary(qt_xdisplay(), DefaultRootWindow(qt_xdisplay())); + if (primaryoutput == randr_screen_info->outputs[i]->id) + screendata->is_primary = false; + else + screendata->is_primary = true; screendata->is_extended = screen_active; // Get this screen's absolute position @@ -939,6 +1023,31 @@ TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() { screendata->current_x_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).width(); screendata->current_y_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).height(); + // Get this screen's current gamma values + // [FIXME] + // This attempts to guess a gamma value based on the LUT settings at 50% + // It may not always be 100% correct, or even anywhere close... + // Essentially it "undoes" the LUT gamma calculation from xrandr + // lut_gamma->green[i] = (pow(i/(size - 1), desired_gamma.green) * (size - 1) * 256); + if (current_crtc) { + //int slot = 127; + int slot = 7; + int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id); + XRRCrtcGamma *gammastruct = XRRGetCrtcGamma (randr_display, current_crtc->id); + screendata->gamma_red = log(gammastruct->red[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); + screendata->gamma_green = log(gammastruct->green[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); + screendata->gamma_blue = log(gammastruct->blue[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); + } + else { + screendata->gamma_red = 2.2; + screendata->gamma_green = 2.2; + screendata->gamma_blue = 2.2; + } + // Round off the gamma to one decimal place + screendata->gamma_red = floorf(screendata->gamma_red * 10 + 0.5) / 10; + screendata->gamma_green = floorf(screendata->gamma_green * 10 + 0.5) / 10; + screendata->gamma_blue = floorf(screendata->gamma_blue * 10 + 0.5) / 10; + delete cur_screen; } else { @@ -955,6 +1064,10 @@ TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() { screendata->current_refresh_rate_index = 0; screendata->current_color_depth_index = 0; + screendata->gamma_red = 2.2; + screendata->gamma_green = 2.2; + screendata->gamma_blue = 2.2; + screendata->current_rotation_index = 0; screendata->current_orientation_mask = 0; screendata->has_x_flip = false; @@ -972,6 +1085,8 @@ TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() { // Check for more screens... numberOfScreens++; } + + freeScreenInfoStructure(randr_screen_info); } else { screendata = new SingleScreenData; @@ -991,6 +1106,10 @@ TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() { screendata->current_refresh_rate_index = 0; screendata->current_color_depth_index = 0; + screendata->gamma_red = 2.2; + screendata->gamma_green = 2.2; + screendata->gamma_blue = 2.2; + screendata->current_rotation_index = 0; screendata->current_orientation_mask = 0; screendata->has_x_flip = false; diff --git a/krandr/libkrandr.h b/krandr/libkrandr.h index a56f46daa..6ef7a4b8d 100644 --- a/krandr/libkrandr.h +++ b/krandr/libkrandr.h @@ -84,10 +84,16 @@ class KRANDR_EXPORT KRandrSimpleAPI : public RandRDisplay /** * Reads current screen information. + * NOTE: The caller is responsible for calling freeScreenInfoStructure() when done */ ScreenInfo* read_screen_info(Display *display); /** + * Frees the ScreenInfo structure + */ + void freeScreenInfoStructure(ScreenInfo* screen_info); + + /** * Sets the screen size. */ int set_screen_size (ScreenInfo *screen_info); @@ -191,6 +197,11 @@ class KRANDR_EXPORT KRandrSimpleAPI : public RandRDisplay bool applySystemwideDisplayConfiguration(TQPtrList<SingleScreenData> screenInfoArray, bool test=TRUE); /** + * Applies the gamma contained within the systemwide display configuration screenInfoArray to the hardware + */ + void applySystemwideDisplayGamma(TQPtrList<SingleScreenData> screenInfoArray); + + /** * Destroys a screen information object */ void destroyScreenInformationObject(TQPtrList<SingleScreenData> screenInfoArray); diff --git a/krandr/randr.h b/krandr/randr.h index 8f3d14a33..9faf9b366 100644 --- a/krandr/randr.h +++ b/krandr/randr.h @@ -43,6 +43,10 @@ struct SingleScreenData { int current_refresh_rate_index; int current_color_depth_index; + float gamma_red; + float gamma_green; + float gamma_blue; + int current_rotation_index; int current_orientation_mask; bool has_x_flip; |