Unverified Commit 7c12a857 authored by Nikolai Rykunov's avatar Nikolai Rykunov Committed by GitHub

Fix memory leak because of missing autoreleasepool in offscreen rendering for Swing interop (#764)

parent 1afda4d3
...@@ -25,7 +25,26 @@ internal fun MetalAdapter.dispose() { ...@@ -25,7 +25,26 @@ internal fun MetalAdapter.dispose() {
disposeAdapter(ptr) disposeAdapter(ptr)
} }
/**
* [@autoreleasepool](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html)
*/
@Suppress("SpellCheckingInspection")
internal inline fun <R> autoreleasepool(block: () -> R): R {
val handle = openAutoreleasepool()
return try {
block()
} finally {
closeAutoreleasepool(handle)
}
}
private external fun chooseAdapter(adapterPriority: Int): Long private external fun chooseAdapter(adapterPriority: Int): Long
private external fun disposeAdapter(adapter: Long) private external fun disposeAdapter(adapter: Long)
private external fun getAdapterName(adapter: Long): String private external fun getAdapterName(adapter: Long): String
private external fun getAdapterMemorySize(adapter: Long): Long private external fun getAdapterMemorySize(adapter: Long): Long
@Suppress("SpellCheckingInspection")
private external fun openAutoreleasepool(): Long
@Suppress("SpellCheckingInspection")
private external fun closeAutoreleasepool(handle: Long)
\ No newline at end of file
...@@ -154,11 +154,8 @@ internal class MetalRedrawer( ...@@ -154,11 +154,8 @@ internal class MetalRedrawer(
// - it makes frames consistent and limits FPS // - it makes frames consistent and limits FPS
displayLinkThrottler.waitVSync(windowPtr = layer.windowHandle) displayLinkThrottler.waitVSync(windowPtr = layer.windowHandle)
val handle = startRendering() autoreleasepool {
try {
contextHandler.draw() contextHandler.draw()
} finally {
endRendering(handle)
} }
} }
} }
...@@ -188,6 +185,4 @@ internal class MetalRedrawer( ...@@ -188,6 +185,4 @@ internal class MetalRedrawer(
private external fun setContentScale(device: Long, contentScale: Float) private external fun setContentScale(device: Long, contentScale: Float)
private external fun setVSyncEnabled(device: Long, enabled: Boolean) private external fun setVSyncEnabled(device: Long, enabled: Boolean)
private external fun isOccluded(window: Long): Boolean private external fun isOccluded(window: Long): Boolean
private external fun startRendering(): Long
private external fun endRendering(handle: Long)
} }
...@@ -44,7 +44,9 @@ internal class MetalSwingRedrawer( ...@@ -44,7 +44,9 @@ internal class MetalSwingRedrawer(
super.dispose() super.dispose()
} }
override fun onRender(g: Graphics2D, width: Int, height: Int, nanoTime: Long) = autoCloseScope { override fun onRender(g: Graphics2D, width: Int, height: Int, nanoTime: Long) {
autoreleasepool {
autoCloseScope {
val renderTarget = makeRenderTarget(width, height).autoClose() val renderTarget = makeRenderTarget(width, height).autoClose()
val surface = Surface.makeFromBackendRenderTarget( val surface = Surface.makeFromBackendRenderTarget(
context, context,
...@@ -60,6 +62,8 @@ internal class MetalSwingRedrawer( ...@@ -60,6 +62,8 @@ internal class MetalSwingRedrawer(
skikoView.onRender(canvas, width, height, nanoTime) skikoView.onRender(canvas, width, height, nanoTime)
flush(surface, g) flush(surface, g)
} }
}
}
private fun flush(surface: Surface, g: Graphics2D) { private fun flush(surface: Surface, g: Graphics2D) {
surface.flushAndSubmit(syncCpu = true) surface.flushAndSubmit(syncCpu = true)
......
...@@ -26,6 +26,21 @@ ...@@ -26,6 +26,21 @@
extern "C" extern "C"
{ {
extern "C" void* objc_autoreleasePoolPush(void);
extern "C" void objc_autoreleasePoolPop(void*);
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_MetalApiKt_openAutoreleasepool(
JNIEnv * env, jobject redrawer)
{
return (jlong)objc_autoreleasePoolPush();
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_MetalApiKt_closeAutoreleasepool(
JNIEnv * env, jobject redrawer, jlong handle)
{
objc_autoreleasePoolPop((void*)handle);
}
BOOL isUsingIntegratedGPU() { BOOL isUsingIntegratedGPU() {
kern_return_t kernResult = 0; kern_return_t kernResult = 0;
io_iterator_t iterator = IO_OBJECT_NULL; io_iterator_t iterator = IO_OBJECT_NULL;
......
...@@ -54,21 +54,6 @@ ...@@ -54,21 +54,6 @@
extern "C" extern "C"
{ {
extern "C" void* objc_autoreleasePoolPush(void);
extern "C" void objc_autoreleasePoolPop(void*);
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_startRendering(
JNIEnv * env, jobject redrawer)
{
return (jlong)objc_autoreleasePoolPush();
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_endRendering(
JNIEnv * env, jobject redrawer, jlong handle)
{
objc_autoreleasePoolPop((void*)handle);
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMetalDevice( JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMetalDevice(
JNIEnv *env, jobject redrawer, jlong windowPtr, jboolean transparency, jlong adapterPtr, jlong platformInfoPtr) JNIEnv *env, jobject redrawer, jlong windowPtr, jboolean transparency, jlong adapterPtr, jlong platformInfoPtr)
{ {
......
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