Skip to content

Commit

Permalink
Add configurable logger, solidify workaround for JBR-5274 (#683)
Browse files Browse the repository at this point in the history
* sometimes when we change scale via `EasyRes` or when we close/open lid and window is migrated to other screen `paint` is not called

see FL-18544

* customizable logger behaviour

* add debug logs in AWT layer
  • Loading branch information
SergeevPavel authored Mar 29, 2023
1 parent db11bf1 commit ea760f8
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 23 deletions.
12 changes: 10 additions & 2 deletions skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkiaLayer.awt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ actual open class SkiaLayer internal constructor(
layout = null
backedLayer = object : HardwareLayer(externalAccessibleFactory) {
override fun paint(g: java.awt.Graphics) {
Logger.debug { "Paint called on $this" }
checkContentScale()

// 1. JPanel.paint is not always called (in rare cases).
Expand Down Expand Up @@ -123,6 +124,7 @@ actual open class SkiaLayer internal constructor(
}

addPropertyChangeListener("graphicsContextScaleTransform") {
Logger.debug { "graphicsContextScaleTransform changed for $this" }
redrawer?.syncSize()
notifyChange(PropertyKind.ContentScale)

Expand All @@ -140,13 +142,15 @@ actual open class SkiaLayer internal constructor(
private var fullscreenAdapter = FullscreenAdapter(backedLayer)

override fun removeNotify() {
Logger.debug { "SkiaLayer.awt#removeNotify $this" }
val window = SwingUtilities.getRoot(this) as Window
window.removeComponentListener(fullscreenAdapter)
dispose()
super.removeNotify()
}

override fun addNotify() {
Logger.debug { "SkiaLayer.awt#addNotify $this" }
super.addNotify()
val window = SwingUtilities.getRoot(this) as Window
window.addComponentListener(fullscreenAdapter)
Expand Down Expand Up @@ -314,7 +318,7 @@ actual open class SkiaLayer internal constructor(
redrawer = renderFactory.createRedrawer(this, renderApi, analytics, properties)
redrawer?.syncSize()
} catch (e: RenderException) {
Logger.warn("Fallback to next API: ${e.message}")
Logger.warn(e) { "Fallback to next API" }
thrown = true
}
} while (thrown && fallbackRenderApiQueue.isNotEmpty())
Expand Down Expand Up @@ -365,13 +369,15 @@ actual open class SkiaLayer internal constructor(
}

override fun doLayout() {
Logger.debug { "doLayout on $this" }
backedLayer.setBounds(0, 0, roundSize(width), roundSize(height))
backedLayer.validate()
redrawer?.syncSize()
}


override fun paint(g: java.awt.Graphics) {
Logger.debug { "Paint called on: $this" }
checkContentScale()

// `paint` can be called when we already inside `draw` method.
Expand Down Expand Up @@ -524,6 +530,8 @@ actual open class SkiaLayer internal constructor(
check(isEventDispatchThread()) { "Method should be called from AWT event dispatch thread" }
check(!isDisposed) { "SkiaLayer is disposed" }

checkContentScale()

FrameWatcher.nextFrame()
fpsCounter?.tick()

Expand Down Expand Up @@ -566,7 +574,7 @@ actual open class SkiaLayer internal constructor(
// ignore
} catch (e: RenderException) {
if (!isDisposed) {
Logger.warn("Exception in draw scope: ${e.message}")
Logger.warn(e) { "Exception in draw scope" }
findNextWorkingRenderApi()
redrawer?.redrawImmediately()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : JvmContextHandler(laye
if (context == null) {
context = directXRedrawer.makeContext()
if (System.getProperty("skiko.hardwareInfo.enabled") == "true") {
Logger.info("Renderer info:\n ${rendererInfo()}")
Logger.info { "Renderer info:\n ${rendererInfo()}" }
}
}
} catch (e: Exception) {
Logger.warn("${e.message}\n Failed to create Skia Direct3D context!")
Logger.warn(e) { "Failed to create Skia Direct3D context!" }
return false
}
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : JvmContextHandle
override fun initContext(): Boolean {
if (!isInited) {
if (System.getProperty("skiko.hardwareInfo.enabled") == "true") {
Logger.info("Renderer info:\n ${rendererInfo()}")
Logger.info { "Renderer info:\n ${rendererInfo()}" }
}
isInited = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ internal class MetalContextHandler(layer: SkiaLayer) : JvmContextHandler(layer)
if (context == null) {
context = metalRedrawer.makeContext()
if (System.getProperty("skiko.hardwareInfo.enabled") == "true") {
Logger.info("Renderer info:\n ${rendererInfo()}")
Logger.info { "Renderer info:\n ${rendererInfo()}" }
}
}
} catch (e: Exception) {
Logger.warn("${e.message}\nFailed to create Skia Metal context!")
Logger.warn(e) { "Failed to create Skia Metal context!" }
return false
}
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : JvmContextHandler(layer)
if (context == null) {
context = makeGLContext()
if (System.getProperty("skiko.hardwareInfo.enabled") == "true") {
Logger.info("Renderer info:\n ${rendererInfo()}")
Logger.info { "Renderer info:\n ${rendererInfo()}" }
}
}
} catch (e: Exception) {
Logger.warn("${e.message}\nFailed to create Skia OpenGL context!")
Logger.warn(e) { "Failed to create Skia OpenGL context!" }
return false
}
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : JvmContextHandler(laye
// Raster does not need context
if (!isInited) {
if (System.getProperty("skiko.hardwareInfo.enabled") == "true") {
Logger.info("Renderer info:\n ${rendererInfo()}")
Logger.info { "Renderer info:\n ${rendererInfo()}" }
}
isInited = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,16 @@ internal class MetalRedrawer(
val rootPane = getRootPane(layer)
val globalPosition = convertPoint(layer, layer.x, layer.y, rootPane)
setContentScale(device, layer.contentScale)
resizeLayers(
device,
globalPosition.x,
rootPane.height - globalPosition.y - layer.height,
layer.width.coerceAtLeast(0),
layer.height.coerceAtLeast(0)
)
val x = globalPosition.x
val y = rootPane.height - globalPosition.y - layer.height
val width = layer.width.coerceAtLeast(0)
val height = layer.height.coerceAtLeast(0)
Logger.debug { "MetalRedrawer#resizeLayers $this $x $y $width $height" }
resizeLayers(device, x, y, width, height)
}

override fun setVisible(isVisible: Boolean) {
Logger.debug { "MetalRedrawer#setVisible $this $isVisible" }
setLayerVisible(device, isVisible)
}

Expand Down
146 changes: 140 additions & 6 deletions skiko/src/commonMain/kotlin/org/jetbrains/skiko/Logging.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,149 @@
package org.jetbrains.skiko

interface SkikoLoggerInterface {
val isTraceEnabled: Boolean
val isDebugEnabled: Boolean
val isInfoEnabled: Boolean
val isWarnEnabled: Boolean
val isErrorEnabled: Boolean

fun trace(message: String)
fun debug(message: String)
fun info(message: String)
fun warn(message: String)
fun error(message: String)

fun trace(t: Throwable, message: String)
fun debug(t: Throwable, message: String)
fun info(t: Throwable, message: String)
fun warn(t: Throwable, message: String)
fun error(t: Throwable, message: String)
}

fun setupSkikoLoggerFactory(createLogger: () -> SkikoLoggerInterface) {
Logger.loggerFactory = createLogger
}

internal object DefaultConsoleLogger: SkikoLoggerInterface {
override val isTraceEnabled: Boolean
get() = false
override val isDebugEnabled: Boolean
get() = false
override val isInfoEnabled: Boolean
get() = true
override val isWarnEnabled: Boolean
get() = true
override val isErrorEnabled: Boolean
get() = true

override fun trace(message: String) {
println("[SKIKO] trace: $message")
}

override fun trace(t: Throwable, message: String) {
println("[SKIKO] trace: $message")
println(t)
}

override fun debug(message: String) {
println("[SKIKO] debug: $message")
}

override fun debug(t: Throwable, message: String) {
println("[SKIKO] debug: $message")
println(t)
}

override fun info(message: String) {
println("[SKIKO] info: $message")
}

override fun info(t: Throwable, message: String) {
println("[SKIKO] info: $message")
println(t)
}

override fun warn(message: String) {
println("[SKIKO] warn: $message")
}

override fun warn(t: Throwable, message: String) {
println("[SKIKO] warn: $message")
println(t)
}

override fun error(message: String) {
println("[SKIKO] error: $message")
}

override fun error(t: Throwable, message: String) {
println("[SKIKO] error: $message")
println(t)
}
}

internal object Logger {
fun info(msg: String) {
println("[SKIKO] info: $msg")
var loggerFactory: () -> SkikoLoggerInterface = { DefaultConsoleLogger }

val loggerImpl by lazy {
loggerFactory()
}

inline fun trace(msg: () -> String) {
if (loggerImpl.isTraceEnabled) {
loggerImpl.trace(msg())
}
}

inline fun debug(msg: () -> String) {
if (loggerImpl.isDebugEnabled) {
loggerImpl.debug(msg())
}
}

fun warn(msg: String) {
println("[SKIKO] warn: $msg")
inline fun info(msg: () -> String) {
if (loggerImpl.isInfoEnabled) {
loggerImpl.info(msg())
}
}

fun error(msg: String) {
println("[SKIKO] error: $msg")
inline fun warn(msg: () -> String) {
if (loggerImpl.isWarnEnabled) {
loggerImpl.warn(msg())
}
}

inline fun error(msg: () -> String) {
if (loggerImpl.isErrorEnabled) {
loggerImpl.error(msg())
}
}

inline fun trace(t: Throwable, msg: () -> String) {
if (loggerImpl.isTraceEnabled) {
loggerImpl.trace(t, msg())
}
}

inline fun debug(t: Throwable, msg: () -> String) {
if (loggerImpl.isDebugEnabled) {
loggerImpl.debug(t, msg())
}
}

inline fun info(t: Throwable, msg: () -> String) {
if (loggerImpl.isInfoEnabled) {
loggerImpl.info(t, msg())
}
}
inline fun warn(t: Throwable, msg: () -> String) {
if (loggerImpl.isWarnEnabled) {
loggerImpl.warn(t, msg())
}
}
inline fun error(t: Throwable, msg:() -> String) {
if (loggerImpl.isErrorEnabled) {
loggerImpl.error(t, msg())
}
}
}

0 comments on commit ea760f8

Please sign in to comment.