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 docsNOTE: 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.

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

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.

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).

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.

I'm going to send you the sources of my implementation. It's pretty straighforward. Send me an email address at mik@classx.it

I'm very new to OpenGL sorry. Anyway you are suggesting me to enable render-to-texture on my Pbuffers ?

That's what I've got:- create a Pbuffer (one static instance).- SGLBitmap holds a texture which is the one that must be bound to the Pbuffer.- SGLImage holds a texture. This one is constructed my making the PBuffer current.- SGLBitmap.drawImage(SGLImage) will draw the texture to the Pbuffer.- I can grab the SGLBitmap texture pixels through glGetTexImage() from the texture bound to the Pbuffer.

Mmmh, some nice things:- I couldn't care less if the PBuffer loses its contents.- no context switch. Very good for speed.

the bad: I have to rewrite everything.

Q: if the design above is right, can you tell me how glGetTexImage() perform compared to glReadPixels() ?

That's more or less right I think. To clarify, I'd probably make a SGLBitmap and SGLImage the same, say, SGLGraphics. It would work something like this:

- As an initialization, create the singleton pbuffer and make it current. There's no context switches from now on, since that single pbuffer is always used. - The "active" SGLGraphics is stored as a singleton variable along with the pbuffer. This is for caching. - When a WGLGraphics is constructed, it is assigned a texture id. - SGLGraphics.flush() uses either render-to-texture or simply glCopyTexImage2D to copy the contents of the pbuffer to its texture. Render-to-texture is very fast, but even glCopyTexImage2D should be much faster than glReadPixels or glGetTexImage(). - SGLGraphics.makeActive() uses a quad or something to draw the entire SGLGraphics texture onto the pbuffer, ready for changes. Additionally, it sets the active SGLGraphics to itself. - SGLGraphics.drawSomething() does the following: 1. if (this != active_sglgraphics) { active_sglgraphics.flush(); makeActive(); } 2. Draw the desired texture or primitive.

To actually get at the pixel data from a SGLGraphics you'll need to use glGetTexImage.

GetTexImage = very very fast, copies from VRAM to VRAM.ReadPixels = very very slow, reads the wrong way across the AGP buffer, aaaagh!

Cas

Cas is slightly wrong here. GetTexImage and ReadPixels are probably equally fast, depending on whether the texture is cached in system ram or not. It's CopyTexImage2D that is (potentially) VRAM to VRAM and therefore fast.

I'd like to add that render-to-texture is not an option in such a system, because:

A) When pbuffer contents get lost, the texture contents will be lost too. render-to-texture is more appropriate for dynamic textures that get refreshed each frame.B) How can multiple textures be created from a single render-to-texture pbuffer? Only by making it huge and packing multiple images. Not very nice.

So, CopyTexImage should be the best option and more than fast enough too.

I implemented the SGLGraphics as suggested. There was a little design problem in your description. No problem, I fixed it today.

I benchmarked both implementations with 20000 loops of misc graphics:

2 bitmap/graphics switches per loop

SGLGraphics gives:Time s. 11.46202Fps. 1744.8932

SGLBitmap:Time s. 9.126782Fps. 2191.3528

4 bitmap/graphics switches per loop

SGLGraphics gives:Time s. 22.803085Fps. 877.0743

SGLBitmap:Time s. 14.629756Fps. 1367.0768

From the numbers the SGLBitmap seems to be quite better. The reason is the number of graphics copys from/to the pbuffer needed from SGLGraphics.

Even more, with SGLGraphics, when the pbuffer loses it contents, even the textures in its context go away. This forces me to reallocate every texture in the "new" pbuffer (including the SGLGraphics backbuffer).

From the SGLBitmap side, when the pbuffer gets lost I can recreate it and ask SGLImages to re-create their textures at drawImage() time.

Anyway, the Pbuffers shared context works as expected and this is a great feature.

However Pbuffer flushing is still a problem. For this reason I would suggest what I call a "missing feature": create an invisible Display i.e. by putting a boolean in the constructor and a pair of hide()/show() methods.

This would be useful in order to share the Display context between subsequent Pbuffer allocations in order to keep the textures when the Pbuffers get lost. Nice, isn't it ?

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org