Bug 1288 : Resizing window in OPENGL breaks ImageCaches
Last modified: 2009-07-18 20:00




Status:
ASSIGNED
Resolution:
-
Priority:
P2
Severity:
normal

 

Reporter:
taifunbrowser
Assigned To:
fry

Attachment Type Created Size Actions
An updated PGraphicsOpenGL that solves both this bug and bug 1176 patch 2009-07-09 19:28 18.72 KB

Description:   Opened: 2009-07-09 13:41
This is in referrence to bug 1176:
http://dev.processing.org/bugs/show_bug.cgi?id=1176
This bug was resolved, via the following flawed fix
(processing.opengl.PGraphicsOpenGL.java rev 5605)

CODE SAMPLE NUMBER 1:
[code]
//In method allocate():
context.destroy();
context = drawable.createContext(null);
gl = context.getGL();
reapplySettings();
[/code]

whenever the window is resized, the opengl context is, as you can see, scuttled. This
has wide ranging implications to any users writing OPENGL-specific libraries; as
anything they have stored on the GPU is gone.

However, it breaks processing too, as I will demonstrate.
/////////////////////////////////
TO REPLICATE:
0) Use processing 1.0.4 or 1.0.5. Both come packaged with rev. 5605 of the opengl
renderer.

1) Load processing's "Transparency" example
(Examples/Basics/Image/Transparency)

2) Add the following line after void(setup){
[code]
frame.setResizable(true);
[/code]

3) Run the sketch. drag the borders of the window to resize, The images should
remain intact

4) Switch the size() call in setup() so that the OPENGL renderer is used.

5) Repeat step 3. You will find that the images become blank, white, or corrupted
after any resize operation.

No bug report is complete without some proposal of a fix.
/////////////////////////////////
TO FIX (note: this fixes not only this bug, but also #1176!)
1) Using revision 5605 of PGraphicsOpenGL, remove CODE SAMPLE NUMBER 1
(above).

2) Replace those lines with the following:
[code]
gl.glViewPort(0,0,parent.getWidth(),parent.getHeight());
[/code]

3) Recompile the opengl.jar, reload, and run the above example. You should be able
to resize the window, no distortion should occur, and the images / more should stay
on the GPU.

-Taif
Additional Comment #1 From taifunbrowser 2009-07-09 13:46
oh that's embarrasing. Stop, stop, it doesn't work yet. Come back in an hour or so: I'm
looking into this further.
Additional Comment #2 From taifunbrowser 2009-07-09 14:09
OK. here we go.

The fix is not simply

gl.glViewPort(0,0,parent.getWidth(),parent.getHeight());

it, is, rather

gl.glViewPort(0,0,parent.getWidth(),parent.getHeight());
gl.glClear(GL.GL_DEPTH_BUFFER_BIT);

ahhh.. much better.
Additional Comment #3 From taifunbrowser 2009-07-09 14:31
erk. scrap it. someone else want to figure out how to get processing's matrices to sync
up with opengl? I'm still getting distortion on window resize.
Additional Comment #4 From taifunbrowser 2009-07-09 15:42
OK!

it took ~ 20 lines of code, but here's a PDE zip that has a hacked up version of
PGraphicsOpenGL that:

1) Does NOT replace the context every resize
2) Behaves IDENTICALLY to p3D.

Get it:
http://www.speedyshare.com/648967855.html

The example is as I proposed in the first post.
whew!
Additional Comment #5 From taifunbrowser 2009-07-09 19:16
Version 2:

Disregard the above solution. I don't know why I posted it.

Here's a simpler solution:

1) Using revision 5605 of PGraphicsOpenGL, remove CODE SAMPLE NUMBER 1
(above).

2) Leave that "else" block blank. (Essentially, allocate does nothing on 2nd time)

3) Go to beginDraw. At the end, add

gl.glViewport(0,0,width,height).

Test it out.
Additional Comment #6 From taifunbrowser 2009-07-09 19:28
edit]
An updated PGraphicsOpenGL that solves both this bug and bug 1176

Attached the working fix.
Additional Comment #7 From taifunbrowser 2009-07-10 13:16
A final note: I've tested my proposed fix further, and it still appears to
work. However,

any application that depends on NOT calling background() every frame in
OPENGL mode will have to think of a way to "recover" the canvas during a
resize: When the frame is resized, the existing pixels tend to be torn.
This is not a bug; not calling background() means you're trusting that
opengl will hold on to your pixels for you in between redraws, which, in
this case, is definately impossible.
Additional Comment #8 From taifunbrowser 2009-07-10 21:05
Meh, I take that back; Already twice now I've forgotten to do that check, and I wrote the
dern fix.

I advise that the final patch will include a call to background(0) or some sensible
equivalent inside the else block of the allocate() method... this flushes the corrupted
depth and color buffers created by a window resize.
Additional Comment #9 From fry 2009-07-13 11:07
(thanks for the help, but for the time being please don't change who the
bug is assigned to, it also prevents me from getting updates about what's
going on.)

aside from the image cache issue, does the previous fix work? i wonder if
it would be far simpler to just reset the image cache.
Additional Comment #10 From taifunbrowser 2009-07-13 14:29
Resetting the image cache is something I tried; and it isn't a bad option.

If you download the patch I actually attached above, it doesn't have any of my above
posts, except the last's, additions.

Basically, I found that only adding

gl.glViewport(0,0,width,height)

at the end of beginDraw every frame, and adding

background(0)

in allocate() is my ultimate solution. Take it or leave it; it's two lines of code that I
have faith in.
Additional Comment #11 From fry 2009-07-18 20:00
Hm, the attachment only includes the .class files, I need to see the actual
code. ;-)
This bug is now being tracked here.