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
3158b8d7
Unverified
Commit
3158b8d7
authored
Mar 16, 2021
by
Roman Sedaikin
Committed by
GitHub
Mar 16, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #70 from JetBrains/metal
Metal API prototype.
parents
1f13701d
427dbacf
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
426 additions
and
101 deletions
+426
-101
.gitignore
.gitignore
+1
-0
build.gradle.kts
skiko/build.gradle.kts
+8
-2
HardwareLayer.kt
...o/src/jvmMain/kotlin/org/jetbrains/skiko/HardwareLayer.kt
+9
-45
PlatformOperations.kt
.../jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
+6
-4
SkiaLayer.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+82
-8
SkikoProperties.kt
...src/jvmMain/kotlin/org/jetbrains/skiko/SkikoProperties.kt
+2
-2
ContextHandler.kt
...Main/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
+1
-0
MetalContextHandler.kt
...kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
+15
-9
SoftwareContextHandler.kt
...lin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
+1
-1
Direct3DRedrawer.kt
...n/kotlin/org/jetbrains/skiko/redrawer/Direct3DRedrawer.kt
+2
-2
LinuxOpenGLRedrawer.kt
...otlin/org/jetbrains/skiko/redrawer/LinuxOpenGLRedrawer.kt
+6
-5
MacOsOpenGLRedrawer.kt
...otlin/org/jetbrains/skiko/redrawer/MacOsOpenGLRedrawer.kt
+3
-3
MetalRedrawer.kt
...Main/kotlin/org/jetbrains/skiko/redrawer/MetalRedrawer.kt
+79
-0
SoftwareRedrawer.kt
...n/kotlin/org/jetbrains/skiko/redrawer/SoftwareRedrawer.kt
+2
-2
WindowsOpenGLRedrawer.kt
...lin/org/jetbrains/skiko/redrawer/WindowsOpenGLRedrawer.kt
+3
-3
Drawlayer.mm
skiko/src/jvmMain/objectiveC/macos/Drawlayer.mm
+8
-3
MetalRedrawer.mm
skiko/src/jvmMain/objectiveC/macos/MetalRedrawer.mm
+181
-0
OpenGLRedrawer.mm
skiko/src/jvmMain/objectiveC/macos/OpenGLRedrawer.mm
+17
-12
No files found.
.gitignore
View file @
3158b8d7
build
.gradle
.project
local.properties
.DS_Store
run.sh
...
...
skiko/build.gradle.kts
View file @
3158b8d7
...
...
@@ -288,15 +288,21 @@ tasks.withType(CppCompile::class.java).configureEach {
project
.
tasks
.
register
<
Exec
>(
"objcCompile"
)
{
val
inputDir
=
"$projectDir/src/jvmMain/objectiveC/${targetOs.id}"
val
outDir
=
"$buildDir/objc/$target"
val
names
=
File
(
inputDir
).
listFiles
()
!!
.
map
{
it
.
name
.
removeSuffix
(
".m"
)
}
val
srcs
=
names
.
map
{
"$inputDir/$it.m"
}.
toTypedArray
()
val
names
=
File
(
inputDir
).
listFiles
()
!!
.
map
{
it
.
name
.
removeSuffix
(
".m
m
"
)
}
val
srcs
=
names
.
map
{
"$inputDir/$it.m
m
"
}.
toTypedArray
()
val
outs
=
names
.
map
{
"$outDir/$it.o"
}.
toTypedArray
()
workingDir
=
File
(
outDir
)
val
skiaDir
=
skiaDir
.
get
().
absolutePath
commandLine
=
listOf
(
"clang"
,
"-mmacosx-version-min=10.13"
,
"-I$jdkHome/include"
,
"-I$jdkHome/include/darwin"
,
"-I$skiaDir"
,
"-I$skiaDir/include"
,
"-I$skiaDir/include/gpu"
,
"-DSK_METAL"
,
"-std=c++17"
,
"-c"
,
*
srcs
)
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/HardwareLayer.kt
View file @
3158b8d7
...
...
@@ -13,62 +13,32 @@ 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
()
}
override
fun
paint
(
g
:
Graphics
)
{}
protected
open
fun
init
()
{
internal
open
fun
init
()
{
useDrawingSurfacePlatformInfo
(
::
nativeInit
)
onInit
()
}
fun
dispose
()
{
if
(
isInit
)
{
onDispose
()
nativeDispose
()
}
internal
fun
dispose
()
{
nativeDispose
()
}
protected
open
fun
onInit
()
=
Unit
protected
open
fun
onDispose
()
=
Unit
private
external
fun
nativeInit
(
platformInfo
:
Long
)
private
external
fun
nativeDispose
()
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
{
...
...
@@ -77,12 +47,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
)
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
View file @
3158b8d7
...
...
@@ -6,6 +6,7 @@ import org.jetbrains.skiko.redrawer.SoftwareRedrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.WindowsOpenGLRedrawer
import
org.jetbrains.skiko.redrawer.Direct3DRedrawer
import
org.jetbrains.skiko.redrawer.MetalRedrawer
import
java.awt.Component
import
java.awt.Window
import
javax.swing.SwingUtilities
...
...
@@ -14,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
:
Hardware
Layer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
):
Redrawer
fun
createRedrawer
(
layer
:
Skia
Layer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
):
Redrawer
}
internal
val
platformOperations
:
PlatformOperations
by
lazy
{
...
...
@@ -33,11 +34,12 @@ internal val platformOperations: PlatformOperations by lazy {
}
override
fun
createRedrawer
(
layer
:
Hardware
Layer
,
layer
:
Skia
Layer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
SoftwareRedrawer
(
layer
)
GraphicsApi
.
METAL
->
MetalRedrawer
(
layer
,
properties
)
else
->
MacOsOpenGLRedrawer
(
layer
,
properties
)
}
}
...
...
@@ -60,7 +62,7 @@ internal val platformOperations: PlatformOperations by lazy {
}
override
fun
createRedrawer
(
layer
:
Hardware
Layer
,
layer
:
Skia
Layer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
...
...
@@ -101,7 +103,7 @@ internal val platformOperations: PlatformOperations by lazy {
}
override
fun
createRedrawer
(
layer
:
Hardware
Layer
,
layer
:
Skia
Layer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
View file @
3158b8d7
...
...
@@ -8,7 +8,14 @@ import org.jetbrains.skija.Rect
import
org.jetbrains.skiko.context.ContextHandler
import
org.jetbrains.skiko.context.createContextHandler
import
org.jetbrains.skiko.redrawer.Redrawer
import
java.awt.event.InputMethodListener
import
java.awt.event.KeyListener
import
java.awt.event.MouseListener
import
java.awt.event.MouseMotionListener
import
java.awt.event.MouseWheelListener
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 +27,48 @@ 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
)
layout
=
null
backedLayer
=
object
:
HardwareLayer
()
{
}
add
(
backedLayer
)
@Suppress
(
"LeakingThis"
)
backedLayer
.
addHierarchyListener
{
if
(
it
.
changeFlags
and
HierarchyEvent
.
SHOWING_CHANGED
.
toLong
()
!=
0L
)
{
checkIsShowing
()
}
}
}
private
var
isInited
=
false
private
fun
checkIsShowing
()
{
if
(!
isInited
&&
isShowing
)
{
backedLayer
.
defineContentScale
()
init
()
isInited
=
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 +80,8 @@ open class SkiaLayer(
private
val
pictureRecorder
=
PictureRecorder
()
private
val
pictureLock
=
Any
()
o
verride
fun
onI
nit
()
{
super
.
onI
nit
()
o
pen
fun
i
nit
()
{
backedLayer
.
i
nit
()
val
initialRenderApi
=
fallbackRenderApiQueue
.
removeAt
(
0
)
contextHandler
=
createContextHandler
(
this
,
initialRenderApi
)
redrawer
=
platformOperations
.
createRedrawer
(
this
,
initialRenderApi
,
properties
)
...
...
@@ -45,7 +89,7 @@ open class SkiaLayer(
redraw
()
}
o
verride
fun
onD
ispose
()
{
o
pen
fun
d
ispose
()
{
check
(!
isDisposed
)
check
(
isEventDispatchThread
())
redrawer
?.
dispose
()
// we should dispose redrawer first (to cancel `draw` in rendering thread)
...
...
@@ -53,21 +97,51 @@ open class SkiaLayer(
picture
?.
instance
?.
close
()
pictureRecorder
.
close
()
isDisposed
=
true
super
.
onDispose
()
if
(
isInited
)
{
backedLayer
.
dispose
()
}
}
override
fun
setBounds
(
x
:
Int
,
y
:
Int
,
width
:
Int
,
height
:
Int
)
{
super
.
setBounds
(
x
,
y
,
width
,
height
)
backedLayer
.
setSize
(
width
,
height
)
if
(
backedLayer
.
checkContentScale
())
{
contentScaleChanged
()
}
redrawer
?.
syncSize
()
redraw
()
revalidate
()
}
override
fun
paint
(
g
:
Graphics
)
{
super
.
paint
(
g
)
if
(
backedLayer
.
checkContentScale
())
{
contentScaleChanged
()
}
redrawer
?.
syncSize
()
redrawer
?.
redrawImmediately
()
}
override
fun
addInputMethodListener
(
l
:
InputMethodListener
)
{
backedLayer
.
addInputMethodListener
(
l
)
}
override
fun
addMouseListener
(
l
:
MouseListener
)
{
backedLayer
.
addMouseListener
(
l
)
}
override
fun
addMouseMotionListener
(
l
:
MouseMotionListener
)
{
backedLayer
.
addMouseMotionListener
(
l
)
}
override
fun
addMouseWheelListener
(
l
:
MouseWheelListener
)
{
backedLayer
.
addMouseWheelListener
(
l
)
}
override
fun
addKeyListener
(
l
:
KeyListener
)
{
backedLayer
.
addKeyListener
(
l
)
}
private
var
redrawScheduled
=
false
/**
...
...
@@ -97,7 +171,7 @@ open class SkiaLayer(
@Suppress
(
"LeakingThis"
)
private
val
fpsCounter
=
defaultFPSCounter
(
this
)
o
verride
fun
update
(
nanoTime
:
Long
)
{
o
pen
fun
update
(
nanoTime
:
Long
)
{
check
(!
isDisposed
)
check
(
isEventDispatchThread
())
...
...
@@ -126,7 +200,7 @@ open class SkiaLayer(
}
}
o
verride
fun
draw
()
{
o
pen
fun
draw
()
{
check
(!
isDisposed
)
contextHandler
?.
apply
{
if
(!
initContext
())
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkikoProperties.kt
View file @
3158b8d7
...
...
@@ -43,7 +43,7 @@ internal object SkikoProperties {
private
fun
bestRenderApiForCurrentOS
():
GraphicsApi
{
when
(
hostOs
)
{
OS
.
MacOS
->
return
GraphicsApi
.
OPENG
L
OS
.
MacOS
->
return
GraphicsApi
.
META
L
OS
.
Linux
->
return
GraphicsApi
.
OPENGL
OS
.
Windows
->
return
GraphicsApi
.
DIRECT3D
}
...
...
@@ -54,8 +54,8 @@ internal object SkikoProperties {
var
renderApiList
=
mutableListOf
<
GraphicsApi
>()
when
(
hostOs
)
{
OS
.
MacOS
->
renderApiList
=
mutableListOf
(
GraphicsApi
.
OPENGL
,
GraphicsApi
.
SOFTWARE
)
OS
.
Linux
->
renderApiList
=
mutableListOf
(
GraphicsApi
.
OPENGL
,
GraphicsApi
.
SOFTWARE
)
OS
.
MacOS
->
renderApiList
=
mutableListOf
(
GraphicsApi
.
METAL
,
GraphicsApi
.
OPENGL
,
GraphicsApi
.
SOFTWARE
)
OS
.
Windows
->
renderApiList
=
mutableListOf
(
GraphicsApi
.
DIRECT3D
,
GraphicsApi
.
OPENGL
,
GraphicsApi
.
SOFTWARE
)
}
renderApiList
.
remove
(
head
)
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
View file @
3158b8d7
...
...
@@ -17,6 +17,7 @@ internal fun createContextHandler(layer: SkiaLayer, renderApi: GraphicsApi): Con
GraphicsApi
.
SOFTWARE
->
SoftwareContextHandler
(
layer
)
GraphicsApi
.
OPENGL
->
OpenGLContextHandler
(
layer
)
GraphicsApi
.
DIRECT3D
->
Direct3DContextHandler
(
layer
)
GraphicsApi
.
METAL
->
MetalContextHandler
(
layer
)
else
->
TODO
(
"Unsupported yet."
)
}
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
View file @
3158b8d7
...
...
@@ -4,20 +4,20 @@ import org.jetbrains.skija.ColorSpace
import
org.jetbrains.skija.Surface
import
org.jetbrains.skija.SurfaceColorFormat
import
org.jetbrains.skija.SurfaceOrigin
import
org.jetbrains.skiko.GraphicsApi
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.makeMetalContext
import
org.jetbrains.skiko.makeMetalRenderTarget
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.MetalRedrawer
internal
class
MetalContextHandler
(
layer
:
SkiaLayer
)
:
ContextHandler
(
layer
)
{
val
metalRedrawer
:
MetalRedrawer
get
()
=
layer
.
redrawer
!!
as
MetalRedrawer
override
fun
initContext
():
Boolean
{
try
{
if
(
context
==
null
)
{
context
=
m
akeMetal
Context
()
context
=
m
etalRedrawer
.
make
Context
()
}
}
catch
(
e
:
Exception
)
{
println
(
"Failed to create Skia Metal context!"
)
println
(
"
${e.message}\n
Failed to create Skia Metal context!"
)
return
false
}
return
true
...
...
@@ -30,16 +30,22 @@ internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
renderTarget
=
m
akeMetalRenderTarget
(
w
,
h
,
0
)
renderTarget
=
m
etalRedrawer
.
makeRenderTarget
(
w
,
h
)
surface
=
Surface
.
makeFromBackendRenderTarget
(
context
!!
,
renderTarget
!!
,
SurfaceOrigin
.
BOTTOM
_LEFT
,
SurfaceColorFormat
.
RGB
A_8888
,
SurfaceOrigin
.
TOP
_LEFT
,
SurfaceColorFormat
.
BGR
A_8888
,
ColorSpace
.
getSRGB
()
)
canvas
=
surface
!!
.
canvas
}
override
fun
flush
()
{
super
.
flush
()
surface
!!
.
flushAndSubmit
()
metalRedrawer
.
finishFrame
()
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
View file @
3158b8d7
...
...
@@ -73,7 +73,7 @@ internal class SoftwareContextHandler(layer: SkiaLayer) : ContextHandler(layer)
null
)
image
=
BufferedImage
(
colorModel
,
raster
!!
,
false
,
null
)
layer
.
getGraphics
()
?.
drawImage
(
image
!!
,
0
,
0
,
layer
.
width
,
layer
.
height
,
null
)
layer
.
backedLayer
.
getGraphics
()
?.
drawImage
(
image
!!
,
0
,
0
,
layer
.
width
,
layer
.
height
,
null
)
}
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/Direct3DRedrawer.kt
View file @
3158b8d7
...
...
@@ -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.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
import
org.jetbrains.skiko.SkiaLayerProperties
internal
class
Direct3DRedrawer
(
private
val
layer
:
Hardware
Layer
,
private
val
layer
:
Skia
Layer
,
private
val
properties
:
SkiaLayerProperties
)
:
Redrawer
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/LinuxOpenGLRedrawer.kt
View file @
3158b8d7
...
...
@@ -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
:
Hardware
Layer
,
private
val
layer
:
Skia
Layer
,
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
)
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/MacOsOpenGLRedrawer.kt
View file @
3158b8d7
...
...
@@ -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.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
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
:
Hardware
Layer
,
private
val
layer
:
Skia
Layer
,
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
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/MetalRedrawer.kt
0 → 100644
View file @
3158b8d7
package
org.jetbrains.skiko.redrawer
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.swing.Swing
import
org.jetbrains.skija.BackendRenderTarget
import
org.jetbrains.skija.DirectContext
import
org.jetbrains.skiko.FrameDispatcher
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
:
SkiaLayer
,
private
val
properties
:
SkiaLayerProperties
)
:
Redrawer
{
private
var
isDisposed
=
false
private
val
device
=
layer
.
backedLayer
.
useDrawingSurfacePlatformInfo
(
::
createMetalDevice
)
private
val
frameDispatcher
=
FrameDispatcher
(
Dispatchers
.
Swing
)
{
update
(
System
.
nanoTime
())
draw
()
}
override
fun
dispose
()
{
frameDispatcher
.
cancel
()
disposeDevice
(
device
)
isDisposed
=
true
}
override
fun
needRedraw
()
{
check
(!
isDisposed
)
frameDispatcher
.
scheduleFrame
()
}
override
fun
redrawImmediately
()
{
check
(!
isDisposed
)
update
(
System
.
nanoTime
())
draw
()
}
private
fun
update
(
nanoTime
:
Long
)
{
layer
.
update
(
nanoTime
)
}
private
fun
draw
()
{
layer
.
draw
()
}
override
fun
syncSize
()
{
val
globalPosition
=
convertPoint
(
layer
,
layer
.
x
,
layer
.
y
,
getRootPane
(
layer
))
setContentScale
(
device
,
layer
.
contentScale
)
resizeLayers
(
device
,
globalPosition
.
x
,
globalPosition
.
y
,
layer
.
width
.
coerceAtLeast
(
0
),
layer
.
height
.
coerceAtLeast
(
0
)
)
}
fun
makeContext
()
=
DirectContext
(
makeMetalContext
(
device
)
)
fun
makeRenderTarget
(
width
:
Int
,
height
:
Int
)
=
BackendRenderTarget
(
makeMetalRenderTarget
(
device
,
width
,
height
)
)
fun
finishFrame
()
=
finishFrame
(
device
)
private
external
fun
createMetalDevice
(
platformInfo
:
Long
):
Long
private
external
fun
makeMetalContext
(
device
:
Long
):
Long
private
external
fun
makeMetalRenderTarget
(
device
:
Long
,
width
:
Int
,
height
:
Int
):
Long
private
external
fun
disposeDevice
(
device
:
Long
)
private
external
fun
finishFrame
(
device
:
Long
)
private
external
fun
resizeLayers
(
device
:
Long
,
x
:
Int
,
y
:
Int
,
width
:
Int
,
height
:
Int
)
private
external
fun
setContentScale
(
device
:
Long
,
contentScale
:
Float
)
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/SoftwareRedrawer.kt
View file @
3158b8d7
...
...
@@ -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.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
internal
class
SoftwareRedrawer
(
private
val
layer
:
Hardware
Layer
private
val
layer
:
Skia
Layer
)
:
Redrawer
{
private
val
frameDispatcher
=
FrameDispatcher
(
Dispatchers
.
Swing
)
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/WindowsOpenGLRedrawer.kt
View file @
3158b8d7
...
...
@@ -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.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
import
org.jetbrains.skiko.OpenGLApi
import
org.jetbrains.skiko.SkiaLayerProperties
import
org.jetbrains.skiko.useDrawingSurfacePlatformInfo
internal
class
WindowsOpenGLRedrawer
(
private
val
layer
:
Hardware
Layer
,
private
val
layer
:
Skia
Layer
,
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
...
...
skiko/src/jvmMain/objectiveC/macos/
drawlayer.
m
→
skiko/src/jvmMain/objectiveC/macos/
Drawlayer.m
m
View file @
3158b8d7
...
...
@@ -36,7 +36,7 @@
- (void) disposeLayer:(JNIEnv *) env
{
(
*
env
)
->
DeleteGlobalRef
(
env
,
self
.
canvasGlobalRef
);
env->DeleteGlobalRef(
self.canvasGlobalRef);
self.canvasGlobalRef = NULL;
self.container = NULL;
self.window = NULL;
...
...
@@ -71,7 +71,7 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
}
for (LayerHandler* layer in layerStorage)
{
if
(
(
*
env
)
->
IsSameObject
(
env
,
object
,
layer
.
canvasGlobalRef
)
==
JNI_TRUE
)
if (
env->IsSameObject(
object, layer.canvasGlobalRef) == JNI_TRUE)
{
return layer;
}
...
...
@@ -79,6 +79,9 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
return NULL;
}
extern "C"
{
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_nativeInit(JNIEnv *env, jobject canvas, jlong platformInfoPtr)
{
if (layerStorage == nil)
...
...
@@ -91,7 +94,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_nativeInit(JNIEnv
LayerHandler *layersSet = [[LayerHandler alloc] init];
layersSet.container = [dsi_mac windowLayer];
jobject
canvasGlobalRef
=
(
*
env
)
->
NewGlobalRef
(
env
,
canvas
);
jobject canvasGlobalRef =
env->NewGlobalRef(
canvas);
[layersSet setCanvasGlobalRef: canvasGlobalRef];
NSMutableArray<NSWindow *> *windows = [NSMutableArray arrayWithArray: [[NSApplication sharedApplication] windows]];
...
...
@@ -153,3 +156,5 @@ void getMetalDeviceAndQueue(void** device, void** queue)
*device = (__bridge void*)fDevice;
*queue = (__bridge void*)fQueue;
}
} // extern C
\ No newline at end of file
skiko/src/jvmMain/objectiveC/macos/MetalRedrawer.mm
0 → 100644
View file @
3158b8d7
#ifdef SK_METAL
#import <jawt.h>
#import <jawt_md.h>
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
#import <GrBackendSurface.h>
#import <GrDirectContext.h>
#import <mtl/GrMtlBackendContext.h>
#import <mtl/GrMtlTypes.h>
@interface AWTMetalLayer : CAMetalLayer
@property jobject javaRef;
@end
@interface MetalDevice : NSObject
@property (retain, strong) CALayer *container;
@property (retain, strong) AWTMetalLayer *layer;
@property (retain, strong) id<MTLDevice> device;
@property (retain, strong) id<MTLCommandQueue> queue;
@property (retain, strong) id<CAMetalDrawable> drawableHandle;
@end
@implementation AWTMetalLayer
- (id)init
{
self = [super init];
assert(self != NULL);
[self removeAllAnimations];
[self setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[self setNeedsDisplayOnBoundsChange: YES];
return self;
}
@end
@implementation MetalDevice
- (id) init
{
self = [super init];
if (self)
{
self.layer = nil;
self.device = nil;
self.queue = nil;
self.drawableHandle = nil;
}
return self;
}
@end
extern "C"
{
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_makeMetalContext(
JNIEnv* env, jobject redrawer, jlong devicePtr)
{
MetalDevice *device = (MetalDevice *) devicePtr;
GrMtlBackendContext backendContext = {};
backendContext.fDevice.retain((GrMTLHandle) device.device);
backendContext.fQueue.retain((GrMTLHandle) device.queue);
return (jlong) GrDirectContext::MakeMetal(backendContext).release();
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_makeMetalRenderTarget(
JNIEnv * env, jobject redrawer, jlong devicePtr, jint width, jint height)
{
MetalDevice *device = (MetalDevice *) devicePtr;
device.layer.drawableSize = CGRectMake(0, 0, width, height).size;
id<CAMetalDrawable> currentDrawable = [device.layer nextDrawable];
GrMtlTextureInfo info;
info.fTexture.retain(currentDrawable.texture);
GrBackendRenderTarget* renderTarget = new GrBackendRenderTarget(width, height, 0, info);
device.drawableHandle = currentDrawable;
return (jlong) renderTarget;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMetalDevice(
JNIEnv *env, jobject redrawer, jlong platformInfoPtr)
{
MetalDevice *device = [MetalDevice new];
NSObject<JAWT_SurfaceLayers>* dsi_mac = (__bridge NSObject<JAWT_SurfaceLayers> *) platformInfoPtr;
CALayer *container = [dsi_mac windowLayer];
[container removeAllAnimations];
[container setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[container setNeedsDisplayOnBoundsChange: YES];
AWTMetalLayer *layer = [AWTMetalLayer new];
[container addSublayer: layer];
layer.javaRef = env->NewGlobalRef(redrawer);
id<MTLDevice> fDevice = MTLCreateSystemDefaultDevice();
id<MTLCommandQueue> fQueue = [fDevice newCommandQueue];
device.container = container;
device.layer = layer;
device.device = fDevice;
device.queue = fQueue;
device.layer.device = device.device;
device.layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
device.layer.contentsGravity = kCAGravityTopLeft;
CGFloat transparent[] = { 0.0f, 0.0f, 0.0f, 0.0f };
device.layer.backgroundColor = CGColorCreate(CGColorSpaceCreateDeviceRGB(), transparent);
device.layer.opaque = NO;
return (jlong) device;
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_resizeLayers(
JNIEnv *env, jobject redrawer, jlong devicePtr, jint x, jint y, jint width, jint height)
{
MetalDevice *device = (MetalDevice *) devicePtr;
y = (int)device.container.frame.size.height - y - height;
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
device.layer.frame = CGRectMake(x, y, width, height);
[CATransaction commit];
[CATransaction flush];
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_setContentScale(JNIEnv *env, jobject obj, jlong devicePtr, jfloat contentScale)
{
MetalDevice *device = (MetalDevice *) devicePtr;
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
assert(contentScale != 0);
device.layer.contentsScale = contentScale;
[CATransaction commit];
[CATransaction flush];
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_finishFrame(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
MetalDevice *device = (MetalDevice *) devicePtr;
id<CAMetalDrawable> currentDrawable = device.drawableHandle;
id<MTLCommandBuffer> commandBuffer = [device.queue commandBuffer];
commandBuffer.label = @"Present";
[commandBuffer presentDrawable:currentDrawable];
[commandBuffer commit];
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_disposeDevice(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
MetalDevice *device = (MetalDevice *) devicePtr;
[device.layer removeFromSuperlayer];
env->DeleteGlobalRef(device.layer.javaRef);
[device.layer release];
[device release];
}
} // extern C
#endif
\ No newline at end of file
skiko/src/jvmMain/objectiveC/macos/
redrawer.
m
→
skiko/src/jvmMain/objectiveC/macos/
OpenGLRedrawer.m
m
View file @
3158b8d7
...
...
@@ -36,13 +36,13 @@ JavaVM *jvm = NULL;
{
assert(jvm != NULL);
JNIEnv *env;
(
*
jvm
)
->
AttachCurrentThread
(
jvm
,
(
void
**
)
&
env
,
NULL
);
jvm->AttachCurrentThread(
(void **)&env, NULL);
static jclass cls = NULL;
static jmethodID method = NULL;
if
(
!
cls
)
cls
=
(
*
env
)
->
GetObjectClass
(
env
,
self
.
javaRef
);
if
(
!
method
)
method
=
(
*
env
)
->
GetMethodID
(
env
,
cls
,
"canDraw"
,
"()Z"
);
return
(
*
env
)
->
CallBooleanMethod
(
env
,
self
.
javaRef
,
method
);
if (!cls) cls =
env->GetObjectClass(
self.javaRef);
if (!method) method =
env->GetMethodID(
cls, "canDraw", "()Z");
return
env->CallBooleanMethod(
self.javaRef, method);
}
-(void)drawInCGLContext:(CGLContextObj)ctx
...
...
@@ -54,22 +54,25 @@ JavaVM *jvm = NULL;
assert(jvm != NULL);
JNIEnv *env;
(
*
jvm
)
->
AttachCurrentThread
(
jvm
,
(
void
**
)
&
env
,
NULL
);
jvm->AttachCurrentThread(
(void **)&env, NULL);
static jclass cls = NULL;
static jmethodID method = NULL;
if
(
!
cls
)
cls
=
(
*
env
)
->
GetObjectClass
(
env
,
self
.
javaRef
);
if
(
!
method
)
method
=
(
*
env
)
->
GetMethodID
(
env
,
cls
,
"performDraw"
,
"()V"
);
(
*
env
)
->
CallVoidMethod
(
env
,
self
.
javaRef
,
method
);
if (!cls) cls =
env->GetObjectClass(
self.javaRef);
if (!method) method =
env->GetMethodID(
cls, "performDraw", "()V");
env->CallVoidMethod(
self.javaRef, method);
[super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts];
}
@end
extern "C"
{
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_initContainer(JNIEnv *env, jobject redrawer, jlong platformInfoPtr)
{
(
*
env
)
->
GetJavaVM
(
env
,
&
jvm
);
env->GetJavaVM(
&jvm);
NSObject<JAWT_SurfaceLayers>* dsi_mac = (__bridge NSObject<JAWT_SurfaceLayers> *) platformInfoPtr;
...
...
@@ -93,7 +96,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_
CALayer *container = (CALayer *) containerPtr;
AWTGLLayer *glLayer = [AWTGLLayer new];
glLayer
.
javaRef
=
(
*
env
)
->
NewGlobalRef
(
env
,
layer
);
glLayer.javaRef =
env->NewGlobalRef(
layer);
[glLayer setNeedsDisplayOnBoundsChange: setNeedsDisplayOnBoundsChange];
[container addSublayer: glLayer];
...
...
@@ -104,7 +107,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_d
{
AWTGLLayer *glLayer = (AWTGLLayer *) ptr;
[glLayer removeFromSuperlayer];
(
*
env
)
->
DeleteGlobalRef
(
env
,
glLayer
.
javaRef
);
env->DeleteGlobalRef(
glLayer.javaRef);
[glLayer release];
}
...
...
@@ -138,4 +141,6 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AWTGLLayer_setFrame(JNI
forKey:kCATransactionDisableActions]; // disable animations
glLayer.frame = CGRectMake(x, y, width, height);
[CATransaction commit];
}
\ No newline at end of file
}
} // extern C
\ No newline at end of file
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