Optimized buffer allocation

This commit is contained in:
Ioannis Tsakpinis 2005-01-26 22:48:12 +00:00
parent a1fec2734a
commit d37c176cf4
1 changed files with 134 additions and 149 deletions

View File

@ -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;
} }