Skip to content

Commit

Permalink
Fix rendering of an empty layer on metal (#504)
Browse files Browse the repository at this point in the history
* Fix rendering of an empty layer on metal

* Fix Windows
  • Loading branch information
igordmn authored Feb 21, 2022
1 parent 47985fa commit 8d61a57
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,25 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : JvmContextHandle
val h = (layer.height * scale).toInt().coerceAtLeast(0)
if (isSizeChanged(w, h) || surface == null) {
disposeCanvas()
softwareRedrawer.resize(w, h)
surface = softwareRedrawer.acquireSurface()
canvas = surface!!.canvas
if (w > 0 && h > 0) {
softwareRedrawer.resize(w, h)
surface = softwareRedrawer.acquireSurface()
canvas = surface!!.canvas
} else {
surface = null
canvas = null
}
}
}

override fun flush() {
try {
softwareRedrawer.finishFrame(getPtr(surface!!))
} finally {
Reference.reachabilityFence(surface!!)
val surface = surface
if (surface != null) {
try {
softwareRedrawer.finishFrame(getPtr(surface))
} finally {
Reference.reachabilityFence(surface)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,28 @@ internal class MetalContextHandler(layer: SkiaLayer) : JvmContextHandler(layer)
val w = (layer.width * 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(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface")
surface = Surface.makeFromBackendRenderTarget(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface")

canvas = surface!!.canvas
canvas = surface!!.canvas
} else {
renderTarget = null
surface = null
canvas = null
}
}

override fun flush() {
super.flush()
surface!!.flushAndSubmit()
surface?.flushAndSubmit()
metalRedrawer.finishFrame()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,29 @@ internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer, lay
metalRedrawer.syncSize()
}

renderTarget = metalRedrawer.makeRenderTarget(w, h)
if (w > 0 && h > 0) {
renderTarget = metalRedrawer.makeRenderTarget(w, h)

surface = Surface.makeFromBackendRenderTarget(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface")
surface = Surface.makeFromBackendRenderTarget(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface")

canvas = surface!!.canvas
canvas = surface!!.canvas
} else {
renderTarget = null
surface = null
canvas = null
}
}

override fun flush() {
// TODO: maybe make flush async as in JVM version.
super.flush()
surface!!.flushAndSubmit()
surface?.flushAndSubmit()
metalRedrawer.finishFrame()
}

Expand Down
50 changes: 50 additions & 0 deletions skiko/src/jvmTest/kotlin/org/jetbrains/skiko/SkiaLayerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import java.awt.Color
import java.awt.Dimension
import java.awt.event.WindowEvent
import javax.swing.JFrame
import javax.swing.JLayeredPane
import javax.swing.WindowConstants
import kotlin.random.Random
import kotlin.test.assertTrue
Expand Down Expand Up @@ -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
fun `resize window`() = uiTest {
val window = UiTestWindow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,29 @@ internal class MacOsMetalContextHandler(layer: SkiaLayer) : ContextHandler(layer
val w = (layer.nsView.frame.useContents { size.width } * 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(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface")
surface = Surface.makeFromBackendRenderTarget(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.BGRA_8888,
ColorSpace.sRGB
) ?: throw RenderException("Cannot create surface")

canvas = surface!!.canvas
canvas = surface!!.canvas
} else {
renderTarget = null
surface = null
canvas = null
}
}

override fun flush() {
// TODO: maybe make flush async as in JVM version.
super.flush()
surface!!.flushAndSubmit()
surface?.flushAndSubmit()
metalRedrawer.finishFrame()
}

Expand Down

0 comments on commit 8d61a57

Please sign in to comment.