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
d12c114d
Commit
d12c114d
authored
Jan 27, 2021
by
Roman Sedaikin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Software rendering support.
parent
8f723ef8
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
288 additions
and
82 deletions
+288
-82
App.kt
...kijaInjectSample/src/main/kotlin/SkijaInjectSample/App.kt
+3
-1
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
+15
-3
SkiaLayer.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+7
-77
ContextHandler.kt
...Main/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
+69
-0
MetalContextHandler.kt
...kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
+38
-0
OpenGLContextHandler.kt
...otlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
+49
-0
RasterContextHandler.kt
...otlin/org/jetbrains/skiko/context/RasterContextHandler.kt
+81
-0
RasterRedrawer.kt
...ain/kotlin/org/jetbrains/skiko/redrawer/RasterRedrawer.kt
+24
-0
No files found.
samples/SkijaInjectSample/src/main/kotlin/SkijaInjectSample/App.kt
View file @
d12c114d
...
...
@@ -15,8 +15,10 @@ import kotlin.math.cos
import
kotlin.math.sin
fun
main
(
args
:
Array
<
String
>)
{
System
.
setProperty
(
"skiko.renderApi"
,
"RASTER"
)
repeat
(
1
)
{
createWindow
(
"window $it"
)
// createWindow("window $it")
SwingSkia
()
}
}
...
...
samples/SkijaInjectSample/src/main/kotlin/SkijaInjectSample/SkiaPanel.kt
View file @
d12c114d
...
...
@@ -34,5 +34,6 @@ open class SkiaPanel: JLayeredPane {
override
fun
removeNotify
()
{
super
.
removeNotify
()
layer
.
dispose
()
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/GraphicsApi.kt
View file @
d12c114d
package
org.jetbrains.skiko
enum
class
GraphicsApi
{
UNKNOWN
,
OPENGL
,
VULKAN
,
METAL
UNKNOWN
,
RASTER
,
OPENGL
,
D3D
,
VULKAN
,
METAL
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
View file @
d12c114d
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.MacOsRedrawer
import
org.jetbrains.skiko.redrawer.RasterRedrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.WindowsRedrawer
import
java.awt.Component
...
...
@@ -30,7 +33,10 @@ internal val platformOperations: PlatformOperations by lazy {
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
MacOsRedrawer
(
layer
)
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
when
(
renderApi
)
{
GraphicsApi
.
RASTER
->
RasterRedrawer
(
layer
)
else
->
MacOsRedrawer
(
layer
)
}
}
OS
.
Windows
->
{
object
:
PlatformOperations
{
...
...
@@ -50,7 +56,10 @@ internal val platformOperations: PlatformOperations by lazy {
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
WindowsRedrawer
(
layer
)
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
when
(
renderApi
)
{
GraphicsApi
.
RASTER
->
RasterRedrawer
(
layer
)
else
->
WindowsRedrawer
(
layer
)
}
}
}
OS
.
Linux
->
{
...
...
@@ -83,7 +92,10 @@ internal val platformOperations: PlatformOperations by lazy {
// return linuxGetDpiScaleNative(component)
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
LinuxRedrawer
(
layer
)
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
when
(
renderApi
)
{
GraphicsApi
.
RASTER
->
RasterRedrawer
(
layer
)
else
->
LinuxRedrawer
(
layer
)
}
}
}
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
View file @
d12c114d
...
...
@@ -2,22 +2,10 @@ package org.jetbrains.skiko
import
org.jetbrains.skija.*
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.context.createContextHandler
import
java.awt.Graphics
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
{
suspend
fun
onRender
(
canvas
:
Canvas
,
width
:
Int
,
height
:
Int
,
nanoTime
:
Long
)
}
...
...
@@ -25,12 +13,10 @@ interface SkiaRenderer {
private
class
PictureHolder
(
val
instance
:
Picture
,
val
width
:
Int
,
val
height
:
Int
)
open
class
SkiaLayer
:
HardwareLayer
()
{
open
val
api
:
GraphicsApi
=
GraphicsApi
.
OPENGL
var
renderer
:
SkiaRenderer
?
=
null
val
clipComponents
=
mutableListOf
<
ClipRectangle
>()
private
val
skijaState
=
SkijaState
(
)
private
val
skijaState
=
createContextHandler
(
this
)
@Volatile
private
var
isDisposed
=
false
...
...
@@ -114,26 +100,17 @@ open class SkiaLayer : HardwareLayer() {
override
fun
draw
()
{
check
(!
isDisposed
)
if
(
skijaState
.
context
==
null
)
{
skijaState
.
context
=
when
(
api
)
{
GraphicsApi
.
OPENGL
->
makeGLContext
()
GraphicsApi
.
METAL
->
makeMetalContext
()
else
->
TODO
(
"Unsupported yet"
)
}
}
initSkija
()
skijaState
.
apply
{
canvas
!!
.
clear
(
bleachConstant
)
initContext
()
initCanvas
()
clearCanvas
()
synchronized
(
pictureLock
)
{
val
picture
=
picture
if
(
picture
!=
null
)
{
canvas
!!
.
drawPicture
(
picture
.
instance
)
drawOnCanvas
(
picture
.
instance
)
}
}
context
!!
.
flush
()
flush
()
}
}
...
...
@@ -150,51 +127,4 @@ open class SkiaLayer : HardwareLayer() {
true
)
}
private
fun
initSkija
()
{
initRenderTarget
()
initSurface
()
}
private
fun
initRenderTarget
()
{
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 @
d12c114d
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
)
{
"RASTER"
->
return
GraphicsApi
.
RASTER
"OPENGL"
->
return
GraphicsApi
.
OPENGL
"VULKAN"
->
return
GraphicsApi
.
VULKAN
"METAL"
->
return
GraphicsApi
.
METAL
else
->
return
GraphicsApi
.
OPENGL
}
}
internal
fun
createContextHandler
(
layer
:
HardwareLayer
):
ContextHandler
{
return
when
(
renderApi
)
{
GraphicsApi
.
RASTER
->
RasterContextHandler
(
layer
)
GraphicsApi
.
OPENGL
->
OpenGLContextHandler
(
layer
)
GraphicsApi
.
METAL
->
MetalContextHandler
(
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
()
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 @
d12c114d
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
()
{
if
(
context
==
null
)
{
context
=
makeMetalContext
()
}
}
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 @
d12c114d
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
()
{
if
(
context
==
null
)
{
context
=
makeGLContext
()
}
}
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/RasterContextHandler.kt
0 → 100644
View file @
d12c114d
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
RasterContextHandler
(
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
()
{
// Raster does not need context
}
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 @
d12c114d
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