Modified so that read-only operations will not
clobber each other if done from other threads and provided a way to safely access the whole buffer if only read-only access is required. Round 1 of a fix for GeometryBatchFactory... git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9098 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
0f41e1fee1
commit
606b676d69
@ -374,12 +374,62 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the raw internal data buffer used by this VertexBuffer.
|
||||||
|
* This buffer is not safe to call from multiple threads since buffers
|
||||||
|
* have their own internal position state that cannot be shared.
|
||||||
|
* Call getData().duplicate(), getData().asReadOnlyBuffer(), or
|
||||||
|
* the more convenient getDataReadOnly() if the buffer may be accessed
|
||||||
|
* from multiple threads.
|
||||||
|
*
|
||||||
* @return A native buffer, in the specified {@link Format format}.
|
* @return A native buffer, in the specified {@link Format format}.
|
||||||
*/
|
*/
|
||||||
public Buffer getData(){
|
public Buffer getData(){
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a safe read-only version of this VertexBuffer's data. The
|
||||||
|
* contents of the buffer will reflect whatever changes are made on
|
||||||
|
* other threads (eventually) but these should not be used in that way.
|
||||||
|
* This method provides a read-only buffer that is safe to _read_ from
|
||||||
|
* a separate thread since it has its own book-keeping state (position, limit, etc.)
|
||||||
|
*
|
||||||
|
* @return A rewound native buffer in the specified {@link Format format}
|
||||||
|
* that is safe to read from a separate thread from other readers.
|
||||||
|
*/
|
||||||
|
public Buffer getDataReadOnly() {
|
||||||
|
|
||||||
|
if (data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a read-only duplicate(). Note: this does not copy
|
||||||
|
// the underlying memory, it just creates a new read-only wrapper
|
||||||
|
// with its own buffer position state.
|
||||||
|
|
||||||
|
// Unfortunately, this is not 100% straight forward since Buffer
|
||||||
|
// does not have an asReadOnlyBuffer() method.
|
||||||
|
Buffer result;
|
||||||
|
if( data instanceof ByteBuffer ) {
|
||||||
|
result = ((ByteBuffer)data).asReadOnlyBuffer();
|
||||||
|
} else if( data instanceof FloatBuffer ) {
|
||||||
|
result = ((FloatBuffer)data).asReadOnlyBuffer();
|
||||||
|
} else if( data instanceof ShortBuffer ) {
|
||||||
|
result = ((ShortBuffer)data).asReadOnlyBuffer();
|
||||||
|
} else if( data instanceof IntBuffer ) {
|
||||||
|
result = ((IntBuffer)data).asReadOnlyBuffer();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException( "Cannot get read-only view of buffer type:" + data );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the caller gets a consistent view since we may
|
||||||
|
// have grabbed this buffer while another thread was reading
|
||||||
|
// the raw data.
|
||||||
|
result.rewind();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The usage of this buffer. See {@link Usage} for more
|
* @return The usage of this buffer. See {@link Usage} for more
|
||||||
* information.
|
* information.
|
||||||
@ -470,6 +520,9 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
if (usage == null || format == null || data == null)
|
if (usage == null || format == null || data == null)
|
||||||
throw new IllegalArgumentException("None of the arguments can be null");
|
throw new IllegalArgumentException("None of the arguments can be null");
|
||||||
|
|
||||||
|
if (data.isReadOnly())
|
||||||
|
throw new IllegalArgumentException( "VertexBuffer data cannot be read-only." );
|
||||||
|
|
||||||
if (components < 1 || components > 4)
|
if (components < 1 || components > 4)
|
||||||
throw new IllegalArgumentException("components must be between 1 and 4");
|
throw new IllegalArgumentException("components must be between 1 and 4");
|
||||||
|
|
||||||
@ -499,6 +552,12 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
// request to update data is okay
|
// request to update data is okay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the data buffer is read-only which is a sign
|
||||||
|
// of a bug on the part of the caller
|
||||||
|
if (data != null && data.isReadOnly()) {
|
||||||
|
throw new IllegalArgumentException( "VertexBuffer data cannot be read-only." );
|
||||||
|
}
|
||||||
|
|
||||||
// will force renderer to call glBufferData again
|
// will force renderer to call glBufferData again
|
||||||
if (data != null && (this.data.getClass() != data.getClass() || data.limit() != lastLimit)){
|
if (data != null && (this.data.getClass() != data.getClass() || data.limit() != lastLimit)){
|
||||||
dataSizeChanged = true;
|
dataSizeChanged = true;
|
||||||
@ -669,24 +728,24 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
elementPos *= 2;
|
elementPos *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.clear();
|
Buffer srcData = getDataReadOnly();
|
||||||
|
|
||||||
switch (format){
|
switch (format){
|
||||||
case Byte:
|
case Byte:
|
||||||
case UnsignedByte:
|
case UnsignedByte:
|
||||||
case Half:
|
case Half:
|
||||||
ByteBuffer bin = (ByteBuffer) data;
|
ByteBuffer bin = (ByteBuffer) srcData;
|
||||||
return bin.get(inPos + elementPos);
|
return bin.get(inPos + elementPos);
|
||||||
case Short:
|
case Short:
|
||||||
case UnsignedShort:
|
case UnsignedShort:
|
||||||
ShortBuffer sin = (ShortBuffer) data;
|
ShortBuffer sin = (ShortBuffer) srcData;
|
||||||
return sin.get(inPos + elementPos);
|
return sin.get(inPos + elementPos);
|
||||||
case Int:
|
case Int:
|
||||||
case UnsignedInt:
|
case UnsignedInt:
|
||||||
IntBuffer iin = (IntBuffer) data;
|
IntBuffer iin = (IntBuffer) srcData;
|
||||||
return iin.get(inPos + elementPos);
|
return iin.get(inPos + elementPos);
|
||||||
case Float:
|
case Float:
|
||||||
FloatBuffer fin = (FloatBuffer) data;
|
FloatBuffer fin = (FloatBuffer) srcData;
|
||||||
return fin.get(inPos + elementPos);
|
return fin.get(inPos + elementPos);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unrecognized buffer format: "+format);
|
throw new UnsupportedOperationException("Unrecognized buffer format: "+format);
|
||||||
@ -718,14 +777,17 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
elementSz *= 2;
|
elementSz *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.clear();
|
// Make sure to grab a read-only copy in case some other
|
||||||
|
// thread is also accessing the buffer and messing with its
|
||||||
|
// position()
|
||||||
|
Buffer srcData = getDataReadOnly();
|
||||||
outVb.data.clear();
|
outVb.data.clear();
|
||||||
|
|
||||||
switch (format){
|
switch (format){
|
||||||
case Byte:
|
case Byte:
|
||||||
case UnsignedByte:
|
case UnsignedByte:
|
||||||
case Half:
|
case Half:
|
||||||
ByteBuffer bin = (ByteBuffer) data;
|
ByteBuffer bin = (ByteBuffer) srcData;
|
||||||
ByteBuffer bout = (ByteBuffer) outVb.data;
|
ByteBuffer bout = (ByteBuffer) outVb.data;
|
||||||
bin.position(inPos).limit(inPos + elementSz);
|
bin.position(inPos).limit(inPos + elementSz);
|
||||||
bout.position(outPos).limit(outPos + elementSz);
|
bout.position(outPos).limit(outPos + elementSz);
|
||||||
@ -733,7 +795,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
break;
|
break;
|
||||||
case Short:
|
case Short:
|
||||||
case UnsignedShort:
|
case UnsignedShort:
|
||||||
ShortBuffer sin = (ShortBuffer) data;
|
ShortBuffer sin = (ShortBuffer) srcData;
|
||||||
ShortBuffer sout = (ShortBuffer) outVb.data;
|
ShortBuffer sout = (ShortBuffer) outVb.data;
|
||||||
sin.position(inPos).limit(inPos + elementSz);
|
sin.position(inPos).limit(inPos + elementSz);
|
||||||
sout.position(outPos).limit(outPos + elementSz);
|
sout.position(outPos).limit(outPos + elementSz);
|
||||||
@ -741,14 +803,14 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
break;
|
break;
|
||||||
case Int:
|
case Int:
|
||||||
case UnsignedInt:
|
case UnsignedInt:
|
||||||
IntBuffer iin = (IntBuffer) data;
|
IntBuffer iin = (IntBuffer) srcData;
|
||||||
IntBuffer iout = (IntBuffer) outVb.data;
|
IntBuffer iout = (IntBuffer) outVb.data;
|
||||||
iin.position(inPos).limit(inPos + elementSz);
|
iin.position(inPos).limit(inPos + elementSz);
|
||||||
iout.position(outPos).limit(outPos + elementSz);
|
iout.position(outPos).limit(outPos + elementSz);
|
||||||
iout.put(iin);
|
iout.put(iin);
|
||||||
break;
|
break;
|
||||||
case Float:
|
case Float:
|
||||||
FloatBuffer fin = (FloatBuffer) data;
|
FloatBuffer fin = (FloatBuffer) srcData;
|
||||||
FloatBuffer fout = (FloatBuffer) outVb.data;
|
FloatBuffer fout = (FloatBuffer) outVb.data;
|
||||||
fin.position(inPos).limit(inPos + elementSz);
|
fin.position(inPos).limit(inPos + elementSz);
|
||||||
fout.position(outPos).limit(outPos + elementSz);
|
fout.position(outPos).limit(outPos + elementSz);
|
||||||
@ -758,7 +820,6 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
throw new UnsupportedOperationException("Unrecognized buffer format: "+format);
|
throw new UnsupportedOperationException("Unrecognized buffer format: "+format);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.clear();
|
|
||||||
outVb.data.clear();
|
outVb.data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,8 +868,13 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
VertexBuffer vb = (VertexBuffer) super.clone();
|
VertexBuffer vb = (VertexBuffer) super.clone();
|
||||||
vb.handleRef = new Object();
|
vb.handleRef = new Object();
|
||||||
vb.id = -1;
|
vb.id = -1;
|
||||||
if (data != null)
|
if (data != null) {
|
||||||
vb.updateData(BufferUtils.clone(data));
|
// Make sure to pass a read-only buffer to clone so that
|
||||||
|
// the position information doesn't get clobbered by another
|
||||||
|
// reading thread during cloning (and vice versa) since this is
|
||||||
|
// a purely read-only operation.
|
||||||
|
vb.updateData(BufferUtils.clone(getDataReadOnly()));
|
||||||
|
}
|
||||||
|
|
||||||
return vb;
|
return vb;
|
||||||
}
|
}
|
||||||
@ -824,7 +890,12 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
VertexBuffer vb = new VertexBuffer(overrideType);
|
VertexBuffer vb = new VertexBuffer(overrideType);
|
||||||
vb.components = components;
|
vb.components = components;
|
||||||
vb.componentsLength = componentsLength;
|
vb.componentsLength = componentsLength;
|
||||||
vb.data = BufferUtils.clone(data);
|
|
||||||
|
// Make sure to pass a read-only buffer to clone so that
|
||||||
|
// the position information doesn't get clobbered by another
|
||||||
|
// reading thread during cloning (and vice versa) since this is
|
||||||
|
// a purely read-only operation.
|
||||||
|
vb.data = BufferUtils.clone(getDataReadOnly());
|
||||||
vb.format = format;
|
vb.format = format;
|
||||||
vb.handleRef = new Object();
|
vb.handleRef = new Object();
|
||||||
vb.id = -1;
|
vb.id = -1;
|
||||||
@ -876,22 +947,23 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
|
|||||||
oc.write(stride, "stride", 0);
|
oc.write(stride, "stride", 0);
|
||||||
|
|
||||||
String dataName = "data" + format.name();
|
String dataName = "data" + format.name();
|
||||||
|
Buffer roData = getDataReadOnly();
|
||||||
switch (format){
|
switch (format){
|
||||||
case Float:
|
case Float:
|
||||||
oc.write((FloatBuffer) data, dataName, null);
|
oc.write((FloatBuffer) roData, dataName, null);
|
||||||
break;
|
break;
|
||||||
case Short:
|
case Short:
|
||||||
case UnsignedShort:
|
case UnsignedShort:
|
||||||
oc.write((ShortBuffer) data, dataName, null);
|
oc.write((ShortBuffer) roData, dataName, null);
|
||||||
break;
|
break;
|
||||||
case UnsignedByte:
|
case UnsignedByte:
|
||||||
case Byte:
|
case Byte:
|
||||||
case Half:
|
case Half:
|
||||||
oc.write((ByteBuffer) data, dataName, null);
|
oc.write((ByteBuffer) roData, dataName, null);
|
||||||
break;
|
break;
|
||||||
case Int:
|
case Int:
|
||||||
case UnsignedInt:
|
case UnsignedInt:
|
||||||
oc.write((IntBuffer) data, dataName, null);
|
oc.write((IntBuffer) roData, dataName, null);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IOException("Unsupported export buffer format: "+format);
|
throw new IOException("Unsupported export buffer format: "+format);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user