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