Pbuffers no longer working with the latest CVS

Looks like the Pbuffers no longer work with the latest LWJGL CVS. Can someone confirm ?

java.lang.IllegalStateException: Pbuffers are not supported
at org.lwjgl.opengl.Pbuffer.(Pbuffer.java:179)
at PbufferTest.initialize(PbufferTest.java:124)
at PbufferTest.execute(PbufferTest.java:109)

Are you using the latest native lib too? Try:

http://odense.kollegienet.dk/~/naur/lwjgl_19012005.zip

  • elias

If yes, what does Pbuffer.getCapabilities() return?

  • elias

Ah, my bad. It’s fixed in:

http://odense.kollegienet.dk/~naur/lwjgl_19012005-2.zip

  • elias

I can confirm that now it works. BRAVO!

Now I have a little problem (still in the previous version). I get:

org.lwjgl.opengl.OpenGLException: Invalid operation (1282) at org.lwjgl.opengl.Pbuffer.destroy(Pbuffer.java:240)

it happens systematically after using ogl display lists with pbuffers. No problems if I open a Display.

I’m not sure that’s our fault. Try a call to org.lwjgl.Util.checkGLError() just before the destroy(). If that is failing too, it’s probably caused by an erroneous GL call.

  • elias

I get no errors in the Util.checkGLError();

I also get no errors if I do not call the Destroy(), so I’m quite sure that the problem is there.


    public void destroy() {
        try {
            makeCurrent();
            int error = GL11.glGetError();
            Display.getImplementation().destroyPbuffer(handle);
            GLContext.useContext(null);
            GLContext.unloadOpenGLLibrary();
            if (error != GL11.GL_NO_ERROR)
                throw new OpenGLException(error);
        } catch (LWJGLException e) {
            // ignore exception
        }
    }

This is the Pbuffer.destroy() code. Could you try doing a Util.checkGLError() after making sure that the pbuffer is current?

  • elias

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

Aha, you appear to be calling glTranslatef inside a glBegin/glEnd. Problem solved!

Cas :slight_smile:

Aha, just a silly problem! Thanks!
I was fooled by the fact that the error appeared only with pbuffers.
p.s. here’s the indication that I’m new to OpenGL.