Commit ba58cd5f authored by Roman Sedaikin's avatar Roman Sedaikin

Changed SkiaLayer to contain HardwareLayer rather than inherit from it.

parent b83b0e67
...@@ -13,52 +13,26 @@ abstract class HardwareLayer : Canvas() { ...@@ -13,52 +13,26 @@ abstract class HardwareLayer : Canvas() {
// getDpiScale is expensive operation on some platforms, so we cache it // getDpiScale is expensive operation on some platforms, so we cache it
private var _contentScale: Float? = null private var _contentScale: Float? = null
private var isInit = false
init { internal fun defineContentScale() {
@Suppress("LeakingThis")
addHierarchyListener {
if (it.changeFlags and HierarchyEvent.SHOWING_CHANGED.toLong() != 0L) {
checkIsShowing()
}
}
}
private fun checkIsShowing() {
if (!isInit && isShowing) {
_contentScale = getDpiScale() _contentScale = getDpiScale()
init()
isInit = true
}
} }
protected open fun init() { internal open fun init() {
useDrawingSurfacePlatformInfo(::nativeInit) useDrawingSurfacePlatformInfo(::nativeInit)
} }
protected open external fun nativeInit(platformInfo: Long) protected open external fun nativeInit(platformInfo: Long)
open external fun dispose()
protected open fun contentScaleChanged() = Unit
override fun setBounds(x: Int, y: Int, width: Int, height: Int) {
super.setBounds(x, y, width, height)
checkContentScale()
}
override fun paint(g: Graphics) {
checkContentScale()
}
// TODO checkContentScale is called before init. it is ok, but when we fix getDpiScale on Linux we should check [isInit] // TODO checkContentScale is called before init. it is ok, but when we fix getDpiScale on Linux we should check [isInit]
private fun checkContentScale() { internal fun checkContentScale(): Boolean {
val contentScale = getDpiScale() val contentScale = getDpiScale()
if (contentScale != _contentScale) { if (contentScale != _contentScale) {
_contentScale = contentScale _contentScale = contentScale
contentScaleChanged() return true
} }
return false
} }
private fun getDpiScale(): Float { private fun getDpiScale(): Float {
...@@ -67,12 +41,6 @@ abstract class HardwareLayer : Canvas() { ...@@ -67,12 +41,6 @@ abstract class HardwareLayer : Canvas() {
return scale return scale
} }
// Should be called in Swing thread
internal abstract fun update(nanoTime: Long)
// Should be called in the OpenGL thread, and only once after update
internal abstract fun draw()
val windowHandle: Long val windowHandle: Long
get() = useDrawingSurfacePlatformInfo(::getWindowHandle) get() = useDrawingSurfacePlatformInfo(::getWindowHandle)
......
...@@ -15,7 +15,7 @@ internal interface PlatformOperations { ...@@ -15,7 +15,7 @@ internal interface PlatformOperations {
fun isFullscreen(component: Component): Boolean fun isFullscreen(component: Component): Boolean
fun setFullscreen(component: Component, value: Boolean) fun setFullscreen(component: Component, value: Boolean)
fun getDpiScale(component: Component): Float fun getDpiScale(component: Component): Float
fun createRedrawer(layer: HardwareLayer, renderApi: GraphicsApi, properties: SkiaLayerProperties): Redrawer fun createRedrawer(layer: SkiaLayer, renderApi: GraphicsApi, properties: SkiaLayerProperties): Redrawer
} }
internal val platformOperations: PlatformOperations by lazy { internal val platformOperations: PlatformOperations by lazy {
...@@ -34,7 +34,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -34,7 +34,7 @@ internal val platformOperations: PlatformOperations by lazy {
} }
override fun createRedrawer( override fun createRedrawer(
layer: HardwareLayer, layer: SkiaLayer,
renderApi: GraphicsApi, renderApi: GraphicsApi,
properties: SkiaLayerProperties properties: SkiaLayerProperties
) = when(renderApi) { ) = when(renderApi) {
...@@ -62,7 +62,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -62,7 +62,7 @@ internal val platformOperations: PlatformOperations by lazy {
} }
override fun createRedrawer( override fun createRedrawer(
layer: HardwareLayer, layer: SkiaLayer,
renderApi: GraphicsApi, renderApi: GraphicsApi,
properties: SkiaLayerProperties properties: SkiaLayerProperties
) = when(renderApi) { ) = when(renderApi) {
...@@ -103,7 +103,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -103,7 +103,7 @@ internal val platformOperations: PlatformOperations by lazy {
} }
override fun createRedrawer( override fun createRedrawer(
layer: HardwareLayer, layer: SkiaLayer,
renderApi: GraphicsApi, renderApi: GraphicsApi,
properties: SkiaLayerProperties properties: SkiaLayerProperties
) = when(renderApi) { ) = when(renderApi) {
......
...@@ -9,6 +9,8 @@ import org.jetbrains.skiko.context.ContextHandler ...@@ -9,6 +9,8 @@ import org.jetbrains.skiko.context.ContextHandler
import org.jetbrains.skiko.context.createContextHandler import org.jetbrains.skiko.context.createContextHandler
import org.jetbrains.skiko.redrawer.Redrawer import org.jetbrains.skiko.redrawer.Redrawer
import java.awt.Graphics import java.awt.Graphics
import java.awt.event.HierarchyEvent
import javax.swing.JPanel
import javax.swing.SwingUtilities.invokeLater import javax.swing.SwingUtilities.invokeLater
import javax.swing.SwingUtilities.isEventDispatchThread import javax.swing.SwingUtilities.isEventDispatchThread
...@@ -20,11 +22,47 @@ private class PictureHolder(val instance: Picture, val width: Int, val height: I ...@@ -20,11 +22,47 @@ private class PictureHolder(val instance: Picture, val width: Int, val height: I
open class SkiaLayer( open class SkiaLayer(
private val properties: SkiaLayerProperties = SkiaLayerProperties() private val properties: SkiaLayerProperties = SkiaLayerProperties()
) : HardwareLayer() { ) : JPanel() {
val backedLayer : HardwareLayer
init {
setOpaque(false)
backedLayer = object : HardwareLayer() { }
add(backedLayer)
@Suppress("LeakingThis")
addHierarchyListener {
if (it.changeFlags and HierarchyEvent.SHOWING_CHANGED.toLong() != 0L) {
checkIsShowing()
}
}
}
private var isInit = false
private fun checkIsShowing() {
if (!isInit && isShowing) {
backedLayer.defineContentScale()
init()
isInit = true
}
}
val contentScale: Float
get() = backedLayer.contentScale
val windowHandle: Long
get() = backedLayer.windowHandle
var fullscreen: Boolean
get() = backedLayer.fullscreen
set(value) { backedLayer.fullscreen = value }
protected open fun contentScaleChanged() = Unit
var renderer: SkiaRenderer? = null var renderer: SkiaRenderer? = null
val clipComponents = mutableListOf<ClipRectangle>() val clipComponents = mutableListOf<ClipRectangle>()
@Volatile @Volatile
private var isDisposed = false private var isDisposed = false
internal var redrawer: Redrawer? = null internal var redrawer: Redrawer? = null
...@@ -36,8 +74,8 @@ open class SkiaLayer( ...@@ -36,8 +74,8 @@ open class SkiaLayer(
private val pictureRecorder = PictureRecorder() private val pictureRecorder = PictureRecorder()
private val pictureLock = Any() private val pictureLock = Any()
override fun init() { open fun init() {
super.init() backedLayer.init()
val initialRenderApi = fallbackRenderApiQueue.removeAt(0) val initialRenderApi = fallbackRenderApiQueue.removeAt(0)
contextHandler = createContextHandler(this, initialRenderApi) contextHandler = createContextHandler(this, initialRenderApi)
redrawer = platformOperations.createRedrawer(this, initialRenderApi, properties) redrawer = platformOperations.createRedrawer(this, initialRenderApi, properties)
...@@ -45,7 +83,7 @@ open class SkiaLayer( ...@@ -45,7 +83,7 @@ open class SkiaLayer(
redraw() redraw()
} }
override fun dispose() { open fun dispose() {
check(!isDisposed) check(!isDisposed)
check(isEventDispatchThread()) check(isEventDispatchThread())
contextHandler?.dispose() contextHandler?.dispose()
...@@ -53,17 +91,22 @@ open class SkiaLayer( ...@@ -53,17 +91,22 @@ open class SkiaLayer(
picture?.instance?.close() picture?.instance?.close()
pictureRecorder.close() pictureRecorder.close()
isDisposed = true isDisposed = true
super.dispose()
} }
override fun setBounds(x: Int, y: Int, width: Int, height: Int) { override fun setBounds(x: Int, y: Int, width: Int, height: Int) {
super.setBounds(x, y, width, height) super.setBounds(x, y, width, height)
if (backedLayer.checkContentScale()) {
contentScaleChanged()
}
redrawer?.syncSize() redrawer?.syncSize()
redraw() redraw()
} }
override fun paint(g: Graphics) { override fun paint(g: Graphics) {
super.paint(g) super.paint(g)
if (backedLayer.checkContentScale()) {
contentScaleChanged()
}
redrawer?.syncSize() redrawer?.syncSize()
redrawer?.redrawImmediately() redrawer?.redrawImmediately()
} }
...@@ -97,7 +140,7 @@ open class SkiaLayer( ...@@ -97,7 +140,7 @@ open class SkiaLayer(
@Suppress("LeakingThis") @Suppress("LeakingThis")
private val fpsCounter = defaultFPSCounter(this) private val fpsCounter = defaultFPSCounter(this)
override fun update(nanoTime: Long) { open fun update(nanoTime: Long) {
check(!isDisposed) check(!isDisposed)
check(isEventDispatchThread()) check(isEventDispatchThread())
...@@ -126,7 +169,7 @@ open class SkiaLayer( ...@@ -126,7 +169,7 @@ open class SkiaLayer(
} }
} }
override fun draw() { open fun draw() {
check(!isDisposed) check(!isDisposed)
contextHandler?.apply { contextHandler?.apply {
if (!initContext()) { if (!initContext()) {
......
...@@ -5,11 +5,11 @@ import kotlinx.coroutines.swing.Swing ...@@ -5,11 +5,11 @@ import kotlinx.coroutines.swing.Swing
import org.jetbrains.skija.BackendRenderTarget import org.jetbrains.skija.BackendRenderTarget
import org.jetbrains.skija.DirectContext import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties import org.jetbrains.skiko.SkiaLayerProperties
internal class Direct3DRedrawer( internal class Direct3DRedrawer(
private val layer: HardwareLayer, private val layer: SkiaLayer,
private val properties: SkiaLayerProperties private val properties: SkiaLayerProperties
) : Redrawer { ) : Redrawer {
......
...@@ -5,23 +5,24 @@ import kotlinx.coroutines.Dispatchers ...@@ -5,23 +5,24 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.swing.Swing import kotlinx.coroutines.swing.Swing
import org.jetbrains.skiko.DrawingSurface import org.jetbrains.skiko.DrawingSurface
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.OpenGLApi import org.jetbrains.skiko.OpenGLApi
import org.jetbrains.skiko.SkiaLayerProperties import org.jetbrains.skiko.SkiaLayerProperties
import org.jetbrains.skiko.getDrawingSurface import org.jetbrains.skiko.getDrawingSurface
internal class LinuxOpenGLRedrawer( internal class LinuxOpenGLRedrawer(
private val layer: HardwareLayer, private val layer: SkiaLayer,
private val properties: SkiaLayerProperties private val properties: SkiaLayerProperties
) : Redrawer { ) : Redrawer {
private val context = layer.lockDrawingSurface { private val context = layer.backedLayer.lockDrawingSurface {
it.createContext() it.createContext()
} }
private var isDisposed = false private var isDisposed = false
override fun dispose() { override fun dispose() {
check(!isDisposed) check(!isDisposed)
layer.lockDrawingSurface { layer.backedLayer.lockDrawingSurface {
it.destroyContext(context) it.destroyContext(context)
} }
isDisposed = true isDisposed = true
...@@ -33,7 +34,7 @@ internal class LinuxOpenGLRedrawer( ...@@ -33,7 +34,7 @@ internal class LinuxOpenGLRedrawer(
frameDispatcher.scheduleFrame() frameDispatcher.scheduleFrame()
} }
override fun redrawImmediately() = layer.lockDrawingSurface { override fun redrawImmediately() = layer.backedLayer.lockDrawingSurface {
check(!isDisposed) check(!isDisposed)
update(System.nanoTime()) update(System.nanoTime())
it.makeCurrent(context) it.makeCurrent(context)
...@@ -73,7 +74,7 @@ internal class LinuxOpenGLRedrawer( ...@@ -73,7 +74,7 @@ internal class LinuxOpenGLRedrawer(
val isVsyncEnabled = toRedrawAlive.all { it.properties.isVsyncEnabled } val isVsyncEnabled = toRedrawAlive.all { it.properties.isVsyncEnabled }
val drawingSurfaces = toRedrawAlive.map { lockDrawingSurface(it.layer) }.toList() val drawingSurfaces = toRedrawAlive.map { lockDrawingSurface(it.layer.backedLayer) }.toList()
try { try {
toRedrawAlive.forEachIndexed { index, redrawer -> toRedrawAlive.forEachIndexed { index, redrawer ->
drawingSurfaces[index].makeCurrent(redrawer.context) drawingSurfaces[index].makeCurrent(redrawer.context)
......
...@@ -4,7 +4,7 @@ import kotlinx.coroutines.Dispatchers ...@@ -4,7 +4,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.swing.Swing import kotlinx.coroutines.swing.Swing
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.OpenGLApi import org.jetbrains.skiko.OpenGLApi
import org.jetbrains.skiko.SkiaLayerProperties import org.jetbrains.skiko.SkiaLayerProperties
import org.jetbrains.skiko.Task import org.jetbrains.skiko.Task
...@@ -21,10 +21,10 @@ import kotlin.system.measureNanoTime ...@@ -21,10 +21,10 @@ import kotlin.system.measureNanoTime
// P.S. MacOsOpenGLRedrawer will not be used by default in the future, because we will support Metal. // P.S. MacOsOpenGLRedrawer will not be used by default in the future, because we will support Metal.
internal class MacOsOpenGLRedrawer( internal class MacOsOpenGLRedrawer(
private val layer: HardwareLayer, private val layer: SkiaLayer,
private val properties: SkiaLayerProperties private val properties: SkiaLayerProperties
) : Redrawer { ) : Redrawer {
private val containerLayerPtr = layer.useDrawingSurfacePlatformInfo(::initContainer) private val containerLayerPtr = layer.backedLayer.useDrawingSurfacePlatformInfo(::initContainer)
private val drawLock = Any() private val drawLock = Any()
private var isDisposed = false private var isDisposed = false
...@@ -106,7 +106,6 @@ internal class MacOsOpenGLRedrawer( ...@@ -106,7 +106,6 @@ internal class MacOsOpenGLRedrawer(
} }
override fun syncSize() { override fun syncSize() {
println("syncsize")
val globalPosition = convertPoint(layer, layer.x, layer.y, getRootPane(layer)) val globalPosition = convertPoint(layer, layer.x, layer.y, getRootPane(layer))
setContentScale(containerLayerPtr, layer.contentScale) setContentScale(containerLayerPtr, layer.contentScale)
setContentScale(drawLayer.ptr, layer.contentScale) setContentScale(drawLayer.ptr, layer.contentScale)
......
...@@ -5,18 +5,18 @@ import kotlinx.coroutines.swing.Swing ...@@ -5,18 +5,18 @@ import kotlinx.coroutines.swing.Swing
import org.jetbrains.skija.BackendRenderTarget import org.jetbrains.skija.BackendRenderTarget
import org.jetbrains.skija.DirectContext import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties import org.jetbrains.skiko.SkiaLayerProperties
import org.jetbrains.skiko.useDrawingSurfacePlatformInfo import org.jetbrains.skiko.useDrawingSurfacePlatformInfo
import javax.swing.SwingUtilities.convertPoint import javax.swing.SwingUtilities.convertPoint
import javax.swing.SwingUtilities.getRootPane import javax.swing.SwingUtilities.getRootPane
internal class MetalRedrawer( internal class MetalRedrawer(
private val layer: HardwareLayer, private val layer: SkiaLayer,
private val properties: SkiaLayerProperties private val properties: SkiaLayerProperties
) : Redrawer { ) : Redrawer {
private var isDisposed = false private var isDisposed = false
private val device = layer.useDrawingSurfacePlatformInfo(::createMetalDevice) private val device = layer.backedLayer.useDrawingSurfacePlatformInfo(::createMetalDevice)
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) { private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
update(System.nanoTime()) update(System.nanoTime())
......
...@@ -3,10 +3,10 @@ package org.jetbrains.skiko.redrawer ...@@ -3,10 +3,10 @@ package org.jetbrains.skiko.redrawer
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.swing.Swing import kotlinx.coroutines.swing.Swing
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.SkiaLayer
internal class SoftwareRedrawer( internal class SoftwareRedrawer(
private val layer: HardwareLayer private val layer: SkiaLayer
) : Redrawer { ) : Redrawer {
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) { private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
......
...@@ -5,16 +5,16 @@ import kotlinx.coroutines.Dispatchers ...@@ -5,16 +5,16 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.swing.Swing import kotlinx.coroutines.swing.Swing
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.OpenGLApi import org.jetbrains.skiko.OpenGLApi
import org.jetbrains.skiko.SkiaLayerProperties import org.jetbrains.skiko.SkiaLayerProperties
import org.jetbrains.skiko.useDrawingSurfacePlatformInfo import org.jetbrains.skiko.useDrawingSurfacePlatformInfo
internal class WindowsOpenGLRedrawer( internal class WindowsOpenGLRedrawer(
private val layer: HardwareLayer, private val layer: SkiaLayer,
private val properties: SkiaLayerProperties private val properties: SkiaLayerProperties
) : Redrawer { ) : Redrawer {
private val device = layer.useDrawingSurfacePlatformInfo(::getDevice) private val device = layer.backedLayer.useDrawingSurfacePlatformInfo(::getDevice)
private val context = createContext(device) private val context = createContext(device)
private var isDisposed = false private var isDisposed = false
......
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