summaryrefslogblamecommitdiffstats
path: root/src/blueshift_w32gdi_c.c
blob: d304b25c291b3089c9cd028cd14cef9f08641b41 (plain) (tree)







































                                                                        
          








                                                           
                   
























                                                                               

                                                                                     









                                                                       
                               























































                                                                                             
                                                  



























                                                                                         
        





                                  
/**
 * Copyright © 2014  Mattias Andrée (maandree@member.fsf.org)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "blueshift_w32gdi_c.h"



/**
 * The number of CRTC:s on the system
 */
static int crtc_count;

/**
 * The device contexts for each CRTC
 */
static HDC* crtcs;



/**
 * Start stage of colour curve control
 * 
 * @return  Zero on success
 */
int blueshift_w32gdi_open(void)
{
  int c;
  HDC hDC;
  DISPLAY_DEVICE display;
  display.cb = sizeof(DISPLAY_DEVICE);
  
  crtc_count = 0;
  while (EnumDisplayDevices(NULL, crtc_count, &display, 0))
    crtc_count++;
  
  if (crtc_count == 0)
    {
      crtcs = NULL;
      return 0;
    }
  
  crtcs = malloc(crtc_count * sizeof(HDC));
  if (crtcs == NULL)
    {
      fprintf(stderr, "Out of memory\n");
      return 1;
    }
  
  for (c = 0; c < crtc_count; c++)
    {
      /* Open device context */
      if (EnumDisplayDevices(NULL, c, &display, 0) == FALSE)
	{
	  fprintf(stderr, "Cannot find display, are you unplugging stuff?\n");
	  crtc_count = c;
	  return 1;
	}
      if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
	{
	  fprintf(stderr, "Cannot to open device context, it is not active\n");
	  crtc_count = c;
	  return 1;
	}
      hDC = *(crtcs + c) = CreateDC(TEXT("DISPLAY"), display.DeviceName, NULL, NULL);
      if (hDC == NULL)
	{
	  fprintf(stderr, "Unable to open device context\n");
	  crtc_count = c;
	  return 1;
	}
      
      /* Check support for gamma ramps */
      if (GetDeviceCaps(hDC, COLORMGMTCAPS) != CM_GAMMA_RAMP)
	{
	  fprintf(stderr, "CRTC %i does not support gamma ramps\n", c);
	  ReleaseDC(NULL, hDC);
	  crtc_count = c;
	  return 1;
	}
    }
  
  return 0;
}


/**
 * Get the number of CRTC:s on the system
 * 
 * @return  The number of CRTC:s on the system
 */
int blueshift_w32gdi_crtc_count(void)
{
  return crtc_count;
}


/**
 * Gets the current colour curves
 * 
 * @param   use_crtc  The CRTC to use
 * @return            {the size of the each curve, *the red curve,
 *                    *the green curve, *the blue curve},
 *                    needs to be free:d. `NULL` on error.
 */
uint16_t* blueshift_w32gdi_read(int use_crtc)
{
  uint16_t* rc = NULL;
  if ((use_crtc < 0) || (use_crtc >= crtc_count))
    fprintf(stderr, "CRTC %i does not exist\n", use_crtc);
  else
    {
      rc = malloc((1 + 3 * GAMMA_RAMP_SIZE) * sizeof(uint16_t));
      if (rc == NULL)
	fprintf(stderr, "Out of memory\n");
      else
	{
	  *rc = GAMMA_RAMP_SIZE;
	  if (GetDeviceGammaRamp(*(crtcs + use_crtc), rc + 1) == FALSE)
	    {
	      fprintf(stderr, "Unable to read current gamma ramps from CRTC %i\n", use_crtc);
	      free(rc);
	      rc = NULL;
	    }
	}
    }
  return rc;
}


/**
 * Apply stage of colour curve control
 * 
 * @param   use_crtc   The CRTC to use, -1 for all
 * @param   rgb_curve  The concatenation of the red, the green and the blue colour curves
 * @return             Zero on success
 */
int blueshift_w32gdi_apply(int use_crtc, uint16_t* rgb_curves)
{
  int r = 1;
  if (use_crtc < crtc_count)
    {
      int c = use_crtc < 0 ? 0 : use_crtc;
      int n = use_crtc < 0 ? crtc_count : (use_crtc + 1);
      for (; c < n; c++)
	if (!(r = SetDeviceGammaRamp(*(crtcs + c), rgb_curves)))
	  {
	    fprintf(stderr, "Unable to set gamma ramps\n");
	    break;
	  }
    }
  else
    fprintf(stderr, "CRTC %i does not exist\n", use_crtc);
  return !r;
}


/**
 * Resource freeing stage of colour curve control
 */
void blueshift_w32gdi_close(void)
{
  int c;
  for (c = 0; c < crtc_count; c++)
    ReleaseDC(NULL, *(crtcs + c));
  if (crtcs != NULL)
    free(crtcs);
}