aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/Makefile219
-rw-r--r--make/gl-common.cfg16
-rw-r--r--make/gl-glx-common.cfg64
-rw-r--r--make/gl-glx-macosx.cfg10
-rw-r--r--make/gl-glx-x11.cfg8
-rw-r--r--make/gl-impl-macosx.cfg2
-rw-r--r--make/gl-impl-win32.cfg2
-rw-r--r--make/gl-impl-x11.cfg2
-rw-r--r--make/glu-impl-common-CustomJavaCode.java13
-rw-r--r--make/glu-impl-common.cfg5
-rw-r--r--make/glu-impl-macosx.cfg2
-rw-r--r--make/glu-impl-x11.cfg4
-rw-r--r--make/glx-x11.cfg86
-rw-r--r--make/stub_includes/opengl/GL/glu.h61
-rw-r--r--make/stub_includes/win32/windows.h1
-rw-r--r--make/stub_includes/win32/wingdi.h3
-rw-r--r--make/stub_includes/x11/X11/X.h1
-rw-r--r--make/stub_includes/x11/X11/Xutil.h5
-rw-r--r--make/stub_includes/x11/window-system.c138
-rw-r--r--make/wingdi-win32.cfg2
-rw-r--r--src/net/java/games/gluegen/CMethodBindingEmitter.java210
-rw-r--r--src/net/java/games/gluegen/DebugEmitter.java9
-rw-r--r--src/net/java/games/gluegen/GlueEmitter.java8
-rw-r--r--src/net/java/games/gluegen/GlueGen.java21
-rw-r--r--src/net/java/games/gluegen/JavaConfiguration.java28
-rw-r--r--src/net/java/games/gluegen/JavaEmitter.java69
-rw-r--r--src/net/java/games/gluegen/JavaMethodBindingEmitter.java2
-rw-r--r--src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java13
-rw-r--r--src/net/java/games/gluegen/JavaType.java55
-rw-r--r--src/net/java/games/gluegen/MethodBinding.java5
-rw-r--r--src/net/java/games/gluegen/ReferencedStructs.java13
-rw-r--r--src/net/java/games/gluegen/cgram/types/PointerType.java4
-rw-r--r--src/net/java/games/gluegen/opengl/BuildComposablePipeline.java2
-rw-r--r--src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java16
-rw-r--r--src/net/java/games/gluegen/opengl/GLEmitter.java95
-rw-r--r--src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java11
-rw-r--r--src/net/java/games/gluegen/runtime/ProcAddressHelper.java46
-rw-r--r--src/net/java/games/jogl/impl/GLContext.java48
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java70
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java83
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java4
-rw-r--r--src/net/java/games/jogl/impl/x11/X11GLContext.java95
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java24
-rw-r--r--src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java338
44 files changed, 1245 insertions, 468 deletions
diff --git a/make/Makefile2 b/make/Makefile2
index cf9b6f655..91b9d6641 100644
--- a/make/Makefile2
+++ b/make/Makefile2
@@ -156,6 +156,7 @@ GG_JAVAFILES = \
$(GLUEGEN_DIR)/StructLayout.java \
$(GLUEGEN_DIR)/TypeInfo.java \
$(GLUEGEN_DIR)/runtime/BufferFactory.java \
+ $(GLUEGEN_DIR)/runtime/ProcAddressHelper.java \
$(GLUEGEN_DIR)/runtime/StructAccessor.java \
$(GLUEGEN_DIR)/opengl/ConvertFromGL4Java.java \
$(GLUEGEN_DIR)/opengl/CGLPAWrapperEmitter.java \
@@ -394,6 +395,7 @@ JOGL_JAVAFILES_WINDOWS = \
JOGL_GENERATED_JAVAFILES_WINDOWS = \
$(GENSRC_JOGL_IMPL_DIR)/windows/BITMAPINFO.java \
$(GENSRC_JOGL_IMPL_DIR)/windows/BITMAPINFOHEADER.java \
+ $(GENSRC_JOGL_IMPL_DIR)/windows/GLProcAddressTable.java \
$(GENSRC_JOGL_IMPL_DIR)/windows/JAWT_Win32DrawingSurfaceInfo.java \
$(GENSRC_JOGL_IMPL_DIR)/windows/PIXELFORMATDESCRIPTOR.java \
$(GENSRC_JOGL_IMPL_DIR)/windows/RGBQUAD.java \
@@ -408,12 +410,17 @@ JOGL_JAVAFILES_X11 = \
$(JOGL_IMPL_DIR)/x11/X11GLContext.java \
$(JOGL_IMPL_DIR)/x11/X11GLContextFactory.java \
$(JOGL_IMPL_DIR)/x11/X11OnscreenGLContext.java \
- $(JOGL_IMPL_DIR)/x11/X11OffscreenGLContext.java
+ $(JOGL_IMPL_DIR)/x11/X11OffscreenGLContext.java \
+ $(JOGL_IMPL_DIR)/x11/X11PbufferGLContext.java
JOGL_GENERATED_JAVAFILES_X11 = \
+ $(GENSRC_JOGL_IMPL_DIR)/x11/GLProcAddressTable.java \
$(GENSRC_JOGL_IMPL_DIR)/x11/GLX.java \
+ $(GENSRC_JOGL_IMPL_DIR)/x11/GLXFBConfig.java \
+ $(GENSRC_JOGL_IMPL_DIR)/x11/GLXProcAddressTable.java \
$(GENSRC_JOGL_IMPL_DIR)/x11/JAWT_X11DrawingSurfaceInfo.java \
- $(GENSRC_JOGL_IMPL_DIR)/x11/X11GLImpl.java
+ $(GENSRC_JOGL_IMPL_DIR)/x11/X11GLImpl.java \
+ $(GENSRC_JOGL_IMPL_DIR)/x11/XVisualInfo.java
JOGL_GENERATED_CFILES_X11 = \
$(GENSRC_GL_NATIVE_DIR)/GLX_JNI.c \
@@ -429,6 +436,7 @@ JOGL_JAVAFILES_MACOSX = \
JOGL_GENERATED_JAVAFILES_MACOSX = \
$(GENSRC_JOGL_IMPL_DIR)/macosx/CGL.java \
+ $(GENSRC_JOGL_IMPL_DIR)/macosx/GLProcAddressTable.java \
$(GENSRC_JOGL_IMPL_DIR)/macosx/JAWT_MacOSXDrawingSurfaceInfo.java \
$(GENSRC_JOGL_IMPL_DIR)/macosx/MacOSXGLImpl.java
@@ -478,7 +486,7 @@ JOGL_GENERATED_CFILES_PD=$(JOGL_GENERATED_CFILES_WINDOWS)
GL_DEFINES=/D "JOGL_EXPORTS" $(DEFINES)
GL_INCLUDES=/I"$(JOGL_STUB_INCLUDES_DIR_OPENGL)" $(INCLUDES)
GL_C_BUILD_OBJ_CMD=$(CC) /c $< $(CFLAGS) $(GL_INCLUDES) $(GL_DEFINES) /Fo"$@"
-JOGL_DSO_LINK_ADDITIONAL_LIBS=opengl32.lib glu32.lib jawt.lib gdi32.lib
+JOGL_DSO_LINK_ADDITIONAL_LIBS=opengl32.lib glu32.lib jawt.lib gdi32.lib kernel32.lib
GL_LINKFLAGS=$(LINKFLAGS) $(JOGL_DSO_LINK_ADDITIONAL_LIBS)
GL_C_LINK_DSO_CMD=$(LINK) /OUT:"$@" $(GL_LINKFLAGS)
endif # WIN32
@@ -551,16 +559,15 @@ JOGL_GENERATED_JAVAFILES = \
$(GENSRC_JOGL_DIR)/WGL.java \
$(GENSRC_JOGL_DIR)/GLX.java \
$(GENSRC_JOGL_DIR)/CGL.java \
- $(GENSRC_JOGL_DIR)/XVisualInfo.java \
$(GENSRC_JOGL_GLU_DIR)/GLU.java \
$(GENSRC_JOGL_GLU_DIR)/GLUquadric.java \
$(GENSRC_JOGL_GLU_IMPL_DIR)/GLUImpl.java \
+ $(GENSRC_JOGL_GLU_IMPL_DIR)/GLUProcAddressTable.java \
$(GENSRC_JOGL_IMPL_DIR)/JAWT.java \
$(GENSRC_JOGL_IMPL_DIR)/JAWTFactory.java \
$(GENSRC_JOGL_IMPL_DIR)/JAWT_DrawingSurface.java \
$(GENSRC_JOGL_IMPL_DIR)/JAWT_DrawingSurfaceInfo.java \
$(GENSRC_JOGL_IMPL_DIR)/JAWT_Rectangle.java \
- $(GENSRC_JOGL_IMPL_DIR)/ProcAddressTable.java \
$(GENSRC_JOGL_IMPL_DIR)/StaticGLInfo.java \
$(JOGL_GENERATED_JAVAFILES_PD)
@@ -878,7 +885,7 @@ $(JOGL_GENERATED_JAVAFILES) $(JOGL_GENERATED_CFILES) : $(JOGL_STUB_INCLUDES_PD)
$(JAVA) -cp "$(CLASSES_DIR)$(CP_SEPARATOR)$(CLASSPATH)" net.java.games.gluegen.GlueGen -Enet.java.games.gluegen.JavaEmitter -C$(JOGL_JAWT_CFG) $(JOGL_GLUEGEN_INCLUDES) -I"$(JAVA_INCLUDE_PATH)" "$(JAVA_INCLUDE_PATH_PD)/jawt_md.h"
# generate WGL/GLX/CGL implementation class
- $(JAVA) -cp "$(CLASSES_DIR)$(CP_SEPARATOR)$(CLASSPATH)" net.java.games.gluegen.GlueGen -Enet.java.games.gluegen.JavaEmitter -C$(JOGL_WINDOW_SYSTEM_CFG) $(JOGL_GLUEGEN_INCLUDES) -I$(JOGL_STUB_INCLUDES_DIR_OPENGL) $(JOGL_STUB_INCLUDES_DIR_PD)/window-system.c
+ $(JAVA) -cp "$(CLASSES_DIR)$(CP_SEPARATOR)$(CLASSPATH)" net.java.games.gluegen.GlueGen -Enet.java.games.gluegen.opengl.GLEmitter -C$(JOGL_WINDOW_SYSTEM_CFG) $(JOGL_GLUEGEN_INCLUDES) -I$(JOGL_STUB_INCLUDES_DIR_OPENGL) $(JOGL_STUB_INCLUDES_DIR_PD)/window-system.c
# generate StaticGLInfo class
$(JAVA) -cp "$(CLASSES_DIR)$(CP_SEPARATOR)$(CLASSPATH)" net.java.games.gluegen.opengl.BuildStaticGLInfo net.java.games.jogl.impl $(GENSRC_JOGL_IMPL_DIR) $(JOGL_HEADERS)
diff --git a/make/gl-common.cfg b/make/gl-common.cfg
index f824432d0..32664d7a0 100644
--- a/make/gl-common.cfg
+++ b/make/gl-common.cfg
@@ -7,6 +7,7 @@ RuntimeExceptionType GLException
# Imports needed by all glue code
Import java.nio.*
Import net.java.games.jogl.*
+Import net.java.games.jogl.impl.*
# Don't output #defines of GL version identifier strings as constants,
# because we don't need them java-side.
@@ -362,10 +363,6 @@ Opaque long __GLXextFuncPtr
Opaque boolean Bool
Opaque long Display *
Opaque long GLXContext
-Opaque long GLXFBConfig
-Opaque long GLXFBConfig *
-Opaque long GLXFBConfigSGIX
-Opaque long GLXFBConfigSGIX *
Opaque long Visual *
# Ignore the empty Display and Visual data structures (though made
# opaque, the references from XVisualInfo and elsewhere are still
@@ -377,3 +374,14 @@ Ignore Visual
ArgumentIsString glXGetProcAddress 0
ArgumentIsString glXGetProcAddressARB 0
ReturnsString glXQueryExtensionsString
+ReturnsString glXQueryServerString
+ReturnsString glXGetClientString
+TemporaryCVariableDeclaration glXChooseFBConfig int count;
+TemporaryCVariableAssignment glXChooseFBConfig count = _ptr3[0];
+ReturnValueLength glXChooseFBConfig count
+TemporaryCVariableDeclaration glXChooseFBConfigSGIX int count;
+TemporaryCVariableAssignment glXChooseFBConfigSGIX count = _ptr3[0];
+ReturnValueLength glXChooseFBConfigSGIX count
+TemporaryCVariableDeclaration glXGetFBConfigs int count;
+TemporaryCVariableAssignment glXGetFBConfigs count = _ptr2[0];
+ReturnValueLength glXGetFBConfigs count
diff --git a/make/gl-glx-common.cfg b/make/gl-glx-common.cfg
new file mode 100644
index 000000000..2c3a4b4dd
--- /dev/null
+++ b/make/gl-glx-common.cfg
@@ -0,0 +1,64 @@
+# This .cfg file causes the core GLX routines to be ignored from both
+# the public API as well as from the GL implementation files on
+# non-X11 platforms.
+
+# Ignore all of the core GLX routines, which are exposed only in the
+# implementation GLX class
+Ignore glXChooseVisual
+Ignore glXCreateContext
+Ignore glXDestroyContext
+Ignore glXMakeCurrent
+Ignore glXCopyContext
+Ignore glXSwapBuffers
+Ignore glXCreateGLXPixmap
+Ignore glXDestroyGLXPixmap
+Ignore glXQueryExtension
+Ignore glXQueryVersion
+Ignore glXIsDirect
+Ignore glXGetConfig
+Ignore glXGetCurrentContext
+Ignore glXGetCurrentDrawable
+Ignore glXWaitGL
+Ignore glXWaitX
+Ignore glXUseXFont
+Ignore glXQueryExtensionsString
+Ignore glXQueryServerString
+Ignore glXGetClientString
+Ignore glXGetCurrentDisplay
+Ignore glXChooseFBConfig
+Ignore glXGetFBConfigAttrib
+Ignore glXGetFBConfigs
+Ignore glXGetVisualFromFBConfig
+Ignore glXCreateWindow
+Ignore glXDestroyWindow
+Ignore glXCreatePixmap
+Ignore glXDestroyPixmap
+Ignore glXCreatePbuffer
+Ignore glXDestroyPbuffer
+Ignore glXQueryDrawable
+Ignore glXCreateNewContext
+Ignore glXMakeContextCurrent
+Ignore glXGetCurrentReadDrawable
+Ignore glXQueryContext
+Ignore glXSelectEvent
+Ignore glXGetSelectedEvent
+Ignore glXGetProcAddress
+
+# Ignore a few extensions that bring in data types we don't want to
+# expose in the public API (and that are useless anyway without
+# exposing more of the implementation)
+Ignore glXGetFBConfigAttribSGIX
+Ignore glXChooseFBConfigSGIX
+Ignore glXCreateGLXPixmapWithConfigSGIX
+Ignore glXCreateContextWithConfigSGIX
+Ignore glXGetVisualFromFBConfigSGIX
+Ignore glXGetFBConfigFromVisualSGIX
+Ignore glXCreateGLXPbufferSGIX
+Ignore glXDestroyGLXPbufferSGIX
+Ignore glXQueryGLXPbufferSGIX
+Ignore glXSelectEventSGIX
+Ignore glXGetSelectedEventSGIX
+Ignore glXCreateGLXPixmapMESA
+
+# Now we can ignore the GLXFBConfig data type in the public API
+Ignore GLXFBConfig
diff --git a/make/gl-glx-macosx.cfg b/make/gl-glx-macosx.cfg
deleted file mode 100644
index 7a6d826ce..000000000
--- a/make/gl-glx-macosx.cfg
+++ /dev/null
@@ -1,10 +0,0 @@
-# This .cfg file is used to generate the interface which contains the
-# window system-specific extensions which are exposed (via
-# inheritance) to the GL interface.
-Package net.java.games.jogl
-Style InterfaceOnly
-JavaClass MacOSXGL
-Include gl-common-macosx.cfg
-
-# Ignore everything that doesn't start with glX, GLX or XVisualInfo
-IgnoreNot ^(glX|GLX|XVisualInf).+
diff --git a/make/gl-glx-x11.cfg b/make/gl-glx-x11.cfg
index 99292615a..359e35c62 100644
--- a/make/gl-glx-x11.cfg
+++ b/make/gl-glx-x11.cfg
@@ -6,5 +6,9 @@ Style InterfaceOnly
JavaClass GLX
Include gl-common-x11.cfg
-# Ignore everything that doesn't start with glX, GLX or XVisualInfo
-IgnoreNot ^(glX|GLX|XVisualInf).+
+# Ignore everything that doesn't start with glX or GLX
+IgnoreNot ^(glX|GLX).+
+
+# Pick up ignores that must also be included in other platforms' impl
+# files
+Include gl-glx-common.cfg
diff --git a/make/gl-impl-macosx.cfg b/make/gl-impl-macosx.cfg
index 5ada8af01..5aa8ea786 100644
--- a/make/gl-impl-macosx.cfg
+++ b/make/gl-impl-macosx.cfg
@@ -6,8 +6,10 @@ JavaClass GL
ImplPackage net.java.games.jogl.impl.macosx
ImplJavaClass MacOSXGLImpl
Include gl-common-macosx.cfg
+Include gl-glx-common.cfg
EmitProcAddressTable true
+ProcAddressTableClassName GLProcAddressTable
CustomCCode #include <inttypes.h>
diff --git a/make/gl-impl-win32.cfg b/make/gl-impl-win32.cfg
index caa65180e..4891bd490 100644
--- a/make/gl-impl-win32.cfg
+++ b/make/gl-impl-win32.cfg
@@ -6,8 +6,10 @@ JavaClass GL
ImplPackage net.java.games.jogl.impl.windows
ImplJavaClass WindowsGLImpl
Include gl-common-win32.cfg
+Include gl-glx-common.cfg
EmitProcAddressTable true
+ProcAddressTableClassName GLProcAddressTable
CustomCCode #define WIN32_LEAN_AND_MEAN
CustomCCode #include <windows.h>
diff --git a/make/gl-impl-x11.cfg b/make/gl-impl-x11.cfg
index 35595e829..2ec48039e 100644
--- a/make/gl-impl-x11.cfg
+++ b/make/gl-impl-x11.cfg
@@ -6,8 +6,10 @@ JavaClass GL
ImplPackage net.java.games.jogl.impl.x11
ImplJavaClass X11GLImpl
Include gl-common-x11.cfg
+Include gl-glx-common.cfg
EmitProcAddressTable true
+ProcAddressTableClassName GLProcAddressTable
# Pick up XVisualInfo from jogl
Ignore XVisualInfo
diff --git a/make/glu-impl-common-CustomJavaCode.java b/make/glu-impl-common-CustomJavaCode.java
index 8722ea64a..04505db55 100644
--- a/make/glu-impl-common-CustomJavaCode.java
+++ b/make/glu-impl-common-CustomJavaCode.java
@@ -1,8 +1,11 @@
-/** WARNING: this function is not yet implemented! */
+/** Indicates whether the given GLU routine is available to be called. */
public boolean isFunctionAvailable(String gluFunctionName)
{
- // TODO FIXME: Implement the GLU equivalent GL.isFunctionAvailable(String)
- if (true) throw new GLException("GLU.isFunctionAvailable is not yet implemented.");
-
- return false;
+ return (gluProcAddressTable.getAddressFor(gluFunctionName) != 0);
+}
+
+private GLUProcAddressTable gluProcAddressTable;
+public GLUImpl(GLUProcAddressTable gluProcAddressTable)
+{
+ this.gluProcAddressTable = gluProcAddressTable;
}
diff --git a/make/glu-impl-common.cfg b/make/glu-impl-common.cfg
index d4fdb7911..1e6ae0699 100644
--- a/make/glu-impl-common.cfg
+++ b/make/glu-impl-common.cfg
@@ -5,9 +5,12 @@ Include glu-common.cfg
Style ImplOnly
+EmitProcAddressTable true
+ProcAddressTableClassName GLUProcAddressTable
+GetProcAddressTableExpr gluProcAddressTable
+
# Custom Java code for GLUImpl class
IncludeAs CustomJavaCode GLUImpl glu-impl-common-CustomJavaCode.java
# Custom C code for GLUImpl class
IncludeAs CustomCCode glu-impl-common-CustomCCode.c
-
diff --git a/make/glu-impl-macosx.cfg b/make/glu-impl-macosx.cfg
index cf40212d0..5e856c7ec 100644
--- a/make/glu-impl-macosx.cfg
+++ b/make/glu-impl-macosx.cfg
@@ -2,3 +2,5 @@
# Mac OS X.
Include glu-impl-common.cfg
+
+CustomCCode #include <inttypes.h>
diff --git a/make/glu-impl-x11.cfg b/make/glu-impl-x11.cfg
index 42e97a00e..3e46a73b5 100644
--- a/make/glu-impl-x11.cfg
+++ b/make/glu-impl-x11.cfg
@@ -3,8 +3,6 @@
Include glu-impl-common.cfg
-# !! FIXME: Chris doesn't have access to X11 yet, so he
-# doesn't know what CustomCCode directives to put in here.
-
+CustomCCode #include <inttypes.h>
diff --git a/make/glx-x11.cfg b/make/glx-x11.cfg
index f9a69c0b3..39098f0a8 100644
--- a/make/glx-x11.cfg
+++ b/make/glx-x11.cfg
@@ -5,13 +5,24 @@ JavaClass GLX
Style allstatic
Include gl-common-x11.cfg
+EmitProcAddressTable true
+ProcAddressTableClassName GLXProcAddressTable
+GetProcAddressTableExpr glxProcAddressTable
+# This must be present for bootstrapping
+SkipProcAddressGen glXGetProcAddressARB
+
+CustomJavaCode GLX private static GLXProcAddressTable glxProcAddressTable = new GLXProcAddressTable();
+CustomJavaCode GLX public static GLXProcAddressTable getGLXProcAddressTable() { return glxProcAddressTable; }
+CustomJavaCode GLX public static native long dlsym(String name);
+
CustomCCode #include <inttypes.h>
CustomCCode #include <X11/Xlib.h>
CustomCCode #include <X11/Xutil.h>
CustomCCode #include <GL/glx.h>
-
-# Pick up XVisualInfo from jogl
-Ignore XVisualInfo
+CustomCCode /* Linux headers don't work properly */
+CustomCCode #define __USE_GNU
+CustomCCode #include <dlfcn.h>
+CustomCCode #undef __USE_GNU
ArgumentIsString XOpenDisplay 0
@@ -26,3 +37,72 @@ CustomCCode JNIEXPORT jlong JNICALL
CustomCCode Java_net_java_games_jogl_impl_x11_GLX_RootWindow(JNIEnv *env, jclass _unused, jlong display, jint screen) {
CustomCCode return RootWindow((Display*) (intptr_t) display, screen);
CustomCCode }
+CustomCCode JNIEXPORT jlong JNICALL
+CustomCCode Java_net_java_games_jogl_impl_x11_GLX_dlsym(JNIEnv *env, jclass _unused, jstring name) {
+CustomCCode const jbyte* chars;
+CustomCCode void* res;
+CustomCCode chars = (*env)->GetStringUTFChars(env, name, NULL);
+CustomCCode res = dlsym(RTLD_DEFAULT, chars);
+CustomCCode (*env)->ReleaseStringUTFChars(env, name, chars);
+CustomCCode return (jlong) ((intptr_t) res);
+CustomCCode }
+
+# Ignore everything not in the GLX core (up through GLX 1.4) aside from glXGetProcAddress
+# FIXME: this needs to be kept in sync with the stub headers more than usual
+Ignore glXFreeContextEXT
+Ignore glXGetContextIDEXT
+Ignore glXGetCurrentDisplayEXT
+Ignore glXImportContextEXT
+Ignore glXQueryContextInfoEXT
+
+Ignore glXCopySubBufferMESA
+Ignore glXCreateGLXPixmapMESA
+Ignore glXReleaseBuffersMESA
+Ignore glXSet3DfxModeMESA
+
+Ignore glXGetSyncValuesOML
+Ignore glXGetMscRateOML
+Ignore glXSwapBuffersMscOML
+Ignore glXWaitForMscOML
+Ignore glXWaitForSbcOML
+
+Ignore glXAllocateMemoryNV
+Ignore glXFreeMemoryNV
+
+Ignore glXCushionSGI
+Ignore glXGetVideoSyncSGI
+Ignore glXWaitVideoSyncSGI
+Ignore glXSwapIntervalSGI
+Ignore glXMakeCurrentReadSGI
+Ignore glXGetCurrentReadDrawableSGI
+
+Ignore glXCreateGLXVideoSourceSGIX
+Ignore glXDestroyGLXVideoSourceSGIX
+Ignore glXGetFBConfigAttribSGIX
+Ignore glXChooseFBConfigSGIX
+Ignore glXCreateGLXPixmapWithConfigSGIX
+Ignore glXCreateContextWithConfigSGIX
+Ignore glXGetVisualFromFBConfigSGIX
+Ignore glXGetFBConfigFromVisualSGIX
+Ignore glXCreateGLXPbufferSGIX
+Ignore glXDestroyGLXPbufferSGIX
+Ignore glXQueryGLXPbufferSGIX
+Ignore glXSelectEventSGIX
+Ignore glXGetSelectedEventSGIX
+Ignore glXBindChannelToWindowSGIX
+Ignore glXChannelRectSGIX
+Ignore glXQueryChannelRectSGIX
+Ignore glXQueryChannelDeltasSGIX
+Ignore glXChannelRectSyncSGIX
+Ignore glXAssociateDMPbufferSGIX
+Ignore glXJoinSwapGroupSGIX
+Ignore glXBindSwapBarrierSGIX
+Ignore glXQueryMaxSwapBarriersSGIX
+
+Ignore glXGetTransparentIndexSUN
+
+# Ignore non-GLX GL routines and constants
+Ignore ^GL_.+
+Ignore TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB
+Ignore CLAMP_TO_EDGE_EXT
+Ignore ^gl[^X].+
diff --git a/make/stub_includes/opengl/GL/glu.h b/make/stub_includes/opengl/GL/glu.h
index 89c3f34e3..8f64238f2 100644
--- a/make/stub_includes/opengl/GL/glu.h
+++ b/make/stub_includes/opengl/GL/glu.h
@@ -330,6 +330,67 @@ GLAPI void GLAPIENTRY gluTessVertex (GLUtesselator* tess, GLdouble *location, GL
GLAPI GLint GLAPIENTRY gluUnProject (GLdouble winX, GLdouble winY, GLdouble winZ, const GLdouble *model, const GLdouble *proj, const GLint *view, GLdouble* objX, GLdouble* objY, GLdouble* objZ);
GLAPI GLint GLAPIENTRY gluUnProject4 (GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble clipW, const GLdouble *model, const GLdouble *proj, const GLint *view, GLdouble nearVal, GLdouble farVal, GLdouble* objX, GLdouble* objY, GLdouble* objZ, GLdouble* objW);
+
+typedef void (GLAPIENTRY * PFNGLUBEGINCURVEPROC) (GLUnurbs* nurb);
+typedef void (GLAPIENTRY * PFNGLUBEGINPOLYGONPROC) (GLUtesselator* tess);
+typedef void (GLAPIENTRY * PFNGLUBEGINSURFACEPROC) (GLUnurbs* nurb);
+typedef void (GLAPIENTRY * PFNGLUBEGINTRIMPROC) (GLUnurbs* nurb);
+typedef GLint (GLAPIENTRY * PFNGLUBUILD1DMIPMAPLEVELSPROC) (GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, GLint level, GLint base, GLint max, const void *data);
+typedef GLint (GLAPIENTRY * PFNGLUBUILD1DMIPMAPSPROC) (GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, const void *data);
+typedef GLint (GLAPIENTRY * PFNGLUBUILD2DMIPMAPLEVELSPROC) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint level, GLint base, GLint max, const void *data);
+typedef GLint (GLAPIENTRY * PFNGLUBUILD2DMIPMAPSPROC) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data);
+typedef GLint (GLAPIENTRY * PFNGLUBUILD3DMIPMAPLEVELSPROC) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLint level, GLint base, GLint max, const void *data);
+typedef GLint (GLAPIENTRY * PFNGLUBUILD3DMIPMAPSPROC) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+typedef GLboolean (GLAPIENTRY * PFNGLUCHECKEXTENSIONPROC) (const GLubyte *extName, const GLubyte *extString);
+typedef void (GLAPIENTRY * PFNGLUCYLINDERPROC) (GLUquadric* quad, GLdouble base, GLdouble top, GLdouble height, GLint slices, GLint stacks);
+typedef void (GLAPIENTRY * PFNGLUDELETENURBSRENDERERPROC) (GLUnurbs* nurb);
+typedef void (GLAPIENTRY * PFNGLUDELETEQUADRICPROC) (GLUquadric* quad);
+typedef void (GLAPIENTRY * PFNGLUDELETETESSPROC) (GLUtesselator* tess);
+typedef void (GLAPIENTRY * PFNGLUDISKPROC) (GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops);
+typedef void (GLAPIENTRY * PFNGLUENDCURVEPROC) (GLUnurbs* nurb);
+typedef void (GLAPIENTRY * PFNGLUENDPOLYGONPROC) (GLUtesselator* tess);
+typedef void (GLAPIENTRY * PFNGLUENDSURFACEPROC) (GLUnurbs* nurb);
+typedef void (GLAPIENTRY * PFNGLUENDTRIMPROC) (GLUnurbs* nurb);
+typedef const GLubyte * (GLAPIENTRY * PFNGLUERRORSTRINGPROC) (GLenum error);
+typedef void (GLAPIENTRY * PFNGLUGETNURBSPROPERTYPROC) (GLUnurbs* nurb, GLenum property, GLfloat* data);
+typedef const GLubyte * (GLAPIENTRY * PFNGLUGETSTRINGPROC) (GLenum name);
+typedef void (GLAPIENTRY * PFNGLUGETTESSPROPERTYPROC) (GLUtesselator* tess, GLenum which, GLdouble* data);
+typedef void (GLAPIENTRY * PFNGLULOADSAMPLINGMATRICESPROC) (GLUnurbs* nurb, const GLfloat *model, const GLfloat *perspective, const GLint *view);
+typedef void (GLAPIENTRY * PFNGLULOOKATPROC) (GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ, GLdouble centerX, GLdouble centerY, GLdouble centerZ, GLdouble upX, GLdouble upY, GLdouble upZ);
+typedef GLUnurbs* (GLAPIENTRY * PFNGLUNEWNURBSRENDERERPROC) (void);
+typedef GLUquadric* (GLAPIENTRY * PFNGLUNEWQUADRICPROC) (void);
+typedef GLUtesselator* (GLAPIENTRY * PFNGLUNEWTESSPROC) (void);
+typedef void (GLAPIENTRY * PFNGLUNEXTCONTOURPROC) (GLUtesselator* tess, GLenum type);
+typedef void (GLAPIENTRY * PFNGLUNURBSCALLBACKPROC) (GLUnurbs* nurb, GLenum which, _GLUfuncptr CallBackFunc);
+typedef void (GLAPIENTRY * PFNGLUNURBSCALLBACKDATAPROC) (GLUnurbs* nurb, GLvoid* userData);
+typedef void (GLAPIENTRY * PFNGLUNURBSCALLBACKDATAEXTPROC) (GLUnurbs* nurb, GLvoid* userData);
+typedef void (GLAPIENTRY * PFNGLUNURBSCURVEPROC) (GLUnurbs* nurb, GLint knotCount, GLfloat *knots, GLint stride, GLfloat *control, GLint order, GLenum type);
+typedef void (GLAPIENTRY * PFNGLUNURBSPROPERTYPROC) (GLUnurbs* nurb, GLenum property, GLfloat value);
+typedef void (GLAPIENTRY * PFNGLUNURBSSURFACEPROC) (GLUnurbs* nurb, GLint sKnotCount, GLfloat* sKnots, GLint tKnotCount, GLfloat* tKnots, GLint sStride, GLint tStride, GLfloat* control, GLint sOrder, GLint tOrder, GLenum type);
+typedef void (GLAPIENTRY * PFNGLUORTHO2DPROC) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top);
+typedef void (GLAPIENTRY * PFNGLUPARTIALDISKPROC) (GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops, GLdouble start, GLdouble sweep);
+typedef void (GLAPIENTRY * PFNGLUPERSPECTIVEPROC) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+typedef void (GLAPIENTRY * PFNGLUPICKMATRIXPROC) (GLdouble x, GLdouble y, GLdouble delX, GLdouble delY, GLint *viewport);
+typedef GLint (GLAPIENTRY * PFNGLUPROJECTPROC) (GLdouble objX, GLdouble objY, GLdouble objZ, const GLdouble *model, const GLdouble *proj, const GLint *view, GLdouble* winX, GLdouble* winY, GLdouble* winZ);
+typedef void (GLAPIENTRY * PFNGLUPWLCURVEPROC) (GLUnurbs* nurb, GLint count, GLfloat* data, GLint stride, GLenum type);
+typedef void (GLAPIENTRY * PFNGLUQUADRICCALLBACKPROC) (GLUquadric* quad, GLenum which, _GLUfuncptr CallBackFunc);
+typedef void (GLAPIENTRY * PFNGLUQUADRICDRAWSTYLEPROC) (GLUquadric* quad, GLenum draw);
+typedef void (GLAPIENTRY * PFNGLUQUADRICNORMALSPROC) (GLUquadric* quad, GLenum normal);
+typedef void (GLAPIENTRY * PFNGLUQUADRICORIENTATIONPROC) (GLUquadric* quad, GLenum orientation);
+typedef void (GLAPIENTRY * PFNGLUQUADRICTEXTUREPROC) (GLUquadric* quad, GLboolean texture);
+typedef GLint (GLAPIENTRY * PFNGLUSCALEIMAGEPROC) (GLenum format, GLsizei wIn, GLsizei hIn, GLenum typeIn, const void *dataIn, GLsizei wOut, GLsizei hOut, GLenum typeOut, GLvoid* dataOut);
+typedef void (GLAPIENTRY * PFNGLUSPHEREPROC) (GLUquadric* quad, GLdouble radius, GLint slices, GLint stacks);
+typedef void (GLAPIENTRY * PFNGLUTESSBEGINCONTOURPROC) (GLUtesselator* tess);
+typedef void (GLAPIENTRY * PFNGLUTESSBEGINPOLYGONPROC) (GLUtesselator* tess, GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLUTESSCALLBACKPROC) (GLUtesselator* tess, GLenum which, _GLUfuncptr CallBackFunc);
+typedef void (GLAPIENTRY * PFNGLUTESSENDCONTOURPROC) (GLUtesselator* tess);
+typedef void (GLAPIENTRY * PFNGLUTESSENDPOLYGONPROC) (GLUtesselator* tess);
+typedef void (GLAPIENTRY * PFNGLUTESSNORMALPROC) (GLUtesselator* tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ);
+typedef void (GLAPIENTRY * PFNGLUTESSPROPERTYPROC) (GLUtesselator* tess, GLenum which, GLdouble data);
+typedef void (GLAPIENTRY * PFNGLUTESSVERTEXPROC) (GLUtesselator* tess, GLdouble *location, GLvoid* data);
+typedef GLint (GLAPIENTRY * PFNGLUUNPROJECTPROC) (GLdouble winX, GLdouble winY, GLdouble winZ, const GLdouble *model, const GLdouble *proj, const GLint *view, GLdouble* objX, GLdouble* objY, GLdouble* objZ);
+typedef GLint (GLAPIENTRY * PFNGLUUNPROJECT4PROC) (GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble clipW, const GLdouble *model, const GLdouble *proj, const GLint *view, GLdouble nearVal, GLdouble farVal, GLdouble* objX, GLdouble* objY, GLdouble* objZ, GLdouble* objW);
+
#ifdef __cplusplus
}
#endif
diff --git a/make/stub_includes/win32/windows.h b/make/stub_includes/win32/windows.h
index 24b9df4fa..fa4ae1c95 100644
--- a/make/stub_includes/win32/windows.h
+++ b/make/stub_includes/win32/windows.h
@@ -20,6 +20,7 @@ typedef HANDLE HBITMAP;
typedef HANDLE HDC;
typedef HANDLE HGDIOBJ;
typedef HANDLE HGLRC;
+typedef HANDLE HMODULE;
typedef HANDLE HPALETTE;
typedef HANDLE HWND;
typedef long LONG;
diff --git a/make/stub_includes/win32/wingdi.h b/make/stub_includes/win32/wingdi.h
index 5365a8990..3cb6f8568 100644
--- a/make/stub_includes/win32/wingdi.h
+++ b/make/stub_includes/win32/wingdi.h
@@ -115,6 +115,8 @@ typedef struct tagPIXELFORMATDESCRIPTOR
// Windows routines
WINBASEAPI DWORD WINAPI GetLastError(VOID);
+WINBASEAPI HMODULE WINAPI LoadLibraryA(LPCSTR lpLibFileName);
+WINBASEAPI PROC WINAPI GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
// OpenGL-related routines
WINGDIAPI int WINAPI ChoosePixelFormat(HDC, CONST PIXELFORMATDESCRIPTOR *);
@@ -148,4 +150,3 @@ WINGDIAPI HBITMAP WINAPI CreateDIBSection(HDC, CONST BITMAPINFO *, UINT, VOID **
WINGDIAPI BOOL WINAPI DeleteDC(HDC);
WINGDIAPI BOOL WINAPI DeleteObject(HGDIOBJ);
WINGDIAPI HGDIOBJ WINAPI SelectObject(HDC, HGDIOBJ);
-
diff --git a/make/stub_includes/x11/X11/X.h b/make/stub_includes/x11/X11/X.h
index 8aa8500cb..2cd64bbf0 100644
--- a/make/stub_includes/x11/X11/X.h
+++ b/make/stub_includes/x11/X11/X.h
@@ -10,6 +10,7 @@ typedef unsigned long VisualID;
typedef XID Colormap;
typedef XID Cursor;
typedef XID Drawable;
+typedef XID Font;
typedef XID GContext;
typedef XID KeySym;
typedef XID Pixmap;
diff --git a/make/stub_includes/x11/X11/Xutil.h b/make/stub_includes/x11/X11/Xutil.h
index 017f8fb98..32c8d5be5 100644
--- a/make/stub_includes/x11/X11/Xutil.h
+++ b/make/stub_includes/x11/X11/Xutil.h
@@ -1,3 +1,6 @@
+#ifndef _XUTIL_H_
+#define _XUTIL_H_
+
#include <X11/X.h>
#include <X11/Xlib.h>
@@ -30,3 +33,5 @@ typedef struct {
#define VisualColormapSizeMask 0x80
#define VisualBitsPerRGBMask 0x100
#define VisualAllMask 0x1FF
+
+#endif /* #defined _XUTIL_H_ */
diff --git a/make/stub_includes/x11/window-system.c b/make/stub_includes/x11/window-system.c
index 55e70c7f7..6af85eeb9 100644
--- a/make/stub_includes/x11/window-system.c
+++ b/make/stub_includes/x11/window-system.c
@@ -1,140 +1,10 @@
-/*
- * Essential glX and supporting routines and data structures extracted
- * from glx.h.
- *
- * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
- */
+// Define GLX_GLXEXT_PROTOTYPES so that the OpenGL GLX extension prototypes in
+// "glxext.h" are parsed.
+#define GLX_GLXEXT_PROTOTYPES
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-
-/*
- * Tokens for glXChooseVisual and glXGetConfig:
- */
-#define GLX_USE_GL 1
-#define GLX_BUFFER_SIZE 2
-#define GLX_LEVEL 3
-#define GLX_RGBA 4
-#define GLX_DOUBLEBUFFER 5
-#define GLX_STEREO 6
-#define GLX_AUX_BUFFERS 7
-#define GLX_RED_SIZE 8
-#define GLX_GREEN_SIZE 9
-#define GLX_BLUE_SIZE 10
-#define GLX_ALPHA_SIZE 11
-#define GLX_DEPTH_SIZE 12
-#define GLX_STENCIL_SIZE 13
-#define GLX_ACCUM_RED_SIZE 14
-#define GLX_ACCUM_GREEN_SIZE 15
-#define GLX_ACCUM_BLUE_SIZE 16
-#define GLX_ACCUM_ALPHA_SIZE 17
-
-/*
- * Error codes returned by glXGetConfig:
- */
-#define GLX_BAD_SCREEN 1
-#define GLX_BAD_ATTRIBUTE 2
-#define GLX_NO_EXTENSION 3
-#define GLX_BAD_VISUAL 4
-#define GLX_BAD_CONTEXT 5
-#define GLX_BAD_VALUE 6
-#define GLX_BAD_ENUM 7
-
-/*
- * GLX 1.3 and later:
- */
-#define GLX_CONFIG_CAVEAT 0x20
-#define GLX_DONT_CARE 0xFFFFFFFF
-#define GLX_SLOW_CONFIG 0x8001
-#define GLX_NON_CONFORMANT_CONFIG 0x800D
-#define GLX_X_VISUAL_TYPE 0x22
-#define GLX_TRANSPARENT_TYPE 0x23
-#define GLX_TRANSPARENT_INDEX_VALUE 0x24
-#define GLX_TRANSPARENT_RED_VALUE 0x25
-#define GLX_TRANSPARENT_GREEN_VALUE 0x26
-#define GLX_TRANSPARENT_BLUE_VALUE 0x27
-#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
-#define GLX_MAX_PBUFFER_WIDTH 0x8016
-#define GLX_MAX_PBUFFER_HEIGHT 0x8017
-#define GLX_MAX_PBUFFER_PIXELS 0x8018
-#define GLX_PRESERVED_CONTENTS 0x801B
-#define GLX_LARGEST_PBUFFER 0x801C
-#define GLX_WIDTH 0x801D
-#define GLX_HEIGHT 0x801E
-#define GLX_EVENT_MASK 0x801F
-#define GLX_DRAWABLE_TYPE 0x8010
-#define GLX_FBCONFIG_ID 0x8013
-#define GLX_VISUAL_ID 0x800B
-#define GLX_WINDOW_BIT 0x00000001
-#define GLX_PIXMAP_BIT 0x00000002
-#define GLX_PBUFFER_BIT 0x00000004
-#define GLX_AUX_BUFFERS_BIT 0x00000010
-#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
-#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
-#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
-#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
-#define GLX_DEPTH_BUFFER_BIT 0x00000020
-#define GLX_STENCIL_BUFFER_BIT 0x00000040
-#define GLX_ACCUM_BUFFER_BIT 0x00000080
-#define GLX_DRAWABLE_TYPE 0x8010
-#define GLX_RENDER_TYPE 0x8011
-#define GLX_X_RENDERABLE 0x8012
-#define GLX_NONE 0x8000
-#define GLX_TRUE_COLOR 0x8002
-#define GLX_DIRECT_COLOR 0x8003
-#define GLX_PSEUDO_COLOR 0x8004
-#define GLX_STATIC_COLOR 0x8005
-#define GLX_GRAY_SCALE 0x8006
-#define GLX_STATIC_GRAY 0x8007
-#define GLX_TRANSPARENT_RGB 0x8008
-#define GLX_TRANSPARENT_INDEX 0x8009
-#define GLX_RGBA_TYPE 0x8014
-#define GLX_COLOR_INDEX_TYPE 0x8015
-#define GLX_COLOR_INDEX_BIT 0x00000002
-#define GLX_RGBA_BIT 0x00000001
-#define GLX_SCREEN 0x800C
-#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
-#define GLX_DAMAGED 0x8020
-#define GLX_SAVED 0x8021
-#define GLX_WINDOW 0x8022
-#define GLX_PBUFFER 0x8023
-#define GLX_PBUFFER_HEIGHT 0x8040
-#define GLX_PBUFFER_WIDTH 0x8041
-
-/*
- * GLX 1.4 and later:
- */
-#define GLX_SAMPLE_BUFFERS 0x186a0 /*100000*/
-#define GLX_SAMPLES 0x186a1 /*100001*/
-
-extern XVisualInfo* glXChooseVisual( Display *dpy, int screen,
- int *attribList );
-
-extern GLXContext glXCreateContext( Display *dpy, XVisualInfo *vis,
- GLXContext shareList, Bool direct );
-
-extern void glXDestroyContext( Display *dpy, GLXContext ctx );
-
-extern Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable,
- GLXContext ctx);
-
-extern void glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
- unsigned long mask );
-
-extern void glXSwapBuffers( Display *dpy, GLXDrawable drawable );
-
-extern GLXPixmap glXCreateGLXPixmap( Display *dpy, XVisualInfo *visual,
- Pixmap pixmap );
-
-extern void glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap );
-
-// Use ARB version for compatibility with older GLX installations
-extern __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *procname);
-
-extern int glXGetConfig( Display *dpy, XVisualInfo *visual,
- int attrib, int *value );
-
-extern const char *glXQueryExtensionsString( Display *dpy, int screen );
+#include <GL/glx.h>
// Routines needed from Xlib.h and Xutil.h (placed here to avoid having
// XVisualInfo generated multiple times)
diff --git a/make/wingdi-win32.cfg b/make/wingdi-win32.cfg
index 3b0a011fa..622cef25d 100644
--- a/make/wingdi-win32.cfg
+++ b/make/wingdi-win32.cfg
@@ -10,6 +10,8 @@ Include gl-common-win32.cfg
# Implement the first argument to wglGetProcAddress as String instead
# of byte[]
ArgumentIsString wglGetProcAddress 0
+ArgumentIsString LoadLibraryA 0
+ArgumentIsString GetProcAddress 1
CustomCCode #define WIN32_LEAN_AND_MEAN
CustomCCode #include <windows.h>
diff --git a/src/net/java/games/gluegen/CMethodBindingEmitter.java b/src/net/java/games/gluegen/CMethodBindingEmitter.java
index 45035f640..763fe6695 100644
--- a/src/net/java/games/gluegen/CMethodBindingEmitter.java
+++ b/src/net/java/games/gluegen/CMethodBindingEmitter.java
@@ -50,6 +50,10 @@ public class CMethodBindingEmitter extends FunctionEmitter
{
protected static final CommentEmitter defaultCommentEmitter =
new DefaultCommentEmitter();
+
+ protected static final String arrayResLength = "_array_res_length";
+ protected static final String arrayRes = "_array_res";
+ protected static final String arrayIdx = "_array_idx";
private MethodBinding binding;
@@ -89,6 +93,12 @@ public class CMethodBindingEmitter extends FunctionEmitter
*/
private MessageFormat returnValueCapacityExpression = null;
+ /**
+ * Length of the returned array. Is ignored if
+ * binding.getJavaReturnType().isArray() is false.
+ */
+ private MessageFormat returnValueLengthExpression = null;
+
// Note: the VC++ 6.0 compiler emits hundreds of warnings when the
// (necessary) null-checking code is enabled. This appears to just
// be a compiler bug, but would be good to track down exactly why it
@@ -168,6 +178,49 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
/**
+ * Get the expression for the length of the returned array
+ */
+ public final MessageFormat getReturnValueLengthExpression()
+ {
+ return returnValueLengthExpression;
+ }
+
+ /**
+ * If this function returns an array, sets the expression for the
+ * length of the returned array.
+ *
+ * @param expression a MessageFormat which, when applied to an array
+ * of type String[] that contains each of the arguments names of the
+ * Java-side binding, returns an expression that will (when compiled
+ * by a C compiler) evaluate to an integer-valued expression. The
+ * value of this expression is the length of the array returned from
+ * this method.
+ *
+ * @throws IllegalArgumentException if the <code>
+ * binding.getJavaReturnType().isNIOBuffer() == false
+ * </code>
+ */
+ public final void setReturnValueLengthExpression(MessageFormat expression)
+ {
+ returnValueLengthExpression = expression;
+
+ if (!binding.getJavaReturnType().isArray())
+ {
+ throw new IllegalArgumentException(
+ "Cannot specify return value length for a method that does not " +
+ "return an array: \"" + binding + "\"");
+ }
+ }
+
+ /**
+ * Returns the List of Strings containing declarations for temporary
+ * C variables to be assigned to after the underlying function call.
+ */
+ public final List/*<String>*/ getTemporaryCVariableDeclarations() {
+ return temporaryCVariableDeclarations;
+ }
+
+ /**
* Sets up a List of Strings containing declarations for temporary C
* variables to be assigned to after the underlying function call. A
* null argument indicates that no manual declarations are to be made.
@@ -177,6 +230,16 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
/**
+ * Returns the List of Strings containing assignments for temporary
+ * C variables which are made after the underlying function call. A
+ * null argument indicates that no manual assignments are to be
+ * made.
+ */
+ public final List/*<String>*/ getTemporaryCVariableAssignments() {
+ return temporaryCVariableAssignments;
+ }
+
+ /**
* Sets up a List of Strings containing assignments for temporary C
* variables which are made after the underlying function call. A
* null argument indicates that no manual assignments are to be made.
@@ -340,8 +403,6 @@ public class CMethodBindingEmitter extends FunctionEmitter
Type cReturnType = binding.getCReturnType();
JavaType javaReturnType = binding.getJavaReturnType();
- String arrayResLength = "_array_res_length";
- String arrayRes = "_array_res";
String capitalizedComponentType = null;
if (!cReturnType.isVoid()) {
writer.print(" ");
@@ -349,24 +410,36 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.print(binding.getCSymbol().getReturnType().getName(true));
writer.println(" _res;");
if (javaReturnType.isArray()) {
- writer.print(" int ");
- writer.print(arrayResLength);
- writer.println(";");
+ if (javaReturnType.isNIOByteBufferArray()) {
+ writer.print(" int ");
+ writer.print(arrayResLength);
+ writer.println(";");
+ writer.print(" int ");
+ writer.print(arrayIdx);
+ writer.println(";");
+ writer.print(" jobjectArray ");
+ writer.print(arrayRes);
+ writer.println(";");
+ } else {
+ writer.print(" int ");
+ writer.print(arrayResLength);
+ writer.println(";");
- Class componentType = javaReturnType.getJavaClass().getComponentType();
- if (componentType.isArray()) {
- throw new RuntimeException("Multi-dimensional arrays not supported yet");
- }
+ Class componentType = javaReturnType.getJavaClass().getComponentType();
+ if (componentType.isArray()) {
+ throw new RuntimeException("Multi-dimensional arrays not supported yet");
+ }
- String javaTypeName = componentType.getName();
- capitalizedComponentType =
- "" + Character.toUpperCase(javaTypeName.charAt(0)) + javaTypeName.substring(1);
- String javaArrayTypeName = "j" + javaTypeName + "Array";
- writer.print(" ");
- writer.print(javaArrayTypeName);
- writer.print(" ");
- writer.print(arrayRes);
- writer.println(";");
+ String javaTypeName = componentType.getName();
+ capitalizedComponentType =
+ "" + Character.toUpperCase(javaTypeName.charAt(0)) + javaTypeName.substring(1);
+ String javaArrayTypeName = "j" + javaTypeName + "Array";
+ writer.print(" ");
+ writer.print(javaArrayTypeName);
+ writer.print(" ");
+ writer.print(arrayRes);
+ writer.println(";");
+ }
}
}
}
@@ -568,6 +641,11 @@ public class CMethodBindingEmitter extends FunctionEmitter
if (EMIT_NULL_CHECKS) {
writer.println(" }");
}
+ } else if (javaArgType.isArrayOfCompoundTypeWrappers()) {
+
+ // FIXME
+ throw new RuntimeException("Outgoing arrays of StructAccessors not yet implemented");
+
}
}
}
@@ -696,6 +774,11 @@ public class CMethodBindingEmitter extends FunctionEmitter
if (EMIT_NULL_CHECKS) {
writer.println(" }");
}
+ } else if (javaArgType.isArrayOfCompoundTypeWrappers()) {
+
+ // FIXME
+ throw new RuntimeException("Outgoing arrays of StructAccessors not yet implemented");
+
}
}
}
@@ -826,35 +909,63 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.print(" if (_res == NULL) return NULL;");
writer.println(" return (*env)->NewStringUTF(env, _res);");
} else if (javaReturnType.isArray()) {
- // FIXME: must have user provide length of array in .cfg file
- // by providing a constant value, input parameter, or
- // expression which computes the array size (already present
- // as ReturnValueCapacity, not yet implemented / tested here)
-
- throw new RuntimeException(
- "Could not emit native code for function \"" + binding +
- "\": array return values for non-char types not implemented yet");
-
- // FIXME: This is approximately what will be required here
- //
- //writer.print(" ");
- //writer.print(arrayRes);
- //writer.print(" = (*env)->New");
- //writer.print(capitalizedComponentType);
- //writer.print("Array(env, ");
- //writer.print(arrayResLength);
- //writer.println(");");
- //writer.print(" (*env)->Set");
- //writer.print(capitalizedComponentType);
- //writer.print("ArrayRegion(env, ");
- //writer.print(arrayRes);
- //writer.print(", 0, ");
- //writer.print(arrayResLength);
- //writer.println(", _res);");
- //writer.print(" return ");
- //writer.print(arrayRes);
- //writer.println(";");
-
+ if (javaReturnType.isNIOByteBufferArray()) {
+ writer.println(" if (_res == NULL) return NULL;");
+ if (returnValueLengthExpression == null) {
+ throw new RuntimeException("Error while generating C code: no length specified for array returned from function " +
+ binding);
+ }
+ String[] argumentNames = new String[binding.getNumArguments()];
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ argumentNames[i] = binding.getArgumentName(i);
+ }
+ writer.println(" " + arrayResLength + " = " + returnValueLengthExpression.format(argumentNames) + ";");
+ writer.println(" " + arrayRes + " = (*env)->NewObjectArray(env, " + arrayResLength + ", (*env)->FindClass(env, \"java/nio/ByteBuffer\"), NULL);");
+ writer.println(" for (" + arrayIdx + " = 0; " + arrayIdx + " < " + arrayResLength + "; " + arrayIdx + "++) {");
+ Type retType = binding.getCSymbol().getReturnType();
+ Type baseType;
+ if (retType.isPointer()) {
+ baseType = retType.asPointer().getTargetType().asPointer().getTargetType();
+ } else {
+ baseType = retType.asArray().getElementType().asPointer().getTargetType();
+ }
+ int sz = baseType.getSize();
+ if (sz < 0)
+ sz = 0;
+ writer.println(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx +
+ ", (*env)->NewDirectByteBuffer(env, _res[" + arrayIdx + "], " + sz + "));");
+ writer.println(" }");
+ writer.println(" return " + arrayRes + ";");
+ } else {
+ // FIXME: must have user provide length of array in .cfg file
+ // by providing a constant value, input parameter, or
+ // expression which computes the array size (already present
+ // as ReturnValueCapacity, not yet implemented / tested here)
+
+ throw new RuntimeException(
+ "Could not emit native code for function \"" + binding +
+ "\": array return values for non-char types not implemented yet");
+
+ // FIXME: This is approximately what will be required here
+ //
+ //writer.print(" ");
+ //writer.print(arrayRes);
+ //writer.print(" = (*env)->New");
+ //writer.print(capitalizedComponentType);
+ //writer.print("Array(env, ");
+ //writer.print(arrayResLength);
+ //writer.println(");");
+ //writer.print(" (*env)->Set");
+ //writer.print(capitalizedComponentType);
+ //writer.print("ArrayRegion(env, ");
+ //writer.print(arrayRes);
+ //writer.print(", 0, ");
+ //writer.print(arrayResLength);
+ //writer.println(", _res);");
+ //writer.print(" return ");
+ //writer.print(arrayRes);
+ //writer.println(";");
+ }
}
}
}
@@ -1034,6 +1145,11 @@ public class CMethodBindingEmitter extends FunctionEmitter
throw new RuntimeException("Unsupported pointer type: \"" + cType.getName() + "\"");
}
}
+ else if (javaType.isArrayOfCompoundTypeWrappers())
+ {
+ // FIXME
+ throw new RuntimeException("Outgoing arrays of StructAccessors not yet implemented");
+ }
else
{
ptrTypeString = cType.getName();
diff --git a/src/net/java/games/gluegen/DebugEmitter.java b/src/net/java/games/gluegen/DebugEmitter.java
index 677c3e7e6..8618e1576 100644
--- a/src/net/java/games/gluegen/DebugEmitter.java
+++ b/src/net/java/games/gluegen/DebugEmitter.java
@@ -95,8 +95,13 @@ public class DebugEmitter implements GlueEmitter {
TypeDictionary structDictionary,
Map canonMap) {
}
- public void emitStruct(CompoundType t) {
- System.out.println("Referenced type \"" + t.getName() + "\"");
+ public void emitStruct(CompoundType t, String alternateName) {
+ String name = t.getName();
+ if (name == null && alternateName != null) {
+ name = alternateName;
+ }
+
+ System.out.println("Referenced type \"" + name + "\"");
}
public void endStructs() {}
}
diff --git a/src/net/java/games/gluegen/GlueEmitter.java b/src/net/java/games/gluegen/GlueEmitter.java
index 3d55474e0..e816ffc9d 100644
--- a/src/net/java/games/gluegen/GlueEmitter.java
+++ b/src/net/java/games/gluegen/GlueEmitter.java
@@ -93,7 +93,11 @@ public interface GlueEmitter {
public void beginStructs(TypeDictionary typedefDictionary,
TypeDictionary structDictionary,
Map canonMap) throws Exception;
- /** Emit glue code for the given CompoundType. */
- public void emitStruct(CompoundType t) throws Exception;
+ /** Emit glue code for the given CompoundType. alternateName is
+ provided when the CompoundType (e.g. "struct foo_t") has not
+ been typedefed to anything but the type of "pointer to struct
+ foo_t" has (e.g. "typedef struct foo_t {} *Foo"); in this case
+ alternateName would be set to Foo. */
+ public void emitStruct(CompoundType t, String alternateName) throws Exception;
public void endStructs() throws Exception;
}
diff --git a/src/net/java/games/gluegen/GlueGen.java b/src/net/java/games/gluegen/GlueGen.java
index 374611c81..2e5f3421a 100644
--- a/src/net/java/games/gluegen/GlueGen.java
+++ b/src/net/java/games/gluegen/GlueGen.java
@@ -241,20 +241,35 @@ public class GlueGen implements GlueEmitterControls {
System.err.println("WARNING: during forced struct emission: type \"" + name + "\" was not a struct");
} else {
type.visit(referencedStructs);
- }
+ }
}
// Lay out structs
emit.beginStructLayout();
for (Iterator iter = referencedStructs.results(); iter.hasNext(); ) {
- emit.layoutStruct((CompoundType) iter.next());
+ Type t = (Type) iter.next();
+ if (t.isCompound()) {
+ emit.layoutStruct(t.asCompound());
+ } else if (t.isPointer()) {
+ PointerType p = t.asPointer();
+ CompoundType c = p.getTargetType().asCompound();
+ emit.layoutStruct(c);
+ }
}
emit.endStructLayout();
// Emit structs
emit.beginStructs(td, sd, headerParser.getCanonMap());
for (Iterator iter = referencedStructs.results(); iter.hasNext(); ) {
- emit.emitStruct((CompoundType) iter.next());
+ Type t = (Type) iter.next();
+ if (t.isCompound()) {
+ emit.emitStruct(t.asCompound(), null);
+ } else if (t.isPointer()) {
+ PointerType p = t.asPointer();
+ CompoundType c = p.getTargetType().asCompound();
+ assert p.hasTypedefedName() && c.getName() == null : "ReferencedStructs incorrectly recorded pointer type " + p;
+ emit.emitStruct(c, p.getName());
+ }
}
emit.endStructs();
diff --git a/src/net/java/games/gluegen/JavaConfiguration.java b/src/net/java/games/gluegen/JavaConfiguration.java
index ecd953480..3950a7014 100644
--- a/src/net/java/games/gluegen/JavaConfiguration.java
+++ b/src/net/java/games/gluegen/JavaConfiguration.java
@@ -105,6 +105,7 @@ public class JavaConfiguration {
private List/*<String>*/ forcedStructs = new ArrayList();
private Map/*<String,List<Integer>>*/ mirroredArgs = new HashMap();
private Map/*<String, String>*/ returnValueCapacities = new HashMap();
+ private Map/*<String, String>*/ returnValueLengths = new HashMap();
private Map/*<String, List<String>>*/ temporaryCVariableDeclarations = new HashMap();
private Map/*<String, List<String>>*/ temporaryCVariableAssignments = new HashMap();
private Map/*<String,List<String>>*/ extendedInterfaces = new HashMap();
@@ -288,7 +289,9 @@ public class JavaConfiguration {
/** Provides a Java MessageFormat expression indicating the number
of elements in the returned array from the specified function
- name as defined by the ReturnsArray directive. */
+ name. Indicates that the given return value, which must be a
+ pointer to a CompoundType, is actually an array of the
+ CompoundType rather than a pointer to a single object. */
public String returnedArrayLength(String functionName) {
return (String) returnedArrayLengths.get(functionName);
}
@@ -378,6 +381,13 @@ public class JavaConfiguration {
return (String) returnValueCapacities.get(functionName);
}
+ /** Returns a MessageFormat string of the C expression calculating
+ the length of the array being returned from a native method, or
+ null if no expression has been specified. */
+ public String returnValueLength(String functionName) {
+ return (String) returnValueLengths.get(functionName);
+ }
+
/** Returns a List of Strings of expressions declaring temporary C
variables in the glue code for the specified function. */
public List/*<String>*/ temporaryCVariableDeclarations(String functionName) {
@@ -582,6 +592,10 @@ public class JavaConfiguration {
readReturnValueCapacity(tok, filename, lineNo);
// Warning: make sure delimiters are reset at the top of this loop
// because ReturnValueCapacity changes them.
+ } else if (cmd.equalsIgnoreCase("ReturnValueLength")) {
+ readReturnValueLength(tok, filename, lineNo);
+ // Warning: make sure delimiters are reset at the top of this loop
+ // because ReturnValueLength changes them.
} else if (cmd.equalsIgnoreCase("Include")) {
doInclude(tok, file, filename, lineNo);
} else if (cmd.equalsIgnoreCase("IncludeAs")) {
@@ -926,6 +940,18 @@ public class JavaConfiguration {
}
}
+ protected void readReturnValueLength(StringTokenizer tok, String filename, int lineNo) {
+ try {
+ String functionName = tok.nextToken();
+ String restOfLine = tok.nextToken("\n\r\f");
+ restOfLine = restOfLine.trim();
+ returnValueLengths.put(functionName, restOfLine);
+ } catch (NoSuchElementException e) {
+ throw new RuntimeException("Error parsing \"ReturnValueLength\" command at line " + lineNo +
+ " in file \"" + filename + "\"", e);
+ }
+ }
+
protected void readTemporaryCVariableDeclaration(StringTokenizer tok, String filename, int lineNo) {
try {
String functionName = tok.nextToken();
diff --git a/src/net/java/games/gluegen/JavaEmitter.java b/src/net/java/games/gluegen/JavaEmitter.java
index 228b5aff2..26e2a4f23 100644
--- a/src/net/java/games/gluegen/JavaEmitter.java
+++ b/src/net/java/games/gluegen/JavaEmitter.java
@@ -451,18 +451,26 @@ public class JavaEmitter implements GlueEmitter {
this.canonMap = canonMap;
}
- public void emitStruct(CompoundType structType) throws Exception {
- if (structType.getName() == null) {
+ public void emitStruct(CompoundType structType, String alternateName) throws Exception {
+ String name = structType.getName();
+ if (name == null && alternateName != null) {
+ name = alternateName;
+ }
+
+ if (name == null) {
System.err.println("WARNING: skipping emission of unnamed struct \"" + structType + "\"");
return;
}
- if (cfg.shouldIgnore(structType.getName())) {
+ if (cfg.shouldIgnore(name)) {
return;
}
Type containingCType = canonicalize(new PointerType(machDesc.pointerSizeInBytes(), structType, 0));
JavaType containingType = typeToJavaType(containingCType, false);
+ if (!containingType.isCompoundTypeWrapper()) {
+ return;
+ }
String containingTypeName = containingType.getName();
boolean needsNativeCode = false;
@@ -473,7 +481,7 @@ public class JavaEmitter implements GlueEmitter {
}
}
- String structClassPkg = cfg.packageForStruct(structType.getName());
+ String structClassPkg = cfg.packageForStruct(name);
PrintWriter writer = null;
PrintWriter cWriter = null;
try
@@ -534,7 +542,7 @@ public class JavaEmitter implements GlueEmitter {
for (int i = 0; i < structType.getNumFields(); i++) {
Field field = structType.getField(i);
Type fieldType = field.getType();
- if (!cfg.shouldIgnore(structType.getName() + " " + field.getName())) {
+ if (!cfg.shouldIgnore(name + " " + field.getName())) {
if (fieldType.isFunctionPointer()) {
try {
// Emit method call and associated native code
@@ -566,7 +574,7 @@ public class JavaEmitter implements GlueEmitter {
cWriter);
cEmitter.emit();
} catch (Exception e) {
- System.err.println("While processing field " + field + " of type " + structType.getName() + ":");
+ System.err.println("While processing field " + field + " of type " + name + ":");
throw(e);
}
} else if (fieldType.isCompound()) {
@@ -575,7 +583,7 @@ public class JavaEmitter implements GlueEmitter {
// a name?)
if (fieldType.getName() == null) {
throw new RuntimeException("Anonymous structs as fields not supported yet (field \"" +
- field + "\" in type \"" + structType.getName() + "\")");
+ field + "\" in type \"" + name + "\")");
}
writer.println();
@@ -586,7 +594,7 @@ public class JavaEmitter implements GlueEmitter {
// FIXME: add setter by autogenerating "copyTo" for all compound type wrappers
} else if (fieldType.isArray()) {
- System.err.println("WARNING: Array fields (field \"" + field + "\" of type \"" + structType.getName() +
+ System.err.println("WARNING: Array fields (field \"" + field + "\" of type \"" + name +
"\") not implemented yet");
} else {
JavaType javaType = null;
@@ -594,7 +602,7 @@ public class JavaEmitter implements GlueEmitter {
javaType = typeToJavaType(fieldType, false);
} catch (Exception e) {
System.err.println("Error occurred while creating accessor for field \"" +
- field.getName() + "\" in type \"" + structType.getName() + "\"");
+ field.getName() + "\" in type \"" + name + "\"");
e.printStackTrace();
throw(e);
}
@@ -629,10 +637,6 @@ public class JavaEmitter implements GlueEmitter {
writer.println(" }");
} else {
// FIXME
- String name = structType.getName();
- if (name == null) {
- name = structType.toString();
- }
System.err.println("WARNING: Complicated fields (field \"" + field + "\" of type \"" + name +
"\") not implemented yet");
// throw new RuntimeException("Complicated fields (field \"" + field + "\" of type \"" + t +
@@ -663,6 +667,7 @@ public class JavaEmitter implements GlueEmitter {
String bindingJavaClassName,
PrintWriter output) {
MessageFormat returnValueCapacityFormat = null;
+ MessageFormat returnValueLengthFormat = null;
JavaType javaReturnType = binding.getJavaReturnType();
if (javaReturnType.isNIOBuffer()) {
// See whether capacity has been specified
@@ -670,6 +675,12 @@ public class JavaEmitter implements GlueEmitter {
if (capacity != null) {
returnValueCapacityFormat = new MessageFormat(capacity);
}
+ } else if (javaReturnType.isArray()) {
+ // See whether length has been specified
+ String len = cfg.returnValueLength(binding.getName());
+ if (len != null) {
+ returnValueLengthFormat = new MessageFormat(len);
+ }
}
CMethodBindingEmitter cEmitter;
if (doingImplRoutine) {
@@ -686,6 +697,9 @@ public class JavaEmitter implements GlueEmitter {
if (returnValueCapacityFormat != null) {
cEmitter.setReturnValueCapacityExpression(returnValueCapacityFormat);
}
+ if (returnValueLengthFormat != null) {
+ cEmitter.setReturnValueLengthExpression(returnValueLengthFormat);
+ }
cEmitter.setTemporaryCVariableDeclarations(cfg.temporaryCVariableDeclarations(binding.getName()));
cEmitter.setTemporaryCVariableAssignments(cfg.temporaryCVariableAssignments(binding.getName()));
return cEmitter;
@@ -758,12 +772,21 @@ public class JavaEmitter implements GlueEmitter {
throw new RuntimeException("Arrays of compound types not handled yet");
}
// Special cases for known JNI types (in particular for converting jawt.h)
- if (cType.getName() != null &&
- cType.getName().equals("jobject")) {
+ if (t.getName() != null &&
+ t.getName().equals("jobject")) {
return javaType(java.lang.Object.class);
}
- return JavaType.createForCStruct(cfg.renameJavaType(targetType.getName()));
+ String name = targetType.getName();
+ if (name == null) {
+ // Try containing pointer type for any typedefs
+ name = t.getName();
+ if (name == null) {
+ throw new RuntimeException("Couldn't find a proper type name for pointer type " + t);
+ }
+ }
+
+ return JavaType.createForCStruct(cfg.renameJavaType(name));
} else {
throw new RuntimeException("Don't know how to convert pointer/array type \"" +
t + "\"");
@@ -775,15 +798,16 @@ public class JavaEmitter implements GlueEmitter {
// Get the target type of the target type (targetType was computer earlier
// as to be a pointer to the target type, so now we need to get its
// target type)
+ Type bottomType;
if (targetType.isPointer()) {
// t is<type>**, targetType is <type>*, we need to get <type>
- targetType = targetType.asPointer().getTargetType();
+ bottomType = targetType.asPointer().getTargetType();
} else {
// t is<type>[][], targetType is <type>[], we need to get <type>
- targetType = targetType.asArray().getElementType();
+ bottomType = targetType.asArray().getElementType();
}
- if (targetType.isInt()) {
- switch (targetType.getSize())
+ if (bottomType.isInt()) {
+ switch (bottomType.getSize())
{
case 1: return javaType(ArrayTypes.byteArrayArrayClass);
// FIXME: handle 2,4,8-byte int types here
@@ -793,10 +817,13 @@ public class JavaEmitter implements GlueEmitter {
"Java type; Currently, the only supported depth=2 " +
"pointer/array integer types are \"char**\" and \"char[][]\"");
}
+ } else if (targetType.isPointer() && (targetType.pointerDepth() == 1)) {
+ // Array of pointers; convert as array of StructAccessors
+ return JavaType.createForCArray(targetType);
} else {
throw new RuntimeException(
"Could not convert C type \"" + t + "\" " +
- "to appropriate Java type; need to add support for " +
+ "to appropriate Java type; need to add more support for " +
"depth=2 pointer/array types with non-integral target " +
"types [debug info: targetType=\"" + targetType + "\"]");
}
diff --git a/src/net/java/games/gluegen/JavaMethodBindingEmitter.java b/src/net/java/games/gluegen/JavaMethodBindingEmitter.java
index 003ea8643..850a2c701 100644
--- a/src/net/java/games/gluegen/JavaMethodBindingEmitter.java
+++ b/src/net/java/games/gluegen/JavaMethodBindingEmitter.java
@@ -122,7 +122,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
}
protected String getReturnTypeString(boolean skipArray) {
- if (skipArray || getReturnedArrayLengthExpression() == null) {
+ if (skipArray || (getReturnedArrayLengthExpression() == null && !binding.getJavaReturnType().isArrayOfCompoundTypeWrappers())) {
return binding.getJavaReturnType().getName();
}
return binding.getJavaReturnType().getName() + "[]";
diff --git a/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java b/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
index 2357e7c38..2ec2723bd 100644
--- a/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
+++ b/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
@@ -113,6 +113,9 @@ public class JavaMethodBindingImplEmitter extends JavaMethodBindingEmitter
returnType.isNIOByteBuffer()) {
writer.println("ByteBuffer _res;");
writer.print(" _res = ");
+ } else if (returnType.isArrayOfCompoundTypeWrappers()) {
+ writer.println("ByteBuffer[] _res;");
+ writer.print(" _res = ");
} else {
writer.print("return ");
}
@@ -205,7 +208,7 @@ public class JavaMethodBindingImplEmitter extends JavaMethodBindingEmitter
writer.println(" _tmp.order(ByteOrder.nativeOrder());");
writer.println(" _res.position(0);");
writer.println(" _res.limit(_res.capacity());");
- writer.println(" _retarray[_count] = new " + returnType.getName() + "(_tmp);");
+ writer.println(" _retarray[_count] = new " + getReturnTypeString(true) + "(_tmp);");
writer.println(" }");
writer.print (" return _retarray");
}
@@ -213,6 +216,14 @@ public class JavaMethodBindingImplEmitter extends JavaMethodBindingEmitter
writer.println(";");
writer.println(" if (_res == null) return null;");
writer.print(" return _res.order(ByteOrder.nativeOrder())");
+ } else if (returnType.isArrayOfCompoundTypeWrappers()) {
+ writer.println(";");
+ writer.println(" if (_res == null) return null;");
+ writer.println(" " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[_res.length];");
+ writer.println(" for (int _count = 0; _count < _res.length; _count++) {");
+ writer.println(" _retarray[_count] = new " + getReturnTypeString(true) + "(_res[_count]);");
+ writer.println(" }");
+ writer.print (" return _retarray");
}
writer.println(";");
}
diff --git a/src/net/java/games/gluegen/JavaType.java b/src/net/java/games/gluegen/JavaType.java
index ac42aa0f1..ea771613e 100644
--- a/src/net/java/games/gluegen/JavaType.java
+++ b/src/net/java/games/gluegen/JavaType.java
@@ -39,6 +39,10 @@
package net.java.games.gluegen;
+import java.nio.*;
+
+import net.java.games.gluegen.cgram.types.*;
+
/**
* Describes a java-side representation of a type that is used to represent
* the same data on both the Java-side and C-side during a JNI operation. Also
@@ -47,8 +51,10 @@ package net.java.games.gluegen;
public class JavaType {
private Class clazz; // Primitive types and other types representable as Class objects
private String name; // Types we're generating glue code for (i.e., C structs)
+ private Type elementType; // Element type if this JavaType represents a C array
private static JavaType nioBufferType;
private static JavaType nioByteBufferType;
+ private static JavaType nioByteBufferArrayType;
public boolean equals(Object arg) {
if ((arg == null) || (!(arg instanceof JavaType))) {
@@ -70,14 +76,28 @@ public class JavaType {
return clazz.hashCode();
}
+ /** Creates a JavaType corresponding to the given Java type. This
+ can be used to represent arrays of primitive values or Strings;
+ the emitters understand how to perform proper conversion from
+ the corresponding C type. */
public static JavaType createForClass(Class clazz) {
return new JavaType(clazz);
}
+ /** Creates a JavaType corresponding to the specified C CompoundType
+ name; for example, if "Foo" is supplied, then this JavaType
+ represents a "Foo *" by way of a StructAccessor. */
public static JavaType createForCStruct(String name) {
return new JavaType(name);
}
+ /** Creates a JavaType corresponding to an array of the given
+ element type. This is used to represent arrays of "Foo **" which
+ should be mapped to Foo[] in Java. */
+ public static JavaType createForCArray(Type elementType) {
+ return new JavaType(elementType);
+ }
+
public static JavaType createForVoidPointer() {
return new JavaType();
}
@@ -100,6 +120,14 @@ public class JavaType {
return nioByteBufferType;
}
+ public static JavaType forNIOByteBufferArrayClass() {
+ if (nioByteBufferArrayType == null) {
+ ByteBuffer[] tmp = new ByteBuffer[0];
+ nioByteBufferArrayType = createForClass(tmp.getClass());
+ }
+ return nioByteBufferArrayType;
+ }
+
/**
* Returns the Java Class corresponding to this type. Returns null if this
* object corresponds to a C "void*" type.
@@ -119,6 +147,9 @@ public class JavaType {
}
return clazz.getName();
}
+ if (elementType != null) {
+ return elementType.getName();
+ }
return name;
}
@@ -151,6 +182,10 @@ public class JavaType {
return "jobjectArray /*elements are String*/";
//return "jobjectArray";
}
+ else if (elementType == java.nio.ByteBuffer.class)
+ {
+ return "jobjectArray /*elements are ByteBuffer*/";
+ }
else if (elementType.isArray())
{
// Type is array-of-arrays-of-something
@@ -189,6 +224,10 @@ public class JavaType {
return (clazz == java.nio.ByteBuffer.class);
}
+ public boolean isNIOByteBufferArray() {
+ return (this == nioByteBufferArrayType);
+ }
+
public boolean isString() {
return (clazz == java.lang.String.class);
}
@@ -205,17 +244,16 @@ public class JavaType {
return (clazz == Void.TYPE);
}
- public boolean isObjectType() {
- // FIXME: what about char* -> String conversion?
- return (isNIOBuffer() || isArray());
- }
-
public boolean isCompoundTypeWrapper() {
return (clazz == null && name != null && !isJNIEnv());
}
+ public boolean isArrayOfCompoundTypeWrappers() {
+ return (elementType != null);
+ }
+
public boolean isVoidPointerType() {
- return (clazz == null && name == null);
+ return (clazz == null && name == null && elementType == null);
}
public boolean isJNIEnv() {
@@ -252,6 +290,11 @@ public class JavaType {
this.name = name;
}
+ /** Constructs a type representing an array of C pointers. */
+ private JavaType(Type elementType) {
+ this.elementType = elementType;
+ }
+
/**
* Default constructor; the type is initialized to the equivalent of a
* C-language "void *".
diff --git a/src/net/java/games/gluegen/MethodBinding.java b/src/net/java/games/gluegen/MethodBinding.java
index 9cdcd4b0b..b8f0eefdf 100644
--- a/src/net/java/games/gluegen/MethodBinding.java
+++ b/src/net/java/games/gluegen/MethodBinding.java
@@ -174,7 +174,8 @@ public class MethodBinding {
public boolean needsBody() {
if (!computedNeedsBody) {
if (javaReturnType.isCompoundTypeWrapper() ||
- javaReturnType.isNIOByteBuffer()) {
+ javaReturnType.isNIOByteBuffer() ||
+ javaReturnType.isArrayOfCompoundTypeWrappers()) {
// Needs wrapping and/or setting of byte order (neither of
// which can be done easily from native code)
needsBody = true;
@@ -204,6 +205,8 @@ public class MethodBinding {
binding.thisPointerIndex = thisPointerIndex;
if (javaReturnType.isCompoundTypeWrapper()) {
binding.setJavaReturnType(JavaType.forNIOByteBufferClass());
+ } else if (javaReturnType.isArrayOfCompoundTypeWrappers()) {
+ binding.setJavaReturnType(JavaType.forNIOByteBufferArrayClass());
} else {
binding.setJavaReturnType(javaReturnType);
}
diff --git a/src/net/java/games/gluegen/ReferencedStructs.java b/src/net/java/games/gluegen/ReferencedStructs.java
index 1b3b75198..4a7a8aadf 100644
--- a/src/net/java/games/gluegen/ReferencedStructs.java
+++ b/src/net/java/games/gluegen/ReferencedStructs.java
@@ -54,7 +54,18 @@ public class ReferencedStructs implements TypeVisitor {
}
public void visitType(Type t) {
- if (t.isCompound()) {
+ if (t.isPointer()) {
+ PointerType p = t.asPointer();
+ if (p.hasTypedefedName()) {
+ CompoundType c = p.getTargetType().asCompound();
+ if (c != null && c.getName() == null) {
+ // This otherwise-unnamed CompoundType is referred to by a
+ // PointerType that has a typedef name. Assume that it is
+ // referred to in the glue code and emit it.
+ results.add(p);
+ }
+ }
+ } else if (t.isCompound()) {
results.add(t);
}
}
diff --git a/src/net/java/games/gluegen/cgram/types/PointerType.java b/src/net/java/games/gluegen/cgram/types/PointerType.java
index 62bfe9c1a..64acbade4 100644
--- a/src/net/java/games/gluegen/cgram/types/PointerType.java
+++ b/src/net/java/games/gluegen/cgram/types/PointerType.java
@@ -100,6 +100,10 @@ public class PointerType extends Type {
}
}
+ public boolean hasTypedefedName() {
+ return hasTypedefedName;
+ }
+
public PointerType asPointer() { return this; }
public Type getTargetType() { return targetType; }
diff --git a/src/net/java/games/gluegen/opengl/BuildComposablePipeline.java b/src/net/java/games/gluegen/opengl/BuildComposablePipeline.java
index 47476a54c..c6ac77c7b 100644
--- a/src/net/java/games/gluegen/opengl/BuildComposablePipeline.java
+++ b/src/net/java/games/gluegen/opengl/BuildComposablePipeline.java
@@ -209,7 +209,7 @@ public class BuildComposablePipeline
{
output.print(" public ");
output.print(' ');
- output.print(m.getReturnType().getName());
+ output.print(JavaType.createForClass(m.getReturnType()).getName());
output.print(' ');
output.print(m.getName());
output.print('(');
diff --git a/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
index cd0554dc3..2a1559e52 100644
--- a/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
+++ b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
@@ -68,6 +68,15 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter
methodToWrap.getIsJavaMethodStatic(),
methodToWrap.getDefaultOutput()
);
+
+ if (methodToWrap.getReturnValueCapacityExpression() != null) {
+ setReturnValueCapacityExpression(methodToWrap.getReturnValueCapacityExpression());
+ }
+ if (methodToWrap.getReturnValueLengthExpression() != null) {
+ setReturnValueLengthExpression(methodToWrap.getReturnValueLengthExpression());
+ }
+ setTemporaryCVariableDeclarations(methodToWrap.getTemporaryCVariableDeclarations());
+ setTemporaryCVariableAssignments (methodToWrap.getTemporaryCVariableAssignments ());
setCommentEmitter(defaultCommentEmitter);
}
@@ -192,6 +201,13 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter
writer.println(");");
}
+ protected String jniMangle(MethodBinding binding) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(super.jniMangle(binding));
+ jniMangle(Long.TYPE, buf);
+ return buf.toString();
+ }
+
/** This class emits the comment for the wrapper method */
private static class CGLPAWrapperCommentEmitter extends CMethodBindingEmitter.DefaultCommentEmitter {
protected void emitBeginning(FunctionEmitter methodEmitter, PrintWriter writer) {
diff --git a/src/net/java/games/gluegen/opengl/GLEmitter.java b/src/net/java/games/gluegen/opengl/GLEmitter.java
index 27cc07e2c..f6e26fd3b 100644
--- a/src/net/java/games/gluegen/opengl/GLEmitter.java
+++ b/src/net/java/games/gluegen/opengl/GLEmitter.java
@@ -44,6 +44,7 @@ import java.text.MessageFormat;
import java.util.*;
import net.java.games.gluegen.*;
import net.java.games.gluegen.cgram.types.*;
+import net.java.games.gluegen.runtime.*;
/**
* A subclass of JavaEmitter that modifies the normal emission of C and Java
@@ -52,11 +53,12 @@ import net.java.games.gluegen.cgram.types.*;
*/
public class GLEmitter extends JavaEmitter
{
- public static final String PROCADDRESS_VAR_PREFIX = "_addressof_";
+ public static final String PROCADDRESS_VAR_PREFIX = ProcAddressHelper.PROCADDRESS_VAR_PREFIX;
protected static final String WRAP_PREFIX = "dispatch_";
private TypeDictionary typedefDictionary;
private PrintWriter tableWriter;
- private String tableClassName = "ProcAddressTable";
+ private String tableClassPackage;
+ private String tableClassName;
private int numProcAddressEntries;
public void beginFunctions(TypeDictionary typedefDictionary,
@@ -70,7 +72,7 @@ public class GLEmitter extends JavaEmitter
cWriter().println();
}
- if (((GLConfiguration)getConfig()).emitProcAddressTable())
+ if (getGLConfig().emitProcAddressTable())
{
beginGLProcAddressTable();
}
@@ -79,7 +81,7 @@ public class GLEmitter extends JavaEmitter
public void endFunctions() throws Exception
{
- if (((GLConfiguration)getConfig()).emitProcAddressTable())
+ if (getGLConfig().emitProcAddressTable())
{
endGLProcAddressTable();
}
@@ -118,7 +120,7 @@ public class GLEmitter extends JavaEmitter
// 9 is default # expanded bindings for void*
ArrayList modifiedEmitters = new ArrayList(9);
- if (((GLConfiguration)getConfig()).emitProcAddressTable())
+ if (getGLConfig().emitProcAddressTable())
{
// emit an entry in the GL proc address table for this method.
emitGLProcAddressTableEntryForSymbol(sym);
@@ -185,7 +187,7 @@ public class GLEmitter extends JavaEmitter
return null;
return baseJavaEmitter;
}
- return new JavaGLPAWrapperEmitter(baseJavaEmitter);
+ return new JavaGLPAWrapperEmitter(baseJavaEmitter, getGLConfig().getProcAddressTableExpr());
}
private CMethodBindingEmitter generateModifiedEmitter(CMethodBindingEmitter baseCEmitter)
@@ -205,11 +207,17 @@ public class GLEmitter extends JavaEmitter
{
String symName = sym.getName();
+ GLConfiguration config = getGLConfig();
+
// We should only wrap the GL symbol if its function pointer typedef has
// been defined (most likely in glext.h).
String funcPointerTypedefName = getGLFunctionPointerTypedefName(sym);
boolean shouldWrap = typedefDictionary.containsKey(funcPointerTypedefName);
//System.err.println(funcPointerTypedefName + " defined: " + shouldWrap);
+
+ if (config.skipProcAddressGen(symName)) {
+ shouldWrap = false;
+ }
if (!shouldWrap)
{
@@ -221,26 +229,27 @@ public class GLEmitter extends JavaEmitter
private void beginGLProcAddressTable() throws Exception
{
- String implPackageName = getImplPackageName();
+ tableClassPackage = getGLConfig().tableClassPackage();
+ tableClassName = getGLConfig().tableClassName();
+
+ // Table defaults to going into the impl directory unless otherwise overridden
+ String implPackageName = tableClassPackage;
+ if (implPackageName == null) {
+ implPackageName = getImplPackageName();
+ }
String jImplRoot =
getJavaOutputDir() + File.separator +
CodeGenUtils.packageAsPath(implPackageName);
- // HACK: until we have a way to make the impl dir different from the
- // WindowsGLImpl dir and the interface dir
- //tableWriter = openFile(jImplRoot + File.separator + tableClassName + ".java");
- File tmpFile = new File(jImplRoot);
- tmpFile = tmpFile.getParentFile();
- tmpFile = new File(tmpFile, tableClassName + ".java");
- tableWriter = openFile(tmpFile.getPath());
- // tableWriter = openFile(jImplRoot + File.separator + ".." + File.separator + tableClassName + ".java");
+ tableWriter = openFile(jImplRoot + File.separator + tableClassName + ".java");
CodeGenUtils.emitAutogeneratedWarning(tableWriter, this);
- // HACK: until we have a way to make the impl dir different from the
- // WindowsGLImpl dir and the interface dir
- //tableWriter.println("package " + implPackageName + ";");
- tableWriter.println("package " + getJavaPackageName() + ".impl;");
+ tableWriter.println("package " + implPackageName + ";");
+ tableWriter.println();
+ for (Iterator iter = getConfig().imports().iterator(); iter.hasNext(); ) {
+ tableWriter.println("import " + ((String) iter.next()) + ";");
+ }
tableWriter.println();
tableWriter.println("/**");
tableWriter.println(" * This table is a cache of the native pointers to OpenGL extension");
@@ -260,9 +269,6 @@ public class GLEmitter extends JavaEmitter
private void endGLProcAddressTable() throws Exception
{
PrintWriter w = tableWriter;
- w.print(" protected static long __PROCADDRESSINDEX__LASTINDEX = ");
- w.print(numProcAddressEntries-1);
- w.println(';');
w.println();
w.println(" /**");
@@ -301,30 +307,69 @@ public class GLEmitter extends JavaEmitter
private void emitGLProcAddressTableEntryForSymbol(FunctionSymbol cFunc)
{
- tableWriter.print(" public static long ");
+ tableWriter.print(" public long ");
tableWriter.print(PROCADDRESS_VAR_PREFIX);
tableWriter.print(cFunc.getName());
tableWriter.println(";");
++numProcAddressEntries;
}
+ private GLConfiguration getGLConfig() {
+ return (GLConfiguration) getConfig();
+ }
+
protected static class GLConfiguration extends JavaConfiguration
{
private boolean emitProcAddressTable = false;
-
+ private String tableClassPackage;
+ private String tableClassName = "ProcAddressTable";
+ private Set/*<String>*/ skipProcAddressGen = new HashSet();
+ private String getProcAddressTableExpr = "context.getGLProcAddressTable()";
+
protected void dispatch(String cmd, StringTokenizer tok, File file, String filename, int lineNo) throws IOException {
if (cmd.equalsIgnoreCase("EmitProcAddressTable"))
{
emitProcAddressTable =
readBoolean("EmitProcAddressTable", tok, filename, lineNo).booleanValue();
}
+ else if (cmd.equalsIgnoreCase("ProcAddressTablePackage"))
+ {
+ tableClassPackage = readString("ProcAddressTablePackage", tok, filename, lineNo);
+ }
+ else if (cmd.equalsIgnoreCase("ProcAddressTableClassName"))
+ {
+ tableClassName = readString("ProcAddressTableClassName", tok, filename, lineNo);
+ }
+ else if (cmd.equalsIgnoreCase("SkipProcAddressGen"))
+ {
+ String sym = readString("SkipProcAddressGen", tok, filename, lineNo);
+ skipProcAddressGen.add(sym);
+ }
+ else if (cmd.equalsIgnoreCase("GetProcAddressTableExpr"))
+ {
+ getProcAddressTableExpr = readGetProcAddressTableExpr(tok, filename, lineNo);
+ }
else
{
super.dispatch(cmd,tok,file,filename,lineNo);
}
}
- public boolean emitProcAddressTable() { return emitProcAddressTable; }
+ protected String readGetProcAddressTableExpr(StringTokenizer tok, String filename, int lineNo) {
+ try {
+ String restOfLine = tok.nextToken("\n\r\f");
+ return restOfLine.trim();
+ } catch (NoSuchElementException e) {
+ throw new RuntimeException("Error parsing \"GetProcAddressTableExpr\" command at line " + lineNo +
+ " in file \"" + filename + "\"", e);
+ }
+ }
+
+ public boolean emitProcAddressTable() { return emitProcAddressTable; }
+ public String tableClassPackage() { return tableClassPackage; }
+ public String tableClassName() { return tableClassName; }
+ public boolean skipProcAddressGen (String name) { return skipProcAddressGen.contains(name); }
+ public String getProcAddressTableExpr() { return getProcAddressTableExpr; }
} // end class GLConfiguration
}
diff --git a/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java b/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
index e0a098f2a..c3b17f6cb 100644
--- a/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
+++ b/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
@@ -50,10 +50,12 @@ public class JavaGLPAWrapperEmitter extends JavaMethodBindingImplEmitter
new WrappedMethodCommentEmitter();
private JavaMethodBindingEmitter emitterBeingWrapped;
+ private String getProcAddressTableExpr;
- public JavaGLPAWrapperEmitter(JavaMethodBindingEmitter methodToWrap)
+ public JavaGLPAWrapperEmitter(JavaMethodBindingEmitter methodToWrap, String getProcAddressTableExpr)
{
super(methodToWrap.getBinding(), methodToWrap.getDefaultOutput(), methodToWrap.getRuntimeExceptionType());
+ this.getProcAddressTableExpr = getProcAddressTableExpr;
if (methodToWrap.getBinding().hasContainingType())
{
@@ -119,6 +121,9 @@ public class JavaGLPAWrapperEmitter extends JavaMethodBindingImplEmitter
// Now make our binding use the original access of the wrapped method
this.addModifier(origAccess);
+ if (emitterBeingWrapped.hasModifier(STATIC)) {
+ this.addModifier(STATIC);
+ }
}
protected boolean needsBody() {
@@ -152,9 +157,7 @@ public class JavaGLPAWrapperEmitter extends JavaMethodBindingImplEmitter
String procAddressVariable =
GLEmitter.PROCADDRESS_VAR_PREFIX + wrappedBinding.getName();
- writer.print(" final long addr = context.getGLProcAddressTable().");
- writer.print(procAddressVariable);
- writer.println(';');
+ writer.println(" final long addr = " + getProcAddressTableExpr + "." + procAddressVariable + ";");
writer.println(" if (addr == 0) {");
writer.println(" throw new GLException(\"Method \\\"" + binding.getName() + "\\\" not available\");");
writer.println(" }");
diff --git a/src/net/java/games/gluegen/runtime/ProcAddressHelper.java b/src/net/java/games/gluegen/runtime/ProcAddressHelper.java
new file mode 100644
index 000000000..fec0eb366
--- /dev/null
+++ b/src/net/java/games/gluegen/runtime/ProcAddressHelper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2003 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
+ * MIDROSYSTEMS, 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 net.java.games.gluegen.runtime;
+
+/** Contains constants used in glue code generation. */
+
+public class ProcAddressHelper {
+ public static final String PROCADDRESS_VAR_PREFIX = "_addressof_";
+}
diff --git a/src/net/java/games/jogl/impl/GLContext.java b/src/net/java/games/jogl/impl/GLContext.java
index 98b1c6065..eb7d21988 100644
--- a/src/net/java/games/jogl/impl/GLContext.java
+++ b/src/net/java/games/jogl/impl/GLContext.java
@@ -42,6 +42,7 @@ package net.java.games.jogl.impl;
import java.awt.Component;
import java.awt.EventQueue;
import net.java.games.jogl.*;
+import net.java.games.gluegen.runtime.*;
public abstract class GLContext {
protected static final boolean DEBUG = false;
@@ -75,8 +76,10 @@ public abstract class GLContext {
// All GLU interfaces eventually route calls down to gluRoot. It can be
// static because GLU it doesn't actually need to own context, it just makes
// GL calls and assumes some context is active.
- protected static final GLU gluRoot = new GLUImpl();
- protected static GLU glu = gluRoot; // this is the context's GLU interface
+ protected static final GLUProcAddressTable gluProcAddressTable = new GLUProcAddressTable();
+ protected static final GLU gluRoot = new GLUImpl(gluProcAddressTable);
+ protected static boolean haveResetGLUProcAddressTable;
+ protected GLU glu = gluRoot; // this is the context's GLU interface
protected Thread renderingThread;
protected Runnable deferredReshapeAction;
@@ -282,6 +285,13 @@ public abstract class GLContext {
*/
protected void resetGLFunctionAvailability() {
functionAvailability.flush();
+ if (!haveResetGLUProcAddressTable) {
+ if (DEBUG) {
+ System.err.println("!!! Initializing GLU extension address table");
+ }
+ resetProcAddressTable(gluProcAddressTable);
+ haveResetGLUProcAddressTable = true; // Only need to do this once globally
+ }
}
/**
@@ -391,6 +401,40 @@ public abstract class GLContext {
conditions cause a GLException to be thrown. */
protected abstract void swapBuffers() throws GLException;
+ /** Helper routine which resets a ProcAddressTable generated by the
+ GLEmitter by looking up anew all of its function pointers. */
+ protected void resetProcAddressTable(Object table) {
+ Class tableClass = table.getClass();
+ java.lang.reflect.Field[] fields = tableClass.getDeclaredFields();
+
+ for (int i = 0; i < fields.length; ++i) {
+ String addressFieldName = fields[i].getName();
+ if (!addressFieldName.startsWith(ProcAddressHelper.PROCADDRESS_VAR_PREFIX)) {
+ // not a proc address variable
+ continue;
+ }
+ int startOfMethodName = ProcAddressHelper.PROCADDRESS_VAR_PREFIX.length();
+ String glFuncName = addressFieldName.substring(startOfMethodName);
+ try {
+ java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
+ assert(addressField.getType() == Long.TYPE);
+ long newProcAddress = dynamicLookupFunction(glFuncName);
+ // set the current value of the proc address variable in the table object
+ addressField.setLong(table, newProcAddress);
+ if (DEBUG) {
+ System.err.println(glFuncName + " = 0x" + Long.toHexString(newProcAddress));
+ }
+ } catch (Exception e) {
+ throw new GLException("Cannot get GL proc address for method \"" +
+ glFuncName + "\": Couldn't set value of field \"" + addressFieldName +
+ "\" in class " + tableClass.getName(), e);
+ }
+ }
+ }
+
+ /** Dynamically looks up the given function. */
+ protected abstract long dynamicLookupFunction(String glFuncName);
+
//----------------------------------------------------------------------
// Internals only below this point
//
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
index 23367c045..d35392ac1 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
@@ -41,7 +41,7 @@ package net.java.games.jogl.impl.macosx;
import java.awt.Component;
import java.util.*;
-import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX
+import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -49,6 +49,9 @@ public abstract class MacOSXGLContext extends GLContext
{
private static JAWT jawt;
protected long nsContext; // NSOpenGLContext
+ // Table that holds the addresses of the native C-language entry points for
+ // OpenGL functions.
+ private GLProcAddressTable glProcAddressTable;
public MacOSXGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser)
{
@@ -90,74 +93,25 @@ public abstract class MacOSXGLContext extends GLContext
protected abstract void swapBuffers() throws GLException;
+ protected long dynamicLookupFunction(String glFuncName) {
+ return CGL.getProcAddress(glFuncName);
+ }
protected void resetGLFunctionAvailability()
{
super.resetGLFunctionAvailability();
- resetGLProcAddressTable();
- }
-
- protected void resetGLProcAddressTable()
- {
if (DEBUG) {
System.err.println("!!! Initializing OpenGL extension address table");
}
-
- net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable();
-
- // if GL is no longer an interface, we'll have to re-implement the code
- // below so it only iterates through gl methods (a non-interface might
- // have constructors, custom methods, etc). For now we assume all methods
- // will be gl methods.
- GL gl = getGL();
-
- Class tableClass = table.getClass();
-
- java.lang.reflect.Field[] fields = tableClass.getDeclaredFields();
-
- for (int i = 0; i < fields.length; ++i) {
- String addressFieldName = fields[i].getName();
- if (!addressFieldName.startsWith(GLEmitter.PROCADDRESS_VAR_PREFIX))
- {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length();
- String glFuncName = addressFieldName.substring(startOfMethodName);
- try
- {
- java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
- assert(addressField.getType() == Long.TYPE);
- // get the current value of the proc address variable in the table object
- long oldProcAddress = addressField.getLong(table);
- long newProcAddress = CGL.getProcAddress(glFuncName);
- /*
- System.err.println(
- "!!! Address=" + (newProcAddress == 0
- ? "<NULL> "
- : ("0x" +
- Long.toHexString(newProcAddress))) +
- "\tGL func: " + glFuncName);
- */
- // set the current value of the proc address variable in the table object
- addressField.setLong(gl, newProcAddress);
- } catch (Exception e) {
- throw new GLException(
- "Cannot get GL proc address for method \"" +
- glFuncName + "\": Couldn't get value of field \"" + addressFieldName +
- "\" in class " + tableClass.getName(), e);
- }
- }
-
+ resetProcAddressTable(getGLProcAddressTable());
}
- public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable()
+ public GLProcAddressTable getGLProcAddressTable()
{
if (glProcAddressTable == null) {
// FIXME: cache ProcAddressTables by capability bits so we can
// share them among contexts with the same capabilities
- glProcAddressTable =
- new net.java.games.jogl.impl.ProcAddressTable();
+ glProcAddressTable = new GLProcAddressTable();
}
return glProcAddressTable;
}
@@ -171,10 +125,6 @@ public abstract class MacOSXGLContext extends GLContext
// Internals only below this point
//
- // Table that holds the addresses of the native C-language entry points for
- // OpenGL functions.
- private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable;
-
protected JAWT getJAWT()
{
if (jawt == null)
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index 4575b6210..5a6021acf 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -41,7 +41,7 @@ package net.java.games.jogl.impl.windows;
import java.awt.Component;
import java.util.*;
-import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX
+import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -53,6 +53,11 @@ public abstract class WindowsGLContext extends GLContext {
private boolean wglGetExtensionsStringEXTAvailable;
private static final Map/*<String, String>*/ functionNameMap;
private static final Map/*<String, String>*/ extensionNameMap;
+ // Table that holds the addresses of the native C-language entry points for
+ // OpenGL functions.
+ private GLProcAddressTable glProcAddressTable;
+ // Handle to GLU32.dll
+ private long hglu32;
static {
functionNameMap = new HashMap();
@@ -132,72 +137,34 @@ public abstract class WindowsGLContext extends GLContext {
protected abstract void swapBuffers() throws GLException;
+ protected long dynamicLookupFunction(String glFuncName) {
+ long res = WGL.wglGetProcAddress(glFuncName);
+ if (res == 0) {
+ // GLU routines aren't known to the OpenGL function lookup
+ if (hglu32 == 0) {
+ hglu32 = WGL.LoadLibraryA("GLU32");
+ if (hglu32 == 0) {
+ throw new GLException("Error loading GLU32.DLL");
+ }
+ }
+ res = WGL.GetProcAddress(hglu32, glFuncName);
+ }
+ return res;
+ }
protected void resetGLFunctionAvailability() {
super.resetGLFunctionAvailability();
- resetGLProcAddressTable();
- }
-
- protected void resetGLProcAddressTable() {
-
if (DEBUG) {
System.err.println("!!! Initializing OpenGL extension address table");
}
-
- net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable();
-
- // if GL is no longer an interface, we'll have to re-implement the code
- // below so it only iterates through gl methods (a non-interface might
- // have constructors, custom methods, etc). For now we assume all methods
- // will be gl methods.
- GL gl = getGL();
-
- Class tableClass = table.getClass();
-
- java.lang.reflect.Field[] fields = tableClass.getDeclaredFields();
-
- for (int i = 0; i < fields.length; ++i) {
- String addressFieldName = fields[i].getName();
- if (!addressFieldName.startsWith(GLEmitter.PROCADDRESS_VAR_PREFIX))
- {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length();
- String glFuncName = addressFieldName.substring(startOfMethodName);
- try
- {
- java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
- assert(addressField.getType() == Long.TYPE);
- // get the current value of the proc address variable in the table object
- long oldProcAddress = addressField.getLong(table);
- long newProcAddress = WGL.wglGetProcAddress(glFuncName);
- /*
- System.err.println(
- "!!! Address=" + (newProcAddress == 0
- ? "<NULL> "
- : ("0x" +
- Long.toHexString(newProcAddress))) +
- "\tGL func: " + glFuncName);
- */
- // set the current value of the proc address variable in the table object
- addressField.setLong(gl, newProcAddress);
- } catch (Exception e) {
- throw new GLException(
- "Cannot get GL proc address for method \"" +
- glFuncName + "\": Couldn't get value of field \"" + addressFieldName +
- "\" in class " + tableClass.getName(), e);
- }
- }
-
+ resetProcAddressTable(getGLProcAddressTable());
}
- public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() {
+ public GLProcAddressTable getGLProcAddressTable() {
if (glProcAddressTable == null) {
// FIXME: cache ProcAddressTables by capability bits so we can
// share them among contexts with the same capabilities
- glProcAddressTable =
- new net.java.games.jogl.impl.ProcAddressTable();
+ glProcAddressTable = new GLProcAddressTable();
}
return glProcAddressTable;
}
@@ -234,10 +201,6 @@ public abstract class WindowsGLContext extends GLContext {
// Internals only below this point
//
- // Table that holds the addresses of the native C-language entry points for
- // OpenGL functions.
- private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable;
-
protected JAWT getJAWT() {
if (jawt == null) {
JAWT j = new JAWT();
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
index 300e9cb85..484c8f8af 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
@@ -119,6 +119,10 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
public void createPbuffer(long parentHdc, long parentHglrc) {
GL gl = getGL();
+ // Must initally grab OpenGL function pointers while parent's
+ // context is current because otherwise we don't have the wgl
+ // extensions available to us
+ resetGLFunctionAvailability();
int[] iattributes = new int [2*MAX_ATTRIBS];
float[] fattributes = new float[2*MAX_ATTRIBS];
diff --git a/src/net/java/games/jogl/impl/x11/X11GLContext.java b/src/net/java/games/jogl/impl/x11/X11GLContext.java
index 8e9804578..ec430bfe8 100644
--- a/src/net/java/games/jogl/impl/x11/X11GLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11GLContext.java
@@ -41,7 +41,7 @@ package net.java.games.jogl.impl.x11;
import java.awt.Component;
import java.util.*;
-import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX
+import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -53,6 +53,11 @@ public abstract class X11GLContext extends GLContext {
private boolean glXQueryExtensionsStringInitialized;
private boolean glXQueryExtensionsStringAvailable;
private static final Map/*<String, String>*/ functionNameMap;
+ private boolean isGLX13;
+ // Table that holds the addresses of the native C-language entry points for
+ // OpenGL functions.
+ private GLProcAddressTable glProcAddressTable;
+ private static boolean haveResetGLXProcAddressTable;
static {
functionNameMap = new HashMap();
@@ -105,6 +110,14 @@ public abstract class X11GLContext extends GLContext {
*/
protected abstract void create();
+ public boolean isExtensionAvailable(String glExtensionName) {
+ if (glExtensionName.equals("GL_ARB_pbuffer") ||
+ glExtensionName.equals("GL_ARB_pixel_format")) {
+ return isGLX13;
+ }
+ return super.isExtensionAvailable(glExtensionName);
+ }
+
protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
boolean created = false;
if (context == 0) {
@@ -140,72 +153,44 @@ public abstract class X11GLContext extends GLContext {
protected abstract void swapBuffers() throws GLException;
+ protected long dynamicLookupFunction(String glFuncName) {
+ long res = GLX.glXGetProcAddressARB(glFuncName);
+ if (res == 0) {
+ // GLU routines aren't known to the OpenGL function lookup
+ res = GLX.dlsym(glFuncName);
+ }
+ return res;
+ }
protected void resetGLFunctionAvailability() {
super.resetGLFunctionAvailability();
- resetGLProcAddressTable();
- }
-
- protected void resetGLProcAddressTable() {
-
if (DEBUG) {
System.err.println("!!! Initializing OpenGL extension address table");
}
+ resetProcAddressTable(getGLProcAddressTable());
- net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable();
-
- // if GL is no longer an interface, we'll have to re-implement the code
- // below so it only iterates through gl methods (a non-interface might
- // have constructors, custom methods, etc). For now we assume all methods
- // will be gl methods.
- GL gl = getGL();
-
- Class tableClass = table.getClass();
-
- java.lang.reflect.Field[] fields = tableClass.getDeclaredFields();
-
- for (int i = 0; i < fields.length; ++i) {
- String addressFieldName = fields[i].getName();
- if (!addressFieldName.startsWith(GLEmitter.PROCADDRESS_VAR_PREFIX))
- {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length();
- String glFuncName = addressFieldName.substring(startOfMethodName);
- try
- {
- java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
- assert(addressField.getType() == Long.TYPE);
- // get the current value of the proc address variable in the table object
- long oldProcAddress = addressField.getLong(table);
- long newProcAddress = GLX.glXGetProcAddressARB(glFuncName);
- /*
- System.err.println(
- "!!! Address=" + (newProcAddress == 0
- ? "<NULL> "
- : ("0x" +
- Long.toHexString(newProcAddress))) +
- "\tGL func: " + glFuncName);
- */
- // set the current value of the proc address variable in the table object
- addressField.setLong(gl, newProcAddress);
- } catch (Exception e) {
- throw new GLException(
- "Cannot get GL proc address for method \"" +
- glFuncName + "\": Couldn't get value of field \"" + addressFieldName +
- "\" in class " + tableClass.getName(), e);
- }
+ if (!haveResetGLXProcAddressTable) {
+ resetProcAddressTable(GLX.getGLXProcAddressTable());
}
+ // Figure out whether we are running GLX version 1.3 or above and
+ // therefore have pbuffer support
+ if (display == 0) {
+ throw new GLException("Expected non-null DISPLAY for querying GLX version");
+ }
+ int[] major = new int[1];
+ int[] minor = new int[1];
+ if (!GLX.glXQueryVersion(display, major, minor)) {
+ throw new GLException("glXQueryVersion failed");
+ }
+ isGLX13 = ((major[0] > 1) || (minor[0] > 2));
}
- public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() {
+ public GLProcAddressTable getGLProcAddressTable() {
if (glProcAddressTable == null) {
// FIXME: cache ProcAddressTables by capability bits so we can
// share them among contexts with the same capabilities
- glProcAddressTable =
- new net.java.games.jogl.impl.ProcAddressTable();
+ glProcAddressTable = new GLProcAddressTable();
}
return glProcAddressTable;
}
@@ -245,10 +230,6 @@ public abstract class X11GLContext extends GLContext {
// Internals only below this point
//
- // Table that holds the addresses of the native C-language entry points for
- // OpenGL functions.
- private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable;
-
protected JAWT getJAWT() {
if (jawt == null) {
JAWT j = new JAWT();
diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
index 496e113a5..385874da7 100644
--- a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
@@ -40,6 +40,8 @@
package net.java.games.jogl.impl.x11;
import java.awt.Component;
+import java.util.*;
+
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -49,6 +51,9 @@ public class X11OnscreenGLContext extends X11GLContext {
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_X11DrawingSurfaceInfo x11dsi;
+ // Variables for pbuffer support
+ List pbuffersToInstantiate = new ArrayList();
+
public X11OnscreenGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) {
super(component, capabilities, chooser);
}
@@ -75,14 +80,16 @@ public class X11OnscreenGLContext extends X11GLContext {
}
public boolean canCreatePbufferContext() {
- // For now say no
- return false;
+ // FIXME: should we gate this on GLX 1.3 being available?
+ return true;
}
public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
int initialWidth,
int initialHeight) {
- throw new GLException("Not yet supported");
+ X11PbufferGLContext ctx = new X11PbufferGLContext(capabilities, initialWidth, initialHeight);
+ pbuffersToInstantiate.add(ctx);
+ return ctx;
}
public void bindPbufferToTexture() {
@@ -98,7 +105,16 @@ public class X11OnscreenGLContext extends X11GLContext {
if (!lockSurface()) {
return false;
}
- return super.makeCurrent(initAction);
+ boolean ret = super.makeCurrent(initAction);
+ if (ret) {
+ // Instantiate any pending pbuffers
+ while (!pbuffersToInstantiate.isEmpty()) {
+ X11PbufferGLContext ctx =
+ (X11PbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
+ ctx.createPbuffer(display, context);
+ }
+ }
+ return ret;
} catch (RuntimeException e) {
try {
unlockSurface();
diff --git a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
new file mode 100644
index 000000000..264d60fc7
--- /dev/null
+++ b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2003 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
+ * MIDROSYSTEMS, 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 net.java.games.jogl.impl.x11;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class X11PbufferGLContext extends X11GLContext {
+ private static final boolean DEBUG = false;
+
+ private int initWidth;
+ private int initHeight;
+
+ private long buffer; // GLXPbuffer
+ private GLXFBConfig fbConfig;
+ private int width;
+ private int height;
+
+ // FIXME: kept around because we create the OpenGL context lazily to
+ // better integrate with the X11GLContext framework
+ private long parentContext;
+
+ private static final int MAX_PFORMATS = 256;
+ private static final int MAX_ATTRIBS = 256;
+
+ // FIXME: figure out how to support render-to-texture and
+ // render-to-texture-rectangle (which appear to be supported, though
+ // it looks like floating-point buffers are not)
+
+ public X11PbufferGLContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ super(null, capabilities, null);
+ this.initWidth = initialWidth;
+ this.initHeight = initialHeight;
+ if (initWidth <= 0 || initHeight <= 0) {
+ throw new GLException("Initial width and height of pbuffer must be positive (were (" +
+ initWidth + ", " + initHeight + "))");
+ }
+ }
+
+ public boolean canCreatePbufferContext() {
+ return false;
+ }
+
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ throw new GLException("Not supported");
+ }
+
+ public void bindPbufferToTexture() {
+ // FIXME: figure out how to implement this
+ throw new GLException("Not yet implemented");
+ }
+
+ public void releasePbufferFromTexture() {
+ // FIXME: figure out how to implement this
+ throw new GLException("Not yet implemented");
+ }
+
+ public void createPbuffer(long display, long parentContext) {
+ if (display == 0) {
+ throw new GLException("Null display");
+ }
+
+ if (parentContext == 0) {
+ throw new GLException("Null parentContext");
+ }
+
+ if (capabilities.getOffscreenFloatingPointBuffers()) {
+ throw new GLException("Floating-point pbuffers not supported yet on X11");
+ }
+
+ if (capabilities.getOffscreenRenderToTexture()) {
+ throw new GLException("Render-to-texture pbuffers not supported yet on X11");
+ }
+
+ if (capabilities.getOffscreenRenderToTextureRectangle()) {
+ throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11");
+ }
+
+ int[] iattributes = new int [2*MAX_ATTRIBS];
+ float[] fattributes = new float[2*MAX_ATTRIBS];
+ int nfattribs = 0;
+ int niattribs = 0;
+
+ // Since we are trying to create a pbuffer, the GLXFBConfig we
+ // request (and subsequently use) must be "p-buffer capable".
+ iattributes[niattribs++] = GL.GLX_DRAWABLE_TYPE;
+ iattributes[niattribs++] = GL.GLX_PBUFFER_BIT;
+
+ iattributes[niattribs++] = GL.GLX_RENDER_TYPE;
+ iattributes[niattribs++] = GL.GLX_RGBA_BIT;
+
+ iattributes[niattribs++] = GLX.GLX_DOUBLEBUFFER;
+ if (capabilities.getDoubleBuffered()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = GLX.GLX_DEPTH_SIZE;
+ iattributes[niattribs++] = capabilities.getDepthBits();
+
+ iattributes[niattribs++] = GLX.GLX_RED_SIZE;
+ iattributes[niattribs++] = capabilities.getRedBits();
+
+ iattributes[niattribs++] = GLX.GLX_GREEN_SIZE;
+ iattributes[niattribs++] = capabilities.getGreenBits();
+
+ iattributes[niattribs++] = GLX.GLX_BLUE_SIZE;
+ iattributes[niattribs++] = capabilities.getBlueBits();
+
+ iattributes[niattribs++] = GLX.GLX_ALPHA_SIZE;
+ iattributes[niattribs++] = capabilities.getAlphaBits();
+
+ if (capabilities.getStencilBits() > 0) {
+ iattributes[niattribs++] = GLX.GLX_STENCIL_SIZE;
+ iattributes[niattribs++] = capabilities.getStencilBits();
+ }
+
+ if (capabilities.getAccumRedBits() > 0 ||
+ capabilities.getAccumGreenBits() > 0 ||
+ capabilities.getAccumBlueBits() > 0) {
+ iattributes[niattribs++] = GLX.GLX_ACCUM_RED_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumRedBits();
+ iattributes[niattribs++] = GLX.GLX_ACCUM_GREEN_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumGreenBits();
+ iattributes[niattribs++] = GLX.GLX_ACCUM_BLUE_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumBlueBits();
+ }
+
+ iattributes[niattribs++] = 0; // null-terminate
+
+ int screen = 0; // FIXME: provide way to specify this?
+ int[] nelementsTmp = new int[1];
+ GLXFBConfig[] fbConfigs = GLX.glXChooseFBConfig(display, screen, iattributes, nelementsTmp);
+ if (fbConfigs == null || fbConfigs.length == 0 || fbConfigs[0] == null) {
+ throw new GLException("pbuffer creation error: glXChooseFBConfig() failed");
+ }
+ // Note that we currently don't allow selection of anything but
+ // the first GLXFBConfig in the returned list
+ GLXFBConfig fbConfig = fbConfigs[0];
+ int nelements = nelementsTmp[0];
+ if (nelements <= 0) {
+ throw new GLException("pbuffer creation error: couldn't find a suitable frame buffer configuration");
+ }
+
+ if (DEBUG) {
+ System.err.println("Found " + fbConfigs.length + " matching GLXFBConfigs");
+ System.err.println("Parameters of default one:");
+ System.err.println("render type: 0x" + Integer.toHexString(queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE)));
+ System.err.println("rgba: " + ((queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE) & GLX.GLX_RGBA_BIT) != 0));
+ System.err.println("r: " + queryFBConfig(display, fbConfig, GLX.GLX_RED_SIZE));
+ System.err.println("g: " + queryFBConfig(display, fbConfig, GLX.GLX_GREEN_SIZE));
+ System.err.println("b: " + queryFBConfig(display, fbConfig, GLX.GLX_BLUE_SIZE));
+ System.err.println("a: " + queryFBConfig(display, fbConfig, GLX.GLX_ALPHA_SIZE));
+ System.err.println("depth: " + queryFBConfig(display, fbConfig, GLX.GLX_DEPTH_SIZE));
+ System.err.println("double buffered: " + queryFBConfig(display, fbConfig, GLX.GLX_DOUBLEBUFFER));
+ }
+
+ // Create the p-buffer.
+ niattribs = 0;
+
+ iattributes[niattribs++] = GL.GLX_PBUFFER_WIDTH;
+ iattributes[niattribs++] = initWidth;
+ iattributes[niattribs++] = GL.GLX_PBUFFER_HEIGHT;
+ iattributes[niattribs++] = initHeight;
+
+ iattributes[niattribs++] = 0;
+
+ int tmpBuffer = GLX.glXCreatePbuffer(display, fbConfig, iattributes);
+ if (tmpBuffer == 0) {
+ // FIXME: query X error code for detail error message
+ throw new GLException("pbuffer creation error: glXCreatePbuffer() failed");
+ }
+
+ // Set up instance variables
+ this.display = display;
+ this.parentContext = parentContext;
+ buffer = tmpBuffer;
+ this.fbConfig = fbConfig;
+
+ // Determine the actual width and height we were able to create.
+ int[] tmp = new int[1];
+ GLX.glXQueryDrawable(display, (int) buffer, GL.GLX_WIDTH, tmp);
+ width = tmp[0];
+ GLX.glXQueryDrawable(display, (int) buffer, GL.GLX_HEIGHT, tmp);
+ height = tmp[0];
+
+ if (DEBUG) {
+ System.err.println("Created pbuffer " + width + " x " + height);
+ }
+ }
+
+ protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ if (buffer == 0) {
+ // pbuffer not instantiated yet
+ return false;
+ }
+
+ lockAWT();
+ try {
+ boolean created = false;
+ if (context == 0) {
+ create();
+ if (DEBUG) {
+ System.err.println("!!! Created GL context for " + getClass().getName());
+ }
+ created = true;
+ }
+
+ // FIXME: this cast to int would be wrong on 64-bit platforms
+ // where the argument type to glXMakeCurrent would change (should
+ // probably make GLXDrawable, and maybe XID, Opaque as long)
+ if (!GLX.glXMakeContextCurrent(display, (int) buffer, (int) buffer, context)) {
+ throw new GLException("Error making context current");
+ }
+
+ if (created) {
+ resetGLFunctionAvailability();
+ initAction.run();
+ }
+ return true;
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ protected synchronized void free() throws GLException {
+ lockAWT();
+ try {
+ if (!GLX.glXMakeContextCurrent(display, 0, 0, 0)) {
+ throw new GLException("Error freeing OpenGL context");
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void handleModeSwitch(long parentHdc, long parentHglrc) {
+ throw new GLException("Not yet implemented");
+ }
+
+ protected boolean isOffscreen() {
+ // FIXME: currently the only caller of this won't cause proper
+ // resizing of the pbuffer anyway.
+ return false;
+ }
+
+ public int getOffscreenContextBufferedImageType() {
+ throw new GLException("Should not call this");
+ }
+
+ public int getOffscreenContextReadBuffer() {
+ throw new GLException("Should not call this");
+ }
+
+ public boolean offscreenImageNeedsVerticalFlip() {
+ throw new GLException("Should not call this");
+ }
+
+ protected void create() {
+ if (DEBUG) {
+ System.err.println("Creating context for pbuffer " + width + " x " + height);
+ }
+
+ // Create a gl context for the p-buffer.
+ // FIXME: provide option to not share display lists with subordinate pbuffer?
+ context = GLX.glXCreateNewContext(display, fbConfig, GL.GLX_RGBA_TYPE, parentContext, true);
+ if (context == 0) {
+ throw new GLException("pbuffer creation error: glXCreateNewContext() failed");
+ }
+
+ if (DEBUG) {
+ System.err.println("Created context for pbuffer " + width + " x " + height);
+ }
+ }
+
+ protected void swapBuffers() throws GLException {
+ // FIXME: do we need to do anything if the pbuffer is double-buffered?
+ }
+
+ private int queryFBConfig(long display, GLXFBConfig fbConfig, int attrib) {
+ int[] tmp = new int[1];
+ if (GLX.glXGetFBConfigAttrib(display, fbConfig, attrib, tmp) != 0) {
+ throw new GLException("glXGetFBConfigAttrib failed");
+ }
+ return tmp[0];
+ }
+
+ // These synchronization primitives, which prevent the AWT from
+ // making requests from the X server asynchronously to this code,
+ // are required for pbuffers to work properly on X11.
+ private void lockAWT() {
+ getJAWT().Lock();
+ }
+
+ private void unlockAWT() {
+ getJAWT().Unlock();
+ }
+}