diff options
author | Sven Gothel <[email protected]> | 2010-11-06 06:26:56 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-11-06 06:26:56 +0100 |
commit | d1a03d19398960d6e34232f29a30f1d569fba2a7 (patch) | |
tree | 92f90bb3c3c7587910272ff1235c3980b097cfcd /src/jogl/classes/com | |
parent | eab5a8ded0b3ee13cdc66bddb369439e0871bae7 (diff) |
Fix buffer size: 64bit GLBufferSizeTracker, hash over addr+size, save fail-fast hash cache, ..
Relates to GlueGen 6b6b9b3b81cdc85b7260664ebec547756a6be5d7, branch sgothel_wip_fixes01.
Memory object size is ptrdiff_t, hence long (64bit).
The hash value must include size as well, otherwise boundaries cannot be verified. (security)
Double check hash collisions while adding a new MemoryObject.
Diffstat (limited to 'src/jogl/classes/com')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java | 27 | ||||
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/impl/MemoryObject.java | 142 |
2 files changed, 158 insertions, 11 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java index ceabd3910..6ebda222b 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -40,7 +41,7 @@ package com.jogamp.opengl.impl; import javax.media.opengl.*; -import com.jogamp.common.util.IntIntHashMap; +import com.jogamp.common.util.IntLongHashMap; /** * Tracks as closely as possible the sizes of allocated OpenGL buffer @@ -93,17 +94,17 @@ public class GLBufferSizeTracker { // objects, which is probably sub-optimal. The expected usage // pattern of buffer objects indicates that the fact that this map // never shrinks is probably not that bad. - private IntIntHashMap bufferSizeMap; + private IntLongHashMap bufferSizeMap; protected static final boolean DEBUG = Debug.debug("GLStatusTracker"); public GLBufferSizeTracker() { - bufferSizeMap = new IntIntHashMap(); + bufferSizeMap = new IntLongHashMap(); bufferSizeMap.setKeyNotFoundValue(-1); } public void setBufferSize(GLBufferStateTracker bufferStateTracker, - int target, GL caller, int size) { + int target, GL caller, long size) { // Need to do some similar queries to getBufferSize below int buffer = bufferStateTracker.getBoundBufferObject(target, caller); boolean valid = bufferStateTracker.isBoundBufferObjectKnown(target); @@ -125,11 +126,11 @@ public class GLBufferSizeTracker { // left to do except drop this piece of information on the floor. } - public void setDirectStateBufferSize(int buffer, GL caller, int size) { + public void setDirectStateBufferSize(int buffer, GL caller, long size) { bufferSizeMap.put(buffer, size); } - public int getBufferSize(GLBufferStateTracker bufferStateTracker, + public long getBufferSize(GLBufferStateTracker bufferStateTracker, int target, GL caller) { // See whether we know what buffer is currently bound to the given @@ -149,25 +150,29 @@ public class GLBufferSizeTracker { return getBufferSizeImpl(target, buffer, caller); } // We don't know what's going on in this case; query the GL for an answer + // FIXME: both functions return 'int' types, which is not suitable, + // since buffer lenght is 64bit ? int[] tmp = new int[1]; caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0); if (DEBUG) { System.err.println("GLBufferSizeTracker.getBufferSize(): no cached buffer information"); } - return tmp[0]; + return (long) tmp[0]; } - public int getDirectStateBufferSize(int buffer, GL caller) { + public long getDirectStateBufferSize(int buffer, GL caller) { return getBufferSizeImpl(0, buffer, caller); } - private int getBufferSizeImpl(int target, int buffer, GL caller) { + private long getBufferSizeImpl(int target, int buffer, GL caller) { // See whether we know the size of this buffer object; at this // point we almost certainly should if the application is // written correctly - int sz = bufferSizeMap.get(buffer); + long sz = bufferSizeMap.get(buffer); if (0 > sz) { // For robustness, try to query this value from the GL as we used to + // FIXME: both functions return 'int' types, which is not suitable, + // since buffer lenght is 64bit ? int[] tmp = new int[1]; if(0==target) { // DirectState .. @@ -186,7 +191,7 @@ public class GLBufferSizeTracker { " was zero; probably application error"); } // Assume we just don't know what's happening - sz = tmp[0]; + sz = (long) tmp[0]; bufferSizeMap.put(buffer, sz); if (DEBUG) { System.err.println("GLBufferSizeTracker.getBufferSize(): made slow query to cache size " + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/MemoryObject.java b/src/jogl/classes/com/jogamp/opengl/impl/MemoryObject.java new file mode 100644 index 000000000..a691a6156 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/MemoryObject.java @@ -0,0 +1,142 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl; + +import java.nio.ByteBuffer; +import java.util.HashMap; + +/** + * + */ +public class MemoryObject { + private long addr; + private long size; + private int hash32; + private ByteBuffer buffer=null; + + public MemoryObject(long addr, long size) { + this.addr = addr; + this.size = size; + this.hash32 = getHash32(addr, size); + } + + public void setBuffer(ByteBuffer buffer) { + this.buffer = buffer; + } + + public ByteBuffer getBuffer() { + return this.buffer; + } + + /** + * @return the 32bit hash value generated via {@link #getHash32(long, long)} + */ + public int hashCode() { + return hash32; + } + + /** + * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br> + * + * @return true of reference is equal or <code>obj</code> is of type <code>MemoryObject</code> + * and <code>addr</code> and <code>size</code> is equal.<br> + */ + public boolean equals(Object obj) { + if(this == obj) { return true; } + if(obj instanceof MemoryObject) { + MemoryObject m = (MemoryObject) obj; + return addr == m.addr && size == m.size ; + } + return false; + } + + /** + * Generates a 32bit hash value by <code>addr</code> and <code>size</code>.<br> + * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br> + */ + public static int getHash32(long addr, long size) { + // avoid xor collisions of eg low/high parts + // 31 * x == (x << 5) - x + int hash = 31 + (int) addr ; // lo addr + hash = ((hash << 5) - hash) + (int) ( addr >>> 32 ) ; // hi addr + hash = ((hash << 5) - hash) + (int) size ; // lo size + hash = ((hash << 5) - hash) + (int) ( size >>> 32 ) ; // hi size + + return hash; + } + + /** + * Generates a 64bit hash value by <code>addr</code> and <code>size</code>.<br> + * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br> + */ + public static long getHash64(long addr, long size) { + // 31 * x == (x << 5) - x + final long hash = 31 + addr; + return ((hash << 5) - hash) + size; + } + + public String toString() { + return "MemoryObject[addr 0x"+Long.toHexString(addr)+", size 0x"+Long.toHexString(size)+", hash32: 0x"+Integer.toHexString(hash32)+"]"; + } + + /** + * Verifies the hash map operation, ie + * <ul> + * <li>slow add: if !map.contains(obj0), the values are verified (slow)</li> + * <li>fast get: if map.contains(obj0), the mapped value is compared with equals (fast) </li> + * </ul> + * In case the above verification fails, a RuntimeException is thrown.<br> + * In such case the calculation of the hash value should either be tuned,<br> + * or we just cannot use hash mapping.<br> + * + * @param map the identity HashMap mapping MemoryObject to MemoryObject + * @param obj0 the MemoryObject to get or add in the map + * @return either the already mapped one where <code>obj0</code> != <code>return</code>, + * or the added <code>obj0</code> == <code>return</code>. + * @throws RuntimeException if hash collision occurs + */ + public static MemoryObject getOrAddSafe(HashMap/*<MemoryObject,MemoryObject>*/ map, MemoryObject obj0) { + MemoryObject obj1 = (MemoryObject) map.get(obj0); // get identity (fast) + if(null == obj1) { + // verify hash collision (slow) + if( map.values().contains(obj0) ) { + throw new RuntimeException("Hash collision, hash !exist, but in values: "+obj0); + } + map.put(obj0, obj0); + obj1 = obj0; + } else { + // verify hash collision (ok) + if( !obj1.equals(obj0) ) { + throw new RuntimeException("Hash collision, hash equals, but objects not: query "+obj0+" != contained "+obj1); + } + } + return obj1; + } + +}
\ No newline at end of file |