JDK-8123020 : Resizing a Window causes the size of objects to jitter
  • Type: Bug
  • Component: javafx
  • Sub-Component: graphics
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-05-29
  • Updated: 2015-06-17
  • Resolved: 2013-10-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Fixed
Related Reports
Blocks :  
Duplicate :  
Duplicate :  
Relates :  
Description
1) Run EnsembleApp
2) Resize by dragging the bottom right corner
3) Watch the menu bar draw with smaller then bigger


Comments
Verified on 8.0b120.
30-12-2013

Update... Previous comment is mostly still correct... in GlassViewEventHandler in the RESIZE handler, commenting out the renderLock and enabling live resize fixes it. (validate stage graphics was already called in PresentingPainter so it isnt needed.) Live Resize is a heavyweight fix, it hides the fact that there are parts of Prism that are not in sync with the same w/h as the camera. Kevin and I thought we covered all of the spots by ensuring the updateSceneState takes in a width and height that will be the same as the camera's calculations and making sure these are only updated to the render thread at sync time, but I am now checking native code in the hwnd to see if there are any spots where we are using the windows width and height where we should be using the w/h associated with the camera/sceneState.
30-09-2013

The flag you need is -Djavafx.live.resize=true.
16-09-2013

Progress!! Okay, so my theory about rendering happening between the time where we resize and sync, thus causing camera and w/h to become inconsistent is looking like the issue. There are 3 places where this can happen (in terms of timing). 2 of them are in GlassViewEventHandler in RESIZE:. Updating the Scene State before syncing will pass a new width and height and leave the old camera matrix (bad). Commenting that out. It is still possible to render a new frame with the old width and height if we render a frame AFTER resizeing and before we sync, so we need to turn on live resize. Lastly, and this may or may not further eliminate the race condition, but validate stage graphics in ViewPainter is called before rendering to ensure that the view width and height of the ViewPainter is in sync with the SceneState before we render. it would be nice if we could turn on live resize for windows, but if we can't, we will want to sync camera and w/h at the same time, regardless, after a resize.
12-09-2013

Normally, pulses are fired by the timer in another thread, then queued in a runLater() for the UI thread. On Mac, when a resize happens, PaintCollector.liveRepaintRenderJob() runs in the UI Thread. This code runs almost the same code that would run when a normal pulse comes in (ie. cause a sync between the UI thread and the Render Thread), adds a render job for the Render Thread, then waits for the job to complete in the UI Thread. This forces painting to happen during the operating system resize and before the resize returns. I was hoping that a similar thing could be done for Windows (I tried the flags) but I think something else is going on there. Thor had some insight behind the "black flashing bug" and D3D with respect to what happens when the underlying surface changes size. Thor?
09-09-2013

Hey Steve, Just to make certain, with live resize on windows, A pulse is fired right when glass receives a resize event? If that still doesnt fix it, that leaves my current hypothesis totally wrong. I thought that maybe the View Width and Height were not getting synced quickly enough to the Render Thread because of the time between a resize and a sync might kickoff another render of a frame.
06-09-2013

Glass has only one window: the top level one. In the past, on Windows, the Glass View also had an HWND but this code has been gone for a while. I believe that Glass does not resize the window (ie. it is the user resizing it that changes the size). It is possible that Glass has a cached value that is not up to date.
03-09-2013

Running with -Djavafx.live.resize=false on Mac does not show the problem. I had expected that it would. Also running with -Djavafx.live.resize=true on Windows doesn't fix it.
03-09-2013

I've moved most of the computation back to the render thread (NG Camera) and also commented out updating the view on a resize from the view event handler, and also left it in AND added setting camera view width and height at the same time. In both cases, jitter still occurred.
03-09-2013

Correct me if i'm wrong but since resizing is triggered from the UI thread (Glass), the render thread will be unaware of a resized window UNTIL the pulse's synchronization, and the camera will be updated at THAT moment in time. Basically as far as the render thread is concerned, it will never render with a viewport that doesnt match the current size of the window. The only thing i think makes the above statement untrue is that glass resizes the window itself on the UI thread. So then the render thread could possibly be rendering into an old window size for a frame.
29-08-2013

I like to think this is throwing a bunch of hay onto a needle, but I am about to light the hay on fire :)
28-08-2013

All I'm saying is that we went from a build with no jitter to a build with jitter and we know what the build is. We should be able to find the change and you guys are on it
28-08-2013

Although, I think the gist of what Pavel is saying is correct (and yes, some variant of solution #1 seems best).
28-08-2013

Pavel's suggestions are not 100% accurate according to the debugging kevin and I did. For the most part the viewport is fine, and jitter occours when it is correct. There is a race condition where it is incorrect, but according to our debugging it happens even with a correct viewport.
28-08-2013

Pavel seems to have debugged it and has even pointed to the change that caused it, no? I like suggested fix 1).
28-08-2013

Yea, I was hunting down which values might be causing the race condition before my vacation and didnt find any. I obviously am not looking hard enough.
28-08-2013

I just did the same test as Kevin (as this jitter has been aggravating me for a while), and can confirm that disabling multi-threading also works for me - the resize is no longer jittery and in general feels smoother (like there is less lag between my mouse input and the scene content resizing). I tested with HelloTableView, which is a relatively dense scenegraph.
28-08-2013

It would be worth trying this with multi-threading disabled: -Dquantum.multithreaded=false I just tried this on my system and that does in fact make the problem go away.
28-08-2013

Update: I'm actually getting the same behavior on ES2 regardless of the if (w != vw || h != vh) { scratchTx.scale(vw / w, vh / h, 1.0); } On D3D this is damn near rock solid on my machine, last week Kevin walked in my office and after some effort i was able to get SOME jitter. I've been waving my hand on a resize drag for 4 minutes straight and it is completely solid. Es2 is awful though. I'm not sure we can characterize this to one specific issue.
06-08-2013

We know the cause. This is my earlier evaluation (only sent in an email): Problem: When a window is being resized, the content jitters - scales and jumps back and forth. As Kevin suggested, this is most probably caused by the camera changes done some time ago. Probable cause: Before the camera changes, rendering always took current viewport, computed all the camera transforms for it and rendered the frame. Now the viewport and transforms are computed on Scenegraph level and synced to render tree. It looks like in the moment between window resize and the nearest pulse the actual rendering viewport does not match the one in Camera which causes the weird rendering. Behavior: On SW pipeline, it looks good, but it doesn't work with cameras at all. On ES2 pipeline, the content is first magnified to fit the new window size and then fixed. The magnification is caused by the fix for power-of-two textures later enhanced to this (in ES2Context around line 237): if (w != vw || h != vh) { scratchTx.scale(vw / w, vh / h, 1.0); } If I remove this code the content stops magnifying during resize, but it keeps jumping around. On D3D pipeline, the content is also magnified, I'm not familiar with this code at all. Solutions I can see: Can we do one of the following? (1): keep rendering the same thing, based on camera parameters, until it is updated in the next pulse (we do that with all the other stuff) (2): force fire an immediate pulse on window resize (3): switch dynamically to quantum.multithreaded=false for the time of window resize In the subsequent discussion it looked like (1) should be the way to go, but Joe should have more insight there (and perhaps even some better solution).
11-07-2013

The change happened between b86 and b87. Surely we have a tag somewhere and can browse differences?
10-07-2013

I'm not sure this is related to proper handling of the content width of an RTT, i still need to do some more testing but the camera just creates another RTT if the one it is using has the incorrect w/h. I guess on a resize this could cause an explosion of new RTTs which may cause jitter?
10-07-2013

This is a very serious issue and has been broken for a while. Upping the priority.
10-07-2013

This is probably caused by the temporary inconsistency of window size and camera viewport between the resize and the nearest pulse. Note that if we simply stop resizing the texture the inconsistency starts to show as position jitter.
10-06-2013

This could possibly be the camera changes which first went into b87. Not sure why it would affect Mac differently that Windows, but possibly the CALayer is buffering it so we don't see it on Mac? Need to try it on Linux.
29-05-2013

This seems specific to Windows, and affects both the d3d and es2 pipelines. This regression was introduced in b87. I verified that it works in b86 but fails in b87.
29-05-2013