/*------------------------------------------------------------------------------
 src/plugin/djImageIoVlut/load.cxx
 
 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

//#define DJ_DBG
#include "io.h"

extern "C" {
const dj::List<dj::ImageLoad *> djImageLoad()
{
  dj::List<dj::ImageLoad *> out;
  out += new djImageIoVlut::Load;
  return out;
}
}

namespace djImageIoVlut {

Load::Load() :
  _x(0)
{}

Load::~Load()
{
  if (_x) delete _x;
}

bool Load::open(const Str & fileName, ImageIoInfo * info)
{
  DJ_DBG_FNC("djImageIoVlut::Load::open");
  DJ_DBG_PRN("file name = " << fileName);
  
  _displayName = fileName;
  if (! imageOpen(_displayName, info)) return false;
  
  return true;
}

bool Load::imageBegin(int, ImageIoInfo * info)
{
  DJ_DBG_FNC("djImageIoVlut::Load::imageBegin");
  
  if (! imageOpen(_displayName, info)) return false;
  
  return true;
}

#if defined(DJ_VLUT_XORG)

bool Load::imageOpen(const Str & fileName, ImageIoInfo * info)
{
  DJ_DBG_FNC("djImageIoVlut::Load::imageOpen");
  DJ_DBG_PRN("file name = " << fileName);
  
  // Open display.
  //
  if (_x) delete _x;
  _x = new XHandle(fileName);
  if (! _x->display) return false;
  
  // Setup information.
  //
  if (! XF86VidModeGetGammaRampSize(_x->display, _x->screen, &_size))
    return false;
  DJ_DBG_PRN("vlut size = " << _size);
  info->set(Vec2i(_size, 1), Pixel(PIXEL_RGB, PIXEL_U16));

  return true;
}

bool Load::imageGet(PixelData * out, int proxyScale)
{
  DJ_DBG_FNC("djImageIoVlut::Load::imageGet");
  DJ_DBG_PRN("out = " << *out);
  DJ_DBG_PRN("proxy = " << proxyScale);
  
  // Read.
  //
  PixelData scanline(Vec2i(_size, 1), Pixel(PIXEL_RGB, PIXEL_U16));
  unsigned short * const p =
    reinterpret_cast<unsigned short *>(scanline.data());
  if (
    ! XF86VidModeGetGammaRamp(
      _x->display, _x->screen, _size, p, p + _size, p + _size * 2
    )
  )
    return false;
    
  for (int c = 0; c < 3; ++c)
    pixelCopy(
      p + _size * c, out->data() + c * pixelSize(out->type()),
      out->width(), Pixel(PIXEL_L, PIXEL_U16), out->pixel(),
      proxyScale, false, 1
    );
  
  delete _x;
  _x = 0;
  return true;
}

#elif defined(DJ_VLUT_XSGI)

bool Load::imageOpen(const Str & fileName, ImageIoInfo * info)
{
  DJ_DBG_FNC("djImageIoVlut::Load::imageOpen");
  DJ_DBG_PRN("file name = " << fileName);

  // Open display.
  //
  if (_x) delete _x;
  _x = new XHandle(fileName);
  if (! _x->display) return false;
  
  // Information.
  //
  int maps = 0, precision = 0, attr = 0;
  if (! XSGIvcQueryScreenGammaMaps(_x->display, _x->screen, &maps))
    return false;
  if (maps <= 0) return false;
  if (
    ! XSGIvcQueryGammaMap(
      _x->display, _x->screen, 0, &_size, &precision, &attr
    )
  )
    return false;
  if (attr & XSGIVC_GMReadLock) return false;
  DJ_DBG_PRN("vlut size = " << _size);
  info->set(Vec2i(_size, 1), Pixel(PIXEL_RGB, PIXEL_U16));

  return true;
}

bool Load::imageGet(PixelData * out, int proxyScale)
{
  DJ_DBG_FNC("djImageIoVlut::Load::imageGet");
  DJ_DBG_PRN("out = " << *out);
  DJ_DBG_PRN("proxy = " << proxyScale);
  
  // Read.
  //
  unsigned short * p [] = { 0, 0, 0 };
  int size = 0;
do {

  if (
    ! XSGIvcQueryGammaColors(
      _x->display, _x->screen, 0, XSGIVC_COMPONENT_RED, &size, &p[0]
    )
  )
    break;
  if (
    ! XSGIvcQueryGammaColors(
      _x->display, _x->screen, 0, XSGIVC_COMPONENT_GREEN, &size, &p[1]
    )
  )
    break;
  if (
    ! XSGIvcQueryGammaColors(
      _x->display, _x->screen, 0, XSGIVC_COMPONENT_BLUE, &size, &p[2]
    )
  )
    break;
    
  for (int c = 0; c < 3; ++c)
    pixelCopy(
      p[c], out->data() + c * pixelSize(out->type()),
      out->width(), Pixel(PIXEL_L, PIXEL_U16), out->pixel(),
      proxyScale, false, 1
    );

} while (0);
  XFree(p[0]);
  XFree(p[1]);
  XFree(p[2]);
  
  delete _x;
  _x = 0;
  return size;
}

#endif

}
