Unverified Commit 57dea506 authored by Elijah Semyonov's avatar Elijah Semyonov Committed by GitHub

Fix crash when creating SwingRedrawer on DirectX (#917)

### Changes
Throw `RenderException` when constructing `Direct3DSwingRedrawer` with
`nullptr` device. (Similar to `Direct3DRedrawer`)

To avoid crash in:
```
DirectXOffscreenDevice *d3dDevice = fromJavaPointer<DirectXOffscreenDevice *>(devicePtr);
GrD3DBackendContext backendContext = d3dDevice->backendContext;
return toJavaPointer(GrDirectContext::MakeDirect3D(backendContext).release());
```

### Fixes

Speculative fix for crash with a stack head below:
```
---------------  T H R E A D  ---------------

Current thread (0x000001cbcb0793f0):  JavaThread "AWT-EventQueue-0" [_thread_in_native, id=16744, stack(0x0000009488c00000,0x0000009488d00000)]

Stack: [0x0000009488c00000,0x0000009488d00000],  sp=0x0000009488cfc670,  free space=1009k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [skiko-windows-x64.dll+0x58afa]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.jetbrains.skiko.swing.Direct3DSwingRedrawer.makeDirectXContext(J)J+0
```

### Note
I've found suspicious place in
```kotlin
// RedrawManager.kt:30
_renderApi = fallbackRenderApiQueue.removeAt(0)
_redrawer = redrawerFactory(_renderApi, redrawer)
```
Seems like `redrawer` is disposed twice if `redrawerFactory` throws
(both paths constructing `RedrawerManager` are affected).

@igordmn can you have a look?
It's a universal path for all desktop users, so I wonder why it didn't
backfire, if it's indeed incorrect.
May be it's because we don't really call `redrawerFactory` if a redrawer
was constructed correctly, so disposal of old one doesn't ever get
called in this context. I'm not sure where are the invariant boundaries
here.
parent 37ef84bf
...@@ -30,6 +30,7 @@ internal class RedrawerManager<R>( ...@@ -30,6 +30,7 @@ internal class RedrawerManager<R>(
_renderApi = fallbackRenderApiQueue.removeAt(0) _renderApi = fallbackRenderApiQueue.removeAt(0)
_redrawer = redrawerFactory(_renderApi, redrawer) _redrawer = redrawerFactory(_renderApi, redrawer)
} catch (e: RenderException) { } catch (e: RenderException) {
_redrawer = null
Logger.warn(e) { "Fallback to next API" } Logger.warn(e) { "Fallback to next API" }
thrown = true thrown = true
} }
......
...@@ -23,9 +23,13 @@ internal class Direct3DSwingRedrawer( ...@@ -23,9 +23,13 @@ internal class Direct3DSwingRedrawer(
private val swingOffscreenDrawer = SwingOffscreenDrawer(swingLayerProperties) private val swingOffscreenDrawer = SwingOffscreenDrawer(swingLayerProperties)
private val context = DirectContext( private val context = if (device == 0L) {
makeDirectXContext(device) throw RenderException("Failed to create DirectX12 device.")
) } else {
DirectContext(
makeDirectXContext(device)
)
}
private var texturePtr: Long = 0 private var texturePtr: Long = 0
private var bytesToDraw = ByteArray(0) private var bytesToDraw = ByteArray(0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment