On Wed, 17 Mar 2021 20:47:09 GMT, Kevin Rushforth <k...@openjdk.org> wrote:

>> 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.
>
> Kevin Rushforth has updated the pull request with a new target base due to a 
> merge or a rebase. The incremental webrev excludes the unrelated changes 
> brought in by the merge/rebase. The pull request contains six additional 
> commits since the last revision:
> 
>  - Merge branch 'master' into 8239589-rdp-reconnect
>  - 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

I did a pass over the review and left a few inline comments pointing out minor 
changes that I plan to make (in print statements and comments).

modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DContext.java line 
158:

> 156:         int hr = D3DResourceFactory.nTestCooperativeLevel(pContext);
> 157: 
> 158:         if (PrismSettings.verbose && hr != D3D_OK) {

This makes `prism.verbose` too noisy, since it will sometimes continually print 
non-failing return codes such as `S_PRESENT_MODE_CHANGED` or 
`S_PRESENT_OCCLUDED`. Separately, I might file an RFE to handle 
`S_PRESENT_MODE_CHANGED` which can happen in many cases (not related to this 
bug) such as changing the resolution of of the screen or plugging / unplugging 
a monitor.

I'll change this to: `PrismSettings.verbose && FAILED(hr)`

modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DPipeline.java line 
186:

> 184:     void reinitialize() {
> 185:         if (PrismSettings.verbose) {
> 186:             System.err.println("D3DPipeline: reinitialize after device 
> lost");

This probably should say "...device removed"

modules/javafx.graphics/src/main/java/com/sun/prism/impl/ps/PaintHelper.java 
line 161:

> 159: 
> 160:         // gradientCacheTexture is left permanent and locked, although 
> we still
> 161:         // must check for isSurfaceLost() is the case the device is 
> disposed.

Typo: "is the case..." --> "in case..."

modules/javafx.graphics/src/main/java/com/sun/prism/impl/ps/PaintHelper.java 
line 174:

> 172: 
> 173:         // gtexCacheTexture is left permanent and locked, although we 
> still
> 174:         // must check for isSurfaceLost() is the case the device is 
> disposed.

Typo: "is the case..." --> "in case..."

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

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

Reply via email to