Optimized buffer allocation
This commit is contained in:
parent
a1fec2734a
commit
d37c176cf4
|
@ -31,10 +31,10 @@
|
||||||
*/
|
*/
|
||||||
package org.lwjgl.opengl.glu;
|
package org.lwjgl.opengl.glu;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MipMap.java
|
* MipMap.java
|
||||||
|
@ -57,39 +57,24 @@ public class MipMap extends Util {
|
||||||
* @param data
|
* @param data
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public static int gluBuild2DMipmaps(
|
public static int gluBuild2DMipmaps(final int target,
|
||||||
int target,
|
final int components, final int width, final int height,
|
||||||
int components,
|
final int format, final int type, final ByteBuffer data) {
|
||||||
int width,
|
if ( width < 1 || height < 1 ) return GLU.GLU_INVALID_VALUE;
|
||||||
int height,
|
|
||||||
int format,
|
|
||||||
int type,
|
|
||||||
ByteBuffer data) {
|
|
||||||
|
|
||||||
int retVal = 0;
|
final int bpp = bytesPerPixel(format, type);
|
||||||
int error;
|
if ( bpp == 0 )
|
||||||
int w, h, maxSize;
|
|
||||||
ByteBuffer image, newimage;
|
|
||||||
int neww, newh, level, bpp;
|
|
||||||
boolean done;
|
|
||||||
|
|
||||||
if (width < 1 || height < 1) return GLU.GLU_INVALID_VALUE;
|
|
||||||
|
|
||||||
maxSize = glGetIntegerv(GL11.GL_MAX_TEXTURE_SIZE);
|
|
||||||
|
|
||||||
w = nearestPower(width);
|
|
||||||
if (w > maxSize) {
|
|
||||||
w = maxSize;
|
|
||||||
}
|
|
||||||
h = nearestPower(height);
|
|
||||||
if (h > maxSize) {
|
|
||||||
h = maxSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpp = bytesPerPixel(format, type);
|
|
||||||
if (bpp == 0) {
|
|
||||||
return GLU.GLU_INVALID_ENUM;
|
return GLU.GLU_INVALID_ENUM;
|
||||||
}
|
|
||||||
|
final int maxSize = glGetIntegerv(GL11.GL_MAX_TEXTURE_SIZE);
|
||||||
|
|
||||||
|
int w = nearestPower(width);
|
||||||
|
if ( w > maxSize )
|
||||||
|
w = maxSize;
|
||||||
|
|
||||||
|
int h = nearestPower(height);
|
||||||
|
if ( h > maxSize )
|
||||||
|
h = maxSize;
|
||||||
|
|
||||||
// Get current glPixelStore state
|
// Get current glPixelStore state
|
||||||
PixelStoreState pss = new PixelStoreState();
|
PixelStoreState pss = new PixelStoreState();
|
||||||
|
@ -100,49 +85,62 @@ public class MipMap extends Util {
|
||||||
GL11.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 0);
|
GL11.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 0);
|
||||||
GL11.glPixelStorei(GL11.GL_PACK_SKIP_PIXELS, 0);
|
GL11.glPixelStorei(GL11.GL_PACK_SKIP_PIXELS, 0);
|
||||||
|
|
||||||
done = false;
|
ByteBuffer image;
|
||||||
|
int retVal = 0;
|
||||||
|
boolean done = false;
|
||||||
|
|
||||||
if (w != width || h != height) {
|
if ( w != width || h != height ) {
|
||||||
// must rescale image to get "top" mipmap texture image
|
// must rescale image to get "top" mipmap texture image
|
||||||
image = BufferUtils.createByteBuffer((w + 4) * h * bpp);
|
image = BufferUtils.createByteBuffer((w + 4) * h * bpp);
|
||||||
error = gluScaleImage(format, width, height, type, data, w, h, type, image);
|
int error = gluScaleImage(format, width, height, type, data, w, h, type, image);
|
||||||
if (error != 0) {
|
if ( error != 0 ) {
|
||||||
retVal = error;
|
retVal = error;
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
image = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
level = 0;
|
|
||||||
while (!done) {
|
|
||||||
if (image != data) {
|
|
||||||
/* set pixel unpacking */
|
/* set pixel unpacking */
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
|
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
|
||||||
|
} else {
|
||||||
|
image = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteBuffer bufferA = null;
|
||||||
|
ByteBuffer bufferB = null;
|
||||||
|
|
||||||
|
int level = 0;
|
||||||
|
while ( !done ) {
|
||||||
GL11.glTexImage2D(target, level, components, w, h, 0, format, type, image);
|
GL11.glTexImage2D(target, level, components, w, h, 0, format, type, image);
|
||||||
|
|
||||||
if (w == 1 && h == 1)
|
if ( w == 1 && h == 1 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
neww = (w < 2) ? 1 : w / 2;
|
final int newW = (w < 2) ? 1 : w >> 1;
|
||||||
newh = (h < 2) ? 1 : h / 2;
|
final int newH = (h < 2) ? 1 : h >> 1;
|
||||||
newimage = BufferUtils.createByteBuffer((neww + 4) * newh * bpp);
|
|
||||||
|
|
||||||
error = gluScaleImage(format, w, h, type, image, neww, newh, type, newimage);
|
final ByteBuffer newImage;
|
||||||
if (error != 0) {
|
|
||||||
|
if ( bufferA == null )
|
||||||
|
newImage = (bufferA = BufferUtils.createByteBuffer((newW + 4) * newH * bpp));
|
||||||
|
else if ( bufferB == null )
|
||||||
|
newImage = (bufferB = BufferUtils.createByteBuffer((newW + 4) * newH * bpp));
|
||||||
|
else
|
||||||
|
newImage = bufferB;
|
||||||
|
|
||||||
|
int error = gluScaleImage(format, w, h, type, image, newW, newH, type, newImage);
|
||||||
|
if ( error != 0 ) {
|
||||||
retVal = error;
|
retVal = error;
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
image = newimage;
|
image = newImage;
|
||||||
|
if ( bufferB != null )
|
||||||
|
bufferB = bufferA;
|
||||||
|
|
||||||
w = neww;
|
w = newW;
|
||||||
h = newh;
|
h = newH;
|
||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,48 +163,39 @@ public class MipMap extends Util {
|
||||||
* @param dataOut
|
* @param dataOut
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public static int gluScaleImage(
|
public static int gluScaleImage(int format,
|
||||||
int format,
|
int widthIn, int heightIn, int typein, ByteBuffer dataIn,
|
||||||
int widthIn,
|
int widthOut, int heightOut, int typeOut, ByteBuffer dataOut) {
|
||||||
int heightIn,
|
|
||||||
int typein,
|
|
||||||
ByteBuffer dataIn,
|
|
||||||
int widthOut,
|
|
||||||
int heightOut,
|
|
||||||
int typeOut,
|
|
||||||
ByteBuffer dataOut) {
|
|
||||||
|
|
||||||
int components, i, j, k;
|
final int components = compPerPix(format);
|
||||||
float[] tempin, tempout;
|
if ( components == -1 )
|
||||||
|
return GLU.GLU_INVALID_ENUM;
|
||||||
|
|
||||||
|
int i, j, k;
|
||||||
|
float[] tempIn, tempOut;
|
||||||
float sx, sy;
|
float sx, sy;
|
||||||
int sizein, sizeout;
|
int sizein, sizeout;
|
||||||
int rowstride, rowlen;
|
int rowstride, rowlen;
|
||||||
|
|
||||||
components = compPerPix(format);
|
|
||||||
if (components == -1) {
|
|
||||||
return GLU.GLU_INVALID_ENUM;
|
|
||||||
}
|
|
||||||
|
|
||||||
// temp image data
|
// temp image data
|
||||||
tempin = new float[widthIn * heightIn * components];
|
tempIn = new float[widthIn * heightIn * components];
|
||||||
tempout = new float[widthOut * heightOut * components];
|
tempOut = new float[widthOut * heightOut * components];
|
||||||
|
|
||||||
// Determine bytes per input type
|
// Determine bytes per input type
|
||||||
switch (typein) {
|
switch ( typein ) {
|
||||||
case GL11.GL_UNSIGNED_BYTE :
|
case GL11.GL_UNSIGNED_BYTE:
|
||||||
sizein = 1;
|
sizein = 1;
|
||||||
break;
|
break;
|
||||||
default :
|
default:
|
||||||
return GL11.GL_INVALID_ENUM;
|
return GL11.GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine bytes per output type
|
// Determine bytes per output type
|
||||||
switch (typeOut) {
|
switch ( typeOut ) {
|
||||||
case GL11.GL_UNSIGNED_BYTE :
|
case GL11.GL_UNSIGNED_BYTE:
|
||||||
sizeout = 1;
|
sizeout = 1;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
default :
|
|
||||||
return GL11.GL_INVALID_ENUM;
|
return GL11.GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,62 +203,60 @@ public class MipMap extends Util {
|
||||||
PixelStoreState pss = new PixelStoreState();
|
PixelStoreState pss = new PixelStoreState();
|
||||||
|
|
||||||
//Unpack the pixel data and convert to floating point
|
//Unpack the pixel data and convert to floating point
|
||||||
if (pss.unpackRowLength > 0) {
|
if ( pss.unpackRowLength > 0 )
|
||||||
rowlen = pss.unpackRowLength;
|
rowlen = pss.unpackRowLength;
|
||||||
} else {
|
else
|
||||||
rowlen = widthIn;
|
rowlen = widthIn;
|
||||||
}
|
|
||||||
if (sizein >= pss.unpackAlignment) {
|
|
||||||
rowstride = components * rowlen;
|
|
||||||
} else {
|
|
||||||
rowstride = pss.unpackAlignment / sizein * ceil(components * rowlen * sizein, pss.unpackAlignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (typein) {
|
if ( sizein >= pss.unpackAlignment )
|
||||||
case GL11.GL_UNSIGNED_BYTE :
|
rowstride = components * rowlen;
|
||||||
|
else
|
||||||
|
rowstride = pss.unpackAlignment / sizein * ceil(components * rowlen * sizein, pss.unpackAlignment);
|
||||||
|
|
||||||
|
switch ( typein ) {
|
||||||
|
case GL11.GL_UNSIGNED_BYTE:
|
||||||
k = 0;
|
k = 0;
|
||||||
dataIn.rewind();
|
dataIn.rewind();
|
||||||
for (i = 0; i < heightIn; i++) {
|
for ( i = 0; i < heightIn; i++ ) {
|
||||||
int ubptr = i * rowstride + pss.unpackSkipRows * rowstride + pss.unpackSkipPixels * components;
|
int ubptr = i * rowstride + pss.unpackSkipRows * rowstride + pss.unpackSkipPixels * components;
|
||||||
for (j = 0; j < widthIn * components; j++) {
|
for ( j = 0; j < widthIn * components; j++ ) {
|
||||||
tempin[k++] = (float) ((int) dataIn.get(ubptr++) & 0xff);
|
tempIn[k++] = (float)((int)dataIn.get(ubptr++) & 0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
default :
|
|
||||||
return GLU.GLU_INVALID_ENUM;
|
return GLU.GLU_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do scaling
|
// Do scaling
|
||||||
sx = (float) widthIn / (float) widthOut;
|
sx = (float)widthIn / (float)widthOut;
|
||||||
sy = (float) heightIn / (float) heightOut;
|
sy = (float)heightIn / (float)heightOut;
|
||||||
|
|
||||||
float[] c = new float[components];
|
float[] c = new float[components];
|
||||||
int src, dst;
|
int src, dst;
|
||||||
|
|
||||||
for (int iy = 0; iy < heightOut; iy++) {
|
for ( int iy = 0; iy < heightOut; iy++ ) {
|
||||||
for (int ix = 0; ix < widthOut; ix++) {
|
for ( int ix = 0; ix < widthOut; ix++ ) {
|
||||||
int x0 = (int) (ix * sx);
|
int x0 = (int)(ix * sx);
|
||||||
int x1 = (int) ((ix + 1) * sx);
|
int x1 = (int)((ix + 1) * sx);
|
||||||
int y0 = (int) (iy * sy);
|
int y0 = (int)(iy * sy);
|
||||||
int y1 = (int) ((iy + 1) * sy);
|
int y1 = (int)((iy + 1) * sy);
|
||||||
|
|
||||||
int readPix = 0;
|
int readPix = 0;
|
||||||
|
|
||||||
// reset weighted pixel
|
// reset weighted pixel
|
||||||
for (int ic = 0; ic < components; ic++) {
|
for ( int ic = 0; ic < components; ic++ ) {
|
||||||
c[ic] = 0;
|
c[ic] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create weighted pixel
|
// create weighted pixel
|
||||||
for (int ix0 = x0; ix0 < x1; ix0++) {
|
for ( int ix0 = x0; ix0 < x1; ix0++ ) {
|
||||||
for (int iy0 = y0; iy0 < y1; iy0++) {
|
for ( int iy0 = y0; iy0 < y1; iy0++ ) {
|
||||||
|
|
||||||
src = (iy0 * widthIn + ix0) * components;
|
src = (iy0 * widthIn + ix0) * components;
|
||||||
|
|
||||||
for (int ic = 0; ic < components; ic++) {
|
for ( int ic = 0; ic < components; ic++ ) {
|
||||||
c[ic] += tempin[src + ic];
|
c[ic] += tempIn[src + ic];
|
||||||
}
|
}
|
||||||
|
|
||||||
readPix++;
|
readPix++;
|
||||||
|
@ -279,16 +266,16 @@ public class MipMap extends Util {
|
||||||
// store weighted pixel
|
// store weighted pixel
|
||||||
dst = (iy * widthOut + ix) * components;
|
dst = (iy * widthOut + ix) * components;
|
||||||
|
|
||||||
if (readPix == 0) {
|
if ( readPix == 0 ) {
|
||||||
// Image is sized up, caused by non power of two texture as input
|
// Image is sized up, caused by non power of two texture as input
|
||||||
src = (y0 * widthIn + x0) * components;
|
src = (y0 * widthIn + x0) * components;
|
||||||
for (int ic = 0; ic < components; ic++) {
|
for ( int ic = 0; ic < components; ic++ ) {
|
||||||
tempout[dst++] = tempin[src + ic];
|
tempOut[dst++] = tempIn[src + ic];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// sized down
|
// sized down
|
||||||
for (k = 0; k < components; k++) {
|
for ( k = 0; k < components; k++ ) {
|
||||||
tempout[dst++] = c[k] / readPix;
|
tempOut[dst++] = c[k] / readPix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,30 +283,28 @@ public class MipMap extends Util {
|
||||||
|
|
||||||
|
|
||||||
// Convert temp output
|
// Convert temp output
|
||||||
if (pss.packRowLength > 0) {
|
if ( pss.packRowLength > 0 )
|
||||||
rowlen = pss.packRowLength;
|
rowlen = pss.packRowLength;
|
||||||
} else {
|
else
|
||||||
rowlen = widthOut;
|
rowlen = widthOut;
|
||||||
}
|
|
||||||
if (sizeout >= pss.packAlignment) {
|
|
||||||
rowstride = components * rowlen;
|
|
||||||
} else {
|
|
||||||
rowstride = pss.packAlignment / sizeout * ceil(components * rowlen * sizeout, pss.packAlignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (typeOut) {
|
if ( sizeout >= pss.packAlignment )
|
||||||
case GL11.GL_UNSIGNED_BYTE :
|
rowstride = components * rowlen;
|
||||||
|
else
|
||||||
|
rowstride = pss.packAlignment / sizeout * ceil(components * rowlen * sizeout, pss.packAlignment);
|
||||||
|
|
||||||
|
switch ( typeOut ) {
|
||||||
|
case GL11.GL_UNSIGNED_BYTE:
|
||||||
k = 0;
|
k = 0;
|
||||||
for (i = 0; i < heightOut; i++) {
|
for ( i = 0; i < heightOut; i++ ) {
|
||||||
int ubptr = i * rowstride + pss.packSkipRows * rowstride + pss.packSkipPixels * components;
|
int ubptr = i * rowstride + pss.packSkipRows * rowstride + pss.packSkipPixels * components;
|
||||||
|
|
||||||
for (j = 0; j < widthOut * components; j++) {
|
for ( j = 0; j < widthOut * components; j++ ) {
|
||||||
dataOut.put(ubptr++, (byte) tempout[k++]);
|
dataOut.put(ubptr++, (byte)tempOut[k++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
default :
|
|
||||||
return GLU.GLU_INVALID_ENUM;
|
return GLU.GLU_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue