private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(
     EGLGraphicsDevice eglDisplay, GLCapabilitiesImmutable caps) {
   final IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
   if (!EGL.eglGetConfigs(eglDisplay.getHandle(), null, 0, numConfigs)) {
     throw new GLException(
         "EGLDrawableFactory.getAvailableEGLConfigs: Get maxConfigs (eglGetConfigs) call failed, error "
             + EGLContext.toHexString(EGL.eglGetError()));
   }
   if (0 < numConfigs.get(0)) {
     final PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
     final IntBuffer attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(caps);
     final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(caps);
     if (EGL.eglChooseConfig(
             eglDisplay.getHandle(), attrs, configs, configs.capacity(), numConfigs)
         && numConfigs.get(0) > 0) {
       return EGLGraphicsConfigurationFactory.eglConfigs2GLCaps(
           eglDisplay,
           caps.getGLProfile(),
           configs,
           numConfigs.get(0),
           winattrmask,
           false /* forceTransparentFlag */);
     }
   }
   return new ArrayList<GLCapabilitiesImmutable>(0);
 }
 private void dumpMap() {
   synchronized (sharedMap) {
     System.err.println("EGLDrawableFactory.map " + sharedMap.size());
     int i = 0;
     Set<String> keys = sharedMap.keySet();
     for (Iterator<String> keyI = keys.iterator(); keyI.hasNext(); i++) {
       String key = keyI.next();
       SharedResource sr = sharedMap.get(key);
       System.err.println(
           "EGLDrawableFactory.map["
               + i
               + "] "
               + key
               + " -> "
               + sr.getDevice()
               + ", "
               + "es1   [avail "
               + sr.wasES1ContextCreated
               + ", pbuffer "
               + sr.hasPBufferES1
               + ", quirks "
               + sr.rendererQuirksES1
               + ", ctp "
               + EGLContext.getGLVersion(1, 0, sr.ctpES1, null)
               + "], "
               + "es2/3 [es2 "
               + sr.wasES2ContextCreated
               + ", es3 "
               + sr.wasES3ContextCreated
               + ", [pbuffer "
               + sr.hasPBufferES3ES2
               + ", quirks "
               + sr.rendererQuirksES3ES2
               + ", ctp "
               + EGLContext.getGLVersion(2, 0, sr.ctpES3ES2, null)
               + "]]");
     }
     ;
   }
 }
  private final void evalUpstreamSurface(String dbgPrefix, ProxySurface surface) {
    //
    // evaluate nature of upstreamSurface, may create EGL instances if required
    //

    boolean isEGLSurfaceValid = true; // assume yes

    final EGLGraphicsDevice eglDevice;
    final AbstractGraphicsConfiguration aConfig;
    {
      final AbstractGraphicsConfiguration surfaceConfig = surface.getGraphicsConfiguration();
      final AbstractGraphicsDevice surfaceDevice =
          null != surfaceConfig ? surfaceConfig.getScreen().getDevice() : null;
      if (DEBUG) {
        System.err.println(
            dbgPrefix
                + "SurfaceDevice: "
                + surfaceDevice.getClass().getSimpleName()
                + ", hash 0x"
                + Integer.toHexString(surfaceDevice.hashCode())
                + ", "
                + surfaceDevice);
        System.err.println(
            dbgPrefix
                + "SurfaceConfig: "
                + surfaceConfig.getClass().getSimpleName()
                + ", hash 0x"
                + Integer.toHexString(surfaceConfig.hashCode())
                + ", "
                + surfaceConfig);
      }

      final AbstractGraphicsConfiguration upstreamConfig =
          upstreamSurface.getGraphicsConfiguration();
      final AbstractGraphicsDevice upstreamDevice = upstreamConfig.getScreen().getDevice();
      if (DEBUG) {
        System.err.println(
            dbgPrefix
                + "UpstreamDevice: "
                + upstreamDevice.getClass().getSimpleName()
                + ", hash 0x"
                + Integer.toHexString(upstreamDevice.hashCode())
                + ", "
                + upstreamDevice);
        System.err.println(
            dbgPrefix
                + "UpstreamConfig: "
                + upstreamConfig.getClass().getSimpleName()
                + ", hash 0x"
                + Integer.toHexString(upstreamConfig.hashCode())
                + ", "
                + upstreamConfig);
      }

      if (surfaceDevice instanceof EGLGraphicsDevice) {
        eglDevice = (EGLGraphicsDevice) surfaceDevice;
        aConfig = surfaceConfig;
        if (DEBUG) {
          System.err.println(
              dbgPrefix
                  + "Reusing this eglDevice: "
                  + eglDevice
                  + ", using this config "
                  + aConfig.getClass().getSimpleName()
                  + " "
                  + aConfig);
        }
        if (EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
          eglDevice.open();
          isEGLSurfaceValid = false;
          surface.addUpstreamOptionBits(ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE);
        }
      } else if (upstreamDevice instanceof EGLGraphicsDevice) {
        eglDevice = (EGLGraphicsDevice) upstreamDevice;
        aConfig = upstreamConfig;
        if (DEBUG) {
          System.err.println(
              dbgPrefix
                  + "Reusing upstream eglDevice: "
                  + eglDevice
                  + ", using upstream config "
                  + aConfig.getClass().getSimpleName()
                  + " "
                  + aConfig);
        }
        if (EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
          eglDevice.open();
          isEGLSurfaceValid = false;
          surface.addUpstreamOptionBits(ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE);
        }
      } else {
        eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
        eglDevice.open();
        aConfig = upstreamConfig;
        isEGLSurfaceValid = false;
        surface.addUpstreamOptionBits(ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE);
      }
    }

    final GLCapabilitiesImmutable capsRequested =
        (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
    final EGLGraphicsConfiguration eglConfig;
    if (aConfig instanceof EGLGraphicsConfiguration) {
      // Config is already in EGL type - reuse ..
      final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
      if (!isEGLSurfaceValid
          || !EGLGraphicsConfiguration.isEGLConfigValid(
              eglDevice.getHandle(), capsChosen.getEGLConfig())) {
        // 'refresh' the native EGLConfig handle
        capsChosen.setEGLConfig(
            EGLGraphicsConfiguration.EGLConfigId2EGLConfig(
                eglDevice.getHandle(), capsChosen.getEGLConfigID()));
        if (0 == capsChosen.getEGLConfig()) {
          throw new GLException(
              "Refreshing native EGLConfig handle failed with error "
                  + EGLContext.toHexString(EGL.eglGetError())
                  + ": "
                  + eglDevice
                  + ", "
                  + capsChosen
                  + " of "
                  + aConfig);
        }
        final AbstractGraphicsScreen eglScreen =
            new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
        eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null);
        if (DEBUG) {
          System.err.println(dbgPrefix + "Refreshing eglConfig: " + eglConfig);
        }
        isEGLSurfaceValid = false;
      } else {
        eglConfig = (EGLGraphicsConfiguration) aConfig;
        if (DEBUG) {
          System.err.println(dbgPrefix + "Reusing eglConfig: " + eglConfig);
        }
      }
    } else {
      final AbstractGraphicsScreen eglScreen =
          new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
      eglConfig =
          EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
              capsRequested,
              capsRequested,
              null,
              eglScreen,
              aConfig.getVisualID(VIDType.NATIVE),
              false /* forceTransparencyFlag */);

      if (null == eglConfig) {
        throw new GLException("Couldn't create EGLGraphicsConfiguration from " + eglScreen);
      } else if (DEBUG) {
        System.err.println(dbgPrefix + "Chosen eglConfig: " + eglConfig);
      }
      isEGLSurfaceValid = false;
    }
    surface.setGraphicsConfiguration(eglConfig);

    if (isEGLSurfaceValid) {
      isEGLSurfaceValid =
          EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle());
    }
    if (isEGLSurfaceValid) {
      surface.setSurfaceHandle(upstreamSurface.getSurfaceHandle());
      surface.clearUpstreamOptionBits(ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE);
      if (DEBUG) {
        System.err.println(
            dbgPrefix + "Fin: Already valid EGL surface - use as-is: " + upstreamSurface);
      }
    } else {
      surface.setSurfaceHandle(EGL.EGL_NO_SURFACE);
      surface.addUpstreamOptionBits(
          ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE); // create/destroy in EGLDrawable
      if (DEBUG) {
        System.err.println(dbgPrefix + "Fin: EGL surface n/a - TBD: " + upstreamSurface);
      }
    }
  }
  private SharedResource createEGLSharedResourceImpl(AbstractGraphicsDevice adevice) {
    final boolean madeCurrentES1;
    final boolean madeCurrentES2;
    final boolean madeCurrentES3;
    boolean[] hasPBufferES1 = new boolean[] {false};
    boolean[] hasPBufferES3ES2 = new boolean[] {false};
    // EGLContext[] eglCtxES1 = new EGLContext[] { null };
    // EGLContext[] eglCtxES2 = new EGLContext[] { null };
    GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] {null};
    GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] {null};
    int[] ctpES1 = new int[] {-1};
    int[] ctpES3ES2 = new int[] {-1};

    if (DEBUG) {
      System.err.println("EGLDrawableFactory.createShared(): device " + adevice);
    }

    if (null != eglES1DynamicLookupHelper) {
      madeCurrentES1 =
          mapAvailableEGLESConfig(adevice, 1, hasPBufferES1, rendererQuirksES1, ctpES1);
    } else {
      madeCurrentES1 = false;
    }
    if (null != eglES2DynamicLookupHelper) {
      madeCurrentES3 =
          mapAvailableEGLESConfig(adevice, 3, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2);
      if (madeCurrentES3) {
        // Only support highest - FIXME: Proper ES2/ES3 profile selection
        madeCurrentES2 = false;
      } else {
        madeCurrentES2 =
            mapAvailableEGLESConfig(adevice, 2, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2);
      }
    } else {
      madeCurrentES2 = false;
      madeCurrentES3 = false;
    }

    if (!EGLContext.getAvailableGLVersionsSet(adevice)) {
      // Even though we override the non EGL native mapping intentionally,
      // avoid exception due to double 'set' - carefull exception of the rule.
      EGLContext.setAvailableGLVersionsSet(adevice);
    }
    if (hasX11) {
      handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]);
      handleDontCloseX11DisplayQuirk(rendererQuirksES3ES2[0]);
    }
    final SharedResource sr =
        new SharedResource(
            defaultDevice,
            madeCurrentES1,
            hasPBufferES1[0],
            rendererQuirksES1[0],
            ctpES1[0],
            madeCurrentES2,
            madeCurrentES3,
            hasPBufferES3ES2[0],
            rendererQuirksES3ES2[0],
            ctpES3ES2[0]);

    synchronized (sharedMap) {
      sharedMap.put(adevice.getUniqueID(), sr);
    }
    if (DEBUG) {
      System.err.println(
          "EGLDrawableFactory.createShared: devices: queried nativeTK "
              + QUERY_EGL_ES_NATIVE_TK
              + ", adevice "
              + adevice
              + ", defaultDevice "
              + defaultDevice);
      System.err.println(
          "EGLDrawableFactory.createShared: context ES1: "
              + madeCurrentES1
              + ", hasPBuffer "
              + hasPBufferES1[0]);
      System.err.println(
          "EGLDrawableFactory.createShared: context ES2: "
              + madeCurrentES2
              + ", hasPBuffer "
              + hasPBufferES3ES2[0]);
      System.err.println(
          "EGLDrawableFactory.createShared: context ES3: "
              + madeCurrentES3
              + ", hasPBuffer "
              + hasPBufferES3ES2[0]);
      dumpMap();
    }
    return sr;
  }
  private boolean mapAvailableEGLESConfig(
      AbstractGraphicsDevice adevice,
      int esProfile,
      boolean[] hasPBuffer,
      GLRendererQuirks[] rendererQuirks,
      int[] ctp) {
    final String profileString;
    switch (esProfile) {
      case 3:
        profileString = GLProfile.GLES3;
        break;
      case 2:
        profileString = GLProfile.GLES2;
        break;
      case 1:
        profileString = GLProfile.GLES1;
        break;
      default:
        throw new GLException("Invalid ES profile number " + esProfile);
    }
    if (!GLProfile.isAvailable(adevice, profileString)) {
      if (DEBUG) {
        System.err.println(
            "EGLDrawableFactory.mapAvailableEGLESConfig: " + profileString + " n/a on " + adevice);
      }
      return false;
    }
    final GLProfile glp = GLProfile.get(adevice, profileString);
    final GLDrawableFactoryImpl desktopFactory =
        (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory();
    final boolean mapsADeviceToDefaultDevice =
        !QUERY_EGL_ES_NATIVE_TK || null == desktopFactory || adevice instanceof EGLGraphicsDevice;
    if (DEBUG) {
      System.err.println(
          "EGLDrawableFactory.mapAvailableEGLESConfig: "
              + profileString
              + " ( "
              + esProfile
              + " ), "
              + "defaultSharedResourceSet "
              + (null != defaultSharedResource)
              + ", mapsADeviceToDefaultDevice "
              + mapsADeviceToDefaultDevice
              + " (QUERY_EGL_ES_NATIVE_TK "
              + QUERY_EGL_ES_NATIVE_TK
              + ", hasDesktopFactory "
              + (null != desktopFactory)
              + ", isEGLGraphicsDevice "
              + (adevice instanceof EGLGraphicsDevice)
              + ")");
    }

    EGLGraphicsDevice eglDevice = null;
    NativeSurface surface = null;
    ProxySurface upstreamSurface = null; // X11, GLX, ..
    boolean success = false;
    boolean deviceFromUpstreamSurface = false;
    try {
      final GLCapabilities reqCapsAny = new GLCapabilities(glp);
      reqCapsAny.setRedBits(5);
      reqCapsAny.setGreenBits(5);
      reqCapsAny.setBlueBits(5);
      reqCapsAny.setAlphaBits(0);
      reqCapsAny.setDoubleBuffered(false);

      if (mapsADeviceToDefaultDevice) {
        // In this branch, any non EGL device is mapped to EGL default shared resources (default
        // behavior).
        // Only one default shared resource instance is ever be created.
        final GLCapabilitiesImmutable reqCapsPBuffer =
            GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny);
        final List<GLCapabilitiesImmutable> availablePBufferCapsL =
            getAvailableEGLConfigs(defaultDevice, reqCapsPBuffer);
        hasPBuffer[0] = availablePBufferCapsL.size() > 0;

        // 1st case: adevice is not the EGL default device, map default shared resources
        if (adevice != defaultDevice) {
          if (null == defaultSharedResource) {
            return false;
          }
          switch (esProfile) {
            case 3:
              if (!defaultSharedResource.wasES3ContextCreated) {
                return false;
              }
              rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2;
              ctp[0] = defaultSharedResource.ctpES3ES2;
              break;
            case 2:
              if (!defaultSharedResource.wasES2ContextCreated) {
                return false;
              }
              rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2;
              ctp[0] = defaultSharedResource.ctpES3ES2;
              break;
            case 1:
              if (!defaultSharedResource.wasES1ContextCreated) {
                return false;
              }
              rendererQuirks[0] = defaultSharedResource.rendererQuirksES1;
              ctp[0] = defaultSharedResource.ctpES1;
              break;
          }
          EGLContext.mapStaticGLVersion(adevice, esProfile, 0, ctp[0]);
          return true;
        }

        // attempt to created the default shared resources ..

        eglDevice = defaultDevice; // reuse

        if (hasPBuffer[0]) {
          // 2nd case create defaultDevice shared resource using pbuffer surface
          surface =
              createDummySurfaceImpl(
                  eglDevice,
                  false,
                  reqCapsPBuffer,
                  reqCapsPBuffer,
                  null,
                  64,
                  64); // egl pbuffer offscreen
          upstreamSurface = (ProxySurface) surface;
          upstreamSurface.createNotify();
          deviceFromUpstreamSurface = false;
        } else {
          // 3rd case fake creation of defaultDevice shared resource, no pbuffer available
          final List<GLCapabilitiesImmutable> capsAnyL =
              getAvailableEGLConfigs(eglDevice, reqCapsAny);
          if (capsAnyL.size() > 0) {
            final GLCapabilitiesImmutable chosenCaps = capsAnyL.get(0);
            EGLContext.mapStaticGLESVersion(eglDevice, chosenCaps);
            success = true;
          }
          if (DEBUG) {
            System.err.println(
                "EGLDrawableFactory.mapAvailableEGLESConfig() no pbuffer config available, detected !pbuffer config: "
                    + success);
            EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err);
          }
        }
      } else {
        // 4th case always creates a true mapping of given device to EGL
        surface =
            desktopFactory.createDummySurface(
                adevice, reqCapsAny, null, 64, 64); // X11, WGL, .. dummy window
        upstreamSurface = (surface instanceof ProxySurface) ? (ProxySurface) surface : null;
        if (null != upstreamSurface) {
          upstreamSurface.createNotify();
        }
        eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface);
        deviceFromUpstreamSurface = true;
        hasPBuffer[0] = true;
      }

      if (null != surface) {
        final EGLDrawable drawable =
            (EGLDrawable)
                createOnscreenDrawableImpl(
                    surface); // works w/ implicit pbuffer surface via proxy-hook
        drawable.setRealized(true);
        final EGLContext context = (EGLContext) drawable.createContext(null);
        if (null != context) {
          try {
            context.makeCurrent(); // could cause exception
            if (context.isCurrent()) {
              final String glVersion = context.getGL().glGetString(GL.GL_VERSION);
              if (null != glVersion) {
                context.mapCurrentAvailableGLVersion(eglDevice);
                if (eglDevice != adevice) {
                  context.mapCurrentAvailableGLVersion(adevice);
                }
                rendererQuirks[0] = context.getRendererQuirks();
                ctp[0] = context.getContextOptions();
                success = true;
              } else {
                // Oops .. something is wrong
                if (DEBUG) {
                  System.err.println(
                      "EGLDrawableFactory.mapAvailableEGLESConfig: "
                          + eglDevice
                          + ", "
                          + context.getGLVersion()
                          + " - VERSION is null, dropping availability!");
                }
              }
            }
          } catch (GLException gle) {
            if (DEBUG) {
              System.err.println(
                  "EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed");
              gle.printStackTrace();
            }
          } finally {
            context.destroy();
          }
        }
        drawable.setRealized(false);
      }
    } catch (Throwable t) {
      if (DEBUG) {
        System.err.println("Catched Exception on thread " + getThreadName());
        t.printStackTrace();
      }
      success = false;
    } finally {
      if (eglDevice == defaultDevice) {
        if (null != upstreamSurface) {
          upstreamSurface.destroyNotify();
        }
      } else if (deviceFromUpstreamSurface) {
        if (null != eglDevice) {
          eglDevice.close();
        }
        if (null != upstreamSurface) {
          upstreamSurface.destroyNotify();
        }
      } else {
        if (null != upstreamSurface) {
          upstreamSurface.destroyNotify();
        }
        if (null != eglDevice) {
          eglDevice.close();
        }
      }
    }
    return success;
  }