From 7d5dd09ee26381b6a41d01fbe7ab04e9b5bddc2a Mon Sep 17 00:00:00 2001 From: tpearson Date: Thu, 25 Aug 2011 00:35:24 +0000 Subject: 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 --- krandr/libkrandr.cc | 135 ++++++++++++++++++++++++++++++++++++++++++++++++---- krandr/libkrandr.h | 11 +++++ 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 #include +#include #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 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(TQPtrListn_output; i++) { screendata = screenInfoArray.at(i); @@ -565,6 +575,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrListcurrent_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(TQPtrListn_output; i++) { @@ -613,6 +625,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrListcur_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(TQPtrListn_output; i++) { @@ -652,6 +666,7 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrListn_output; i++) { screendata = screenInfoArray.at(i); @@ -679,9 +694,12 @@ bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList return TQPoint(primary_offset_x, primary_offset_y); } +void KRandrSimpleAPI::applySystemwideDisplayGamma(TQPtrList 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; in_crtc; i++) { + free(screen_info->crtcs[i]); + } + for (i=0; in_output; i++) { + free(screen_info->outputs[i]); + } + free(screen_info->outputs); + free(screen_info->crtcs); + free(screen_info); +} + TQPtrList KRandrSimpleAPI::readCurrentDisplayConfiguration() { // Discover display information int i; @@ -824,7 +905,7 @@ TQPtrList 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 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 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 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 KRandrSimpleAPI::readCurrentDisplayConfiguration() { // Check for more screens... numberOfScreens++; } + + freeScreenInfoStructure(randr_screen_info); } else { screendata = new SingleScreenData; @@ -991,6 +1106,10 @@ TQPtrList 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,9 +84,15 @@ 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. */ @@ -190,6 +196,11 @@ class KRANDR_EXPORT KRandrSimpleAPI : public RandRDisplay */ bool applySystemwideDisplayConfiguration(TQPtrList screenInfoArray, bool test=TRUE); + /** + * Applies the gamma contained within the systemwide display configuration screenInfoArray to the hardware + */ + void applySystemwideDisplayGamma(TQPtrList screenInfoArray); + /** * Destroys a screen information object */ 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; -- cgit v1.2.1