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
50223f6b
Unverified
Commit
50223f6b
authored
Feb 03, 2021
by
Igor Demin
Committed by
GitHub
Feb 03, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #61 from JetBrains/fps-rewrite
Rewrite FPS counting
parents
dc374a75
676bf9ef
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
91 additions
and
43 deletions
+91
-43
SkijaInjectSample (show long frames) .run.xml
.run/SkijaInjectSample (show long frames) .run.xml
+25
-0
FPSCounter.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/FPSCounter.kt
+43
-27
SkiaLayer.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+11
-11
SkikoProperties.kt
...src/jvmMain/kotlin/org/jetbrains/skiko/SkikoProperties.kt
+12
-5
No files found.
.run/SkijaInjectSample (show long frames) .run.xml
0 → 100644
View file @
50223f6b
<component
name=
"ProjectRunConfigurationManager"
>
<configuration
default=
"false"
name=
"SkijaInjectSample (show long frames) "
type=
"GradleRunConfiguration"
factoryName=
"Gradle"
>
<ExternalSystemSettings>
<option
name=
"executionName"
/>
<option
name=
"externalProjectPath"
value=
"$PROJECT_DIR$/samples/SkijaInjectSample"
/>
<option
name=
"externalSystemIdString"
value=
"GRADLE"
/>
<option
name=
"scriptParameters"
value=
"-Dskiko.fps.longFrames.show=true"
/>
<option
name=
"taskDescriptions"
>
<list
/>
</option>
<option
name=
"taskNames"
>
<list>
<option
value=
"run"
/>
</list>
</option>
<option
name=
"vmOptions"
value=
""
/>
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>
true
</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>
true
</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>
false
</DebugAllEnabled>
<method
v=
"2"
>
<option
name=
"Gradle.BeforeRunTask"
enabled=
"false"
tasks=
"publishToMavenLocal"
externalProjectPath=
"$PROJECT_DIR$/skiko"
vmOptions=
""
scriptParameters=
""
/>
</method>
</configuration>
</component>
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/FPSCounter.kt
View file @
50223f6b
package
org.jetbrains.skiko
import
java.
util.*
import
java.
awt.Component
import
kotlin.math.roundToInt
internal
class
FPSCounter
(
private
val
count
:
Int
,
private
val
probability
:
Double
private
val
periodSeconds
:
Double
,
private
val
showLongFrames
:
Boolean
,
private
val
getLongFrameMillis
:
()
->
Double
)
{
private
var
i
=
0
private
val
times
=
LinkedList
<
Double
>()
private
var
t1
=
System
.
nanoTime
()
/**
* [value] 0.0 - min, 1.0 - max, 0.5 - median
*/
private
fun
MutableList
<
Double
>.
quantile
(
value
:
Double
)
:
Double
{
val
index
=
(
value
*
(
size
-
1
)).
toInt
()
return
sorted
()[
index
]
}
private
val
times
=
mutableListOf
<
Long
>()
private
var
lastLogTime
=
System
.
nanoTime
()
private
var
lastTime
=
System
.
nanoTime
()
fun
tick
()
{
val
t2
=
System
.
nanoTime
()
val
frameTime
=
(
t2
-
t1
)
/
1
E6
t1
=
t2
val
time
=
System
.
nanoTime
()
val
timestamp
=
time
.
nanosToMillis
().
toLong
()
val
frameTime
=
time
-
lastTime
lastTime
=
time
i
++
times
.
add
(
frameTime
)
if
(
times
.
size
>
count
)
{
times
.
removeFirst
(
)
if
(
showLongFrames
&&
frameTime
>
getLongFrameMillis
().
millisToNanos
()
)
{
println
(
"[%d] Long frame %.2f ms"
.
format
(
timestamp
,
frameTime
.
nanosToMillis
())
)
}
if
(
i
%
count
==
0
)
{
val
quantile
=
(
1
-
probability
)
/
2.0
val
average
=
(
1000.0
/
times
.
average
()
).
roundToInt
()
val
m
in
=
(
1000.0
/
times
.
quantile
(
1
-
quantile
)
).
roundToInt
()
val
max
=
(
1000.0
/
times
.
quantile
(
quantile
)).
roundToInt
(
)
val
probability
=
(
100
*
probability
).
roundToInt
()
println
(
"FPS $average ($min-$max $probability%)"
)
if
(
(
time
-
lastLogTime
)
>
periodSeconds
.
secondsToNanos
()
)
{
val
average
=
(
nanosPerSecond
/
times
.
average
()).
roundToInt
()
val
min
=
(
nanosPerSecond
/
times
.
max
()
!!
).
roundToInt
()
val
m
ax
=
(
nanosPerSecond
/
times
.
min
()
!!
).
roundToInt
()
println
(
"[$timestamp] FPS $average ($min-$max)"
)
times
.
clear
()
lastLogTime
=
time
}
}
private
val
nanosPerMillis
=
1
_000_000
.
0
private
val
nanosPerSecond
=
1
_000_000_000
.
0
private
fun
Long
.
nanosToMillis
():
Double
=
this
/
nanosPerMillis
private
fun
Double
.
millisToNanos
():
Long
=
(
this
*
nanosPerMillis
).
toLong
()
private
fun
Double
.
secondsToNanos
():
Long
=
(
this
*
nanosPerSecond
).
toLong
()
}
internal
fun
defaultFPSCounter
(
component
:
Component
):
FPSCounter
?
=
with
(
SkikoProperties
)
{
if
(!
SkikoProperties
.
fpsEnabled
)
return
@with
null
// it is slow on Linux (100ms), so we cache it. Also refreshRate available only after window is visible
val
refreshRate
by
lazy
{
component
.
graphicsConfiguration
.
device
.
displayMode
.
refreshRate
}
FPSCounter
(
periodSeconds
=
fpsPeriodSeconds
,
showLongFrames
=
fpsLongFramesShow
,
getLongFrameMillis
=
{
fpsLongFramesMillis
?:
1.5
*
1000
/
refreshRate
}
)
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
View file @
50223f6b
package
org.jetbrains.skiko
import
org.jetbrains.skija.*
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.RasterRedrawer
import
org.jetbrains.skiko.context.createContextHandler
import
org.jetbrains.skija.Canvas
import
org.jetbrains.skija.ClipMode
import
org.jetbrains.skija.Picture
import
org.jetbrains.skija.PictureRecorder
import
org.jetbrains.skija.Rect
import
org.jetbrains.skiko.context.SoftwareContextHandler
import
org.jetbrains.skiko.context.createContextHandler
import
org.jetbrains.skiko.redrawer.RasterRedrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
java.awt.Graphics
import
javax.swing.SwingUtilities.isEventDispatchThread
...
...
@@ -64,18 +68,14 @@ open class SkiaLayer : HardwareLayer() {
redrawer
?.
needRedraw
()
}
private
val
fpsCounter
=
FPSCounter
(
count
=
SkikoProperties
.
fpsCount
,
probability
=
SkikoProperties
.
fpsProbability
)
@Suppress
(
"LeakingThis"
)
private
val
fpsCounter
=
defaultFPSCounter
(
this
)
override
fun
update
(
nanoTime
:
Long
)
{
check
(!
isDisposed
)
check
(
isEventDispatchThread
())
if
(
SkikoProperties
.
fpsEnabled
)
{
fpsCounter
.
tick
()
}
fpsCounter
?.
tick
()
val
pictureWidth
=
(
width
*
contentScale
).
toInt
().
coerceAtLeast
(
0
)
val
pictureHeight
=
(
height
*
contentScale
).
toInt
().
coerceAtLeast
(
0
)
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkikoProperties.kt
View file @
50223f6b
...
...
@@ -5,8 +5,15 @@ internal object SkikoProperties {
val
vsyncEnabled
:
Boolean
by
property
(
"skiko.vsync.enabled"
,
default
=
true
)
val
fpsEnabled
:
Boolean
by
property
(
"skiko.fps.enabled"
,
default
=
false
)
val
fpsCount
:
Int
by
property
(
"skiko.fps.count"
,
default
=
300
)
val
fpsProbability
:
Double
by
property
(
"skiko.fps.probability"
,
default
=
0.97
)
val
fpsPeriodSeconds
:
Double
by
property
(
"skiko.fps.periodSeconds"
,
default
=
2.0
)
/**
* Show long frames which is longer than [fpsLongFramesMillis].
* If [fpsLongFramesMillis] isn't defined will show frames longer than 1.5 * (1000 / displayRefreshRate)
*/
val
fpsLongFramesShow
:
Boolean
by
property
(
"skiko.fps.longFrames.show"
,
default
=
false
)
val
fpsLongFramesMillis
:
Double
?
by
property
(
"skiko.fps.longFrames.millis"
,
default
=
null
)
val
renderApi
:
GraphicsApi
by
lazy
{
val
environment
=
System
.
getenv
(
"SKIKO_RENDER_API"
)
...
...
@@ -30,11 +37,11 @@ internal object SkikoProperties {
System
.
getProperty
(
name
)
?.
toBoolean
()
?:
default
}
private
fun
property
(
name
:
String
,
default
:
Int
)
=
lazy
{
System
.
getProperty
(
name
)
?.
to
Int
()
?:
default
private
fun
property
(
name
:
String
,
default
:
Double
)
=
lazy
{
System
.
getProperty
(
name
)
?.
to
Double
()
?:
default
}
private
fun
property
(
name
:
String
,
default
:
Double
)
=
lazy
{
private
fun
property
(
name
:
String
,
default
:
Double
?
)
=
lazy
{
System
.
getProperty
(
name
)
?.
toDouble
()
?:
default
}
}
\ 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