Unverified Commit f6f67b81 authored by Igor Demin's avatar Igor Demin Committed by GitHub

Merge pull request #55 from JetBrains/immediate-redraw

Immediate redraw on resize and window start
parents 6ad0a4e6 98358124
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="SkijaInjectSample (software)" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/samples/SkijaInjectSample" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Dskiko.renderApi=SOFTWARE" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="run" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2">
<option name="Gradle.BeforeRunTask" enabled="false" tasks="publishToMavenLocal" externalProjectPath="$PROJECT_DIR$/skiko" vmOptions="" scriptParameters="" />
</method>
</configuration>
</component>
\ No newline at end of file
......@@ -89,7 +89,7 @@ class Renderer(
var canvas: Canvas? = null
override suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
this.canvas = canvas
val contentScale = layer.contentScale
canvas.scale(contentScale, contentScale)
......
......@@ -73,7 +73,7 @@ native crash in SkiaWindowTest "render single window"
setSize(width, height)
defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
layer.renderer = object : SkiaRenderer {
override suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
if (canCollect && frameTimes.size < frameCount) {
frameTimes.add(System.nanoTime()) // we check the real time, not the time provided by the argument
}
......@@ -183,7 +183,7 @@ j org.jetbrains.skiko.redrawer.MacOsRedrawer$drawLayer$1.draw()V+7
var t1 = Long.MAX_VALUE
val refreshRate = window.graphicsConfiguration.device.displayMode.refreshRate
override suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
val t2 = System.nanoTime()
val frameTime = (t2 - t1).coerceAtLeast(0)
t1 = t2
......
......@@ -138,7 +138,7 @@ class SkiaWindowTest {
window.setSize(40, 20)
window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
window.layer.renderer = object : SkiaRenderer {
override suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
renderCount++
}
}
......@@ -231,7 +231,7 @@ class SkiaWindowTest {
val paragraph by lazy { paragraph(window.layer.contentScale * 40, "=-+Нп") }
window.layer.renderer = object : SkiaRenderer {
override suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
paragraph.layout(Float.POSITIVE_INFINITY)
paragraph.paint(canvas, 0f, 0f)
}
......@@ -259,7 +259,7 @@ class SkiaWindowTest {
var rectHeight: Int,
private val rectColor: Color
) : SkiaRenderer {
override suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
val dpi = layer.contentScale
canvas.drawRect(Rect(0f, 0f, width.toFloat(), height.toFloat()), Paint().apply {
color = Color.WHITE.rgb
......@@ -278,7 +278,7 @@ class SkiaWindowTest {
private var oldNanoTime = Long.MAX_VALUE
private var x = 0.0
override suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
canvas.clear(Color.WHITE.rgb)
val dt = (nanoTime - oldNanoTime).coerceAtLeast(0) / 1E9
......
......@@ -14,7 +14,7 @@ extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt);
extern "C"
{
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_lockDrawingSurfaceNative(JNIEnv *env, jobject redrawer, jobject layer)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_lockDrawingSurfaceNative(JNIEnv *env, jobject redrawer, jobject layer)
{
JAWT awt;
awt.version = (jint)JAWT_VERSION_9;
......@@ -30,7 +30,7 @@ extern "C"
return static_cast<jlong>(reinterpret_cast<uintptr_t>(ds));
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_unlockDrawingSurfaceNative(JNIEnv *env, jobject redrawer, jlong drawingSurfacePtr)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_unlockDrawingSurfaceNative(JNIEnv *env, jobject redrawer, jlong drawingSurfacePtr)
{
JAWT_DrawingSurface *ds = reinterpret_cast<JAWT_DrawingSurface *>(static_cast<uintptr_t>(drawingSurfacePtr));
JAWT awt;
......@@ -47,7 +47,7 @@ extern "C"
return static_cast<jlong>(reinterpret_cast<uintptr_t>(ds));
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_getDisplay(JNIEnv *env, jobject redrawer, jlong drawingSurfacePtr)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_getDisplay(JNIEnv *env, jobject redrawer, jlong drawingSurfacePtr)
{
JAWT_DrawingSurface *ds = reinterpret_cast<JAWT_DrawingSurface *>(static_cast<uintptr_t>(drawingSurfacePtr));
JAWT_DrawingSurfaceInfo *dsi = ds->GetDrawingSurfaceInfo(ds);
......@@ -59,7 +59,7 @@ extern "C"
return static_cast<jlong>(reinterpret_cast<uintptr_t>(display));
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_getWindow(JNIEnv *env, jobject redrawer, jlong drawingSurfacePtr)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_getWindow(JNIEnv *env, jobject redrawer, jlong drawingSurfacePtr)
{
JAWT_DrawingSurface *ds = reinterpret_cast<JAWT_DrawingSurface *>(static_cast<uintptr_t>(drawingSurfacePtr));
JAWT_DrawingSurfaceInfo *dsi = ds->GetDrawingSurfaceInfo(ds);
......@@ -71,7 +71,7 @@ extern "C"
return static_cast<jlong>(reinterpret_cast<uintptr_t>(window));
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_setSwapInterval(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong windowPtr, jint interval)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_setSwapInterval(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong windowPtr, jint interval)
{
Display *display = reinterpret_cast<Display *>(static_cast<uintptr_t>(displayPtr));
Window window = reinterpret_cast<Window>(static_cast<uintptr_t>(windowPtr));
......@@ -104,7 +104,7 @@ extern "C"
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_swapBuffers(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong windowPtr)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_swapBuffers(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong windowPtr)
{
Display *display = reinterpret_cast<Display *>(static_cast<uintptr_t>(displayPtr));
Window window = reinterpret_cast<Window>(static_cast<uintptr_t>(windowPtr));
......@@ -112,7 +112,7 @@ extern "C"
glXSwapBuffers(display, window);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_makeCurrent(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong windowPtr, jlong contextPtr)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_makeCurrent(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong windowPtr, jlong contextPtr)
{
Display *display = reinterpret_cast<Display *>(static_cast<uintptr_t>(displayPtr));
Window window = reinterpret_cast<Window>(static_cast<uintptr_t>(windowPtr));
......@@ -121,7 +121,7 @@ extern "C"
glXMakeCurrent(display, window, *context);
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_createContext(JNIEnv *env, jobject redrawer, jlong displayPtr)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_createContext(JNIEnv *env, jobject redrawer, jlong displayPtr)
{
Display *display = reinterpret_cast<Display *>(static_cast<uintptr_t>(displayPtr));
GLint att[] = {GLX_RGBA, GLX_DOUBLEBUFFER, True, None};
......@@ -131,7 +131,7 @@ extern "C"
return static_cast<jlong>(reinterpret_cast<uintptr_t>(context));
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_destroyContext(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong contextPtr)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_LinuxOpenGLRedrawerKt_destroyContext(JNIEnv *env, jobject redrawer, jlong displayPtr, jlong contextPtr)
{
Display *display = reinterpret_cast<Display *>(static_cast<uintptr_t>(displayPtr));
GLXContext *context = reinterpret_cast<GLXContext *>(static_cast<uintptr_t>(contextPtr));
......
......@@ -8,7 +8,7 @@ extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt);
extern "C"
{
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_getDevice(JNIEnv *env, jobject redrawer, jobject layer)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_WindowsOpenGLRedrawerKt_getDevice(JNIEnv *env, jobject redrawer, jobject layer)
{
JAWT awt;
awt.version = (jint)JAWT_VERSION_9;
......@@ -48,7 +48,7 @@ extern "C"
return static_cast<jlong>(reinterpret_cast<uintptr_t>(device));
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_setSwapInterval(JNIEnv *env, jobject redrawer, jint interval)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsOpenGLRedrawerKt_setSwapInterval(JNIEnv *env, jobject redrawer, jint interval)
{
typedef BOOL (WINAPI *PFNWGLSWAPINTERVALEXTPROC)(int interval);
// according to [https://opengl.gpuinfo.org/listreports.php?extension=WGL_EXT_swap_control&option=not] (filter by OS=windows)
......@@ -60,32 +60,32 @@ extern "C"
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_swapBuffers(JNIEnv *env, jobject redrawer, jlong devicePtr)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsOpenGLRedrawerKt_swapBuffers(JNIEnv *env, jobject redrawer, jlong devicePtr)
{
HDC device = reinterpret_cast<HDC>(static_cast<uintptr_t>(devicePtr));
SwapBuffers(device);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_makeCurrent(JNIEnv *env, jobject redrawer, jlong devicePtr, jlong contextPtr)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsOpenGLRedrawerKt_makeCurrent(JNIEnv *env, jobject redrawer, jlong devicePtr, jlong contextPtr)
{
HDC device = reinterpret_cast<HDC>(static_cast<uintptr_t>(devicePtr));
HGLRC context = reinterpret_cast<HGLRC>(static_cast<uintptr_t>(contextPtr));
wglMakeCurrent(device, context);
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_createContext(JNIEnv *env, jobject redrawer, jlong devicePtr)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_WindowsOpenGLRedrawerKt_createContext(JNIEnv *env, jobject redrawer, jlong devicePtr)
{
HDC device = reinterpret_cast<HDC>(static_cast<uintptr_t>(devicePtr));
return static_cast<jlong>(reinterpret_cast<uintptr_t>(wglCreateContext(device)));
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_deleteContext(JNIEnv *env, jobject redrawer, jlong contextPtr)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsOpenGLRedrawerKt_deleteContext(JNIEnv *env, jobject redrawer, jlong contextPtr)
{
HGLRC context = reinterpret_cast<HGLRC>(static_cast<uintptr_t>(contextPtr));
wglDeleteContext(context);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_dwmFlush(JNIEnv *env, jobject redrawer)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_WindowsOpenGLRedrawerKt_dwmFlush(JNIEnv *env, jobject redrawer)
{
DwmFlush();
}
......
......@@ -62,7 +62,7 @@ abstract class HardwareLayer : Canvas() {
}
// Should be called in Swing thread
internal abstract suspend fun update(nanoTime: Long)
internal abstract fun update(nanoTime: Long)
// Should be called in the OpenGL thread, and only once after update
internal abstract fun draw()
......
package org.jetbrains.skiko
import org.jetbrains.skiko.GraphicsApi
import org.jetbrains.skiko.context.renderApi
import org.jetbrains.skiko.redrawer.LinuxRedrawer
import org.jetbrains.skiko.redrawer.MacOsRedrawer
import org.jetbrains.skiko.SkikoProperties.renderApi
import org.jetbrains.skiko.redrawer.LinuxOpenGLRedrawer
import org.jetbrains.skiko.redrawer.MacOsOpenGLRedrawer
import org.jetbrains.skiko.redrawer.RasterRedrawer
import org.jetbrains.skiko.redrawer.Redrawer
import org.jetbrains.skiko.redrawer.WindowsRedrawer
import org.jetbrains.skiko.redrawer.WindowsOpenGLRedrawer
import java.awt.Component
import java.awt.Window
import javax.swing.SwingUtilities
......@@ -35,7 +34,7 @@ internal val platformOperations: PlatformOperations by lazy {
override fun createRedrawer(layer: HardwareLayer) = when(renderApi) {
GraphicsApi.SOFTWARE -> RasterRedrawer(layer)
else -> MacOsRedrawer(layer)
else -> MacOsOpenGLRedrawer(layer)
}
}
OS.Windows -> {
......@@ -58,7 +57,7 @@ internal val platformOperations: PlatformOperations by lazy {
override fun createRedrawer(layer: HardwareLayer) = when(renderApi) {
GraphicsApi.SOFTWARE -> RasterRedrawer(layer)
else -> WindowsRedrawer(layer)
else -> WindowsOpenGLRedrawer(layer)
}
}
}
......@@ -94,7 +93,7 @@ internal val platformOperations: PlatformOperations by lazy {
override fun createRedrawer(layer: HardwareLayer) = when(renderApi) {
GraphicsApi.SOFTWARE -> RasterRedrawer(layer)
else -> LinuxRedrawer(layer)
else -> LinuxOpenGLRedrawer(layer)
}
}
}
......
......@@ -9,7 +9,7 @@ import java.awt.Graphics
import javax.swing.SwingUtilities.isEventDispatchThread
interface SkiaRenderer {
suspend fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long)
fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long)
}
private class PictureHolder(val instance: Picture, val width: Int, val height: Int)
......@@ -33,7 +33,7 @@ open class SkiaLayer : HardwareLayer() {
super.init()
redrawer = platformOperations.createRedrawer(this)
redrawer?.syncSize()
needRedraw()
redrawer?.redrawImmediately()
}
override fun dispose() {
......@@ -49,7 +49,7 @@ open class SkiaLayer : HardwareLayer() {
override fun setBounds(x: Int, y: Int, width: Int, height: Int) {
super.setBounds(x, y, width, height)
redrawer?.syncSize()
needRedraw()
redrawer?.redrawImmediately()
}
override fun paint(g: Graphics) {
......@@ -69,7 +69,7 @@ open class SkiaLayer : HardwareLayer() {
probability = SkikoProperties.fpsProbability
)
override suspend fun update(nanoTime: Long) {
override fun update(nanoTime: Long) {
check(!isDisposed)
check(isEventDispatchThread())
......
......@@ -8,6 +8,24 @@ internal object SkikoProperties {
val fpsCount: Int by property("skiko.fps.count", default = 300)
val fpsProbability: Double by property("skiko.fps.probability", default = 0.97)
val renderApi: GraphicsApi by lazy {
val environment = System.getenv("SKIKO_RENDER_API")
val property = System.getProperty("skiko.renderApi")
if (environment != null) {
parseRenderApi(environment)
} else {
parseRenderApi(property)
}
}
private fun parseRenderApi(text: String?): GraphicsApi {
when(text) {
"SOFTWARE" -> return GraphicsApi.SOFTWARE
"OPENGL" -> return GraphicsApi.OPENGL
else -> return GraphicsApi.OPENGL
}
}
private fun property(name: String, default: Boolean) = lazy {
System.getProperty(name)?.toBoolean() ?: default
}
......
......@@ -7,29 +7,12 @@ import org.jetbrains.skija.Picture
import org.jetbrains.skija.Surface
import org.jetbrains.skiko.GraphicsApi
import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.hostOs
import org.jetbrains.skiko.OS
internal val renderApi: GraphicsApi by lazy {
val environment = System.getenv("SKIKO_RENDER_API")
val property = System.getProperty("skiko.renderApi")
if (environment != null) {
parseRenderApi(environment)
} else {
parseRenderApi(property)
}
}
private fun parseRenderApi(text: String?): GraphicsApi {
when(text) {
"SOFTWARE" -> return GraphicsApi.SOFTWARE
"OPENGL" -> return GraphicsApi.OPENGL
else -> return GraphicsApi.OPENGL
}
}
import org.jetbrains.skiko.SkikoProperties
import org.jetbrains.skiko.hostOs
internal fun createContextHandler(layer: HardwareLayer): ContextHandler {
return when (renderApi) {
return when (SkikoProperties.renderApi) {
GraphicsApi.SOFTWARE -> SoftwareContextHandler(layer)
GraphicsApi.OPENGL -> OpenGLContextHandler(layer)
else -> TODO("Unsupported yet")
......
......@@ -2,25 +2,19 @@ package org.jetbrains.skiko.redrawer
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.swing.Swing
import kotlinx.coroutines.withContext
import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.OpenGLApi
import org.jetbrains.skiko.SkikoProperties
internal class LinuxRedrawer(
internal class LinuxOpenGLRedrawer(
private val layer: HardwareLayer
) : Redrawer {
private val context = layer.lockDrawingSurface {
val context = it.createContext()
it.makeCurrent(context)
it.setSwapInterval(if (SkikoProperties.vsyncEnabled) 1 else 0)
context
it.createContext()
}
private var isDisposed = false
private val job = Job()
override fun dispose() {
check(!isDisposed)
......@@ -28,7 +22,6 @@ internal class LinuxRedrawer(
it.destroyContext(context)
}
isDisposed = true
job.cancel()
}
override fun needRedraw() {
......@@ -37,10 +30,18 @@ internal class LinuxRedrawer(
frameDispatcher.scheduleFrame()
}
private suspend fun update(nanoTime: Long) {
withContext(job) {
layer.update(nanoTime)
}
override fun redrawImmediately() = layer.lockDrawingSurface {
check(!isDisposed)
update(System.nanoTime())
it.makeCurrent(context)
draw()
it.setSwapInterval(0)
it.swapBuffers()
OpenGLApi.instance.glFinish()
}
private fun update(nanoTime: Long) {
layer.update(nanoTime)
}
private fun draw() {
......@@ -48,9 +49,9 @@ internal class LinuxRedrawer(
}
companion object {
private val toRedraw = mutableSetOf<LinuxRedrawer>()
private val toRedrawCopy = mutableSetOf<LinuxRedrawer>()
private val toRedrawAlive = toRedrawCopy.asSequence().filterNot(LinuxRedrawer::isDisposed)
private val toRedraw = mutableSetOf<LinuxOpenGLRedrawer>()
private val toRedrawCopy = mutableSetOf<LinuxOpenGLRedrawer>()
private val toRedrawAlive = toRedrawCopy.asSequence().filterNot(LinuxOpenGLRedrawer::isDisposed)
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
toRedrawCopy.clear()
......@@ -75,6 +76,8 @@ internal class LinuxRedrawer(
}
toRedrawAlive.forEachIndexed { index, _ ->
// it is ok to set swap interval every frame, there is no performance overhead
drawingSurfaces[index].setSwapInterval(if (SkikoProperties.vsyncEnabled) 1 else 0)
drawingSurfaces[index].swapBuffers()
}
......
......@@ -10,7 +10,7 @@ import org.jetbrains.skiko.SkikoProperties
import javax.swing.SwingUtilities.convertPoint
import javax.swing.SwingUtilities.getRootPane
internal class MacOsRedrawer(
internal class MacOsOpenGLRedrawer(
private val layer: HardwareLayer
) : Redrawer {
private val containerLayerPtr = initContainer(layer)
......@@ -104,6 +104,11 @@ internal class MacOsRedrawer(
override fun needRedraw() {
frameDispatcher.scheduleFrame()
}
override fun redrawImmediately() {
layer.update(System.nanoTime())
drawLayer.setNeedsDisplay()
}
}
private open class AWTGLLayer(private val containerPtr: Long, setNeedsDisplayOnBoundsChange: Boolean) {
......
......@@ -21,4 +21,9 @@ internal class RasterRedrawer(
override fun needRedraw() {
frameDispatcher.scheduleFrame()
}
override fun redrawImmediately() {
layer.update(System.nanoTime())
layer.draw()
}
}
\ No newline at end of file
......@@ -3,5 +3,6 @@ package org.jetbrains.skiko.redrawer
interface Redrawer {
fun dispose()
fun needRedraw()
fun redrawImmediately()
fun syncSize() = Unit
}
\ No newline at end of file
......@@ -2,7 +2,6 @@ package org.jetbrains.skiko.redrawer
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.swing.Swing
import kotlinx.coroutines.withContext
import org.jetbrains.skiko.FrameDispatcher
......@@ -10,13 +9,12 @@ import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.OpenGLApi
import org.jetbrains.skiko.SkikoProperties
internal class WindowsRedrawer(
internal class WindowsOpenGLRedrawer(
private val layer: HardwareLayer
) : Redrawer {
private val device = getDevice(layer)
private val context = createContext(device)
private var isDisposed = false
private val job = Job()
init {
makeCurrent()
......@@ -31,7 +29,6 @@ internal class WindowsRedrawer(
check(!isDisposed)
deleteContext(context)
isDisposed = true
job.cancel()
}
override fun needRedraw() {
......@@ -40,10 +37,17 @@ internal class WindowsRedrawer(
frameDispatcher.scheduleFrame()
}
private suspend fun update(nanoTime: Long) {
withContext(job) {
layer.update(nanoTime)
}
override fun redrawImmediately() {
check(!isDisposed)
update(System.nanoTime())
makeCurrent()
draw()
swapBuffers()
OpenGLApi.instance.glFinish()
}
private fun update(nanoTime: Long) {
layer.update(nanoTime)
}
private fun draw() {
......@@ -54,9 +58,9 @@ internal class WindowsRedrawer(
private fun swapBuffers() = swapBuffers(device)
companion object {
private val toRedraw = mutableSetOf<WindowsRedrawer>()
private val toRedrawCopy = mutableSetOf<WindowsRedrawer>()
private val toRedrawAlive = toRedrawCopy.asSequence().filterNot(WindowsRedrawer::isDisposed)
private val toRedraw = mutableSetOf<WindowsOpenGLRedrawer>()
private val toRedrawCopy = mutableSetOf<WindowsOpenGLRedrawer>()
private val toRedrawAlive = toRedrawCopy.asSequence().filterNot(WindowsOpenGLRedrawer::isDisposed)
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
toRedrawCopy.clear()
......
......@@ -69,7 +69,7 @@ JavaVM *jvm = NULL;
@end
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initContainer(JNIEnv *env, jobject redrawer, jobject layer)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_initContainer(JNIEnv *env, jobject redrawer, jobject layer)
{
JAWT awt;
awt.version = JAWT_VERSION_9;
......@@ -101,14 +101,14 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initCo
return (jlong) container;
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_setContentScale(JNIEnv *env, jobject obj, jlong layerPtr, jfloat contentScale)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_setContentScale(JNIEnv *env, jobject obj, jlong layerPtr, jfloat contentScale)
{
CALayer *layer = (CALayer *) layerPtr;
assert(contentScale != 0);
layer.contentsScale = contentScale;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initAWTGLLayer(JNIEnv *env, jobject obj, jlong containerPtr, jobject layer, jboolean setNeedsDisplayOnBoundsChange)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_initAWTGLLayer(JNIEnv *env, jobject obj, jlong containerPtr, jobject layer, jboolean setNeedsDisplayOnBoundsChange)
{
CALayer *container = (CALayer *) containerPtr;
......@@ -120,7 +120,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initAW
return (jlong) glLayer;
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_disposeAWTGLLayer(JNIEnv *env, jobject obj, jlong ptr)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_disposeAWTGLLayer(JNIEnv *env, jobject obj, jlong ptr)
{
AWTGLLayer *glLayer = (AWTGLLayer *) ptr;
[glLayer removeFromSuperlayer];
......
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