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
86aaf759
Commit
86aaf759
authored
Feb 20, 2021
by
Alexander Gorshenev
Committed by
alexander-gorshenev
Apr 28, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Native] Experimental skiko for kotlin/native available under -Pskiko.native.enabled=true.
parent
8ebf6920
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
888 additions
and
1 deletion
+888
-1
build.gradle.kts
samples/SkiaNativeSample/build.gradle.kts
+73
-0
gradle.properties
samples/SkiaNativeSample/gradle.properties
+2
-0
gradlew
samples/SkiaNativeSample/gradlew
+185
-0
settings.gradle.kts
samples/SkiaNativeSample/settings.gradle.kts
+12
-0
App.kt
...osX64Main/kotlin/org.jetbrains.skiko.sample.native/App.kt
+63
-0
build.gradle.kts
skiko/build.gradle.kts
+61
-1
properties.kt
skiko/buildSrc/src/main/kotlin/properties.kt
+4
-0
gradle.properties
skiko/gradle.properties
+1
-0
GraphicsApi.kt
...rc/macosX64Main/kotlin/org/jetbrains/skiko/GraphicsApi.kt
+6
-0
HardwareLayer.kt
.../macosX64Main/kotlin/org/jetbrains/skiko/HardwareLayer.kt
+47
-0
PlatformOperations.kt
...sX64Main/kotlin/org/jetbrains/skiko/PlatformOperations.kt
+18
-0
SkiaLayer.kt
.../src/macosX64Main/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+84
-0
SkiaLayerProperties.kt
...X64Main/kotlin/org/jetbrains/skiko/SkiaLayerProperties.kt
+5
-0
SkiaWindow.kt
...src/macosX64Main/kotlin/org/jetbrains/skiko/SkiaWindow.kt
+32
-0
SkikoProperties.kt
...acosX64Main/kotlin/org/jetbrains/skiko/SkikoProperties.kt
+20
-0
ContextHandler.kt
...Main/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
+51
-0
OpenGLContextHandler.kt
...otlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
+72
-0
MacOsOpenGLRedrawer.kt
...otlin/org/jetbrains/skiko/redrawer/MacOsOpenGLRedrawer.kt
+117
-0
Redrawer.kt
...osX64Main/kotlin/org/jetbrains/skiko/redrawer/Redrawer.kt
+9
-0
skia.def
skiko/src/nativeInterop/cinterop/skia.def
+26
-0
No files found.
samples/SkiaNativeSample/build.gradle.kts
0 → 100644
View file @
86aaf759
plugins
{
kotlin
(
"multiplatform"
)
version
"1.4.30"
}
repositories
{
mavenLocal
()
jcenter
()
maven
(
"https://dl.bintray.com/kotlin/kotlin-eap"
)
maven
(
"https://maven.pkg.jetbrains.space/public/p/compose/dev"
)
}
val
osName
=
System
.
getProperty
(
"os.name"
)
val
targetOs
=
when
{
osName
==
"Mac OS X"
->
"macos"
osName
.
startsWith
(
"Win"
)
->
"windows"
osName
.
startsWith
(
"Linux"
)
->
"linux"
else
->
error
(
"Unsupported OS: $osName"
)
}
val
osArch
=
System
.
getProperty
(
"os.arch"
)
var
targetArch
=
when
(
osArch
)
{
"x86_64"
,
"amd64"
->
"x64"
"aarch64"
->
"arm64"
else
->
error
(
"Unsupported arch: $osArch"
)
}
val
target
=
"${targetOs}-${targetArch}"
var
version
=
"0.0.0-SNAPSHOT"
if
(
project
.
hasProperty
(
"skiko.version"
))
{
version
=
project
.
properties
[
"skiko.version"
]
as
String
}
kotlin
{
val
nativeTarget
=
when
{
osName
==
"Mac OS X"
->
macosX64
()
osName
.
startsWith
(
"Win"
)
->
mingwX64
()
osName
.
startsWith
(
"Linux"
)
->
linuxX64
()
else
->
throw
GradleException
(
"Host OS is not supported in Kotlin/Native."
)
}
nativeTarget
.
apply
{
binaries
{
executable
{
entryPoint
=
"org.jetbrains.skiko.sample.native.main"
}
}
}
sourceSets
{
val
commonMain
by
getting
{
dependencies
{
implementation
(
kotlin
(
"stdlib-common"
))
}
}
val
nativeMain
by
creating
{
dependsOn
(
commonMain
)
dependencies
{
}
}
val
macosX64Main
by
getting
{
dependsOn
(
nativeMain
)
dependencies
{
implementation
(
"org.jetbrains.skiko:skiko-native-runtime-$target:$version"
)
implementation
(
"org.jetbrains.skiko:skiko-native-skia-interop-$target:$version"
)
}
}
}
}
samples/SkiaNativeSample/gradle.properties
0 → 100644
View file @
86aaf759
kotlin.code.style
=
official
kotlin.native.version
=
1.5.20-dev-5723
samples/SkiaNativeSample/gradlew
0 → 100755
View file @
86aaf759
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG
=
"
$0
"
# Need this for relative symlinks.
while
[
-h
"
$PRG
"
]
;
do
ls
=
`
ls
-ld
"
$PRG
"
`
link
=
`
expr
"
$ls
"
:
'.*-> \(.*\)$'
`
if
expr
"
$link
"
:
'/.*'
>
/dev/null
;
then
PRG
=
"
$link
"
else
PRG
=
`
dirname
"
$PRG
"
`
"/
$link
"
fi
done
SAVED
=
"
`
pwd
`
"
cd
"
`
dirname
\"
$PRG
\"
`
/"
>
/dev/null
APP_HOME
=
"
`
pwd
-P
`
"
cd
"
$SAVED
"
>
/dev/null
APP_NAME
=
"Gradle"
APP_BASE_NAME
=
`
basename
"
$0
"
`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS
=
'"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD
=
"maximum"
warn
()
{
echo
"
$*
"
}
die
()
{
echo
echo
"
$*
"
echo
exit
1
}
# OS specific support (must be 'true' or 'false').
cygwin
=
false
msys
=
false
darwin
=
false
nonstop
=
false
case
"
`
uname
`
"
in
CYGWIN
*
)
cygwin
=
true
;;
Darwin
*
)
darwin
=
true
;;
MINGW
*
)
msys
=
true
;;
NONSTOP
*
)
nonstop
=
true
;;
esac
CLASSPATH
=
$APP_HOME
/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if
[
-n
"
$JAVA_HOME
"
]
;
then
if
[
-x
"
$JAVA_HOME
/jre/sh/java"
]
;
then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD
=
"
$JAVA_HOME
/jre/sh/java"
else
JAVACMD
=
"
$JAVA_HOME
/bin/java"
fi
if
[
!
-x
"
$JAVACMD
"
]
;
then
die
"ERROR: JAVA_HOME is set to an invalid directory:
$JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD
=
"java"
which java
>
/dev/null 2>&1
||
die
"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if
[
"
$cygwin
"
=
"false"
-a
"
$darwin
"
=
"false"
-a
"
$nonstop
"
=
"false"
]
;
then
MAX_FD_LIMIT
=
`
ulimit
-H
-n
`
if
[
$?
-eq
0
]
;
then
if
[
"
$MAX_FD
"
=
"maximum"
-o
"
$MAX_FD
"
=
"max"
]
;
then
MAX_FD
=
"
$MAX_FD_LIMIT
"
fi
ulimit
-n
$MAX_FD
if
[
$?
-ne
0
]
;
then
warn
"Could not set maximum file descriptor limit:
$MAX_FD
"
fi
else
warn
"Could not query maximum file descriptor limit:
$MAX_FD_LIMIT
"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if
$darwin
;
then
GRADLE_OPTS
=
"
$GRADLE_OPTS
\"
-Xdock:name=
$APP_NAME
\"
\"
-Xdock:icon=
$APP_HOME
/media/gradle.icns
\"
"
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if
[
"
$cygwin
"
=
"true"
-o
"
$msys
"
=
"true"
]
;
then
APP_HOME
=
`
cygpath
--path
--mixed
"
$APP_HOME
"
`
CLASSPATH
=
`
cygpath
--path
--mixed
"
$CLASSPATH
"
`
JAVACMD
=
`
cygpath
--unix
"
$JAVACMD
"
`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW
=
`
find
-L
/
-maxdepth
1
-mindepth
1
-type
d 2>/dev/null
`
SEP
=
""
for
dir
in
$ROOTDIRSRAW
;
do
ROOTDIRS
=
"
$ROOTDIRS$SEP$dir
"
SEP
=
"|"
done
OURCYGPATTERN
=
"(^(
$ROOTDIRS
))"
# Add a user-defined pattern to the cygpath arguments
if
[
"
$GRADLE_CYGPATTERN
"
!=
""
]
;
then
OURCYGPATTERN
=
"
$OURCYGPATTERN
|(
$GRADLE_CYGPATTERN
)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i
=
0
for
arg
in
"
$@
"
;
do
CHECK
=
`
echo
"
$arg
"
|egrep
-c
"
$OURCYGPATTERN
"
-
`
CHECK2
=
`
echo
"
$arg
"
|egrep
-c
"^-"
`
### Determine if an option
if
[
$CHECK
-ne
0
]
&&
[
$CHECK2
-eq
0
]
;
then
### Added a condition
eval
`
echo
args
$i
`
=
`
cygpath
--path
--ignore
--mixed
"
$arg
"
`
else
eval
`
echo
args
$i
`
=
"
\"
$arg
\"
"
fi
i
=
`
expr
$i
+ 1
`
done
case
$i
in
0
)
set
--
;;
1
)
set
--
"
$args0
"
;;
2
)
set
--
"
$args0
"
"
$args1
"
;;
3
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
;;
4
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
;;
5
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
;;
6
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
;;
7
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
;;
8
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
"
$args7
"
;;
9
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
"
$args7
"
"
$args8
"
;;
esac
fi
# Escape application args
save
()
{
for
i
do
printf
%s
\\
n
"
$i
"
|
sed
"s/'/'
\\\\
''/g;1s/^/'/;
\$
s/
\$
/'
\\\\
/"
;
done
echo
" "
}
APP_ARGS
=
`
save
"
$@
"
`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set
--
$DEFAULT_JVM_OPTS
$JAVA_OPTS
$GRADLE_OPTS
"
\"
-Dorg.gradle.appname=
$APP_BASE_NAME
\"
"
-classpath
"
\"
$CLASSPATH
\"
"
org.gradle.wrapper.GradleWrapperMain
"
$APP_ARGS
"
exec
"
$JAVACMD
"
"
$@
"
samples/SkiaNativeSample/settings.gradle.kts
0 → 100644
View file @
86aaf759
pluginManagement
{
repositories
{
mavenCentral
()
gradlePluginPortal
()
maven
{
url
=
uri
(
"https://dl.bintray.com/kotlin/kotlin-eap"
)
}
}
}
rootProject
.
name
=
"SkiaNativeSample"
samples/SkiaNativeSample/src/macosX64Main/kotlin/org.jetbrains.skiko.sample.native/App.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.sample.native
import
platform.AppKit.*
import
org.jetbrains.skiko.skia.native.*
import
org.jetbrains.skiko.native.SkiaLayer
import
org.jetbrains.skiko.native.SkiaRenderer
import
org.jetbrains.skiko.native.SkiaWindow
import
kotlinx.cinterop.*
import
kotlin.math.cos
import
kotlin.math.sin
fun
main
(
args
:
Array
<
String
>)
{
NSApplication
.
sharedApplication
()
createWindow
(
"Skia/Native macos sample"
)
NSApp
?.
run
()
}
fun
createWindow
(
title
:
String
)
{
val
window
=
SkiaWindow
()
var
angle
=
0.0f
window
.
layer
.
renderer
=
Renderer
(
window
.
layer
)
{
renderer
,
w
,
h
,
nanoTime
->
displayScene
(
renderer
,
nanoTime
)
}
window
.
nsWindow
.
orderFrontRegardless
()
}
class
Renderer
(
val
layer
:
SkiaLayer
,
val
displayScene
:
(
Renderer
,
Int
,
Int
,
Long
)
->
Unit
):
SkiaRenderer
{
var
canvas
:
SkCanvas
?
=
null
override
fun
onRender
(
canvas
:
SkCanvas
,
width
:
Int
,
height
:
Int
,
nanoTime
:
Long
)
{
this
.
canvas
=
canvas
val
contentScale
=
layer
.
contentScale
canvas
.
scale
(
contentScale
,
contentScale
)
displayScene
(
this
,
(
width
/
contentScale
).
toInt
(),
(
height
/
contentScale
).
toInt
(),
nanoTime
)
layer
.
needRedraw
()
}
}
fun
displayScene
(
renderer
:
Renderer
,
nanoTime
:
Long
)
{
val
canvas
=
renderer
.
canvas
!!
val
paint
=
SkPaint
()
paint
.
setColor
(
SK_ColorGREEN
)
canvas
.
clear
(
SK_ColorRED
);
canvas
.
save
();
canvas
.
translate
(
128.0f
,
128.0f
)
canvas
.
rotate
(
nanoTime
.
toFloat
()
/
1
e7f
)
val
rect
=
SkRect
.
MakeXYWH
(-
90.5f
,
-
90.5f
,
181.0f
,
181.0f
)
canvas
.
drawRect
(
rect
,
paint
.
ptr
)
canvas
.
restore
();
// TODO: need memory management.
// nativeHeap.free(paint)
}
skiko/build.gradle.kts
View file @
86aaf759
...
@@ -2,9 +2,11 @@ import de.undercouch.gradle.tasks.download.Download
...
@@ -2,9 +2,11 @@ import de.undercouch.gradle.tasks.download.Download
import
org.gradle.crypto.checksum.Checksum
import
org.gradle.crypto.checksum.Checksum
import
org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import
org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import
org.jetbrains.kotlin.gradle.tasks.KotlinTest
import
org.jetbrains.kotlin.gradle.tasks.KotlinTest
import
org.jetbrains.kotlin.gradle.tasks.CInteropProcess
import
org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
plugins
{
plugins
{
kotlin
(
"multiplatform"
)
version
"1.
3.72
"
kotlin
(
"multiplatform"
)
version
"1.
4.30
"
`
cpp
-
library
`
`
cpp
-
library
`
`
maven
-
publish
`
`
maven
-
publish
`
id
(
"org.gradle.crypto.checksum"
)
version
"1.1.0"
id
(
"org.gradle.crypto.checksum"
)
version
"1.1.0"
...
@@ -146,6 +148,9 @@ val skijaSrcDir = run {
...
@@ -146,6 +148,9 @@ val skijaSrcDir = run {
}.
map
{
delombokSkijaSrcDir
}
}.
map
{
delombokSkijaSrcDir
}
}
}
val
Project
.
supportNative
:
Boolean
get
()
=
properties
.
get
(
"skiko.native.enabled"
)
==
"true"
kotlin
{
kotlin
{
jvm
{
jvm
{
compilations
.
all
{
compilations
.
all
{
...
@@ -154,6 +159,35 @@ kotlin {
...
@@ -154,6 +159,35 @@ kotlin {
withJava
()
withJava
()
}
}
if
(
supportNative
)
{
val
nativeTarget
=
when
(
target
)
{
"macos-x64"
->
macosX64
()
// "linux-x64" -> linuxX64()
// "windows-x64" -> mingwX64()
else
->
null
}
nativeTarget
?.
apply
{
compilations
.
getByName
(
"main"
)
{
val
skia
by
cinterops
.
creating
{
defFile
(
"src/nativeInterop/cinterop/skia.def"
)
val
skiaDir
=
skiaDir
.
get
().
absolutePath
val
kotlinNativeDataPath
=
System
.
getenv
(
"KONAN_DATA_DIR"
)
?.
let
{
File
(
it
)
}
?:
File
(
System
.
getProperty
(
"user.home"
)).
resolve
(
".konan"
)
compilerOpts
(
// TODO: Why do we need `include/c++/v1`?
"-I$kotlinNativeDataPath/dependencies/clang-llvm-apple-8.0.0-darwin-macos//include/c++/v1"
,
"-I$skiaDir"
)
extraOpts
(
"-staticLibrary"
,
"libskia.a"
)
extraOpts
(
"-libraryPath"
,
"$skiaDir/out/${buildType.id}-${targetArch.id}"
)
}
}
}
}
sourceSets
{
sourceSets
{
val
commonMain
by
getting
{
val
commonMain
by
getting
{
dependencies
{
dependencies
{
...
@@ -182,7 +216,16 @@ kotlin {
...
@@ -182,7 +216,16 @@ kotlin {
implementation
(
kotlin
(
"test-junit"
))
implementation
(
kotlin
(
"test-junit"
))
}
}
}
}
if
(
supportNative
)
{
val
macosX64Main
by
getting
{
}
}
}
}
}
tasks
.
withType
(
CInteropProcess
::
class
.
java
).
forEach
{
it
.
dependsOn
(
skiaDir
)
}
}
tasks
.
withType
(
JavaCompile
::
class
.
java
).
configureEach
{
tasks
.
withType
(
JavaCompile
::
class
.
java
).
configureEach
{
...
@@ -616,6 +659,23 @@ publishing {
...
@@ -616,6 +659,23 @@ publishing {
artifact
(
skikoJvmRuntimeJar
.
map
{
it
.
archiveFile
.
get
()
})
artifact
(
skikoJvmRuntimeJar
.
map
{
it
.
archiveFile
.
get
()
})
}
}
}
}
if
(
supportNative
)
{
create
<
MavenPublication
>(
"skikoNativeSkiaInterop"
)
{
artifactId
=
SkikoArtifacts
.
nativeSkiaInteropArtifactIdFor
(
targetOs
,
targetArch
)
afterEvaluate
{
artifact
(
project
.
tasks
.
withType
(
CInteropProcess
::
class
.
java
).
single
().
outputs
.
getFiles
().
single
())
}
}
create
<
MavenPublication
>(
"skikoNativeRuntime"
)
{
artifactId
=
SkikoArtifacts
.
nativeRuntimeArtifactIdFor
(
targetOs
,
targetArch
)
afterEvaluate
{
artifact
(
project
.
tasks
.
withType
(
KotlinNativeCompile
::
class
.
java
)
.
single
{
it
.
name
.
startsWith
(
"compileKotlin"
)
}
// Exclude compileTestKotlin.
.
outputs
.
getFiles
().
single
{
it
.
name
.
endsWith
(
".klib"
)
}
)
}
}
}
}
}
}
}
...
...
skiko/buildSrc/src/main/kotlin/properties.kt
View file @
86aaf759
...
@@ -135,4 +135,8 @@ object SkikoArtifacts {
...
@@ -135,4 +135,8 @@ object SkikoArtifacts {
val
commonArtifactId
=
"skiko-jvm"
val
commonArtifactId
=
"skiko-jvm"
fun
runtimeArtifactIdFor
(
os
:
OS
,
arch
:
Arch
)
=
fun
runtimeArtifactIdFor
(
os
:
OS
,
arch
:
Arch
)
=
"skiko-jvm-runtime-${targetId(os, arch)}"
"skiko-jvm-runtime-${targetId(os, arch)}"
fun
nativeRuntimeArtifactIdFor
(
os
:
OS
,
arch
:
Arch
)
=
"skiko-native-runtime-${targetId(os, arch)}"
fun
nativeSkiaInteropArtifactIdFor
(
os
:
OS
,
arch
:
Arch
)
=
"skiko-native-skia-interop-${targetId(os, arch)}"
}
}
\ No newline at end of file
skiko/gradle.properties
View file @
86aaf759
kotlin.code.style
=
official
kotlin.code.style
=
official
deploy.version
=
0.0.0
deploy.version
=
0.0.0
kotlin.native.version
=
1.5.20-dev-5723
dependencies.skija.git.commit
=
a5d6dfd746b8a8ec2ef52ebea4baa53f299d080c
dependencies.skija.git.commit
=
a5d6dfd746b8a8ec2ef52ebea4baa53f299d080c
dependencies.skia.windows-x64
=
m90-d9182fe437/Skia-m90-d9182fe437-windows-Release-x64
dependencies.skia.windows-x64
=
m90-d9182fe437/Skia-m90-d9182fe437-windows-Release-x64
...
...
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/GraphicsApi.kt
0 → 100644
View file @
86aaf759
// TODO: Commonize! This is a complete copy of jvm counterpart.
package
org.jetbrains.skiko.native
enum
class
GraphicsApi
{
UNKNOWN
,
SOFTWARE
,
OPENGL
,
DIRECT3D
,
VULKAN
,
METAL
}
\ No newline at end of file
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/HardwareLayer.kt
0 → 100755
View file @
86aaf759
package
org.jetbrains.skiko.native
import
kotlinx.cinterop.readValue
import
platform.Cocoa.*
import
platform.AppKit.*
import
platform.Foundation.*
import
platform.CoreGraphics.*
abstract
class
HardwareLayer
{
val
nsView
=
NSView
(
NSMakeRect
(
0.0
,
0.0
,
640.0
,
480.0
))
// getDpiScale is expensive operation on some platforms, so we cache it
private
var
_contentScale
:
Float
?
=
null
private
var
isInit
=
false
fun
checkIsShowing
()
{
if
(!
isInit
&&
!
nsView
.
hiddenOrHasHiddenAncestor
)
{
// _contentScale = getDpiScale()
_contentScale
=
1.0f
// TODO: what's the proper way here?
init
()
isInit
=
true
}
}
open
fun
init
()
{
}
protected
open
fun
nativeInit
(
platformInfo
:
Long
)
{
}
open
fun
dispose
()
{
}
protected
open
fun
contentScaleChanged
()
=
Unit
private
fun
checkContentScale
()
{
}
internal
abstract
fun
update
(
nanoTime
:
Long
)
internal
abstract
fun
draw
()
val
contentScale
:
Float
get
()
=
_contentScale
!!
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/PlatformOperations.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native
import
org.jetbrains.skiko.native.*
import
org.jetbrains.skiko.native.SkikoProperties.renderApi
import
org.jetbrains.skiko.native.redrawer.*
internal
interface
PlatformOperations
{
fun
createRedrawer
(
layer
:
HardwareLayer
,
properties
:
SkiaLayerProperties
):
Redrawer
}
internal
val
platformOperations
:
PlatformOperations
by
lazy
{
object
:
PlatformOperations
{
override
fun
createRedrawer
(
layer
:
HardwareLayer
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
OPENGL
->
MacOsOpenGLRedrawer
(
layer
,
properties
)
else
->
error
(
"No software rendering for native yet"
)
}
}
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/SkiaLayer.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native
import
kotlinx.cinterop.pointed
import
kotlinx.cinterop.useContents
import
org.jetbrains.skiko.native.context.*
import
org.jetbrains.skiko.native.redrawer.*
import
org.jetbrains.skiko.skia.native.*
interface
SkiaRenderer
{
fun
onRender
(
canvas
:
SkCanvas
,
width
:
Int
,
height
:
Int
,
nanoTime
:
Long
)
}
// TODO: this is exact copy of jvm counterpart. Commonize!
private
class
PictureHolder
(
val
instance
:
SkPicture
,
val
width
:
Int
,
val
height
:
Int
)
open
class
SkiaLayer
(
private
val
properties
:
SkiaLayerProperties
=
SkiaLayerProperties
()
)
:
HardwareLayer
()
{
var
renderer
:
SkiaRenderer
?
=
null
internal
var
skiaState
=
createContextHandler
(
this
)
private
var
isDisposed
=
false
private
var
redrawer
:
Redrawer
?
=
null
private
var
picture
:
PictureHolder
?
=
null
private
val
pictureRecorder
=
SkPictureRecorder
()
private
val
pictureLock
=
Any
()
override
fun
init
()
{
println
(
"SkiaLayer::init"
)
super
.
init
()
redrawer
=
platformOperations
.
createRedrawer
(
this
,
properties
)
redrawer
?.
redrawImmediately
()
}
override
fun
dispose
()
{
redrawer
?.
dispose
()
super
.
dispose
()
}
fun
needRedraw
()
{
redrawer
?.
needRedraw
()
}
override
fun
update
(
nanoTime
:
Long
)
{
println
(
"SkiaLayer::update"
)
val
width
=
nsView
.
frame
.
useContents
{
size
.
width
}
val
height
=
nsView
.
frame
.
useContents
{
size
.
height
}
val
pictureWidth
=
(
width
*
contentScale
).
coerceAtLeast
(
0.0
)
val
pictureHeight
=
(
height
*
contentScale
).
coerceAtLeast
(
0.0
)
val
bounds
=
SkRect
.
MakeWH
(
pictureWidth
.
toFloat
(),
pictureHeight
.
toFloat
())
val
canvas
=
pictureRecorder
.
beginRecording
(
bounds
,
null
)
!!
// TODO: get rid of .pointed?
renderer
?.
onRender
(
canvas
.
pointed
,
pictureWidth
.
toInt
(),
pictureHeight
.
toInt
(),
nanoTime
)
val
picture
=
pictureRecorder
.
finishRecordingAsPicture
()
!!
this
.
picture
=
PictureHolder
(
picture
,
pictureWidth
.
toInt
(),
pictureHeight
.
toInt
())
}
override
fun
draw
()
{
println
(
"SkiaLayer::draw"
)
skiaState
.
apply
{
if
(!
initContext
())
{
error
(
"initContext() failure. No fallback to raster for Skia/native yet."
)
return
}
initCanvas
()
clearCanvas
()
val
picture
=
picture
println
(
"SkiaLayer::draw: picture=$picture"
)
if
(
picture
!=
null
)
{
drawOnCanvas
(
picture
.
instance
)
}
flush
()
}
}
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/SkiaLayerProperties.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native
class
SkiaLayerProperties
(
val
isVsyncEnabled
:
Boolean
=
SkikoProperties
.
vsyncEnabled
)
\ No newline at end of file
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/SkiaWindow.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native
import
platform.AppKit.*
import
platform.Cocoa.*
import
platform.Foundation.*
open
class
SkiaWindow
(
properties
:
SkiaLayerProperties
=
SkiaLayerProperties
()
)
{
val
windowStyle
=
NSWindowStyleMaskTitled
or
NSWindowStyleMaskMiniaturizable
or
NSWindowStyleMaskClosable
or
NSWindowStyleMaskResizable
// TODO: what's the proper way to create window here?
// Should we subclass NSWindow?
// Provide multiple constructors for SkiaWindow?
// Behave similar to Skiko/JVM?
val
nsWindow
=
NSWindow
(
contentRect
=
NSMakeRect
(
0.0
,
0.0
,
640.0
,
480.0
),
styleMask
=
windowStyle
,
backing
=
NSBackingStoreBuffered
,
defer
=
true
)
val
layer
=
SkiaLayer
(
properties
)
init
{
nsWindow
.
contentView
?.
addSubview
(
layer
.
nsView
)
layer
.
checkIsShowing
()
// TODO: The awt versions has hierarchy listener. What should we use here?
}
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/SkikoProperties.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native
// TODO: jvm version uses java properties here.
// there is no properties support available for native.
internal
object
SkikoProperties
{
val
vsyncEnabled
:
Boolean
=
true
val
renderApi
:
GraphicsApi
by
lazy
{
GraphicsApi
.
OPENGL
}
private
fun
parseRenderApi
(
text
:
String
?):
GraphicsApi
{
when
(
text
)
{
"SOFTWARE"
->
return
GraphicsApi
.
SOFTWARE
"OPENGL"
->
return
GraphicsApi
.
OPENGL
else
->
return
GraphicsApi
.
OPENGL
}
}
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native.context
import
kotlinx.cinterop.ptr
import
org.jetbrains.skiko.skia.native.*
import
org.jetbrains.skiko.native.*
internal
fun
createContextHandler
(
layer
:
HardwareLayer
):
ContextHandler
{
return
OpenGLContextHandler
(
layer
)
//return when (SkikoProperties.renderApi) {
// GraphicsApi.SOFTWARE -> SoftwareContextHandler(layer)
// GraphicsApi.OPENGL -> OpenGLContextHandler(layer)
// else -> TODO("Unsupported yet")
//}
}
internal
abstract
class
ContextHandler
(
val
layer
:
HardwareLayer
)
{
// TODO: hostOs is all written in jdk kotlin.
// open val bleachConstant = if (hostOs == OS.MacOS) 0 else -1
open
val
bleachConstant
=
0
U
var
context
:
GrDirectContext
?
=
null
var
renderTarget
:
GrBackendRenderTarget
?
=
null
var
surface
:
SkSurface
?
=
null
var
canvas
:
SkCanvas
?
=
null
abstract
fun
initContext
():
Boolean
abstract
fun
initCanvas
()
fun
clearCanvas
()
{
println
(
"ContextHandler::clearCanvas"
)
canvas
?.
clear
(
bleachConstant
)
}
open
fun
drawOnCanvas
(
picture
:
SkPicture
)
{
println
(
"ContextHandler::drawOnCanvas"
)
canvas
?.
drawPicture
(
picture
.
ptr
)
}
open
fun
flush
()
{
println
(
"ContextHandler::flush"
)
context
?.
flush
()
}
fun
dispose
()
{
println
(
"Need to free surface"
)
println
(
"Need to free renderTarget"
)
// surface?.close()
// renderTarget?.close()
}
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native.context
import
kotlinx.cinterop.*
import
org.jetbrains.skiko.skia.native.*
import
org.jetbrains.skiko.native.*
import
platform.OpenGL.GL_DRAW_FRAMEBUFFER_BINDING
import
platform.OpenGL.GL_RGBA8
import
platform.OpenGL.glGetIntegerv
import
platform.OpenGL.*
import
platform.OpenGLCommon.GLenum
internal
class
OpenGLContextHandler
(
layer
:
HardwareLayer
)
:
ContextHandler
(
layer
)
{
override
fun
initContext
():
Boolean
{
println
(
"OpenGLContextHandler::initContext"
)
try
{
if
(
context
==
null
)
{
context
=
GrDirectContext
.
MakeGL
()
}
}
catch
(
e
:
Exception
)
{
println
(
"Failed to create Skia OpenGL context!"
)
return
false
}
return
true
}
@ExperimentalUnsignedTypes
private
fun
openglGetIntegerv
(
pname
:
GLenum
):
UInt
{
var
result
:
UInt
=
0
U
memScoped
{
val
data
=
alloc
<
IntVar
>()
glGetIntegerv
(
pname
,
data
.
ptr
);
result
=
data
.
value
.
toUInt
();
}
return
result
}
@ExperimentalUnsignedTypes
override
fun
initCanvas
()
{
println
(
"OpenGLContextHandler::initCanvas"
)
dispose
()
val
scale
=
layer
.
contentScale
val
w
=
(
layer
.
nsView
.
frame
.
useContents
{
size
.
width
}
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
(
layer
.
nsView
.
frame
.
useContents
{
size
.
height
}
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
fbId
=
openglGetIntegerv
(
GL_DRAW_FRAMEBUFFER_BINDING
.
toUInt
())
// TODO: Skia C++ interop: glInfo is a `struct`, not `class`,
// so we fallback to C interop here.
memScoped
{
val
glInfo
:
GrGLFramebufferInfo
=
alloc
<
GrGLFramebufferInfo
>()
glInfo
.
fFBOID
=
fbId
glInfo
.
fFormat
=
GL_RGBA8
.
toUInt
()
renderTarget
=
GrBackendRenderTarget
(
w
,
h
,
0
,
8
,
glInfo
.
readValue
())
}
surface
=
SkSurface
.
MakeFromBackendRenderTarget
(
// TODO: C++ interop knows nothing about inheritance.
context
!!
.
ptr
.
reinterpret
<
GrRecordingContext
>(),
renderTarget
!!
.
ptr
,
GrSurfaceOrigin
.
kBottomLeft_GrSurfaceOrigin
,
colorType
=
kRGBA_8888_SkColorType
,
colorSpace
=
SkColorSpace
.
MakeSRGB
(),
surfaceProps
=
null
,
releaseProc
=
null
,
releaseContext
=
null
)
?:
error
(
"Could not obtain SkSurface"
)
canvas
=
surface
!!
.
getCanvas
()
?.
pointed
?:
error
(
"Could not obtain SkCanvas from SkSurface"
)
}
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/redrawer/MacOsOpenGLRedrawer.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native.redrawer
import
kotlinx.cinterop.CPointer
import
kotlinx.cinterop.useContents
import
org.jetbrains.skiko.native.*
import
platform.CoreFoundation.CFTimeInterval
import
platform.CoreGraphics.CGRectMake
import
platform.CoreVideo.CVTimeStamp
import
platform.OpenGLCommon.CGLContextObj
import
platform.OpenGLCommon.CGLPixelFormatObj
import
platform.OpenGLCommon.CGLSetCurrentContext
import
platform.QuartzCore.CAOpenGLLayer
import
platform.QuartzCore.*
import
kotlin.system.getTimeNanos
internal
class
MacOsOpenGLRedrawer
(
private
val
layer
:
HardwareLayer
,
private
val
properties
:
SkiaLayerProperties
)
:
Redrawer
{
private
var
isDisposed
=
false
private
val
drawLayer
=
MacosGLLayer
(
layer
,
setNeedsDisplayOnBoundsChange
=
true
)
override
fun
dispose
()
{
drawLayer
.
dispose
()
}
override
fun
syncSize
()
{
// TODO: What do we really do here?
layer
.
nsView
.
frame
.
useContents
{
drawLayer
.
setFrame
(
origin
.
x
.
toInt
(),
origin
.
y
.
toInt
(),
size
.
width
.
toInt
().
coerceAtLeast
(
0
),
size
.
height
.
toInt
().
coerceAtLeast
(
0
)
)
}
}
override
fun
needRedraw
()
{
}
override
fun
redrawImmediately
()
{
layer
.
update
(
getTimeNanos
())
}
}
class
MacosGLLayer
(
val
layer
:
HardwareLayer
,
setNeedsDisplayOnBoundsChange
:
Boolean
)
:
CAOpenGLLayer
()
{
val
container
=
layer
.
nsView
init
{
this
.
setNeedsDisplayOnBoundsChange
(
setNeedsDisplayOnBoundsChange
)
this
.
removeAllAnimations
()
this
.
setAutoresizingMask
(
kCALayerWidthSizable
or
kCALayerHeightSizable
)
container
.
layer
=
this
container
.
wantsLayer
=
true
}
fun
draw
()
{
println
(
"MacosGLLayer::draw"
)
layer
.
update
(
getTimeNanos
())
layer
.
draw
()
}
fun
setFrame
(
x
:
Int
,
y
:
Int
,
width
:
Int
,
height
:
Int
)
{
val
newY
=
container
.
frame
.
useContents
{
size
.
height
}
-
y
-
height
CATransaction
.
begin
()
CATransaction
.
setDisableActions
(
true
)
this
.
frame
=
CGRectMake
(
x
.
toDouble
(),
newY
,
width
.
toDouble
(),
height
.
toDouble
())
CATransaction
.
commit
()
}
fun
dispose
()
{
this
.
removeFromSuperlayer
()
// TODO: anything else to dispose the layer?
}
protected
open
fun
canDraw
()
=
true
@Suppress
(
"unused"
)
private
fun
performDraw
()
{
try
{
draw
()
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
}
//display.finish()
}
override
fun
canDrawInCGLContext
(
ctx
:
CGLContextObj
?,
pixelFormat
:
CGLPixelFormatObj
?,
forLayerTime
:
CFTimeInterval
,
displayTime
:
CPointer
<
CVTimeStamp
>?
):
Boolean
{
return
canDraw
()
}
override
fun
drawInCGLContext
(
ctx
:
CGLContextObj
?,
pixelFormat
:
CGLPixelFormatObj
?,
forLayerTime
:
CFTimeInterval
,
displayTime
:
CPointer
<
CVTimeStamp
>?
)
{
CGLSetCurrentContext
(
ctx
);
println
(
"MacosGLLayer::drawInCGLContext"
)
performDraw
()
//context.flush() // TODO: I thought the below should call context.flush().
super
.
drawInCGLContext
(
ctx
,
pixelFormat
,
forLayerTime
,
displayTime
)
}
}
skiko/src/macosX64Main/kotlin/org/jetbrains/skiko/redrawer/Redrawer.kt
0 → 100644
View file @
86aaf759
package
org.jetbrains.skiko.native.redrawer
// TODO: this is exact copy of jvm counterpart. Commonize!
interface
Redrawer
{
fun
dispose
()
fun
needRedraw
()
fun
redrawImmediately
()
fun
syncSize
()
=
Unit
}
\ No newline at end of file
skiko/src/nativeInterop/cinterop/skia.def
0 → 100644
View file @
86aaf759
package
=
org
.
jetbrains
.
skiko
.
skia
.
native
language
=
C
++
plugin
=
org
.
jetbrains
.
kotlin
.
native
.
cinterop
.
plugin
.
skia
compilerOpts
.
osx
=
-
x
c
++
-
std
=
c
++
14
\
-
DSK_GL
\
-
DSK_SUPPORT_GPU
=
1
\
-
DSK_SHAPER_CORETEXT_AVAILABLE
\
-
DSK_BUILD_FOR_MAC
\
-
DSK_METAL
\
-
DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS
=
1
\
-
DSK_FORCE_DISTANCE_FIELD_TEXT
=
0
\
-
DSK_GAMMA_APPLY_TO_A8
\
-
DSK_GAMMA_SRGB
\
-
DSK_SCALAR_TO_FLOAT_EXCLUDED
\
-
DSK_SHAPER_HARFBUZZ_AVAILABLE
\
-
DSK_SUPPORT_OPENCL
=
0
\
-
DSK_UNICODE_AVAILABLE
headers
=
include
/
core
/
SkCanvas
.
h
include
/
core
/
SkData
.
h
include
/
core
/
SkImage
.
h
include
/
core
/
SkMath
.
h
include
/
core
/
SkStream
.
h
include
/
core
/
SkSurface
.
h
include
/
core
/
SkSurfaceProps
.
h
include
/
core
/
SkTypes
.
h
include
/
core
/
SkPaint
.
h
include
/
core
/
SkPictureRecorder
.
h
include
/
core
/
SkImageInfo
.
h
include
/
core
/
SkColor
.
h
include
/
core
/
SkColorSpace
.
h
include
/
gpu
/
GrDirectContext
.
h
include
/
gpu
/
GrBackendSurface
.
h
include
/
gpu
/
GrConfig
.
h
include
/
gpu
/
gl
/
GrGLInterface
.
h
headerFilter
=
include
/
core
/
SkCanvas
.
h
include
/
core
/
SkData
.
h
include
/
core
/
SkImage
.
h
include
/
core
/
SkMath
.
h
include
/
core
/
SkStream
.
h
include
/
core
/
SkSurface
.
h
include
/
core
/
SkSurfaceProps
.
h
include
/
core
/
SkTypes
.
h
include
/
core
/
SkPaint
.
h
include
/
core
/
SkPictureRecorder
.
h
include
/
core
/
SkImageInfo
.
h
include
/
core
/
SkColor
.
h
include
/
core
/
SkColorSpace
.
h
include
/
gpu
/
GrDirectContext
.
h
include
/
gpu
/
GrBackendSurface
.
h
include
/
gpu
/
GrConfig
.
h
include
/
gpu
/
gl
/
GrGLInterface
.
h
#
const
overloads
are
not
supported
yet
excludedFunctions
=
saveLayer
mapRect
ptr
priv
linkerOpts
.
osx
=
-
framework
CoreServices
-
framework
CoreText
-
framework
CoreGraphics
-
framework
Metal
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