From: <eli...@us...> - 2008-09-07 08:21:30
|
Revision: 3122 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3122&view=rev Author: elias_naur Date: 2008-09-07 08:21:28 +0000 (Sun, 07 Sep 2008) Log Message: ----------- Bumped all jni versions Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java Modified: trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java 2008-09-07 08:16:11 UTC (rev 3121) +++ trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java 2008-09-07 08:21:28 UTC (rev 3122) @@ -39,7 +39,7 @@ * $Id$ */ final class LinuxSysImplementation extends J2SESysImplementation { - private final static int JNI_VERSION = 16; + private final static int JNI_VERSION = 17; static { java.awt.Toolkit.getDefaultToolkit(); // This will make sure libjawt.so is loaded Modified: trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java 2008-09-07 08:16:11 UTC (rev 3121) +++ trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java 2008-09-07 08:21:28 UTC (rev 3122) @@ -42,7 +42,7 @@ * $Id$ */ final class MacOSXSysImplementation extends J2SESysImplementation { - private final static int JNI_VERSION = 16; + private final static int JNI_VERSION = 17; static { // Make sure AWT is properly initialized. This avoids hangs on Mac OS X 10.3 Modified: trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java 2008-09-07 08:16:11 UTC (rev 3121) +++ trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java 2008-09-07 08:21:28 UTC (rev 3122) @@ -45,7 +45,7 @@ * $Id$ */ final class WindowsSysImplementation extends DefaultSysImplementation { - private final static int JNI_VERSION = 19; + private final static int JNI_VERSION = 20; static { Sys.initialize(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <eli...@us...> - 2008-12-28 19:30:50
|
Revision: 3172 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3172&view=rev Author: elias_naur Date: 2008-12-28 19:30:43 +0000 (Sun, 28 Dec 2008) Log Message: ----------- Added Display.setDisplayModeAndFullscreen(mode) to switch mode and set fullscreen in one call (idea stolen from MatthiasM). Tweaked FullScreenWindowedTest to use the new method. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java 2008-12-28 17:50:08 UTC (rev 3171) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java 2008-12-28 19:30:43 UTC (rev 3172) @@ -496,10 +496,33 @@ * from getAvailableDisplayModes() or if the mode switch fails. */ public static void setFullscreen(boolean fullscreen) throws LWJGLException { + setDisplayModeAndFullscreenInternal(fullscreen, current_mode); + } + + /** + * Set the mode of the context. If no context has been created through create(), + * the mode will apply when create() is called. If mode.isFullscreenCapable() is true, the context will become + * a fullscreen context and the display mode is switched to the mode given by getDisplayMode(). If + * mode.isFullscreenCapable() is false, the context will become a windowed context with the dimensions given in the + * mode returned by getDisplayMode(). The native cursor position is also reset. + * + * @param mode The new display mode to set. Must be non-null. + * + * @throws LWJGLException If the mode switch fails. + */ + public static void setDisplayModeAndFullscreen(DisplayMode mode) throws LWJGLException { + setDisplayModeAndFullscreenInternal(mode.isFullscreenCapable(), mode); + } + + private static void setDisplayModeAndFullscreenInternal(boolean fullscreen, DisplayMode mode) throws LWJGLException { synchronized ( GlobalLock.lock ) { + if (mode == null) + throw new NullPointerException("mode must be non-null"); + DisplayMode old_mode = current_mode; + current_mode = mode; boolean was_fullscreen = isFullscreen(); Display.fullscreen = fullscreen; - if (was_fullscreen != isFullscreen()) { + if (was_fullscreen != isFullscreen() || !mode.equals(old_mode)) { if (!isCreated()) return; destroyWindow(); Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java 2008-12-28 17:50:08 UTC (rev 3171) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java 2008-12-28 19:30:43 UTC (rev 3172) @@ -74,13 +74,19 @@ mainLoop(); cleanup(); } + + private void switchMode() throws LWJGLException { + mode = findDisplayMode(800, 600, Display.getDisplayMode().getBitsPerPixel()); + Display.setDisplayModeAndFullscreen(mode); + } + /** * Initializes the test */ private void initialize() { try { //find displaymode - mode = findDisplayMode(800, 600, Display.getDisplayMode().getBitsPerPixel()); + switchMode(); // start of in windowed mode Display.create(); glInit(); @@ -163,7 +169,7 @@ //check for fullscreen key if (Keyboard.isKeyDown(Keyboard.KEY_F)) { try { - Display.setFullscreen(true); + switchMode(); } catch (Exception e) { e.printStackTrace(); } @@ -171,7 +177,9 @@ //check for window key if (Keyboard.isKeyDown(Keyboard.KEY_W)) { try { - Display.setFullscreen(false); + mode = new DisplayMode(640, 480); + Display.setDisplayModeAndFullscreen(mode); + glInit(); } catch (Exception e) { e.printStackTrace(); } @@ -237,15 +245,10 @@ DisplayMode[] modes = Display.getAvailableDisplayModes(); for (int i = 0; i < modes.length; i++) { if (modes[i].getWidth() == width && modes[i].getHeight() == height && modes[i].getBitsPerPixel() >= bpp && modes[i].getFrequency() <= 60) { - try { - Display.setDisplayMode(modes[i]); - } catch (LWJGLException e) { - e.printStackTrace(); - } return modes[i]; } } - return Display.getDisplayMode(); + return Display.getDesktopDisplayMode(); } /** * Initializes OGL This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2009-04-04 19:19:47
|
Revision: 3194 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3194&view=rev Author: spasi Date: 2009-04-04 19:19:43 +0000 (Sat, 04 Apr 2009) Log Message: ----------- Fixed ContextAttribs version validation. Added OpenGL version test. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java 2009-03-27 12:56:14 UTC (rev 3193) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java 2009-04-04 19:19:43 UTC (rev 3194) @@ -72,7 +72,7 @@ if ( majorVersion < 0 || 3 < majorVersion || minorVersion < 0 || - (majorVersion == 3 && 0 < minorVersion) || + (majorVersion == 3 && 1 < minorVersion) || (majorVersion == 2 && 1 < minorVersion) || (majorVersion == 1 && 5 < minorVersion) ) throw new IllegalArgumentException("Invalid OpenGL version specified: " + majorVersion + '.' + minorVersion); Added: trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java 2009-04-04 19:19:43 UTC (rev 3194) @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Created by LWJGL. + * User: spasi + * Date: 2009-04-04 + * Time: 21:20:24 pm + */ + +package org.lwjgl.test.opengl; + +import org.lwjgl.LWJGLException; +import org.lwjgl.opengl.*; + +import java.util.StringTokenizer; +import java.util.regex.Pattern; + +public final class VersionTest { + + private VersionTest() { + } + + public static void main(String[] args) { + initialize(args); + cleanup(); + System.exit(0); + } + + private static void initialize(String[] args) { + if ( args.length < 2 ) + argsError("Insufficient number of arguments"); + + int majorInput = 1; + int minorInput = 0; + + try { + majorInput = Integer.parseInt(args[0]); + minorInput = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + argsError("Invalid number format"); + } + + ContextAttribs ca = new ContextAttribs(majorInput, minorInput); + + if ( 2 < args.length ) { + for ( int i = 2; i < args.length; i++ ) { + if ( Pattern.matches("[0-9]+", args[i]) ) + ca = ca.withLayer(Integer.parseInt(args[i])); + else if ( "debug".equalsIgnoreCase(args[i]) ) + ca = ca.withDebug(true); + else if ( "fc".equalsIgnoreCase(args[i]) ) + ca = ca.withForwardCompatible(true); + else + argsError("Unknown argument: \'" + args[i] + "\'"); + } + } + + try { + DisplayMode[] modes = Display.getAvailableDisplayModes(); + + DisplayMode displayMode; + + displayMode = chooseMode(modes, 1024, 768); + if ( displayMode == null ) + displayMode = chooseMode(modes, 800, 600); + if ( displayMode == null ) + displayMode = chooseMode(modes, 640, 480); + if ( displayMode == null ) + kill("Failed to set an appropriate display mode."); + + System.out.println("Setting display mode to: " + displayMode); + Display.setDisplayMode(displayMode); + Display.create(new PixelFormat(8, 24, 0), ca); + } catch (LWJGLException e) { + kill(e.getMessage()); + } + + System.out.println("\n---------\n"); + + final String version = GL11.glGetString(GL11.GL_VERSION); + + System.out.println("GL Version requested: " + majorInput + '.' + minorInput); + System.out.println("GL Version returned : " + version); + + final StringTokenizer version_tokenizer = new StringTokenizer(version, ". "); + + int majorVersion = Integer.parseInt(version_tokenizer.nextToken()); + int minorVersion = Integer.parseInt(version_tokenizer.nextToken()); + + if ( majorVersion != majorInput || minorVersion != minorInput ) { + if ( majorInput == 1 && minorInput == 0 ) + System.out.println("\tThe maximum supported version has been returned. The driver is well-behaved. :)"); + else if ( majorInput < 3 && majorVersion < 3 ) + System.out.println("\tThe maximum supported version pre-3.0 has been returned. The driver is well-behaved. :)"); + else + System.out.println("\tThe requested version was not returned. The driver is buggy! :("); + } else + System.out.println("\tThe requested version was returned. :)"); + + System.out.println("\n---------\n"); + + System.out.println("Debug mode: " + ca.isDebug()); + System.out.println("Forward compatible mode: " + ca.isForwardCompatible()); + System.out.println("ARB_compatibility: " + GLContext.getCapabilities().GL_ARB_compatibility); + try { + GL11.glVertex3f(0.0f, 0.0f, 0.0f); + System.out.println("Deprecated functionality present: " + true); + } catch (Throwable t) { + System.out.println("Deprecated functionality present: " + false); + if ( GLContext.getCapabilities().GL_ARB_compatibility ) { + System.out.println("\tARB_compatibility is present, but LWJGL has enabled pseudo-forward compatible mode."); + } + } + } + + private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) { + DisplayMode bestMode = null; + + for ( int i = 0; i < modes.length; i++ ) { + DisplayMode mode = modes[i]; + if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) { + if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) ) + bestMode = mode; + } + } + + return bestMode; + } + + private static void cleanup() { + if ( Display.isCreated() ) + Display.destroy(); + } + + private static void argsError(final String msg) { + System.out.println("\nInvalid arguments error: " + msg); + System.out.println("\nUsage: VersionTest <majorVersion> <minorVersion> {<layer>, 'debug', 'fc'}:\n"); + System.out.println("majorVersion\t- Major OpenGL version."); + System.out.println("majorVersion\t- Minor OpenGL version."); + System.out.println("layer\t- Layer plane (optional)."); + System.out.println("debug\t- Enables debug mode (optional)."); + System.out.println("fc\t- Enables forward compatibility mode (optional)."); + + cleanup(); + System.exit(-1); + } + + static void kill(String reason) { + System.out.println("The VersionTest program was terminated because an error occured.\n"); + System.out.println("Reason: " + (reason == null ? "Unknown" : reason)); + + cleanup(); + System.exit(-1); + } + +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kev...@us...> - 2009-04-05 22:07:55
|
Revision: 3195 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3195&view=rev Author: kevglass Date: 2009-04-05 22:07:46 +0000 (Sun, 05 Apr 2009) Log Message: ----------- Ported GLU tessellation code from JOGL to work within LWJGL Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/util/glu/GLU.java Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/test/glu/ trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/ trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessCallback.java trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessellationTest.java trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/VertexData.java trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellator.java trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallback.java trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallbackAdapter.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/ trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/ActiveRegion.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/CachedVertex.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Dict.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/DictNode.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/GLUface.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/GLUhalfEdge.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/GLUmesh.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/GLUtessellatorImpl.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/GLUvertex.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Geom.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Mesh.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Normal.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/PriorityQ.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/PriorityQHeap.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/PriorityQSort.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Render.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Sweep.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/TessMono.java trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/TessState.java Added: trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessCallback.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessCallback.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessCallback.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.glu.tessellation; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.glu.GLUtessellatorCallbackAdapter; + +public class TessCallback extends GLUtessellatorCallbackAdapter { + + public void begin(int type) { + GL11.glBegin(type); + } + + public void combine(double[] coords, Object[] data, float[] weight, Object[] outData) { + for (int i=0;i<outData.length;i++) { + double[] combined = new double[6]; + combined[0] = coords[0]; + combined[1] = coords[1]; + combined[2] = coords[2]; + combined[3] = 1; + combined[4] = 1; + combined[5] = 1; + + outData[i] = new VertexData(combined); + } +// vertex[0] = coords[0]; +// vertex[1] = coords[1]; +// vertex[2] = coords[2]; +// +// for (int i = 3; i < 6; i++) +// { +// vertex[i] = weight[0] * vertex_data[0][i] + +// indent indweight[1] * vertex_data[1][i] + +// indent indweight[2] * vertex_data[2][i] + +// indent indweight[3] * vertex_data[3][i]; +// } +// +// *dataOut = vertex; + } + + public void end() { + GL11.glEnd(); + } + + public void vertex(Object vertexData) { + VertexData vertex = (VertexData) vertexData; + + GL11.glVertex3d(vertex.data[0], vertex.data[1], vertex.data[2]); + GL11.glColor3d(vertex.data[3], vertex.data[4], vertex.data[5]); + } +} Added: trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessellationTest.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessellationTest.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/TessellationTest.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.glu.tessellation; +import org.lwjgl.LWJGLException; +import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.DisplayMode; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.glu.GLU; +import org.lwjgl.util.glu.GLUtessellator; + +public class TessellationTest { + private GLUtessellator tesselator; + + void init() + { + // Create a new tessellation object + tesselator = GLU.gluNewTess(); + + // Set callback functions + TessCallback callback = new TessCallback(); + tesselator.gluTessCallback(GLU.GLU_TESS_VERTEX, callback); + tesselator.gluTessCallback(GLU.GLU_TESS_BEGIN, callback); + tesselator.gluTessCallback(GLU.GLU_TESS_END, callback); + tesselator.gluTessCallback(GLU.GLU_TESS_COMBINE, callback); + } + + void setWindingRule(int windingRule) + { + // Set the winding rule + tesselator.gluTessProperty(GLU.GLU_TESS_WINDING_RULE, windingRule); + } + + void renderContour(double obj_data[][], int num_vertices) + { + for (int x = 0; x < num_vertices; x++) //loop through the vertices + { + tesselator.gluTessVertex(obj_data[x], 0, new VertexData(obj_data[x])); //store the vertex + } + } + + void beginPolygon() + { + tesselator.gluTessBeginPolygon(null); + } + + void endPolygon() + { + tesselator.gluTessEndPolygon(); + } + + void beginContour() + { + tesselator.gluTessBeginContour(); + } + + void endContour() + { + tesselator.gluTessEndContour(); + } + + void end() + { + tesselator.gluDeleteTess(); + } + + private void createDisplay() throws LWJGLException { + int width = 300; + int height = 300; + + Display.setDisplayMode(new DisplayMode(width,height)); + Display.create(); + Display.setVSyncEnabled(true); + + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glShadeModel(GL11.GL_SMOOTH); + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDisable(GL11.GL_LIGHTING); + + GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + GL11.glClearDepth(1); + + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + GL11.glViewport(0,0,width,height); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + + GL11.glMatrixMode(GL11.GL_PROJECTION); + GL11.glLoadIdentity(); + GL11.glOrtho(0, width, height, 0, 1, -1); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + } + + private void loop() { + while (true) { + render(); + Display.update(); + Display.sync(100); + + if (Display.isCloseRequested()) { + System.exit(0); + } + } + } + + private void render() { + GL11.glTranslatef(150,125,0); + + GL11.glScalef(50,50,1); + // first polygon: a star-5 vertices and color information + double star[][] = { {0.6f, -0.1f, 0f, 1.0f, 1.0f, 1.0f}, + {1.35f, 1.4f, 0f, 1.0f, 1.0f, 1.0f}, + {2.1f, -0.1f, 0f, 1.0f, 1.0f, 1.0f}, + {0.6f, 0.9f, 0f, 1.0f, 1.0f, 1.0f}, + {2.1f, 0.9f, 0f, 1.0f, 1.0f, 1.0f} }; + + //second polygon: a quad-4 vertices; first contour + double quad[][] = { {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f}, + {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}, + {1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f} }; + + //second polygon: a triangle-3 vertices; second contour + double tri[][] = {{0.3f, 0.3f, 0.0f, 0.0f, 0.0f, 0.0f}, + {0.7f, 0.3f, 0.0f, 0.0f, 0.0f, 0.0f}, + {0.5f, 0.7f, 0.0f, 0.0f, 0.0f, 0.0f} }; + + // render the first polygon: the textured star + + // set winding rule to positive + setWindingRule(GLU.GLU_TESS_WINDING_POSITIVE); + beginPolygon(); + beginContour(); + renderContour(star, 5); + endContour(); + endPolygon(); + + // render the second polygon: triangle cut out of a quad + + GL11.glTranslatef(-2,0,0); + // set winding rule to odd + setWindingRule(GLU.GLU_TESS_WINDING_ODD); + // begin the new polygon + beginPolygon(); + beginContour(); + renderContour(quad, 4); + endContour(); + beginContour(); + renderContour(tri, 3); + endContour(); + endPolygon(); + // delete the tess object + end(); + } + + private void start() throws LWJGLException { + createDisplay(); + init(); + loop(); + } + + public static void main(String[] argv) throws LWJGLException { + TessellationTest test = new TessellationTest(); + test.start(); + } +} Added: trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/VertexData.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/VertexData.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/glu/tessellation/VertexData.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.glu.tessellation; + +class VertexData { + public double[] data; + + VertexData(double[] data) { + this.data = data; + } +} Modified: trunk/LWJGL/src/java/org/lwjgl/util/glu/GLU.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/GLU.java 2009-04-04 19:19:43 UTC (rev 3194) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/GLU.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -37,6 +37,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.Util; +import org.lwjgl.util.glu.tessellation.GLUtessellatorImpl; /** * GLU.java @@ -86,6 +87,7 @@ /**** Tesselation constants ****/ + public static final double GLU_TESS_MAX_COORD = 1.0e150; public static final double TESS_MAX_COORD = 1.0e150; /* TessProperty */ @@ -420,4 +422,8 @@ return Util.translateGLErrorString(error_code); } } + + public static GLUtessellator gluNewTess() { + return new GLUtessellatorImpl(); + } } Added: trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellator.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellator.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellator.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.lwjgl.util.glu; + +public interface GLUtessellator { + + public abstract void gluDeleteTess(); + + public abstract void gluTessProperty(int which, double value); + + /* Returns tessellator property */ + public abstract void gluGetTessProperty(int which, double[] value, + int value_offset); /* gluGetTessProperty() */ + + public abstract void gluTessNormal(double x, double y, double z); + + public abstract void gluTessCallback(int which, + GLUtessellatorCallback aCallback); + + public abstract void gluTessVertex(double[] coords, int coords_offset, + Object vertexData); + + public abstract void gluTessBeginPolygon(Object data); + + public abstract void gluTessBeginContour(); + + public abstract void gluTessEndContour(); + + public abstract void gluTessEndPolygon(); + + /*******************************************************/ + + /* Obsolete calls -- for backward compatibility */ + + public abstract void gluBeginPolygon(); + + /*ARGSUSED*/ + public abstract void gluNextContour(int type); + + public abstract void gluEndPolygon(); + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallback.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallback.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallback.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package org.lwjgl.util.glu; + +/** + * <b>GLUtessellatorCallback</b> interface provides methods that the user will + * override to define the callbacks for a tessellation object. + * + * @author Eric Veach, July 1994 + * @author Java Port: Pepijn Van Eeckhoudt, July 2003 + * @author Java Port: Nathan Parker Burg, August 2003 + */ +public interface GLUtessellatorCallback { + /** + * The <b>begin</b> callback method is invoked like + * {@link javax.media.opengl.GL#glBegin glBegin} to indicate the start of a + * (triangle) primitive. The method takes a single argument of type int. If + * the <b>GLU_TESS_BOUNDARY_ONLY</b> property is set to <b>GL_FALSE</b>, then + * the argument is set to either <b>GL_TRIANGLE_FAN</b>, + * <b>GL_TRIANGLE_STRIP</b>, or <b>GL_TRIANGLES</b>. If the + * <b>GLU_TESS_BOUNDARY_ONLY</b> property is set to <b>GL_TRUE</b>, then the + * argument will be set to <b>GL_LINE_LOOP</b>. + * + * @param type + * Specifics the type of begin/end pair being defined. The following + * values are valid: <b>GL_TRIANGLE_FAN</b>, <b>GL_TRIANGLE_STRIP</b>, + * <b>GL_TRIANGLES</b> or <b>GL_LINE_LOOP</b>. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #end end + * @see #begin begin + */ + public void begin(int type); + + /** + * The same as the {@link #begin begin} callback method except that + * it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param type + * Specifics the type of begin/end pair being defined. The following + * values are valid: <b>GL_TRIANGLE_FAN</b>, <b>GL_TRIANGLE_STRIP</b>, + * <b>GL_TRIANGLES</b> or <b>GL_LINE_LOOP</b>. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #endData endData + * @see #begin begin + */ + public void beginData(int type, Object polygonData); + + + /** + * The <b>edgeFlag</b> callback method is similar to + * {@link javax.media.opengl.GL#glEdgeFlag glEdgeFlag}. The method takes + * a single boolean boundaryEdge that indicates which edges lie on the + * polygon boundary. If the boundaryEdge is <b>GL_TRUE</b>, then each vertex + * that follows begins an edge that lies on the polygon boundary, that is, + * an edge that separates an interior region from an exterior one. If the + * boundaryEdge is <b>GL_FALSE</b>, then each vertex that follows begins an + * edge that lies in the polygon interior. The edge flag callback (if + * defined) is invoked before the first vertex callback.<P> + * + * Since triangle fans and triangle strips do not support edge flags, the + * begin callback is not called with <b>GL_TRIANGLE_FAN</b> or + * <b>GL_TRIANGLE_STRIP</b> if a non-null edge flag callback is provided. + * (If the callback is initialized to null, there is no impact on + * performance). Instead, the fans and strips are converted to independent + * triangles. + * + * @param boundaryEdge + * Specifics which edges lie on the polygon boundary. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #edgeFlagData edgeFlagData + */ + public void edgeFlag(boolean boundaryEdge); + + + /** + * The same as the {@link #edgeFlag edgeFlage} callback method + * except that it takes an additional reference argument. This + * reference is identical to the opaque reference provided when + * {@link GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param boundaryEdge + * Specifics which edges lie on the polygon boundary. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #edgeFlag edgeFlag + */ + public void edgeFlagData(boolean boundaryEdge, Object polygonData); + + + /** + * The <b>vertex</b> callback method is invoked between the {@link + * #begin begin} and {@link #end end} callback methods. It is + * similar to {@link javax.media.opengl.GL#glVertex3f glVertex3f}, + * and it defines the vertices of the triangles created by the + * tessellation process. The method takes a reference as its only + * argument. This reference is identical to the opaque reference + * provided by the user when the vertex was described (see {@link + * GLU#gluTessVertex gluTessVertex}). + * + * @param vertexData + * Specifics a reference to the vertices of the triangles created + * byt the tessellatin process. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #vertexData vertexData + */ + public void vertex(Object vertexData); + + + /** + * The same as the {@link #vertex vertex} callback method except + * that it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param vertexData + * Specifics a reference to the vertices of the triangles created + * byt the tessellatin process. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #vertex vertex + */ + public void vertexData(Object vertexData, Object polygonData); + + + /** + * The end callback serves the same purpose as + * {@link javax.media.opengl.GL#glEnd glEnd}. It indicates the end of a + * primitive and it takes no arguments. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #begin begin + * @see #endData endData + */ + public void end(); + + + /** + * The same as the {@link #end end} callback method except that it + * takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #beginData beginData + * @see #end end + */ + public void endData(Object polygonData); + + + /** + * The <b>combine</b> callback method is called to create a new vertex when + * the tessellation detects an intersection, or wishes to merge features. The + * method takes four arguments: an array of three elements each of type + * double, an array of four references, an array of four elements each of + * type float, and a reference to a reference.<P> + * + * The vertex is defined as a linear combination of up to four existing + * vertices, stored in <i>data</i>. The coefficients of the linear combination + * are given by <i>weight</i>; these weights always add up to 1. All vertex + * pointers are valid even when some of the weights are 0. <i>coords</i> gives + * the location of the new vertex.<P> + * + * The user must allocate another vertex, interpolate parameters using + * <i>data</i> and <i>weight</i>, and return the new vertex pointer in + * <i>outData</i>. This handle is supplied during rendering callbacks. The + * user is responsible for freeing the memory some time after + * {@link GLU#gluTessEndPolygon gluTessEndPolygon} is + * called.<P> + * + * For example, if the polygon lies in an arbitrary plane in 3-space, and a + * color is associated with each vertex, the <b>GLU_TESS_COMBINE</b> + * callback might look like this: + * </UL> + * <PRE> + * void myCombine(double[] coords, Object[] data, + * float[] weight, Object[] outData) + * { + * MyVertex newVertex = new MyVertex(); + * + * newVertex.x = coords[0]; + * newVertex.y = coords[1]; + * newVertex.z = coords[2]; + * newVertex.r = weight[0]*data[0].r + + * weight[1]*data[1].r + + * weight[2]*data[2].r + + * weight[3]*data[3].r; + * newVertex.g = weight[0]*data[0].g + + * weight[1]*data[1].g + + * weight[2]*data[2].g + + * weight[3]*data[3].g; + * newVertex.b = weight[0]*data[0].b + + * weight[1]*data[1].b + + * weight[2]*data[2].b + + * weight[3]*data[3].b; + * newVertex.a = weight[0]*data[0].a + + * weight[1]*data[1].a + + * weight[2]*data[2].a + + * weight[3]*data[3].a; + * outData = newVertex; + * }</PRE> + * + * @param coords + * Specifics the location of the new vertex. + * @param data + * Specifics the vertices used to create the new vertex. + * @param weight + * Specifics the weights used to create the new vertex. + * @param outData + * Reference user the put the coodinates of the new vertex. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #combineData combineData + */ + public void combine(double[] coords, Object[] data, + float[] weight, Object[] outData); + + + /** + * The same as the {@link #combine combine} callback method except + * that it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param coords + * Specifics the location of the new vertex. + * @param data + * Specifics the vertices used to create the new vertex. + * @param weight + * Specifics the weights used to create the new vertex. + * @param outData + * Reference user the put the coodinates of the new vertex. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #combine combine + */ + public void combineData(double[] coords, Object[] data, + float[] weight, Object[] outData, + Object polygonData); + + + /** + * The <b>error</b> callback method is called when an error is encountered. + * The one argument is of type int; it indicates the specific error that + * occurred and will be set to one of <b>GLU_TESS_MISSING_BEGIN_POLYGON</b>, + * <b>GLU_TESS_MISSING_END_POLYGON</b>, <b>GLU_TESS_MISSING_BEGIN_CONTOUR</b>, + * <b>GLU_TESS_MISSING_END_CONTOUR</b>, <b>GLU_TESS_COORD_TOO_LARGE</b>, + * <b>GLU_TESS_NEED_COMBINE_CALLBACK</b> or <b>GLU_OUT_OF_MEMORY</b>. + * Character strings describing these errors can be retrieved with the + * {@link GLU#gluErrorString gluErrorString} call.<P> + * + * The GLU library will recover from the first four errors by inserting the + * missing call(s). <b>GLU_TESS_COORD_TOO_LARGE</b> indicates that some + * vertex coordinate exceeded the predefined constant + * <b>GLU_TESS_MAX_COORD</b> in absolute value, and that the value has been + * clamped. (Coordinate values must be small enough so that two can be + * multiplied together without overflow.) + * <b>GLU_TESS_NEED_COMBINE_CALLBACK</b> indicates that the tessellation + * detected an intersection between two edges in the input data, and the + * <b>GLU_TESS_COMBINE</b> or <b>GLU_TESS_COMBINE_DATA</b> callback was not + * provided. No output is generated. <b>GLU_OUT_OF_MEMORY</b> indicates that + * there is not enough memory so no output is generated. + * + * @param errnum + * Specifics the error number code. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #errorData errorData + */ + public void error(int errnum); + + + /** + * The same as the {@link #error error} callback method except that + * it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param errnum + * Specifics the error number code. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #error error + */ + public void errorData(int errnum, Object polygonData); + + //void mesh(com.sun.opengl.impl.tessellator.GLUmesh mesh); +} Added: trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallbackAdapter.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallbackAdapter.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/GLUtessellatorCallbackAdapter.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package org.lwjgl.util.glu; + +/** + * The <b>GLUtessellatorCallbackAdapter</b> provides a default implementation of + * {@link GLUtessellatorCallback GLUtessellatorCallback} + * with empty callback methods. This class can be extended to provide user + * defined callback methods. + * + * @author Eric Veach, July 1994 + * @author Java Port: Pepijn Van Eechhoudt, July 2003 + * @author Java Port: Nathan Parker Burg, August 2003 + */ + +public class GLUtessellatorCallbackAdapter implements GLUtessellatorCallback { + public void begin(int type) {} + public void edgeFlag(boolean boundaryEdge) {} + public void vertex(Object vertexData) {} + public void end() {} +// public void mesh(com.sun.opengl.impl.tessellator.GLUmesh mesh) {} + public void error(int errnum) {} + public void combine(double[] coords, Object[] data, + float[] weight, Object[] outData) {} + public void beginData(int type, Object polygonData) {} + public void edgeFlagData(boolean boundaryEdge, + Object polygonData) {} + public void vertexData(Object vertexData, Object polygonData) {} + public void endData(Object polygonData) {} + public void errorData(int errnum, Object polygonData) {} + public void combineData(double[] coords, Object[] data, + float[] weight, Object[] outData, + Object polygonData) {} +} Added: trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/ActiveRegion.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/ActiveRegion.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/ActiveRegion.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package org.lwjgl.util.glu.tessellation; + +class ActiveRegion { + GLUhalfEdge eUp; /* upper edge, directed right to left */ + DictNode nodeUp; /* dictionary node corresponding to eUp */ + int windingNumber; /* used to determine which regions are + * inside the polygon */ + boolean inside; /* is this region inside the polygon? */ + boolean sentinel; /* marks fake edges at t = +/-infinity */ + boolean dirty; /* marks regions where the upper or lower + * edge has changed, but we haven't checked + * whether they intersect yet */ + boolean fixUpperEdge; /* marks temporary edges introduced when + * we process a "right vertex" (one without + * any edges leaving to the right) */ +} Added: trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/CachedVertex.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/CachedVertex.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/CachedVertex.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package org.lwjgl.util.glu.tessellation; + +class CachedVertex { + public double[] coords = new double[3]; + public Object data; +} Added: trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Dict.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Dict.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/Dict.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package org.lwjgl.util.glu.tessellation; + +class Dict { + DictNode head; + Object frame; + DictLeq leq; + + private Dict() { + } + + static Dict dictNewDict(Object frame, DictLeq leq) { + Dict dict = new Dict(); + dict.head = new DictNode(); + + dict.head.key = null; + dict.head.next = dict.head; + dict.head.prev = dict.head; + + dict.frame = frame; + dict.leq = leq; + + return dict; + } + + static void dictDeleteDict(Dict dict) { + dict.head = null; + dict.frame = null; + dict.leq = null; + } + + static DictNode dictInsert(Dict dict, Object key) { + return dictInsertBefore(dict, dict.head, key); + } + + static DictNode dictInsertBefore(Dict dict, DictNode node, Object key) { + do { + node = node.prev; + } while (node.key != null && !dict.leq.leq(dict.frame, node.key, key)); + + DictNode newNode = new DictNode(); + newNode.key = key; + newNode.next = node.next; + node.next.prev = newNode; + newNode.prev = node; + node.next = newNode; + + return newNode; + } + + static Object dictKey(DictNode aNode) { + return aNode.key; + } + + static DictNode dictSucc(DictNode aNode) { + return aNode.next; + } + + static DictNode dictPred(DictNode aNode) { + return aNode.prev; + } + + static DictNode dictMin(Dict aDict) { + return aDict.head.next; + } + + static DictNode dictMax(Dict aDict) { + return aDict.head.prev; + } + + static void dictDelete(Dict dict, DictNode node) { + node.next.prev = node.prev; + node.prev.next = node.next; + } + + static DictNode dictSearch(Dict dict, Object key) { + DictNode node = dict.head; + + do { + node = node.next; + } while (node.key != null && !(dict.leq.leq(dict.frame, key, node.key))); + + return node; + } + + public interface DictLeq { + boolean leq(Object frame, Object key1, Object key2); + } +} Added: trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/DictNode.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/DictNode.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/glu/tessellation/DictNode.java 2009-04-05 22:07:46 UTC (rev 3195) @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF TH... [truncated message content] |
From: <sp...@us...> - 2009-09-08 12:28:06
|
Revision: 3236 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3236&view=rev Author: spasi Date: 2009-09-08 12:27:59 +0000 (Tue, 08 Sep 2009) Log Message: ----------- Fixed Context init when using the debug library. Removed glGetError call before buffer swapping. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java trunk/LWJGL/src/java/org/lwjgl/util/generator/ContextCapabilitiesGenerator.java Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java 2009-09-03 20:15:46 UTC (rev 3235) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java 2009-09-08 12:27:59 UTC (rev 3236) @@ -637,7 +637,8 @@ if ( !isCreated() ) throw new IllegalStateException("Display not created"); - Util.checkGLError(); + if ( LWJGLUtil.DEBUG ) + Util.checkGLError(); Context.swapBuffers(); } } Modified: trunk/LWJGL/src/java/org/lwjgl/util/generator/ContextCapabilitiesGenerator.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/generator/ContextCapabilitiesGenerator.java 2009-09-03 20:15:46 UTC (rev 3235) +++ trunk/LWJGL/src/java/org/lwjgl/util/generator/ContextCapabilitiesGenerator.java 2009-09-08 12:27:59 UTC (rev 3236) @@ -118,6 +118,7 @@ writer.println("\tprivate Set " + ALL_INIT_METHOD_NAME + "(boolean forwardCompatible) throws LWJGLException {"); // Load the basic pointers we need to detect OpenGL version and supported extensions. + writer.println("\t\tGL11_glGetError_pointer = GLContext.getFunctionAddress(\"glGetError\");"); writer.println("\t\tGL11_glGetString_pointer = GLContext.getFunctionAddress(\"glGetString\");"); // Initialize GL11.glGetIntegerv and GL30.glGetStringi here, in case we have created an OpenGL 3.0 context. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ma...@us...> - 2009-11-26 22:44:31
|
Revision: 3255 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3255&view=rev Author: matzon Date: 2009-11-26 22:44:17 +0000 (Thu, 26 Nov 2009) Log Message: ----------- stop updating cursor all the time and only continue animation if mouse is inside window Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/input/Mouse.java trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java Modified: trunk/LWJGL/src/java/org/lwjgl/input/Mouse.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/input/Mouse.java 2009-11-24 20:13:12 UTC (rev 3254) +++ trunk/LWJGL/src/java/org/lwjgl/input/Mouse.java 2009-11-26 22:44:17 UTC (rev 3255) @@ -630,7 +630,7 @@ */ public static void updateCursor() { synchronized (OpenGLPackageAccess.global_lock) { - if (emulateCursorAnimation && currentCursor != null && currentCursor.hasTimedOut()) { + if (emulateCursorAnimation && currentCursor != null && currentCursor.hasTimedOut() && Mouse.isInsideWindow()) { currentCursor.nextCursor(); try { setNativeCursor(currentCursor); Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java 2009-11-24 20:13:12 UTC (rev 3254) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java 2009-11-26 22:44:17 UTC (rev 3255) @@ -761,7 +761,6 @@ private static native int defWindowProc(long hwnd, int msg, long wParam, long lParam); private void checkCursorState() { - updateCursor(); updateClipping(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ma...@us...> - 2010-03-28 23:11:24
|
Revision: 3298 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3298&view=rev Author: matzon Date: 2010-03-28 23:11:17 +0000 (Sun, 28 Mar 2010) Log Message: ----------- bumping native version Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java Modified: trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java 2010-03-27 16:04:30 UTC (rev 3297) +++ trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java 2010-03-28 23:11:17 UTC (rev 3298) @@ -39,7 +39,7 @@ * $Id$ */ final class LinuxSysImplementation extends J2SESysImplementation { - private final static int JNI_VERSION = 17; + private final static int JNI_VERSION = 18; static { java.awt.Toolkit.getDefaultToolkit(); // This will make sure libjawt.so is loaded Modified: trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java 2010-03-27 16:04:30 UTC (rev 3297) +++ trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java 2010-03-28 23:11:17 UTC (rev 3298) @@ -42,7 +42,7 @@ * $Id$ */ final class MacOSXSysImplementation extends J2SESysImplementation { - private final static int JNI_VERSION = 17; + private final static int JNI_VERSION = 18; static { // Make sure AWT is properly initialized. This avoids hangs on Mac OS X 10.3 Modified: trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java 2010-03-27 16:04:30 UTC (rev 3297) +++ trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java 2010-03-28 23:11:17 UTC (rev 3298) @@ -45,7 +45,7 @@ * $Id$ */ final class WindowsSysImplementation extends DefaultSysImplementation { - private final static int JNI_VERSION = 21; + private final static int JNI_VERSION = 22; static { Sys.initialize(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2010-04-20 18:21:12
|
Revision: 3332 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3332&view=rev Author: spasi Date: 2010-04-20 18:21:05 +0000 (Tue, 20 Apr 2010) Log Message: ----------- Added support for a new Drawable type (SharedDrawable) that shares its context with another Drawable. Added new methods to the Drawable interface (makeCurrent, releaseContext, destroy). Added a background thread texture loading test (using either Pbuffer or SharedDrawable). Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/AWTGLCanvas.java trunk/LWJGL/src/java/org/lwjgl/opengl/Context.java trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java trunk/LWJGL/src/java/org/lwjgl/opengl/Drawable.java trunk/LWJGL/src/java/org/lwjgl/opengl/Pbuffer.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/awt/DemoBox.java Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/opengl/SharedDrawable.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/ trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/AWTGLCanvas.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/AWTGLCanvas.java 2010-04-16 19:06:53 UTC (rev 3331) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/AWTGLCanvas.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -109,6 +109,16 @@ return context; } + public Context createSharedContext() throws LWJGLException { + synchronized ( GlobalLock.lock ) { + synchronized ( SYNC_LOCK ) { + if ( context == null ) throw new IllegalStateException("Canvas not yet displayable"); + + return new Context(peer_info, context.getContextAttribs(), context); + } + } + } + /** Constructor using the default PixelFormat. */ public AWTGLCanvas() throws LWJGLException { this(new PixelFormat()); @@ -175,7 +185,7 @@ */ public void removeNotify() { synchronized ( SYNC_LOCK ) { - destroyContext(); + destroy(); super.removeNotify(); } } @@ -225,7 +235,7 @@ } /** Destroy the OpenGL context. This happens when the component becomes undisplayable */ - private void destroyContext() { + public final void destroy() { synchronized ( SYNC_LOCK ) { try { if ( context != null ) { Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/Context.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/Context.java 2010-04-16 19:06:53 UTC (rev 3331) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/Context.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -61,7 +61,7 @@ private final ByteBuffer handle; private final PeerInfo peer_info; - private final IntBuffer attribList; + private final ContextAttribs contextAttribs; private final boolean forwardCompatible; /** Whether the context has been destroyed */ @@ -94,6 +94,10 @@ return peer_info; } + ContextAttribs getContextAttribs() { + return contextAttribs; + } + static Context getCurrentContext() { return (Context)current_context_local.get(); } @@ -109,6 +113,9 @@ GLContext.loadOpenGLLibrary(); try { this.peer_info = peer_info; + this.contextAttribs = attribs; + + IntBuffer attribList; if ( attribs != null ) { attribList = attribs.getAttribList(); forwardCompatible = attribs.isForwardCompatible(); Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java 2010-04-16 19:06:53 UTC (rev 3331) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/Display.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -143,6 +143,26 @@ return isCreated() ? context : null; } } + + public Context createSharedContext() throws LWJGLException { + synchronized ( GlobalLock.lock ) { + if ( !isCreated() ) throw new IllegalStateException("Display must be created."); + + return new Context(peer_info, context.getContextAttribs(), context); + } + } + + public void makeCurrent() throws LWJGLException { + Display.makeCurrent(); + } + + public void releaseContext() throws LWJGLException { + Display.releaseContext(); + } + + public void destroy() { + Display.destroy(); + } }; } Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/Drawable.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/Drawable.java 2010-04-16 19:06:53 UTC (rev 3331) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/Drawable.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -31,6 +31,8 @@ */ package org.lwjgl.opengl; +import org.lwjgl.LWJGLException; + /** * The Drawable interface describes an OpenGL drawable with an associated * Context. @@ -39,5 +41,38 @@ */ public interface Drawable { + + /** + * [INTERNAL USE ONLY] Returns the Drawable's Context. + * + * @return the Drawable's Context + */ Context getContext(); + + /** + * [INTERNAL USE ONLY] Creates a new Context that is shared with the Drawable's Context. + * + * @return a Context shared with the Drawable's Context. + */ + Context createSharedContext() throws LWJGLException; + + /** + * Makes the Drawable's context current in the current thread. + * + * @throws LWJGLException + */ + void makeCurrent() throws LWJGLException; + + /** + * If the Drawable's context is current in the current thread, no context will be current after a call to this method. + * + * @throws LWJGLException + */ + void releaseContext() throws LWJGLException; + + /** + * Destroys the Drawable. + */ + void destroy(); + } Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/Pbuffer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/Pbuffer.java 2010-04-16 19:06:53 UTC (rev 3331) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/Pbuffer.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -255,6 +255,12 @@ return context; } + public Context createSharedContext() throws LWJGLException { + synchronized ( GlobalLock.lock ) { + return new Context(peer_info, context.getContextAttribs(), context); + } + } + private void checkDestroyed() { if (destroyed) throw new IllegalStateException("Pbuffer is destroyed"); @@ -281,6 +287,12 @@ context.makeCurrent(); } + public void releaseContext() throws LWJGLException { + checkDestroyed(); + if ( context.isCurrent() ) + Context.releaseCurrentContext(); + } + /** * Gets the Pbuffer capabilities. * Added: trunk/LWJGL/src/java/org/lwjgl/opengl/SharedDrawable.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/SharedDrawable.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/SharedDrawable.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.opengl; + +import org.lwjgl.LWJGLException; +import org.lwjgl.LWJGLUtil; + +/** + * @author Spasi + * @since 20 \xC1\xF0\xF1 2010 + */ + +/** + * A Drawable implementation that shares its context with another Drawable. This is useful + * for background loading of resources. See org.lwjgl.test.opengl.multithread.BackgroundLoad + * for an example. + * + * @author Spasi + */ +public final class SharedDrawable implements Drawable { + + private Context context; + + private boolean destroyed; + + public SharedDrawable(final Drawable drawable) throws LWJGLException { + this.context = drawable.createSharedContext(); + } + + public Context getContext() { + return context; + } + + public Context createSharedContext() { + throw new UnsupportedOperationException(); + } + + public void makeCurrent() throws LWJGLException { + checkDestroyed(); + context.makeCurrent(); + + } + + public void releaseContext() throws LWJGLException { + checkDestroyed(); + if ( context.isCurrent() ) + Context.releaseCurrentContext(); + } + + public void destroy() { + if ( destroyed ) + return; + + try { + context.forceDestroy(); + destroyed = true; + } catch (LWJGLException e) { + LWJGLUtil.log("Exception occurred while destroying SharedDrawable: " + e); + } + } + + private void checkDestroyed() { + if ( destroyed ) + throw new IllegalStateException("SharedDrawable is destroyed"); + } + +} \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/awt/DemoBox.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/awt/DemoBox.java 2010-04-16 19:06:53 UTC (rev 3331) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/awt/DemoBox.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -150,7 +150,7 @@ addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { - demoCanvas.destroy(); + demoCanvas.destroyCanvas(); dispose(); System.exit(0); } @@ -269,7 +269,7 @@ } } - public void destroy() { + public void destroyCanvas() { setActiveDemo(null); renderThread = null; } Added: trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.opengl.multithread; + +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.*; +import org.lwjgl.util.glu.GLU; +import org.lwjgl.util.glu.Sphere; + +import java.nio.FloatBuffer; + +/** + * A test of loading textures in a background thread. This can be achieved in 2 ways: + * <br> + * a) A dummy Pbuffer is created and its context shares the rendering context.<br> + * b) A SharedDrawable is used.<br> + * <br> + * When the test starts, there's no texture created and rendering is done with texturing disabled. + * 2 seconds later a "dummy" texture is created in the background thread and texturing is enabled. This dummy texture + * can by anything the developer wants to have as a placeholder while textures are being loaded. + * Finally, 5 seconds later the "true" texture is loaded and displayed. This texture will change every 5 seconds after + * that, until the test is terminated (ESC key). + * + * @author Spasi + */ +public final class BackgroundLoadTest { + + private static boolean run = true; + + private static BackgroundLoader backgroundLoader; + + private static Sphere sphere; + + private BackgroundLoadTest() { + } + + public static void main(String[] args) { + initialize(args); + + Util.checkGLError(); + + try { + backgroundLoader.start(); + } catch (LWJGLException e) { + kill("Failed to start background thread.", e); + } + + Util.checkGLError(); + + while ( run ) { + if ( !Display.isVisible() ) + Thread.yield(); + else { + handleIO(); + + GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); + + renderObject(); + + Util.checkGLError(); + + // Restore camera position. + GL11.glPopMatrix(); + GL11.glPushMatrix(); + } + + Display.update(); + + if ( Display.isCloseRequested() ) + break; + } + + cleanup(); + System.exit(0); + } + + private static void initialize(String[] args) { + if ( args.length != 1 ) + argsError(); + + DisplayMode displayMode = null; + + try { + DisplayMode[] modes = Display.getAvailableDisplayModes(); + + displayMode = chooseMode(modes, 1024, 768); + if ( displayMode == null ) + displayMode = chooseMode(modes, 800, 600); + if ( displayMode == null ) + displayMode = chooseMode(modes, 640, 480); + if ( displayMode == null ) + kill("Failed to set an appropriate display mode."); + + System.out.println("Setting display mode to: " + displayMode); + Display.setDisplayMode(displayMode); + Display.setTitle("Background Loading Test"); + Display.create(new PixelFormat(8, 24, 0)); + } catch (LWJGLException e) { + kill(e.getMessage()); + } + + GL11.glViewport(0, 0, displayMode.getWidth(), displayMode.getHeight()); + + GL11.glMatrixMode(GL11.GL_PROJECTION); + GL11.glLoadIdentity(); + GLU.gluPerspective(45, displayMode.getWidth() / (float)displayMode.getHeight(), 1.0f, 10.0f); + + GL11.glMatrixMode(GL11.GL_MODELVIEW); + GL11.glLoadIdentity(); + + // Setup camera position. + GL11.glTranslatef(0.0f, 0.0f, -4.0f); + GL11.glRotatef(90.0f, 1.0f, 0.0f, 0.0f); + GL11.glPushMatrix(); + + GL11.glClearDepth(1.0f); + GL11.glDepthFunc(GL11.GL_LEQUAL); + + GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST); + + GL11.glFrontFace(GL11.GL_CCW); + GL11.glPolygonMode(GL11.GL_FRONT, GL11.GL_FILL); + + GL11.glCullFace(GL11.GL_BACK); + GL11.glEnable(GL11.GL_CULL_FACE); + + GL11.glAlphaFunc(GL11.GL_GREATER, 0.0f); + GL11.glEnable(GL11.GL_ALPHA_TEST); + + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_BLEND); + + GL11.glShadeModel(GL11.GL_SMOOTH); + + final FloatBuffer vectorBuffer = BufferUtils.createFloatBuffer(4); + + vectorBuffer.clear(); + vectorBuffer.put(0, 1.0f).put(1, 1.0f).put(2, 1.0f).put(3, 1.0f); + GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, vectorBuffer); + + vectorBuffer.put(0, 1.0f).put(1, 1.0f).put(2, 1.0f).put(3, 1.0f); + GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, vectorBuffer); + + vectorBuffer.put(0, 1.0f).put(1, 1.0f).put(2, 0.5f).put(3, 1.0f); + GL11.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, vectorBuffer); + + vectorBuffer.put(0, -1.0f / 3.0f).put(1, 1.0f / 3.0f).put(2, 1.0f / 3.0f).put(3, 0.0f); // Infinite + GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, vectorBuffer); + + vectorBuffer.put(0, 0.2f).put(1, 0.2f).put(2, 0.2f).put(3, 1.0f); + GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, vectorBuffer); + + GL11.glEnable(GL11.GL_LIGHT0); + GL11.glEnable(GL11.GL_LIGHTING); + + sphere = new Sphere(); + + if ( "PB".equalsIgnoreCase(args[0]) ) { + backgroundLoader = new BackgroundLoader() { + Drawable getDrawable() throws LWJGLException { + return new Pbuffer(2, 2, new PixelFormat(8, 24, 0), Display.getDrawable()); + } + }; + } else if ( "SD".equalsIgnoreCase(args[0]) ) { + backgroundLoader = new BackgroundLoader() { + Drawable getDrawable() throws LWJGLException { + return new SharedDrawable(Display.getDrawable()); + } + }; + } else { + argsError(); + } + } + + private static void handleIO() { + if ( Keyboard.getNumKeyboardEvents() != 0 ) { + while ( Keyboard.next() ) { + if ( Keyboard.getEventKeyState() ) + continue; + + switch ( Keyboard.getEventKey() ) { + case Keyboard.KEY_ESCAPE: + run = false; + break; + } + } + } + + while ( Mouse.next() ) ; + } + + static void renderObject() { + GL11.glColor3f(1.0f, 1.0f, 1.0f); + + int texID = backgroundLoader.getTexID(); + if ( texID == 0 ) { + sphere.setTextureFlag(false); + GL11.glDisable(GL11.GL_TEXTURE_2D); + } else { + sphere.setTextureFlag(true); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID); + } + + sphere.draw(1.0f, 32, 32); + + if ( texID != 0 ) { // Unbind so we can update from the background thread. + GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); + GL11.glDisable(GL11.GL_TEXTURE_2D); + } + } + + private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) { + DisplayMode bestMode = null; + + for ( int i = 0; i < modes.length; i++ ) { + DisplayMode mode = modes[i]; + if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) { + if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) ) + bestMode = mode; + } + } + + return bestMode; + } + + private static void cleanup() { + backgroundLoader.cleanup(); + + Thread.yield(); // Let background thread finish. + + if ( Display.isCreated() ) + Display.destroy(); + } + + private static void argsError() { + System.out.println("\nInvalid program arguments."); + System.out.println("\nUsage: BackgroundLoadTest <testType>, where <testType> argument can be one of the following:\n"); + System.out.println("PB\t- Use a Pbuffer context for the background thread."); + System.out.println("SD\t- Use a SharedDrawable context for the background thread."); + + cleanup(); + System.exit(-1); + } + + static void kill(String reason) { + System.out.println("The BackgroundLoadTest program was terminated because an error occured.\n"); + System.out.println("Reason: " + (reason == null ? "Unknown" : reason)); + + cleanup(); + System.exit(-1); + } + + static void kill(String reason, Throwable t) { + System.out.println("The BackgroundLoadTest program was terminated because an exception occured.\n"); + System.out.println("Reason: " + (reason == null ? "Unknown" : reason)); + + System.out.println("Exception message: " + t.getMessage()); + + cleanup(); + System.exit(-1); + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java 2010-04-20 18:21:05 UTC (rev 3332) @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Created by LWJGL. + * User: spasi + * Date: 2004-03-30 + * Time: 8:41:42 pm + */ +package org.lwjgl.test.opengl.multithread; + +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.opengl.Drawable; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.Color; +import org.lwjgl.util.ReadableColor; + +import java.nio.ByteBuffer; + +abstract class BackgroundLoader { + + private static final int WIDTH = 32; + private static final int HEIGHT = 32; + + private static final Object lock = new Object(); + + private Drawable drawable; + + private boolean running; + + private ByteBuffer texture; + private int texID; + + protected BackgroundLoader() { + running = true; + texture = BufferUtils.createByteBuffer(WIDTH * HEIGHT * 3); + } + + abstract Drawable getDrawable() throws LWJGLException; + + void cleanup() { + running = false; + } + + void start() throws LWJGLException { + new Thread(new Runnable() { + public void run() { + System.out.println("-- Background Thread started --"); + + System.out.println("** Sleeping, no texture created yet **"); + + long start = System.currentTimeMillis(); + + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + try { + drawable = getDrawable(); + drawable.makeCurrent(); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } + + System.out.println("** Drawable created **"); + + synchronized ( lock ) { + // Create a "dummy" texture while we wait for texture IO + createCheckerTexture(Color.RED, Color.WHITE, 2); + + texID = GL11.glGenTextures(); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID); + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, WIDTH, HEIGHT, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, texture); + + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + + GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); + } + + System.out.println("** Dummy texture created **"); + + long lastTextureCreated = System.currentTimeMillis(); // Delay first texture creation + int count = 0; + while ( running ) { + long time = System.currentTimeMillis(); + if ( time - lastTextureCreated < 5000 ) { // Update the texture every 5 seconds + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + continue; + } + + // Create the "true" texture + if ( count % 2 == 0 ) + createGradientTexture(Color.RED, Color.BLUE); + else + createGradientTexture(Color.GREEN, Color.YELLOW); + + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID); + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, WIDTH, HEIGHT, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, texture); + + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + + GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); + + System.out.println("** Created new gradient texture **"); + + lastTextureCreated = System.currentTimeMillis(); + count++; + } + + drawable.destroy(); + + System.out.println("-- Background Thread finished --"); + } + }).start(); + } + + int getTexID() { + synchronized ( lock ) { + return texID; + } + } + + private void createCheckerTexture(final ReadableColor a, final ReadableColor b, final int size) { + int i = 0; + for ( int y = 0; y < HEIGHT; y++ ) { + for ( int x = 0; x < WIDTH; x++ ) { + ReadableColor c = (x / size) % 2 == 0 ? ((y / size) % 2 == 0 ? a : b) : ((y / size) % 2 == 0 ? b : a); + texture.put(i + 0, c.getRedByte()); + texture.put(i + 1, c.getGreenByte()); + texture.put(i + 2, c.getBlueByte()); + i += 3; + } + } + } + + private void createGradientTexture(final ReadableColor a, final ReadableColor b) { + float l = 0.0f; + int i = 0; + for ( int y = 0; y < HEIGHT; y++ ) { + for ( int x = 0; x < WIDTH; x++ ) { + texture.put(i + 0, lerp(a.getRed(), b.getRed(), l)); + texture.put(i + 1, lerp(a.getGreen(), b.getGreen(), l)); + texture.put(i + 2, lerp(a.getBlue(), b.getBlue(), l)); + i += 3; + } + l += (1.0f / (HEIGHT - 1)); + } + } + + private static byte lerp(final int a, final int b, final float l) { + return (byte)Math.round(((1.0f - l) * a + l * b)); + } + +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2010-05-22 16:53:55
|
Revision: 3344 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3344&view=rev Author: spasi Date: 2010-05-22 16:53:49 +0000 (Sat, 22 May 2010) Log Message: ----------- Updated ContextAttribs to not default to the core profile for 3.2+ versions. Updated VersionTest (version 20 of ARB_create_context). Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/VBOIndexTest.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java 2010-05-21 22:55:11 UTC (rev 3343) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java 2010-05-22 16:53:49 UTC (rev 3344) @@ -37,16 +37,16 @@ import java.nio.IntBuffer; /** - * This class represents the context attributes passed to CreateContextAttribs of the XGL_create_context extension. + * This class represents the context attributes passed to CreateContextAttribs of the ARB_create_context and + * ARB_create_context_profile extensions. * These attributes can be used to indicate at context creation which OpenGL interface will be used. This includes the * OpenGL version, the layer plane on which rendering takes place and also optional debug and forward combatibility modes. - * (read the XGL_create_context spec for details) + * (read the ARB_create_context spec for details) * <p/> * Use of this class is optional. If an OpenGL context is created without passing an instance of this class - * (or XGL_create_context is not supported), the old context creation code will be used. Use of ContextAttribs is required - * to create an OpenGL 3.0 or newer context. Support for debug and forward compatible mobes is not guaranteed by the OpenGL - * implementation. Developers may encounter debug contexts being the same as non-debug contexts or forward compatible - * contexts having support for deprecated functionality. + * (or ARB_create_context is not supported), the old context creation code will be used. Support for debug and forward + * compatible mobes is not guaranteed by the OpenGL implementation. Developers may encounter debug contexts being the same + * as non-debug contexts or forward compatible contexts having support for deprecated functionality. * <p/> * If the forwardCompatible * attribute is used, LWJGL will not load the deprecated functionality (as defined in the OpenGL 3.0 specification). This @@ -72,10 +72,10 @@ } public ContextAttribs(final int majorVersion, final int minorVersion) { - if ( majorVersion < 0 || - 3 < majorVersion || + if ( majorVersion < 0 || 4 < majorVersion || minorVersion < 0 || - (majorVersion == 3 && 2 < minorVersion) || + (majorVersion == 4 && 0 < minorVersion) || + (majorVersion == 3 && 3 < minorVersion) || (majorVersion == 2 && 1 < minorVersion) || (majorVersion == 1 && 5 < minorVersion) ) throw new IllegalArgumentException("Invalid OpenGL version specified: " + majorVersion + '.' + minorVersion); @@ -88,7 +88,7 @@ this.debug = false; this.forwardCompatible = false; - this.profileCore = 3 < majorVersion || (majorVersion == 3 && 2 <= minorVersion) ? true : false; + this.profileCore = false; this.profileCompatibility = false; } Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/VBOIndexTest.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/VBOIndexTest.java 2010-05-21 22:55:11 UTC (rev 3343) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/VBOIndexTest.java 2010-05-22 16:53:49 UTC (rev 3344) @@ -179,6 +179,7 @@ mapped_indices_buffer); if ( new_mapped_buffer != mapped_indices_buffer ) mapped_indices_int_buffer = new_mapped_buffer.order(ByteOrder.nativeOrder()).asIntBuffer(); + mapped_indices_buffer = new_mapped_buffer; mapped_float_buffer.rewind(); vertices.rewind(); Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java 2010-05-21 22:55:11 UTC (rev 3343) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/VersionTest.java 2010-05-22 16:53:49 UTC (rev 3344) @@ -29,13 +29,6 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * Created by LWJGL. - * User: spasi - * Date: 2009-04-04 - * Time: 21:20:24 pm - */ - package org.lwjgl.test.opengl; import org.lwjgl.LWJGLException; @@ -44,6 +37,11 @@ import java.util.StringTokenizer; import java.util.regex.Pattern; +/** + * Tests the ARB_create_context extension through the use of the ContextAttribs class. + * + * @author Spasi + */ public final class VersionTest { private VersionTest() { @@ -110,46 +108,105 @@ System.out.println("\n---------\n"); + System.out.println("Requested " + ca); + final String version = GL11.glGetString(GL11.GL_VERSION); - System.out.print("GL Version requested: " + majorInput + '.' + minorInput); - if ( ca.isProfileCore() ) - System.out.print(" - Core Profile"); - else if ( ca.isProfileCompatibility() ) - System.out.print(" - Compatibility Profile"); - System.out.println("\nGL Version returned : " + version); + boolean deprecated = false; + try { + GL11.glVertex3f(0.0f, 0.0f, 0.0f); + deprecated = true; + } catch (Throwable t) {} final StringTokenizer version_tokenizer = new StringTokenizer(version, ". "); int majorVersion = Integer.parseInt(version_tokenizer.nextToken()); int minorVersion = Integer.parseInt(version_tokenizer.nextToken()); - if ( majorVersion != majorInput || minorVersion != minorInput ) { - if ( majorInput == 1 && minorInput == 0 ) - System.out.println("\tThe maximum supported version has been returned. The driver is well-behaved. :)"); - else if ( majorInput < 3 && majorVersion < 3 ) - System.out.println("\tThe maximum supported version pre-3.0 has been returned. The driver is well-behaved. :)"); - else - System.out.println("\tThe requested version was not returned. The driver is buggy! :("); - } else - System.out.println("\tThe requested version was returned. :)"); + final boolean compatibilityProfile; + final boolean coreProfile; - if ( ca.isProfileCompatibility() && !GLContext.getCapabilities().GL_ARB_compatibility ) - System.out.println("\tThe driver does not support the Compatibility Profile."); + if ( 3 < majorVersion || (majorVersion == 3 && 2 <= minorVersion) ) { + final int profileMask = GL11.glGetInteger(GL32.GL_CONTEXT_PROFILE_MASK); - System.out.println("\n---------\n"); + compatibilityProfile = (profileMask & GL32.GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0; + coreProfile = (profileMask & GL32.GL_CONTEXT_CORE_PROFILE_BIT) != 0; + } else { + compatibilityProfile = false; + coreProfile = false; + } - System.out.println("Debug mode: " + ca.isDebug()); - System.out.println("Forward compatible mode: " + ca.isForwardCompatible()); - System.out.println("ARB_compatibility: " + GLContext.getCapabilities().GL_ARB_compatibility); - try { - GL11.glVertex3f(0.0f, 0.0f, 0.0f); - System.out.println("Deprecated functionality present: " + true); - } catch (Throwable t) { - System.out.println("Deprecated functionality present: " + false); - if ( GLContext.getCapabilities().GL_ARB_compatibility ) { - System.out.println("\tARB_compatibility is present, but LWJGL has enabled pseudo-forward compatible mode."); - } + System.out.println("\nGL_VERSION returned : " + version); + System.out.println("\tCore profile: " + coreProfile); + System.out.println("\tCompatibility profile: " + compatibilityProfile); + System.out.println("ARB_compatibility present: " + GLContext.getCapabilities().GL_ARB_compatibility); + System.out.println("Deprecated functionality present: " + deprecated); + if ( !deprecated && GLContext.getCapabilities().GL_ARB_compatibility ) + System.out.println("\tARB_compatibility is present, but LWJGL has enabled pseudo-forward compatible mode."); + + System.out.println("\n---------"); + + boolean success = false; + boolean check; + if ( majorInput < 3 || minorInput == 0 ) { + System.out.println("\nA version less than or equal to 3.0 is requested, the context\n" + + "returned may implement any of the following versions:"); + + System.out.println("\n1) Any version no less than that requested and no greater than 3.0."); + check = (majorInput < majorVersion || (majorInput == majorVersion && minorInput <= minorVersion)) // Satisfies requested version + && (majorVersion < 3 || (majorVersion == 3 && minorVersion == 0)); // 3.0 or earlier + System.out.println("\t" + check); + success |= check; + + System.out.println("\n2) Version 3.1, if the GL_ARB_compatibility extension is also implemented."); + check = majorVersion == 3 && minorVersion == 1 && GLContext.getCapabilities().GL_ARB_compatibility; + System.out.println("\t" + check); + success |= check; + + System.out.println("\n3) The compatibility profile of version 3.2 or greater."); + check = compatibilityProfile; // No need to check version, profiles are only available with 3.2+. + System.out.println("\t" + check); + success |= check; + + System.out.println("\nTEST " + (success ? "SUCCEEDED" : "FAILED")); + if ( !success && ca.isForwardCompatible() ) + System.out.println("\t(probably because the forward compatible flag was set)"); + } else if ( majorInput == 3 && minorInput == 1 ) { + System.out.println("\nVersion 3.1 is requested, the context returned may implement\n" + + "any of the following versions:"); + + System.out.println("\n1) Version 3.1. The GL_ARB_compatibility extension may or may not\n" + + "be implemented, as determined by the implementation."); + check = majorVersion == 3 && minorVersion == 1; + System.out.println("\t" + check); + success |= check; + + System.out.println("\n2) The core profile of version 3.2 or greater."); + check = coreProfile; // No need to check version, profiles are only available with 3.2+. + System.out.println("\t" + check); + success |= check; + + System.out.println("\nTEST " + (success ? "SUCCEEDED" : "FAILED")); + } else { + System.out.println("\nVersion 3.2 or greater is requested, the context returned may\n" + + "implement any of the following versions:"); + + System.out.println("\n1) The requested profile of the requested version."); + check = majorInput == majorVersion && minorInput == minorVersion + && (!ca.isProfileCompatibility() || compatibilityProfile) + && (!ca.isProfileCore() || coreProfile); + System.out.println("\t" + check); + success |= check; + + System.out.println("\n2) The requested profile of any later version, so long as no\n" + + "features have been removed from that later version and profile."); + check = majorInput < majorVersion || (majorInput == majorVersion && minorInput < minorVersion) + && (!ca.isProfileCompatibility() || compatibilityProfile) + && (!ca.isProfileCore() || coreProfile); + System.out.println("\t" + check); + success |= check; + + System.out.println("\nTEST " + (success ? "SUCCEEDED" : "FAILED")); } } @@ -174,12 +231,14 @@ private static void argsError(final String msg) { System.out.println("\nInvalid arguments error: " + msg); - System.out.println("\nUsage: VersionTest <majorVersion> <minorVersion> {<layer>, 'debug', 'fc'}:\n"); + System.out.println("\nUsage: VersionTest <majorVersion> <minorVersion> {'core'|'compatibility', <layer>, 'debug', 'fc'}:\n"); System.out.println("majorVersion\t- Major OpenGL version."); System.out.println("majorVersion\t- Minor OpenGL version."); + System.out.println("core\t- Sets the Core Profile bit (optional, requires 3.2+)."); + System.out.println("compatibility\t- Sets the Compatibility Profile bit (optional, requires 3.2+)."); System.out.println("layer\t- Layer plane (optional)."); System.out.println("debug\t- Enables debug mode (optional)."); - System.out.println("fc\t- Enables forward compatibility mode (optional)."); + System.out.println("fc\t- Enables forward compatibility mode (optional, requires 3.0+)."); cleanup(); System.exit(-1); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2010-07-04 17:14:40
|
Revision: 3364 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3364&view=rev Author: spasi Date: 2010-07-04 17:14:33 +0000 (Sun, 04 Jul 2010) Log Message: ----------- Fix for Linux fullscreen mode problem with Compiz (http://lwjgl.org/forum/index.php/topic,3335.0.html) Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/APIUtils.java trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/APIUtils.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/APIUtils.java 2010-07-04 14:45:33 UTC (rev 3363) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/APIUtils.java 2010-07-04 17:14:33 UTC (rev 3364) @@ -158,6 +158,7 @@ final InfiniteCharSequence infiniteSeq = getInfiniteSeq(); infiniteSeq.setString(string); encoder.encode(infiniteSeq.buffer, buffer, true); + infiniteSeq.clear(); } /** Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2010-07-04 14:45:33 UTC (rev 3363) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2010-07-04 17:14:33 UTC (rev 3364) @@ -410,7 +410,11 @@ ByteBuffer handle = peer_info.lockAndGetHandle(); try { current_window_mode = getWindowMode(Display.isFullscreen()); - boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated") || current_window_mode != WINDOWED; + // Setting _MOTIF_WM_HINTS in fullscreen mode is problematic for certain window + // managers. We do not set MWM_HINTS_DECORATIONS in fullscreen mode anymore, + // unless org.lwjgl.opengl.Window.undecorated_fs has been specified. + // See native/linux/org_lwjgl_opengl_Display.c, createWindow function. + boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated") || (current_window_mode != WINDOWED && Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated_fs")); this.parent = parent; parent_window = parent != null ? getHandle(parent) : getRootWindow(getDisplay(), getDefaultScreen()); current_window = nCreateWindow(getDisplay(), getDefaultScreen(), handle, mode, current_window_mode, x, y, undecorated, parent_window); Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java 2010-07-04 14:45:33 UTC (rev 3363) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java 2010-07-04 17:14:33 UTC (rev 3364) @@ -222,6 +222,8 @@ if (angleRotation > MAX_SPEED) { angleRotation = MAX_SPEED; } + + while ( Mouse.next() ); } /** * Cleans up the test This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ma...@us...> - 2010-07-27 19:19:04
|
Revision: 3396 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3396&view=rev Author: matzon Date: 2010-07-27 19:18:58 +0000 (Tue, 27 Jul 2010) Log Message: ----------- bumping native version Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java Modified: trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java 2010-07-27 19:17:53 UTC (rev 3395) +++ trunk/LWJGL/src/java/org/lwjgl/LinuxSysImplementation.java 2010-07-27 19:18:58 UTC (rev 3396) @@ -39,7 +39,7 @@ * $Id$ */ final class LinuxSysImplementation extends J2SESysImplementation { - private final static int JNI_VERSION = 18; + private final static int JNI_VERSION = 19; static { java.awt.Toolkit.getDefaultToolkit(); // This will make sure libjawt.so is loaded Modified: trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java 2010-07-27 19:17:53 UTC (rev 3395) +++ trunk/LWJGL/src/java/org/lwjgl/MacOSXSysImplementation.java 2010-07-27 19:18:58 UTC (rev 3396) @@ -42,7 +42,7 @@ * $Id$ */ final class MacOSXSysImplementation extends J2SESysImplementation { - private final static int JNI_VERSION = 18; + private final static int JNI_VERSION = 19; static { // Make sure AWT is properly initialized. This avoids hangs on Mac OS X 10.3 Modified: trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java 2010-07-27 19:17:53 UTC (rev 3395) +++ trunk/LWJGL/src/java/org/lwjgl/WindowsSysImplementation.java 2010-07-27 19:18:58 UTC (rev 3396) @@ -45,7 +45,7 @@ * $Id$ */ final class WindowsSysImplementation extends DefaultSysImplementation { - private final static int JNI_VERSION = 22; + private final static int JNI_VERSION = 23; static { Sys.initialize(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ma...@us...> - 2010-10-12 15:34:33
|
Revision: 3438 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3438&view=rev Author: matzon Date: 2010-10-12 15:34:26 +0000 (Tue, 12 Oct 2010) Log Message: ----------- fixed issue with signed/unsigned code dialog popping up Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/examples/spaceinvaders/TextureLoader.java trunk/LWJGL/src/java/org/lwjgl/util/WaveData.java Modified: trunk/LWJGL/src/java/org/lwjgl/examples/spaceinvaders/TextureLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/examples/spaceinvaders/TextureLoader.java 2010-10-12 09:32:34 UTC (rev 3437) +++ trunk/LWJGL/src/java/org/lwjgl/examples/spaceinvaders/TextureLoader.java 2010-10-12 15:34:26 UTC (rev 3438) @@ -33,6 +33,7 @@ import java.awt.Color; import java.awt.Graphics; +import java.awt.Image; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; @@ -41,7 +42,6 @@ import java.awt.image.DataBufferByte; import java.awt.image.Raster; import java.awt.image.WritableRaster; -import java.io.BufferedInputStream; import java.io.IOException; import java.net.URL; import java.nio.ByteBuffer; @@ -50,7 +50,7 @@ import java.util.HashMap; import java.util.Hashtable; -import javax.imageio.ImageIO; +import javax.swing.ImageIcon; import org.lwjgl.BufferUtils; @@ -277,7 +277,14 @@ throw new IOException("Cannot find: " + ref); } - BufferedImage bufferedImage = ImageIO.read(new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(ref))); + // due to an issue with ImageIO and mixed signed code + // we are now using good oldfashioned ImageIcon to load + // images and the paint it on top of a new BufferedImage + Image img = new ImageIcon(url).getImage(); + BufferedImage bufferedImage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); + Graphics g = bufferedImage.getGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); return bufferedImage; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/WaveData.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/WaveData.java 2010-10-12 09:32:34 UTC (rev 3437) +++ trunk/LWJGL/src/java/org/lwjgl/util/WaveData.java 2010-10-12 15:34:26 UTC (rev 3438) @@ -46,6 +46,8 @@ import org.lwjgl.openal.AL10; +import com.sun.media.sound.WaveFileReader; + /** * * Utitlity class for loading wavefiles. @@ -92,9 +94,11 @@ */ public static WaveData create(URL path) { try { - return create( - AudioSystem.getAudioInputStream( - new BufferedInputStream(path.openStream()))); + // due to an issue with AudioSystem.getAudioInputStream + // and mixing unsigned and signed code + // we will use the reader directly + WaveFileReader wfr = new WaveFileReader(); + return create(wfr.getAudioInputStream(new BufferedInputStream(path.openStream()))); } catch (Exception e) { org.lwjgl.LWJGLUtil.log("Unable to create from: " + path + ", " + e.getMessage()); return null; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ka...@us...> - 2010-12-15 18:49:02
|
Revision: 3463 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3463&view=rev Author: kappa1 Date: 2010-12-15 18:48:56 +0000 (Wed, 15 Dec 2010) Log Message: ----------- fix minor typo in javadoc/comments Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/input/Keyboard.java trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java Modified: trunk/LWJGL/src/java/org/lwjgl/input/Keyboard.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/input/Keyboard.java 2010-12-13 11:35:47 UTC (rev 3462) +++ trunk/LWJGL/src/java/org/lwjgl/input/Keyboard.java 2010-12-15 18:48:56 UTC (rev 3463) @@ -541,7 +541,7 @@ } /** - * Gets the state of the tkey that generated the + * Gets the state of the key that generated the * current event * * @return True if key was down, or false if released Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2010-12-13 11:35:47 UTC (rev 3462) +++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2010-12-15 18:48:56 UTC (rev 3463) @@ -925,7 +925,7 @@ * Due to the way applets on plugin1 work, one jvm must * be used for all applets. We need to use multiple * classloaders in the same jvm due to LWJGL's static - * nature. I order to solve this we simply remove the + * nature. In order to solve this we simply remove the * natives from a previous classloader allowing a new * classloader to use those natives in the same jvm. * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ka...@us...> - 2011-06-23 11:26:49
|
Revision: 3549 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3549&view=rev Author: kappa1 Date: 2011-06-23 11:26:42 +0000 (Thu, 23 Jun 2011) Log Message: ----------- Add "Unix" as a linux platform to allow LWJGL to work on Slackware Linux, thx to kruno73 for pointing this out. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java Modified: trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-06-19 20:18:02 UTC (rev 3548) +++ trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-06-23 11:26:42 UTC (rev 3549) @@ -277,7 +277,7 @@ final String osName = getPrivilegedProperty("os.name"); if ( osName.startsWith("Windows") ) PLATFORM = PLATFORM_WINDOWS; - else if ( osName.startsWith("Linux") || osName.startsWith("FreeBSD") || osName.startsWith("SunOS") ) + else if ( osName.startsWith("Linux") || osName.startsWith("FreeBSD") || osName.startsWith("SunOS") || osName.startsWith("Unix") ) PLATFORM = PLATFORM_LINUX; else if ( osName.startsWith("Mac OS X") || osName.startsWith("Darwin") ) PLATFORM = PLATFORM_MACOSX; Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-06-19 20:18:02 UTC (rev 3548) +++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-06-23 11:26:42 UTC (rev 3549) @@ -702,7 +702,7 @@ nativeJarList = getParameter("al_windows"); } - } else if (osName.startsWith("Linux")) { + } else if (osName.startsWith("Linux") || osName.startsWith("Unix")) { // check if arch specific natives have been specified if (System.getProperty("os.arch").endsWith("64")) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ka...@us...> - 2011-07-10 00:31:22
|
Revision: 3559 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3559&view=rev Author: kappa1 Date: 2011-07-10 00:31:16 +0000 (Sun, 10 Jul 2011) Log Message: ----------- minor update to comments and add missing JavaDoc Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2011-07-09 21:56:22 UTC (rev 3558) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2011-07-10 00:31:16 UTC (rev 3559) @@ -956,8 +956,8 @@ * in xembed mode. Every xembed embedder window has a focus proxy * window that recieves all the input. This method will test whether * the provided window handle is the focus proxy, if so it will get its - * parent window and then test whether this is indeed the window that - * belongs to our current_window. If so then parent window is active. + * parent window and then test whether this is an ancestor to our + * current_window. If so then parent window is active. * * @param window - the window handle to test */ Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-07-09 21:56:22 UTC (rev 3558) +++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-07-10 00:31:16 UTC (rev 3559) @@ -120,6 +120,9 @@ * <li>al_windows32 - [String] If specifed it will be used instead of al_windows on 32bit windows systems.</li> * <li>al_linux64 - [String] If specifed it will be used instead of al_linux on 64bit linux systems.</li> * <li>al_linux32 - [String] If specifed it will be used instead of al_linux on 32bit linux systems.</li> + * <li>al_mac32 - [String] If specifed it will be used instead of al_mac on 64bit mac systems.</li> + * <li>al_mac64 - [String] If specifed it will be used instead of al_mac on 32bit mac systems.</li> + * <li>al_macppc - [String] If specifed it will be used instead of al_mac on PPC mac systems.</li> * <p> * <li>boxbgcolor - [String] any String AWT color ("red", "blue", etc), RGB (0-255) or hex formated color (#RRGGBB) to use as background. <i>Default: #ffffff</i>.</li> * <li>boxfgcolor - [String] any String AWT color ("red", "blue", etc), RGB (0-255) or hex formated color (#RRGGBB) to use as foreground. <i>Default: #000000</i>.</li> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-07-12 13:29:14
|
Revision: 3571 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3571&view=rev Author: spasi Date: 2011-07-12 13:29:04 +0000 (Tue, 12 Jul 2011) Log Message: ----------- Mapped object code improvements: added license, additional documentation, reformatted code, now using LWJGLUtil.log instead of System.err. Added system properties for bytecode transformer debug output. (org.lwjgl.util.mapped.PrintTiming & org.lwjgl.util.mapped.PrintActivity) Added support for bounds checking the view of mapped objects. Enabled with org.lwjgl.util.mapped.Checks Added tests for mapped objects. (org.lwjgl.test.mapped package) Added "[LWJGL] " prefix to all LWJGL generated debug messages. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectUnsafe.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectBench.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java Modified: trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-07-12 07:27:00 UTC (rev 3570) +++ trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -448,7 +448,7 @@ /** * Gets a boolean property as a privileged action. */ - private static boolean getPrivilegedBoolean(final String property_name) { + public static boolean getPrivilegedBoolean(final String property_name) { Boolean value = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { public Boolean run() { return Boolean.getBoolean(property_name); @@ -464,7 +464,7 @@ */ public static void log(String msg) { if (DEBUG) { - System.err.println(msg); + System.err.println("[LWJGL] " + msg); } } Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.MappedObject; +import org.lwjgl.util.mapped.MappedType; + +/** @author Riven */ +@MappedType(sizeof = 4) +public class MappedFloat extends MappedObject { + + public MappedFloat() { + this.test(); + } + + public float value; + + public void test() { + this.value = 4; + } + + @Override + public String toString() { + return "MappedFloat[" + value + "]"; + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectBench.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectBench.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectBench.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.MappedObjectUnsafe; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +import static org.lwjgl.util.mapped.MappedHelper.*; + +/** @author Riven */ +@SuppressWarnings("static-access") +public class MappedObjectBench { + + static class InstanceVec3 { + + float x, y, z; + + @Override + public String toString() { + return "InstanceVec3[" + x + ", " + y + ", " + z + "]"; + } + } + + static class ArrayVec3 { + + float[] a; + int i; + + @Override + public String toString() { + return "ArrayVec3[" + a[i * 3 + 0] + ", " + a[i * 3 + 1] + ", " + a[i * 3 + 2] + "]"; + } + } + + static void benchmarkInstances() { + final int runs = 64; + final int iterations = 64 * 1024; + + InstanceVec3 vec1 = new InstanceVec3(); + InstanceVec3 vec2 = new InstanceVec3(); + InstanceVec3 vec3 = new InstanceVec3(); + + long[] took = new long[runs]; + for ( int run = 0; run < runs; run++ ) { + long t0 = System.nanoTime(); + for ( int iteration = 0; iteration < iterations; iteration++ ) { + vec1.x = 13; + vec1.y += vec1.y * vec1.x + 0.3f; + vec1.z += vec2.y + vec1.x + 0.3f; + vec2.z += vec2.y + vec1.x; + vec3.z += vec2.z + vec1.y; + } + long t1 = System.nanoTime(); + took[run] = t1 - t0; + } + + Arrays.sort(took); + System.out.println("instance took: " + took[took.length / 2] / 1024 + "us"); + + System.out.println(vec1); + System.out.println(vec2); + System.out.println(vec3); + } + + static void benchmarkMapped() { + final int runs = 64; + final int iterations = 64 * 1024; + + ByteBuffer bb = ByteBuffer.allocateDirect(200); + + MappedVec3 vecs = MappedVec3.map(bb); + + MappedVec3 vec1 = vecs.dup(); + MappedVec3 vec2 = vecs.dup(); + MappedVec3 vec3 = vecs.dup(); + + vec1.view = 0; + vec2.view = 1; + vec3.view = 2; + + long[] took = new long[runs]; + for ( int run = 0; run < runs; run++ ) { + long t0 = System.nanoTime(); + for ( int iteration = 0; iteration < iterations; iteration += 2 ) { + vec1.x = 13; + vec1.y += vec1.y * vec1.x + 0.3f; + vec1.z += vec2.y + vec1.x + 0.3f; + vec2.z += vec2.y + vec1.x; + vec3.z += vec2.z + vec1.y; + + vec1.x = 13; + vec1.y += vec1.y * vec1.x + 0.3f; + vec1.z += vec2.y + vec1.x + 0.3f; + vec2.z += vec2.y + vec1.x; + vec3.z += vec2.z + vec1.y; + } + long t1 = System.nanoTime(); + took[run] = t1 - t0; + } + + Arrays.sort(took); + System.out.println("mapped took: " + took[took.length / 2] / 1024 + "us"); + + System.out.println(vec1); + System.out.println(vec2); + System.out.println(vec3); + + System.out.println(bb); + } + + static void benchmarkIndirectArray() { + final int runs = 64; + final int iterations = 64 * 1024; + + float[] bb = new float[200]; + + ArrayVec3 vec1 = new ArrayVec3(); + ArrayVec3 vec2 = new ArrayVec3(); + ArrayVec3 vec3 = new ArrayVec3(); + + vec1.a = bb; + vec2.a = bb; + vec3.a = bb; + + vec1.i = 0; + vec2.i = 1; + vec3.i = 2; + + long[] took = new long[runs]; + for ( int run = 0; run < runs; run++ ) { + long t0 = System.nanoTime(); + for ( int iteration = 0; iteration < iterations; iteration++ ) { + vec1.a[vec1.i * 3 + 0] = 13; + vec1.a[vec1.i * 3 + 1] += vec1.a[vec1.i * 3 + 1] * vec1.a[vec1.i * 3 + 0] + 0.3f; + vec1.a[vec1.i * 3 + 2] += vec2.a[vec2.i * 3 + 1] + vec1.a[vec1.i * 3 + 0] + 0.3f; + vec2.a[vec2.i * 3 + 2] += vec2.a[vec2.i * 3 + 1] + vec1.a[vec1.i * 3 + 0]; + vec3.a[vec3.i * 3 + 2] += vec2.a[vec2.i * 3 + 2] + vec2.a[vec2.i * 3 + 1]; + } + long t1 = System.nanoTime(); + took[run] = t1 - t0; + } + + Arrays.sort(took); + System.out.println("array took: " + took[took.length / 2] / 1024 + "us"); + + System.out.println(vec1); + System.out.println(vec2); + System.out.println(vec3); + + System.out.println(bb); + } + + static void benchmarkDirectArray() { + final int runs = 64; + final int iterations = 64 * 1024; + + float[] bb = new float[200]; + + long[] took = new long[runs]; + for ( int run = 0; run < runs; run++ ) { + long t0 = System.nanoTime(); + for ( int iteration = 0; iteration < iterations; iteration++ ) { + bb[1 * 3 + 0] = 13; + bb[1 * 3 + 1] += bb[1 * 3 + 1] * bb[1 * 3 + 0] + 0.3f; + bb[1 * 3 + 2] += bb[2 * 3 + 1] + bb[1 * 3 + 0] + 0.3f; + bb[2 * 3 + 2] += bb[2 * 3 + 1] + bb[1 * 3 + 0]; + bb[3 * 3 + 2] += bb[2 * 3 + 2] + bb[2 * 3 + 1]; + } + long t1 = System.nanoTime(); + took[run] = t1 - t0; + } + + Arrays.sort(took); + System.out.println("array2 took: " + took[took.length / 2] / 1024 + "us"); + + System.out.println(bb); + } + + static void benchmarkUnsafe() { + final int runs = 64; + final int iterations = 64 * 1024; + + ByteBuffer bb = ByteBuffer.allocateDirect(200); + long addr = MappedObjectUnsafe.getBufferBaseAddress(bb); + + long[] took = new long[runs]; + for ( int run = 0; run < runs; run++ ) { + long t0 = System.nanoTime(); + for ( int iteration = 0; iteration < iterations; iteration++ ) { + fput(13, addr + (1 * 3 + 0) * 4); + fput(fget(addr + (1 * 3 + 1) * 4) + fget(addr + (1 * 3 + 1) * 4) * fget(addr + (1 * 3 + 0) * 4) + 0.3f, addr + (1 * 3 + 1) * 4); + fput(fget(addr + (1 * 3 + 2) * 4) + fget(addr + (2 * 3 + 1) * 4) + fget(addr + (1 * 3 + 0) * 4) + 0.3f, addr + (1 * 3 + 2) * 4); + fput(fget(addr + (2 * 3 + 2) * 4) + fget(addr + (2 * 3 + 1) * 4) + fget(addr + (1 * 3 + 0) * 4), addr + (2 * 3 + 2) * 4); + fput(fget(addr + (3 * 3 + 2) * 4) + fget(addr + (2 * 3 + 2) * 4) + fget(addr + (2 * 3 + 1) * 4), addr + (3 * 3 + 2) * 4); + } + long t1 = System.nanoTime(); + took[run] = t1 - t0; + } + + Arrays.sort(took); + System.out.println("unsafe took: " + took[took.length / 2] / 1024 + "us"); + + System.out.println(bb); + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.MappedHelper; +import org.lwjgl.util.mapped.MappedObjectUnsafe; + +import java.nio.ByteBuffer; + +/** @author Riven */ +@SuppressWarnings("static-access") +public class MappedObjectTests1 { + + static class Test { + + int value; + } + + static void testViewField() { + Test test = new Test(); + test.value = 13; + test.value += 1; + test.value++; + System.out.println(test); + + ByteBuffer bb = ByteBuffer.allocateDirect(200); + MappedFloat vecs = MappedFloat.map(bb); + + // verify 'malloc' and SIZEOF + { + MappedFloat vecs1 = MappedFloat.malloc(1234); + + assert (vecs1.stride == MappedFloat.SIZEOF); + assert (vecs1.stride * 1234 == vecs1.backingByteBuffer().capacity()); + assert (MappedFloat.SIZEOF * 1234 == vecs1.backingByteBuffer().capacity()); + } + + // manipulate 'mapped.value' + { + assert (vecs.value == 0.0f); // 4.0 is set in constructor, but runViewConstructor is not called + vecs.value = 1.1f; + assert (vecs.value == 1.1f); + } + + // manipulate 'view' with assignment + { + assert (vecs.view == 0); + vecs.view = 1; + assert (vecs.view == 1); + assert (vecs.value != 1.1f); // old view + vecs.view = 0; + } + + // manipulate 'view' with iinc + { + assert (vecs.view == 0); + vecs.view++; + assert (vecs.view == 1); + assert (vecs.value != 1.1f); // old view + vecs.view = 0; + } + + // test bound check + { + assert (vecs.view == 0); + try { + vecs.view = 50; + System.out.println("org.lwjgl.util.mapped.Checks is false or there is a bug in bounds checking."); + vecs.view = 0; + } catch (IndexOutOfBoundsException e) { + // expected, ignore + } + assert (vecs.view == 0); + } + + // test dup + { + int newStride = 16; + int doOffset = 0; + + vecs.view = 0; + MappedFloat.configure(vecs, newStride, doOffset); + MappedFloat dec2 = vecs.dup(); + MappedFloat.configure(dec2, newStride, doOffset); + + String s1 = vecs.baseAddress + "," + vecs.viewAddress + "," + vecs.stride + "," + vecs.SIZEOF; + String s2 = dec2.baseAddress + "," + dec2.viewAddress + "," + dec2.stride + "," + dec2.SIZEOF; + // System.out.println(s1); + // System.out.println(s2); + assert (s1.equals(s2)); + + dec2.view++; + + String s3 = vecs.baseAddress + "," + vecs.viewAddress + "," + vecs.stride + "," + vecs.SIZEOF; + String s4 = dec2.baseAddress + "," + dec2.viewAddress + "," + dec2.stride + "," + dec2.SIZEOF; + // System.out.println(s3); + // System.out.println(s4); + assert (!s3.equals(s4)); + } + + // test newBuffer + { + long addr1 = MappedObjectUnsafe.getBufferBaseAddress(bb); + ByteBuffer bb2 = MappedHelper.newBuffer(addr1, bb.capacity()); + long addr2 = MappedObjectUnsafe.getBufferBaseAddress(bb); + + System.out.println(bb); + System.out.println(bb2); + System.out.println(addr1); + System.out.println(addr2); + } + + // test 'copy' + { + vecs.value = 13.37f; + MappedFloat dec2 = vecs.dup(); + dec2.view = 1; + System.out.println(vecs); + System.out.println(dec2); + vecs.copyTo(dec2); + System.out.println(vecs); + System.out.println(dec2); + assert (dec2.value == 13.37f); + + vecs.value = 73.31f; + vecs.copyRange(dec2, 1); + assert (dec2.value == 73.31f); + } + } +} Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import java.nio.ByteBuffer; + +/** @author Riven */ +@SuppressWarnings("static-access") +public class MappedObjectTests2 { + + static void testWriteFieldAccess(MappedVec3 vecs) { + // write access results into a transform-time IllegalAccessException + + System.out.println(vecs.baseAddress); // test read-access + + System.out.println(vecs.viewAddress); // test read-access + + System.out.println(vecs.align); // test read-access + + System.out.println(MappedVec3.SIZEOF); // test read-access + } + + static void testFields() { + ByteBuffer bb = ByteBuffer.allocateDirect(200); + MappedVec3 vecs = MappedVec3.map(bb); + + testWriteFieldAccess(vecs); + + vecs.x = 13.13f; + vecs.y = 14.14f; + vecs.z = 15.15f; + + System.out.println(vecs.viewAddress); + + assert (vecs.x == 13.13f); + assert (vecs.y == 14.14f); + assert (vecs.z == 15.15f); + + vecs.view = 0; + + assert (vecs.x == 13.13f); + assert (vecs.y == 14.14f); + assert (vecs.z == 15.15f); + + System.out.println(vecs); + vecs.view = 1; + System.out.println(vecs); + + assert (vecs.x == 0.0f); + assert (vecs.y == 0.0f); + assert (vecs.z == 0.0f); + + // now it becomes weird: offsets and strides + + vecs.view = 1; + vecs.x = 0.1234f; + vecs.view = 0; + + // test stride & sizeof + { + long a1 = vecs.viewAddress; + vecs.view = 1; + long a2 = vecs.viewAddress; + assert (a2 - a1 == MappedVec3.SIZEOF); + assert (a2 - a1 == vecs.stride); + vecs.view = 0; + } + + int newStride = 16; + + MappedVec3.configure(vecs, newStride, +4); + assert (vecs.z == 0.1234f); // vecs[1].x ended up in vecs[0].z due to 1float offset + + MappedVec3.configure(vecs, newStride, +8); + assert (vecs.z == 0.0000f); // vecs[1].z ended up in vecs[0].z due to 2float offset + + // test new stride + { + long a1 = vecs.viewAddress; + vecs.view = 1; + long a2 = vecs.viewAddress; + assert (a2 - a1 == newStride); + vecs.view = 0; + } + + // example: GPU => VBO => VTN + { + MappedVec3 v = MappedVec3.map(bb); + MappedVec2 t = MappedVec2.map(bb); + MappedVec3 n = MappedVec3.map(bb); + + int stride = MappedVec3.SIZEOF + MappedVec2.SIZEOF + MappedVec3.SIZEOF; + assert (stride == 32); + + MappedVec3.configure(v, stride, 0); + MappedVec2.configure(t, stride, MappedVec3.SIZEOF); + MappedVec3.configure(n, stride, MappedVec3.SIZEOF + MappedVec2.SIZEOF); + } + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.*; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import static org.lwjgl.util.mapped.MappedObject.*; + +/** @author Riven */ +@SuppressWarnings("static-access") +public class MappedObjectTests3 { + + static void testMappedBuffer() { + int elementCount = 4; + + MappedSomething some = MappedSomething.malloc(elementCount); + + assert (some.data != some.data); + + long addr1 = MappedObjectUnsafe.getBufferBaseAddress(some.backingByteBuffer()); + + ByteBuffer mapped = some.data; // creates new ByteBuffer instance + long addr2 = MappedObjectUnsafe.getBufferBaseAddress(mapped); + + assert (addr2 - addr1 == 4); + assert (mapped.capacity() == MappedSomething.SIZEOF - 4); + + some.view++; + mapped = some.data; // creates new ByteBuffer instance + + long addr3 = MappedObjectUnsafe.getBufferBaseAddress(mapped); + assert (addr3 - addr1 == 4 + MappedSomething.SIZEOF); + assert (addr3 - addr2 == 0 + MappedSomething.SIZEOF); + assert (mapped.capacity() == MappedSomething.SIZEOF - 4); + } + + static void testForeach() { + int elementCount = 4; + MappedSomething some = MappedSomething.malloc(elementCount); + + int i = 0; + for ( MappedSomething item : foreach(some, elementCount) ) { + assert (item.view == i++); + } + assert (some.view != elementCount); + System.out.println("current.view=" + some.view + ", not " + elementCount + ", as you might expect"); + } + + @MappedType(sizeof = 12) + public static class Xyz extends MappedObject { + + int x, y, z; + } + + static void testConstructor() { + int capacity = 1024; + ByteBuffer bb = ByteBuffer.allocateDirect(capacity).order(ByteOrder.nativeOrder()); + long address = MappedObjectUnsafe.getBufferBaseAddress(bb); + + MappedFloat mf = MappedFloat.map(address, capacity); + + assert (address == mf.baseAddress); + + assert (mf.value == 0.0f); + mf.view = 1; + assert (mf.value == 0.0f); + mf.runViewConstructor(); + assert (mf.value == 4.0f); + + Xyz.malloc(3); + } + + static void testMappedSet() { + MappedVec2 vec2 = MappedVec2.malloc(3); + MappedVec3 vec3 = MappedVec3.malloc(3); + + MappedSet2 set = MappedSet.create(vec2, vec3); + + assert (vec2.view == 0); + assert (vec3.view == 0); + + set.view = 2; + assert (vec2.view == 2); + assert (vec3.view == 2); + + set.view = 0; + assert (vec2.view == 0); + assert (vec3.view == 0); + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.MappedField; +import org.lwjgl.util.mapped.MappedObject; +import org.lwjgl.util.mapped.MappedType; + +import java.nio.ByteBuffer; + +/** @author Riven */ +@MappedType(sizeof = 64) +public class MappedSomething extends MappedObject { + + @MappedField(byteOffset = 0) + public int used; + + @MappedField(byteOffset = 4, byteLength = 64 - 4) + public ByteBuffer data; + + @Override + public String toString() { + return "MappedSomething[" + used + "]"; + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.MappedObject; +import org.lwjgl.util.mapped.MappedType; + +/** @author Riven */ +@MappedType(sizeof = 8) +public class MappedVec2 extends MappedObject { + + public float x; + + public float y; + + @Override + public String toString() { + return "MappedVec2[" + x + "," + y + "]"; + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.MappedObject; +import org.lwjgl.util.mapped.MappedType; + +/** @author Riven */ +@MappedType(sizeof = 12) +public class MappedVec3 extends MappedObject { + + public float x; + + public float y; + + public float z; + + @Override + public String toString() { + return "[" + x + "," + y + "," + z + "]"; + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.mapped; + +import org.lwjgl.util.mapped.MappedObjectClassLoader; +import org.lwjgl.util.mapped.MappedObjectTransformer; + +/** @author Riven */ +public class TestMappedObject { + + static { + boolean assertsEnabled = false; + assert assertsEnabled = true; // Intentional side effect!!! + if ( !assertsEnabled ) + throw new RuntimeException("Asserts must be enabled for this test."); + } + + public static void main(String[] args) { + MappedObjectTransformer.register(MappedFloat.class); + MappedObjectTransformer.register(MappedVec2.class); + MappedObjectTransformer.register(MappedVec3.class); + MappedObjectTransformer.register(MappedSomething.class); + + MappedObjectTransformer.register(MappedObjectTests3.Xyz.class); + + if ( MappedObjectClassLoader.fork(TestMappedObject.class, args) ) { + return; + } + + MappedObjectTests1.testViewField(); + + MappedObjectTests2.testFields(); + + // MappedObjectBench.benchmarkMapped(); + // MappedObjectBench.benchmarkInstances(); + // MappedObjectBench.benchmarkIndirectArray(); + // MappedObjectBench.benchmarkDirectArray(); + // MappedObjectBench.benchmarkUnsafe(); + + MappedObjectTests3.testMappedBuffer(); + MappedObjectTests3.testForeach(); + MappedObjectTests3.testConstructor(); + MappedObjectTests3.testMappedSet(); + } + +} \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java 2011-07-12 07:27:00 UTC (rev 3570) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -1,19 +1,65 @@ /* - * Created on Jun 24, 2011 + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package org.lwjgl.util.mapped; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** + * This annotation can be used on fields of {@link MappedType} classes, + * to manually specify byte offsets and lengths. This is useful when the + * mapped fields require custom alignment. {@link java.nio.ByteBuffer} + * fields are required to have this annotation with a hardcoded byte length. + * * @author Riven */ - @Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) public @interface MappedField { - long byteOffset(); - long byteLength() default -1; -} + /** + * Specifies the field byte offset within the mapped object. + * + * @return the field byte offset + */ + long byteOffset(); + + /** + * Specifies the field byte length. Required for {@link java.nio.ByteBuffer} fields. + * + * @return the field byte length + */ + long byteLength() default -1; + +} \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java 2011-07-12 07:27:00 UTC (rev 3570) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -1,52 +1,72 @@ /* - * Created on Jul 4, 2011 + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package org.lwjgl.util.mapped; import java.util.Iterator; /** + * Iterable implementation for {@link MappedObject}. + * * @author Riven */ +public class MappedForeach<T extends MappedObject> implements Iterable<T> { -public class MappedForeach<T extends MappedObject> implements Iterable<T> -{ - final T mapped; - final int elementCount; + private final T mapped; + private final int elementCount; - MappedForeach(T mapped, int elementCount) - { - this.mapped = mapped; - this.elementCount = elementCount; - } + MappedForeach(T mapped, int elementCount) { + this.mapped = mapped; + this.elementCount = elementCount; + } - @Override - public Iterator<T> iterator() - { - return new Iterator<T>() - { - private int index = 0; + public Iterator<T> iterator() { + return new Iterator<T>() { - @Override - public boolean hasNext() - { - return this.index < (MappedForeach.this.elementCount); - } + private int index; - @Override - public T next() - { - mapped.viewAddress = mapped.baseAddress + (this.index++) * mapped.stride; + public boolean hasNext() { + return this.index < (MappedForeach.this.elementCount); + } - return mapped; - } + public T next() { + mapped.viewAddress = mapped.baseAddress + (this.index++) * mapped.stride; - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } - }; - } -} + return mapped; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + +} \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-12 07:27:00 UTC (rev 3570) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -1,181 +1,188 @@ /* - * Created on Jun 28, 2011 + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package org.lwjgl.util.mapped; import java.nio.ByteBuffer; /** + * [INTERNAL USE ONLY] + * <p/> + * Helper class used by the bytecode transformer. + * * @author Riven */ +public class MappedHelper { -public class MappedHelper -{ - public static void setup(MappedObject mo, ByteBuffer buffer, int align, int sizeof) - { - if (mo.baseAddress != 0L) - throw new IllegalStateException("this method should not be called by user-code"); + public static void setup(MappedObject mo, ByteBuffer buffer, int align, int sizeof) { + if ( mo.baseAddress != 0L ) + throw new IllegalStateException("this method should not be called by user-code"); - if (buffer == null) - throw new NullPointerException("buffer"); - if (!buffer.isDirect()) - throw new IllegalArgumentException("bytebuffer must be direct"); - mo.preventGC = buffer; + if ( buffer == null ) + throw new NullPointerException("buffer"); + if ( !buffer.isDirect() ) + throw new IllegalArgumentException("bytebuffer must be direct"); + mo.preventGC = buffer; - if (align <= 0) - throw new IllegalArgumentException("invalid alignment"); - mo.align = align; + if ( align <= 0 ) + throw new IllegalArgumentException("invalid alignment"); + mo.align = align; - if (sizeof % align != 0) - throw new IllegalStateException("sizeof not a multiple of alignment"); - mo.stride = sizeof; + if ( sizeof % align != 0 ) + throw new IllegalStateException("sizeof not a multiple of alignment"); + mo.stride = sizeof; - long addr = MappedObjectUnsafe.getBufferBaseAddress(buffer); - if (addr % align != 0) - throw new IllegalStateException("buffer address not aligned on " + align + " bytes"); + long addr = MappedObjectUnsafe.getBufferBaseAddress(buffer); + if ( addr % align != 0 ) + throw new IllegalStateException("buffer address not aligned on " + align + " bytes"); - mo.baseAddress = mo.viewAddress = addr; - } + mo.baseAddress = mo.viewAddress = addr; + } - public static void put_views(MappedSet2 set, int view) - { - set.view(view); - } + public static void put_views(MappedSet2 set, int view) { + set.view(view); + } - public static void put_views(MappedSet3 set, int view) - { - set.view(view); - } + public static void put_views(MappedSet3 set, int view) { + set.view(view); + } - public static void put_views(MappedSet4 set, int view) - { - set.view(view); - } + public static void put_views(MappedSet4 set, int view) { + set.view(view); + } - public static void put_view(MappedObject mapped, int view) - { - mapped.viewAddress = mapped.baseAddress + view * mapped.stride; - } + public static void put_view(MappedObject mapped, int view) { + mapped.setViewAddress(mapped.baseAddress + view * mapped.stride); + } - public static int get_view(MappedObject mapped) - { - return (int) (mapped.viewAddress - mapped.baseAddress) / mapped.stride; - } + public static int get_view(MappedObject mapped) { + return (int)(mapped.viewAddress - mapped.baseAddress) / mapped.stride; + } - public static MappedObject dup(MappedObject src, MappedObject dst) - { - dst.baseAddress = src.baseAddress; - dst.viewAddress = src.viewAddress; - dst.stride = src.stride; - dst.align = src.align; - dst.preventGC = src.preventGC; - return dst; - } + public static MappedObject dup(MappedObject src, MappedObject dst) { + dst.baseAddress = src.baseAddress; + dst.viewAddress = src.viewAddress; + dst.stride = src.stride; + dst.align = src.align; + dst.preventGC = src.preventGC; + return dst; + } - public static MappedObject slice(MappedObject src, MappedObject dst) - { - dst.baseAddress = src.viewAddress; // ! - dst.viewAddress = src.viewAddress; - dst.stride = src.stride; - dst.align = src.align; - dst.preventGC = src.preventGC; - return dst; - } + public static MappedObject slice(MappedObject src, MappedObject dst) { + dst.baseAddress = src.viewAddress; // ! + dst.viewAddress = src.viewAddress; + dst.stride = src.stride; + dst.align = src.align; + dst.preventGC = src.preventGC; + return dst; + } - public static void copy(MappedObject src, MappedObject dst, int bytes) - { - MappedObjectUnsafe.INSTANCE.copyMemory(src.viewAddress, dst.viewAddress, bytes); - } + public static void copy(MappedObject src, MappedObject dst, int bytes) { + MappedObjectUnsafe.INSTANCE.copyMemory(src.viewAddress, dst.viewAddress, bytes); + } - public static ByteBuffer newBuffer(long address, int capacity) - { - return MappedObjectUnsafe.newBuffer(address, capacity); - } + public static ByteBuffer newBuffer(long address, int capacity) { + return MappedObjectUnsafe.newBuffer(address, capacity); + } - // ---- primitive fields read/write + // ---- primitive fields read/write - // byte + // byte - public static void bput(byte value, long addr) - { - MappedObjectUnsafe.INSTANCE.putByte(addr, value); - } + public static void bput(byte value, long addr) { + MappedObjectUnsafe.INSTANCE.putByte(addr, value); + } - public static byte bget(long addr) - { - return MappedObjectUnsafe.INSTANCE.getByte(addr); - } + public static byte bget(long addr) { + return MappedObjectUnsafe.INSTANCE.getByte(addr); + } - // short + // short - public static void sput(short value, long addr) - { - MappedObjectUnsafe.INSTANCE.putShort(addr, value); - } + public static void sput(short value, long addr) { + MappedObjectUnsafe.INSTANCE.putShort(addr, value); + } - public static short sget(long addr) - { - return MappedObjectUnsafe.INSTANCE.getShort(addr); - } + public static short sget(long addr) { + return MappedObjectUnsafe.INSTANCE.getShort(addr); + } - // char + // char - public static void cput(char value, long addr) - { - MappedObjectUnsafe.INSTANCE.putChar(addr, value); - } + public static void cput(char value, long addr) { + MappedObjectUnsafe.INSTANCE.putChar(addr, value); + } - public static char cget(long addr) - { - return MappedObjectUnsafe.INSTANCE.getChar(addr); - } + public static char cget(long addr) { + return MappedObjectUnsafe.INSTANCE.getChar(addr); + } - // int + // int - public static void iput(int value, long addr) - { - MappedObjectUnsafe.INSTANCE.putInt(addr, value); - } + public static void iput(int value, long addr) { + MappedObjectUnsafe.INSTANCE.putInt(addr, value); + } - public static int iget(long addr) - { - return MappedObjectUnsafe.INSTANCE.getInt(addr); - } + public static int iget(long addr) { + return MappedObjectUnsafe.INSTANCE.getInt(addr); + } - // float + // float - public static void fput(float value, long addr) - { - MappedObjectUnsafe.INSTANCE.putFloat(addr, value); - } + public static void fput(float value, long addr) { + MappedObjectUnsafe.INSTANCE.putFloat(addr, value); + } - public static float fget(long addr) - { - return MappedObjectUnsafe.INSTANCE.getFloat(addr); - } + public static float fget(long addr) { + return MappedObjectUnsafe.INSTANCE.getFloat(addr); + } - // long + // long - public static void jput(long value, long addr) - { - MappedObjectUnsafe.INSTANCE.putLong(addr, value); - } + public static void jput(long value, long addr) { + MappedObjectUnsafe.INSTANCE.putLong(addr, value); + } - public static long jget(long addr) - { - return MappedObjectUnsafe.INSTANCE.getLong(addr); - } + public static long jget(long addr) { + return MappedObjectUnsafe.INSTANCE.getLong(addr); + } - // double + // double - public static void dput(double value, long addr) - { - MappedObjectUnsafe.INSTANCE.putDouble(addr, value); - } + public static void dput(double value, long addr) { + MappedObjectUnsafe.INSTANCE.putDouble(addr, value); + } - public static double dget(long addr) - { - return MappedObjectUnsafe.INSTANCE.getDouble(addr); - } + public static double dget(long addr) { + return MappedObjectUnsafe.INSTANCE.getDouble(addr); + } + } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-12 07:27:00 UTC (rev 3570) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-12 13:29:04 UTC (rev 3571) @@ -1,185 +1,248 @@ /* - * Created on Jun 25, 2011 + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package org.lwjgl.util.mapped; +import org.lwjgl.LWJGLUtil; + import java.nio.ByteBuffer; /** + * Base superclass of all mapped objects. Classes that require + * data mapping should extend this class and also be annotated + * with {@link MappedType}. + * <p/> + * Subclasses may only specify the default constructor. Any code + * inside that constructor is optional, but will not run when the + * view is instantiated, see {@link #runViewConstructor()}. + * <p/> + * Bounds checking may be enabled through a JVM system property: org.lwjgl.util.mapped.Checks=true + * * @author Riven */ +public class MappedObject { -public class MappedObject -{ - public MappedObject() - { - // - } + static final boolean CHECKS = LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.Checks"); - // these fields are not assignable/writable by user-code - public long baseAddress; - public long viewAddress; - public int stride; - public int align; + public MappedObject() { + // + } - /** - * Holds the value of sizeof of the sub-type of this MappedObject<br> - * <br> - * The behavior of this (transformed) method does not follow the normal Java behavior.<br> - * <code>Vec2.SIZEOF</code> will yield 8 (2 floats)<br> - * <code>Vec3.SIZEOF</code> will yield 12 (3 floats)<br> - * This (required) notation might cause compiler warnings, which can be suppressed with @SuppressWarnings("static-access").<br> - * Using Java 5.0's static-import on this method will break functionality. - */ + /** The mapped object base memory address, in bytes. Read-only. */ + public long baseAddress; - // any method that calls these field will have its call-site modified - public static int SIZEOF = -1; // 'final' per subtype - public int view; // read/write + /** The mapped object view memory address, in bytes. Read-only. */ + public long viewAddress; - public final void next() - { - this.viewAddress += this.stride; - } + /** The mapped object stride, in bytes. Read-only. */ + public int stride; - /** - * Creates a MappedObject instance, mapping the memory region of the specified direct ByteBuffer.<br> - * <br> - * The behavior of this (transformed) method does not follow the normal Java behavior.<br> - * <code>Vec2.map(buffer)</code> will return a mapped Vec2 instance.<br> - * <code>Vec3.map(buffer)</code> will return a mapped Vec3 instance.<br> - * This (required) notation might cause compiler warnings, which can be suppressed with @SuppressWarnings("static-access").<br> - * Using Java 5.0's static-import on this method will break functionality. - */ + /** The mapped object memory alignment, in bytes. Read-only. */ + public int align; - @SuppressWarnings("unused") - public static <T extends MappedObject> T map(ByteBuffer bb) - { - // any method that calls this method will have its call-site modified - throw new InternalError("type not registered"); - } + /** + * Holds the value of sizeof of the sub-type of this MappedObject<br> + * <br> + * The behavior of this (transformed) method does not follow the normal Java behavior.<br> + * <code>Vec2.SIZEOF</code> will yield 8 (2 floats)<br> + * <code>Vec3.SIZEOF</code> will yield 12 (3 floats)<br> + * This (required) notation might cause compiler warnings, which can be suppressed with @SuppressWarnings("static-access").<br> + * Using Java 5.0's static-import on this method will break functionality. + */ + public static int SIZEOF = -1; // any method that calls these field will have its call-site modified ('final' per subtype) - @SuppressWarnings("unused") - public static <T extends MappedObject> T map(long address, int capacity) - { - // any method that calls this method will have its call-site modified - throw new InternalError("ty... [truncated message content] |
From: <sp...@us...> - 2011-07-12 13:44:19
|
Revision: 3572 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3572&view=rev Author: spasi Date: 2011-07-12 13:44:13 +0000 (Tue, 12 Jul 2011) Log Message: ----------- Fixed bounds checking to work with .sliced mapped objects. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-12 13:29:04 UTC (rev 3571) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-12 13:44:13 UTC (rev 3572) @@ -89,17 +89,34 @@ vecs.view = 0; } - // test bound check + // test bounds checking { assert (vecs.view == 0); try { + vecs.view = 49; + assert vecs.view == 49; + vecs.view = 0; vecs.view = 50; System.out.println("org.lwjgl.util.mapped.Checks is false or there is a bug in bounds checking."); vecs.view = 0; } catch (IndexOutOfBoundsException e) { // expected, ignore } + assert (vecs.view == 0); + + try { + vecs.view = 10; + MappedFloat vecs2 = vecs.slice(); + vecs.view = 0; + + vecs2.view = 39; + assert vecs2.view == 39; + vecs2.view = 40; + System.out.println("org.lwjgl.util.mapped.Checks is false or there is a bug in bounds checking."); + } catch (IndexOutOfBoundsException e) { + // expected, ignore + } } // test dup Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-12 13:29:04 UTC (rev 3571) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-12 13:44:13 UTC (rev 3572) @@ -97,7 +97,7 @@ } final void checkAddress(final long address) { - if ( preventGC.capacity() < (address + stride - baseAddress) ) + if ( preventGC.capacity() < (address - MappedObjectUnsafe.getBufferBaseAddress(preventGC) + stride) ) throw new IndexOutOfBoundsException(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-07-12 14:21:36
|
Revision: 3573 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3573&view=rev Author: spasi Date: 2011-07-12 14:21:29 +0000 (Tue, 12 Jul 2011) Log Message: ----------- Changed mapping behavior to be consistent with the LWJGL API; it now starts at the buffer's current .position(). Reverted client JVM warning to use serr instead of LWJGLUtil.log, for extra visibility when Debug is disabled. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-12 13:44:13 UTC (rev 3572) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-12 14:21:29 UTC (rev 3573) @@ -117,6 +117,19 @@ } catch (IndexOutOfBoundsException e) { // expected, ignore } + + try { + ByteBuffer posTest = ByteBuffer.allocateDirect(200); + posTest.position(10 * MappedFloat.SIZEOF); // position > 0 + + MappedFloat vecs2 = MappedFloat.map(posTest); + vecs2.view = 39; + assert vecs2.view == 39; + vecs2.view = 40; + System.out.println("org.lwjgl.util.mapped.Checks is false or there is a bug in bounds checking."); + } catch (IndexOutOfBoundsException e) { + // expected, ignore + } } // test dup Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-12 13:44:13 UTC (rev 3572) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-12 14:21:29 UTC (rev 3573) @@ -60,7 +60,7 @@ throw new IllegalStateException("sizeof not a multiple of alignment"); mo.stride = sizeof; - long addr = MappedObjectUnsafe.getBufferBaseAddress(buffer); + long addr = MappedObjectUnsafe.getBufferBaseAddress(buffer) + buffer.position(); if ( addr % align != 0 ) throw new IllegalStateException("buffer address not aligned on " + align + " bytes"); Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-12 13:44:13 UTC (rev 3572) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-12 14:21:29 UTC (rev 3573) @@ -62,7 +62,7 @@ String vmName = System.getProperty("java.vm.name"); if ( vmName != null && !vmName.contains("Server") ) { - LWJGLUtil.log("Warning: " + MappedObject.class.getSimpleName() + "s have inferiour performance on Client VMs, please consider switching to a Server VM."); + System.err.println("Warning: " + MappedObject.class.getSimpleName() + "s have inferiour performance on Client VMs, please consider switching to a Server VM."); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <riv...@us...> - 2011-07-12 17:50:04
|
Revision: 3575 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3575&view=rev Author: riven-lwjgl Date: 2011-07-12 17:49:58 +0000 (Tue, 12 Jul 2011) Log Message: ----------- Test case showing problems on loading library (64 vs 32 bit) Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java Added: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java 2011-07-12 17:49:58 UTC (rev 3575) @@ -0,0 +1,18 @@ +/* + * Created on Jul 12, 2011 + */ + +package org.lwjgl.test.mapped; + +import java.io.File; + +import org.lwjgl.opengl.Display; + +public class MappedObjectWithLibrary +{ + public static void testLWJGL() throws Exception + { + System.out.println(new File(System.getProperty("java.library.path")).getCanonicalPath()); + Display.create(); + } +} Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-07-12 15:36:16 UTC (rev 3574) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-07-12 17:49:58 UTC (rev 3575) @@ -44,7 +44,7 @@ throw new RuntimeException("Asserts must be enabled for this test."); } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { MappedObjectTransformer.register(MappedFloat.class); MappedObjectTransformer.register(MappedVec2.class); MappedObjectTransformer.register(MappedVec3.class); @@ -70,6 +70,8 @@ MappedObjectTests3.testForeach(); MappedObjectTests3.testConstructor(); MappedObjectTests3.testMappedSet(); + + MappedObjectWithLibrary.testLWJGL(); } } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-12 15:36:16 UTC (rev 3574) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-12 17:49:58 UTC (rev 3575) @@ -50,7 +50,7 @@ */ public class MappedObject { - static final boolean CHECKS = LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.Checks"); + static final boolean CHECKS = false;//LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.Checks"); public MappedObject() { // Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-12 15:36:16 UTC (rev 3574) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-12 17:49:58 UTC (rev 3575) @@ -32,8 +32,8 @@ */ public class MappedObjectTransformer { - static final boolean PRINT_TIMING = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintTiming"); - static final boolean PRINT_ACTIVITY = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintActivity"); + static final boolean PRINT_TIMING = false;//LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintTiming"); + static final boolean PRINT_ACTIVITY = false;//LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintActivity"); static final boolean PRINT_BYTECODE = false; //LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintBytecode"); private static final Map<String, MappedSubtypeInfo> className_to_subtype; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-07-13 22:15:32
|
Revision: 3585 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3585&view=rev Author: spasi Date: 2011-07-13 22:15:25 +0000 (Wed, 13 Jul 2011) Log Message: ----------- Removed stride and .configure. Mapped object view updates are now 50% faster. [Riven] org.lwjgl.util.mapped.PrintBytecode is now functional. [Riven] Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -59,8 +59,8 @@ { MappedFloat vecs1 = MappedFloat.malloc(1234); - assert (vecs1.stride == MappedFloat.SIZEOF); - assert (vecs1.stride * 1234 == vecs1.backingByteBuffer().capacity()); + assert (vecs1.sizeof == MappedFloat.SIZEOF); + assert (vecs1.sizeof * 1234 == vecs1.backingByteBuffer().capacity()); assert (MappedFloat.SIZEOF * 1234 == vecs1.backingByteBuffer().capacity()); } @@ -132,31 +132,6 @@ } } - // test dup - { - int newStride = 16; - int doOffset = 0; - - vecs.view = 0; - MappedFloat.configure(vecs, newStride, doOffset); - MappedFloat dec2 = vecs.dup(); - MappedFloat.configure(dec2, newStride, doOffset); - - String s1 = vecs.baseAddress + "," + vecs.viewAddress + "," + vecs.stride + "," + vecs.SIZEOF; - String s2 = dec2.baseAddress + "," + dec2.viewAddress + "," + dec2.stride + "," + dec2.SIZEOF; - // System.out.println(s1); - // System.out.println(s2); - assert (s1.equals(s2)); - - dec2.view++; - - String s3 = vecs.baseAddress + "," + vecs.viewAddress + "," + vecs.stride + "," + vecs.SIZEOF; - String s4 = dec2.baseAddress + "," + dec2.viewAddress + "," + dec2.stride + "," + dec2.SIZEOF; - // System.out.println(s3); - // System.out.println(s4); - assert (!s3.equals(s4)); - } - // test newBuffer { long addr1 = MappedObjectUnsafe.getBufferBaseAddress(bb); Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -91,40 +91,8 @@ vecs.view = 1; long a2 = vecs.viewAddress; assert (a2 - a1 == MappedVec3.SIZEOF); - assert (a2 - a1 == vecs.stride); + assert (a2 - a1 == vecs.sizeof); vecs.view = 0; } - - int newStride = 16; - - MappedVec3.configure(vecs, newStride, +4); - assert (vecs.z == 0.1234f); // vecs[1].x ended up in vecs[0].z due to 1float offset - - MappedVec3.configure(vecs, newStride, +8); - assert (vecs.z == 0.0000f); // vecs[1].z ended up in vecs[0].z due to 2float offset - - // test new stride - { - long a1 = vecs.viewAddress; - vecs.view = 1; - long a2 = vecs.viewAddress; - assert (a2 - a1 == newStride); - vecs.view = 0; - } - - // example: GPU => VBO => VTN - { - MappedVec3 v = MappedVec3.map(bb); - MappedVec2 t = MappedVec2.map(bb); - MappedVec3 n = MappedVec3.map(bb); - - int stride = MappedVec3.SIZEOF + MappedVec2.SIZEOF + MappedVec3.SIZEOF; - assert (stride == 32); - - MappedVec3.configure(v, stride, 0); - MappedVec2.configure(t, stride, MappedVec3.SIZEOF); - MappedVec3.configure(n, stride, MappedVec3.SIZEOF + MappedVec2.SIZEOF); - } } - } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectWithLibrary.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -4,15 +4,14 @@ package org.lwjgl.test.mapped; +import org.lwjgl.opengl.Display; + import java.io.File; -import org.lwjgl.opengl.Display; +public class MappedObjectWithLibrary { -public class MappedObjectWithLibrary -{ - public static void testLWJGL() throws Exception - { - System.out.println(new File(System.getProperty("java.library.path")).getCanonicalPath()); - Display.create(); - } + public static void testLWJGL() throws Exception { + System.out.println(new File(System.getProperty("java.library.path")).getCanonicalPath()); + Display.create(); + } } Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -35,6 +35,7 @@ import org.lwjgl.util.mapped.MappedObjectTransformer; /** @author Riven */ +@SuppressWarnings("static-access") public class TestMappedObject { static { @@ -49,7 +50,6 @@ MappedObjectTransformer.register(MappedVec2.class); MappedObjectTransformer.register(MappedVec3.class); MappedObjectTransformer.register(MappedSomething.class); - MappedObjectTransformer.register(MappedObjectTests3.Xyz.class); if ( MappedObjectClassLoader.fork(TestMappedObject.class, args) ) { @@ -70,8 +70,8 @@ MappedObjectTests3.testForeach(); MappedObjectTests3.testConstructor(); MappedObjectTests3.testMappedSet(); - - MappedObjectWithLibrary.testLWJGL(); + + System.out.println("done"); } } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -58,7 +58,7 @@ } public T next() { - MappedHelper.put_view(mapped, this.index++); + MappedHelper.put_view(mapped, this.index++, mapped.sizeof); return mapped; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -58,7 +58,7 @@ if ( sizeof % align != 0 ) throw new IllegalStateException("sizeof not a multiple of alignment"); - mo.stride = sizeof; + mo.sizeof = sizeof; long addr = MappedObjectUnsafe.getBufferBaseAddress(buffer) + buffer.position(); if ( addr % align != 0 ) @@ -79,19 +79,19 @@ set.view(view); } - public static void put_view(MappedObject mapped, int view) { - mapped.setViewAddress(mapped.baseAddress + view * mapped.stride); + public static void put_view(MappedObject mapped, int view, int sizeof) { + mapped.setViewAddress(mapped.baseAddress + view * sizeof); } - public static int get_view(MappedObject mapped) { - return (int)(mapped.viewAddress - mapped.baseAddress) / mapped.stride; + public static int get_view(MappedObject mapped, int sizeof) { + return (int)(mapped.viewAddress - mapped.baseAddress) / sizeof; } public static MappedObject dup(MappedObject src, MappedObject dst) { dst.baseAddress = src.baseAddress; dst.viewAddress = src.viewAddress; - dst.stride = src.stride; dst.align = src.align; + dst.sizeof = src.sizeof; dst.preventGC = src.preventGC; return dst; } @@ -99,8 +99,8 @@ public static MappedObject slice(MappedObject src, MappedObject dst) { dst.baseAddress = src.viewAddress; // ! dst.viewAddress = src.viewAddress; - dst.stride = src.stride; dst.align = src.align; + dst.sizeof = src.sizeof; dst.preventGC = src.preventGC; return dst; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -63,12 +63,12 @@ /** The mapped object view memory address, in bytes. Read-only. */ public long viewAddress; - /** The mapped object stride, in bytes. Read-only. */ - public int stride; - /** The mapped object memory alignment, in bytes. Read-only. */ public int align; + /** The mapped object memory sizeof, in bytes. Read-only. */ + public int sizeof; + /** * Holds the value of sizeof of the sub-type of this MappedObject<br> * <br> @@ -88,7 +88,7 @@ /** Moves the current view to the next element. */ public final void next() { - setViewAddress(this.viewAddress + this.stride); + setViewAddress(this.viewAddress + this.sizeof); } final void setViewAddress(final long address) { @@ -99,7 +99,7 @@ final void checkAddress(final long address) { final long base = MappedObjectUnsafe.getBufferBaseAddress(preventGC); - if ( address < base || preventGC.capacity() < (address - base + stride) ) + if ( address < base || preventGC.capacity() < (address - base + this.sizeof) ) throw new IndexOutOfBoundsException(); } @@ -218,32 +218,6 @@ return new MappedForeach<T>(mapped, elementCount); } - /** - * Configures a newly initiated mapped object with the specified stride and offset. - * - * @throws IllegalStateException if view is not at index 0 - */ - public static <T extends MappedObject> T configure(T mapped, int stride, int offset) { - if ( mapped.baseAddress != mapped.viewAddress ) - throw new IllegalStateException("view must be zero"); - - if ( offset < 0 ) - throw new IllegalStateException("offset must not be negative: " + offset); - if ( offset % mapped.align != 0 ) - throw new IllegalStateException("offset not a multiple of alignment: " + offset); - - if ( stride < mapped.stride ) - throw new IllegalStateException("new stride must not be smaller than current stride: " + stride); - if ( stride % mapped.align != 0 ) - throw new IllegalStateException("stride not a multiple of alignment: " + stride); - - mapped.baseAddress += offset; - mapped.viewAddress += offset; - mapped.stride = stride; - - return mapped; - } - ByteBuffer preventGC; /** Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -34,7 +34,7 @@ static final boolean PRINT_TIMING = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintTiming"); static final boolean PRINT_ACTIVITY = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintActivity"); - static final boolean PRINT_BYTECODE = false; //LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintBytecode"); + static final boolean PRINT_BYTECODE = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintBytecode"); static final Map<String, MappedSubtypeInfo> className_to_subtype; @@ -372,6 +372,7 @@ if ( mappedSubtype == null ) { String mappedSetPrefix = jvmClassName(MappedSet.class); + // MappedSet.view outer: if ( "view".equals(fieldName) && className.startsWith(mappedSetPrefix) ) { if ( opcode == GETFIELD ) @@ -418,17 +419,23 @@ if ( opcode == GETFIELD ) { // stack: instance - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "get_view", "(L" + jvmClassName(MappedObject.class) + ";)I"); + pushInt(super.mv, mappedSubtype.sizeof); + // stack: sizeof, instance + super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "get_view", "(L" + jvmClassName(MappedObject.class) + ";I)I"); + // stack: view return; } if ( opcode == PUTFIELD ) { - // stack: int, instance - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_view", "(L" + jvmClassName(MappedObject.class) + ";I)V"); + // stack: view, instance + pushInt(super.mv, mappedSubtype.sizeof); + // stack: sizeof, view, instance + super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_view", "(L" + jvmClassName(MappedObject.class) + ";II)V"); + // stack: - return; } } - if ( "align".equals(fieldName) ) { + if ( "align".equals(fieldName) || "sizeof".equals(fieldName) ) { if ( !"I".equals(typeName) ) throw new IllegalStateException(); @@ -436,7 +443,10 @@ // stack: instance super.visitInsn(POP); // stack: - - pushInt(super.mv, mappedSubtype.align); + if ( "sizeof".equals(fieldName) ) + pushInt(super.mv, mappedSubtype.sizeof); + else if ( "align".equals(fieldName) ) + pushInt(super.mv, mappedSubtype.align); // stack: int return; } @@ -445,18 +455,6 @@ } } - if ( "stride".equals(fieldName) ) { - if ( !"I".equals(typeName) ) - throw new IllegalStateException(); - - if ( opcode == GETFIELD ) { - // do not change a thing - } - if ( opcode == PUTFIELD ) { - throwAccessErrorOnReadOnlyField(className, fieldName); - } - } - if ( "baseAddress".equals(fieldName) || "viewAddress".equals(fieldName) ) { if ( !"J".equals(typeName) ) throw new IllegalStateException(); @@ -476,6 +474,8 @@ return; } + // now we're going to transform ByteBuffer-typed field access + if ( typeName.equals("L" + jvmClassName(ByteBuffer.class) + ";") ) { if ( opcode == PUTFIELD ) { throwAccessErrorOnReadOnlyField(className, fieldName); @@ -500,30 +500,34 @@ } } + // we're now going to transform the field access + if ( opcode == PUTFIELD ) { // stack: value, ref super.visitInsn(SWAP); // stack: ref, value super.visitFieldInsn(GETFIELD, mappedSubtype.className, "viewAddress", "J"); - // stack: long, value + // stack: viewAddr, value super.visitLdcInsn(fieldOffset); - // stack: long, long, value + // stack: offset, viewAddr, value super.visitInsn(LADD); - // stack: long, value + // stack: fieldAddr, value super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), typeName.toLowerCase() + "put", "(" + typeName + "J)V"); // stack - + return; } if ( opcode == GETFIELD ) { // stack: ref super.visitFieldInsn(GETFIELD, mappedSubtype.className, "viewAddress", "J"); - // stack: long + // stack: viewAddr super.visitLdcInsn(fieldOffset); - // stack: long, long + // stack: fieldOffset, viewAddr super.visitInsn(LADD); - // stack: long + // stack: fieldAddr super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), typeName.toLowerCase() + "get", "(J)" + typeName); // stack: value + return; } @@ -553,7 +557,7 @@ else if ( value >= Short.MIN_VALUE && value <= Short.MAX_VALUE ) mv.visitIntInsn(SIPUSH, value); else - mv.visitLdcInsn(Integer.valueOf(value)); + mv.visitLdcInsn(value); } static String jvmClassName(Class<?> type) { Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -44,8 +44,8 @@ public int view; void view(int view) { - MappedHelper.put_view(this.a, view); - MappedHelper.put_view(this.b, view); + MappedHelper.put_view(this.a, view, this.a.sizeof); + MappedHelper.put_view(this.b, view, this.b.sizeof); } public void next() { Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -45,9 +45,9 @@ public int view; void view(int view) { - MappedHelper.put_view(this.a, view); - MappedHelper.put_view(this.b, view); - MappedHelper.put_view(this.c, view); + MappedHelper.put_view(this.a, view, this.a.sizeof); + MappedHelper.put_view(this.b, view, this.b.sizeof); + MappedHelper.put_view(this.c, view, this.c.sizeof); } public void next() { Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java 2011-07-13 19:29:15 UTC (rev 3584) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java 2011-07-13 22:15:25 UTC (rev 3585) @@ -46,10 +46,10 @@ public int view; void view(int view) { - MappedHelper.put_view(this.a, view); - MappedHelper.put_view(this.b, view); - MappedHelper.put_view(this.c, view); - MappedHelper.put_view(this.d, view); + MappedHelper.put_view(this.a, view, this.a.sizeof); + MappedHelper.put_view(this.b, view, this.b.sizeof); + MappedHelper.put_view(this.c, view, this.c.sizeof); + MappedHelper.put_view(this.d, view, this.d.sizeof); } public void next() { @@ -58,5 +58,4 @@ this.c.next(); this.d.next(); } - } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-07-14 16:54:32
|
Revision: 3587 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3587&view=rev Author: spasi Date: 2011-07-14 16:54:25 +0000 (Thu, 14 Jul 2011) Log Message: ----------- Implemented .next() with bytecode transformation, 4x faster now. Made method transformation a bit faster. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-13 22:15:35 UTC (rev 3586) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-14 16:54:25 UTC (rev 3587) @@ -89,6 +89,15 @@ vecs.view = 0; } + // manipulate 'view' with next() + { + assert (vecs.view == 0); + vecs.next(); + assert (vecs.view == 1); + assert (vecs.value != 1.1f); // old view + vecs.view = 0; + } + // test bounds checking { assert (vecs.view == 0); Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-13 22:15:35 UTC (rev 3586) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-14 16:54:25 UTC (rev 3587) @@ -87,6 +87,10 @@ return (int)(mapped.viewAddress - mapped.baseAddress) / sizeof; } + public static void put_view_next(MappedObject mapped, int sizeof) { + mapped.setViewAddress(mapped.viewAddress + sizeof); + } + public static MappedObject dup(MappedObject src, MappedObject dst) { dst.baseAddress = src.baseAddress; dst.viewAddress = src.viewAddress; Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-13 22:15:35 UTC (rev 3586) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-14 16:54:25 UTC (rev 3587) @@ -86,12 +86,7 @@ */ public int view; - /** Moves the current view to the next element. */ - public final void next() { - setViewAddress(this.viewAddress + this.sizeof); - } - - final void setViewAddress(final long address) { + public final void setViewAddress(final long address) { if ( CHECKS ) checkAddress(address); this.viewAddress = address; @@ -99,8 +94,9 @@ final void checkAddress(final long address) { final long base = MappedObjectUnsafe.getBufferBaseAddress(preventGC); - if ( address < base || preventGC.capacity() < (address - base + this.sizeof) ) - throw new IndexOutOfBoundsException(); + final int offset = (int)(address - base); + if ( address < base || preventGC.capacity() < (offset + this.sizeof) ) + throw new IndexOutOfBoundsException(Integer.toString(offset / sizeof)); } final void checkRange(final int bytes) { @@ -186,6 +182,12 @@ throw new InternalError("type not registered"); } + /** Moves the current view to the next element. */ + public final void next() { + // any method that calls this method will have its call-site modified + throw new InternalError("type not registered"); + } + /** * Copies and amount of <code>SIZEOF</code> bytes, from the current * mapped object, to the specified mapped object. Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-13 22:15:35 UTC (rev 3586) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-14 16:54:25 UTC (rev 3587) @@ -38,6 +38,9 @@ static final Map<String, MappedSubtypeInfo> className_to_subtype; + static final String MAPPED_OBJECT_JVM = jvmClassName(MappedObject.class); + static final String MAPPED_HELPER_JVM = jvmClassName(MappedHelper.class); + static { className_to_subtype = new HashMap<String, MappedSubtypeInfo>(); @@ -56,7 +59,7 @@ // => IADD // => PUTFIELD MyMappedType.view // - MappedSubtypeInfo info = new MappedSubtypeInfo(jvmClassName(MappedObject.class), -1, -1); + MappedSubtypeInfo info = new MappedSubtypeInfo(MAPPED_OBJECT_JVM, -1, -1); className_to_subtype.put(info.className, info); } @@ -162,7 +165,7 @@ { MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className); - if ( mappedSubtype != null && !mappedSubtype.className.equals(jvmClassName(MappedObject.class)) ) { + if ( mappedSubtype != null && !mappedSubtype.className.equals(MAPPED_OBJECT_JVM) ) { if ( "<init>".equals(name) ) { if ( !"()V".equals(desc) ) throw new IllegalStateException(className + " can only have a default constructor, found: " + desc); @@ -170,7 +173,7 @@ MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, jvmClassName(MappedObject.class), "<init>", "()V"); + mv.visitMethodInsn(INVOKESPECIAL, MAPPED_OBJECT_JVM, "<init>", "()V"); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); @@ -181,7 +184,7 @@ } } - return new MappedInstanceMethodAdapter(className, name, desc, super.visitMethod(access, name, desc, signature, exceptions)); + return new MappedInstanceMethodAdapter(access, className, name, desc, super.visitMethod(access, name, desc, signature, exceptions)); } @Override @@ -252,18 +255,26 @@ @Override public void visitMethodInsn(int opcode, String className, String methodName, String signature) { - if ( opcode == INVOKESPECIAL && className.equals(jvmClassName(MappedObject.class)) && "<init>".equals(methodName) && "()V".equals(signature) ) { + if ( opcode == INVOKESPECIAL && className.equals(MAPPED_OBJECT_JVM) && "<init>".equals(methodName) && "()V".equals(signature) ) { // stack: instance visitInsn(POP); // stack: - return; } - for ( MappedSubtypeInfo mappedType : className_to_subtype.values() ) { - boolean isMapDirectMethod = (opcode == INVOKESTATIC && "map".equals(methodName) && className.equals(mappedType.className) && signature.equals("(JI)L" + jvmClassName(MappedObject.class) + ";")); - boolean isMapBufferMethod = (opcode == INVOKESTATIC && "map".equals(methodName) && className.equals(mappedType.className) && signature.equals("(Ljava/nio/ByteBuffer;)L" + jvmClassName(MappedObject.class) + ";")); - boolean isMallocMethod = (opcode == INVOKESTATIC && "malloc".equals(methodName) && className.equals(mappedType.className) && signature.equals("(I)L" + jvmClassName(MappedObject.class) + ";")); + MappedSubtypeInfo mappedType = className_to_subtype.get(className); + if ( mappedType != null && visitMappedMethod(opcode, className, methodName, signature, mappedType) ) + return; + super.visitMethodInsn(opcode, className, methodName, signature); + } + + private boolean visitMappedMethod(final int opcode, final String className, final String methodName, final String signature, final MappedSubtypeInfo mappedType) { + if ( opcode == INVOKESTATIC ) { + boolean isMapDirectMethod = "map".equals(methodName) && signature.equals("(JI)L" + MAPPED_OBJECT_JVM + ";"); + boolean isMapBufferMethod = "map".equals(methodName) && signature.equals("(Ljava/nio/ByteBuffer;)L" + MAPPED_OBJECT_JVM + ";"); + boolean isMallocMethod = "malloc".equals(methodName) && signature.equals("(I)L" + MAPPED_OBJECT_JVM + ";"); + if ( (isMapDirectMethod || isMapBufferMethod) || isMallocMethod ) { if ( isMallocMethod ) { // stack: count @@ -275,7 +286,7 @@ // stack: buffer } else if ( isMapDirectMethod ) { // stack: capacity, address - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";"); // stack: buffer } @@ -294,12 +305,12 @@ // stack: int, buffer, new, new pushInt(super.mv, mappedType.sizeof); // stack: int, int, buffer, new, new - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "setup", "(L" + jvmClassName(MappedObject.class) + ";Ljava/nio/ByteBuffer;II)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "setup", "(L" + MAPPED_OBJECT_JVM + ";Ljava/nio/ByteBuffer;II)V"); // stack: new - return; + return true; } - - if ( opcode == INVOKEVIRTUAL && "dup".equals(methodName) && className.equals(mappedType.className) && signature.equals("()L" + jvmClassName(MappedObject.class) + ";") ) { + } else if ( opcode == INVOKEVIRTUAL ) { + if ( "dup".equals(methodName) && signature.equals("()L" + MAPPED_OBJECT_JVM + ";") ) { // stack: this super.visitTypeInsn(NEW, className); // stack: new, this @@ -307,12 +318,12 @@ // stack: new, new, this super.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V"); // stack: new, this - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "dup", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";)L" + jvmClassName(MappedObject.class) + ";"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "dup", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";)L" + MAPPED_OBJECT_JVM + ";"); // stack: new - return; + return true; } - if ( opcode == INVOKEVIRTUAL && "slice".equals(methodName) && className.equals(mappedType.className) && signature.equals("()L" + jvmClassName(MappedObject.class) + ";") ) { + if ( "slice".equals(methodName) && signature.equals("()L" + MAPPED_OBJECT_JVM + ";") ) { // stack: this super.visitTypeInsn(NEW, className); // stack: new, this @@ -320,46 +331,55 @@ // stack: new, new, this super.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V"); // stack: new, this - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "slice", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";)L" + jvmClassName(MappedObject.class) + ";"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "slice", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";)L" + MAPPED_OBJECT_JVM + ";"); // stack: new - return; + return true; } // - if ( opcode == INVOKEVIRTUAL && "runViewConstructor".equals(methodName) && className.equals(mappedType.className) && "()V".equals(signature) ) { + if ( "runViewConstructor".equals(methodName) && "()V".equals(signature) ) { // stack: this super.visitInsn(DUP); // stack: this, this super.visitMethodInsn(INVOKEVIRTUAL, className, view_constructor_method, "()V"); // stack: this - return; + return true; } // - if ( opcode == INVOKEVIRTUAL && "copyTo".equals(methodName) && className.equals(mappedType.className) && signature.equals("(L" + jvmClassName(MappedObject.class) + ";)V") ) { + if ( "copyTo".equals(methodName) && signature.equals("(L" + MAPPED_OBJECT_JVM + ";)V") ) { // stack: target, this pushInt(super.mv, mappedType.sizeof); // stack: sizeof, target, this - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "copy", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";I)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "copy", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";I)V"); // stack: - - return; + return true; } - if ( opcode == INVOKEVIRTUAL && "copyRange".equals(methodName) && className.equals(mappedType.className) && signature.equals("(L" + jvmClassName(MappedObject.class) + ";I)V") ) { + if ( "copyRange".equals(methodName) && signature.equals("(L" + MAPPED_OBJECT_JVM + ";I)V") ) { // stack: instances, target, this pushInt(super.mv, mappedType.sizeof); // stack: sizeof, instances, target, this super.visitInsn(IMUL); // stack: bytes, target, this - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "copy", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";I)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "copy", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";I)V"); // stack: - - return; + return true; } + + if ( "next".equals(methodName) && "()V".equals(signature) ) { + // stack: this + pushInt(super.mv, mappedType.sizeof); + // stack: sizeof, this + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_view_next", "(L" + MAPPED_OBJECT_JVM + ";I)V"); + // stack: - + return true; + } } - super.visitMethodInsn(opcode, className, methodName, signature); + return false; } private static void throwAccessErrorOnReadOnlyField(String className, String fieldName) { @@ -384,11 +404,11 @@ if ( false ) break outer; else if ( className.equals(jvmClassName(MappedSet2.class)) ) - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_views", "(L" + jvmClassName(MappedSet2.class) + ";I)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_views", "(L" + jvmClassName(MappedSet2.class) + ";I)V"); else if ( className.equals(jvmClassName(MappedSet3.class)) ) - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_views", "(L" + jvmClassName(MappedSet3.class) + ";I)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_views", "(L" + jvmClassName(MappedSet3.class) + ";I)V"); else if ( className.equals(jvmClassName(MappedSet4.class)) ) - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_views", "(L" + jvmClassName(MappedSet4.class) + ";I)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_views", "(L" + jvmClassName(MappedSet4.class) + ";I)V"); else break outer; // stack: - @@ -421,7 +441,7 @@ // stack: instance pushInt(super.mv, mappedSubtype.sizeof); // stack: sizeof, instance - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "get_view", "(L" + jvmClassName(MappedObject.class) + ";I)I"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "get_view", "(L" + MAPPED_OBJECT_JVM + ";I)I"); // stack: view return; } @@ -429,7 +449,7 @@ // stack: view, instance pushInt(super.mv, mappedSubtype.sizeof); // stack: sizeof, view, instance - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_view", "(L" + jvmClassName(MappedObject.class) + ";II)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_view", "(L" + MAPPED_OBJECT_JVM + ";II)V"); // stack: - return; } @@ -494,7 +514,7 @@ // stack: long, long super.visitInsn(L2I); // stack: int, long - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";"); // stack: buffer return; } @@ -512,7 +532,7 @@ // stack: offset, viewAddr, value super.visitInsn(LADD); // stack: fieldAddr, value - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), typeName.toLowerCase() + "put", "(" + typeName + "J)V"); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, typeName.toLowerCase() + "put", "(" + typeName + "J)V"); // stack - return; @@ -525,7 +545,7 @@ // stack: fieldOffset, viewAddr super.visitInsn(LADD); // stack: fieldAddr - super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), typeName.toLowerCase() + "get", "(J)" + typeName); + super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, typeName.toLowerCase() + "get", "(J)" + typeName); // stack: value return; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-07-22 20:09:08
|
Revision: 3598 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3598&view=rev Author: spasi Date: 2011-07-22 20:09:01 +0000 (Fri, 22 Jul 2011) Log Message: ----------- Converted sizeof and align to methods. Override more methods in MappedObject subclasses, foreach is now 4 times faster. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -60,8 +60,8 @@ { MappedFloat vecs1 = MappedFloat.malloc(1234); - assert (vecs1.sizeof == MappedFloat.SIZEOF); - assert (vecs1.sizeof * 1234 == vecs1.backingByteBuffer().capacity()); + assert (vecs1.getSizeof() == MappedFloat.SIZEOF); + assert (vecs1.getSizeof() * 1234 == vecs1.backingByteBuffer().capacity()); assert (MappedFloat.SIZEOF * 1234 == vecs1.backingByteBuffer().capacity()); } Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests2.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -44,7 +44,7 @@ System.out.println(vecs.viewAddress); // test read-access - System.out.println(vecs.align); // test read-access + System.out.println(vecs.getAlign()); // test read-access System.out.println(MappedVec3.SIZEOF); // test read-access } @@ -91,7 +91,7 @@ vecs.view = 1; long a2 = vecs.viewAddress; assert (a2 - a1 == MappedVec3.SIZEOF); - assert (a2 - a1 == vecs.sizeof); + assert (a2 - a1 == vecs.getSizeof()); vecs.view = 0; } } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedForeach.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -58,7 +58,7 @@ } public T next() { - MappedHelper.put_view(mapped, this.index++, mapped.sizeof); + mapped.setViewAddress(mapped.getViewAddress(this.index++)); return mapped; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -55,11 +55,9 @@ if ( LWJGLUtil.CHECKS && align <= 0 ) throw new IllegalArgumentException("invalid alignment"); - mo.align = align; if ( LWJGLUtil.CHECKS && (sizeof <= 0 || sizeof % align != 0) ) throw new IllegalStateException("sizeof not a multiple of alignment"); - mo.sizeof = sizeof; long addr = MemoryUtil.getAddress(buffer); if ( LWJGLUtil.CHECKS && addr % align != 0 ) @@ -107,8 +105,6 @@ public static MappedObject dup(MappedObject src, MappedObject dst) { dst.baseAddress = src.baseAddress; dst.viewAddress = src.viewAddress; - dst.align = src.align; - dst.sizeof = src.sizeof; dst.preventGC = src.preventGC; return dst; } @@ -116,8 +112,6 @@ public static MappedObject slice(MappedObject src, MappedObject dst) { dst.baseAddress = src.viewAddress; // ! dst.viewAddress = src.viewAddress; - dst.align = src.align; - dst.sizeof = src.sizeof; dst.preventGC = src.preventGC; return dst; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -50,11 +50,11 @@ * * @author Riven */ -public class MappedObject { +public abstract class MappedObject { static final boolean CHECKS = LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.Checks"); - public MappedObject() { + protected MappedObject() { // } @@ -64,12 +64,9 @@ /** The mapped object view memory address, in bytes. Read-only. */ public long viewAddress; - /** The mapped object memory alignment, in bytes. Read-only. */ - public int align; + /** The mapped buffer. */ + ByteBuffer preventGC; - /** The mapped object memory sizeof, in bytes. Read-only. */ - public int sizeof; - /** * Holds the value of sizeof of the sub-type of this MappedObject<br> * <br> @@ -87,6 +84,12 @@ */ public int view; + protected final long getViewAddress(final int view) { + // No call-site modification for this, we override in every subclass instead, + // so that we can use it in MappedForeach. + throw new InternalError("type not registered"); + } + public final void setViewAddress(final long address) { if ( CHECKS ) checkAddress(address); @@ -96,8 +99,8 @@ final void checkAddress(final long address) { final long base = MemoryUtil.getAddress0(preventGC); final int offset = (int)(address - base); - if ( address < base || preventGC.capacity() < (offset + this.sizeof) ) - throw new IndexOutOfBoundsException(Integer.toString(offset / sizeof)); + if ( address < base || preventGC.capacity() < (offset + getSizeof()) ) + throw new IndexOutOfBoundsException(Integer.toString(offset / getSizeof())); } final void checkRange(final int bytes) { @@ -108,7 +111,28 @@ throw new BufferOverflowException(); } + /** The mapped object memory alignment, in bytes. Read-only. */ /** + * Returns the mapped object memory alignment, in bytes. + * + * @return the memory alignment + */ + public final int getAlign() { + // No call-site modification for this, we override in every subclass instead. + throw new InternalError("type not registered"); + } + + /** + * Returns the mapped object memory sizeof, in bytes. + * + * @return the sizeof value + */ + public final int getSizeof() { + // No call-site modification for this, we override in every subclass instead. + throw new InternalError("type not registered"); + } + + /** * Creates a MappedObject instance, mapping the memory region of the specified direct ByteBuffer. * <p/> * The behavior of this (transformed) method does not follow the normal Java behavior.<br> @@ -178,22 +202,18 @@ * Any code in the default constructor will not run automatically. This method * can be used to run execute that code on the current view. */ - public final <T extends MappedObject> void runViewConstructor() { + public final void runViewConstructor() { // any method that calls this method will have its call-site modified throw new InternalError("type not registered"); } /** Moves the current view to the next element. */ public final void next() { - // any method that calls this method will have its call-site modified + // No call-site modification for this, we override in every subclass instead, + // so that we can use it in MappedSetX. throw new InternalError("type not registered"); } - /** Moves the current view to the next element. Non-transformed implementation for MappedSets. */ - final void nextSet() { - setViewAddress(viewAddress + sizeof); - } - /** * Copies and amount of <code>SIZEOF</code> bytes, from the current * mapped object, to the specified mapped object. @@ -232,14 +252,12 @@ throw new InternalError("type not registered"); } - ByteBuffer preventGC; - /** * Returns the {@link java.nio.ByteBuffer} that backs this mapped object. * * @return the backing buffer */ - public ByteBuffer backingByteBuffer() { + public final ByteBuffer backingByteBuffer() { return this.preventGC; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -73,7 +73,9 @@ FORKED = true; try { - URLClassLoader loader = new MappedObjectClassLoader(mainClass); + MappedObjectClassLoader loader = new MappedObjectClassLoader(mainClass); + loader.loadMappedObject(); + Class<?> replacedMainClass = loader.loadClass(mainClass.getName()); Method mainMethod = replacedMainClass.getMethod("main", String[].class); mainMethod.invoke(null, new Object[] { args }); @@ -90,6 +92,28 @@ super(((URLClassLoader)mainClass.getClassLoader()).getURLs()); } + protected synchronized Class<?> loadMappedObject() throws ClassNotFoundException { + final String name = MappedObject.class.getName(); + String className = name.replace('.', '/'); + + if ( MappedObjectTransformer.PRINT_ACTIVITY ) + LWJGLUtil.log(MappedObjectClassLoader.class.getSimpleName() + ": " + className); + + byte[] bytecode = readStream(this.getResourceAsStream(className.concat(".class"))); + + long t0 = System.nanoTime(); + bytecode = MappedObjectTransformer.transformMappedObject(bytecode); + long t1 = System.nanoTime(); + total_time_transforming += (t1 - t0); + + if ( MappedObjectTransformer.PRINT_TIMING ) + LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)"); + + Class<?> clazz = super.defineClass(name, bytecode, 0, bytecode.length); + resolveClass(clazz); + return clazz; + } + private static long total_time_transforming; @Override @@ -104,10 +128,8 @@ if ( name.startsWith("sunw.") ) return super.loadClass(name, resolve); - // never transform classes in this very package, sub-packages should be transformed - if ( name.startsWith(MAPPEDOBJECT_PACKAGE_PREFIX) ) - if ( name.substring(MAPPEDOBJECT_PACKAGE_PREFIX.length()).indexOf('.') == -1 ) - return super.loadClass(name, resolve); + if ( name.equals(MappedObjectClassLoader.class.getName()) ) + return super.loadClass(name, resolve); String className = name.replace('.', '/'); @@ -116,13 +138,16 @@ byte[] bytecode = readStream(this.getResourceAsStream(className.concat(".class"))); - long t0 = System.nanoTime(); - bytecode = MappedObjectTransformer.transformMappedAPI(className, bytecode); - long t1 = System.nanoTime(); - total_time_transforming += (t1 - t0); + // Classes in this package do not get transformed, but need to go through here because we have transformed MappedObject. + if ( !(name.startsWith(MAPPEDOBJECT_PACKAGE_PREFIX) && name.substring(MAPPEDOBJECT_PACKAGE_PREFIX.length()).indexOf('.') == -1) ) { + long t0 = System.nanoTime(); + bytecode = MappedObjectTransformer.transformMappedAPI(className, bytecode); + long t1 = System.nanoTime(); - if ( MappedObjectTransformer.PRINT_TIMING ) - LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)"); + total_time_transforming += (t1 - t0); + if ( MappedObjectTransformer.PRINT_TIMING ) + LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)"); + } Class<?> clazz = super.defineClass(name, bytecode, 0, bytecode.length); if ( resolve ) Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -35,6 +35,7 @@ import org.objectweb.asm.*; import org.objectweb.asm.tree.*; import org.objectweb.asm.tree.analysis.*; +import org.objectweb.asm.tree.analysis.Frame; import org.objectweb.asm.util.TraceClassVisitor; import java.io.PrintWriter; @@ -76,10 +77,16 @@ static final String MAPPED_SET3_JVM = jvmClassName(MappedSet3.class); static final String MAPPED_SET4_JVM = jvmClassName(MappedSet4.class); - static final String LENGTH_METHOD_NAME = "length$LWJGL"; - static final String VIEWADDRESS_METHOD_NAME = "getViewAddress$LWJGL"; - static final String VIEW_CONSTRUCTOR_NAME = "constructView$LWJGL"; + // Public methods + static final String VIEWADDRESS_METHOD_NAME = "getViewAddress"; + static final String NEXT_METHOD_NAME = "next"; + static final String ALIGN_METHOD_NAME = "getAlign"; + static final String SIZEOF_METHOD_NAME = "getSizeof"; + // Internal methods + static final String LENGTH_METHOD_NAME = "length$LWJGL"; // Used for .asArray().length + static final String VIEW_CONSTRUCTOR_NAME = "constructView$LWJGL"; // Used by runViewConstructor + static final Map<Integer, String> OPCODE_TO_NAME = new HashMap<Integer, String>(); static final Map<Integer, String> INSNTYPE_TO_NAME = new HashMap<Integer, String>(); @@ -122,9 +129,6 @@ * @param type the mapped object class. */ public static void register(Class<?> type) { - if ( MappedObjectClassLoader.FORKED ) - return; - final MappedType mapped = type.getAnnotation(MappedType.class); if ( mapped == null ) throw new InternalError("missing " + MappedType.class.getName() + " annotation"); @@ -185,6 +189,34 @@ return (int)byteLength; } + /** Removes final from methods that will be overriden by subclasses. */ + static byte[] transformMappedObject(byte[] bytecode) { + final ClassWriter cw = new ClassWriter(0); + + ClassVisitor cv = new ClassAdapter(cw) { + + private final String[] DEFINALIZE_LIST = { + VIEWADDRESS_METHOD_NAME, + NEXT_METHOD_NAME, + ALIGN_METHOD_NAME, + SIZEOF_METHOD_NAME, + }; + + public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature, final String[] exceptions) { + for ( String method : DEFINALIZE_LIST ) { + if ( name.equals(method) ) { + access &= ~ACC_FINAL; + break; + } + } + return super.visitMethod(access, name, desc, signature, exceptions); + } + }; + + new ClassReader(bytecode).accept(cv, 0); + return cw.toByteArray(); + } + static byte[] transformMappedAPI(final String className, byte[] bytecode) { final ClassWriter cw = new ClassWriter(COMPUTE_FRAMES) { @@ -203,8 +235,7 @@ if ( className_to_subtype.containsKey(className) ) // Do a first pass to generate address getters cv = getMethodGenAdapter(className, cv); - //cr.accept(cv, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - new ClassReader(bytecode).accept(cv, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + new ClassReader(bytecode).accept(cv, ClassReader.SKIP_FRAMES); bytecode = cw.toByteArray(); if ( PRINT_BYTECODE ) @@ -218,11 +249,14 @@ @Override public void visitEnd() { + final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className); + generateViewAddressGetter(); generateLengthGetter(); + generateAlignGetter(mappedSubtype); + generateSizeofGetter(); + generateNext(); - final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className); - for ( String fieldName : mappedSubtype.fieldToOffset.keySet() ) { final Type type = mappedSubtype.fieldToType.get(fieldName); @@ -238,7 +272,7 @@ } private void generateViewAddressGetter() { - MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J", null, null); + MethodVisitor mv = super.visitMethod(ACC_PUBLIC, VIEWADDRESS_METHOD_NAME, "(I)J", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, MAPPED_OBJECT_JVM, "baseAddress", "J"); @@ -266,7 +300,7 @@ MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, LENGTH_METHOD_NAME, "(L" + className + ";)I", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKEVIRTUAL, className, "backingByteBuffer", "()L" + jvmClassName(ByteBuffer.class) + ";"); + mv.visitMethodInsn(INVOKEVIRTUAL, MAPPED_OBJECT_JVM, "backingByteBuffer", "()L" + jvmClassName(ByteBuffer.class) + ";"); mv.visitMethodInsn(INVOKEVIRTUAL, jvmClassName(ByteBuffer.class), "capacity", "()I"); mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I"); mv.visitInsn(IDIV); @@ -275,12 +309,45 @@ mv.visitEnd(); } + private void generateAlignGetter(final MappedSubtypeInfo mappedSubtype) { + MethodVisitor mv = super.visitMethod(ACC_PUBLIC, ALIGN_METHOD_NAME, "()I", null, null); + mv.visitCode(); + visitIntNode(mv, mappedSubtype.sizeof); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + private void generateSizeofGetter() { + MethodVisitor mv = super.visitMethod(ACC_PUBLIC, SIZEOF_METHOD_NAME, "()I", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I"); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + private void generateNext() { + MethodVisitor mv = super.visitMethod(ACC_PUBLIC, NEXT_METHOD_NAME, "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(DUP); + mv.visitFieldInsn(GETFIELD, MAPPED_OBJECT_JVM, "viewAddress", "J"); + mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I"); + mv.visitInsn(I2L); + mv.visitInsn(LADD); + mv.visitMethodInsn(INVOKEVIRTUAL, className, "setViewAddress", "(J)V"); + mv.visitInsn(RETURN); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + private void generateByteBufferGetter(final MappedSubtypeInfo mappedSubtype, final String fieldName, final Type type) { MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, getterName(fieldName), "(L" + className + ";I)" + type.getDescriptor(), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 1); - mv.visitMethodInsn(INVOKESTATIC, className, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J"); + mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J"); visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue()); mv.visitInsn(I2L); mv.visitInsn(LADD); @@ -296,13 +363,13 @@ mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 1); - mv.visitMethodInsn(INVOKESTATIC, className, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J"); + mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J"); visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue()); mv.visitInsn(I2L); mv.visitInsn(LADD); mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, type.getDescriptor().toLowerCase() + "get", "(J)" + type.getDescriptor()); mv.visitInsn(type.getOpcode(IRETURN)); - mv.visitMaxs(2, 2); + mv.visitMaxs(3, 2); mv.visitEnd(); } @@ -331,13 +398,13 @@ mv.visitVarInsn(load, 2); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 1); - mv.visitMethodInsn(INVOKESTATIC, className, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J"); + mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J"); visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue()); mv.visitInsn(I2L); mv.visitInsn(LADD); mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, type.getDescriptor().toLowerCase() + "put", "(" + type.getDescriptor() + "J)V"); mv.visitInsn(RETURN); - mv.visitMaxs(3, 3); + mv.visitMaxs(4, 3); mv.visitEnd(); } @@ -415,12 +482,14 @@ @Override public void visitEnd() { - if ( needsTransformation ) // Early-out for methods that do not touch a mapped object. + if ( needsTransformation ) { // Early-out for methods that do not touch a mapped object. + //System.err.println("\nTRANSFORMING: " + className + "." + name + desc); try { transformMethod(analyse()); } catch (Exception e) { throw new RuntimeException(e); } + } // Pass the instruction stream to the adapter's MethodVisitor accept(mv); @@ -433,8 +502,6 @@ } private void transformMethod(final Frame<BasicValue>[] frames) { - //System.err.println("\nTRANSFORMING: " + className + " - " + name + desc); - final InsnList instructions = this.instructions; final Map<Integer, MappedSubtypeInfo> arrayVars = new HashMap<Integer, MappedSubtypeInfo>(); @@ -540,10 +607,6 @@ break; } - if ( "next".equals(methodInsn.name) && "()V".equals(methodInsn.desc) ) { - i = replace(instructions, i, methodInsn, generateNextInstructions(mappedType)); - break; - } break; case INVOKESPECIAL: // super() in VIEW_CONSTRUCTOR_NAME, remove @@ -567,18 +630,6 @@ return i; } - private static InsnList generateNextInstructions(final MappedSubtypeInfo mappedType) { - final InsnList list = new InsnList(); - - // stack: this - list.add(getIntNode(mappedType.sizeof)); - // stack: sizeof, this - list.add(new MethodInsnNode(INVOKESTATIC, MAPPED_HELPER_JVM, "put_view_next", "(L" + MAPPED_OBJECT_JVM + ";I)V")); - // stack: - - - return list; - } - private static InsnList generateCopyRangeInstructions(final MappedSubtypeInfo mappedType) { final InsnList list = new InsnList(); @@ -705,9 +756,6 @@ if ( "view".equals(fieldInsn.name) ) return generateViewInstructions(fieldInsn, mappedSubtype); - if ( "align".equals(fieldInsn.name) || "sizeof".equals(fieldInsn.name) ) - return generateAlignSizeofInstructions(fieldInsn, mappedSubtype); - if ( "baseAddress".equals(fieldInsn.name) || "viewAddress".equals(fieldInsn.name) ) { return generateAddressInstructions(fieldInsn); } @@ -806,29 +854,6 @@ throw new InternalError(); } - private static InsnList generateAlignSizeofInstructions(final FieldInsnNode fieldInsn, final MappedSubtypeInfo mappedSubtype) { - if ( !"I".equals(fieldInsn.desc) ) - throw new InternalError(); - - if ( fieldInsn.getOpcode() == GETFIELD ) { - final InsnList list = new InsnList(); - - // stack: instance - list.add(new InsnNode(POP)); - // stack: - - if ( "sizeof".equals(fieldInsn.name) ) - list.add(getIntNode(mappedSubtype.sizeof)); - else if ( "align".equals(fieldInsn.name) ) - list.add(getIntNode(mappedSubtype.align)); - // stack: int - return list; - } - - if ( fieldInsn.getOpcode() == PUTFIELD ) - throwAccessErrorOnReadOnlyField(fieldInsn.owner, fieldInsn.name); - throw new InternalError(); - } - private static InsnList generateAddressInstructions(final FieldInsnNode fieldInsn) { if ( !"J".equals(fieldInsn.desc) ) throw new IllegalStateException(); @@ -961,7 +986,7 @@ nextInsn = getter; continue; } else if ( stackSize < loadStackSize ) - throw new ClassFormatError("Invalid .asArray() usage detected: " + getOpcodeName(nextInsn)); + throw new ClassFormatError("Invalid " + mappedSubtype.className + " view array usage detected: " + getOpcodeName(nextInsn)); } instructions.remove(aaLoadInsn); Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet2.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -44,13 +44,13 @@ public int view; void view(int view) { - MappedHelper.put_view(this.a, view, this.a.sizeof); - MappedHelper.put_view(this.b, view, this.b.sizeof); + a.setViewAddress(a.getViewAddress(view)); + b.setViewAddress(b.getViewAddress(view)); } public void next() { - this.a.nextSet(); - this.b.nextSet(); + this.a.next(); + this.b.next(); } } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet3.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -45,15 +45,15 @@ public int view; void view(int view) { - MappedHelper.put_view(this.a, view, this.a.sizeof); - MappedHelper.put_view(this.b, view, this.b.sizeof); - MappedHelper.put_view(this.c, view, this.c.sizeof); + a.setViewAddress(a.getViewAddress(view)); + b.setViewAddress(b.getViewAddress(view)); + c.setViewAddress(c.getViewAddress(view)); } public void next() { - this.a.nextSet(); - this.b.nextSet(); - this.c.nextSet(); + this.a.next(); + this.b.next(); + this.c.next(); } } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java 2011-07-22 02:01:56 UTC (rev 3597) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedSet4.java 2011-07-22 20:09:01 UTC (rev 3598) @@ -46,16 +46,16 @@ public int view; void view(int view) { - MappedHelper.put_view(this.a, view, this.a.sizeof); - MappedHelper.put_view(this.b, view, this.b.sizeof); - MappedHelper.put_view(this.c, view, this.c.sizeof); - MappedHelper.put_view(this.d, view, this.d.sizeof); + a.setViewAddress(a.getViewAddress(view)); + b.setViewAddress(b.getViewAddress(view)); + c.setViewAddress(c.getViewAddress(view)); + d.setViewAddress(d.getViewAddress(view)); } public void next() { - this.a.nextSet(); - this.b.nextSet(); - this.c.nextSet(); - this.d.nextSet(); + this.a.next(); + this.b.next(); + this.c.next(); + this.d.next(); } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-07-23 22:02:08
|
Revision: 3599 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3599&view=rev Author: spasi Date: 2011-07-23 22:02:01 +0000 (Sat, 23 Jul 2011) Log Message: ----------- Removed sizeof from @MappedType, it's calculated automatically now. Added padding to @MappedType, defaults to 0. Added support for @Pointer long fields for easier interaction with pointer data. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java Modified: trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -462,7 +462,7 @@ * * @param msg Message to print */ - public static void log(String msg) { + public static void log(CharSequence msg) { if (DEBUG) { System.err.println("[LWJGL] " + msg); } Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -35,7 +35,7 @@ import org.lwjgl.util.mapped.MappedType; /** @author Riven */ -@MappedType(sizeof = 4) +@MappedType public class MappedFloat extends MappedObject { public MappedFloat() { Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -82,7 +82,7 @@ System.out.println("current.view=" + some.view + ", not " + elementCount + ", as you might expect"); } - @MappedType(sizeof = 12) + @MappedType public static class Xyz extends MappedObject { int x, y, z; Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -32,7 +32,11 @@ package org.lwjgl.test.mapped; import org.lwjgl.MemoryUtil; +import org.lwjgl.PointerBuffer; import org.lwjgl.opengl.Display; +import org.lwjgl.util.mapped.MappedObject; +import org.lwjgl.util.mapped.MappedType; +import org.lwjgl.util.mapped.Pointer; import java.io.File; import java.nio.ByteBuffer; @@ -112,4 +116,35 @@ } } + @MappedType + public static class MappedPointer extends MappedObject { + + int foo; + @Pointer long pointer; + int bar; + + } + + public static void testPointer() { + MappedPointer data = MappedPointer.malloc(100); + + assert (data.backingByteBuffer().capacity() == 100 * (4 + 4 + PointerBuffer.getPointerSize())); + + for ( int i = 0; i < 100; i++ ) { + data.view = i; + + data.foo = i; + data.pointer = i * 1000; + data.bar = i * 2; + } + + for ( int i = 0; i < 100; i++ ) { + data.view = i; + + assert (data.foo == i); + assert (data.pointer == i * 1000); + assert (data.bar == i * 2); + } + } + } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -38,7 +38,7 @@ import java.nio.ByteBuffer; /** @author Riven */ -@MappedType(sizeof = 64) +@MappedType public class MappedSomething extends MappedObject { @MappedField(byteOffset = 0) Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -35,7 +35,7 @@ import org.lwjgl.util.mapped.MappedType; /** @author Riven */ -@MappedType(sizeof = 8) +@MappedType public class MappedVec2 extends MappedObject { public float x; Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -35,7 +35,7 @@ import org.lwjgl.util.mapped.MappedType; /** @author Riven */ -@MappedType(sizeof = 12) +@MappedType public class MappedVec3 extends MappedObject { public float x; Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -51,6 +51,7 @@ MappedObjectTransformer.register(MappedVec3.class); MappedObjectTransformer.register(MappedSomething.class); MappedObjectTransformer.register(MappedObjectTests3.Xyz.class); + MappedObjectTransformer.register(MappedObjectTests4.MappedPointer.class); if ( MappedObjectClassLoader.fork(TestMappedObject.class, args) ) { return; @@ -72,10 +73,9 @@ MappedObjectTests3.testMappedSet(); MappedObjectTests4.testLocalView(); - //MappedObjectTests4.testLWJGL(); + MappedObjectTests4.testPointer(); - System.out.println("done"); } Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -204,14 +204,14 @@ return texID; } - @MappedType(sizeof = 4) + @MappedType public static class Pixel4b extends MappedObject { public byte r, g, b, a; } - @MappedType(sizeof = 3, align = 3) + @MappedType(align = 3) public static class Pixel3b extends MappedObject { public byte r, g, b; @@ -413,15 +413,15 @@ Display.destroy(); } - @MappedType(sizeof = 4 * 4) + @MappedType public static class Sprite extends MappedObject { - public float x, y; - public float dx, dy; + public float x, dx; + public float y, dy; } - @MappedType(sizeof = 2 * 4) + @MappedType public static class SpriteRender extends MappedObject { public float x, y; @@ -536,12 +536,15 @@ x += dx * delta; if ( x < ballRadius ) { x = ballRadius; - sprites[b].dx = -dx; + dx = -dx; } else if ( x > boundW ) { x = boundW; - sprites[b].dx = -dx; + dx = -dx; } + sprites[b].x = x; + sprites[b].dx = dx; + spritesRender[r].x = x; float y = sprites[b].y; float dy = sprites[b].dy; @@ -549,14 +552,14 @@ y += dy * delta; if ( y < ballRadius ) { y = ballRadius; - sprites[b].dy = -dy; + dy = -dy; } else if ( y > boundH ) { y = boundH; - sprites[b].dy = -dy; + dy = -dy; } + sprites[b].y = y; - - spritesRender[r].x = x; + sprites[b].dy = dy; spritesRender[r].y = y; } } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -239,6 +239,24 @@ return MappedObjectUnsafe.INSTANCE.getLong(mapped.viewAddress + fieldOffset); } + // address + + public static void aput(long value, long addr) { + MappedObjectUnsafe.INSTANCE.putAddress(addr, value); + } + + public static void aput(MappedObject mapped, long value, int fieldOffset) { + MappedObjectUnsafe.INSTANCE.putAddress(mapped.viewAddress + fieldOffset, value); + } + + public static long aget(long addr) { + return MappedObjectUnsafe.INSTANCE.getAddress(addr); + } + + public static long aget(MappedObject mapped, int fieldOffset) { + return MappedObjectUnsafe.INSTANCE.getAddress(mapped.viewAddress + fieldOffset); + } + // double public static void dput(double value, long addr) { Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -96,9 +96,6 @@ final String name = MappedObject.class.getName(); String className = name.replace('.', '/'); - if ( MappedObjectTransformer.PRINT_ACTIVITY ) - LWJGLUtil.log(MappedObjectClassLoader.class.getSimpleName() + ": " + className); - byte[] bytecode = readStream(this.getResourceAsStream(className.concat(".class"))); long t0 = System.nanoTime(); @@ -106,8 +103,8 @@ long t1 = System.nanoTime(); total_time_transforming += (t1 - t0); - if ( MappedObjectTransformer.PRINT_TIMING ) - LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)"); + if ( MappedObjectTransformer.PRINT_ACTIVITY ) + printActivity(className, t0, t1); Class<?> clazz = super.defineClass(name, bytecode, 0, bytecode.length); resolveClass(clazz); @@ -128,25 +125,29 @@ if ( name.startsWith("sunw.") ) return super.loadClass(name, resolve); - if ( name.equals(MappedObjectClassLoader.class.getName()) ) + if ( name.startsWith("org.objectweb.asm.") ) return super.loadClass(name, resolve); + if ( name.equals(MappedObjectClassLoader.class.getName()) || name.equals((MappedObjectTransformer.class.getName())) ) + return super.loadClass(name, resolve); + String className = name.replace('.', '/'); - if ( MappedObjectTransformer.PRINT_ACTIVITY ) - LWJGLUtil.log(MappedObjectClassLoader.class.getSimpleName() + ": " + className); - byte[] bytecode = readStream(this.getResourceAsStream(className.concat(".class"))); // Classes in this package do not get transformed, but need to go through here because we have transformed MappedObject. if ( !(name.startsWith(MAPPEDOBJECT_PACKAGE_PREFIX) && name.substring(MAPPEDOBJECT_PACKAGE_PREFIX.length()).indexOf('.') == -1) ) { long t0 = System.nanoTime(); - bytecode = MappedObjectTransformer.transformMappedAPI(className, bytecode); + final byte[] newBytecode = MappedObjectTransformer.transformMappedAPI(className, bytecode); long t1 = System.nanoTime(); total_time_transforming += (t1 - t0); - if ( MappedObjectTransformer.PRINT_TIMING ) - LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)"); + + if ( bytecode != newBytecode ) { + bytecode = newBytecode; + if ( MappedObjectTransformer.PRINT_ACTIVITY ) + printActivity(className, t0, t1); + } } Class<?> clazz = super.defineClass(name, bytecode, 0, bytecode.length); @@ -155,6 +156,15 @@ return clazz; } + private static void printActivity(final String className, final long t0, final long t1) { + final StringBuilder msg = new StringBuilder(MappedObjectClassLoader.class.getSimpleName() + ": " + className); + + if ( MappedObjectTransformer.PRINT_TIMING ) + msg.append("\n\ttransforming took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)"); + + LWJGLUtil.log(msg); + } + private static byte[] readStream(InputStream in) { byte[] bytecode = new byte[256]; int len = 0; Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -63,8 +63,8 @@ */ public class MappedObjectTransformer { - static final boolean PRINT_TIMING = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintTiming"); static final boolean PRINT_ACTIVITY = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintActivity"); + static final boolean PRINT_TIMING = PRINT_ACTIVITY && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintTiming"); static final boolean PRINT_BYTECODE = LWJGLUtil.DEBUG && LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.PrintBytecode"); static final Map<String, MappedSubtypeInfo> className_to_subtype; @@ -113,7 +113,7 @@ // => IADD // => PUTFIELD MyMappedType.view // - className_to_subtype.put(MAPPED_OBJECT_JVM, new MappedSubtypeInfo(MAPPED_OBJECT_JVM, -1, -1)); + className_to_subtype.put(MAPPED_OBJECT_JVM, new MappedSubtypeInfo(MAPPED_OBJECT_JVM, null, -1, -1)); } final String vmName = System.getProperty("java.vm.name"); @@ -129,39 +129,66 @@ * @param type the mapped object class. */ public static void register(Class<?> type) { + if ( MappedObjectClassLoader.FORKED ) + return; + final MappedType mapped = type.getAnnotation(MappedType.class); if ( mapped == null ) - throw new InternalError("missing " + MappedType.class.getName() + " annotation"); + throw new ClassFormatError("missing " + MappedType.class.getName() + " annotation"); + if ( mapped.padding() < 0 ) + throw new ClassFormatError("Invalid mapped type padding: " + mapped.padding()); + if ( type.getEnclosingClass() != null && !Modifier.isStatic(type.getModifiers()) ) throw new InternalError("only top-level or static inner classes are allowed"); - final MappedSubtypeInfo mappedType = new MappedSubtypeInfo(jvmClassName(type), mapped.sizeof(), mapped.align()); + final String className = jvmClassName(type); + final Map<String, FieldInfo> fields = new HashMap<String, FieldInfo>(); int advancingOffset = 0; - for ( Field field : type.getDeclaredFields() ) - advancingOffset += registerField(mapped, mappedType.className, mappedType, advancingOffset, field); + long sizeof = 0; + for ( Field field : type.getDeclaredFields() ) { + FieldInfo fieldInfo = registerField(mapped, className, advancingOffset, field); + if ( fieldInfo == null ) + continue; - if ( className_to_subtype.put(mappedType.className, mappedType) != null ) + fields.put(field.getName(), fieldInfo); + + advancingOffset += fieldInfo.length; + sizeof = Math.max(sizeof, fieldInfo.offset + fieldInfo.length); + } + + sizeof += mapped.padding(); + + final MappedSubtypeInfo mappedType = new MappedSubtypeInfo(className, fields, (int)sizeof, mapped.align()); + if ( className_to_subtype.put(className, mappedType) != null ) throw new InternalError("duplicate mapped type: " + mappedType.className); } - private static int registerField(final MappedType mapped, final String className, final MappedSubtypeInfo mappedType, int advancingOffset, final Field field) { + private static FieldInfo registerField(final MappedType mapped, final String className, int advancingOffset, final Field field) { if ( Modifier.isStatic(field.getModifiers()) ) // static fields are never mapped - return 0; + return null; // we only support primitives and ByteBuffers if ( !field.getType().isPrimitive() && field.getType() != ByteBuffer.class ) - throw new InternalError("field '" + className + "." + field.getName() + "' not supported: " + field.getType()); + throw new ClassFormatError("field '" + className + "." + field.getName() + "' not supported: " + field.getType()); MappedField meta = field.getAnnotation(MappedField.class); if ( meta == null && !mapped.autoGenerateOffsets() ) - throw new InternalError("field '" + className + "." + field.getName() + "' missing annotation " + MappedField.class.getName() + ": " + className); + throw new ClassFormatError("field '" + className + "." + field.getName() + "' missing annotation " + MappedField.class.getName() + ": " + className); + Pointer pointer = field.getAnnotation(Pointer.class); + if ( pointer != null && field.getType() != long.class ) + throw new ClassFormatError("The @Pointer annotation can only be used on long fields. Field found: " + className + "." + field.getName() + ": " + field.getType()); // quick hack long byteOffset = meta == null ? advancingOffset : meta.byteOffset(); long byteLength; - if ( field.getType() == long.class || field.getType() == double.class ) + if ( field.getType() == long.class || field.getType() == double.class ) { + if ( pointer == null ) + byteLength = 8; + else + byteLength = MappedObjectUnsafe.INSTANCE.addressSize(); + } else if ( field.getType() == double.class ) byteLength = 8; else if ( field.getType() == int.class || field.getType() == float.class ) byteLength = 4; @@ -174,7 +201,7 @@ if ( byteLength < 0 ) throw new IllegalStateException("invalid byte length for mapped ByteBuffer field: " + className + "." + field.getName() + " [length=" + byteLength + "]"); } else - throw new InternalError(field.getType().getName()); + throw new ClassFormatError(field.getType().getName()); if ( field.getType() != ByteBuffer.class && (advancingOffset % byteLength) != 0 ) throw new IllegalStateException("misaligned mapped type: " + className + "." + field.getName()); @@ -182,11 +209,7 @@ if ( PRINT_ACTIVITY ) LWJGLUtil.log(MappedObjectTransformer.class.getSimpleName() + ": " + className + "." + field.getName() + " [type=" + field.getType().getSimpleName() + ", offset=" + byteOffset + "]"); - mappedType.fieldToOffset.put(field.getName(), byteOffset); - mappedType.fieldToLength.put(field.getName(), byteLength); - mappedType.fieldToType.put(field.getName(), Type.getType(field.getType())); - - return (int)byteLength; + return new FieldInfo(byteOffset, byteLength, Type.getType(field.getType()), pointer != null); } /** Removes final from methods that will be overriden by subclasses. */ @@ -231,13 +254,18 @@ }; - ClassVisitor cv = getTransformationAdapter(className, cw); + final TransformationAdapter ta = new TransformationAdapter(cw, className); + + ClassVisitor cv = ta; if ( className_to_subtype.containsKey(className) ) // Do a first pass to generate address getters cv = getMethodGenAdapter(className, cv); new ClassReader(bytecode).accept(cv, ClassReader.SKIP_FRAMES); + + if ( !ta.transformed ) + return bytecode; + bytecode = cw.toByteArray(); - if ( PRINT_BYTECODE ) printBytecode(bytecode); @@ -257,14 +285,14 @@ generateSizeofGetter(); generateNext(); - for ( String fieldName : mappedSubtype.fieldToOffset.keySet() ) { - final Type type = mappedSubtype.fieldToType.get(fieldName); + for ( String fieldName : mappedSubtype.fields.keySet() ) { + final FieldInfo field = mappedSubtype.fields.get(fieldName); - if ( type.getDescriptor().length() > 1 ) { // ByteBuffer, getter only - generateByteBufferGetter(mappedSubtype, fieldName, type); + if ( field.type.getDescriptor().length() > 1 ) { // ByteBuffer, getter only + generateByteBufferGetter(fieldName, field); } else { - generateFieldGetter(mappedSubtype, fieldName, type); - generateFieldSetter(mappedSubtype, fieldName, type); + generateFieldGetter(fieldName, field); + generateFieldSetter(fieldName, field); } } @@ -342,42 +370,42 @@ mv.visitEnd(); } - private void generateByteBufferGetter(final MappedSubtypeInfo mappedSubtype, final String fieldName, final Type type) { - MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, getterName(fieldName), "(L" + className + ";I)" + type.getDescriptor(), null, null); + private void generateByteBufferGetter(final String fieldName, final FieldInfo field) { + MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, getterName(fieldName), "(L" + className + ";I)" + field.type.getDescriptor(), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J"); - visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue()); + visitIntNode(mv, (int)field.offset); mv.visitInsn(I2L); mv.visitInsn(LADD); - visitIntNode(mv, mappedSubtype.fieldToLength.get(fieldName).intValue()); + visitIntNode(mv, (int)field.length); mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";"); mv.visitInsn(ARETURN); - mv.visitMaxs(4, 2); + mv.visitMaxs(3, 2); mv.visitEnd(); } - private void generateFieldGetter(final MappedSubtypeInfo mappedSubtype, final String fieldName, final Type type) { - MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, getterName(fieldName), "(L" + className + ";I)" + type.getDescriptor(), null, null); + private void generateFieldGetter(final String fieldName, final FieldInfo field) { + MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, getterName(fieldName), "(L" + className + ";I)" + field.type.getDescriptor(), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J"); - visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue()); + visitIntNode(mv, (int)field.offset); mv.visitInsn(I2L); mv.visitInsn(LADD); - mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, type.getDescriptor().toLowerCase() + "get", "(J)" + type.getDescriptor()); - mv.visitInsn(type.getOpcode(IRETURN)); + mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, field.isPointer ? "a" : field.type.getDescriptor().toLowerCase() + "get", "(J)" + field.type.getDescriptor()); + mv.visitInsn(field.type.getOpcode(IRETURN)); mv.visitMaxs(3, 2); mv.visitEnd(); } - private void generateFieldSetter(final MappedSubtypeInfo mappedSubtype, final String fieldName, final Type type) { - MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, setterName(fieldName), "(L" + className + ";I" + type.getDescriptor() + ")V", null, null); + private void generateFieldSetter(final String fieldName, final FieldInfo field) { + MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, setterName(fieldName), "(L" + className + ";I" + field.type.getDescriptor() + ")V", null, null); mv.visitCode(); int load = 0; - switch ( type.getSort() ) { + switch ( field.type.getSort() ) { case Type.BOOLEAN: case Type.CHAR: case Type.BYTE: @@ -399,156 +427,164 @@ mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J"); - visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue()); + visitIntNode(mv, (int)field.offset); mv.visitInsn(I2L); mv.visitInsn(LADD); - mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, type.getDescriptor().toLowerCase() + "put", "(" + type.getDescriptor() + "J)V"); + mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, field.isPointer ? "a" : field.type.getDescriptor().toLowerCase() + "put", "(" + field.type.getDescriptor() + "J)V"); mv.visitInsn(RETURN); - mv.visitMaxs(4, 3); + mv.visitMaxs(4, 4); mv.visitEnd(); } }; } - private static ClassAdapter getTransformationAdapter(final String className, final ClassWriter cw) { - return new ClassAdapter(cw) { + private static class TransformationAdapter extends ClassAdapter { - @Override - public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { - // remove redirected fields - final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className); - if ( mappedSubtype != null && mappedSubtype.fieldToOffset.containsKey(name) ) { - if ( PRINT_ACTIVITY ) - LWJGLUtil.log(MappedObjectTransformer.class.getSimpleName() + ": discarding field: " + className + "." + name + ":" + desc); - return null; - } + final String className; - return super.visitField(access, name, desc, signature, value); + boolean transformed; + + TransformationAdapter(final ClassVisitor cv, final String className) { + super(cv); + this.className = className; + } + + @Override + public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { + // remove redirected fields + final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className); + if ( mappedSubtype != null && mappedSubtype.fields.containsKey(name) ) { + if ( PRINT_ACTIVITY ) + LWJGLUtil.log(MappedObjectTransformer.class.getSimpleName() + ": discarding field: " + className + "." + name + ":" + desc); + return null; } - @Override - public MethodVisitor visitMethod(final int access, String name, final String desc, final String signature, final String[] exceptions) { - // Move MappedSubtype constructors to another method - if ( "<init>".equals(name) ) { - final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className); - if ( mappedSubtype != null ) { - if ( !"()V".equals(desc) ) - throw new ClassFormatError(className + " can only have a default constructor, found: " + desc); + return super.visitField(access, name, desc, signature, value); + } - final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, MAPPED_OBJECT_JVM, "<init>", "()V"); - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); + @Override + public MethodVisitor visitMethod(final int access, String name, final String desc, final String signature, final String[] exceptions) { + // Move MappedSubtype constructors to another method + if ( "<init>".equals(name) ) { + final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className); + if ( mappedSubtype != null ) { + if ( !"()V".equals(desc) ) + throw new ClassFormatError(className + " can only have a default constructor, found: " + desc); - // put the method body in another method - name = VIEW_CONSTRUCTOR_NAME; - } + final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, MAPPED_OBJECT_JVM, "<init>", "()V"); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + + // put the method body in another method + name = VIEW_CONSTRUCTOR_NAME; } + } - final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - return new MethodNode(access, name, desc, signature, exceptions) { + final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodNode(access, name, desc, signature, exceptions) { - /** When true, the method has touched a mapped object and needs to be transformed. We track this - * so we can skip the expensive frame analysis and tree API usage. */ - boolean needsTransformation; + /** When true, the method has touched a mapped object and needs to be transformed. We track this + * so we can skip the expensive frame analysis and tree API usage. */ + boolean needsTransformation; - @Override - public void visitMaxs(int a, int b) { - try { - is_currently_computing_frames = true; - super.visitMaxs(a, b); - } finally { - is_currently_computing_frames = false; - } + @Override + public void visitMaxs(int a, int b) { + try { + is_currently_computing_frames = true; + super.visitMaxs(a, b); + } finally { + is_currently_computing_frames = false; } + } - @Override - public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { - if ( className_to_subtype.containsKey(owner) || owner.startsWith(MAPPEDSET_PREFIX) ) - needsTransformation = true; + @Override + public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { + if ( className_to_subtype.containsKey(owner) || owner.startsWith(MAPPEDSET_PREFIX) ) + needsTransformation = true; - super.visitFieldInsn(opcode, owner, name, desc); - } + super.visitFieldInsn(opcode, owner, name, desc); + } - @Override - public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { - if ( className_to_subtype.containsKey(owner) ) - needsTransformation = true; + @Override + public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if ( className_to_subtype.containsKey(owner) ) + needsTransformation = true; - super.visitMethodInsn(opcode, owner, name, desc); - } + super.visitMethodInsn(opcode, owner, name, desc); + } - @Override - public void visitEnd() { - if ( needsTransformation ) { // Early-out for methods that do not touch a mapped object. - //System.err.println("\nTRANSFORMING: " + className + "." + name + desc); - try { - transformMethod(analyse()); - } catch (Exception e) { - throw new RuntimeException(e); - } + @Override + public void visitEnd() { + if ( needsTransformation ) { // Early-out for methods that do not touch a mapped object. + //System.err.println("\nTRANSFORMING: " + className + "." + name + desc); + transformed = true; + try { + transformMethod(analyse()); + } catch (Exception e) { + throw new RuntimeException(e); } - - // Pass the instruction stream to the adapter's MethodVisitor - accept(mv); } - private Frame<BasicValue>[] analyse() throws AnalyzerException { - final Analyzer<BasicValue> a = new Analyzer<BasicValue>(new SimpleVerifier()); - a.analyze(className, this); - return a.getFrames(); - } + // Pass the instruction stream to the adapter's MethodVisitor + accept(mv); + } - private void transformMethod(final Frame<BasicValue>[] frames) { - final InsnList instructions = this.instructions; + private Frame<BasicValue>[] analyse() throws AnalyzerException { + final Analyzer<BasicValue> a = new Analyzer<BasicValue>(new SimpleVerifier()); + a.analyze(className, this); + return a.getFrames(); + } - final Map<Integer, MappedSubtypeInfo> arrayVars = new HashMap<Integer, MappedSubtypeInfo>(); + private void transformMethod(final Frame<BasicValue>[] frames) { + final InsnList instructions = this.instructions; - /* - We need this map because we insert/remove instructions from the stream and we need a way - to match each original instruction with the corresponding frame. - TODO: Can we keep track of everything more efficiently without a map? - */ - final Map<AbstractInsnNode, Frame<BasicValue>> frameMap = new HashMap<AbstractInsnNode, Frame<BasicValue>>(); - for ( int i = 0; i < frames.length; i++ ) - frameMap.put(instructions.get(i), frames[i]); + final Map<Integer, MappedSubtypeInfo> arrayVars = new HashMap<Integer, MappedSubtypeInfo>(); - for ( int i = 0; i < instructions.size(); i++ ) { // f is a separate cursor for frames - final AbstractInsnNode instruction = instructions.get(i); + /* + We need this map because we insert/remove instructions from the stream and we need a way + to match each original instruction with the corresponding frame. + TODO: Can we keep track of everything more efficiently without a map? + */ + final Map<AbstractInsnNode, Frame<BasicValue>> frameMap = new HashMap<AbstractInsnNode, Frame<BasicValue>>(); + for ( int i = 0; i < frames.length; i++ ) + frameMap.put(instructions.get(i), frames[i]); - //System.out.println("MAIN LOOP #" + i + " - " + getOpcodeName(instruction)); + for ( int i = 0; i < instructions.size(); i++ ) { // f is a separate cursor for frames + final AbstractInsnNode instruction = instructions.get(i); - switch ( instruction.getType() ) { - case AbstractInsnNode.VAR_INSN: - if ( instruction.getOpcode() == ALOAD ) { - VarInsnNode varInsn = (VarInsnNode)instruction; - final MappedSubtypeInfo mappedSubtype = arrayVars.get(varInsn.var); - if ( mappedSubtype != null ) - i = transformArrayAccess(instructions, i, frameMap, varInsn, mappedSubtype, varInsn.var); - } - break; - case AbstractInsnNode.FIELD_INSN: - FieldInsnNode fieldInsn = (FieldInsnNode)instruction; + //System.out.println("MAIN LOOP #" + i + " - " + getOpcodeName(instruction)); - final InsnList list = transformFieldAccess(fieldInsn); - if ( list != null ) - i = replace(instructions, i, instruction, list); + switch ( instruction.getType() ) { + case AbstractInsnNode.VAR_INSN: + if ( instruction.getOpcode() == ALOAD ) { + VarInsnNode varInsn = (VarInsnNode)instruction; + final MappedSubtypeInfo mappedSubtype = arrayVars.get(varInsn.var); + if ( mappedSubtype != null ) + i = transformArrayAccess(instructions, i, frameMap, varInsn, mappedSubtype, varInsn.var); + } + break; + case AbstractInsnNode.FIELD_INSN: + FieldInsnNode fieldInsn = (FieldInsnNode)instruction; - break; - case AbstractInsnNode.METHOD_INSN: - MethodInsnNode methodInsn = (MethodInsnNode)instruction; - final MappedSubtypeInfo mappedType = className_to_subtype.get(methodInsn.owner); - if ( mappedType != null ) - i = transformMethodCall(instructions, i, frameMap, methodInsn, mappedType, arrayVars); - break; - } + final InsnList list = transformFieldAccess(fieldInsn); + if ( list != null ) + i = replace(instructions, i, instruction, list); + + break; + case AbstractInsnNode.METHOD_INSN: + MethodInsnNode methodInsn = (MethodInsnNode)instruction; + final MappedSubtypeInfo mappedType = className_to_subtype.get(methodInsn.owner); + if ( mappedType != null ) + i = transformMethodCall(instructions, i, frameMap, methodInsn, mappedType, arrayVars); + break; } } - }; - } - }; + } + }; + } } static int transformMethodCall(final InsnList instructions, int i, final Map<AbstractInsnNode, Frame<BasicValue>> frameMap, final MethodInsnNode methodInsn, final MappedSubtypeInfo mappedType, final Map<Integer, MappedSubtypeInfo> arrayVars) { @@ -760,16 +796,16 @@ return generateAddressInstructions(fieldInsn); } - final Long fieldOffset = mappedSubtype.fieldToOffset.get(fieldInsn.name); - if ( fieldOffset == null ) // early out + final FieldInfo field = mappedSubtype.fields.get(fieldInsn.name); + if ( field == null ) // early out return null; // now we're going to transform ByteBuffer-typed field access if ( fieldInsn.desc.equals("L" + jvmClassName(ByteBuffer.class) + ";") ) - return generateByteBufferInstructions(fieldInsn, mappedSubtype, fieldOffset); + return generateByteBufferInstructions(fieldInsn, mappedSubtype, field.offset); // we're now going to transform the field access - return generateFieldInstructions(fieldInsn, fieldOffset); + return generateFieldInstructions(fieldInsn, field); } private static InsnList generateSetViewInstructions(final FieldInsnNode fieldInsn) { @@ -867,13 +903,11 @@ throw new InternalError(); } - private static InsnList generateByteBufferInstructions(final FieldInsnNode fieldInsn, final MappedSubtypeInfo mappedSubtype, final Long fieldOffset) { + private static InsnList generateByteBufferInstructions(final FieldInsnNode fieldInsn, final MappedSubtypeInfo mappedSubtype, final long fieldOffset) { if ( fieldInsn.getOpcode() == PUTFIELD ) throwAccessErrorOnReadOnlyField(fieldInsn.owner, fieldInsn.name); if ( fieldInsn.getOpcode() == GETFIELD ) { - final Long fieldLength = mappedSubtype.fieldToLength.get(fieldInsn.name); - final InsnList list = new InsnList(); // stack: ref @@ -883,7 +917,7 @@ // stack: long, long list.add(new InsnNode(LADD)); // stack: long - list.add(new LdcInsnNode(fieldLength)); + list.add(new LdcInsnNode(mappedSubtype.fields.get(fieldInsn.name).length)); // stack: long, long list.add(new InsnNode(L2I)); // stack: int, long @@ -896,23 +930,25 @@ throw new InternalError(); } - private static InsnList generateFieldInstructions(final FieldInsnNode fieldInsn, final Long fieldOffset) { + private static InsnList generateFieldInstructions(final FieldInsnNode fieldInsn, final FieldInfo field) { final InsnList list = new InsnList(); + final String dataType = field.isPointer ? "a" : fieldInsn.desc.toLowerCase(); + if ( fieldInsn.getOpcode() == PUTFIELD ) { // stack: value, ref - list.add(getIntNode(fieldOffset.intValue())); + list.add(getIntNode((int)field.offset)); // stack: fieldOffset, value, ref - list.add(new MethodInsnNode(INVOKESTATIC, MAPPED_HELPER_JVM, fieldInsn.desc.toLowerCase() + "put", "(L" + MAPPED_OBJECT_JVM + ";" + fieldInsn.desc + "I)V")); + list.add(new MethodInsnNode(INVOKESTATIC, MAPPED_HELPER_JVM, dataType + "put", "(L" + MAPPED_OBJECT_JVM + ";" + fieldInsn.desc + "I)V")); // stack - return list; } if ( fieldInsn.getOpcode() == GETFIELD ) { // stack: ref - list.add(getIntNode(fieldOffset.intValue())); + list.add(getIntNode((int)field.offset)); // stack: fieldOffset, ref - list.add(new MethodInsnNode(INVOKESTATIC, MAPPED_HELPER_JVM, fieldInsn.desc.toLowerCase() + "get", "(L" + MAPPED_OBJECT_JVM + ";I)" + fieldInsn.desc)); + list.add(new MethodInsnNode(INVOKESTATIC, MAPPED_HELPER_JVM, dataType + "get", "(L" + MAPPED_OBJECT_JVM + ";I)" + fieldInsn.desc)); // stack: - return list; } @@ -1006,29 +1042,43 @@ } } + private static class FieldInfo { + + final long offset; + final long length; + final Type type; + final boolean isPointer; + + FieldInfo(final long offset, final long length, final Type type, final boolean isPointer) { + this.offset = offset; + this.length = length; + this.type = type; + this.isPointer = isPointer; + } + + } + private static class MappedSubtypeInfo { - public final String className; + final String className; - public int sizeof; - public int sizeof_shift; - public int align; + final int sizeof; + final int sizeof_shift; + final int align; - public Map<String, Long> fieldToOffset; - public Map<String, Long> fieldToLength; - public Map<String, Type> fieldToType; + final Map<String, FieldInfo> fields; - MappedSubtypeInfo(String className, int sizeof, int align) { + MappedSubtypeInfo(String className, Map<String, FieldInfo> fields, int sizeof, int align) { this.className = className; this.sizeof = sizeof; if ( ((sizeof - 1) & sizeof) == 0 ) this.sizeof_shift = getPoT(sizeof); + else + this.sizeof_shift = 0; this.align = align; - this.fieldToOffset = new HashMap<String, Long>(); - this.fieldToLength = new HashMap<String, Long>(); - this.fieldToType = new HashMap<String, Type>(); + this.fields = fields; } private static int getPoT(int value) { Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java 2011-07-22 20:09:01 UTC (rev 3598) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -60,11 +60,12 @@ public @interface MappedType { /** - * The total size of the mapped object, in bytes. + * The number of bytes to add to the total byte size. + * SIZEOF will be calculated as <code>SIZEOF = max(field_offset + field_length) + padding</code> * - * @return the byte size + * @return the padding amount */ - int sizeof(); + int padding() default 0; /** * The mapped data memory alignment, in bytes. Added: trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java 2011-07-23 22:02:01 UTC (rev 3599) @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.util.mapped; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation can be used on long fields of {@link MappedType} classes, + * to specify that the long value should be interpreted as a pointer. This + * will determine the actual byte size of the field at runtime (4 or 8 bytes). + * + * @author Spasi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Pointer { + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-07-24 09:38:53
|
Revision: 3601 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3601&view=rev Author: spasi Date: 2011-07-24 09:38:46 +0000 (Sun, 24 Jul 2011) Log Message: ----------- @MappedType is now optional. copyTo now only copies (SIZEOF - padding) bytes. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedFloat.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -32,10 +32,8 @@ package org.lwjgl.test.mapped; import org.lwjgl.util.mapped.MappedObject; -import org.lwjgl.util.mapped.MappedType; /** @author Riven */ -@MappedType public class MappedFloat extends MappedObject { public MappedFloat() { Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -35,7 +35,6 @@ import org.lwjgl.util.mapped.MappedObject; import org.lwjgl.util.mapped.MappedSet; import org.lwjgl.util.mapped.MappedSet2; -import org.lwjgl.util.mapped.MappedType; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -82,7 +81,6 @@ System.out.println("current.view=" + some.view + ", not " + elementCount + ", as you might expect"); } - @MappedType public static class Xyz extends MappedObject { int x, y, z; Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -35,7 +35,6 @@ import org.lwjgl.PointerBuffer; import org.lwjgl.opengl.Display; import org.lwjgl.util.mapped.MappedObject; -import org.lwjgl.util.mapped.MappedType; import org.lwjgl.util.mapped.Pointer; import java.io.File; @@ -116,7 +115,6 @@ } } - @MappedType public static class MappedPointer extends MappedObject { int foo; Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -33,12 +33,10 @@ import org.lwjgl.util.mapped.MappedField; import org.lwjgl.util.mapped.MappedObject; -import org.lwjgl.util.mapped.MappedType; import java.nio.ByteBuffer; /** @author Riven */ -@MappedType public class MappedSomething extends MappedObject { @MappedField(byteOffset = 0) Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec2.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -32,10 +32,8 @@ package org.lwjgl.test.mapped; import org.lwjgl.util.mapped.MappedObject; -import org.lwjgl.util.mapped.MappedType; /** @author Riven */ -@MappedType public class MappedVec2 extends MappedObject { public float x; Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedVec3.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -32,10 +32,8 @@ package org.lwjgl.test.mapped; import org.lwjgl.util.mapped.MappedObject; -import org.lwjgl.util.mapped.MappedType; /** @author Riven */ -@MappedType public class MappedVec3 extends MappedObject { public float x; Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -204,7 +204,6 @@ return texID; } - @MappedType public static class Pixel4b extends MappedObject { public byte r, g, b, a; @@ -413,7 +412,6 @@ Display.destroy(); } - @MappedType public static class Sprite extends MappedObject { public float x, dx; @@ -421,7 +419,6 @@ } - @MappedType public static class SpriteRender extends MappedObject { public float x, y; Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -37,7 +37,7 @@ import java.lang.annotation.Target; /** - * This annotation can be used on fields of {@link MappedType} classes, + * This annotation can be used on fields of {@link MappedObject} subclasses, * to manually specify byte offsets and lengths. This is useful when the * mapped fields require custom alignment. {@link java.nio.ByteBuffer} * fields are required to have this annotation with a hardcoded byte length. Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObject.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -39,8 +39,8 @@ /** * Base superclass of all mapped objects. Classes that require - * data mapping should extend this class and also be annotated - * with {@link MappedType}. + * data mapping should extend this class and registered with + * {@link MappedObjectTransformer#register(Class)}. * <p/> * Subclasses may only specify the default constructor. Any code * inside that constructor is optional, but will not run when the @@ -215,7 +215,7 @@ } /** - * Copies and amount of <code>SIZEOF</code> bytes, from the current + * Copies and amount of <code>SIZEOF - padding</code> bytes, from the current * mapped object, to the specified mapped object. */ @SuppressWarnings("unused") @@ -225,8 +225,9 @@ } /** - * Copies and amount of <code>SIZEOF*instances<c/ode> bytes, from the - * current mapped object, to the specified mapped object. + * Copies and amount of <code>SIZEOF * instances</code> bytes, from the + * current mapped object, to the specified mapped object. Note that + * this includes any padding bytes that are part of SIZEOF. */ @SuppressWarnings("unused") public final <T extends MappedObject> void copyRange(T target, int instances) { Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -113,7 +113,7 @@ // => IADD // => PUTFIELD MyMappedType.view // - className_to_subtype.put(MAPPED_OBJECT_JVM, new MappedSubtypeInfo(MAPPED_OBJECT_JVM, null, -1, -1)); + className_to_subtype.put(MAPPED_OBJECT_JVM, new MappedSubtypeInfo(MAPPED_OBJECT_JVM, null, -1, -1, -1)); } final String vmName = System.getProperty("java.vm.name"); @@ -128,15 +128,13 @@ * * @param type the mapped object class. */ - public static void register(Class<?> type) { + public static void register(Class<? extends MappedObject> type) { if ( MappedObjectClassLoader.FORKED ) return; final MappedType mapped = type.getAnnotation(MappedType.class); - if ( mapped == null ) - throw new ClassFormatError("missing " + MappedType.class.getName() + " annotation"); - if ( mapped.padding() < 0 ) + if ( mapped != null && mapped.padding() < 0 ) throw new ClassFormatError("Invalid mapped type padding: " + mapped.padding()); if ( type.getEnclosingClass() != null && !Modifier.isStatic(type.getModifiers()) ) @@ -148,7 +146,7 @@ int advancingOffset = 0; long sizeof = 0; for ( Field field : type.getDeclaredFields() ) { - FieldInfo fieldInfo = registerField(mapped, className, advancingOffset, field); + FieldInfo fieldInfo = registerField(mapped == null || mapped.autoGenerateOffsets(), className, advancingOffset, field); if ( fieldInfo == null ) continue; @@ -158,14 +156,17 @@ sizeof = Math.max(sizeof, fieldInfo.offset + fieldInfo.length); } - sizeof += mapped.padding(); + final int align = mapped == null ? 4 : mapped.align(); + final int padding = mapped == null ? 0 : mapped.padding(); - final MappedSubtypeInfo mappedType = new MappedSubtypeInfo(className, fields, (int)sizeof, mapped.align()); + sizeof += padding; + + final MappedSubtypeInfo mappedType = new MappedSubtypeInfo(className, fields, (int)sizeof, align, padding); if ( className_to_subtype.put(className, mappedType) != null ) throw new InternalError("duplicate mapped type: " + mappedType.className); } - private static FieldInfo registerField(final MappedType mapped, final String className, int advancingOffset, final Field field) { + private static FieldInfo registerField(final boolean autoGenerateOffsets, final String className, int advancingOffset, final Field field) { if ( Modifier.isStatic(field.getModifiers()) ) // static fields are never mapped return null; @@ -174,7 +175,7 @@ throw new ClassFormatError("field '" + className + "." + field.getName() + "' not supported: " + field.getType()); MappedField meta = field.getAnnotation(MappedField.class); - if ( meta == null && !mapped.autoGenerateOffsets() ) + if ( meta == null && !autoGenerateOffsets ) throw new ClassFormatError("field '" + className + "." + field.getName() + "' missing annotation " + MappedField.class.getName() + ": " + className); Pointer pointer = field.getAnnotation(Pointer.class); @@ -688,7 +689,7 @@ final InsnList list = new InsnList(); // stack: target, this - list.add(getIntNode(mappedType.sizeof)); + list.add(getIntNode(mappedType.sizeof - mappedType.padding)); // stack: sizeof, target, this list.add(new MethodInsnNode(INVOKESTATIC, MAPPED_HELPER_JVM, "copy", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";I)V")); // stack: - @@ -1073,10 +1074,11 @@ final int sizeof; final int sizeof_shift; final int align; + final int padding; final Map<String, FieldInfo> fields; - MappedSubtypeInfo(String className, Map<String, FieldInfo> fields, int sizeof, int align) { + MappedSubtypeInfo(String className, Map<String, FieldInfo> fields, int sizeof, int align, int padding) { this.className = className; this.sizeof = sizeof; @@ -1085,6 +1087,7 @@ else this.sizeof_shift = 0; this.align = align; + this.padding = padding; this.fields = fields; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java 2011-07-23 22:28:57 UTC (rev 3600) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/Pointer.java 2011-07-24 09:38:46 UTC (rev 3601) @@ -37,7 +37,7 @@ import java.lang.annotation.Target; /** - * This annotation can be used on long fields of {@link MappedType} classes, + * This annotation can be used on long fields of {@link MappedObject} subclasses, * to specify that the long value should be interpreted as a pointer. This * will determine the actual byte size of the field at runtime (4 or 8 bytes). * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sp...@us...> - 2011-08-10 16:05:54
|
Revision: 3608 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3608&view=rev Author: spasi Date: 2011-08-10 16:05:46 +0000 (Wed, 10 Aug 2011) Log Message: ----------- Added support for cache-line padding and alignment. Made byteOffset() in MappedField optional. Misc fixes and improvements. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectUnsafe.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLinePad.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLineSize.java trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheUtil.java Modified: trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/LWJGLUtil.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -449,15 +449,45 @@ * Gets a boolean property as a privileged action. */ public static boolean getPrivilegedBoolean(final String property_name) { - Boolean value = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { public Boolean run() { return Boolean.getBoolean(property_name); } }); - return value; } /** + * Gets an integer property as a privileged action. + * + * @param property_name the integer property name + * + * @return the property value + */ + public static Integer getPrivilegedInteger(final String property_name) { + return AccessController.doPrivileged(new PrivilegedAction<Integer>() { + public Integer run() { + return Integer.getInteger(property_name); + } + }); + } + + /** + * Gets an integer property as a privileged action. + * + * @param property_name the integer property name + * @param default_val the default value to use if the property is not defined + * + * @return the property value + */ + public static Integer getPrivilegedInteger(final String property_name, final int default_val) { + return AccessController.doPrivileged(new PrivilegedAction<Integer>() { + public Integer run() { + return Integer.getInteger(property_name, default_val); + } + }); + } + + /** * Prints the given message to System.err if DEBUG is true. * * @param msg Message to print Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests3.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -60,6 +60,16 @@ assert (addr2 - addr1 == 4); assert (mapped.capacity() == MappedSomething.SIZEOF - 4); + { + assert (some.shared == 0); + assert (mapped.getInt(8) == 0); + + some.shared = 1234; + + assert (some.shared == 1234); + assert (mapped.getInt(8) == 1234); + } + some.view++; mapped = some.data; // creates new ByteBuffer instance Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedObjectTests4.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -34,10 +34,10 @@ import org.lwjgl.MemoryUtil; import org.lwjgl.PointerBuffer; import org.lwjgl.opengl.Display; -import org.lwjgl.util.mapped.MappedObject; -import org.lwjgl.util.mapped.Pointer; +import org.lwjgl.util.mapped.*; import java.io.File; +import java.lang.reflect.Field; import java.nio.ByteBuffer; /** @author Riven */ @@ -145,4 +145,109 @@ } } + @MappedType(cacheLinePadding = true) + public static class MappedCacheLinePadded extends MappedObject { + + int foo; + int bar; + + } + + public static void testCacheLineAlignment() { + MappedCacheLinePadded data = MappedCacheLinePadded.malloc(10); + + assert (data.backingByteBuffer().capacity() == 10 * CacheUtil.getCacheLineSize()); + assert (MemoryUtil.getAddress(data.backingByteBuffer()) % CacheUtil.getCacheLineSize() == 0); + + for ( int i = 0; i < 10; i++ ) { + data.view = i; + + data.foo = i; + data.bar = i * 2; + } + + for ( int i = 0; i < 10; i++ ) { + data.view = i; + + assert (data.foo == i); + assert (data.bar == i * 2); + } + } + + public static class MappedFieldCacheLinePadded extends MappedObject { + + // If we assume CacheUtil.getCacheLineSize() == 64 + // 0 - 63 + @CacheLinePad long longBar; + // 64 - 71 + long longFoo; + // 72 - 75 + int intFoo; + // 128 - 131 + @CacheLinePad(before = true) int intBar; + // 192 - 195 + int foo; + // 256 - 267 + @CacheLinePad(before = true, after = false) + @MappedField(byteLength = 12) + ByteBuffer buffer; + // 268 - 271 + int bar; + + } + + public static void testCacheLinePadding() { + MappedFieldCacheLinePadded data = MappedFieldCacheLinePadded.map(CacheUtil.createByteBuffer(10 * MappedFieldCacheLinePadded.SIZEOF)); + + final int sizeof = + CacheUtil.getCacheLineSize() + + 8 + + (CacheUtil.getCacheLineSize() - 8) + + CacheUtil.getCacheLineSize() + + 4 + + (CacheUtil.getCacheLineSize() - 4) + + 12 + + 4; + + assert (MappedFieldCacheLinePadded.SIZEOF == sizeof); + assert (data.backingByteBuffer().capacity() == sizeof * 10); + + for ( int i = 0; i < 10; i++ ) { + data.view = i; + + data.longFoo = i * 1000000000L; + data.longBar = i * 2000000000L; + data.intFoo = i * 1000; + data.intBar = i * 2000; + data.foo = i; + } + + for ( int i = 0; i < 10; i++ ) { + data.view = i; + + assert (data.longFoo == i * 1000000000L); + assert (data.longBar == i * 2000000000L); + assert (data.intFoo == i * 1000); + assert (data.intBar == i * 2000); + assert (data.foo == i); + } + } + + public static class POJOFieldCacheLinePadded { + + @CacheLinePad long longBar; + long longFoo; + int intFoo; + @CacheLinePad(before = true) int intBar; + int foo; + @CacheLinePad boolean bool; + int bar; + + } + + public static void testCacheLinePaddingPOJO() { + Field[] fields = new POJOFieldCacheLinePadded().getClass().getDeclaredFields(); + assert (fields.length == (1 + 7) + 1 + 1 + (15 + 1 + 15) + 1 + (1 + 63) + 1); + } + } \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/MappedSomething.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -42,9 +42,12 @@ @MappedField(byteOffset = 0) public int used; - @MappedField(byteOffset = 4, byteLength = 64 - 4) + @MappedField(byteLength = 64 - 4) // optional byteOffset public ByteBuffer data; + @MappedField(byteOffset = 12) // inside data + public int shared; + @Override public String toString() { return "MappedSomething[" + used + "]"; Modified: trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/test/mapped/TestMappedObject.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -52,6 +52,8 @@ MappedObjectTransformer.register(MappedSomething.class); MappedObjectTransformer.register(MappedObjectTests3.Xyz.class); MappedObjectTransformer.register(MappedObjectTests4.MappedPointer.class); + MappedObjectTransformer.register(MappedObjectTests4.MappedCacheLinePadded.class); + MappedObjectTransformer.register(MappedObjectTests4.MappedFieldCacheLinePadded.class); if ( MappedObjectClassLoader.fork(TestMappedObject.class, args) ) { return; @@ -75,6 +77,9 @@ MappedObjectTests4.testLocalView(); //MappedObjectTests4.testLWJGL(); MappedObjectTests4.testPointer(); + MappedObjectTests4.testCacheLineAlignment(); + MappedObjectTests4.testCacheLinePadding(); + MappedObjectTests4.testCacheLinePaddingPOJO(); System.out.println("done"); } Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -86,6 +86,8 @@ private int texBigID; private int texSmallID; + long animateTime; + private SpriteShootout() { } @@ -276,6 +278,8 @@ long timeUsed = 5000 + (startTime - System.currentTimeMillis()); startTime = System.currentTimeMillis() + 5000; System.out.println("FPS: " + (Math.round(fps / (timeUsed / 1000.0) * 10) / 10.0) + ", Balls: " + ballCount); + System.out.println("\tAnimation: " + (animateTime / fps / 1000) + "us"); + animateTime = 0; fps = 0; } } @@ -582,8 +586,12 @@ if ( animate ) { final ByteBuffer buffer = animVBO.map(batchSize * (2 * 4)); + long t0 = System.nanoTime(); animate(transform, buffer.asFloatBuffer(), ballSize, ballIndex, batchSize, delta); + long t1 = System.nanoTime(); + animateTime += t1 - t0; + animVBO.unmap(); } Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutMapped.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -89,6 +89,8 @@ private int texBigID; private int texSmallID; + long animateTime; + private SpriteShootoutMapped() { } @@ -312,6 +314,8 @@ long timeUsed = 5000 + (startTime - System.currentTimeMillis()); startTime = System.currentTimeMillis() + 5000; System.out.println("FPS: " + (Math.round(fps / (timeUsed / 1000.0) * 10) / 10.0) + ", Balls: " + ballCount); + System.out.println("Animation: " + animateTime / fps); + animateTime = 0; fps = 0; } } @@ -414,8 +418,8 @@ public static class Sprite extends MappedObject { - public float x, dx; - public float y, dy; + public float dx, x; + public float dy, y; } @@ -527,8 +531,8 @@ final Sprite[] sprites = sprite.asArray(); final SpriteRender[] spritesRender = spriteRender.asArray(); for ( int b = ballIndex, r = 0, len = (ballIndex + batchSize); b < len; b++, r++ ) { + float dx = sprites[b].dx; float x = sprites[b].x; - float dx = sprites[b].dx; x += dx * delta; if ( x < ballRadius ) { @@ -539,12 +543,12 @@ dx = -dx; } + sprites[b].dx = dx; sprites[b].x = x; - sprites[b].dx = dx; spritesRender[r].x = x; + float dy = sprites[b].dy; float y = sprites[b].y; - float dy = sprites[b].dy; y += dy * delta; if ( y < ballRadius ) { @@ -555,8 +559,8 @@ dy = -dy; } + sprites[b].dy = dy; sprites[b].y = y; - sprites[b].dy = dy; spritesRender[r].y = y; } } @@ -654,8 +658,12 @@ if ( animate ) { final ByteBuffer buffer = animVBO.map(batchSize * (2 * 4)); + long t0 = System.nanoTime(); animate(sprites, SpriteRender.<SpriteRender>map(buffer), ballSize, ballIndex, batchSize, delta); + long t1 = System.nanoTime(); + animateTime += t1 - t0; + animVBO.unmap(); } Added: trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLinePad.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLinePad.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLinePad.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.util.mapped; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * When this annotation is used on a field, automatic cache-line-sized padding + * will be inserted around the field. This is useful in multi-threaded algorithms + * to avoid cache line false sharing. The annotation defaults to padding after + * the field, but can be changed to before or both before and after. It can be + * applied to both mapped object fields and POJO primitive fields. + * + * @author Spasi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface CacheLinePad { + + /** + * When true, cache-line padding will be inserted before the field. + * + * @return + */ + boolean before() default false; + + /** + * When true, cache-line padding will be inserted after the field. + * + * @return + */ + boolean after() default true; + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLineSize.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLineSize.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheLineSize.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -0,0 +1,141 @@ +package org.lwjgl.util.mapped; + +import org.lwjgl.LWJGLUtil; +import org.lwjgl.MemoryUtil; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.lwjgl.util.mapped.MappedHelper.*; + +/** + * This micro-benchmark tries to detect the CPU's cache line size. This is + * done by exploiting cache line false sharing in multi-threaded code: + * When 2 threads simultaneously access the same cache line (and at least + * 1 access is a write), performance drops considerably. We detect this + * performance drop while decreasing the memory padding in every test step. + * + * @author Spasi + */ +final class CacheLineSize { + + private CacheLineSize() { + } + + static int getCacheLineSize() { + final int THREADS = 2; + final int REPEATS = 100000 * THREADS; + final int LOCAL_REPEATS = REPEATS / THREADS; + + // Detection will start from CacheLineMaxSize bytes. + final int MAX_SIZE = LWJGLUtil.getPrivilegedInteger("org.lwjgl.util.mapped.CacheLineMaxSize", 1024) / 4; // in # of integers + // Detection will stop when the execution time increases by more than CacheLineTimeThreshold %. + final double TIME_THRESHOLD = 1.0 + LWJGLUtil.getPrivilegedInteger("org.lwjgl.util.mapped.CacheLineTimeThreshold", 50) / 100.0; + + final ExecutorService executorService = Executors.newFixedThreadPool(THREADS); + final ExecutorCompletionService<Long> completionService = new ExecutorCompletionService<Long>(executorService); + + try { + // We need to use a NIO buffer in order to guarantee memory alignment. + final IntBuffer memory = getMemory(MAX_SIZE); + + // -- WARMUP -- + + final int WARMUP = 10; + for ( int i = 0; i < WARMUP; i++ ) + doTest(THREADS, LOCAL_REPEATS, 0, memory, completionService); + + // -- CACHE LINE SIZE DETECTION -- + + long totalTime = 0; + int count = 0; + int cacheLineSize = 64; // fallback to the most common size these days + boolean found = false; + for ( int i = MAX_SIZE; i >= 1; i >>= 1 ) { + final long time = doTest(THREADS, LOCAL_REPEATS, i, memory, completionService); + if ( totalTime > 0 ) { // Ignore first run + final long avgTime = totalTime / count; + if ( (double)time / (double)avgTime > TIME_THRESHOLD ) { // Try to detect a noticeable jump in execution time + cacheLineSize = (i << 1) * 4; + found = true; + break; + } + } + totalTime += time; + count++; + } + + if ( LWJGLUtil.DEBUG ) { + if ( found ) + LWJGLUtil.log("Cache line size detected: " + cacheLineSize + " bytes"); + else + LWJGLUtil.log("Failed to detect cache line size, assuming " + cacheLineSize + " bytes"); + } + + return cacheLineSize; + } finally { + executorService.shutdown(); + } + } + + public static void main(String[] args) { + CacheUtil.getCacheLineSize(); + } + + static long memoryLoop(final int index, final int repeats, final IntBuffer memory, final int padding) { + final long address = MemoryUtil.getAddress(memory) + (index * padding * 4); + + final long time = System.nanoTime(); + for ( int i = 0; i < repeats; i++ ) { + // Use volatile access to avoid server VM optimizations. + ivput(ivget(address) + 1, address); + } + + return System.nanoTime() - time; + } + + private static IntBuffer getMemory(final int START_SIZE) { + final int PAGE_SIZE = MappedObjectUnsafe.INSTANCE.pageSize(); + + final ByteBuffer buffer = ByteBuffer.allocateDirect((START_SIZE * 4) + PAGE_SIZE).order(ByteOrder.nativeOrder()); + + // Align to page and, consequently, to cache line. Otherwise results will be inconsistent. + if ( MemoryUtil.getAddress(buffer) % PAGE_SIZE != 0 ) { + // Round up to page boundary + buffer.position(PAGE_SIZE - (int)(MemoryUtil.getAddress(buffer) & (PAGE_SIZE - 1))); + } + + return buffer.asIntBuffer(); + } + + private static long doTest(final int threads, final int repeats, final int padding, final IntBuffer memory, final ExecutorCompletionService<Long> completionService) { + for ( int i = 0; i < threads; i++ ) + submitTest(completionService, i, repeats, memory, padding); + return waitForResults(threads, completionService); + } + + private static void submitTest(final ExecutorCompletionService<Long> completionService, final int index, final int repeats, final IntBuffer memory, final int padding) { + completionService.submit(new Callable<Long>() { + public Long call() throws Exception { + return memoryLoop(index, repeats, memory, padding); + } + }); + } + + private static long waitForResults(final int count, final ExecutorCompletionService<Long> completionService) { + try { + long totalTime = 0; + for ( int i = 0; i < count; i++ ) + totalTime += completionService.take().get(); + return totalTime; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} \ No newline at end of file Added: trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheUtil.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheUtil.java (rev 0) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/CacheUtil.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002-2011 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.util.mapped; + +import org.lwjgl.LWJGLUtil; +import org.lwjgl.MemoryUtil; +import org.lwjgl.PointerBuffer; + +import java.nio.*; + +/** + * This class provides utility methods for allocating cache-line-aligned + * NIO buffers. The CPU cache line size is detected using a micro-benchmark + * that exploits the performation degredation that occurs when different + * threads write to different locations of the same cache line. The detection + * should be reasonably robust on both the server and client VM, but there + * are a few system properties that can be used to tune it. + * + * @author Spasi + */ +public final class CacheUtil { + + private static final int CACHE_LINE_SIZE; + + static { + final Integer size = LWJGLUtil.getPrivilegedInteger("org.lwjgl.util.mapped.CacheLineSize"); // forces a specific cache line size + + if ( size != null ) { + if ( size < 1 ) + throw new IllegalStateException("Invalid CacheLineSize specified: " + size); + CACHE_LINE_SIZE = size; + } else if ( Runtime.getRuntime().availableProcessors() == 1 ) { // We cannot use false sharing to detect it + /* + Spasi: + + I have implemented a single-threaded benchmark for this, but it requires + lots of memory allocations and could not tune it for both the client and + server VM. It's not a big deal anyway, 64 bytes should be ok for any + single-core CPU. + */ + if ( LWJGLUtil.DEBUG ) + LWJGLUtil.log("Cannot detect cache line size on single-core CPUs, assuming 64 bytes."); + CACHE_LINE_SIZE = 64; + } else + CACHE_LINE_SIZE = CacheLineSize.getCacheLineSize(); + } + + private CacheUtil() { + } + + /** + * Returns the CPU cache line size, in number of bytes. + * + * @return the cache line size + */ + public static int getCacheLineSize() { + return CACHE_LINE_SIZE; + } + + /** + * Construct a direct, native-ordered and cache-line-aligned bytebuffer with the specified size. + * + * @param size The size, in bytes + * + * @return a ByteBuffer + */ + public static ByteBuffer createByteBuffer(int size) { + ByteBuffer buffer = ByteBuffer.allocateDirect(size + CACHE_LINE_SIZE); + + // Align to cache line. + if ( MemoryUtil.getAddress(buffer) % CACHE_LINE_SIZE != 0 ) { + // Round up to cache line boundary + buffer.position(CACHE_LINE_SIZE - (int)(MemoryUtil.getAddress(buffer) & (CACHE_LINE_SIZE - 1))); + } + + buffer.limit(buffer.position() + size); + return buffer.slice().order(ByteOrder.nativeOrder()); + } + + /** + * Construct a direct, native-ordered and cache-line-aligned shortbuffer with the specified number + * of elements. + * + * @param size The size, in shorts + * + * @return a ShortBuffer + */ + public static ShortBuffer createShortBuffer(int size) { + return createByteBuffer(size << 1).asShortBuffer(); + } + + /** + * Construct a direct, native-ordered and cache-line-aligned charbuffer with the specified number + * of elements. + * + * @param size The size, in chars + * + * @return an CharBuffer + */ + public static CharBuffer createCharBuffer(int size) { + return createByteBuffer(size << 1).asCharBuffer(); + } + + /** + * Construct a direct, native-ordered and cache-line-aligned intbuffer with the specified number + * of elements. + * + * @param size The size, in ints + * + * @return an IntBuffer + */ + public static IntBuffer createIntBuffer(int size) { + return createByteBuffer(size << 2).asIntBuffer(); + } + + /** + * Construct a direct, native-ordered and cache-line-aligned longbuffer with the specified number + * of elements. + * + * @param size The size, in longs + * + * @return an LongBuffer + */ + public static LongBuffer createLongBuffer(int size) { + return createByteBuffer(size << 3).asLongBuffer(); + } + + /** + * Construct a direct, native-ordered and cache-line-aligned floatbuffer with the specified number + * of elements. + * + * @param size The size, in floats + * + * @return a FloatBuffer + */ + public static FloatBuffer createFloatBuffer(int size) { + return createByteBuffer(size << 2).asFloatBuffer(); + } + + /** + * Construct a direct, native-ordered and cache-line-aligned doublebuffer with the specified number + * of elements. + * + * @param size The size, in floats + * + * @return a FloatBuffer + */ + public static DoubleBuffer createDoubleBuffer(int size) { + return createByteBuffer(size << 3).asDoubleBuffer(); + } + + /** + * Construct a cache-line-aligned PointerBuffer with the specified number + * of elements. + * + * @param size The size, in memory addresses + * + * @return a PointerBuffer + */ + public static PointerBuffer createPointerBuffer(int size) { + return new PointerBuffer(createByteBuffer(size * PointerBuffer.getPointerSize())); + } + +} \ No newline at end of file Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedField.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -53,7 +53,7 @@ * * @return the field byte offset */ - long byteOffset(); + long byteOffset() default -1; /** * Specifies the field byte length. Required for {@link java.nio.ByteBuffer} fields. Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedHelper.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -68,7 +68,7 @@ mo.baseAddress = mo.viewAddress = addr; } - public static void checkAddress(MappedObject mapped, long viewAddress) { + public static void checkAddress(long viewAddress, MappedObject mapped) { mapped.checkAddress(viewAddress); } @@ -317,7 +317,7 @@ return INSTANCE.getLong(addr); } - public static long lget(MappedObject mapped, int fieldOffset) { + public static long jget(MappedObject mapped, int fieldOffset) { return INSTANCE.getLong(mapped.viewAddress + fieldOffset); } @@ -333,7 +333,7 @@ return INSTANCE.getLongVolatile(null, addr); } - public static long lvget(MappedObject mapped, int fieldOffset) { + public static long jvget(MappedObject mapped, int fieldOffset) { return INSTANCE.getLongVolatile(null, mapped.viewAddress + fieldOffset); } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectClassLoader.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -48,12 +48,8 @@ */ public class MappedObjectClassLoader extends URLClassLoader { - static final String MAPPEDOBJECT_PACKAGE_PREFIX; + static final String MAPPEDOBJECT_PACKAGE_PREFIX = MappedObjectClassLoader.class.getPackage().getName() + "."; - static { - MAPPEDOBJECT_PACKAGE_PREFIX = MappedObjectClassLoader.class.getPackage().getName() + "."; - } - static boolean FORKED; /** @@ -115,28 +111,28 @@ @Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { - if ( name.startsWith("java.") ) + if ( name.startsWith("java.") + || name.startsWith("javax.") + || name.startsWith("sun.") + || name.startsWith("sunw.") + || name.startsWith("org.objectweb.asm.") + ) return super.loadClass(name, resolve); - if ( name.startsWith("javax.") ) - return super.loadClass(name, resolve); - if ( name.startsWith("sun.") ) - return super.loadClass(name, resolve); - if ( name.startsWith("sunw.") ) - return super.loadClass(name, resolve); + final String className = name.replace('.', '/'); + final boolean inThisPackage = name.startsWith(MAPPEDOBJECT_PACKAGE_PREFIX); - if ( name.startsWith("org.objectweb.asm.") ) + if ( inThisPackage && ( + name.equals(MappedObjectClassLoader.class.getName()) + || name.equals((MappedObjectTransformer.class.getName())) + || name.equals((CacheUtil.class.getName())) + ) ) return super.loadClass(name, resolve); - if ( name.equals(MappedObjectClassLoader.class.getName()) || name.equals((MappedObjectTransformer.class.getName())) ) - return super.loadClass(name, resolve); - - String className = name.replace('.', '/'); - byte[] bytecode = readStream(this.getResourceAsStream(className.concat(".class"))); // Classes in this package do not get transformed, but need to go through here because we have transformed MappedObject. - if ( !(name.startsWith(MAPPEDOBJECT_PACKAGE_PREFIX) && name.substring(MAPPEDOBJECT_PACKAGE_PREFIX.length()).indexOf('.') == -1) ) { + if ( !(inThisPackage && name.substring(MAPPEDOBJECT_PACKAGE_PREFIX.length()).indexOf('.') == -1) ) { long t0 = System.nanoTime(); final byte[] newBytecode = MappedObjectTransformer.transformMappedAPI(className, bytecode); long t1 = System.nanoTime(); Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -31,6 +31,7 @@ */ package org.lwjgl.util.mapped; +import org.lwjgl.BufferUtils; import org.lwjgl.LWJGLUtil; import org.lwjgl.MemoryUtil; import org.objectweb.asm.*; @@ -79,6 +80,8 @@ static final String MAPPED_SET3_JVM = jvmClassName(MappedSet3.class); static final String MAPPED_SET4_JVM = jvmClassName(MappedSet4.class); + static final String CACHE_LINE_PAD_JVM = "L" + jvmClassName(CacheLinePad.class) + ";"; + // Public methods static final String VIEWADDRESS_METHOD_NAME = "getViewAddress"; static final String NEXT_METHOD_NAME = "next"; @@ -115,7 +118,7 @@ // => IADD // => PUTFIELD MyMappedType.view // - className_to_subtype.put(MAPPED_OBJECT_JVM, new MappedSubtypeInfo(MAPPED_OBJECT_JVM, null, -1, -1, -1)); + className_to_subtype.put(MAPPED_OBJECT_JVM, new MappedSubtypeInfo(MAPPED_OBJECT_JVM, null, -1, -1, -1, false)); } final String vmName = System.getProperty("java.vm.name"); @@ -145,30 +148,44 @@ final String className = jvmClassName(type); final Map<String, FieldInfo> fields = new HashMap<String, FieldInfo>(); - int advancingOffset = 0; long sizeof = 0; for ( Field field : type.getDeclaredFields() ) { - FieldInfo fieldInfo = registerField(mapped == null || mapped.autoGenerateOffsets(), className, advancingOffset, field); + FieldInfo fieldInfo = registerField(mapped == null || mapped.autoGenerateOffsets(), className, sizeof, field); if ( fieldInfo == null ) continue; fields.put(field.getName(), fieldInfo); - advancingOffset += fieldInfo.length; - sizeof = Math.max(sizeof, fieldInfo.offset + fieldInfo.length); + sizeof = Math.max(sizeof, fieldInfo.offset + fieldInfo.lengthPadded); } - final int align = mapped == null ? 4 : mapped.align(); - final int padding = mapped == null ? 0 : mapped.padding(); + int align = 4; + int padding = 0; + boolean cacheLinePadded = false; + if ( mapped != null ) { + align = mapped.align(); + if ( mapped.cacheLinePadding() ) { + if ( mapped.padding() != 0 ) + throw new ClassFormatError("Mapped type padding cannot be specified together with cacheLinePadding."); + + final int cacheLineMod = (int)(sizeof % CacheUtil.getCacheLineSize()); + if ( cacheLineMod != 0 ) + padding = CacheUtil.getCacheLineSize() - cacheLineMod; + + cacheLinePadded = true; + } else + padding = mapped.padding(); + } + sizeof += padding; - final MappedSubtypeInfo mappedType = new MappedSubtypeInfo(className, fields, (int)sizeof, align, padding); + final MappedSubtypeInfo mappedType = new MappedSubtypeInfo(className, fields, (int)sizeof, align, padding, cacheLinePadded); if ( className_to_subtype.put(className, mappedType) != null ) throw new InternalError("duplicate mapped type: " + mappedType.className); } - private static FieldInfo registerField(final boolean autoGenerateOffsets, final String className, int advancingOffset, final Field field) { + private static FieldInfo registerField(final boolean autoGenerateOffsets, final String className, long advancingOffset, final Field field) { if ( Modifier.isStatic(field.getModifiers()) ) // static fields are never mapped return null; @@ -188,7 +205,6 @@ throw new ClassFormatError("The volatile keyword is not supported for @Pointer or ByteBuffer fields. Volatile field found: " + className + "." + field.getName() + ": " + field.getType()); // quick hack - long byteOffset = meta == null ? advancingOffset : meta.byteOffset(); long byteLength; if ( field.getType() == long.class || field.getType() == double.class ) { if ( pointer == null ) @@ -213,10 +229,36 @@ if ( field.getType() != ByteBuffer.class && (advancingOffset % byteLength) != 0 ) throw new IllegalStateException("misaligned mapped type: " + className + "." + field.getName()); + CacheLinePad pad = field.getAnnotation(CacheLinePad.class); + + long byteOffset = advancingOffset; + if ( meta != null && meta.byteOffset() != -1 ) { + if ( meta.byteOffset() < 0 ) + throw new ClassFormatError("Invalid field byte offset: " + className + "." + field.getName() + " [byteOffset=" + meta.byteOffset() + "]"); + if ( pad != null ) + throw new ClassFormatError("A field byte offset cannot be specified together with cache-line padding: " + className + "." + field.getName()); + + byteOffset = meta.byteOffset(); + } + + long byteLengthPadded = byteLength; + if ( pad != null ) { + // Pad before + if ( pad.before() && byteOffset % CacheUtil.getCacheLineSize() != 0 ) + byteOffset += CacheUtil.getCacheLineSize() - (byteOffset & (CacheUtil.getCacheLineSize() - 1)); + + // Pad after + if ( pad.after() && (byteOffset + byteLength) % CacheUtil.getCacheLineSize() != 0 ) + byteLengthPadded += CacheUtil.getCacheLineSize() - (byteOffset + byteLength) % CacheUtil.getCacheLineSize(); + + assert !pad.before() || (byteOffset % CacheUtil.getCacheLineSize() == 0); + assert !pad.after() || ((byteOffset + byteLengthPadded) % CacheUtil.getCacheLineSize() == 0); + } + if ( PRINT_ACTIVITY ) LWJGLUtil.log(MappedObjectTransformer.class.getSimpleName() + ": " + className + "." + field.getName() + " [type=" + field.getType().getSimpleName() + ", offset=" + byteOffset + "]"); - return new FieldInfo(byteOffset, byteLength, Type.getType(field.getType()), Modifier.isVolatile(field.getModifiers()), pointer != null); + return new FieldInfo(byteOffset, byteLength, byteLengthPadded, Type.getType(field.getType()), Modifier.isVolatile(field.getModifiers()), pointer != null); } /** Removes final from methods that will be overriden by subclasses. */ @@ -318,17 +360,12 @@ mv.visitInsn(I2L); mv.visitInsn(LADD); if ( MappedObject.CHECKS ) { - mv.visitVarInsn(LSTORE, 2); + mv.visitInsn(DUP2); mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(LLOAD, 2); - mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "checkAddress", "(L" + MAPPED_OBJECT_JVM + ";J)V"); - mv.visitVarInsn(LLOAD, 2); + mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "checkAddress", "(JL" + MAPPED_OBJECT_JVM + ";)V"); } mv.visitInsn(LRETURN); - if ( MappedObject.CHECKS ) - mv.visitMaxs(3, 4); - else - mv.visitMaxs(3, 2); + mv.visitMaxs(3, 2); mv.visitEnd(); } @@ -477,7 +514,71 @@ return null; } - return super.visitField(access, name, desc, signature, value); + if ( (access & ACC_STATIC) == 0 ) { + return new FieldNode(access, name, desc, signature, value) { + public void visitEnd() { + if ( visibleAnnotations == null ) { // early-out + accept(cv); + return; + } + + boolean before = false; + boolean after = false; + int byteLength = 0; + for ( AnnotationNode pad : visibleAnnotations ) { + if ( CACHE_LINE_PAD_JVM.equals(pad.desc) ) { + if ( "J".equals(desc) || "D".equals(desc) ) + byteLength = 8; + else if ( "I".equals(desc) || "F".equals(desc) ) + byteLength = 4; + else if ( "S".equals(desc) || "C".equals(desc) ) + byteLength = 2; + else if ( "B".equals(desc) || "Z".equals(desc) ) + byteLength = 1; + else + throw new ClassFormatError("The @CacheLinePad annotation cannot be used on non-primitive fields: " + className + "." + name); + + transformed = true; + + after = true; + if ( pad.values != null ) { + for ( int i = 0; i < pad.values.size(); i += 2 ) { + final boolean value = pad.values.get(i + 1).equals(Boolean.TRUE); + if ( "before".equals(pad.values.get(i)) ) + before = value; + else + after = value; + } + } + break; + } + } + + /* + We make the fields public to force the JVM to keep the fields in the object. + Instead of using only longs or integers, we use the same type as the original + field. That's because modern JVMs usually reorder fields by type: + longs, then doubles, then integers, then booleans, etc. This way it's more + likely that the padding will work as expected. + */ + + if ( before ) { + final int count = CacheUtil.getCacheLineSize() / byteLength - 1; + for ( int i = count; i >= 1; i-- ) + cv.visitField(access | ACC_PUBLIC | ACC_SYNTHETIC, name + "$PAD_" + i, desc, signature, null); + } + + accept(cv); + + if ( after ) { + final int count = CacheUtil.getCacheLineSize() / byteLength - 1; + for ( int i = 1; i <= count; i++ ) + cv.visitField(access | ACC_PUBLIC | ACC_SYNTHETIC, name + "$PAD" + i, desc, signature, null); + } + } + }; + } else + return super.visitField(access, name, desc, signature, value); } @Override @@ -762,7 +863,7 @@ // stack: sizeof, count trg.add(new InsnNode(IMUL)); // stack: bytes - trg.add(new MethodInsnNode(INVOKESTATIC, jvmClassName(ByteBuffer.class), "allocateDirect", "(I)L" + jvmClassName(ByteBuffer.class) + ";")); + trg.add(new MethodInsnNode(INVOKESTATIC, mappedType.cacheLinePadded ? jvmClassName(CacheUtil.class) : jvmClassName(BufferUtils.class), "createByteBuffer", "(I)L" + jvmClassName(ByteBuffer.class) + ";")); // stack: buffer } else if ( mapDirectMethod ) { // stack: capacity, address @@ -1061,13 +1162,15 @@ final long offset; final long length; + final long lengthPadded; final Type type; final boolean isVolatile; final boolean isPointer; - FieldInfo(final long offset, final long length, final Type type, final boolean isVolatile, final boolean isPointer) { + FieldInfo(final long offset, final long length, final long lengthPadded, final Type type, final boolean isVolatile, final boolean isPointer) { this.offset = offset; this.length = length; + this.lengthPadded = lengthPadded; this.type = type; this.isVolatile = isVolatile; this.isPointer = isPointer; @@ -1083,14 +1186,15 @@ final String className; - final int sizeof; - final int sizeof_shift; - final int align; - final int padding; + final int sizeof; + final int sizeof_shift; + final int align; + final int padding; + final boolean cacheLinePadded; final Map<String, FieldInfo> fields; - MappedSubtypeInfo(String className, Map<String, FieldInfo> fields, int sizeof, int align, int padding) { + MappedSubtypeInfo(String className, Map<String, FieldInfo> fields, int sizeof, int align, int padding, final boolean cacheLinePadded) { this.className = className; this.sizeof = sizeof; @@ -1100,6 +1204,7 @@ this.sizeof_shift = 0; this.align = align; this.padding = padding; + this.cacheLinePadded = cacheLinePadded; this.fields = fields; } Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectUnsafe.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectUnsafe.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedObjectUnsafe.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -34,6 +34,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import sun.misc.Unsafe; @@ -55,7 +56,7 @@ if ( address <= 0L || capacity < 0 ) throw new IllegalStateException("you almost crashed the jvm"); - ByteBuffer buffer = global.duplicate(); + ByteBuffer buffer = global.duplicate().order(ByteOrder.nativeOrder()); INSTANCE.putLong(buffer, BUFFER_ADDRESS_OFFSET, address); INSTANCE.putInt(buffer, BUFFER_CAPACITY_OFFSET, capacity); buffer.position(0); Modified: trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java 2011-08-08 17:02:20 UTC (rev 3607) +++ trunk/LWJGL/src/java/org/lwjgl/util/mapped/MappedType.java 2011-08-10 16:05:46 UTC (rev 3608) @@ -61,13 +61,28 @@ /** * The number of bytes to add to the total byte size. - * SIZEOF will be calculated as <code>SIZEOF = max(field_offset + field_length) + padding</code> + * SIZEOF will be calculated as <code>SIZEOF = max(field_offset + field_length) + padding</code>. + * <p/> + * Cannot be used with {@link #cacheLinePadding()}. * * @return the padding amount */ int padding() default 0; /** + * When true, SIZEOF will be increased (if necessary) so that it's a multiple of the CPU cache line size. + * Additionally, {@link MappedObject#malloc(int)} on the mapped object type will automatically use + * {@link CacheUtil#createByteBuffer(int)} instead of the unaligned {@link org.lwjgl.BufferUtils#createByteBuffer(int)}. + * <p/> + * Cannot be used with {@link #padding()}. + * + * @return if cache-line padding should be applied + * + * @see CacheUtil + */ + boolean cacheLinePadding() default false; + + /** * The mapped data memory alignment, in bytes. * * @return the memory alignment This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |