Commit d56864e2 authored by Igor Demin's avatar Igor Demin

Redrawer. Fix macOs issues

parent 38ae7bf7
......@@ -69,6 +69,7 @@ native crash in SkiaWindowTest "render single window"
}
init {
setLocation(200,200)
setSize(width, height)
defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
layer.renderer = object : SkiaRenderer {
......@@ -208,6 +209,7 @@ j org.jetbrains.skiko.redrawer.MacOsRedrawer$drawLayer$1.draw()V+7
val window = SkiaWindow()
try {
window.setLocation(200, 200)
window.setSize(400, 400)
window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
window.isUndecorated = true
......
......@@ -51,6 +51,7 @@ class SkiaWindowTest {
fun `render single window`() = swingTest {
val window = SkiaWindow()
try {
window.setLocation(200, 200)
window.setSize(400, 200)
window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
val renderer = RectRenderer(window.layer, 200, 100, Color.RED)
......@@ -74,6 +75,7 @@ class SkiaWindowTest {
fun `resize window`() = swingTest {
val window = SkiaWindow()
try {
window.setLocation(200, 200)
window.setSize(40, 20)
window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
window.layer.renderer = RectRenderer(window.layer, 20, 10, Color.RED)
......@@ -93,6 +95,7 @@ class SkiaWindowTest {
@Test
fun `render three windows`() = swingTest {
fun window(color: Color) = SkiaWindow().apply {
setLocation(200,200)
setSize(400, 200)
defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
layer.renderer = RectRenderer(layer, 200, 100, color)
......@@ -131,6 +134,7 @@ class SkiaWindowTest {
val window = SkiaWindow()
try {
window.setLocation(200, 200)
window.setSize(40, 20)
window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
window.layer.renderer = object : SkiaRenderer {
......@@ -161,6 +165,7 @@ class SkiaWindowTest {
@Test
fun `open windows stress test`() = swingTest {
fun window(isAnimated: Boolean) = SkiaWindow().apply {
setLocation(200,200)
setSize(40, 20)
defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
layer.renderer = if (isAnimated) {
......@@ -219,6 +224,7 @@ class SkiaWindowTest {
val window = SkiaWindow()
try {
window.setLocation(200, 200)
window.setSize(400, 200)
window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
......
......@@ -58,9 +58,14 @@ open class SkiaLayer : HardwareLayer() {
super.dispose()
}
override fun setBounds(x: Int, y: Int, width: Int, height: Int) {
super.setBounds(x, y, width, height)
redrawer?.syncSize()
needRedraw()
}
override fun paint(g: Graphics) {
super.paint(g)
// we don't have to call it in setBounds method, because paint will always be called after setBounds
redrawer?.syncSize()
needRedraw()
}
......
......@@ -14,14 +14,14 @@ internal class MacOsRedrawer(
) : Redrawer {
private val containerLayerPtr = initContainer(layer)
private val drawLayer = object : AWTGLLayer(containerLayerPtr) {
private val drawLayer = object : AWTGLLayer(containerLayerPtr, setNeedsDisplayOnBoundsChange = true) {
override fun draw() = layer.draw()
}
// use a separate layer for vsync, because with single layer we cannot asynchronously update layer
// `update` is suspend, and runBlocking(Dispatchers.Swing) causes dead lock with AppKit Thread.
// AWT has a method to avoid dead locks but it is internal (sun.lwawt.macosx.LWCToolkit.invokeAndWait)
private val vsyncLayer = object : AWTGLLayer(containerLayerPtr) {
private val vsyncLayer = object : AWTGLLayer(containerLayerPtr, setNeedsDisplayOnBoundsChange = false) {
@Volatile
private var needDraw: CompletableDeferred<Unit>? = null
......@@ -34,7 +34,7 @@ internal class MacOsRedrawer(
val opengl = OpenGLApi.instance
opengl.glClearColor(0f, 0f, 0f, 0f)
opengl.glClear(opengl.GL_COLOR_BUFFER_BIT)
needDraw!!.complete(Unit)
needDraw?.complete(Unit)
}
override fun canDraw(): Boolean {
......@@ -83,7 +83,12 @@ internal class MacOsRedrawer(
val globalPosition = convertPoint(layer, layer.x, layer.y, getRootPane(layer))
setContentScale(containerLayerPtr, layer.contentScale)
setContentScale(drawLayer.ptr, layer.contentScale)
drawLayer.setFrame(globalPosition.x, globalPosition.y, layer.width, layer.height)
drawLayer.setFrame(
globalPosition.x,
globalPosition.y,
layer.width.coerceAtLeast(0),
layer.height.coerceAtLeast(0)
)
}
override fun needRedraw() {
......@@ -91,9 +96,9 @@ internal class MacOsRedrawer(
}
}
private open class AWTGLLayer(private val containerPtr: Long) {
private open class AWTGLLayer(private val containerPtr: Long, setNeedsDisplayOnBoundsChange: Boolean) {
@Suppress("LeakingThis")
val ptr = initAWTGLLayer(containerPtr, this)
val ptr = initAWTGLLayer(containerPtr, this, setNeedsDisplayOnBoundsChange)
fun setFrame(x: Int, y: Int, width: Int, height: Int) {
setFrame(containerPtr, ptr, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat())
......@@ -111,7 +116,7 @@ private open class AWTGLLayer(private val containerPtr: Long) {
// Called in AppKit Thread
protected open fun canDraw() = true
// Called in AppKit Thread, shouldn't be called if canDraw returned false
// Called in AppKit Thread
protected open fun draw() = Unit
private external fun isAsynchronous(ptr: Long): Boolean
......@@ -122,5 +127,5 @@ private open class AWTGLLayer(private val containerPtr: Long) {
private external fun initContainer(layer: HardwareLayer): Long
private external fun setContentScale(layerNativePtr: Long, contentScale: Float)
private external fun initAWTGLLayer(containerPtr: Long, layer: AWTGLLayer): Long
private external fun initAWTGLLayer(containerPtr: Long, layer: AWTGLLayer, setNeedsDisplayOnBoundsChange: Boolean): Long
private external fun disposeAWTGLLayer(ptr: Long)
......@@ -27,7 +27,6 @@ JavaVM *jvm = NULL;
[self removeAllAnimations];
[self setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[self setNeedsDisplayOnBoundsChange: YES];
return self;
}
......@@ -109,12 +108,13 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_setCont
layer.contentsScale = contentScale;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initAWTGLLayer(JNIEnv *env, jobject obj, jlong containerPtr, jobject layer)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initAWTGLLayer(JNIEnv *env, jobject obj, jlong containerPtr, jobject layer, jboolean setNeedsDisplayOnBoundsChange)
{
CALayer *container = (CALayer *) containerPtr;
AWTGLLayer *glLayer = [AWTGLLayer new];
glLayer.javaRef = (*env)->NewGlobalRef(env, layer);
[glLayer setNeedsDisplayOnBoundsChange: setNeedsDisplayOnBoundsChange];
[container addSublayer: glLayer];
return (jlong) glLayer;
......
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