This is a fix for a long-standing bug where the D3D pipeline will stop 
rendering when a Windows remote desktop session is disconnected and then 
reconnected.

A preliminary Draft PR #315 by @Schmidor was a good first step in solving this. 
I took that and continued the work in my Draft PR #403. It is now ready for 
formal review in this new PR. You can see PR #403 for details on the history of 
the changes.

## Evaluation

The root cause of this bug is that the D3D pipeline did not handle a return 
code of `D3DERR_DEVICEREMOVED` from `TestCooperativeLevel`. When that error 
occurs, an application needs to destroy and recreate the Direct3D device.

The solution is to implement a new `D3DPipeline::reinitialize` method that will 
destroy the native D3D device and dispose the existing ResourceFactory objects 
and their associated BaseContext objects upon receiving `D3DERR_DEVICEREMOVED`. 
Note that the `D3DPipeline` Java object singleton is not recreated (it remains 
a singleton). In support of this, I implemented proper disposal logic in 
`BaseResourceFactory` and `BaseContext` to clean everything up and also to 
avoid memory leaks.

Additionally, there were several places that assumed that some textures (and 
mesh vertices) could be made permanent and never need to handle the case of a 
lost device. These all had to be fixed to allow for the possibility of a lost 
device and associated resource factory. They included:

* UploadingPainter and PresentingPainter need to set the resource factory to 
null when not ready, so it will get the (possibly new) factory the next time it 
tries.
* The gradient texture cache in `PaintHelper` has to be cleared and recreated 
when the surface is lost
* The 3D triangle mesh and Phong material classes need to be disposed when the 
resource factory is disposed.
* WebView often renders to a texture image at a time other than from the main 
rendering job, so needs to directly handle the case of a resource factory that 
is lost.
* Decora PPSRenderer assumed that the resource factory never went away; it also 
accessed it on the wrong thread. Both problems were addressed by deferring the 
initialization of the resource factory and handling the case where the device 
is disposed.
* Snapshot needs to allow for the platform image to be null if the device has 
been disposed.

## Notes to Reviewers

I created this PR from a branch that contains the original 4 commits by 
@Schmidor (rebased on top of the current `master`) and then a single commit on 
top of that to complete it. This allows anyone who is interested to easily see 
the diffs between this PR and Oliver's original Draft PR. Most reviewers can 
just go to the list of "Files" and see the aggregate diffs.

During the course of my testing I discovered three outstanding problems, which 
will be handled by filing follow-up issues. Once I file them, I'll add a 
comment to this PR with the bug IDs.

1. Media: a media stream playing at the time of a reconnect doesn't continue 
playing. Reloading the media works fine. This is not directly related to this 
bug, since it also happens with the software pipeline.
2. Canvas: doesn't preserve the contents after a device reconnect (noticed 
while running Zoomy, where the BG color is wrong after device 
reinitialization). This might point to a need to let the app know they have to 
repaint, since there is no possible way to preserve the contents of the texture 
when the device is lost.
3. WebView: there is a possible memory leak when device isn't ready after first 
reset, due to a `WCRenderQueueImpl::gc` instance being held in a JNIGlobal. 
This looks like a preexisting condition that could happen with a page (re)load 
today. It happens rarely.

This is a complicated enough change that I'd like three reviewers. The bulk of 
the changes are Windows-specific, but there are changes in common code so at 
least a sanity check needs to be done on all platforms using both the HW and SW 
pipelines. The case of a disposed device can currently only happen on Windows 
with the D3D pipeline.

-------------

Commit messages:
 - 8239589: JavaFX UI will not repaint after reconnecting via Remote Desktop
 - Ressource already freed from pool
 - Recreate if adapterCount is zero
 - Fix whitespace error
 - 8239589: JavaFX UI will not repaint after reconnecting via Remote Desktop

Changes: https://git.openjdk.java.net/jfx/pull/430/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jfx&pr=430&range=00
  Issue: https://bugs.openjdk.java.net/browse/JDK-8239589
  Stats: 850 lines in 47 files changed: 728 ins; 36 del; 86 mod
  Patch: https://git.openjdk.java.net/jfx/pull/430.diff
  Fetch: git fetch https://git.openjdk.java.net/jfx pull/430/head:pull/430

PR: https://git.openjdk.java.net/jfx/pull/430

Reply via email to