diff options
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(); + } +} |