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
6ad0a4e6
Unverified
Commit
6ad0a4e6
authored
Feb 01, 2021
by
Roman Sedaikin
Committed by
GitHub
Feb 01, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #56 from JetBrains/raster
Raster
parents
58d59a86
09742091
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
308 additions
and
81 deletions
+308
-81
SkiaPanel.kt
...jectSample/src/main/kotlin/SkijaInjectSample/SkiaPanel.kt
+1
-0
GraphicsApi.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/GraphicsApi.kt
+1
-1
PlatformOperations.kt
.../jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
+16
-4
SkiaLayer.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+19
-76
ContextHandler.kt
...Main/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
+66
-0
MetalContextHandler.kt
...kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
+44
-0
OpenGLContextHandler.kt
...otlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
+55
-0
SoftwareContextHandler.kt
...lin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
+82
-0
RasterRedrawer.kt
...ain/kotlin/org/jetbrains/skiko/redrawer/RasterRedrawer.kt
+24
-0
No files found.
samples/SkijaInjectSample/src/main/kotlin/SkijaInjectSample/SkiaPanel.kt
View file @
6ad0a4e6
...
@@ -33,6 +33,7 @@ open class SkiaPanel: JLayeredPane {
...
@@ -33,6 +33,7 @@ open class SkiaPanel: JLayeredPane {
}
}
override
fun
removeNotify
()
{
override
fun
removeNotify
()
{
layer
.
dispose
()
super
.
removeNotify
()
super
.
removeNotify
()
}
}
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/GraphicsApi.kt
View file @
6ad0a4e6
package
org.jetbrains.skiko
package
org.jetbrains.skiko
enum
class
GraphicsApi
{
enum
class
GraphicsApi
{
UNKNOWN
,
OPENGL
,
VULKAN
,
METAL
UNKNOWN
,
SOFTWARE
,
OPENGL
,
DIRECT3D
,
VULKAN
,
METAL
}
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
View file @
6ad0a4e6
package
org.jetbrains.skiko
package
org.jetbrains.skiko
import
org.jetbrains.skiko.GraphicsApi
import
org.jetbrains.skiko.context.renderApi
import
org.jetbrains.skiko.redrawer.LinuxRedrawer
import
org.jetbrains.skiko.redrawer.LinuxRedrawer
import
org.jetbrains.skiko.redrawer.MacOsRedrawer
import
org.jetbrains.skiko.redrawer.MacOsRedrawer
import
org.jetbrains.skiko.redrawer.RasterRedrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.WindowsRedrawer
import
org.jetbrains.skiko.redrawer.WindowsRedrawer
import
java.awt.Component
import
java.awt.Component
...
@@ -12,7 +15,7 @@ internal interface PlatformOperations {
...
@@ -12,7 +15,7 @@ internal interface PlatformOperations {
fun
isFullscreen
(
component
:
Component
):
Boolean
fun
isFullscreen
(
component
:
Component
):
Boolean
fun
setFullscreen
(
component
:
Component
,
value
:
Boolean
)
fun
setFullscreen
(
component
:
Component
,
value
:
Boolean
)
fun
getDpiScale
(
component
:
Component
):
Float
fun
getDpiScale
(
component
:
Component
):
Float
fun
create
Hardware
Redrawer
(
layer
:
HardwareLayer
):
Redrawer
fun
createRedrawer
(
layer
:
HardwareLayer
):
Redrawer
}
}
internal
val
platformOperations
:
PlatformOperations
by
lazy
{
internal
val
platformOperations
:
PlatformOperations
by
lazy
{
...
@@ -30,7 +33,10 @@ internal val platformOperations: PlatformOperations by lazy {
...
@@ -30,7 +33,10 @@ internal val platformOperations: PlatformOperations by lazy {
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
MacOsRedrawer
(
layer
)
override
fun
createRedrawer
(
layer
:
HardwareLayer
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
RasterRedrawer
(
layer
)
else
->
MacOsRedrawer
(
layer
)
}
}
}
OS
.
Windows
->
{
OS
.
Windows
->
{
object
:
PlatformOperations
{
object
:
PlatformOperations
{
...
@@ -50,7 +56,10 @@ internal val platformOperations: PlatformOperations by lazy {
...
@@ -50,7 +56,10 @@ internal val platformOperations: PlatformOperations by lazy {
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
WindowsRedrawer
(
layer
)
override
fun
createRedrawer
(
layer
:
HardwareLayer
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
RasterRedrawer
(
layer
)
else
->
WindowsRedrawer
(
layer
)
}
}
}
}
}
OS
.
Linux
->
{
OS
.
Linux
->
{
...
@@ -83,7 +92,10 @@ internal val platformOperations: PlatformOperations by lazy {
...
@@ -83,7 +92,10 @@ internal val platformOperations: PlatformOperations by lazy {
// return linuxGetDpiScaleNative(component)
// return linuxGetDpiScaleNative(component)
}
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
LinuxRedrawer
(
layer
)
override
fun
createRedrawer
(
layer
:
HardwareLayer
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
RasterRedrawer
(
layer
)
else
->
LinuxRedrawer
(
layer
)
}
}
}
}
}
}
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
View file @
6ad0a4e6
...
@@ -2,22 +2,12 @@ package org.jetbrains.skiko
...
@@ -2,22 +2,12 @@ package org.jetbrains.skiko
import
org.jetbrains.skija.*
import
org.jetbrains.skija.*
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.RasterRedrawer
import
org.jetbrains.skiko.context.createContextHandler
import
org.jetbrains.skiko.context.SoftwareContextHandler
import
java.awt.Graphics
import
java.awt.Graphics
import
javax.swing.SwingUtilities.isEventDispatchThread
import
javax.swing.SwingUtilities.isEventDispatchThread
private
class
SkijaState
{
val
bleachConstant
=
if
(
hostOs
==
OS
.
MacOS
)
0
else
-
1
var
context
:
DirectContext
?
=
null
var
renderTarget
:
BackendRenderTarget
?
=
null
var
surface
:
Surface
?
=
null
var
canvas
:
Canvas
?
=
null
fun
clear
()
{
surface
?.
close
()
renderTarget
?.
close
()
}
}
interface
SkiaRenderer
{
interface
SkiaRenderer
{
suspend
fun
onRender
(
canvas
:
Canvas
,
width
:
Int
,
height
:
Int
,
nanoTime
:
Long
)
suspend
fun
onRender
(
canvas
:
Canvas
,
width
:
Int
,
height
:
Int
,
nanoTime
:
Long
)
}
}
...
@@ -25,12 +15,10 @@ interface SkiaRenderer {
...
@@ -25,12 +15,10 @@ interface SkiaRenderer {
private
class
PictureHolder
(
val
instance
:
Picture
,
val
width
:
Int
,
val
height
:
Int
)
private
class
PictureHolder
(
val
instance
:
Picture
,
val
width
:
Int
,
val
height
:
Int
)
open
class
SkiaLayer
:
HardwareLayer
()
{
open
class
SkiaLayer
:
HardwareLayer
()
{
open
val
api
:
GraphicsApi
=
GraphicsApi
.
OPENGL
var
renderer
:
SkiaRenderer
?
=
null
var
renderer
:
SkiaRenderer
?
=
null
val
clipComponents
=
mutableListOf
<
ClipRectangle
>()
val
clipComponents
=
mutableListOf
<
ClipRectangle
>()
private
val
skijaState
=
SkijaState
(
)
internal
var
skijaState
=
createContextHandler
(
this
)
@Volatile
@Volatile
private
var
isDisposed
=
false
private
var
isDisposed
=
false
...
@@ -43,7 +31,7 @@ open class SkiaLayer : HardwareLayer() {
...
@@ -43,7 +31,7 @@ open class SkiaLayer : HardwareLayer() {
override
fun
init
()
{
override
fun
init
()
{
super
.
init
()
super
.
init
()
redrawer
=
platformOperations
.
create
Hardware
Redrawer
(
this
)
redrawer
=
platformOperations
.
createRedrawer
(
this
)
redrawer
?.
syncSize
()
redrawer
?.
syncSize
()
needRedraw
()
needRedraw
()
}
}
...
@@ -114,26 +102,20 @@ open class SkiaLayer : HardwareLayer() {
...
@@ -114,26 +102,20 @@ open class SkiaLayer : HardwareLayer() {
override
fun
draw
()
{
override
fun
draw
()
{
check
(!
isDisposed
)
check
(!
isDisposed
)
if
(
skijaState
.
context
==
null
)
{
skijaState
.
context
=
when
(
api
)
{
GraphicsApi
.
OPENGL
->
makeGLContext
()
GraphicsApi
.
METAL
->
makeMetalContext
()
else
->
TODO
(
"Unsupported yet"
)
}
}
initSkija
()
skijaState
.
apply
{
skijaState
.
apply
{
canvas
!!
.
clear
(
bleachConstant
)
if
(!
initContext
())
{
fallbackToRaster
()
return
}
initCanvas
()
clearCanvas
()
synchronized
(
pictureLock
)
{
synchronized
(
pictureLock
)
{
val
picture
=
picture
val
picture
=
picture
if
(
picture
!=
null
)
{
if
(
picture
!=
null
)
{
canvas
!!
.
drawPicture
(
picture
.
instance
)
drawOnCanvas
(
picture
.
instance
)
}
}
}
}
context
!!
.
flush
()
flush
()
}
}
}
}
...
@@ -151,50 +133,11 @@ open class SkiaLayer : HardwareLayer() {
...
@@ -151,50 +133,11 @@ open class SkiaLayer : HardwareLayer() {
)
)
}
}
private
fun
initSkija
()
{
private
fun
fallbackToRaster
()
{
initRenderTarget
()
println
(
"Falling back to software rendering..."
)
initSurface
()
redrawer
?.
dispose
()
}
skijaState
=
SoftwareContextHandler
(
this
)
redrawer
=
RasterRedrawer
(
this
)
private
fun
initRenderTarget
()
{
needRedraw
()
skijaState
.
apply
{
clear
()
val
dpi
=
contentScale
val
width
=
(
width
*
dpi
).
toInt
().
coerceAtLeast
(
0
)
val
height
=
(
height
*
dpi
).
toInt
().
coerceAtLeast
(
0
)
renderTarget
=
when
(
api
)
{
GraphicsApi
.
OPENGL
->
{
val
gl
=
OpenGLApi
.
instance
val
fbId
=
gl
.
glGetIntegerv
(
gl
.
GL_DRAW_FRAMEBUFFER_BINDING
)
makeGLRenderTarget
(
width
,
height
,
0
,
8
,
fbId
,
FramebufferFormat
.
GR_GL_RGBA8
)
}
GraphicsApi
.
METAL
->
makeMetalRenderTarget
(
width
,
height
,
0
)
else
->
TODO
(
"Unsupported yet"
)
}
}
}
private
fun
initSurface
()
{
skijaState
.
apply
{
surface
=
Surface
.
makeFromBackendRenderTarget
(
context
!!
,
renderTarget
!!
,
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceColorFormat
.
RGBA_8888
,
ColorSpace
.
getSRGB
()
)
canvas
=
surface
!!
.
canvas
}
}
}
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
0 → 100644
View file @
6ad0a4e6
package
org.jetbrains.skiko.context
import
org.jetbrains.skija.BackendRenderTarget
import
org.jetbrains.skija.Canvas
import
org.jetbrains.skija.DirectContext
import
org.jetbrains.skija.Picture
import
org.jetbrains.skija.Surface
import
org.jetbrains.skiko.GraphicsApi
import
org.jetbrains.skiko.HardwareLayer
import
org.jetbrains.skiko.hostOs
import
org.jetbrains.skiko.OS
internal
val
renderApi
:
GraphicsApi
by
lazy
{
val
environment
=
System
.
getenv
(
"SKIKO_RENDER_API"
)
val
property
=
System
.
getProperty
(
"skiko.renderApi"
)
if
(
environment
!=
null
)
{
parseRenderApi
(
environment
)
}
else
{
parseRenderApi
(
property
)
}
}
private
fun
parseRenderApi
(
text
:
String
?):
GraphicsApi
{
when
(
text
)
{
"SOFTWARE"
->
return
GraphicsApi
.
SOFTWARE
"OPENGL"
->
return
GraphicsApi
.
OPENGL
else
->
return
GraphicsApi
.
OPENGL
}
}
internal
fun
createContextHandler
(
layer
:
HardwareLayer
):
ContextHandler
{
return
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
SoftwareContextHandler
(
layer
)
GraphicsApi
.
OPENGL
->
OpenGLContextHandler
(
layer
)
else
->
TODO
(
"Unsupported yet"
)
}
}
internal
abstract
class
ContextHandler
(
val
layer
:
HardwareLayer
)
{
open
val
bleachConstant
=
if
(
hostOs
==
OS
.
MacOS
)
0
else
-
1
var
context
:
DirectContext
?
=
null
var
renderTarget
:
BackendRenderTarget
?
=
null
var
surface
:
Surface
?
=
null
var
canvas
:
Canvas
?
=
null
abstract
fun
initContext
():
Boolean
abstract
fun
initCanvas
()
fun
clearCanvas
()
{
canvas
?.
clear
(
bleachConstant
)
}
open
fun
drawOnCanvas
(
picture
:
Picture
)
{
canvas
?.
drawPicture
(
picture
)
}
open
fun
flush
()
{
context
?.
flush
()
}
fun
dispose
()
{
surface
?.
close
()
renderTarget
?.
close
()
}
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
0 → 100644
View file @
6ad0a4e6
package
org.jetbrains.skiko.context
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.HardwareLayer
import
org.jetbrains.skiko.makeMetalContext
import
org.jetbrains.skiko.makeMetalRenderTarget
internal
class
MetalContextHandler
(
layer
:
HardwareLayer
)
:
ContextHandler
(
layer
)
{
override
fun
initContext
():
Boolean
{
try
{
if
(
context
==
null
)
{
context
=
makeMetalContext
()
}
}
catch
(
e
:
Exception
)
{
println
(
"Failed to create Skia Metal context!"
)
return
false
}
return
true
}
override
fun
initCanvas
()
{
dispose
()
val
scale
=
layer
.
contentScale
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
renderTarget
=
makeMetalRenderTarget
(
w
,
h
,
0
)
surface
=
Surface
.
makeFromBackendRenderTarget
(
context
!!
,
renderTarget
!!
,
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceColorFormat
.
RGBA_8888
,
ColorSpace
.
getSRGB
()
)
canvas
=
surface
!!
.
canvas
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
0 → 100644
View file @
6ad0a4e6
package
org.jetbrains.skiko.context
import
org.jetbrains.skija.ColorSpace
import
org.jetbrains.skija.FramebufferFormat
import
org.jetbrains.skija.Picture
import
org.jetbrains.skija.Surface
import
org.jetbrains.skija.SurfaceColorFormat
import
org.jetbrains.skija.SurfaceOrigin
import
org.jetbrains.skiko.HardwareLayer
import
org.jetbrains.skiko.makeGLContext
import
org.jetbrains.skiko.makeGLRenderTarget
import
org.jetbrains.skiko.OpenGLApi
internal
class
OpenGLContextHandler
(
layer
:
HardwareLayer
)
:
ContextHandler
(
layer
)
{
override
fun
initContext
():
Boolean
{
try
{
if
(
context
==
null
)
{
context
=
makeGLContext
()
}
}
catch
(
e
:
Exception
)
{
println
(
"Failed to create Skia OpenGL context!"
)
return
false
}
return
true
}
override
fun
initCanvas
()
{
dispose
()
val
scale
=
layer
.
contentScale
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
gl
=
OpenGLApi
.
instance
val
fbId
=
gl
.
glGetIntegerv
(
gl
.
GL_DRAW_FRAMEBUFFER_BINDING
)
renderTarget
=
makeGLRenderTarget
(
w
,
h
,
0
,
8
,
fbId
,
FramebufferFormat
.
GR_GL_RGBA8
)
surface
=
Surface
.
makeFromBackendRenderTarget
(
context
!!
,
renderTarget
!!
,
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceColorFormat
.
RGBA_8888
,
ColorSpace
.
getSRGB
()
)
canvas
=
surface
!!
.
canvas
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
0 → 100644
View file @
6ad0a4e6
package
org.jetbrains.skiko.context
import
java.awt.AlphaComposite
import
java.awt.color.ColorSpace
import
java.awt.Color
import
java.awt.Graphics2D
import
java.awt.Transparency
import
java.awt.image.ComponentColorModel
import
java.awt.image.BufferedImage
import
java.awt.image.DataBuffer
import
java.awt.image.DataBufferByte
import
java.awt.image.WritableRaster
import
java.awt.image.Raster
import
org.jetbrains.skija.Bitmap
import
org.jetbrains.skija.ColorAlphaType
import
org.jetbrains.skija.Canvas
import
org.jetbrains.skiko.HardwareLayer
import
org.jetbrains.skija.ImageInfo
import
org.jetbrains.skija.Picture
internal
class
SoftwareContextHandler
(
layer
:
HardwareLayer
)
:
ContextHandler
(
layer
)
{
override
val
bleachConstant
=
-
1
// it looks like java.awt.Canvas doesn't support transparency
val
colorModel
=
ComponentColorModel
(
ColorSpace
.
getInstance
(
ColorSpace
.
CS_sRGB
),
true
,
false
,
Transparency
.
TRANSLUCENT
,
DataBuffer
.
TYPE_BYTE
)
val
storage
=
Bitmap
()
var
image
:
BufferedImage
?
=
null
var
imageData
:
ByteArray
?
=
null
var
raster
:
WritableRaster
?
=
null
override
fun
initContext
():
Boolean
{
// Raster does not need context
return
true
}
override
fun
initCanvas
()
{
dispose
()
val
scale
=
layer
.
contentScale
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
if
(
storage
.
getWidth
()
!=
w
||
storage
.
getHeight
()
!=
h
)
{
storage
.
allocPixelsFlags
(
ImageInfo
.
makeS32
(
w
,
h
,
ColorAlphaType
.
PREMUL
),
false
)
}
canvas
=
Canvas
(
storage
)
}
override
fun
drawOnCanvas
(
picture
:
Picture
)
{
super
.
drawOnCanvas
(
picture
)
val
scale
=
layer
.
contentScale
val
w
=
(
layer
.
width
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
h
=
(
layer
.
height
*
scale
).
toInt
().
coerceAtLeast
(
0
)
val
bytes
=
storage
.
readPixels
(
storage
.
getImageInfo
(),
(
w
*
4
).
toLong
(),
0
,
0
)
if
(
bytes
!=
null
)
{
val
buffer
=
DataBufferByte
(
bytes
,
bytes
.
size
)
raster
=
Raster
.
createInterleavedRaster
(
buffer
,
w
,
h
,
w
*
4
,
4
,
intArrayOf
(
2
,
1
,
0
,
3
),
// BGRA order
null
)
image
=
BufferedImage
(
colorModel
,
raster
!!
,
false
,
null
)
layer
.
getGraphics
()
?.
drawImage
(
image
!!
,
0
,
0
,
layer
.
width
,
layer
.
height
,
null
)
}
}
override
fun
flush
()
{
// Raster does not need to flush canvas
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/RasterRedrawer.kt
0 → 100644
View file @
6ad0a4e6
package
org.jetbrains.skiko.redrawer
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.swing.Swing
import
org.jetbrains.skiko.FrameDispatcher
import
org.jetbrains.skiko.HardwareLayer
internal
class
RasterRedrawer
(
private
val
layer
:
HardwareLayer
)
:
Redrawer
{
private
val
frameDispatcher
=
FrameDispatcher
(
Dispatchers
.
Swing
)
{
layer
.
update
(
System
.
nanoTime
())
layer
.
draw
()
}
override
fun
dispose
()
{
frameDispatcher
.
cancel
()
}
override
fun
needRedraw
()
{
frameDispatcher
.
scheduleFrame
()
}
}
\ 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