Unverified Commit 8d61a57a authored by Igor Demin's avatar Igor Demin Committed by GitHub

Fix rendering of an empty layer on metal (#504)

* Fix rendering of an empty layer on metal

* Fix Windows
parent 47985faa
...@@ -38,17 +38,25 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : JvmContextHandle ...@@ -38,17 +38,25 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : JvmContextHandle
val h = (layer.height * scale).toInt().coerceAtLeast(0) val h = (layer.height * scale).toInt().coerceAtLeast(0)
if (isSizeChanged(w, h) || surface == null) { if (isSizeChanged(w, h) || surface == null) {
disposeCanvas() disposeCanvas()
softwareRedrawer.resize(w, h) if (w > 0 && h > 0) {
surface = softwareRedrawer.acquireSurface() softwareRedrawer.resize(w, h)
canvas = surface!!.canvas surface = softwareRedrawer.acquireSurface()
canvas = surface!!.canvas
} else {
surface = null
canvas = null
}
} }
} }
override fun flush() { override fun flush() {
try { val surface = surface
softwareRedrawer.finishFrame(getPtr(surface!!)) if (surface != null) {
} finally { try {
Reference.reachabilityFence(surface!!) softwareRedrawer.finishFrame(getPtr(surface))
} finally {
Reference.reachabilityFence(surface)
}
} }
} }
} }
\ No newline at end of file
...@@ -34,22 +34,28 @@ internal class MetalContextHandler(layer: SkiaLayer) : JvmContextHandler(layer) ...@@ -34,22 +34,28 @@ internal class MetalContextHandler(layer: SkiaLayer) : JvmContextHandler(layer)
val w = (layer.width * scale).toInt().coerceAtLeast(0) val w = (layer.width * scale).toInt().coerceAtLeast(0)
val h = (layer.height * scale).toInt().coerceAtLeast(0) val h = (layer.height * scale).toInt().coerceAtLeast(0)
renderTarget = metalRedrawer.makeRenderTarget(w, h) if (w > 0 && h > 0) {
renderTarget = metalRedrawer.makeRenderTarget(w, h)
surface = Surface.makeFromBackendRenderTarget( surface = Surface.makeFromBackendRenderTarget(
context!!, context!!,
renderTarget!!, renderTarget!!,
SurfaceOrigin.TOP_LEFT, SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888, SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface") ) ?: throw RenderException("Cannot create surface")
canvas = surface!!.canvas canvas = surface!!.canvas
} else {
renderTarget = null
surface = null
canvas = null
}
} }
override fun flush() { override fun flush() {
super.flush() super.flush()
surface!!.flushAndSubmit() surface?.flushAndSubmit()
metalRedrawer.finishFrame() metalRedrawer.finishFrame()
} }
......
...@@ -47,23 +47,29 @@ internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer, lay ...@@ -47,23 +47,29 @@ internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer, lay
metalRedrawer.syncSize() metalRedrawer.syncSize()
} }
renderTarget = metalRedrawer.makeRenderTarget(w, h) if (w > 0 && h > 0) {
renderTarget = metalRedrawer.makeRenderTarget(w, h)
surface = Surface.makeFromBackendRenderTarget( surface = Surface.makeFromBackendRenderTarget(
context!!, context!!,
renderTarget!!, renderTarget!!,
SurfaceOrigin.TOP_LEFT, SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888, SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface") ) ?: throw RenderException("Cannot create surface")
canvas = surface!!.canvas canvas = surface!!.canvas
} else {
renderTarget = null
surface = null
canvas = null
}
} }
override fun flush() { override fun flush() {
// TODO: maybe make flush async as in JVM version. // TODO: maybe make flush async as in JVM version.
super.flush() super.flush()
surface!!.flushAndSubmit() surface?.flushAndSubmit()
metalRedrawer.finishFrame() metalRedrawer.finishFrame()
} }
......
...@@ -25,6 +25,7 @@ import java.awt.Color ...@@ -25,6 +25,7 @@ import java.awt.Color
import java.awt.Dimension import java.awt.Dimension
import java.awt.event.WindowEvent import java.awt.event.WindowEvent
import javax.swing.JFrame import javax.swing.JFrame
import javax.swing.JLayeredPane
import javax.swing.WindowConstants import javax.swing.WindowConstants
import kotlin.random.Random import kotlin.random.Random
import kotlin.test.assertTrue import kotlin.test.assertTrue
...@@ -135,6 +136,55 @@ class SkiaLayerTest { ...@@ -135,6 +136,55 @@ class SkiaLayerTest {
} }
} }
@Test
fun `render empty layer`() = uiTest {
val window = JFrame()
val layer = SkiaLayer(
properties = SkiaLayerProperties(renderApi = renderApi)
)
var renderedWidth = -1
layer.skikoView = object : SkikoView {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
renderedWidth = width
}
}
layer.size = Dimension(0, 0)
val density = window.graphicsConfiguration.defaultTransform.scaleX
try {
val panel = JLayeredPane()
panel.add(layer)
window.contentPane.add(panel)
window.setLocation(200, 200)
window.size = Dimension(200, 200)
window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
window.isUndecorated = true
window.isVisible = true
layer.needRedraw()
delay(1000)
assertEquals(0, renderedWidth)
renderedWidth = -1
layer.needRedraw()
delay(1000)
assertEquals(0, renderedWidth)
renderedWidth = -1
layer.size = Dimension(30, 40)
layer.needRedraw()
delay(1000)
assertEquals((30 * density).toInt(), renderedWidth)
renderedWidth = -1
layer.size = Dimension(0, 0)
layer.needRedraw()
delay(1000)
assertEquals(0, renderedWidth)
} finally {
layer.dispose()
window.close()
}
}
@Test @Test
fun `resize window`() = uiTest { fun `resize window`() = uiTest {
val window = UiTestWindow() val window = UiTestWindow()
......
...@@ -35,23 +35,29 @@ internal class MacOsMetalContextHandler(layer: SkiaLayer) : ContextHandler(layer ...@@ -35,23 +35,29 @@ internal class MacOsMetalContextHandler(layer: SkiaLayer) : ContextHandler(layer
val w = (layer.nsView.frame.useContents { size.width } * scale).toInt().coerceAtLeast(0) val w = (layer.nsView.frame.useContents { size.width } * scale).toInt().coerceAtLeast(0)
val h = (layer.nsView.frame.useContents { size.height } * scale).toInt().coerceAtLeast(0) val h = (layer.nsView.frame.useContents { size.height } * scale).toInt().coerceAtLeast(0)
renderTarget = metalRedrawer.makeRenderTarget(w, h) if (w > 0 && h > 0) {
renderTarget = metalRedrawer.makeRenderTarget(w, h)
surface = Surface.makeFromBackendRenderTarget( surface = Surface.makeFromBackendRenderTarget(
context!!, context!!,
renderTarget!!, renderTarget!!,
SurfaceOrigin.TOP_LEFT, SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888, SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface") ) ?: throw RenderException("Cannot create surface")
canvas = surface!!.canvas canvas = surface!!.canvas
} else {
renderTarget = null
surface = null
canvas = null
}
} }
override fun flush() { override fun flush() {
// TODO: maybe make flush async as in JVM version. // TODO: maybe make flush async as in JVM version.
super.flush() super.flush()
surface!!.flushAndSubmit() surface?.flushAndSubmit()
metalRedrawer.finishFrame() metalRedrawer.finishFrame()
} }
......
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