PBuffers sharing textures without a Display()


SHORT VERSION:


From the docs
NOTE: The Pbuffer will have its own context that shares display lists and textures with the Display context (if it is created).

How can I share textures and display lists between PBuffers without creating a Display() ?


LONG VERSION:

I’m going on with my SGL (Simple Graphics Library) which is more or less a simple lwjgl based Java2D replacement.

It already draws polys and animated images (textured quads) with affinetransforms, alpha compositing etc. It will handle java2d shapes soon. SGL makes wide use of PBuffers.

The speed is fantastic and the API is really simple. Here’s a sample:


            SGLBitmap sb0 = new SGLBitmap(512,256,0);
            SGLBitmap sb1 = new SGLBitmap(220,200,0);
            SGLImage si = new SGLImage(bufferedimage);
            
            
            int loops = 1000;
            sb0.startTimer();
            for (int i=0; i<loops; i++)
            {
                  sb0.setTransform(AffineTransform.getRotateInstance(-i/10f,100,50));
                  sb0.setColor(new Color(220,11,11,10));
                  sb0.fillRect(0,0,180,120);
                  sb0.setColor(Color.white);
                  sb0.drawRect(0,0,190,130);
                  sb0.setColor(new Color(220,240,150,12));
                  sb0.fillRect(20,20,110,120);
                  sb0.drawImage(si,30,10);
                  
                  sb1.setColor(Color.blue);
                  sb1.fillRect(0,0,80,20);
                  sb1.setColor(Color.yellow);
                  sb1.drawRect(0,0,90,30);
                  sb1.drawImage(si,0,0);
            }
            float t = sb0.endTimer();

Now I discovered that the PBuffers constructed without a Display do not share textures and display lists and that’s a problem as they must be shared between SGLBitmaps (each SGLBitmap holds a PBuffer).


From the docs
NOTE: The Pbuffer will have its own context that shares display lists and textures with the Display context (if it is created).

As SGL will work both onscreen and offscreen, I would need to share display lists and textures without creating a Display().

Maybe the LWJGL Pbuffers constructor would need a boolean switch in order to allow the sharing of display lists and textures.

I ought to point out that display lists are broken in a number of cheapass GL drivers.

Cas :slight_smile:

No problems with glists or poor drivers. I’ll have a fallback-to-java2d mode in case of problems.

The main question remains the same: how can I share textures and display lists between PBuffers without creating a Display() ?

I suppose this involves a little change in LWJGL, isn’t it ? I think it would be a nice feature.

POOF - wish granted. You can now specify a Pbuffer to share with in the Pbuffer constructor.

  • elias

FABULOUS :o

Where can I download the new magic ?

You can fetch a version here:

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

I didn’t bother testing it though, since I’m doing a lot of other lwjgl related work at the moment.

  • elias

Thanks Elias,

I’ll give it a run. I hope to see the new feature in the official distribution soon.

Cheers,

Mik

Hi Elias,

it seems that the new Pbuffer shared contex does not work.

here’s my initialization code:

Code:

 

   static Pbuffer sc_pbuffer = null;
 
   // create the first shared-context tiny pbuffer
   if (sc_pbuffer == null)
   {
    sc_pbuffer = new Pbuffer(1, 1, new PixelFormat(8, 24, 0, samples), null, null);
    sc_pbuffer.makeCurrent();
   }
   
   // allocate the pbuffer
   pbuffer = new Pbuffer(width, height, new PixelFormat(8, 24, 0, samples), null, sc_pbuffer);
   pbuffer.makeCurrent();


Mik

I need more than that. Is there an error message? If not, are the textures not shared? If they aren’t, does it work if you create a Display first?

  • elias

Using the “new” Pbuffer shared context:

  • No error messages.
  • Textures are not shared.

Using the “usual” Display shared context:

  • No error messages.
  • Textures shared correctly.
  • Error message if I try to create a Pbuffer with another Pbuffer context after initializing the Display (ok: this works as expected).
    The message:
    org.lwjgl.LWJGLException: Could not share buffer context.
    at org.lwjgl.opengl.Win32Display.nCreatePbuffer(Native Method)
    at org.lwjgl.opengl.Win32Display.createPbuffer(Win32Display.java:115)
    at org.lwjgl.opengl.Pbuffer.createPbuffer(Pbuffer.java:187)

Mik

Strange. However, from the docs for wglShareLists it seems that only new objects are shared. Have you tried this sequence:

  1. Create a pbuffer
  2. Create another pbuffer shared with the first
  3. Create a texture in pbuffer1 and render it from pbuffer2.

Does that work?

  • elias

That’s exacly what I’m doing:

  • create sc_Pbuffer with a null shared pbuffer reference.

  • create Pbuffer0 with a reference to sc_Pbuffer

  • create textures

  • create Pbuffer1 with a reference to sc_Pbuffer

  • make Pbuffer0 current

  • draw textures

  • make Pbuffer1 current

  • draw textures

the textures only appear in Pbuffer0

Not quite. You need to try to create textures after both pbuffer0 and pbuffer1 has been created (and shared). Better yet, try to limit the case to only pbuffer0 and pbuffer1, leaving out the sc_pbuffer.

  • elias

I did almost any kind of try. It doesn’t work.

The only way to make it work is to open a Display first, which is of course not a solution (well at least for me).

[quote]You need to try to create textures after both pbuffer0 and pbuffer1 has been created (and shared).
[/quote]
Wow, are you sure? I didn’t know that. Is that the case with normal framebuffer-pbuffer sharing too?

I’m not sure, I’m just trying to narrow down the possible causes.

  • elias

Javazoid: As an alternative implementation, have you considered having one single pbuffer and a texture for each image? If you draw on one image at a time it will have the same cost. If you draw on multiple images, they will have to be drawn to the pbuffer first (and the old one transferred to its texture).

  • elias

I have several Pbuffers wrapped into SGLBitmaps. they have different sizes and I can draw textures (SGLImages) to one of them at unpredictable times.

SGLImages themselves can be allocated everywhere in the code and still they can be traced into any allocated SGLBitmap. This makes the sharedcontext so important.

Yes, I understand that. What I was trying to say is why not make the SGLBitmaps textures too and only use one pbuffer (and therefore one context)? When a SGLBitmap is being used, it need to draw itself onto the pbuffer first if it is not already there. The old SGLImage on the pbuffer will need to be flushed to its texture. And finally, if some SGLBitmap is created that is larger than the current pbuffer, flush it and re-create a pbuffer of the right size. The OpenGL drivers are probably more tuned to multiple textures than to multiple pbuffers anyway.

  • elias

Oh, and remember that Pbuffer contents can be lost, while textures are always preserved.

  • elias