aboutsummaryrefslogtreecommitdiffstats
path: root/src/classes/com/sun/opengl/impl
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes/com/sun/opengl/impl')
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextImpl.java48
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextShareSet.java55
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/GLObjectTracker.java730
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/Java2D.java8
-rw-r--r--src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java2
5 files changed, 834 insertions, 9 deletions
diff --git a/src/classes/com/sun/opengl/impl/GLContextImpl.java b/src/classes/com/sun/opengl/impl/GLContextImpl.java
index 1eb121b1b..5dbf08df6 100644
--- a/src/classes/com/sun/opengl/impl/GLContextImpl.java
+++ b/src/classes/com/sun/opengl/impl/GLContextImpl.java
@@ -58,11 +58,15 @@ public abstract class GLContextImpl extends GLContext {
// OpenGL functions.
private GLProcAddressTable glProcAddressTable;
+ // Tracks creation and deletion of server-side OpenGL objects when
+ // the Java2D/OpenGL pipeline is active and using FBOs to render
+ private GLObjectTracker tracker;
+
protected GL gl;
public GLContextImpl(GLContext shareWith) {
setGL(createGL());
functionAvailability = new FunctionAvailabilityCache(this);
- if (shareWith != null) {
+ if (shareWith != null || GLContextShareSet.isObjectTrackingDebuggingEnabled()) {
GLContextShareSet.registerSharing(this, shareWith);
}
}
@@ -72,6 +76,11 @@ public abstract class GLContextImpl extends GLContext {
int res = 0;
try {
res = makeCurrentImpl();
+ if ((tracker != null) &&
+ (res == CONTEXT_CURRENT_NEW)) {
+ // Increase reference count of GLObjectTracker
+ tracker.ref();
+ }
} catch (GLException e) {
lock.unlock();
throw(e);
@@ -104,8 +113,27 @@ public abstract class GLContextImpl extends GLContext {
if (lock.isHeld()) {
throw new GLException("Can not destroy context while it is current");
}
- // Should we check the lock state? It should not be current on any
- // thread.
+
+ if (tracker != null) {
+ // Don't need to do anything for contexts that haven't been
+ // created yet
+ if (isCreated()) {
+ // If we are tracking creation and destruction of server-side
+ // OpenGL objects, we must decrement the reference count of the
+ // GLObjectTracker upon context destruction.
+ int res = makeCurrent();
+ if (res != CONTEXT_CURRENT) {
+ // FIXME: we really need to behave better than this
+ throw new GLException("Unable to make context current to destroy tracked server-side OpenGL objects");
+ }
+ try {
+ tracker.unref(getGL());
+ } finally {
+ release();
+ }
+ }
+ }
+
destroyImpl();
}
@@ -135,7 +163,11 @@ public abstract class GLContextImpl extends GLContext {
/** Create the GL for this context. */
protected GL createGL() {
- return new GLImpl(this);
+ GLImpl gl = new GLImpl(this);
+ if (tracker != null) {
+ gl.setObjectTracker(tracker);
+ }
+ return gl;
}
public GLProcAddressTable getGLProcAddressTable() {
@@ -267,4 +299,12 @@ public abstract class GLContextImpl extends GLContext {
public static String toHexString(long hex) {
return "0x" + Long.toHexString(hex);
}
+
+ public void setObjectTracker(GLObjectTracker tracker) {
+ this.tracker = tracker;
+ }
+
+ public GLObjectTracker getObjectTracker() {
+ return tracker;
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/GLContextShareSet.java b/src/classes/com/sun/opengl/impl/GLContextShareSet.java
index a797ae69c..b0d1b1da4 100644
--- a/src/classes/com/sun/opengl/impl/GLContextShareSet.java
+++ b/src/classes/com/sun/opengl/impl/GLContextShareSet.java
@@ -48,11 +48,13 @@ import javax.media.opengl.*;
context creation as is inherent in the AWT and Swing. */
public class GLContextShareSet {
+ private static boolean forceTracking = Debug.isPropertyDefined("jogl.glcontext.forcetracking");
+
// This class is implemented with a WeakHashMap that goes from the
// contexts as keys to a complex data structure as value that tracks
// context creation and deletion.
- private static Map/*<GLContext, WeakReference<ShareSet>>*/ shareMap = new WeakHashMap();
+ private static Map/*<GLContext, ShareSet>*/ shareMap = new WeakHashMap();
private static Object dummyValue = new Object();
private static class ShareSet {
@@ -60,6 +62,17 @@ public class GLContextShareSet {
private Map createdShares = new WeakHashMap();
private Map destroyedShares = new WeakHashMap();
+ // When the Java2D/OpenGL pipeline is active and using FBOs to
+ // render, we need to track the creation and destruction of
+ // server-side OpenGL objects among contexts sharing these objects
+ private GLObjectTracker tracker;
+
+ public ShareSet() {
+ if (isObjectTrackingEnabled()) {
+ tracker = new GLObjectTracker();
+ }
+ }
+
public void add(GLContext ctx) {
if (allShares.put(ctx, dummyValue) == null) {
// FIXME: downcast to GLContextImpl undesirable
@@ -98,23 +111,57 @@ public class GLContextShareSet {
assert res == null : "State of ShareSet corrupted; thought context " +
ctx + " shouldn't have been in destroyed set but was";
}
+
+ public GLObjectTracker getObjectTracker() {
+ return tracker;
+ }
+ }
+
+ private static boolean isObjectTrackingEnabled() {
+ return (Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled());
}
+ /** Indicates to callers whether sharing must be registered even for
+ contexts which don't share textures and display lists with any
+ others. */
+ public static boolean isObjectTrackingDebuggingEnabled() {
+ return forceTracking;
+ }
/** Indicate that contexts <code>share1</code> and
<code>share2</code> will share textures and display lists. */
public static synchronized void registerSharing(GLContext share1, GLContext share2) {
ShareSet share = entryFor(share1);
- if (share == null) {
+ if (share == null && (share2 != null)) {
share = entryFor(share2);
}
if (share == null) {
share = new ShareSet();
}
share.add(share1);
- share.add(share2);
+ if (share2 != null) {
+ share.add(share2);
+ }
addEntry(share1, share);
- addEntry(share2, share);
+ if (share2 != null) {
+ addEntry(share2, share);
+ }
+ GLObjectTracker tracker = share.getObjectTracker();
+ if (tracker != null) {
+ // FIXME: downcast to GLContextImpl undesirable
+ GLContextImpl impl1 = (GLContextImpl) share1;
+ GLContextImpl impl2 = (GLContextImpl) share2;
+ if (impl1.getObjectTracker() == null) {
+ impl1.setObjectTracker(tracker);
+ }
+ if ((impl2 != null) && (impl2.getObjectTracker() == null)) {
+ impl2.setObjectTracker(tracker);
+ }
+ assert impl1.getObjectTracker() == tracker : "State of ShareSet corrupted; " +
+ "got different-than-expected GLObjectTracker for context 1";
+ assert (impl2 == null) || (impl2.getObjectTracker() == tracker) : "State of ShareSet corrupted; " +
+ "got different-than-expected GLObjectTracker for context 2";
+ }
}
public static synchronized GLContext getShareContext(GLContext contextToCreate) {
diff --git a/src/classes/com/sun/opengl/impl/GLObjectTracker.java b/src/classes/com/sun/opengl/impl/GLObjectTracker.java
new file mode 100755
index 000000000..663a7df70
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/GLObjectTracker.java
@@ -0,0 +1,730 @@
+/*
+ * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.sun.opengl.impl;
+
+import java.nio.*;
+import javax.media.opengl.*;
+
+/**
+ * Tracks the creation of server-side OpenGL objects which can be
+ * shared between contexts. Ordinarily, when an OpenGL context is
+ * deleted and no other contexts are sharing server-side objects with
+ * it, all of the server-side objects are automatically deleted by the
+ * OpenGL implementation. It is not necessary for the end user to
+ * explicitly delete these objects. However, when the Java2D/OpenGL
+ * pipeline is active and frame buffer objects are being used for
+ * rendering, it is necessary for all OpenGL contexts created by JOGL
+ * to share server-side objects with the Java2D OpenGL context. This
+ * means that these objects "leak" into the namespace used by Java2D.
+ * In order to prevent memory leaks and to present the same
+ * programming model to the end user, it is necessary to track the
+ * creation and destruction of all of these server-side OpenGL objects
+ * and to explicitly release them when all of the JOGL-created
+ * contexts which can see them have been released. <P>
+ *
+ * The {@link #ref ref} and {@link #unref unref} methods should be
+ * used during the creation and destruction of OpenGL contexts by JOGL
+ * in order to update the liveness of the objects being tracked. The
+ * various other methods should be called by the OpenGL binding in the
+ * various named methods.
+ */
+
+public class GLObjectTracker {
+ private static final boolean DEBUG = Debug.debug("GLObjectTracker");
+
+ //----------------------------------------------------------------------
+ // Adders
+ //
+
+ // glGenBuffers
+ public synchronized void addBuffers(int n, IntBuffer ids) {
+ add(getList(BUFFERS), n, ids);
+ }
+
+ // glGenBuffers
+ public synchronized void addBuffers(int n, int[] ids, int ids_offset) {
+ add(getList(BUFFERS), n, ids, ids_offset);
+ }
+
+ // glGenBuffersARB
+ public synchronized void addBuffersARB(int n, IntBuffer ids) {
+ add(getList(BUFFERS_ARB), n, ids);
+ }
+
+ // glGenBuffersARB
+ public synchronized void addBuffersARB(int n, int[] ids, int ids_offset) {
+ add(getList(BUFFERS_ARB), n, ids, ids_offset);
+ }
+
+ // glGenFencesAPPLE
+ public synchronized void addFencesAPPLE(int n, IntBuffer ids) {
+ add(getList(FENCES_APPLE), n, ids);
+ }
+
+ // glGenFencesAPPLE
+ public synchronized void addFencesAPPLE(int n, int[] ids, int ids_offset) {
+ add(getList(FENCES_APPLE), n, ids, ids_offset);
+ }
+
+ // glGenFencesNV
+ public synchronized void addFencesNV(int n, IntBuffer ids) {
+ add(getList(FENCES_NV), n, ids);
+ }
+
+ // glGenFencesNV
+ public synchronized void addFencesNV(int n, int[] ids, int ids_offset) {
+ add(getList(FENCES_NV), n, ids, ids_offset);
+ }
+
+ // glGenFragmentShadersATI
+ public synchronized void addFragmentShadersATI(int start, int n) {
+ add(getList(FRAGMENT_SHADERS_ATI), start, n);
+ }
+
+ // glGenFramebuffersEXT
+ public synchronized void addFramebuffersEXT(int n, IntBuffer ids) {
+ add(getList(FRAMEBUFFERS_EXT), n, ids);
+ }
+
+ // glGenFramebuffersEXT
+ public synchronized void addFramebuffersEXT(int n, int[] ids, int ids_offset) {
+ add(getList(FRAMEBUFFERS_EXT), n, ids, ids_offset);
+ }
+
+ // glGenLists
+ public synchronized void addLists(int start, int n) {
+ add(getList(LISTS), start, n);
+ }
+
+ // glGenOcclusionQueriesNV
+ public synchronized void addOcclusionQueriesNV(int n, IntBuffer ids) {
+ add(getList(OCCLUSION_QUERIES_NV), n, ids);
+ }
+
+ // glGenOcclusionQueriesNV
+ public synchronized void addOcclusionQueriesNV(int n, int[] ids, int ids_offset) {
+ add(getList(OCCLUSION_QUERIES_NV), n, ids, ids_offset);
+ }
+
+ // glCreateProgram
+ public synchronized void addProgramObject(int obj) {
+ add(getList(PROGRAM_OBJECTS), obj, 1);
+ }
+
+ // glCreateProgramObjectARB
+ public synchronized void addProgramObjectARB(int obj) {
+ add(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1);
+ }
+
+ // glGenProgramsARB
+ public synchronized void addProgramsARB(int n, IntBuffer ids) {
+ add(getList(PROGRAMS_ARB), n, ids);
+ }
+
+ // glGenProgramsARB
+ public synchronized void addProgramsARB(int n, int[] ids, int ids_offset) {
+ add(getList(PROGRAMS_ARB), n, ids, ids_offset);
+ }
+
+ // glGenProgramsNV
+ public synchronized void addProgramsNV(int n, IntBuffer ids) {
+ add(getList(PROGRAMS_NV), n, ids);
+ }
+
+ // glGenProgramsNV
+ public synchronized void addProgramsNV(int n, int[] ids, int ids_offset) {
+ add(getList(PROGRAMS_NV), n, ids, ids_offset);
+ }
+
+ // glGenQueries
+ public synchronized void addQueries(int n, IntBuffer ids) {
+ add(getList(QUERIES), n, ids);
+ }
+
+ // glGenQueries
+ public synchronized void addQueries(int n, int[] ids, int ids_offset) {
+ add(getList(QUERIES), n, ids, ids_offset);
+ }
+
+ // glGenQueriesARB
+ public synchronized void addQueriesARB(int n, IntBuffer ids) {
+ add(getList(QUERIES_ARB), n, ids);
+ }
+
+ // glGenQueriesARB
+ public synchronized void addQueriesARB(int n, int[] ids, int ids_offset) {
+ add(getList(QUERIES_ARB), n, ids, ids_offset);
+ }
+
+ // glGenRenderbuffersEXT
+ public synchronized void addRenderbuffersEXT(int n, IntBuffer ids) {
+ add(getList(RENDERBUFFERS_EXT), n, ids);
+ }
+
+ // glGenRenderbuffersEXT
+ public synchronized void addRenderbuffersEXT(int n, int[] ids, int ids_offset) {
+ add(getList(RENDERBUFFERS_EXT), n, ids, ids_offset);
+ }
+
+ // glCreateShader
+ public synchronized void addShaderObject(int obj) {
+ add(getList(SHADER_OBJECTS), obj, 1);
+ }
+
+ // glCreateShaderObjectARB
+ public synchronized void addShaderObjectARB(int obj) {
+ add(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1);
+ }
+
+ // glGenTextures
+ public synchronized void addTextures(int n, IntBuffer ids) {
+ add(getList(TEXTURES), n, ids);
+ }
+
+ // glGenTextures
+ public synchronized void addTextures(int n, int[] ids, int ids_offset) {
+ add(getList(TEXTURES), n, ids, ids_offset);
+ }
+
+ // glGenVertexArraysAPPLE
+ public synchronized void addVertexArraysAPPLE(int n, IntBuffer ids) {
+ add(getList(VERTEX_ARRAYS_APPLE), n, ids);
+ }
+
+ // glGenVertexArraysAPPLE
+ public synchronized void addVertexArraysAPPLE(int n, int[] ids, int ids_offset) {
+ add(getList(VERTEX_ARRAYS_APPLE), n, ids, ids_offset);
+ }
+
+ // glGenVertexShadersEXT
+ public synchronized void addVertexShadersEXT(int start, int n) {
+ add(getList(VERTEX_SHADERS_EXT), start, n);
+ }
+
+ //----------------------------------------------------------------------
+ // Removers
+ //
+
+ // glDeleteBuffers
+ public synchronized void removeBuffers(int n, IntBuffer ids) {
+ remove(getList(BUFFERS), n, ids);
+ }
+
+ // glDeleteBuffers
+ public synchronized void removeBuffers(int n, int[] ids, int ids_offset) {
+ remove(getList(BUFFERS), n, ids, ids_offset);
+ }
+
+ // glDeleteBuffersARB
+ public synchronized void removeBuffersARB(int n, IntBuffer ids) {
+ remove(getList(BUFFERS_ARB), n, ids);
+ }
+
+ // glDeleteBuffersARB
+ public synchronized void removeBuffersARB(int n, int[] ids, int ids_offset) {
+ remove(getList(BUFFERS_ARB), n, ids, ids_offset);
+ }
+
+ // glDeleteFencesAPPLE
+ public synchronized void removeFencesAPPLE(int n, IntBuffer ids) {
+ remove(getList(FENCES_APPLE), n, ids);
+ }
+
+ // glDeleteFencesAPPLE
+ public synchronized void removeFencesAPPLE(int n, int[] ids, int ids_offset) {
+ remove(getList(FENCES_APPLE), n, ids, ids_offset);
+ }
+
+ // glDeleteFencesNV
+ public synchronized void removeFencesNV(int n, IntBuffer ids) {
+ remove(getList(FENCES_NV), n, ids);
+ }
+
+ // glDeleteFencesNV
+ public synchronized void removeFencesNV(int n, int[] ids, int ids_offset) {
+ remove(getList(FENCES_NV), n, ids, ids_offset);
+ }
+
+ // glDeleteFragmentShaderATI
+ public synchronized void removeFragmentShaderATI(int obj) {
+ remove(getList(FRAGMENT_SHADERS_ATI), obj, 1);
+ }
+
+ // glDeleteFramebuffersEXT
+ public synchronized void removeFramebuffersEXT(int n, IntBuffer ids) {
+ remove(getList(FRAMEBUFFERS_EXT), n, ids);
+ }
+
+ // glDeleteFramebuffersEXT
+ public synchronized void removeFramebuffersEXT(int n, int[] ids, int ids_offset) {
+ remove(getList(FRAMEBUFFERS_EXT), n, ids, ids_offset);
+ }
+
+ // glDeleteLists
+ public synchronized void removeLists(int start, int n) {
+ remove(getList(LISTS), start, n);
+ }
+
+ // glDeleteOcclusionQueriesNV
+ public synchronized void removeOcclusionQueriesNV(int n, IntBuffer ids) {
+ remove(getList(OCCLUSION_QUERIES_NV), n, ids);
+ }
+
+ // glDeleteOcclusionQueriesNV
+ public synchronized void removeOcclusionQueriesNV(int n, int[] ids, int ids_offset) {
+ remove(getList(OCCLUSION_QUERIES_NV), n, ids, ids_offset);
+ }
+
+ // glDeleteProgram
+ public synchronized void removeProgramObject(int obj) {
+ remove(getList(PROGRAM_OBJECTS), obj, 1);
+ }
+
+ // glDeleteObjectARB
+ public synchronized void removeProgramOrShaderObjectARB(int obj) {
+ remove(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1);
+ }
+
+ // glDeleteProgramsARB
+ public synchronized void removeProgramsARB(int n, IntBuffer ids) {
+ remove(getList(PROGRAMS_ARB), n, ids);
+ }
+
+ // glDeleteProgramsARB
+ public synchronized void removeProgramsARB(int n, int[] ids, int ids_offset) {
+ remove(getList(PROGRAMS_ARB), n, ids, ids_offset);
+ }
+
+ // glDeleteProgramsNV
+ public synchronized void removeProgramsNV(int n, IntBuffer ids) {
+ remove(getList(PROGRAMS_NV), n, ids);
+ }
+
+ // glDeleteProgramsNV
+ public synchronized void removeProgramsNV(int n, int[] ids, int ids_offset) {
+ remove(getList(PROGRAMS_NV), n, ids, ids_offset);
+ }
+
+ // glDeleteQueries
+ public synchronized void removeQueries(int n, IntBuffer ids) {
+ remove(getList(QUERIES), n, ids);
+ }
+
+ // glDeleteQueries
+ public synchronized void removeQueries(int n, int[] ids, int ids_offset) {
+ remove(getList(QUERIES), n, ids, ids_offset);
+ }
+
+ // glDeleteQueriesARB
+ public synchronized void removeQueriesARB(int n, IntBuffer ids) {
+ remove(getList(QUERIES_ARB), n, ids);
+ }
+
+ // glDeleteQueriesARB
+ public synchronized void removeQueriesARB(int n, int[] ids, int ids_offset) {
+ remove(getList(QUERIES_ARB), n, ids, ids_offset);
+ }
+
+ // glDeleteRenderbuffersEXT
+ public synchronized void removeRenderbuffersEXT(int n, IntBuffer ids) {
+ remove(getList(RENDERBUFFERS_EXT), n, ids);
+ }
+
+ // glDeleteRenderbuffersEXT
+ public synchronized void removeRenderbuffersEXT(int n, int[] ids, int ids_offset) {
+ remove(getList(RENDERBUFFERS_EXT), n, ids, ids_offset);
+ }
+
+ // glDeleteShader
+ public synchronized void removeShaderObject(int obj) {
+ remove(getList(SHADER_OBJECTS), obj, 1);
+ }
+
+ // glDeleteTextures
+ public synchronized void removeTextures(int n, IntBuffer ids) {
+ remove(getList(TEXTURES), n, ids);
+ }
+
+ // glDeleteTextures
+ public synchronized void removeTextures(int n, int[] ids, int ids_offset) {
+ remove(getList(TEXTURES), n, ids, ids_offset);
+ }
+
+ // glDeleteVertexArraysAPPLE
+ public synchronized void removeVertexArraysAPPLE(int n, IntBuffer ids) {
+ remove(getList(VERTEX_ARRAYS_APPLE), n, ids);
+ }
+
+ // glDeleteVertexArraysAPPLE
+ public synchronized void removeVertexArraysAPPLE(int n, int[] ids, int ids_offset) {
+ remove(getList(VERTEX_ARRAYS_APPLE), n, ids, ids_offset);
+ }
+
+ // glDeleteVertexShaderEXT
+ public synchronized void removeVertexShaderEXT(int obj) {
+ remove(getList(VERTEX_SHADERS_EXT), obj, 1);
+ }
+
+ public synchronized void ref() {
+ ++refCount;
+ }
+
+ public synchronized void unref(GL gl) {
+ if (--refCount == 0) {
+ for (int i = 0; i < lists.length; i++) {
+ ObjectList list = lists[i];
+ if (list != null) {
+ list.delete(gl);
+ lists[i] = null;
+ }
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ // Kinds of sharable server-side OpenGL objects this class tracks
+ private static final int BUFFERS = 0;
+ private static final int BUFFERS_ARB = 1;
+ private static final int FENCES_APPLE = 2;
+ private static final int FENCES_NV = 3;
+ private static final int FRAGMENT_SHADERS_ATI = 4;
+ private static final int FRAMEBUFFERS_EXT = 5;
+ private static final int LISTS = 6;
+ private static final int OCCLUSION_QUERIES_NV = 7;
+ private static final int PROGRAM_AND_SHADER_OBJECTS_ARB = 8;
+ private static final int PROGRAM_OBJECTS = 9;
+ private static final int PROGRAMS_ARB = 10;
+ private static final int PROGRAMS_NV = 11;
+ private static final int QUERIES = 12;
+ private static final int QUERIES_ARB = 13;
+ private static final int RENDERBUFFERS_EXT = 14;
+ private static final int SHADER_OBJECTS = 15;
+ private static final int TEXTURES = 16;
+ private static final int VERTEX_ARRAYS_APPLE = 17;
+ private static final int VERTEX_SHADERS_EXT = 18;
+ private static final int NUM_OBJECT_TYPES = 19;
+
+ static abstract class Deleter {
+ public abstract void delete(GL gl, int obj);
+ }
+
+ static class ObjectList {
+ private static final int MIN_CAPACITY = 4;
+
+ private int size;
+ private int capacity;
+ private int[] data;
+ private Deleter deleter;
+ private String name;
+
+ public ObjectList(Deleter deleter) {
+ this.deleter = deleter;
+ capacity = MIN_CAPACITY;
+ data = new int[capacity];
+ }
+
+ public void add(int obj) {
+ if (size == capacity) {
+ int newCapacity = 2 * capacity;
+ int[] newData = new int[newCapacity];
+ System.arraycopy(data, 0, newData, 0, size);
+ data = newData;
+ capacity = newCapacity;
+ }
+
+ data[size++] = obj;
+ }
+
+ public boolean remove(int value) {
+ for (int i = 0; i < size; i++) {
+ if (data[i] == value) {
+ if (i < size - 1) {
+ System.arraycopy(data, i+1, data, i, size - i - 1);
+ }
+ --size;
+ if ((size < capacity / 4) &&
+ (capacity > MIN_CAPACITY)) {
+ int newCapacity = capacity / 4;
+ if (newCapacity < MIN_CAPACITY) {
+ newCapacity = MIN_CAPACITY;
+ }
+ int[] newData = new int[newCapacity];
+ System.arraycopy(data, 0, newData, 0, size);
+ data = newData;
+ capacity = newCapacity;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setName(String name) {
+ if (DEBUG) {
+ this.name = name;
+ }
+ }
+
+ public void delete(GL gl) {
+ for (int i = 0; i < size; i++) {
+ if (DEBUG) {
+ System.err.println("Deleting server-side OpenGL object " + data[i] +
+ ((name != null) ? (" (" + name + ")") : ""));
+ }
+ deleter.delete(gl, data[i]);
+ }
+ size = 0;
+ }
+ }
+
+ private ObjectList[] lists = new ObjectList[NUM_OBJECT_TYPES];
+ private int refCount;
+
+ private void add(ObjectList list, int n, IntBuffer ids) {
+ int pos = ids.position();
+ for (int i = 0; i < n; i++) {
+ list.add(ids.get(pos + i));
+ }
+ }
+
+ private void add(ObjectList list, int n, int[] ids, int ids_offset) {
+ for (int i = 0; i < n; i++) {
+ list.add(ids[i + ids_offset]);
+ }
+ }
+
+ private void add(ObjectList list, int start, int n) {
+ for (int i = 0; i < n; i++) {
+ list.add(start + i);
+ }
+ }
+
+ private void remove(ObjectList list, int n, IntBuffer ids) {
+ int pos = ids.position();
+ for (int i = 0; i < n; i++) {
+ list.remove(ids.get(pos + i));
+ }
+ }
+
+ private void remove(ObjectList list, int n, int[] ids, int ids_offset) {
+ for (int i = 0; i < n; i++) {
+ list.remove(ids[i + ids_offset]);
+ }
+ }
+
+ private void remove(ObjectList list, int start, int n) {
+ for (int i = 0; i < n; i++) {
+ list.remove(start + i);
+ }
+ }
+
+ private ObjectList getList(int which) {
+ ObjectList list = lists[which];
+ if (list == null) {
+ Deleter deleter = null;
+ String name = null;
+ // Figure out which deleter we need
+ switch (which) {
+ case BUFFERS:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteBuffers(1, new int[] { obj }, 0);
+ }
+ };
+ name = "buffer";
+ break;
+ case BUFFERS_ARB:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteBuffersARB(1, new int[] { obj }, 0);
+ }
+ };
+ name = "ARB buffer";
+ break;
+ case FENCES_APPLE:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteFencesAPPLE(1, new int[] { obj }, 0);
+ }
+ };
+ name = "APPLE fence";
+ break;
+ case FENCES_NV:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteFencesNV(1, new int[] { obj }, 0);
+ }
+ };
+ name = "NV fence";
+ break;
+ case FRAGMENT_SHADERS_ATI:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteFragmentShaderATI(obj);
+ }
+ };
+ name = "ATI fragment shader";
+ break;
+ case FRAMEBUFFERS_EXT:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteFramebuffersEXT(1, new int[] { obj }, 0);
+ }
+ };
+ name = "EXT framebuffer";
+ break;
+ case LISTS:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteLists(obj, 1);
+ }
+ };
+ name = "display list";
+ break;
+ case OCCLUSION_QUERIES_NV:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteOcclusionQueriesNV(1, new int[] { obj }, 0);
+ }
+ };
+ name = "NV occlusion query";
+ break;
+ case PROGRAM_AND_SHADER_OBJECTS_ARB:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteObjectARB(obj);
+ }
+ };
+ name = "ARB program or shader object";
+ break;
+ case PROGRAM_OBJECTS:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteProgram(obj);
+ }
+ };
+ name = "program object";
+ break;
+ case PROGRAMS_ARB:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteProgramsARB(1, new int[] { obj }, 0);
+ }
+ };
+ name = "ARB program object";
+ break;
+ case PROGRAMS_NV:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteProgramsNV(1, new int[] { obj }, 0);
+ }
+ };
+ name = "NV program";
+ break;
+ case QUERIES:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteQueries(1, new int[] { obj }, 0);
+ }
+ };
+ name = "query";
+ break;
+ case QUERIES_ARB:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteQueriesARB(1, new int[] { obj }, 0);
+ }
+ };
+ name = "ARB query";
+ break;
+ case RENDERBUFFERS_EXT:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteRenderbuffersEXT(1, new int[] { obj }, 0);
+ }
+ };
+ name = "EXT renderbuffer";
+ break;
+ case SHADER_OBJECTS:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteShader(obj);
+ }
+ };
+ name = "shader object";
+ break;
+ case TEXTURES:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteTextures(1, new int[] { obj }, 0);
+ }
+ };
+ name = "texture";
+ break;
+ case VERTEX_ARRAYS_APPLE:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteVertexArraysAPPLE(1, new int[] { obj }, 0);
+ }
+ };
+ name = "APPLE vertex array";
+ break;
+ case VERTEX_SHADERS_EXT:
+ deleter = new Deleter() {
+ public void delete(GL gl, int obj) {
+ gl.glDeleteVertexShaderEXT(obj);
+ }
+ };
+ name = "EXT vertex shader";
+ break;
+ default:
+ throw new InternalError("Unexpected OpenGL object type " + which);
+ }
+
+ list = new ObjectList(deleter);
+ list.setName(name);
+ lists[which] = list;
+ }
+ return list;
+ }
+}
diff --git a/src/classes/com/sun/opengl/impl/Java2D.java b/src/classes/com/sun/opengl/impl/Java2D.java
index 7d666e138..c3eaa3b7c 100755
--- a/src/classes/com/sun/opengl/impl/Java2D.java
+++ b/src/classes/com/sun/opengl/impl/Java2D.java
@@ -52,6 +52,7 @@ 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;
@@ -110,6 +111,9 @@ public class Java2D {
Graphics.class
});
getOGLSurfaceIdentifierMethod.setAccessible(true);
+
+ String fbo = System.getProperty("sun.java2d.opengl.fbobject");
+ isFBOEnabled = (fbo != null) && "true".equals(fbo);
} catch (Exception e) {
if (DEBUG && VERBOSE) {
e.printStackTrace();
@@ -130,6 +134,10 @@ public class Java2D {
return isOGLPipelineActive;
}
+ public static boolean isFBOEnabled() {
+ return isFBOEnabled;
+ }
+
public static boolean isQueueFlusherThread() {
if (!isOGLPipelineActive()) {
throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)");
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java b/src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java
index d4b10dbfb..e93c7fb3b 100644
--- a/src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java
@@ -129,7 +129,7 @@ public class WindowsGLContext extends GLContextImpl {
WGL.GetLastError());
}
}
- GLContextShareSet.contextCreated(this);
+ GLContextShareSet.contextCreated(this);
if (DEBUG) {
System.err.println(getThreadName() + ": !!! Created OpenGL context " + toHexString(hglrc) + " for " + this + ", device context " + toHexString(drawable.getHDC()) + ", sharing with " + toHexString(hglrc2));
}