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
f1ce1d44
Unverified
Commit
f1ce1d44
authored
Feb 19, 2021
by
Roman Sedaikin
Committed by
GitHub
Feb 19, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #63 from JetBrains/directx
DirectX rendering implementation.
parents
20bba69b
21f890db
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
596 additions
and
41 deletions
+596
-41
build.gradle.kts
skiko/build.gradle.kts
+1
-0
gradle.properties
skiko/gradle.properties
+4
-4
directXRedrawer.cc
skiko/src/jvmMain/cpp/windows/directXRedrawer.cc
+357
-0
openGLRedrawer.cc
skiko/src/jvmMain/cpp/windows/openGLRedrawer.cc
+0
-0
PlatformOperations.kt
.../jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
+25
-12
SkiaLayer.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+20
-11
SkikoProperties.kt
...src/jvmMain/kotlin/org/jetbrains/skiko/SkikoProperties.kt
+31
-1
ContextHandler.kt
...Main/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
+8
-6
Direct3DContextHandler.kt
...lin/org/jetbrains/skiko/context/Direct3DContextHandler.kt
+68
-0
MetalContextHandler.kt
...kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
+3
-2
OpenGLContextHandler.kt
...otlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
+3
-2
SoftwareContextHandler.kt
...lin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
+3
-2
Direct3DRedrawer.kt
...n/kotlin/org/jetbrains/skiko/redrawer/Direct3DRedrawer.kt
+72
-0
SoftwareRedrawer.kt
...n/kotlin/org/jetbrains/skiko/redrawer/SoftwareRedrawer.kt
+1
-1
No files found.
skiko/build.gradle.kts
View file @
f1ce1d44
...
...
@@ -268,6 +268,7 @@ tasks.withType(CppCompile::class.java).configureEach {
"-DWIN32_LEAN_AND_MEAN"
,
"-DNOMINMAX"
,
"-DSK_GAMMA_APPLY_TO_A8"
,
"-DSK_DIRECT3D"
,
"/utf-8"
,
"/GR-"
,
// no-RTTI.
*
buildType
.
msvcFlags
...
...
skiko/gradle.properties
View file @
f1ce1d44
...
...
@@ -2,9 +2,9 @@ kotlin.code.style=official
deploy.version
=
0.0.0
dependencies.skija.git.commit
=
b85e3e7a70204281cf0036d5595a8eed68bacd2c
dependencies.skia.windows-x64
=
m89-1
5595ea39c/Skia-m89-15595ea39c
-windows-Release-x64
dependencies.skia.linux-x64
=
m89-1
5595ea39c/Skia-m89-15595ea39c
-linux-Release-x64
dependencies.skia.macos-x64
=
m89-1
5595ea39c/Skia-m89-15595ea39c
-macos-Release-x64
dependencies.skia.macos-arm64
=
m89-1
5595ea39c/Skia-m89-15595ea39c
-macos-Release-arm64
dependencies.skia.windows-x64
=
m89-1
9889d74fa/Skia-m89-19889d74fa
-windows-Release-x64
dependencies.skia.linux-x64
=
m89-1
9889d74fa/Skia-m89-19889d74fa
-linux-Release-x64
dependencies.skia.macos-x64
=
m89-1
9889d74fa/Skia-m89-19889d74fa
-macos-Release-x64
dependencies.skia.macos-arm64
=
m89-1
9889d74fa/Skia-m89-19889d74fa
-macos-Release-arm64
# signer=Apple Distribution: Nikolay Igotti (N462MKSJ7M)
skiko/src/jvmMain/cpp/windows/directXRedrawer.cc
0 → 100644
View file @
f1ce1d44
#ifdef SK_DIRECT3D
#include <stdexcept>
#include <Windows.h>
#include <jawt_md.h>
#include "jni_helpers.h"
#include "GrBackendSurface.h"
#include "GrDirectContext.h"
#include "SkSurface.h"
#include "d3d/GrD3DTypes.h"
#include <d3d12sdklayers.h>
#include "d3d/GrD3DBackendContext.h"
#include <d3d12.h>
#include <dxgi1_4.h>
#define GR_D3D_CALL_ERRCHECK(X) \
do \
{ \
HRESULT result = X; \
SkASSERT(SUCCEEDED(result)); \
if (!SUCCEEDED(result)) \
{ \
SkDebugf("Failed Direct3D call. Error: 0x%08x\n", result); \
throw std::exception("ERROR"); \
} \
} while (false)
const
int
BuffersCount
=
2
;
class
DirectXDevice
{
public
:
GrD3DBackendContext
backendContext
;
gr_cp
<
ID3D12Device
>
device
;
gr_cp
<
IDXGISwapChain3
>
swapChain
;
gr_cp
<
ID3D12CommandQueue
>
queue
;
gr_cp
<
ID3D12Fence
>
fence
;
HANDLE
fenceEvent
=
NULL
;
uint64_t
fenceValue
;
unsigned
int
bufferIndex
=
1
;
unsigned
int
bufferWidth
=
0
;
unsigned
int
bufferHeight
=
0
;
bool
isSizeEqualTo
(
unsigned
int
width
,
unsigned
int
height
)
{
return
width
==
bufferWidth
&&
height
==
bufferHeight
;
}
~
DirectXDevice
()
{
if
(
fenceEvent
!=
NULL
)
{
CloseHandle
(
fenceEvent
);
}
}
};
extern
"C"
{
HRESULT
D3D12CreateDevice
(
IUnknown
*
pAdapter
,
D3D_FEATURE_LEVEL
MinimumFeatureLevel
,
REFIID
riid
,
void
**
ppDevice
)
{
typedef
HRESULT
(
*
D3D12CreateDevice_t
)(
IUnknown
*
pAdapter
,
D3D_FEATURE_LEVEL
MinimumFeatureLevel
,
REFIID
riid
,
void
**
ppDevice
);
static
D3D12CreateDevice_t
impl
=
nullptr
;
if
(
!
impl
)
{
auto
d3d12dll
=
LoadLibrary
(
TEXT
(
"D3D12.dll"
));
if
(
!
d3d12dll
)
return
E_NOTIMPL
;
impl
=
(
D3D12CreateDevice_t
)
GetProcAddress
(
d3d12dll
,
"D3D12CreateDevice"
);
if
(
!
impl
)
return
E_NOTIMPL
;
}
return
impl
(
pAdapter
,
MinimumFeatureLevel
,
riid
,
ppDevice
);
}
HRESULT
D3D12SerializeRootSignature
(
const
D3D12_ROOT_SIGNATURE_DESC
*
pRootSignature
,
D3D_ROOT_SIGNATURE_VERSION
Version
,
ID3DBlob
**
ppBlob
,
ID3DBlob
**
ppErrorBlob
)
{
typedef
HRESULT
(
*
D3D12SerializeRootSignature_t
)(
const
D3D12_ROOT_SIGNATURE_DESC
*
pRootSignature
,
D3D_ROOT_SIGNATURE_VERSION
Version
,
ID3DBlob
**
ppBlob
,
ID3DBlob
**
ppErrorBlob
);
static
D3D12SerializeRootSignature_t
impl
=
nullptr
;
if
(
!
impl
)
{
auto
d3d12dll
=
LoadLibrary
(
TEXT
(
"D3D12.dll"
));
if
(
!
d3d12dll
)
return
E_NOTIMPL
;
impl
=
(
D3D12SerializeRootSignature_t
)
GetProcAddress
(
d3d12dll
,
"D3D12SerializeRootSignature"
);
if
(
!
impl
)
return
E_NOTIMPL
;
}
return
impl
(
pRootSignature
,
Version
,
ppBlob
,
ppErrorBlob
);
}
HRESULT
CreateDXGIFactory1
(
REFIID
riid
,
void
**
ppFactory
)
{
typedef
HRESULT
(
*
CreateDXGIFactory1_t
)(
REFIID
riid
,
void
**
ppFactory
);
static
CreateDXGIFactory1_t
impl
=
nullptr
;
if
(
!
impl
)
{
auto
dxgidll
=
LoadLibrary
(
TEXT
(
"Dxgi.dll"
));
if
(
!
dxgidll
)
return
E_NOTIMPL
;
impl
=
(
CreateDXGIFactory1_t
)
GetProcAddress
(
dxgidll
,
"CreateDXGIFactory1"
);
if
(
!
impl
)
return
E_NOTIMPL
;
}
return
impl
(
riid
,
ppFactory
);
}
HRESULT
CreateDXGIFactory2
(
UINT
Flags
,
REFIID
riid
,
void
**
ppFactory
)
{
typedef
HRESULT
(
*
CreateDXGIFactory2_t
)(
UINT
Flags
,
REFIID
riid
,
void
**
ppFactory
);
static
CreateDXGIFactory2_t
impl
=
nullptr
;
if
(
!
impl
)
{
auto
dxgidll
=
LoadLibrary
(
TEXT
(
"Dxgi.dll"
));
if
(
!
dxgidll
)
return
E_NOTIMPL
;
impl
=
(
CreateDXGIFactory2_t
)
GetProcAddress
(
dxgidll
,
"CreateDXGIFactory2"
);
if
(
!
impl
)
return
E_NOTIMPL
;
}
return
impl
(
Flags
,
riid
,
ppFactory
);
}
HRESULT
D3DCompile
(
LPCVOID
pSrcData
,
SIZE_T
SrcDataSize
,
LPCSTR
pSourceName
,
const
D3D_SHADER_MACRO
*
pDefines
,
ID3DInclude
*
pInclude
,
LPCSTR
pEntrypoint
,
LPCSTR
pTarget
,
UINT
Flags1
,
UINT
Flags2
,
ID3DBlob
**
ppCode
,
ID3DBlob
**
ppErrorMsgs
)
{
typedef
HRESULT
(
*
D3DCompile_t
)(
LPCVOID
pSrcData
,
SIZE_T
SrcDataSize
,
LPCSTR
pSourceName
,
const
D3D_SHADER_MACRO
*
pDefines
,
ID3DInclude
*
pInclude
,
LPCSTR
pEntrypoint
,
LPCSTR
pTarget
,
UINT
Flags1
,
UINT
Flags2
,
ID3DBlob
**
ppCode
,
ID3DBlob
**
ppErrorMsgs
);
static
D3DCompile_t
impl
=
nullptr
;
if
(
!
impl
)
{
auto
d3dcompilerdll
=
LoadLibrary
(
TEXT
(
"d3dcompiler_47.dll"
));
if
(
!
d3dcompilerdll
)
return
E_NOTIMPL
;
impl
=
(
D3DCompile_t
)
GetProcAddress
(
d3dcompilerdll
,
"D3DCompile"
);
if
(
!
impl
)
return
E_NOTIMPL
;
}
return
impl
(
pSrcData
,
SrcDataSize
,
pSourceName
,
pDefines
,
pInclude
,
pEntrypoint
,
pTarget
,
Flags1
,
Flags2
,
ppCode
,
ppErrorMsgs
);
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_makeDirectXContext
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
)
{
DirectXDevice
*
d3dDevice
=
fromJavaPointer
<
DirectXDevice
*>
(
devicePtr
);
GrD3DBackendContext
backendContext
=
d3dDevice
->
backendContext
;
return
toJavaPointer
(
GrDirectContext
::
MakeDirect3D
(
backendContext
).
release
());
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_makeDirectXRenderTarget
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
,
jint
width
,
jint
height
)
{
DirectXDevice
*
d3dDevice
=
fromJavaPointer
<
DirectXDevice
*>
(
devicePtr
);
if
(
!
d3dDevice
->
isSizeEqualTo
(
width
,
height
))
{
GR_D3D_CALL_ERRCHECK
(
d3dDevice
->
swapChain
->
ResizeBuffers
(
BuffersCount
,
width
,
height
,
DXGI_FORMAT_R8G8B8A8_UNORM
,
0
));
d3dDevice
->
bufferWidth
=
width
;
d3dDevice
->
bufferHeight
=
height
;
}
d3dDevice
->
bufferIndex
=
d3dDevice
->
swapChain
->
GetCurrentBackBufferIndex
();
ID3D12Resource
*
buffer
;
GR_D3D_CALL_ERRCHECK
(
d3dDevice
->
swapChain
->
GetBuffer
(
d3dDevice
->
bufferIndex
,
IID_PPV_ARGS
(
&
buffer
)));
GrD3DTextureResourceInfo
info
(
buffer
,
nullptr
,
D3D12_RESOURCE_STATE_PRESENT
,
DXGI_FORMAT_R8G8B8A8_UNORM
,
1
,
1
,
0
);
GrBackendRenderTarget
*
renderTarget
=
new
GrBackendRenderTarget
(
width
,
height
,
info
);
return
toJavaPointer
(
renderTarget
);
}
bool
defineHardwareAdapter
(
IDXGIFactory4
*
pFactory
,
IDXGIAdapter1
**
ppAdapter
)
{
*
ppAdapter
=
nullptr
;
for
(
UINT
adapterIndex
=
0
;;
++
adapterIndex
)
{
IDXGIAdapter1
*
pAdapter
=
nullptr
;
if
(
DXGI_ERROR_NOT_FOUND
==
pFactory
->
EnumAdapters1
(
adapterIndex
,
&
pAdapter
))
{
break
;
}
if
(
SUCCEEDED
(
D3D12CreateDevice
(
pAdapter
,
D3D_FEATURE_LEVEL_11_0
,
_uuidof
(
ID3D12Device
),
nullptr
)))
{
*
ppAdapter
=
pAdapter
;
return
true
;
}
pAdapter
->
Release
();
}
return
false
;
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_createDirectXDevice
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
windowHandle
)
{
gr_cp
<
IDXGIFactory4
>
deviceFactory
;
if
(
!
SUCCEEDED
(
CreateDXGIFactory1
(
IID_PPV_ARGS
(
&
deviceFactory
))))
{
return
0
;
}
gr_cp
<
IDXGIAdapter1
>
hardwareAdapter
;
if
(
!
defineHardwareAdapter
(
deviceFactory
.
get
(),
&
hardwareAdapter
))
{
return
0
;
}
gr_cp
<
ID3D12Device
>
device
;
if
(
!
SUCCEEDED
(
D3D12CreateDevice
(
hardwareAdapter
.
get
(),
D3D_FEATURE_LEVEL_11_0
,
IID_PPV_ARGS
(
&
device
))))
{
return
0
;
}
// Create the command queue
gr_cp
<
ID3D12CommandQueue
>
queue
;
D3D12_COMMAND_QUEUE_DESC
queueDesc
=
{};
queueDesc
.
Flags
=
D3D12_COMMAND_QUEUE_FLAG_NONE
;
queueDesc
.
Type
=
D3D12_COMMAND_LIST_TYPE_DIRECT
;
if
(
!
SUCCEEDED
(
device
->
CreateCommandQueue
(
&
queueDesc
,
IID_PPV_ARGS
(
&
queue
))))
{
return
0
;
}
DirectXDevice
*
d3dDevice
=
new
DirectXDevice
();
d3dDevice
->
backendContext
.
fAdapter
=
hardwareAdapter
;
d3dDevice
->
backendContext
.
fDevice
=
device
;
d3dDevice
->
backendContext
.
fQueue
=
queue
;
d3dDevice
->
device
=
device
;
d3dDevice
->
queue
=
queue
;
// Make the swapchain
HWND
fWindow
=
(
HWND
)
windowHandle
;
gr_cp
<
IDXGIFactory4
>
swapChainFactory
;
GR_D3D_CALL_ERRCHECK
(
CreateDXGIFactory2
(
0
,
IID_PPV_ARGS
(
&
swapChainFactory
)));
DXGI_SWAP_CHAIN_DESC1
swapChainDesc
=
{};
swapChainDesc
.
BufferCount
=
BuffersCount
;
swapChainDesc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
swapChainDesc
.
BufferUsage
=
DXGI_USAGE_RENDER_TARGET_OUTPUT
;
swapChainDesc
.
SwapEffect
=
DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
;
swapChainDesc
.
SampleDesc
.
Count
=
1
;
swapChainDesc
.
SampleDesc
.
Quality
=
0
;
swapChainDesc
.
Scaling
=
DXGI_SCALING_NONE
;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC
swapChainFSDesc
=
{};
swapChainFSDesc
.
Windowed
=
TRUE
;
gr_cp
<
IDXGISwapChain1
>
swapChain
;
GR_D3D_CALL_ERRCHECK
(
swapChainFactory
->
CreateSwapChainForHwnd
(
d3dDevice
->
queue
.
get
(),
fWindow
,
&
swapChainDesc
,
&
swapChainFSDesc
,
nullptr
,
&
swapChain
));
DXGI_RGBA
background
=
{
1.0
f
,
1.0
f
,
1.0
f
,
1.0
f
};
swapChain
->
SetBackgroundColor
(
&
background
);
GR_D3D_CALL_ERRCHECK
(
swapChain
->
QueryInterface
(
IID_PPV_ARGS
(
&
d3dDevice
->
swapChain
)));
GR_D3D_CALL_ERRCHECK
(
d3dDevice
->
device
->
CreateFence
(
0
,
D3D12_FENCE_FLAG_NONE
,
IID_PPV_ARGS
(
&
d3dDevice
->
fence
)));
d3dDevice
->
fenceEvent
=
CreateEvent
(
nullptr
,
FALSE
,
FALSE
,
nullptr
);
return
toJavaPointer
(
d3dDevice
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_resizeBuffers
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
,
jint
width
,
jint
height
)
{
DirectXDevice
*
d3dDevice
=
fromJavaPointer
<
DirectXDevice
*>
(
devicePtr
);
if
(
!
d3dDevice
->
isSizeEqualTo
(
width
,
height
))
{
GR_D3D_CALL_ERRCHECK
(
d3dDevice
->
swapChain
->
ResizeBuffers
(
BuffersCount
,
width
,
height
,
DXGI_FORMAT_R8G8B8A8_UNORM
,
0
));
d3dDevice
->
bufferWidth
=
width
;
d3dDevice
->
bufferHeight
=
height
;
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_finishFrame
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
,
jlong
contextPtr
,
jlong
surfacePtr
,
jboolean
isVsyncEnabled
)
{
DirectXDevice
*
d3dDevice
=
fromJavaPointer
<
DirectXDevice
*>
(
devicePtr
);
SkSurface
*
surface
=
fromJavaPointer
<
SkSurface
*>
(
surfacePtr
);
surface
->
flushAndSubmit
();
GrDirectContext
*
fContext
=
fromJavaPointer
<
GrDirectContext
*>
(
contextPtr
);
surface
->
flush
(
SkSurface
::
BackendSurfaceAccess
::
kPresent
,
GrFlushInfo
());
fContext
->
flush
({});
fContext
->
submit
(
true
);
// 1 value in [Present(1, 0)] enables vblank wait so this is how vertical sync works in DirectX.
GR_D3D_CALL_ERRCHECK
(
d3dDevice
->
swapChain
->
Present
((
int
)
isVsyncEnabled
,
0
));
const
UINT64
fence
=
d3dDevice
->
fenceValue
;
GR_D3D_CALL_ERRCHECK
(
d3dDevice
->
queue
->
Signal
(
d3dDevice
->
fence
.
get
(),
fence
));
d3dDevice
->
fenceValue
++
;
if
(
d3dDevice
->
fence
->
GetCompletedValue
()
<
fence
)
{
GR_D3D_CALL_ERRCHECK
(
d3dDevice
->
fence
->
SetEventOnCompletion
(
fence
,
d3dDevice
->
fenceEvent
));
WaitForSingleObjectEx
(
d3dDevice
->
fenceEvent
,
INFINITE
,
FALSE
);
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_disposeDevice
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
)
{
DirectXDevice
*
d3dDevice
=
fromJavaPointer
<
DirectXDevice
*>
(
devicePtr
);
delete
d3dDevice
;
}
}
#endif
skiko/src/jvmMain/cpp/windows/
r
edrawer.cc
→
skiko/src/jvmMain/cpp/windows/
openGLR
edrawer.cc
View file @
f1ce1d44
File moved
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
View file @
f1ce1d44
package
org.jetbrains.skiko
import
org.jetbrains.skiko.SkikoProperties.renderApi
import
org.jetbrains.skiko.redrawer.LinuxOpenGLRedrawer
import
org.jetbrains.skiko.redrawer.MacOsOpenGLRedrawer
import
org.jetbrains.skiko.redrawer.
Raster
Redrawer
import
org.jetbrains.skiko.redrawer.
Software
Redrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.WindowsOpenGLRedrawer
import
org.jetbrains.skiko.redrawer.Direct3DRedrawer
import
java.awt.Component
import
java.awt.Window
import
javax.swing.SwingUtilities
...
...
@@ -14,7 +14,7 @@ internal interface PlatformOperations {
fun
isFullscreen
(
component
:
Component
):
Boolean
fun
setFullscreen
(
component
:
Component
,
value
:
Boolean
)
fun
getDpiScale
(
component
:
Component
):
Float
fun
createRedrawer
(
layer
:
HardwareLayer
,
properties
:
SkiaLayerProperties
):
Redrawer
fun
createRedrawer
(
layer
:
HardwareLayer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
):
Redrawer
}
internal
val
platformOperations
:
PlatformOperations
by
lazy
{
...
...
@@ -32,8 +32,12 @@ internal val platformOperations: PlatformOperations by lazy {
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
override
fun
createRedrawer
(
layer
:
HardwareLayer
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
RasterRedrawer
(
layer
)
override
fun
createRedrawer
(
layer
:
HardwareLayer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
SoftwareRedrawer
(
layer
)
else
->
MacOsOpenGLRedrawer
(
layer
,
properties
)
}
}
...
...
@@ -55,8 +59,13 @@ internal val platformOperations: PlatformOperations by lazy {
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
override
fun
createRedrawer
(
layer
:
HardwareLayer
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
RasterRedrawer
(
layer
)
override
fun
createRedrawer
(
layer
:
HardwareLayer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
SoftwareRedrawer
(
layer
)
GraphicsApi
.
DIRECT3D
->
Direct3DRedrawer
(
layer
,
properties
)
else
->
WindowsOpenGLRedrawer
(
layer
,
properties
)
}
}
...
...
@@ -80,19 +89,23 @@ internal val platformOperations: PlatformOperations by lazy {
// TODO doesn't work well because java doesn't scale windows (content has offset with 200% scale)
//
// Two solutions:
// 1. dynamically change sun.java2d.uiScale (it is global property, so we have to be careful) and update all windows
// 1. dynamically change sun.java2d.uiScale (it is global property,
// so we have to be careful) and update all windows
//
// 2. apply contentScale manually to all windows
// (it is not good, because on different platform windows will have different size.
// Maybe we will apply contentScale manually on all platforms?)
// see also comment for HardwareLayer.checkContentScale
// return component.useDrawingSurfacePlatformInfo(::linuxGetDpiScaleNative)
// return component.useDrawingSurfacePlatformInfo(::linuxGetDpiScaleNative)
}
override
fun
createRedrawer
(
layer
:
HardwareLayer
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
RasterRedrawer
(
layer
)
override
fun
createRedrawer
(
layer
:
HardwareLayer
,
renderApi
:
GraphicsApi
,
properties
:
SkiaLayerProperties
)
=
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
SoftwareRedrawer
(
layer
)
else
->
LinuxOpenGLRedrawer
(
layer
,
properties
)
}
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
View file @
f1ce1d44
...
...
@@ -5,12 +5,15 @@ 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.
Software
ContextHandler
import
org.jetbrains.skiko.context.ContextHandler
import
org.jetbrains.skiko.context.createContextHandler
import
org.jetbrains.skiko.redrawer.RasterRedrawer
import
org.jetbrains.skiko.context.SoftwareContextHandler
import
org.jetbrains.skiko.redrawer.SoftwareRedrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
java.awt.Graphics
import
javax.swing.SwingUtilities.isEventDispatchThread
import
kotlin.collections.MutableList
import
kotlin.collections.toMutableList
interface
SkiaRenderer
{
fun
onRender
(
canvas
:
Canvas
,
width
:
Int
,
height
:
Int
,
nanoTime
:
Long
)
...
...
@@ -24,11 +27,12 @@ open class SkiaLayer(
var
renderer
:
SkiaRenderer
?
=
null
val
clipComponents
=
mutableListOf
<
ClipRectangle
>()
internal
var
skijaState
=
createContextHandler
(
this
)
@Volatile
private
var
isDisposed
=
false
private
var
redrawer
:
Redrawer
?
=
null
internal
var
redrawer
:
Redrawer
?
=
null
private
var
contextHandler
:
ContextHandler
?
=
null
private
val
fallbackRenderApiQueue
=
SkikoProperties
.
fallbackRenderApiQueue
.
toMutableList
()
@Volatile
private
var
picture
:
PictureHolder
?
=
null
...
...
@@ -37,7 +41,9 @@ open class SkiaLayer(
override
fun
init
()
{
super
.
init
()
redrawer
=
platformOperations
.
createRedrawer
(
this
,
properties
)
val
initialRenderApi
=
fallbackRenderApiQueue
.
removeAt
(
0
)
contextHandler
=
createContextHandler
(
this
,
initialRenderApi
)
redrawer
=
platformOperations
.
createRedrawer
(
this
,
initialRenderApi
,
properties
)
redrawer
?.
syncSize
()
redrawer
?.
redrawImmediately
()
}
...
...
@@ -45,6 +51,7 @@ open class SkiaLayer(
override
fun
dispose
()
{
check
(!
isDisposed
)
check
(
isEventDispatchThread
())
contextHandler
?.
dispose
()
redrawer
?.
dispose
()
picture
?.
instance
?.
close
()
pictureRecorder
.
close
()
...
...
@@ -104,9 +111,9 @@ open class SkiaLayer(
override
fun
draw
()
{
check
(!
isDisposed
)
skijaState
.
apply
{
contextHandler
?
.
apply
{
if
(!
initContext
())
{
fallbackTo
Raster
()
fallbackTo
NextApi
()
return
}
initCanvas
()
...
...
@@ -135,11 +142,13 @@ open class SkiaLayer(
)
}
private
fun
fallbackToRaster
()
{
println
(
"Falling back to software rendering..."
)
private
fun
fallbackToNextApi
()
{
val
nextApi
=
fallbackRenderApiQueue
.
removeAt
(
0
)
println
(
"Falling back to $nextApi rendering..."
)
contextHandler
?.
dispose
()
redrawer
?.
dispose
()
skijaState
=
SoftwareContextHandler
(
this
)
redrawer
=
RasterRedrawer
(
thi
s
)
contextHandler
=
createContextHandler
(
this
,
nextApi
)
redrawer
=
platformOperations
.
createRedrawer
(
this
,
nextApi
,
propertie
s
)
needRedraw
()
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkikoProperties.kt
View file @
f1ce1d44
...
...
@@ -29,8 +29,38 @@ internal object SkikoProperties {
when
(
text
)
{
"SOFTWARE"
->
return
GraphicsApi
.
SOFTWARE
"OPENGL"
->
return
GraphicsApi
.
OPENGL
else
->
return
GraphicsApi
.
OPENGL
"DIRECT3D"
->
{
return
if
(
hostOs
==
OS
.
Windows
)
GraphicsApi
.
DIRECT3D
else
throw
Exception
(
"$hostOs does not support DirectX rendering API."
)
}
"METAL"
->
{
return
if
(
hostOs
==
OS
.
MacOS
)
GraphicsApi
.
METAL
else
throw
Exception
(
"$hostOs does not support Metal rendering API."
)
}
else
->
return
bestRenderApiForCurrentOS
()
}
}
private
fun
bestRenderApiForCurrentOS
():
GraphicsApi
{
when
(
hostOs
)
{
OS
.
MacOS
->
return
GraphicsApi
.
OPENGL
OS
.
Linux
->
return
GraphicsApi
.
OPENGL
OS
.
Windows
->
return
GraphicsApi
.
DIRECT3D
}
}
val
fallbackRenderApiQueue
:
List
<
GraphicsApi
>
by
lazy
{
val
head
=
renderApi
var
renderApiList
=
mutableListOf
<
GraphicsApi
>()
when
(
hostOs
)
{
OS
.
MacOS
->
renderApiList
=
mutableListOf
(
GraphicsApi
.
OPENGL
,
GraphicsApi
.
SOFTWARE
)
OS
.
Linux
->
renderApiList
=
mutableListOf
(
GraphicsApi
.
OPENGL
,
GraphicsApi
.
SOFTWARE
)
OS
.
Windows
->
renderApiList
=
mutableListOf
(
GraphicsApi
.
DIRECT3D
,
GraphicsApi
.
OPENGL
,
GraphicsApi
.
SOFTWARE
)
}
renderApiList
.
remove
(
head
)
listOf
(
head
)
+
renderApiList
}
private
fun
property
(
name
:
String
,
default
:
Boolean
)
=
lazy
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/ContextHandler.kt
View file @
f1ce1d44
...
...
@@ -6,20 +6,22 @@ import org.jetbrains.skija.DirectContext
import
org.jetbrains.skija.Picture
import
org.jetbrains.skija.Surface
import
org.jetbrains.skiko.GraphicsApi
import
org.jetbrains.skiko.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
import
org.jetbrains.skiko.OS
import
org.jetbrains.skiko.SkikoProperties
import
org.jetbrains.skiko.hostOs
import
org.jetbrains.skiko.redrawer.Redrawer
internal
fun
createContextHandler
(
layer
:
HardwareLayer
):
ContextHandler
{
return
when
(
SkikoProperties
.
renderApi
)
{
internal
fun
createContextHandler
(
layer
:
SkiaLayer
,
renderApi
:
GraphicsApi
):
ContextHandler
{
return
when
(
renderApi
)
{
GraphicsApi
.
SOFTWARE
->
SoftwareContextHandler
(
layer
)
GraphicsApi
.
OPENGL
->
OpenGLContextHandler
(
layer
)
else
->
TODO
(
"Unsupported yet"
)
GraphicsApi
.
DIRECT3D
->
Direct3DContextHandler
(
layer
)
else
->
TODO
(
"Unsupported yet."
)
}
}
internal
abstract
class
ContextHandler
(
val
layer
:
Hardware
Layer
)
{
internal
abstract
class
ContextHandler
(
val
layer
:
Skia
Layer
)
{
open
val
bleachConstant
=
if
(
hostOs
==
OS
.
MacOS
)
0
else
-
1
var
context
:
DirectContext
?
=
null
var
renderTarget
:
BackendRenderTarget
?
=
null
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/Direct3DContextHandler.kt
0 → 100644
View file @
f1ce1d44
package
org.jetbrains.skiko.context
import
java.lang.ref.Reference
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.skija.impl.Native
import
org.jetbrains.skiko.SkiaLayer
import
org.jetbrains.skiko.redrawer.Direct3DRedrawer
import
org.jetbrains.skiko.redrawer.Redrawer
internal
class
Direct3DContextHandler
(
layer
:
SkiaLayer
)
:
ContextHandler
(
layer
)
{
val
directXRedrawer
:
Direct3DRedrawer
get
()
=
layer
.
redrawer
!!
as
Direct3DRedrawer
var
device
:
Long
=
0
override
fun
initContext
():
Boolean
{
try
{
if
(
context
==
null
)
{
device
=
directXRedrawer
.
createDevice
()
if
(
device
==
0L
)
{
throw
Exception
(
"Failed to create DirectX12 device."
)
}
context
=
directXRedrawer
.
makeContext
(
device
)
}
}
catch
(
e
:
Exception
)
{
println
(
"${e.message}\nFailed to create Skia Direct3D 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
=
directXRedrawer
.
makeRenderTarget
(
device
,
w
,
h
)
surface
=
Surface
.
makeFromBackendRenderTarget
(
context
!!
,
renderTarget
!!
,
SurfaceOrigin
.
TOP_LEFT
,
SurfaceColorFormat
.
RGBA_8888
,
ColorSpace
.
getSRGB
()
)
canvas
=
surface
!!
.
canvas
}
override
fun
flush
()
{
try
{
directXRedrawer
.
finishFrame
(
device
,
Native
.
getPtr
(
context
!!
),
Native
.
getPtr
(
surface
!!
)
)
}
finally
{
Reference
.
reachabilityFence
(
context
!!
)
Reference
.
reachabilityFence
(
surface
!!
)
}
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/MetalContextHandler.kt
View file @
f1ce1d44
...
...
@@ -5,11 +5,12 @@ import org.jetbrains.skija.Surface
import
org.jetbrains.skija.SurfaceColorFormat
import
org.jetbrains.skija.SurfaceOrigin
import
org.jetbrains.skiko.GraphicsApi
import
org.jetbrains.skiko.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
import
org.jetbrains.skiko.makeMetalContext
import
org.jetbrains.skiko.makeMetalRenderTarget
import
org.jetbrains.skiko.redrawer.Redrawer
internal
class
MetalContextHandler
(
layer
:
Hardware
Layer
)
:
ContextHandler
(
layer
)
{
internal
class
MetalContextHandler
(
layer
:
Skia
Layer
)
:
ContextHandler
(
layer
)
{
override
fun
initContext
():
Boolean
{
try
{
if
(
context
==
null
)
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/OpenGLContextHandler.kt
View file @
f1ce1d44
...
...
@@ -6,12 +6,13 @@ import org.jetbrains.skija.Picture
import
org.jetbrains.skija.Surface
import
org.jetbrains.skija.SurfaceColorFormat
import
org.jetbrains.skija.SurfaceOrigin
import
org.jetbrains.skiko.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
import
org.jetbrains.skiko.makeGLContext
import
org.jetbrains.skiko.makeGLRenderTarget
import
org.jetbrains.skiko.OpenGLApi
import
org.jetbrains.skiko.redrawer.Redrawer
internal
class
OpenGLContextHandler
(
layer
:
Hardware
Layer
)
:
ContextHandler
(
layer
)
{
internal
class
OpenGLContextHandler
(
layer
:
Skia
Layer
)
:
ContextHandler
(
layer
)
{
override
fun
initContext
():
Boolean
{
try
{
if
(
context
==
null
)
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/context/SoftwareContextHandler.kt
View file @
f1ce1d44
...
...
@@ -14,11 +14,12 @@ import java.awt.image.Raster
import
org.jetbrains.skija.Bitmap
import
org.jetbrains.skija.ColorAlphaType
import
org.jetbrains.skija.Canvas
import
org.jetbrains.skiko.
Hardware
Layer
import
org.jetbrains.skiko.
Skia
Layer
import
org.jetbrains.skija.ImageInfo
import
org.jetbrains.skija.Picture
import
org.jetbrains.skiko.redrawer.Redrawer
internal
class
SoftwareContextHandler
(
layer
:
Hardware
Layer
)
:
ContextHandler
(
layer
)
{
internal
class
SoftwareContextHandler
(
layer
:
Skia
Layer
)
:
ContextHandler
(
layer
)
{
override
val
bleachConstant
=
-
1
// it looks like java.awt.Canvas doesn't support transparency
val
colorModel
=
ComponentColorModel
(
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/Direct3DRedrawer.kt
0 → 100644
View file @
f1ce1d44
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.HardwareLayer
import
org.jetbrains.skiko.SkiaLayerProperties
internal
class
Direct3DRedrawer
(
private
val
layer
:
HardwareLayer
,
private
val
properties
:
SkiaLayerProperties
)
:
Redrawer
{
private
var
isDisposed
=
false
private
var
device
:
Long
=
0
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
()
}
fun
makeContext
(
device
:
Long
)
=
DirectContext
(
makeDirectXContext
(
device
)
)
fun
makeRenderTarget
(
device
:
Long
,
width
:
Int
,
height
:
Int
)
=
BackendRenderTarget
(
makeDirectXRenderTarget
(
device
,
width
,
height
)
)
fun
createDevice
():
Long
{
device
=
createDirectXDevice
(
layer
.
windowHandle
)
return
device
}
fun
finishFrame
(
device
:
Long
,
context
:
Long
,
surface
:
Long
)
{
finishFrame
(
device
,
context
,
surface
,
properties
.
isVsyncEnabled
)
}
external
fun
createDirectXDevice
(
windowHandle
:
Long
):
Long
external
fun
makeDirectXContext
(
device
:
Long
):
Long
external
fun
makeDirectXRenderTarget
(
device
:
Long
,
width
:
Int
,
height
:
Int
):
Long
external
fun
resizeBuffers
(
device
:
Long
,
width
:
Int
,
height
:
Int
)
private
external
fun
finishFrame
(
device
:
Long
,
context
:
Long
,
surface
:
Long
,
isVsyncEnabled
:
Boolean
)
external
fun
disposeDevice
(
device
:
Long
)
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/
Raster
Redrawer.kt
→
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/
Software
Redrawer.kt
View file @
f1ce1d44
...
...
@@ -5,7 +5,7 @@ import kotlinx.coroutines.swing.Swing
import
org.jetbrains.skiko.FrameDispatcher
import
org.jetbrains.skiko.HardwareLayer
internal
class
Raster
Redrawer
(
internal
class
Software
Redrawer
(
private
val
layer
:
HardwareLayer
)
:
Redrawer
{
...
...
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