2004-06-12 22:28:34 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2002-2004 LWJGL Project
|
|
|
|
|
* All rights reserved.
|
2004-02-04 01:17:13 +01:00
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
2004-06-12 22:28:34 +02:00
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
|
* met:
|
2004-02-04 01:17:13 +01:00
|
|
|
*
|
2004-06-12 22:28:34 +02:00
|
|
|
* * 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.
|
2004-02-04 01:17:13 +01:00
|
|
|
*/
|
|
|
|
|
package org.lwjgl.opengl;
|
2004-07-26 15:36:04 +02:00
|
|
|
|
2004-02-04 01:17:13 +01:00
|
|
|
import java.nio.Buffer;
|
2004-07-26 15:36:04 +02:00
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
|
import java.nio.ShortBuffer;
|
|
|
|
|
import java.nio.FloatBuffer;
|
|
|
|
|
import java.nio.IntBuffer;
|
|
|
|
|
import java.nio.DoubleBuffer;
|
2004-04-03 23:08:23 +02:00
|
|
|
|
2004-02-04 01:17:13 +01:00
|
|
|
/**
|
2004-02-15 20:41:51 +01:00
|
|
|
* $Id$ A class to
|
|
|
|
|
* check buffer boundaries in GL methods. Many GL methods read data from the GL
|
|
|
|
|
* into a native Buffer at its current position. If there is unsufficient space
|
|
|
|
|
* in the buffer when the call is made then a buffer overflow would otherwise
|
|
|
|
|
* occur and cause unexpected behaviour, a crash, or worse, a security risk.
|
|
|
|
|
* Therefore in those methods where GL reads data back into a buffer, we will
|
|
|
|
|
* call a bounds check method from this class to ensure that there is
|
|
|
|
|
* sufficient space in the buffer.
|
|
|
|
|
*
|
2004-02-04 01:17:13 +01:00
|
|
|
* Thrown by the debug build library of the LWJGL if any OpenGL operation
|
|
|
|
|
* causes an error.
|
|
|
|
|
*
|
|
|
|
|
* @author cix_foo <cix_foo@users.sourceforge.net>
|
|
|
|
|
* @version $Revision$
|
|
|
|
|
*/
|
2004-02-08 21:41:00 +01:00
|
|
|
class BufferChecks {
|
2004-02-04 01:17:13 +01:00
|
|
|
/** Static methods only! */
|
2004-02-15 20:41:51 +01:00
|
|
|
private BufferChecks() {
|
2004-02-04 01:17:13 +01:00
|
|
|
}
|
2004-02-18 23:31:00 +01:00
|
|
|
|
2004-02-15 20:41:51 +01:00
|
|
|
/**
|
2004-02-18 23:31:00 +01:00
|
|
|
* Default buffer size for most buffer checks.
|
2004-02-15 20:41:51 +01:00
|
|
|
*/
|
2004-02-18 23:31:00 +01:00
|
|
|
private static final int DEFAULT_BUFFER_SIZE = 4;
|
|
|
|
|
|
2004-07-26 15:36:04 +02:00
|
|
|
/**
|
|
|
|
|
* Helper methods to ensure a buffer is direct or null.
|
|
|
|
|
*/
|
|
|
|
|
static void checkDirectOrNull(ByteBuffer buf) {
|
|
|
|
|
if (buf != null) {
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirectOrNull(FloatBuffer buf) {
|
|
|
|
|
if (buf != null) {
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirectOrNull(ShortBuffer buf) {
|
|
|
|
|
if (buf != null) {
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirectOrNull(IntBuffer buf) {
|
|
|
|
|
if (buf != null) {
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirectOrNull(DoubleBuffer buf) {
|
|
|
|
|
if (buf != null) {
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper methods to ensure a buffer is direct (and, implicitly, non-null).
|
|
|
|
|
*/
|
|
|
|
|
static void checkDirectBuffer(Buffer buf) {
|
|
|
|
|
if (buf instanceof ByteBuffer)
|
|
|
|
|
checkDirect((ByteBuffer)buf);
|
|
|
|
|
else if (buf instanceof ShortBuffer)
|
|
|
|
|
checkDirect((ShortBuffer)buf);
|
|
|
|
|
else if (buf instanceof IntBuffer)
|
|
|
|
|
checkDirect((IntBuffer)buf);
|
|
|
|
|
else if (buf instanceof FloatBuffer)
|
|
|
|
|
checkDirect((FloatBuffer)buf);
|
|
|
|
|
else if (buf instanceof DoubleBuffer)
|
|
|
|
|
checkDirect((DoubleBuffer)buf);
|
|
|
|
|
else
|
|
|
|
|
throw new IllegalStateException("Unsupported buffer type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirect(ByteBuffer buf) {
|
|
|
|
|
if (!buf.isDirect()) {
|
|
|
|
|
throw new IllegalArgumentException("ByteBuffer is not direct");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirect(FloatBuffer buf) {
|
|
|
|
|
if (!buf.isDirect()) {
|
|
|
|
|
throw new IllegalArgumentException("FloatBuffer is not direct");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirect(ShortBuffer buf) {
|
|
|
|
|
if (!buf.isDirect()) {
|
|
|
|
|
throw new IllegalArgumentException("ShortBuffer is not direct");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirect(IntBuffer buf) {
|
|
|
|
|
if (!buf.isDirect()) {
|
|
|
|
|
throw new IllegalArgumentException("IntBuffer is not direct");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkDirect(DoubleBuffer buf) {
|
|
|
|
|
if (!buf.isDirect()) {
|
|
|
|
|
throw new IllegalArgumentException("IntBuffer is not direct");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-04 01:17:13 +01:00
|
|
|
/**
|
2004-02-15 20:41:51 +01:00
|
|
|
* Helper method to ensure a buffer is big enough to receive data from a
|
2004-02-18 23:31:00 +01:00
|
|
|
* glGet* operation.
|
2004-02-15 20:41:51 +01:00
|
|
|
*
|
|
|
|
|
* @param buf
|
|
|
|
|
* The buffer to check
|
2004-02-18 23:31:00 +01:00
|
|
|
* @param size
|
|
|
|
|
* The minimum buffer size
|
2004-02-15 20:41:51 +01:00
|
|
|
* @throws BufferOverflowException
|
2004-02-04 01:17:13 +01:00
|
|
|
*/
|
2004-07-26 15:36:04 +02:00
|
|
|
private static void checkBufferSize(Buffer buf, int size) {
|
2004-02-18 23:31:00 +01:00
|
|
|
if (buf.remaining() < size) {
|
2004-03-29 21:09:10 +02:00
|
|
|
throw new IllegalArgumentException("Number of remaining buffer elements is " + buf.remaining() + ", must be at least " + size);
|
2004-02-04 01:17:13 +01:00
|
|
|
}
|
|
|
|
|
}
|
2004-07-26 15:36:04 +02:00
|
|
|
|
|
|
|
|
static void checkBuffer(ByteBuffer buf, int size) {
|
|
|
|
|
checkBufferSize(buf, size);
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(IntBuffer buf, int size) {
|
|
|
|
|
checkBufferSize(buf, size);
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(ShortBuffer buf, int size) {
|
|
|
|
|
checkBufferSize(buf, size);
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(FloatBuffer buf, int size) {
|
|
|
|
|
checkBufferSize(buf, size);
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(DoubleBuffer buf, int size) {
|
|
|
|
|
checkBufferSize(buf, size);
|
|
|
|
|
checkDirect(buf);
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-04 01:17:13 +01:00
|
|
|
/**
|
2004-07-26 15:36:04 +02:00
|
|
|
* Helper methods to ensure a buffer is big enough to receive data from a
|
2004-02-18 23:31:00 +01:00
|
|
|
* glGet* operation. To avoid unnecessarily complex buffer size checking
|
|
|
|
|
* we've just set the bar artificially high and insist that any receiving
|
|
|
|
|
* buffer has at least 4 remaining().
|
2004-02-15 20:41:51 +01:00
|
|
|
*
|
|
|
|
|
* @param buf
|
|
|
|
|
* The buffer to check
|
|
|
|
|
* @throws BufferOverflowException
|
2004-02-04 01:17:13 +01:00
|
|
|
*/
|
2004-07-26 15:36:04 +02:00
|
|
|
static void checkBuffer(ByteBuffer buf) {
|
|
|
|
|
checkBuffer(buf, DEFAULT_BUFFER_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(ShortBuffer buf) {
|
|
|
|
|
checkBuffer(buf, DEFAULT_BUFFER_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(FloatBuffer buf) {
|
|
|
|
|
checkBuffer(buf, DEFAULT_BUFFER_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(IntBuffer buf) {
|
|
|
|
|
checkBuffer(buf, DEFAULT_BUFFER_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void checkBuffer(DoubleBuffer buf) {
|
2004-02-18 23:31:00 +01:00
|
|
|
checkBuffer(buf, DEFAULT_BUFFER_SIZE);
|
2004-02-04 01:17:13 +01:00
|
|
|
}
|
2004-02-18 23:31:00 +01:00
|
|
|
|
2004-02-04 01:17:13 +01:00
|
|
|
/**
|
2004-02-15 20:41:51 +01:00
|
|
|
* Helper method to ensure that vertex buffer objects are disabled. If they
|
|
|
|
|
* are enabled, we'll throw an OpenGLException
|
2004-02-04 01:17:13 +01:00
|
|
|
*/
|
2004-02-16 04:35:45 +01:00
|
|
|
static void ensureArrayVBOdisabled() {
|
2004-02-04 01:17:13 +01:00
|
|
|
if (VBOTracker.getVBOArrayStack().getState() != 0) {
|
|
|
|
|
throw new OpenGLException("Cannot use Buffers when VBO is enabled");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
2004-02-15 20:41:51 +01:00
|
|
|
* Helper method to ensure that vertex buffer objects are enabled. If they
|
|
|
|
|
* are disabled, we'll throw an OpenGLException
|
2004-02-04 01:17:13 +01:00
|
|
|
*/
|
2004-02-16 04:35:45 +01:00
|
|
|
static void ensureArrayVBOenabled() {
|
2004-02-04 01:17:13 +01:00
|
|
|
if (VBOTracker.getVBOArrayStack().getState() == 0) {
|
|
|
|
|
throw new OpenGLException("Cannot use offsets when VBO is disabled");
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-02-16 04:35:45 +01:00
|
|
|
/**
|
|
|
|
|
* Helper method to ensure that vertex buffer objects are disabled. If they
|
|
|
|
|
* are enabled, we'll throw an OpenGLException
|
|
|
|
|
*/
|
|
|
|
|
static void ensureElementVBOdisabled() {
|
|
|
|
|
if (VBOTracker.getVBOElementStack().getState() != 0) {
|
|
|
|
|
throw new OpenGLException("Cannot use Buffers when VBO is enabled");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Helper method to ensure that vertex buffer objects are enabled. If they
|
|
|
|
|
* are disabled, we'll throw an OpenGLException
|
|
|
|
|
*/
|
|
|
|
|
static void ensureElementVBOenabled() {
|
|
|
|
|
if (VBOTracker.getVBOElementStack().getState() == 0) {
|
|
|
|
|
throw new OpenGLException("Cannot use offsets when VBO is disabled");
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-02-15 20:41:51 +01:00
|
|
|
/**
|
|
|
|
|
* Calculate the storage required for an image.
|
|
|
|
|
*
|
|
|
|
|
* @param format
|
|
|
|
|
* The format of the image (example: GL_RGBA)
|
|
|
|
|
* @param type
|
|
|
|
|
* The type of the image elements (example: GL_UNSIGNED_BYTE)
|
|
|
|
|
* @param width
|
|
|
|
|
* The width of the image
|
|
|
|
|
* @param height
|
|
|
|
|
* The height of the image (1 for 1D images)
|
|
|
|
|
* @param depth
|
|
|
|
|
* The depth of the image (1 for 2D images)
|
|
|
|
|
* @return the size, in bytes, of the image
|
|
|
|
|
*/
|
|
|
|
|
static int calculateImageStorage(int format, int type, int width,
|
|
|
|
|
int height, int depth) {
|
|
|
|
|
int bpe;
|
|
|
|
|
switch (type) {
|
|
|
|
|
case GL11.GL_UNSIGNED_BYTE :
|
|
|
|
|
case GL11.GL_BYTE :
|
|
|
|
|
bpe = 1;
|
|
|
|
|
break;
|
|
|
|
|
case GL11.GL_UNSIGNED_SHORT :
|
|
|
|
|
case GL11.GL_SHORT :
|
|
|
|
|
bpe = 2;
|
|
|
|
|
break;
|
|
|
|
|
case GL11.GL_UNSIGNED_INT :
|
|
|
|
|
case GL11.GL_INT :
|
|
|
|
|
case GL11.GL_FLOAT :
|
|
|
|
|
bpe = 4;
|
|
|
|
|
break;
|
|
|
|
|
default :
|
2004-02-16 04:35:45 +01:00
|
|
|
// TODO: Add more types (like the GL12 types GL_UNSIGNED_INT_8_8_8_8
|
|
|
|
|
return 0;
|
|
|
|
|
// throw new IllegalArgumentException("Unknown type " + type);
|
2004-02-15 20:41:51 +01:00
|
|
|
}
|
|
|
|
|
int epp;
|
|
|
|
|
switch (format) {
|
|
|
|
|
case GL11.GL_LUMINANCE:
|
|
|
|
|
case GL11.GL_ALPHA:
|
|
|
|
|
epp = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GL11.GL_LUMINANCE_ALPHA:
|
|
|
|
|
epp = 2;
|
|
|
|
|
break;
|
|
|
|
|
case GL11.GL_RGB :
|
|
|
|
|
case EXTBgra.GL_BGR_EXT :
|
|
|
|
|
epp = 3;
|
|
|
|
|
break;
|
|
|
|
|
case GL11.GL_RGBA :
|
|
|
|
|
case EXTAbgr.GL_ABGR_EXT :
|
|
|
|
|
case EXTBgra.GL_BGRA_EXT :
|
|
|
|
|
epp = 4;
|
|
|
|
|
break;
|
|
|
|
|
default :
|
2004-02-16 04:35:45 +01:00
|
|
|
// TODO: Add more formats. Assuming 4 is too wasteful on buffer sizes where e.g. 1 is enough (like GL_DEPTH_COMPONENT)
|
|
|
|
|
return 0;
|
|
|
|
|
/* // Assume 4 elements per pixel
|
|
|
|
|
epp = 4;*/
|
2004-02-15 20:41:51 +01:00
|
|
|
}
|
|
|
|
|
return epp * bpe * width * height * depth;
|
|
|
|
|
}
|
2004-02-04 01:17:13 +01:00
|
|
|
}
|