Commit 930ab399 authored by Igor Demin's avatar Igor Demin

macOs. call update only once per draw if vsync is disabled

parent 95056dd1
...@@ -30,7 +30,7 @@ internal class MacOsOpenGLRedrawer( ...@@ -30,7 +30,7 @@ internal class MacOsOpenGLRedrawer(
// AWT has a method to avoid dead locks but it is internal (sun.lwawt.macosx.LWCToolkit.invokeAndWait) // AWT has a method to avoid dead locks but it is internal (sun.lwawt.macosx.LWCToolkit.invokeAndWait)
private val vsyncLayer = object : AWTGLLayer(containerLayerPtr, setNeedsDisplayOnBoundsChange = false) { private val vsyncLayer = object : AWTGLLayer(containerLayerPtr, setNeedsDisplayOnBoundsChange = false) {
@Volatile @Volatile
private var needDraw: CompletableDeferred<Unit>? = null private var canDraw = false
init { init {
setFrame(0, 0, 1, 1) // if frame has zero size then it will be not drawn at all setFrame(0, 0, 1, 1) // if frame has zero size then it will be not drawn at all
...@@ -41,21 +41,17 @@ internal class MacOsOpenGLRedrawer( ...@@ -41,21 +41,17 @@ internal class MacOsOpenGLRedrawer(
val opengl = OpenGLApi.instance val opengl = OpenGLApi.instance
opengl.glClearColor(0f, 0f, 0f, 0f) opengl.glClearColor(0f, 0f, 0f, 0f)
opengl.glClear(opengl.GL_COLOR_BUFFER_BIT) opengl.glClear(opengl.GL_COLOR_BUFFER_BIT)
needDraw?.complete(Unit)
} }
override fun canDraw(): Boolean { override fun canDraw(): Boolean {
val canDraw = needDraw != null val canDraw = canDraw
if (!canDraw) { if (!canDraw) {
isAsynchronous = false // stop asynchronous mode so we don't waste CPU cycles isAsynchronous = false // stop asynchronous mode so we don't waste CPU cycles
} }
return canDraw return canDraw
} }
suspend fun sync() { override fun setNeedsDisplay() {
check(needDraw == null)
needDraw = CompletableDeferred()
// Use asynchronous mode instead of just setNeedsDisplay, // Use asynchronous mode instead of just setNeedsDisplay,
// so Core Animation will wait for the next frame in vsync signal // so Core Animation will wait for the next frame in vsync signal
// //
...@@ -68,17 +64,26 @@ internal class MacOsOpenGLRedrawer( ...@@ -68,17 +64,26 @@ internal class MacOsOpenGLRedrawer(
isAsynchronous = true isAsynchronous = true
super.setNeedsDisplay() super.setNeedsDisplay()
} }
}
needDraw!!.await() suspend fun sync() {
needDraw = null canDraw = true
display()
canDraw = false
} }
} }
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) { private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
synchronized(drawLock) {
layer.update(System.nanoTime()) layer.update(System.nanoTime())
drawLayer.setNeedsDisplay() }
if (SkikoProperties.vsyncEnabled) { if (SkikoProperties.vsyncEnabled) {
drawLayer.setNeedsDisplay()
vsyncLayer.sync() vsyncLayer.sync()
} else {
// If vsync is disabled we should await the drawing to end.
// Otherwise we will call 'update' multiple times.
drawLayer.display()
} }
} }
...@@ -115,6 +120,9 @@ private abstract class AWTGLLayer(private val containerPtr: Long, setNeedsDispla ...@@ -115,6 +120,9 @@ private abstract class AWTGLLayer(private val containerPtr: Long, setNeedsDispla
@Suppress("LeakingThis") @Suppress("LeakingThis")
val ptr = initAWTGLLayer(containerPtr, this, setNeedsDisplayOnBoundsChange) val ptr = initAWTGLLayer(containerPtr, this, setNeedsDisplayOnBoundsChange)
@Volatile
private var onDraw: CompletableDeferred<Unit>? = null
fun setFrame(x: Int, y: Int, width: Int, height: Int) { fun setFrame(x: Int, y: Int, width: Int, height: Int) {
setFrame(containerPtr, ptr, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat()) setFrame(containerPtr, ptr, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat())
} }
...@@ -128,6 +136,14 @@ private abstract class AWTGLLayer(private val containerPtr: Long, setNeedsDispla ...@@ -128,6 +136,14 @@ private abstract class AWTGLLayer(private val containerPtr: Long, setNeedsDispla
open fun setNeedsDisplay() = setNeedsDisplayOnMainThread(ptr) open fun setNeedsDisplay() = setNeedsDisplayOnMainThread(ptr)
suspend fun display() {
check(onDraw == null)
onDraw = CompletableDeferred()
setNeedsDisplay()
onDraw!!.await()
onDraw = null
}
// Called in AppKit Thread // Called in AppKit Thread
protected open fun canDraw() = true protected open fun canDraw() = true
...@@ -138,6 +154,7 @@ private abstract class AWTGLLayer(private val containerPtr: Long, setNeedsDispla ...@@ -138,6 +154,7 @@ private abstract class AWTGLLayer(private val containerPtr: Long, setNeedsDispla
} catch (e: Throwable) { } catch (e: Throwable) {
e.printStackTrace() e.printStackTrace()
} }
onDraw?.complete(Unit)
} }
// Called in AppKit Thread // Called in AppKit Thread
......
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