diff options
author | Kenneth Russel <[email protected]> | 2006-02-11 01:11:57 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2006-02-11 01:11:57 +0000 |
commit | 8ebdef6860e34bf16b9b13c657f651bf9ce32ab3 (patch) | |
tree | e1b51b0c8cacf3987f219b2e992af089aea5d1b4 /src/classes/com/sun/opengl/impl/Java2D.java | |
parent | b75d4a3718b1a5744218e19c4f5c1a9ff0311f34 (diff) |
Further work on FBO support in Java2D/JOGL bridge. Upgraded JOGL's
Java2D class to latest proposed set of APIs in OGLUtilities and
changed usage of these APIs to be approximately correct. Left in
fallback path for working with non-FBO case in current Mustang builds.
Not working yet, and don't yet understand why; checking in at this
intermediate point to be able to more easily test on more machines.
Added error checking to creation of external GLContexts and
GLDrawables on Windows and X11 platforms.
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@597 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/classes/com/sun/opengl/impl/Java2D.java')
-rwxr-xr-x | src/classes/com/sun/opengl/impl/Java2D.java | 193 |
1 files changed, 140 insertions, 53 deletions
diff --git a/src/classes/com/sun/opengl/impl/Java2D.java b/src/classes/com/sun/opengl/impl/Java2D.java index cf9e8ff1e..bf3219b77 100755 --- a/src/classes/com/sun/opengl/impl/Java2D.java +++ b/src/classes/com/sun/opengl/impl/Java2D.java @@ -53,13 +53,27 @@ public class Java2D { private static boolean DEBUG = Debug.debug("Java2D"); private static boolean VERBOSE = Debug.verbose(); private static boolean isOGLPipelineActive; - private static boolean isFBOEnabled; private static Method invokeWithOGLContextCurrentMethod; private static Method isQueueFlusherThreadMethod; private static Method getOGLViewportMethod; private static Method getOGLScissorBoxMethod; private static Method getOGLSurfaceIdentifierMethod; + // The following methods and fields are needed for proper support of + // Frame Buffer Objects in the Java2D/OpenGL pipeline + // (-Dsun.java2d.opengl.fbobject=true) + private static boolean fbObjectSupportInitialized; + private static Method invokeWithOGLSharedContextCurrentMethod; + private static Method getOGLSurfaceTypeMethod; + + // Publicly-visible constants for OpenGL surface types + public static final int UNDEFINED = getOGLUtilitiesIntField("UNDEFINED"); + public static final int WINDOW = getOGLUtilitiesIntField("WINDOW"); + public static final int PBUFFER = getOGLUtilitiesIntField("PBUFFER"); + public static final int TEXTURE = getOGLUtilitiesIntField("TEXTURE"); + public static final int FLIP_BACKBUFFER = getOGLUtilitiesIntField("FLIP_BACKBUFFER"); + public static final int FBOBJECT = getOGLUtilitiesIntField("FBOBJECT"); + // If FBOs are enabled in the Java2D/OpenGL pipeline, all contexts // created by JOGL must share textures and display lists with the // Java2D contexts in order to access the frame buffer object for @@ -69,7 +83,7 @@ public class Java2D { // (on the same display device?) share textures and display lists; // this is an approximation to that notion which will be refined // later. - private static VolatileImage j2dFBOVolatileImage; // just a dummy image + private static boolean initializedJ2DFBOShareContext; private static GLContext j2dFBOShareContext; static { @@ -125,11 +139,32 @@ public class Java2D { }); getOGLSurfaceIdentifierMethod.setAccessible(true); - String fbo = System.getProperty("sun.java2d.opengl.fbobject"); - isFBOEnabled = (fbo != null) && "true".equals(fbo); + // Try to get additional methods required for proper FBO support + fbObjectSupportInitialized = true; + try { + invokeWithOGLSharedContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLSharedContextCurrent", + new Class[] { + GraphicsConfiguration.class, + Runnable.class + }); + invokeWithOGLSharedContextCurrentMethod.setAccessible(true); + + getOGLSurfaceTypeMethod = utils.getDeclaredMethod("getOGLSurfaceType", + new Class[] { + Graphics.class + }); + getOGLSurfaceTypeMethod.setAccessible(true); + } catch (Exception e) { + fbObjectSupportInitialized = false; + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("Disabling Java2D/JOGL FBO support"); + } + } } catch (Exception e) { if (DEBUG && VERBOSE) { e.printStackTrace(); + System.err.println("Disabling Java2D/JOGL integration"); } isOGLPipelineActive = false; } @@ -148,13 +183,11 @@ public class Java2D { } public static boolean isFBOEnabled() { - return isFBOEnabled; + return fbObjectSupportInitialized; } public static boolean isQueueFlusherThread() { - if (!isOGLPipelineActive()) { - throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); - } + checkActive(); try { return ((Boolean) isQueueFlusherThreadMethod.invoke(null, new Object[] {})).booleanValue(); @@ -169,9 +202,7 @@ public class Java2D { Graphics object and runs the given Runnable on the Queue Flushing Thread in one atomic action. */ public static void invokeWithOGLContextCurrent(Graphics g, Runnable r) throws GLException { - if (!isOGLPipelineActive()) { - throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); - } + checkActive(); try { GLDrawableFactoryImpl.getFactoryImpl().lockAWTForJava2D(); @@ -187,6 +218,31 @@ public class Java2D { } } + /** Makes current the "shared" OpenGL context associated with the + given GraphicsConfiguration object, allowing JOGL to share + server-side OpenGL objects like textures and display lists with + this context when necessary. This is needed when Java2D's FBO + support is enabled, because in order to render into that FBO, + JOGL must share textures and display lists with it. Returns + false if the passed GraphicsConfiguration was not an OpenGL + GraphicsConfiguration. */ + public static boolean invokeWithOGLSharedContextCurrent(GraphicsConfiguration g, Runnable r) throws GLException { + checkActive(); + + try { + GLDrawableFactoryImpl.getFactoryImpl().lockAWTForJava2D(); + try { + return ((Boolean) invokeWithOGLSharedContextCurrentMethod.invoke(null, new Object[] {g, r})).booleanValue(); + } finally { + GLDrawableFactoryImpl.getFactoryImpl().unlockAWTForJava2D(); + } + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + /** Returns the OpenGL viewport associated with the given Graphics object, assuming that the Graphics object is associated with a component of the specified width and height. The user should @@ -196,9 +252,7 @@ public class Java2D { public static Rectangle getOGLViewport(Graphics g, int componentWidth, int componentHeight) { - if (!isOGLPipelineActive()) { - throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); - } + checkActive(); try { return (Rectangle) getOGLViewportMethod.invoke(null, new Object[] {g, @@ -218,9 +272,7 @@ public class Java2D { passed to a call to glScissor(). Should only be called from the Queue Flusher Thread. */ public static Rectangle getOGLScissorBox(Graphics g) { - if (!isOGLPipelineActive()) { - throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); - } + checkActive(); try { return (Rectangle) getOGLScissorBoxMethod.invoke(null, new Object[] {g}); @@ -238,9 +290,7 @@ public class Java2D { created (and the old ones destroyed). Should only be called from the Queue Flusher Thread.*/ public static Object getOGLSurfaceIdentifier(Graphics g) { - if (!isOGLPipelineActive()) { - throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); - } + checkActive(); try { return getOGLSurfaceIdentifierMethod.invoke(null, new Object[] {g}); @@ -251,6 +301,27 @@ public class Java2D { } } + /** Returns the underlying surface type for the given Graphics + object. This indicates, in particular, whether Java2D is + currently rendering into a pbuffer or FBO. */ + public static int getOGLSurfaceType(Graphics g) { + checkActive(); + + try { + // FIXME: fallback path for pre-b73 (?) Mustang builds -- remove + // once fbobject support is in OGLUtilities + if (!fbObjectSupportInitialized) { + return 0; + } + + return ((Integer) getOGLSurfaceTypeMethod.invoke(null, new Object[] { g })).intValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + /** Returns either the given GLContext or a substitute one with which clients should share textures and display lists. Needed when the Java2D/OpenGL pipeline is active and FBOs are being @@ -258,7 +329,11 @@ public class Java2D { future to indicate which GraphicsDevice the source context is associated with. */ public static GLContext filterShareContext(GLContext shareContext) { - initFBOShareContext(); + // FIXME: this may need adjustment + initFBOShareContext(GraphicsEnvironment. + getLocalGraphicsEnvironment(). + getDefaultScreenDevice(). + getDefaultConfiguration()); if (j2dFBOShareContext != null) { return j2dFBOShareContext; } @@ -269,8 +344,10 @@ public class Java2D { context", with which all contexts created by JOGL must share textures and display lists when the FBO option is enabled for the Java2D/OpenGL pipeline. */ - public static GLContext getShareContext() { - initFBOShareContext(); + public static GLContext getShareContext(GraphicsConfiguration gc) { + initFBOShareContext(gc); + // FIXME: for full generality probably need to have multiple of + // these, one per GraphicsConfiguration seen? return j2dFBOShareContext; } @@ -278,44 +355,54 @@ public class Java2D { // Internals only below this point // - private static void initFBOShareContext() { + private static void checkActive() { + if (!isOGLPipelineActive()) { + throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); + } + } + + private static int getOGLUtilitiesIntField(final String name) { + Integer i = (Integer) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class utils = Class.forName("sun.java2d.opengl.OGLUtilities"); + Field f = utils.getField(name); + f.setAccessible(true); + return f.get(null); + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + } + return null; + } + } + }); + if (i == null) + return 0; + if (DEBUG && VERBOSE) { + System.err.println("OGLUtilities." + name + " = " + i.intValue()); + } + return i.intValue(); + } + + private static void initFBOShareContext(final GraphicsConfiguration gc) { // Note 1: this must not be done in the static initalizer due to // deadlock problems. // Note 2: the first execution of this method must not be from the // Java2D Queue Flusher Thread. - // Note that at this point it's basically impossible that we're - // executing on the Queue Flusher Thread since all calls (even - // from end users) should be going through this interface and - // we're still in the static initializer if (isOGLPipelineActive() && isFBOEnabled() && - j2dFBOVolatileImage == null) { - // Create a compatible VolatileImage (FIXME: may need one per - // display device, and may need to create them lazily, which may - // cause problems) and create a JOGL GLContext to wrap its - // GLContext. - // - // FIXME: this technique is not really adequate. The - // VolatileImage may be punted at any time, meaning that its - // OpenGL context will be destroyed and any shares of - // server-side objects with it will be gone. This context is - // currently the "pinch point" through which all of the shares - // with the set of contexts created by JOGL go through. Java2D - // has the notion of its own share context with which all of the - // contexts it creates internally share server-side objects; - // what is really needed is another API in OGLUtilities to - // invoke a Runnable with that share context current rather than - // the context associated with a particular Graphics object, so - // that JOGL can grab a handle to that persistent context. - j2dFBOVolatileImage = - GraphicsEnvironment. - getLocalGraphicsEnvironment(). - getDefaultScreenDevice(). - getDefaultConfiguration(). - createCompatibleVolatileImage(2, 2); - invokeWithOGLContextCurrent(j2dFBOVolatileImage.getGraphics(), new Runnable() { + !initializedJ2DFBOShareContext) { + + // FIXME: this technique is probably not adequate in multi-head + // situations. Ideally we would keep track of a given share + // context on a per-GraphicsConfiguration basis or something + // similar rather than keeping one share context in a global + // variable. + initializedJ2DFBOShareContext = true; + invokeWithOGLSharedContextCurrent(gc, new Runnable() { public void run() { j2dFBOShareContext = GLDrawableFactory.getFactory().createExternalGLContext(); } |