Here’s the test case code. It uses display lists to convert a java2d shape into a glist.
Just change the display boolean to switch from Display to PBuffer. When Display is true everything works fine. Otherwise (pbuffer mode) you’ll get an exception during the cleanup.
Cheers!
Mik
/*
* PBUFFER TEST FOR ELIAS "PBuffer Invalid operation (1282)"
*/
import java.awt.Color;
import java.awt.Font;
import java.awt.Shape;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.FlatteningPathIterator;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.EXTBgra;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Pbuffer;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.opengl.glu.GLU;
public class PbufferTestElias
{
private static Pbuffer pbuffer = null;
private static int width = 640;
private static int height = 400;
private static boolean display = false; // CHANGE THIS TO SWITCH PBUFFER/DISPLAY
private PbufferTestElias()
{
}
private static void init() throws Exception
{
if (display)
{
// create the display
DisplayMode mode = findDisplayMode(width, height, 24);
Display.setDisplayMode(mode);
// start of in windowed mode
Display.create();
Display.setVSyncEnabled(false);
Display.makeCurrent();
}
else
{
// allocate the pbuffer
pbuffer = new Pbuffer(width, height, new PixelFormat(8, 24, 0, 0), null, null);
pbuffer.makeCurrent();
}
initGL(width, height);
}
private static void render() throws Exception
{
Shape shp;
//Shape shp = new Ellipse2D.Float(0, 0, width, height);
Font fnt = new Font("dialog",Font.BOLD,50);
shp = fnt.createGlyphVector(new FontRenderContext(AffineTransform.getTranslateInstance(0,0),true,true),"Mik Of ClassX").getOutline();
shp = AffineTransform.getTranslateInstance(50,150).createTransformedShape(shp);
int list_base = GL11.glGenLists(1);
createShape(shp, list_base);
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK,GL11.GL_LINE);
GL11.glLineWidth(2f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
if (display) GL11.glColor3f(1.0f, 1.0f, 1.0f);
else GL11.glColor3f(0.0f, 0.0f, 0.0f);
GL11.glCallList(list_base);
GL11.glFlush();
GL11.glDeleteLists(list_base, 1);
display(screenShot(width, height));
}
private static void cleanup()
{
try
{
if (pbuffer != null)
{
pbuffer.makeCurrent();
pbuffer.destroy();
}
}
catch (LWJGLException e)
{
e.printStackTrace();
}
if (Display.isCreated()) Display.destroy();
}
// find a nice display mode
public static DisplayMode findDisplayMode(int width, int height, int bpp)
{
DisplayMode[] modes = Display.getAvailableDisplayModes();
for (int i = 0; i < modes.length; i++)
{
if (modes[i].getWidth() == width && modes[i].getHeight() == height && modes[i].getBitsPerPixel() >= bpp)
{
return modes[i];
}
}
return null;
}
public static void main(String[] args)
{
try
{
init();
render();
}
catch (Exception e)
{
e.printStackTrace(System.err);
Sys.alert("", "An error occured and the game will exit.");
}
finally
{
cleanup();
}
}
// init the geometry of the current context
public static void initGL(int width, int height)
{
try
{
// init geometry
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluOrtho2D(0, width, 0, height);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glViewport(0, 0, width, height);
// init graphics blending (ALPHA COMPOSITE is SrcOver)
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glEnable(GL11.GL_BLEND);
// various settings
//GL11.glEnable(GL11.GL_POLYGON_SMOOTH); // NO! -> TEXTURES UGLY!
GL11.glEnable(GL11.GL_LINE_SMOOTH);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_SCISSOR_TEST);
GL11.glDisable(GL11.GL_STENCIL_TEST);
GL11.glDisable(GL11.GL_ALPHA_TEST);
// clear background
GL11.glClearColor(0f, 0f, 0f, 0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// create the list
// very simple conversion method. Does not handle complex shapes or compound shapes (like glyphs).
// also does not support open shapes (lines, arcs, etc.).
private static void createShape(Shape shp, int list_id)
{
// the path iterator
FlatteningPathIterator fpi = new FlatteningPathIterator(shp.getPathIterator(null), .01);
// create the list
GL11.glNewList(list_id, GL11.GL_COMPILE);
// the generation mode
int mode = GL11.GL_POLYGON;
// various temp storage
double[] c = { 0, 0, 0, 0, 0, 0 };
boolean start = false;
double sx = 0, sy = 0;
while (!fpi.isDone())
{
switch (fpi.currentSegment(c))
{
case FlatteningPathIterator.SEG_LINETO:
//System.out.println("FlatteningPathIterator.SEG_LINETO "+c[0]+" "+c[1]);
if (start)
{
GL11.glVertex2f((float) c[0], (float) c[1]);
}
break;
case FlatteningPathIterator.SEG_MOVETO:
//System.out.println("FlatteningPathIterator.SEG_MOVETO "+c[0]+" "+c[1]);
start = true;
GL11.glBegin(mode);
GL11.glTranslatef((float) c[0], (float) c[1], 0);
sx = c[0];
sy = c[1];
break;
case FlatteningPathIterator.SEG_CLOSE:
// System.out.println("FlatteningPathIterator.SEG_CLOSE "+c[0]+" "+c[1]);
//GL11.glVertex2f((float)sx,(float)sy);
GL11.glEnd();
start = false;
break;
}
fpi.next();
}
GL11.glEndList();
//GL11.glFlush();
}
// "slowly" take a screenshot of the pbuffer contents
public static BufferedImage screenShot(int width, int height)
{
BufferedImage image = null;
// allocate space for RBGA pixels
ByteBuffer fb = BufferUtils.createByteBuffer(width * height * 4);
int[] pixels = new int[width * height];
int bindex;
/*
// grab a copy of the current frame contents as RGBA
GL11.glReadPixels(0, 0, width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, fb);
// convert RGBA data in ByteBuffer to integer array
for (int i = 0; i < pixels.length; i++)
{
bindex = i * 4;
int a = fb.get(bindex + 3) & 0xff;
int r = fb.get(bindex + 0) & 0xff;
int g = fb.get(bindex + 1) & 0xff;
int b = fb.get(bindex + 2) & 0xff;
pixels[i] = (a << 24) | (r << 16) | (g << 8) | (b);
}
*/
// we have the EXTBgra.GL_BGRA_EXT extension, so we can convert while reading!!
GL11.glReadPixels(0, 0, width, height, EXTBgra.GL_BGRA_EXT, GL11.GL_UNSIGNED_BYTE, fb);
fb.asIntBuffer().get(pixels);
// Create a BufferedImage with the RGBA pixels
try
{
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
image.setRGB(0, 0, width, height, pixels, 0, width);
}
catch (Exception e)
{
System.out.println("ScreenShot() exception: " + e);
}
return image;
}
private static void display(BufferedImage img)
{
final JFrame frame = new JFrame("PBuffer Test");
frame.setSize(width,height);
frame.setBackground(Color.black);
// Display the pbuffer in a JScrollPane
ImageIcon image = new ImageIcon(img);
JLabel label = new JLabel(image);
JScrollPane scrollPane = new JScrollPane(label);
frame.getContentPane().add(scrollPane);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
frame.dispose();
}
});
frame.setVisible(true);
}
}