From 769b17ac6ebc5ae49fe37eba13d43fea77fdfd40 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Tue, 8 Nov 2011 23:52:28 +0100
Subject: OSX: SharedResource add knowledge of NPOT-, RECT- and Float-Texture
 features, used by pbuffer drawable before a current context.

- Also  extract getNextPowerOf2() -> GLBuffers (remove redundancy)
---
 .../macosx/cgl/MacOSXCGLDrawableFactory.java       | 124 ++++++++++++++-------
 .../macosx/cgl/MacOSXPbufferCGLDrawable.java       |  79 ++++++-------
 2 files changed, 116 insertions(+), 87 deletions(-)

(limited to 'src/jogl/classes/jogamp/opengl')

diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 18401a025..95401db83 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -42,6 +42,7 @@ package jogamp.opengl.macosx.cgl;
 
 import java.nio.Buffer;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -51,8 +52,10 @@ import javax.media.nativewindow.DefaultGraphicsScreen;
 import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.NativeWindow;
 import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.NativeWindowHolder;
 import javax.media.nativewindow.ProxySurface;
 import javax.media.nativewindow.macosx.MacOSXGraphicsDevice;
+import javax.media.opengl.GL;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLCapabilitiesChooser;
 import javax.media.opengl.GLCapabilitiesImmutable;
@@ -67,7 +70,6 @@ import jogamp.opengl.DesktopGLDynamicLookupHelper;
 import jogamp.opengl.GLDrawableFactoryImpl;
 import jogamp.opengl.GLDrawableImpl;
 import jogamp.opengl.GLDynamicLookupHelper;
-import jogamp.opengl.GLGraphicsConfigurationUtil;
 
 import com.jogamp.common.JogampRuntimeException;
 import com.jogamp.common.util.ReflectionUtil;
@@ -116,18 +118,28 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
       // private MacOSXCGLContext context;
       MacOSXGraphicsDevice device;
       boolean wasContextCreated;
+      boolean hasNPOTTextures;
+      boolean hasRECTTextures;
+      boolean hasAppletFloatPixels;
 
-      SharedResource(MacOSXGraphicsDevice device, boolean wasContextCreated
+      SharedResource(MacOSXGraphicsDevice device, boolean wasContextCreated, 
+                     boolean hasNPOTTextures, boolean hasRECTTextures, boolean hasAppletFloatPixels
                      /* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */) {
           // drawable = draw;
           // context = ctx;
           this.device = device;
           this.wasContextCreated = wasContextCreated;
+          this.hasNPOTTextures = hasNPOTTextures;
+          this.hasRECTTextures = hasRECTTextures;
+          this.hasAppletFloatPixels = hasAppletFloatPixels;
       }
       final MacOSXGraphicsDevice getDevice() { return device; }
       final boolean wasContextAvailable() { return wasContextCreated; }
+      final boolean isNPOTTextureAvailable() { return hasNPOTTextures; }
+      final boolean isRECTTextureAvailable() { return hasRECTTextures; }
+      final boolean isAppletFloatPixelsAvailable() { return hasAppletFloatPixels; }
   }
-  HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap();
+  HashMap<String, SharedResource> sharedMap = new HashMap<String, SharedResource>();
   MacOSXGraphicsDevice defaultDevice;
 
   public final AbstractGraphicsDevice getDefaultDevice() {
@@ -141,52 +153,78 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
       return false;
   }
 
-  private boolean isOSXContextAvailable(AbstractGraphicsDevice sharedDevice) {
-    boolean madeCurrent = false;
-    GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP);
-    if (null == glp) {
-        throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
-    }    
-    final GLCapabilities caps = new GLCapabilities(glp);
-    caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
-    caps.setDoubleBuffered(false);
-    caps.setOnscreen(false);
-    caps.setPBuffer(true);
-    final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );        
-    if(null!=drawable) {
-        final GLContext context = drawable.createContext(null);
-        if (null != context) {
-            context.setSynchronized(true);
-            try {
-                context.makeCurrent(); // could cause exception
-                madeCurrent = context.isCurrent();
-            } catch (GLException gle) {
-                if (DEBUG) {
-                    System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent failed");
-                    gle.printStackTrace();
-                }
-            } finally {
-                context.destroy();
-            }
-        }
-        drawable.destroy();
-    }
-    return madeCurrent;
+  private HashSet<String> devicesTried = new HashSet<String>();
+
+  private boolean getDeviceTried(String connection) {
+      synchronized (devicesTried) {
+          return devicesTried.contains(connection);
+      }
+  }
+  private void addDeviceTried(String connection) {
+      synchronized (devicesTried) {
+          devicesTried.add(connection);
+      }
+  }
+  private void removeDeviceTried(String connection) {
+      synchronized (devicesTried) {
+          devicesTried.remove(connection);
+      }
   }
   
   /* package */ SharedResource getOrCreateOSXSharedResource(AbstractGraphicsDevice adevice) {
-    String connection = adevice.getConnection();
+    final String connection = adevice.getConnection();
     SharedResource sr;
     synchronized(sharedMap) {
-        sr = (SharedResource) sharedMap.get(connection);
+        sr = sharedMap.get(connection);
     }
-    if(null==sr) {
+    if(null==sr && !getDeviceTried(connection)) {
+        addDeviceTried(connection);
         final MacOSXGraphicsDevice sharedDevice = new MacOSXGraphicsDevice(adevice.getUnitID());
-        final boolean madeCurrent = isOSXContextAvailable(sharedDevice);
-        sr = new SharedResource(sharedDevice, madeCurrent);
+        boolean madeCurrent = false;
+        boolean hasNPOTTextures = false;
+        boolean hasRECTTextures = false;
+        boolean hasAppletFloatPixels = false;
+        {
+            GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP);
+            if (null == glp) {
+                throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
+            }    
+            final GLCapabilities caps = new GLCapabilities(glp);
+            caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
+            caps.setDoubleBuffered(false);
+            caps.setOnscreen(false);
+            caps.setPBuffer(true);
+            final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );        
+            if(null!=drawable) {
+                final GLContext context = drawable.createContext(null);
+                if (null != context) {
+                    context.setSynchronized(true);
+                    try {
+                        context.makeCurrent(); // could cause exception
+                        madeCurrent = context.isCurrent();
+                        if(madeCurrent) {
+                            GL gl = context.getGL();
+                            hasNPOTTextures = gl.isNPOTTextureAvailable();
+                            hasRECTTextures = gl.isExtensionAvailable("GL_EXT_texture_rectangle");
+                            hasAppletFloatPixels = gl.isExtensionAvailable("GL_APPLE_float_pixels");
+                        }
+                    } catch (GLException gle) {
+                        if (DEBUG) {
+                            System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent failed");
+                            gle.printStackTrace();
+                        }
+                    } finally {
+                        context.destroy();
+                    }
+                }
+                drawable.destroy();
+            }
+        }
+        sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppletFloatPixels);
         synchronized(sharedMap) {
             sharedMap.put(connection, sr);
         }
+        removeDeviceTried(connection);
         if (DEBUG) {
             System.err.println("MacOSXCGLDrawableFactory.createShared: device:  " + sharedDevice);
             System.err.println("MacOSXCGLDrawableFactory.createShared: context: " + madeCurrent);
@@ -231,7 +269,11 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
               return r.isLayeredSurface() ? r : null;
           } else {
               // parent surface host, eg. via native parenting w/ NewtCanvasAWT
-              final NativeWindow nwParent = nwThis.getParent();
+              NativeWindow nwParent = nwThis.getParent();
+              if(null != nwParent && nwParent instanceof NativeWindowHolder) {
+                  NativeWindowHolder nwh = (NativeWindowHolder) nwParent;
+                  nwParent = nwh.getNativeWindow();
+              }
               if(null != nwParent && nwParent instanceof MacOSXJAWTWindow) {
                   final MacOSXJAWTWindow r = (MacOSXJAWTWindow) nwParent;
                   return r.isLayeredSurface() ? r : null;
@@ -250,10 +292,8 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
         // layered surface -> PBuffer
         final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) target.getGraphicsConfiguration().getNativeGraphicsConfiguration();
         final GLCapabilities chosenCaps = (GLCapabilities) config.getChosenCapabilities().cloneMutable();
-        // chosenCaps.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN
         chosenCaps.setOnscreen(false);
         chosenCaps.setPBuffer(true);
-        // chosenCaps.setPbufferRenderToTextureRectangle(true);
         config.setChosenCapabilities(chosenCaps);
         return new MacOSXPbufferCGLDrawable(this, target, false);
     }
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index 5f511c505..c29a5f9b5 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -54,7 +54,7 @@ import javax.media.opengl.GLProfile;
 import jogamp.opengl.Debug;
 
 import com.jogamp.common.nio.PointerBuffer;
-
+import com.jogamp.opengl.util.GLBuffers;
 
 public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
   private static final boolean DEBUG = Debug.debug("MacOSXPbufferCGLDrawable");
@@ -76,6 +76,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
   // Note that we can not store this in the NativeSurface because the
   // semantic is that contains an NSView
   protected long pBuffer;
+  protected int pBufferTexTarget, pBufferTexWidth, pBufferTexHeight;
 
   public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeSurface target, boolean realizeNow) {
     super(factory, target, false);
@@ -122,6 +123,10 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
     return pBuffer;
   }
   
+  protected int getTextureTarget() { return pBufferTexTarget;  }
+  protected int getTextureWidth() { return pBufferTexWidth; }
+  protected int getTextureHeight() { return pBufferTexHeight; }
+    
   protected void destroyPbuffer() {
     if (this.pBuffer != 0) {
       NativeSurface ns = getNativeSurface();
@@ -132,65 +137,49 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
   }
 
   private void createPbuffer() {
-    NativeSurface ns = getNativeSurface();
-    DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration();
-    GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities();
-    GLProfile glProfile = capabilities.getGLProfile();
-    final int w, h;
-    int renderTarget;
-    if (glProfile.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle()) {
-      w = getWidth();
-      h = getHeight();
-      renderTarget = GL2.GL_TEXTURE_RECTANGLE;
+    final NativeSurface ns = getNativeSurface();
+    final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration();
+    final GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+    final GLProfile glProfile = capabilities.getGLProfile();
+    MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice());
+    
+    if ( capabilities.getPbufferRenderToTextureRectangle() && null!=sr && sr.isRECTTextureAvailable() ) {
+      pBufferTexTarget = GL2.GL_TEXTURE_RECTANGLE;
+    } else {
+      pBufferTexTarget = GL.GL_TEXTURE_2D;
+    }
+    if ( GL2.GL_TEXTURE_RECTANGLE == pBufferTexTarget || ( null!=sr && sr.isNPOTTextureAvailable() ) ) { 
+      pBufferTexWidth = getWidth();
+      pBufferTexHeight = getHeight();
     } else {
-      w = getNextPowerOf2(getWidth());
-      h = getNextPowerOf2(getHeight());
-      // FIXME - JAU: ((SurfaceChangeable)ns).setSize(w, h); // can't do that, removed orig size
-      renderTarget = GL.GL_TEXTURE_2D;
+      pBufferTexWidth = GLBuffers.getNextPowerOf2(getWidth());
+      pBufferTexHeight = GLBuffers.getNextPowerOf2(getHeight());
     }
 
     int internalFormat = GL.GL_RGBA;
     if (capabilities.getPbufferFloatingPointBuffers()) {
-      // FIXME: want to check availability of GL_APPLE_float_pixels
-      // extension, but need valid OpenGL context in order to do so --
-      // in worst case would need to create dummy window / GLCanvas
-      // (undesirable) -- could maybe also do this with pbuffers
-      /*
-        if (!gl.isExtensionAvailable("GL_APPLE_float_pixels")) {
-        throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available");
-        }
-      */
-      if(glProfile.isGL2GL3()) {
-        switch (capabilities.getRedBits()) {
+      if(!glProfile.isGL2GL3() || null==sr || sr.isAppletFloatPixelsAvailable()) {
+          throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available");
+      }
+      switch (capabilities.getRedBits()) {
         case 16: internalFormat = GL2.GL_RGBA_FLOAT16_APPLE; break;
         case 32: internalFormat = GL2.GL_RGBA_FLOAT32_APPLE; break;
         default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)");
-        }
-      } else {
-        internalFormat = GL.GL_RGBA;
       }
     }
-            
-    pBuffer = impl.create(renderTarget, internalFormat, w, h);
+    
+    pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight());
+    if(DEBUG) {
+        System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+
+                            ", size "+toHexString(pBufferTexWidth)+"x"+toHexString(pBufferTexHeight)+
+                            ", internal-fmt "+toHexString(internalFormat));
+        System.err.println("MacOSXPbufferCGLDrawable pBuffer: "+toHexString(pBuffer));
+    }
     if (pBuffer == 0) {
       throw new GLException("pbuffer creation error: CGL.createPBuffer() failed");
     }
 
     ((SurfaceChangeable)ns).setSurfaceHandle(pBuffer);
-
-  }
-
-  private int getNextPowerOf2(int number) {
-    if (((number-1) & number) == 0) {
-      //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0
-      return number;
-    }
-    int power = 0;
-    while (number > 0) {
-      number = number>>1;
-      power++;
-    }
-    return (1<<power);
   }
 
   public void setOpenGLMode(GLBackendType mode) {
-- 
cgit v1.2.3