@Override
  protected final Buffer getGammaRamp() {
    long display = getOrCreateSharedDpy(defaultDevice);
    if (0 == display) {
      return null;
    }

    int size = getGammaRampLength();
    ShortBuffer rampData = ShortBuffer.wrap(new short[3 * size]);
    rampData.position(0);
    rampData.limit(size);
    ShortBuffer redRampData = rampData.slice();
    rampData.position(size);
    rampData.limit(2 * size);
    ShortBuffer greenRampData = rampData.slice();
    rampData.position(2 * size);
    rampData.limit(3 * size);
    ShortBuffer blueRampData = rampData.slice();

    boolean res =
        X11Lib.XF86VidModeGetGammaRamp(
            display, X11Lib.DefaultScreen(display), size, redRampData, greenRampData, blueRampData);
    if (!res) {
      return null;
    }
    return rampData;
  }
  @Override
  protected final void resetGammaRamp(Buffer originalGammaRamp) {
    if (originalGammaRamp == null) {
      return; // getGammaRamp failed originally
    }
    long display = getOrCreateSharedDpy(defaultDevice);
    if (0 == display) {
      return;
    }

    ShortBuffer rampData = (ShortBuffer) originalGammaRamp;
    int capacity = rampData.capacity();
    if ((capacity % 3) != 0) {
      throw new IllegalArgumentException("Must not be the original gamma ramp");
    }
    int size = capacity / 3;
    rampData.position(0);
    rampData.limit(size);
    ShortBuffer redRampData = rampData.slice();
    rampData.position(size);
    rampData.limit(2 * size);
    ShortBuffer greenRampData = rampData.slice();
    rampData.position(2 * size);
    rampData.limit(3 * size);
    ShortBuffer blueRampData = rampData.slice();

    X11Lib.XF86VidModeSetGammaRamp(
        display, X11Lib.DefaultScreen(display), size, redRampData, greenRampData, blueRampData);
  }
  @Override
  protected final boolean setGammaRamp(float[] ramp) {
    long display = getOrCreateSharedDpy(defaultDevice);
    if (0 == display) {
      return false;
    }

    int len = ramp.length;
    short[] rampData = new short[len];
    for (int i = 0; i < len; i++) {
      rampData[i] = (short) (ramp[i] * 65535);
    }

    boolean res =
        X11Lib.XF86VidModeSetGammaRamp(
            display,
            X11Lib.DefaultScreen(display),
            rampData.length,
            rampData,
            0,
            rampData,
            0,
            rampData,
            0);
    return res;
  }
  static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesXVisual(
      X11GraphicsScreen x11Screen, GLProfile glProfile, boolean isMultisampleAvailable) {
    AbstractGraphicsDevice absDevice = x11Screen.getDevice();
    long display = absDevice.getHandle();

    int screen = x11Screen.getIndex();

    int[] count = new int[1];
    XVisualInfo template = XVisualInfo.create();
    template.setScreen(screen);
    XVisualInfo[] infos =
        X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0);
    if (infos == null || infos.length < 1) {
      throw new GLException("Error while enumerating available XVisualInfos");
    }
    ArrayList<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
    for (int i = 0; i < infos.length; i++) {
      if (!X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(
          availableCaps,
          glProfile,
          display,
          infos[i],
          GLGraphicsConfigurationUtil.ALL_BITS,
          isMultisampleAvailable)) {
        if (DEBUG) {
          System.err.println(
              "X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesXVisual: XVisual invalid: ("
                  + x11Screen
                  + "): fbcfg: "
                  + toHexString(infos[i].getVisualid()));
        }
      }
    }
    return availableCaps;
  }
  @Override
  protected final Buffer getGammaRamp(final NativeSurface surface) {
    final long display = surface.getDisplayHandle();
    if (0 == display) {
      return null;
    }
    final int screenIdx = surface.getScreenIndex();

    final int size = getGammaRampLength(surface);

    final ShortBuffer rampData = Buffers.newDirectShortBuffer(3 * size);
    final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size);
    final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size);
    final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size);

    final boolean res =
        X11Lib.XF86VidModeGetGammaRamp(
            display, screenIdx, size, redRampData, greenRampData, blueRampData);
    if (!res) {
      return null;
    }
    if (DEBUG) {
      dumpRamp("GET__", size, redRampData, greenRampData, blueRampData);
    }
    return rampData;
  }
  @Override
  protected final synchronized int getGammaRampLength() {
    if (gotGammaRampLength) {
      return gammaRampLength;
    }

    long display = getOrCreateSharedDpy(defaultDevice);
    if (0 == display) {
      return 0;
    }

    int[] size = new int[1];
    boolean res =
        X11Lib.XF86VidModeGetGammaRampSize(display, X11Lib.DefaultScreen(display), size, 0);
    if (!res) {
      return 0;
    }
    gotGammaRampLength = true;
    gammaRampLength = size[0];
    return gammaRampLength;
  }
  private static final void resetGammaRamp(
      final long display, final int screenIdx, final Buffer originalGammaRamp) {
    final ShortBuffer rampData = (ShortBuffer) originalGammaRamp;
    final int capacity = rampData.capacity();
    if ((capacity % 3) != 0) {
      throw new IllegalArgumentException("Must not be the original gamma ramp");
    }
    final int size = capacity / 3;

    final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size);
    final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size);
    final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size);
    if (DEBUG) {
      dumpRamp("RESET", size, redRampData, greenRampData, blueRampData);
    }

    X11Lib.XF86VidModeSetGammaRamp(
        display, screenIdx, size, redRampData, greenRampData, blueRampData);
  }
  @Override
  protected final synchronized int getGammaRampLength(final NativeSurface surface) {
    if (gotGammaRampLength) {
      return gammaRampLength;
    }
    final long display = surface.getDisplayHandle();
    if (0 == display) {
      return 0;
    }
    final int screenIdx = surface.getScreenIndex();

    final int[] size = new int[1];
    final boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, screenIdx, size, 0);
    if (!res) {
      return 0;
    }
    gotGammaRampLength = true;
    gammaRampLength = size[0];
    System.err.println("XXX: Gamma ramp size: " + gammaRampLength);
    return gammaRampLength;
  }
 @Override
 protected final ProxySurface createProxySurfaceImpl(
     AbstractGraphicsDevice deviceReq,
     int screenIdx,
     long windowHandle,
     GLCapabilitiesImmutable capsRequested,
     GLCapabilitiesChooser chooser,
     UpstreamSurfaceHook upstream) {
   final X11GraphicsDevice device =
       new X11GraphicsDevice(
           X11Util.openDisplay(deviceReq.getConnection()),
           deviceReq.getUnitID(),
           true /* owner */);
   final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx);
   final int xvisualID = X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
   if (VisualIDHolder.VID_UNDEFINED == xvisualID) {
     throw new GLException(
         "Undefined VisualID of window 0x"
             + Long.toHexString(windowHandle)
             + ", window probably invalid");
   }
   if (DEBUG) {
     System.err.println(
         "X11GLXDrawableFactory.createProxySurfaceImpl 0x"
             + Long.toHexString(windowHandle)
             + ": visualID 0x"
             + Integer.toHexString(xvisualID));
   }
   final X11GLXGraphicsConfiguration cfg =
       X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
           capsRequested, capsRequested, chooser, screen, xvisualID);
   if (DEBUG) {
     System.err.println(
         "X11GLXDrawableFactory.createProxySurfaceImpl 0x"
             + Long.toHexString(windowHandle)
             + ": "
             + cfg);
   }
   return new WrappedSurface(cfg, windowHandle, upstream, true);
 }
  @Override
  protected final boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
    final long display = surface.getDisplayHandle();
    if (0 == display) {
      return false;
    }
    final int screenIdx = surface.getScreenIndex();

    final int len = ramp.length;
    final short[] rampData = new short[len];
    for (int i = 0; i < len; i++) {
      rampData[i] = (short) (ramp[i] * 65535);
    }

    final boolean res =
        X11Lib.XF86VidModeSetGammaRamp(
            display, screenIdx, rampData.length, rampData, 0, rampData, 0, rampData, 0);
    if (DEBUG) {
      dumpRamp("SET__", rampData.length, rampData, rampData, rampData);
    }
    return res;
  }
  private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(
      GLCapabilitiesImmutable capsChosen,
      GLCapabilitiesImmutable capsReq,
      GLCapabilitiesChooser chooser,
      X11GraphicsScreen x11Screen) {
    if (chooser == null) {
      chooser = new DefaultGLCapabilitiesChooser();
    }

    GLProfile glProfile = capsChosen.getGLProfile();
    final int winattrmask =
        GLGraphicsConfigurationUtil.getWinAttributeBits(
            capsChosen.isOnscreen(), false /* pbuffer */);
    ArrayList availableCaps = new ArrayList();
    int recommendedIndex = -1;

    AbstractGraphicsDevice absDevice = x11Screen.getDevice();
    long display = absDevice.getHandle();
    int screen = x11Screen.getIndex();

    final X11GLXDrawableFactory factory =
        (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
    final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice);
    int[] attribs =
        X11GLXGraphicsConfiguration.GLCapabilities2AttribList(
            capsChosen, false, isMultisampleAvailable, display, screen);

    // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as
    // preferred choice
    XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
    if (DEBUG) {
      System.err.print("glXChooseVisual recommended ");
      if (recommendedVis == null) {
        System.err.println("null visual");
      } else {
        System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
      }
    }

    // 2nd choice: get all GLCapabilities available, preferred recommendedIndex might be available
    // if 1st choice was successful
    int[] count = new int[1];
    XVisualInfo template = XVisualInfo.create();
    template.setScreen(screen);
    XVisualInfo[] infos =
        X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0);
    if (infos == null || infos.length < 1) {
      throw new GLException("Error while enumerating available XVisualInfos");
    }

    for (int i = 0; i < infos.length; i++) {
      if (!X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(
          availableCaps, glProfile, display, infos[i], winattrmask, isMultisampleAvailable)) {
        if (DEBUG) {
          System.err.println(
              "X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: XVisual invalid: ("
                  + x11Screen
                  + "): fbcfg: "
                  + toHexString(infos[i].getVisualid()));
        }
      } else {
        // Attempt to find the visual chosenIndex by glXChooseVisual, if not translucent
        if (capsChosen.isBackgroundOpaque()
            && recommendedVis != null
            && recommendedVis.getVisualid() == infos[i].getVisualid()) {
          recommendedIndex = availableCaps.size() - 1;
        }
      }
    }

    int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
    if (0 > chosenIndex) {
      if (DEBUG) {
        System.err.println(
            "X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: failed, return null");
        Thread.dumpStack();
      }
      return null;
    }
    X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex);

    return new X11GLXGraphicsConfiguration(x11Screen, chosenCaps, capsReq, chooser);
  }