Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
skiko
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liuqiang
skiko
Commits
89888a47
Unverified
Commit
89888a47
authored
Mar 13, 2026
by
Alexander Maryanovsky
Committed by
GitHub
Mar 13, 2026
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix race condition reading layer properties in a background thread (#1181)
parent
901d632a
Changes
25
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
143 additions
and
84 deletions
+143
-84
SkiaLayer.awt.kt
...o/src/awtMain/kotlin/org/jetbrains/skiko/SkiaLayer.awt.kt
+12
-3
AngleContextHandler.kt
...kotlin/org/jetbrains/skiko/context/AngleContextHandler.kt
+5
-5
ContextBasedContextHandler.kt
...org/jetbrains/skiko/context/ContextBasedContextHandler.kt
+1
-1
ContextFreeContextHandler.kt
.../org/jetbrains/skiko/context/ContextFreeContextHandler.kt
+4
-4
Direct3DContextHandler.kt
...lin/org/jetbrains/skiko/context/Direct3DContextHandler.kt
+6
-7
DirectSoftwareContextHandler.kt
...g/jetbrains/skiko/context/DirectSoftwareContextHandler.kt
+5
-5
MetalContextHandler.kt
...kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
+7
-7
OpenGLContextHandler.kt
...otlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
+4
-5
SoftwareContextHandler.kt
...lin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
+8
-10
AWTRedrawer.kt
...wtMain/kotlin/org/jetbrains/skiko/redrawer/AWTRedrawer.kt
+1
-1
AbstractDirectSoftwareRedrawer.kt
...etbrains/skiko/redrawer/AbstractDirectSoftwareRedrawer.kt
+1
-1
AngleRedrawer.kt
...Main/kotlin/org/jetbrains/skiko/redrawer/AngleRedrawer.kt
+3
-1
Direct3DRedrawer.kt
...n/kotlin/org/jetbrains/skiko/redrawer/Direct3DRedrawer.kt
+1
-1
LinuxOpenGLRedrawer.kt
...otlin/org/jetbrains/skiko/redrawer/LinuxOpenGLRedrawer.kt
+1
-1
MetalRedrawer.kt
...Main/kotlin/org/jetbrains/skiko/redrawer/MetalRedrawer.kt
+1
-1
SoftwareRedrawer.kt
...n/kotlin/org/jetbrains/skiko/redrawer/SoftwareRedrawer.kt
+1
-1
WindowsOpenGLRedrawer.kt
...lin/org/jetbrains/skiko/redrawer/WindowsOpenGLRedrawer.kt
+1
-1
SkiaLayerTest.kt
...o/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerTest.kt
+2
-2
SkiaLayer.kt
skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+31
-1
ContextHandler.kt
...Main/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
+6
-5
SkiaLayer.macos.kt
...c/macosMain/kotlin/org/jetbrains/skiko/SkiaLayer.macos.kt
+13
-0
MetalContextHandler.macos.kt
.../org/jetbrains/skiko/context/MetalContextHandler.macos.kt
+7
-8
OpenGLContextHandler.macos.kt
...org/jetbrains/skiko/context/OpenGLContextHandler.macos.kt
+10
-9
MetalRedrawer.macos.kt
...otlin/org/jetbrains/skiko/redrawer/MetalRedrawer.macos.kt
+9
-3
OpenGLRedrawer.macos.kt
...tlin/org/jetbrains/skiko/redrawer/OpenGLRedrawer.macos.kt
+3
-1
No files found.
skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkiaLayer.awt.kt
View file @
89888a47
...
@@ -645,13 +645,22 @@ actual open class SkiaLayer internal constructor(
...
@@ -645,13 +645,22 @@ actual open class SkiaLayer internal constructor(
@Suppress
(
"LeakingThis"
)
@Suppress
(
"LeakingThis"
)
private
val
fpsCounter
=
defaultFPSCounter
(
this
)
private
val
fpsCounter
=
defaultFPSCounter
(
this
)
internal
inline
fun
inDrawScope
(
body
:
()
->
Unit
)
{
private
fun
createDrawScope
()
=
LayerDrawScope
(
pixelGeometry
=
pixelGeometry
,
layerWidth
=
width
,
layerHeight
=
height
,
scale
=
contentScale
)
internal
inline
fun
inDrawScope
(
body
:
LayerDrawScope
.()
->
Unit
)
{
check
(
isEventDispatchThread
())
{
"Method should be called from AWT event dispatch thread"
}
check
(
isEventDispatchThread
())
{
"Method should be called from AWT event dispatch thread"
}
check
(!
isDisposed
)
{
"SkiaLayer is disposed"
}
check
(!
isDisposed
)
{
"SkiaLayer is disposed"
}
try
{
try
{
fpsCounter
?.
tick
()
fpsCounter
?.
tick
()
with
(
createDrawScope
())
{
body
()
body
()
}
catch
(
e
:
CancellationException
)
{
}
}
catch
(
_
:
CancellationException
)
{
// ignore
// ignore
}
catch
(
e
:
RenderException
)
{
}
catch
(
e
:
RenderException
)
{
if
(!
isDisposed
)
{
if
(!
isDisposed
)
{
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/AngleContextHandler.kt
View file @
89888a47
...
@@ -2,6 +2,7 @@ package org.jetbrains.skiko.context
...
@@ -2,6 +2,7 @@ package org.jetbrains.skiko.context
import
org.jetbrains.skia.*
import
org.jetbrains.skia.*
import
org.jetbrains.skiko.AngleApi
import
org.jetbrains.skiko.AngleApi
import
org.jetbrains.skiko.LayerDrawScope
import
org.jetbrains.skiko.RenderException
import
org.jetbrains.skiko.RenderException
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.redrawer.AngleRedrawer
import
org.jetbrains.skiko.redrawer.AngleRedrawer
...
@@ -23,12 +24,11 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextBasedContextHandle
...
@@ -23,12 +24,11 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextBasedContextHandle
return
false
return
false
}
}
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
val
context
=
context
?:
return
val
context
=
context
?:
return
val
scale
=
layer
.
contentScale
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
w
=
scaledLayerWidth
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
scaledLayerHeight
if
(
isSizeChanged
(
w
,
h
)
||
surface
==
null
)
{
if
(
isSizeChanged
(
w
,
h
)
||
surface
==
null
)
{
disposeCanvas
()
disposeCanvas
()
...
@@ -41,7 +41,7 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextBasedContextHandle
...
@@ -41,7 +41,7 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextBasedContextHandle
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceColorFormat
.
RGBA_8888
,
SurfaceColorFormat
.
RGBA_8888
,
ColorSpace
.
sRGB
,
ColorSpace
.
sRGB
,
SurfaceProps
(
pixelGeometry
=
layer
.
pixelGeometry
)
SurfaceProps
(
pixelGeometry
=
pixelGeometry
)
)
?:
throw
RenderException
(
"Cannot create surface"
)
)
?:
throw
RenderException
(
"Cannot create surface"
)
}
}
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/ContextBasedContextHandler.kt
View file @
89888a47
...
@@ -6,7 +6,7 @@ import org.jetbrains.skiko.SkiaLayer
...
@@ -6,7 +6,7 @@ import org.jetbrains.skiko.SkiaLayer
internal
abstract
class
ContextBasedContextHandler
(
layer
:
SkiaLayer
,
val
name
:
String
)
:
JvmContextHandler
(
layer
)
{
internal
abstract
class
ContextBasedContextHandler
(
layer
:
SkiaLayer
,
val
name
:
String
)
:
JvmContextHandler
(
layer
)
{
abstract
protected
fun
makeContext
():
DirectContext
protected
abstract
fun
makeContext
():
DirectContext
override
fun
initContext
():
Boolean
{
override
fun
initContext
():
Boolean
{
try
{
try
{
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/ContextFreeContextHandler.kt
View file @
89888a47
...
@@ -3,13 +3,13 @@ package org.jetbrains.skiko.context
...
@@ -3,13 +3,13 @@ package org.jetbrains.skiko.context
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.SkiaLayer
internal
abstract
class
ContextFreeContextHandler
(
layer
:
SkiaLayer
)
:
JvmContextHandler
(
layer
)
{
internal
abstract
class
ContextFreeContextHandler
(
layer
:
SkiaLayer
)
:
JvmContextHandler
(
layer
)
{
private
var
isInited
=
false
private
var
isInit
ializ
ed
=
false
override
fun
initContext
():
Boolean
{
override
fun
initContext
():
Boolean
{
if
(!
isInited
)
{
if
(!
isInit
ializ
ed
)
{
isInited
=
true
isInit
ializ
ed
=
true
onContextInitialized
()
onContextInitialized
()
}
}
return
isInited
return
isInit
ializ
ed
}
}
}
}
\ No newline at end of file
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/Direct3DContextHandler.kt
View file @
89888a47
...
@@ -4,7 +4,7 @@ import org.jetbrains.skia.DirectContext
...
@@ -4,7 +4,7 @@ import org.jetbrains.skia.DirectContext
import
org.jetbrains.skia.Surface
import
org.jetbrains.skia.Surface
import
org.jetbrains.skia.SurfaceProps
import
org.jetbrains.skia.SurfaceProps
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skiko.L
ogger
import
org.jetbrains.skiko.L
ayerDrawScope
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.redrawer.Direct3DRedrawer
import
org.jetbrains.skiko.redrawer.Direct3DRedrawer
import
java.lang.ref.Reference
import
java.lang.ref.Reference
...
@@ -30,15 +30,14 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextBasedContextHan
...
@@ -30,15 +30,14 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextBasedContextHan
return
false
return
false
}
}
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
val
context
=
context
?:
return
val
context
=
context
?:
return
val
scale
=
layer
.
contentScale
// Direct3D can't work with zero size.
// Direct3D can't work with zero size.
// Don't rewrite code to skipping, as we need the whole pipeline in zero case too
// Don't rewrite code to skipping, as we need the whole pipeline in zero case too
// (drawing -> flushing -> swapping -> waiting for vsync)
// (drawing -> flushing -> swapping -> waiting for vsync)
val
width
=
(
layer
.
width
*
scale
).
toInt
()
.
coerceAtLeast
(
1
)
val
width
=
scaledLayerWidth
.
coerceAtLeast
(
1
)
val
height
=
(
layer
.
height
*
scale
).
toInt
()
.
coerceAtLeast
(
1
)
val
height
=
scaledLayerHeight
.
coerceAtLeast
(
1
)
if
(
isSizeChanged
(
width
,
height
)
||
isSurfacesNull
())
{
if
(
isSizeChanged
(
width
,
height
)
||
isSurfacesNull
())
{
disposeCanvas
()
disposeCanvas
()
...
@@ -46,7 +45,7 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextBasedContextHan
...
@@ -46,7 +45,7 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextBasedContextHan
val
justInitialized
=
directXRedrawer
.
changeSize
(
width
,
height
)
val
justInitialized
=
directXRedrawer
.
changeSize
(
width
,
height
)
try
{
try
{
val
surfaceProps
=
SurfaceProps
(
pixelGeometry
=
layer
.
pixelGeometry
)
val
surfaceProps
=
SurfaceProps
(
pixelGeometry
=
pixelGeometry
)
for
(
bufferIndex
in
0
until
bufferCount
)
{
for
(
bufferIndex
in
0
until
bufferCount
)
{
surfaces
[
bufferIndex
]
=
directXRedrawer
.
makeSurface
(
surfaces
[
bufferIndex
]
=
directXRedrawer
.
makeSurface
(
context
=
getPtr
(
context
),
context
=
getPtr
(
context
),
...
@@ -68,7 +67,7 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextBasedContextHan
...
@@ -68,7 +67,7 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextBasedContextHan
canvas
=
surface
!!
.
canvas
canvas
=
surface
!!
.
canvas
}
}
override
fun
flush
()
{
override
fun
flush
(
scope
:
LayerDrawScope
)
{
val
context
=
context
?:
return
val
context
=
context
?:
return
val
surface
=
surface
?:
return
val
surface
=
surface
?:
return
try
{
try
{
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/DirectSoftwareContextHandler.kt
View file @
89888a47
package
org.jetbrains.skiko.context
package
org.jetbrains.skiko.context
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skiko.LayerDrawScope
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.redrawer.AbstractDirectSoftwareRedrawer
import
org.jetbrains.skiko.redrawer.AbstractDirectSoftwareRedrawer
import
java.lang.ref.Reference
import
java.lang.ref.Reference
...
@@ -20,10 +21,9 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : ContextFreeConte
...
@@ -20,10 +21,9 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : ContextFreeConte
return
false
return
false
}
}
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
val
scale
=
layer
.
contentScale
val
w
=
scaledLayerWidth
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
scaledLayerHeight
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
if
(
isSizeChanged
(
w
,
h
)
||
surface
==
null
)
{
if
(
isSizeChanged
(
w
,
h
)
||
surface
==
null
)
{
disposeCanvas
()
disposeCanvas
()
if
(
w
>
0
&&
h
>
0
)
{
if
(
w
>
0
&&
h
>
0
)
{
...
@@ -37,7 +37,7 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : ContextFreeConte
...
@@ -37,7 +37,7 @@ internal class DirectSoftwareContextHandler(layer: SkiaLayer) : ContextFreeConte
}
}
}
}
override
fun
flush
()
{
override
fun
flush
(
scope
:
LayerDrawScope
)
{
val
surface
=
surface
val
surface
=
surface
if
(
surface
!=
null
)
{
if
(
surface
!=
null
)
{
try
{
try
{
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
View file @
89888a47
package
org.jetbrains.skiko.context
package
org.jetbrains.skiko.context
import
org.jetbrains.skia.*
import
org.jetbrains.skia.*
import
org.jetbrains.skiko.LayerDrawScope
import
org.jetbrains.skiko.Logger
import
org.jetbrains.skiko.Logger
import
org.jetbrains.skiko.MetalAdapter
import
org.jetbrains.skiko.MetalAdapter
import
org.jetbrains.skiko.RenderException
import
org.jetbrains.skiko.RenderException
...
@@ -20,12 +21,11 @@ internal class MetalContextHandler(
...
@@ -20,12 +21,11 @@ internal class MetalContextHandler(
private
val
device
:
MetalDevice
,
private
val
device
:
MetalDevice
,
private
val
adapter
:
MetalAdapter
private
val
adapter
:
MetalAdapter
)
:
ContextBasedContextHandler
(
layer
,
"Metal"
)
{
)
:
ContextBasedContextHandler
(
layer
,
"Metal"
)
{
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
disposeCanvas
()
disposeCanvas
()
val
scale
=
layer
.
contentScale
val
width
=
scaledLayerWidth
val
width
=
(
layer
.
backedLayer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
height
=
scaledLayerHeight
val
height
=
(
layer
.
backedLayer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
if
(
width
>
0
&&
height
>
0
)
{
if
(
width
>
0
&&
height
>
0
)
{
renderTarget
=
makeRenderTarget
(
width
,
height
)
renderTarget
=
makeRenderTarget
(
width
,
height
)
...
@@ -36,7 +36,7 @@ internal class MetalContextHandler(
...
@@ -36,7 +36,7 @@ internal class MetalContextHandler(
SurfaceOrigin
.
TOP_LEFT
,
SurfaceOrigin
.
TOP_LEFT
,
SurfaceColorFormat
.
BGRA_8888
,
SurfaceColorFormat
.
BGRA_8888
,
ColorSpace
.
sRGB
,
ColorSpace
.
sRGB
,
SurfaceProps
(
pixelGeometry
=
layer
.
pixelGeometry
)
SurfaceProps
(
pixelGeometry
=
pixelGeometry
)
)
?:
throw
RenderException
(
"Cannot create surface"
)
)
?:
throw
RenderException
(
"Cannot create surface"
)
canvas
=
surface
!!
.
canvas
canvas
=
surface
!!
.
canvas
...
@@ -47,8 +47,8 @@ internal class MetalContextHandler(
...
@@ -47,8 +47,8 @@ internal class MetalContextHandler(
}
}
}
}
override
fun
flush
()
{
override
fun
flush
(
scope
:
LayerDrawScope
)
{
super
.
flush
()
super
.
flush
(
scope
)
surface
?.
flushAndSubmit
()
surface
?.
flushAndSubmit
()
finishFrame
()
finishFrame
()
Logger
.
debug
{
"MetalContextHandler finished drawing frame"
}
Logger
.
debug
{
"MetalContextHandler finished drawing frame"
}
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
View file @
89888a47
...
@@ -18,10 +18,9 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : ContextBasedContextHandl
...
@@ -18,10 +18,9 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : ContextBasedContextHandl
return
false
return
false
}
}
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
val
scale
=
layer
.
contentScale
val
w
=
scaledLayerWidth
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
scaledLayerHeight
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
if
(
isSizeChanged
(
w
,
h
)
||
surface
==
null
)
{
if
(
isSizeChanged
(
w
,
h
)
||
surface
==
null
)
{
disposeCanvas
()
disposeCanvas
()
...
@@ -41,7 +40,7 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : ContextBasedContextHandl
...
@@ -41,7 +40,7 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : ContextBasedContextHandl
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceColorFormat
.
RGBA_8888
,
SurfaceColorFormat
.
RGBA_8888
,
ColorSpace
.
sRGB
,
ColorSpace
.
sRGB
,
SurfaceProps
(
pixelGeometry
=
layer
.
pixelGeometry
)
SurfaceProps
(
pixelGeometry
=
pixelGeometry
)
)
?:
throw
RenderException
(
"Cannot create surface"
)
)
?:
throw
RenderException
(
"Cannot create surface"
)
}
}
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
View file @
89888a47
package
org.jetbrains.skiko.context
package
org.jetbrains.skiko.context
import
org.jetbrains.skia.*
import
org.jetbrains.skia.*
import
org.jetbrains.skiko.LayerDrawScope
import
org.jetbrains.skiko.OS
import
org.jetbrains.skiko.OS
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.hostOs
import
org.jetbrains.skiko.hostOs
...
@@ -22,25 +23,22 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : ContextFreeContextHand
...
@@ -22,25 +23,22 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : ContextFreeContextHand
var
imageData
:
ByteArray
?
=
null
var
imageData
:
ByteArray
?
=
null
var
raster
:
WritableRaster
?
=
null
var
raster
:
WritableRaster
?
=
null
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
disposeCanvas
()
disposeCanvas
()
val
scale
=
layer
.
contentScale
val
w
=
scaledLayerWidth
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
scaledLayerHeight
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
if
(
storage
.
width
!=
w
||
storage
.
height
!=
h
)
{
if
(
storage
.
width
!=
w
||
storage
.
height
!=
h
)
{
storage
.
allocPixelsFlags
(
ImageInfo
.
makeS32
(
w
,
h
,
ColorAlphaType
.
PREMUL
),
false
)
storage
.
allocPixelsFlags
(
ImageInfo
.
makeS32
(
w
,
h
,
ColorAlphaType
.
PREMUL
),
false
)
}
}
canvas
=
Canvas
(
storage
,
SurfaceProps
(
pixelGeometry
=
layer
.
pixelGeometry
))
canvas
=
Canvas
(
storage
,
SurfaceProps
(
pixelGeometry
=
pixelGeometry
))
}
}
override
fun
flush
()
{
override
fun
flush
(
scope
:
LayerDrawScope
)
{
val
scale
=
layer
.
contentScale
val
w
=
scope
.
scaledLayerWidth
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
scope
.
scaledLayerHeight
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
bytes
=
storage
.
readPixels
(
storage
.
imageInfo
,
(
w
*
4
),
0
,
0
)
val
bytes
=
storage
.
readPixels
(
storage
.
imageInfo
,
(
w
*
4
),
0
,
0
)
if
(
bytes
!=
null
)
{
if
(
bytes
!=
null
)
{
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/AWTRedrawer.kt
View file @
89888a47
...
@@ -54,7 +54,7 @@ internal abstract class AWTRedrawer(
...
@@ -54,7 +54,7 @@ internal abstract class AWTRedrawer(
layer
.
update
(
nanoTime
)
layer
.
update
(
nanoTime
)
}
}
protected
inline
fun
inDrawScope
(
body
:
()
->
Unit
)
{
protected
inline
fun
inDrawScope
(
body
:
LayerDrawScope
.
()
->
Unit
)
{
requireNotNull
(
deviceAnalytics
)
{
"deviceAnalytics is not null. Call onDeviceChosen after choosing the drawing device"
}
requireNotNull
(
deviceAnalytics
)
{
"deviceAnalytics is not null. Call onDeviceChosen after choosing the drawing device"
}
if
(!
isDisposed
)
{
if
(!
isDisposed
)
{
val
isFirstFrame
=
!
isFirstFrameRendered
val
isFirstFrame
=
!
isFirstFrameRendered
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/AbstractDirectSoftwareRedrawer.kt
View file @
89888a47
...
@@ -33,7 +33,7 @@ internal abstract class AbstractDirectSoftwareRedrawer(
...
@@ -33,7 +33,7 @@ internal abstract class AbstractDirectSoftwareRedrawer(
frameDispatcher
.
scheduleFrame
()
frameDispatcher
.
scheduleFrame
()
}
}
protected
open
fun
draw
()
=
inDrawScope
(
contextHandler
::
draw
)
protected
open
fun
draw
()
=
inDrawScope
{
contextHandler
.
draw
()
}
override
fun
renderImmediately
()
{
override
fun
renderImmediately
()
{
update
()
update
()
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/AngleRedrawer.kt
View file @
89888a47
...
@@ -89,7 +89,9 @@ internal class AngleRedrawer(
...
@@ -89,7 +89,9 @@ internal class AngleRedrawer(
return
return
}
}
makeCurrent
(
device
)
makeCurrent
(
device
)
layer
.
inDrawScope
{
contextHandler
.
draw
()
contextHandler
.
draw
()
}
swapBuffers
(
device
,
withVsync
)
swapBuffers
(
device
,
withVsync
)
}
}
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/Direct3DRedrawer.kt
View file @
89888a47
...
@@ -86,7 +86,7 @@ internal class Direct3DRedrawer(
...
@@ -86,7 +86,7 @@ internal class Direct3DRedrawer(
}
}
}
}
private
fun
drawAndSwap
(
withVsync
:
Boolean
)
=
synchronized
(
drawLock
)
{
private
fun
LayerDrawScope
.
drawAndSwap
(
withVsync
:
Boolean
)
=
synchronized
(
drawLock
)
{
if
(
isDisposed
)
{
if
(
isDisposed
)
{
return
return
}
}
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/LinuxOpenGLRedrawer.kt
View file @
89888a47
...
@@ -97,7 +97,7 @@ internal class LinuxOpenGLRedrawer(
...
@@ -97,7 +97,7 @@ internal class LinuxOpenGLRedrawer(
}
}
private
fun
draw
()
{
private
fun
draw
()
{
inDrawScope
(
contextHandler
::
draw
)
inDrawScope
{
contextHandler
.
draw
()
}
}
}
companion
object
{
companion
object
{
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/MetalRedrawer.kt
View file @
89888a47
...
@@ -144,7 +144,7 @@ internal class MetalRedrawer(
...
@@ -144,7 +144,7 @@ internal class MetalRedrawer(
windowOcclusionStateChannel
.
trySend
(
isOccluded
)
windowOcclusionStateChannel
.
trySend
(
isOccluded
)
}
}
private
fun
performDraw
()
=
synchronized
(
drawLock
)
{
private
fun
LayerDrawScope
.
performDraw
()
=
synchronized
(
drawLock
)
{
if
(!
isDisposed
)
{
if
(!
isDisposed
)
{
autoreleasepool
{
autoreleasepool
{
contextHandler
.
draw
()
contextHandler
.
draw
()
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/SoftwareRedrawer.kt
View file @
89888a47
...
@@ -27,7 +27,7 @@ internal class SoftwareRedrawer(
...
@@ -27,7 +27,7 @@ internal class SoftwareRedrawer(
if
(
layer
.
isShowing
)
{
if
(
layer
.
isShowing
)
{
update
()
update
()
inDrawScope
(
contextHandler
::
draw
)
inDrawScope
{
contextHandler
.
draw
()
}
}
}
}
}
...
...
skiko/src/awtMain/kotlin/org/jetbrains/skiko/redrawer/WindowsOpenGLRedrawer.kt
View file @
89888a47
...
@@ -78,7 +78,7 @@ internal class WindowsOpenGLRedrawer(
...
@@ -78,7 +78,7 @@ internal class WindowsOpenGLRedrawer(
}
}
private
fun
draw
()
{
private
fun
draw
()
{
inDrawScope
(
contextHandler
::
draw
)
inDrawScope
{
contextHandler
.
draw
()
}
}
}
private
fun
makeCurrent
()
=
makeCurrent
(
device
,
context
)
private
fun
makeCurrent
()
=
makeCurrent
(
device
,
context
)
...
...
skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerTest.kt
View file @
89888a47
...
@@ -578,9 +578,9 @@ class SkiaLayerTest {
...
@@ -578,9 +578,9 @@ class SkiaLayerTest {
object
:
BaseTestRedrawer
(
layer
)
{
object
:
BaseTestRedrawer
(
layer
)
{
private
val
contextHandler
=
object
:
JvmContextHandler
(
layer
)
{
private
val
contextHandler
=
object
:
JvmContextHandler
(
layer
)
{
override
fun
initContext
()
=
false
override
fun
initContext
()
=
false
override
fun
initCanvas
()
=
Unit
override
fun
LayerDrawScope
.
initCanvas
()
=
Unit
}
}
override
fun
renderImmediately
()
=
layer
.
inDrawScope
(
contextHandler
::
draw
)
override
fun
renderImmediately
()
=
layer
.
inDrawScope
{
contextHandler
.
draw
()
}
}
}
}
}
}
}
...
...
skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
View file @
89888a47
...
@@ -3,6 +3,7 @@ package org.jetbrains.skiko
...
@@ -3,6 +3,7 @@ package org.jetbrains.skiko
import
org.jetbrains.skia.Canvas
import
org.jetbrains.skia.Canvas
import
org.jetbrains.skia.Picture
import
org.jetbrains.skia.Picture
import
org.jetbrains.skia.PixelGeometry
import
org.jetbrains.skia.PixelGeometry
import
org.jetbrains.skiko.context.ContextHandler
/**
/**
* Generic layer for Skiko rendering.
* Generic layer for Skiko rendering.
...
@@ -70,6 +71,35 @@ expect open class SkiaLayer {
...
@@ -70,6 +71,35 @@ expect open class SkiaLayer {
internal
fun
draw
(
canvas
:
Canvas
)
internal
fun
draw
(
canvas
:
Canvas
)
}
}
internal
class
PictureHolder
(
val
instance
:
Picture
,
val
width
:
Int
,
val
height
:
Int
)
internal
class
PictureHolder
(
val
instance
:
Picture
,
val
width
:
Int
,
val
height
:
Int
)
internal
class
LayerDrawScope
(
val
pixelGeometry
:
PixelGeometry
,
val
scaledLayerWidth
:
Int
,
val
scaledLayerHeight
:
Int
,
)
{
constructor
(
pixelGeometry
:
PixelGeometry
,
layerWidth
:
Int
,
layerHeight
:
Int
,
scale
:
Float
):
this
(
pixelGeometry
=
pixelGeometry
,
scaledLayerWidth
=
(
layerWidth
*
scale
).
toInt
().
coerceAtLeast
(
0
),
scaledLayerHeight
=
(
layerHeight
*
scale
).
toInt
().
coerceAtLeast
(
0
)
)
constructor
(
pixelGeometry
:
PixelGeometry
,
layerWidth
:
Double
,
layerHeight
:
Double
,
scale
:
Float
):
this
(
pixelGeometry
=
pixelGeometry
,
scaledLayerWidth
=
(
layerWidth
*
scale
).
toInt
().
coerceAtLeast
(
0
),
scaledLayerHeight
=
(
layerHeight
*
scale
).
toInt
().
coerceAtLeast
(
0
)
)
internal
fun
ContextHandler
.
draw
()
{
this
@LayerDrawScope
.
draw
()
}
}
\ No newline at end of file
skiko/src/commonMain/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
View file @
89888a47
...
@@ -13,9 +13,9 @@ internal abstract class ContextHandler(
...
@@ -13,9 +13,9 @@ internal abstract class ContextHandler(
protected
var
canvas
:
Canvas
?
=
null
protected
var
canvas
:
Canvas
?
=
null
protected
abstract
fun
initContext
():
Boolean
protected
abstract
fun
initContext
():
Boolean
protected
abstract
fun
initCanvas
()
protected
abstract
fun
LayerDrawScope
.
initCanvas
()
protected
open
fun
flush
()
{
protected
open
fun
flush
(
scope
:
LayerDrawScope
)
{
context
?.
flush
()
context
?.
flush
()
}
}
...
@@ -35,7 +35,7 @@ internal abstract class ContextHandler(
...
@@ -35,7 +35,7 @@ internal abstract class ContextHandler(
}
}
// throws RenderException if initialization of graphic context was not successful
// throws RenderException if initialization of graphic context was not successful
fun
draw
()
{
fun
LayerDrawScope
.
draw
()
{
if
(!
initContext
())
{
if
(!
initContext
())
{
throw
RenderException
(
"Cannot init graphic context"
)
throw
RenderException
(
"Cannot init graphic context"
)
}
}
...
@@ -44,6 +44,7 @@ internal abstract class ContextHandler(
...
@@ -44,6 +44,7 @@ internal abstract class ContextHandler(
clear
(
Color
.
TRANSPARENT
)
clear
(
Color
.
TRANSPARENT
)
drawContent
()
drawContent
()
}
}
flush
()
flush
(
this
)
}
}
}
}
skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkiaLayer.macos.kt
View file @
89888a47
...
@@ -168,4 +168,17 @@ actual open class SkiaLayer {
...
@@ -168,4 +168,17 @@ actual open class SkiaLayer {
actual
val
pixelGeometry
:
PixelGeometry
actual
val
pixelGeometry
:
PixelGeometry
get
()
=
PixelGeometry
.
UNKNOWN
get
()
=
PixelGeometry
.
UNKNOWN
private
fun
createDrawScope
()
=
LayerDrawScope
(
pixelGeometry
=
pixelGeometry
,
layerWidth
=
nsView
.
frame
.
useContents
{
size
.
width
},
layerHeight
=
nsView
.
frame
.
useContents
{
size
.
height
},
scale
=
contentScale
)
internal
fun
inDrawScope
(
block
:
LayerDrawScope
.()
->
Unit
)
{
with
(
createDrawScope
())
{
block
()
}
}
}
}
skiko/src/macosMain/kotlin/org/jetbrains/skiko/context/MetalContextHandler.macos.kt
View file @
89888a47
package
org.jetbrains.skiko.context
package
org.jetbrains.skiko.context
import
kotlinx.cinterop.useContents
import
org.jetbrains.skia.*
import
org.jetbrains.skia.*
import
org.jetbrains.skiko.LayerDrawScope
import
org.jetbrains.skiko.RenderException
import
org.jetbrains.skiko.RenderException
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.redrawer.MacOsMetalRedrawer
import
org.jetbrains.skiko.redrawer.MacOsMetalRedrawer
/**
/**
* Metal ContextHandler implementation for
MacOs
.
* Metal ContextHandler implementation for
macOS
.
*/
*/
internal
class
MacOsMetalContextHandler
(
layer
:
SkiaLayer
)
:
ContextHandler
(
layer
,
layer
::
draw
)
{
internal
class
MacOsMetalContextHandler
(
layer
:
SkiaLayer
)
:
ContextHandler
(
layer
,
layer
::
draw
)
{
private
val
metalRedrawer
:
MacOsMetalRedrawer
private
val
metalRedrawer
:
MacOsMetalRedrawer
...
@@ -25,12 +25,11 @@ internal class MacOsMetalContextHandler(layer: SkiaLayer) : ContextHandler(layer
...
@@ -25,12 +25,11 @@ internal class MacOsMetalContextHandler(layer: SkiaLayer) : ContextHandler(layer
return
true
return
true
}
}
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
disposeCanvas
()
disposeCanvas
()
val
scale
=
layer
.
contentScale
val
w
=
scaledLayerWidth
val
w
=
(
layer
.
nsView
.
frame
.
useContents
{
size
.
width
}
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
scaledLayerHeight
val
h
=
(
layer
.
nsView
.
frame
.
useContents
{
size
.
height
}
*
scale
).
toInt
().
coerceAtLeast
(
0
)
if
(
w
>
0
&&
h
>
0
)
{
if
(
w
>
0
&&
h
>
0
)
{
renderTarget
=
metalRedrawer
.
makeRenderTarget
(
w
,
h
)
renderTarget
=
metalRedrawer
.
makeRenderTarget
(
w
,
h
)
...
@@ -52,9 +51,9 @@ internal class MacOsMetalContextHandler(layer: SkiaLayer) : ContextHandler(layer
...
@@ -52,9 +51,9 @@ internal class MacOsMetalContextHandler(layer: SkiaLayer) : ContextHandler(layer
}
}
}
}
override
fun
flush
()
{
override
fun
flush
(
scope
:
LayerDrawScope
)
{
// TODO: maybe make flush async as in JVM version.
// TODO: maybe make flush async as in JVM version.
super
.
flush
()
super
.
flush
(
scope
)
surface
?.
flushAndSubmit
()
surface
?.
flushAndSubmit
()
metalRedrawer
.
finishFrame
()
metalRedrawer
.
finishFrame
()
}
}
...
...
skiko/src/macosMain/kotlin/org/jetbrains/skiko/context/OpenGLContextHandler.macos.kt
View file @
89888a47
...
@@ -3,6 +3,7 @@ package org.jetbrains.skiko.context
...
@@ -3,6 +3,7 @@ package org.jetbrains.skiko.context
import
kotlinx.cinterop.*
import
kotlinx.cinterop.*
import
org.jetbrains.skia.*
import
org.jetbrains.skia.*
import
org.jetbrains.skiko.GraphicsApi
import
org.jetbrains.skiko.GraphicsApi
import
org.jetbrains.skiko.LayerDrawScope
import
org.jetbrains.skiko.RenderException
import
org.jetbrains.skiko.RenderException
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.SkiaLayer
import
platform.OpenGL.GL_DRAW_FRAMEBUFFER_BINDING
import
platform.OpenGL.GL_DRAW_FRAMEBUFFER_BINDING
...
@@ -10,7 +11,8 @@ import platform.OpenGL.glGetIntegerv
...
@@ -10,7 +11,8 @@ import platform.OpenGL.glGetIntegerv
import
platform.OpenGLCommon.GLenum
import
platform.OpenGLCommon.GLenum
/**
/**
* OpenGL context handler for MacOs (native).
* OpenGL context handler for macOS (native).
*
* Not used anymore, unless corresponding [GraphicsApi] is hardcoded in [SkiaLayer].
* Not used anymore, unless corresponding [GraphicsApi] is hardcoded in [SkiaLayer].
* See [MacOsMetalContextHandler] instead.
* See [MacOsMetalContextHandler] instead.
*/
*/
...
@@ -20,7 +22,7 @@ internal class MacOSOpenGLContextHandler(layer: SkiaLayer) : ContextHandler(laye
...
@@ -20,7 +22,7 @@ internal class MacOSOpenGLContextHandler(layer: SkiaLayer) : ContextHandler(laye
if
(
context
==
null
)
{
if
(
context
==
null
)
{
context
=
DirectContext
.
makeGL
()
context
=
DirectContext
.
makeGL
()
}
}
}
catch
(
e
:
Exception
)
{
}
catch
(
_
:
Exception
)
{
println
(
"Failed to create Skia OpenGL context!"
)
println
(
"Failed to create Skia OpenGL context!"
)
return
false
return
false
}
}
...
@@ -29,11 +31,11 @@ internal class MacOSOpenGLContextHandler(layer: SkiaLayer) : ContextHandler(laye
...
@@ -29,11 +31,11 @@ internal class MacOSOpenGLContextHandler(layer: SkiaLayer) : ContextHandler(laye
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
private
fun
openglGetIntegerv
(
pname
:
GLenum
):
UInt
{
private
fun
openglGetIntegerv
(
pname
:
GLenum
):
UInt
{
var
result
:
UInt
=
0
U
var
result
=
0
U
memScoped
{
memScoped
{
val
data
=
alloc
<
IntVar
>()
val
data
=
alloc
<
IntVar
>()
glGetIntegerv
(
pname
,
data
.
ptr
)
;
glGetIntegerv
(
pname
,
data
.
ptr
)
result
=
data
.
value
.
toUInt
()
;
result
=
data
.
value
.
toUInt
()
}
}
return
result
return
result
}
}
...
@@ -49,10 +51,9 @@ internal class MacOSOpenGLContextHandler(layer: SkiaLayer) : ContextHandler(laye
...
@@ -49,10 +51,9 @@ internal class MacOSOpenGLContextHandler(layer: SkiaLayer) : ContextHandler(laye
return
false
return
false
}
}
override
fun
initCanvas
()
{
override
fun
LayerDrawScope
.
initCanvas
()
{
val
scale
=
layer
.
contentScale
val
w
=
scaledLayerWidth
val
w
=
(
layer
.
nsView
.
frame
.
useContents
{
size
.
width
}
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
scaledLayerHeight
val
h
=
(
layer
.
nsView
.
frame
.
useContents
{
size
.
height
}
*
scale
).
toInt
().
coerceAtLeast
(
0
)
if
(
isSizeChanged
(
w
,
h
))
{
if
(
isSizeChanged
(
w
,
h
))
{
val
fbId
=
openglGetIntegerv
(
GL_DRAW_FRAMEBUFFER_BINDING
.
toUInt
())
val
fbId
=
openglGetIntegerv
(
GL_DRAW_FRAMEBUFFER_BINDING
.
toUInt
())
renderTarget
=
BackendRenderTarget
.
makeGL
(
renderTarget
=
BackendRenderTarget
.
makeGL
(
...
...
skiko/src/macosMain/kotlin/org/jetbrains/skiko/redrawer/MetalRedrawer.macos.kt
View file @
89888a47
...
@@ -157,18 +157,22 @@ internal class MacOsMetalRedrawer(
...
@@ -157,18 +157,22 @@ internal class MacOsMetalRedrawer(
update
()
update
()
}
}
if
(!
isDisposed
)
{
// Redrawer may be disposed in user code, during `update`
if
(!
isDisposed
)
{
// Redrawer may be disposed in user code, during `update`
skiaLayer
.
inDrawScope
{
contextHandler
.
draw
()
contextHandler
.
draw
()
}
}
}
}
}
}
}
private
suspend
fun
draw
()
{
private
suspend
fun
draw
()
{
autoreleasepool
{
autoreleasepool
{
if
(!
isDisposed
)
{
if
(!
isDisposed
)
{
update
()
update
()
skiaLayer
.
inDrawScope
{
contextHandler
.
draw
()
contextHandler
.
draw
()
}
}
}
}
}
// When window is not visible - it doesn't make sense to redraw fast to avoid battery drain.
// When window is not visible - it doesn't make sense to redraw fast to avoid battery drain.
if
(
isWindowOccluded
)
{
if
(
isWindowOccluded
)
{
...
@@ -233,6 +237,8 @@ internal class MetalLayer : CAMetalLayer {
...
@@ -233,6 +237,8 @@ internal class MetalLayer : CAMetalLayer {
override
fun
drawInContext
(
ctx
:
CGContextRef
?)
{
override
fun
drawInContext
(
ctx
:
CGContextRef
?)
{
skiaLayer
.
update
(
currentNanoTime
())
skiaLayer
.
update
(
currentNanoTime
())
skiaLayer
.
inDrawScope
{
contextHandler
.
draw
()
contextHandler
.
draw
()
}
}
}
}
}
skiko/src/macosMain/kotlin/org/jetbrains/skiko/redrawer/OpenGLRedrawer.macos.kt
View file @
89888a47
...
@@ -133,7 +133,9 @@ internal class MacosGLLayer : CAOpenGLLayer {
...
@@ -133,7 +133,9 @@ internal class MacosGLLayer : CAOpenGLLayer {
CGLSetCurrentContext
(
ctx
)
CGLSetCurrentContext
(
ctx
)
try
{
try
{
skiaLayer
.
update
(
currentNanoTime
())
skiaLayer
.
update
(
currentNanoTime
())
skiaLayer
.
inDrawScope
{
contextHandler
.
draw
()
contextHandler
.
draw
()
}
}
catch
(
e
:
Throwable
)
{
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
e
.
printStackTrace
()
throw
e
throw
e
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment