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
620547af
Commit
620547af
authored
Jan 13, 2021
by
Igor Demin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support vsync
parent
f970ae3d
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
829 additions
and
616 deletions
+829
-616
App.kt
...kijaInjectSample/src/main/kotlin/SkijaInjectSample/App.kt
+4
-2
SwingSkia.kt
...jectSample/src/main/kotlin/SkijaInjectSample/SwingSkia.kt
+0
-1
build.gradle.kts
skiko/build.gradle.kts
+1
-0
drawlayer.cc
skiko/src/jvmMain/cpp/linux/drawlayer.cc
+2
-185
redrawer.cc
skiko/src/jvmMain/cpp/linux/redrawer.cc
+142
-0
drawlayer.cc
skiko/src/jvmMain/cpp/windows/drawlayer.cc
+2
-173
redrawer.cc
skiko/src/jvmMain/cpp/windows/redrawer.cc
+92
-0
Drawable.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Drawable.kt
+0
-9
FrameDispatcher.kt
...src/jvmMain/kotlin/org/jetbrains/skiko/FrameDispatcher.kt
+34
-0
HardwareLayer.kt
...o/src/jvmMain/kotlin/org/jetbrains/skiko/HardwareLayer.kt
+11
-23
PlatformOperations.kt
.../jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
+11
-0
SkiaLayer.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
+28
-13
SkiaWindow.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaWindow.kt
+0
-4
LinuxRedrawer.kt
...Main/kotlin/org/jetbrains/skiko/redrawer/LinuxRedrawer.kt
+110
-0
MacOsRedrawer.kt
...Main/kotlin/org/jetbrains/skiko/redrawer/MacOsRedrawer.kt
+127
-0
Redrawer.kt
...c/jvmMain/kotlin/org/jetbrains/skiko/redrawer/Redrawer.kt
+7
-0
WindowsRedrawer.kt
...in/kotlin/org/jetbrains/skiko/redrawer/WindowsRedrawer.kt
+88
-0
drawlayer.m
skiko/src/jvmMain/objectiveC/macos/drawlayer.m
+9
-206
redrawer.m
skiko/src/jvmMain/objectiveC/macos/redrawer.m
+161
-0
No files found.
samples/SkijaInjectSample/src/main/kotlin/SkijaInjectSample/App.kt
View file @
620547af
...
@@ -15,7 +15,9 @@ import kotlin.math.cos
...
@@ -15,7 +15,9 @@ import kotlin.math.cos
import
kotlin.math.sin
import
kotlin.math.sin
fun
main
(
args
:
Array
<
String
>)
{
fun
main
(
args
:
Array
<
String
>)
{
createWindow
(
"First window"
)
repeat
(
1
)
{
createWindow
(
"window $it"
)
}
}
}
fun
createWindow
(
title
:
String
)
=
SwingUtilities
.
invokeLater
{
fun
createWindow
(
title
:
String
)
=
SwingUtilities
.
invokeLater
{
...
@@ -65,7 +67,6 @@ fun createWindow(title: String) = SwingUtilities.invokeLater {
...
@@ -65,7 +67,6 @@ fun createWindow(title: String) = SwingUtilities.invokeLater {
override
fun
mouseMoved
(
event
:
MouseEvent
)
{
override
fun
mouseMoved
(
event
:
MouseEvent
)
{
mouseX
=
event
.
x
mouseX
=
event
.
x
mouseY
=
event
.
y
mouseY
=
event
.
y
window
.
display
()
}
}
})
})
...
@@ -93,6 +94,7 @@ class Renderer(
...
@@ -93,6 +94,7 @@ class Renderer(
val
contentScale
=
layer
.
contentScale
val
contentScale
=
layer
.
contentScale
canvas
.
scale
(
contentScale
,
contentScale
)
canvas
.
scale
(
contentScale
,
contentScale
)
displayScene
(
this
,
(
width
/
contentScale
).
toInt
(),
(
height
/
contentScale
).
toInt
(),
nanoTime
)
displayScene
(
this
,
(
width
/
contentScale
).
toInt
(),
(
height
/
contentScale
).
toInt
(),
nanoTime
)
layer
.
needRedraw
()
}
}
}
}
...
...
samples/SkijaInjectSample/src/main/kotlin/SkijaInjectSample/SwingSkia.kt
View file @
620547af
...
@@ -69,7 +69,6 @@ fun SwingSkia() {
...
@@ -69,7 +69,6 @@ fun SwingSkia() {
override
fun
mouseMoved
(
event
:
MouseEvent
)
{
override
fun
mouseMoved
(
event
:
MouseEvent
)
{
mouseX
=
event
.
x
mouseX
=
event
.
x
mouseY
=
event
.
y
mouseY
=
event
.
y
panel
.
layer
.
display
()
}
}
})
})
...
...
skiko/build.gradle.kts
View file @
620547af
...
@@ -370,6 +370,7 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach {
...
@@ -370,6 +370,7 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach {
linkerArgs
.
addAll
(
linkerArgs
.
addAll
(
listOf
(
listOf
(
"gdi32.lib"
,
"gdi32.lib"
,
"Dwmapi.lib"
,
"opengl32.lib"
,
"opengl32.lib"
,
"shcore.lib"
,
"shcore.lib"
,
"user32.lib"
"user32.lib"
...
...
skiko/src/jvmMain/cpp/linux/drawlayer.cc
View file @
620547af
// drawcanvas.cpp : Defines the exported functions for the DLL application.
#include <jawt_md.h>
#include <jawt_md.h>
#include <GL/gl.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glx.h>
...
@@ -8,191 +7,19 @@
...
@@ -8,191 +7,19 @@
#include <cstdlib>
#include <cstdlib>
#include <unistd.h>
#include <unistd.h>
#include <stdio.h>
#include <stdio.h>
#include <set>
using
namespace
std
;
typedef
GLXContext
(
*
glXCreateContextAttribsARBProc
)(
Display
*
,
GLXFBConfig
,
GLXContext
,
Bool
,
const
int
*
);
typedef
GLXContext
(
*
glXCreateContextAttribsARBProc
)(
Display
*
,
GLXFBConfig
,
GLXContext
,
Bool
,
const
int
*
);
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
JavaVM
*
jvm
=
NULL
;
class
LayerHandler
{
public
:
jobject
canvasGlobalRef
;
GLXContext
context
;
void
updateLayerContent
()
{
draw
();
}
void
disposeLayer
(
JNIEnv
*
env
)
{
env
->
DeleteGlobalRef
(
canvasGlobalRef
);
canvasGlobalRef
=
NULL
;
context
=
NULL
;
}
private
:
void
draw
()
{
if
(
jvm
!=
NULL
)
{
JNIEnv
*
env
;
jvm
->
GetEnv
((
void
**
)
&
env
,
JNI_VERSION_10
);
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
JAWT_X11DrawingSurfaceInfo
*
dsi_x11
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
result
=
Skiko_GetAWT
(
env
,
&
awt
);
if
(
result
==
JNI_FALSE
)
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
;
}
ds
=
awt
.
GetDrawingSurface
(
env
,
canvasGlobalRef
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi_x11
=
(
JAWT_X11DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
Display
*
display
=
dsi_x11
->
display
;
Window
window
=
dsi_x11
->
drawable
;
if
(
dsi
!=
NULL
)
{
jvm
->
AttachCurrentThread
((
void
**
)
&
env
,
NULL
);
glXMakeCurrent
(
display
,
window
,
context
);
static
jclass
wndClass
=
NULL
;
if
(
!
wndClass
)
wndClass
=
env
->
GetObjectClass
(
canvasGlobalRef
);
static
jmethodID
drawMethod
=
NULL
;
if
(
!
drawMethod
)
drawMethod
=
env
->
GetMethodID
(
wndClass
,
"draw"
,
"()V"
);
if
(
NULL
==
drawMethod
)
{
fprintf
(
stderr
,
"The method Window.draw() not found!
\n
"
);
return
;
}
env
->
CallVoidMethod
(
canvasGlobalRef
,
drawMethod
);
glFinish
();
glXSwapBuffers
(
display
,
window
);
}
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
}
}
};
set
<
LayerHandler
*>
*
layerStorage
=
NULL
;
LayerHandler
*
findByObject
(
JNIEnv
*
env
,
jobject
object
)
{
if
(
layerStorage
==
NULL
)
{
return
NULL
;
}
for
(
auto
&
layer
:
*
layerStorage
)
{
if
(
env
->
IsSameObject
(
object
,
layer
->
canvasGlobalRef
)
==
JNI_TRUE
)
{
return
layer
;
}
}
return
NULL
;
}
extern
"C"
extern
"C"
{
{
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_
updateLayer
(
JNIEnv
*
env
,
jobject
canvas
)
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_
init
(
JNIEnv
*
env
,
jobject
canvas
)
{
{
if
(
layerStorage
!=
NULL
)
{
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
return
;
}
}
else
{
layerStorage
=
new
set
<
LayerHandler
*>
();
}
if
(
jvm
==
NULL
)
{
env
->
GetJavaVM
(
&
jvm
);
}
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
JAWT_X11DrawingSurfaceInfo
*
dsi_x11
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
result
=
Skiko_GetAWT
(
env
,
&
awt
);
if
(
result
==
JNI_FALSE
)
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
;
}
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi_x11
=
(
JAWT_X11DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
Display
*
display
=
dsi_x11
->
display
;
Window
window
=
dsi_x11
->
drawable
;
if
(
dsi
!=
NULL
)
{
GLint
att
[]
=
{
GLX_RGBA
,
GLX_DOUBLEBUFFER
,
True
,
None
};
XVisualInfo
*
vi
=
glXChooseVisual
(
display
,
0
,
att
);
GLXContext
context
=
glXCreateContext
(
display
,
vi
,
NULL
,
GL_TRUE
);
LayerHandler
*
layer
=
new
LayerHandler
();
layerStorage
->
insert
(
layer
);
jobject
canvasRef
=
env
->
NewGlobalRef
(
canvas
);
layer
->
canvasGlobalRef
=
canvasRef
;
layer
->
context
=
context
;
}
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_
redrawLayer
(
JNIEnv
*
env
,
jobject
canvas
)
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_
dispose
(
JNIEnv
*
env
,
jobject
canvas
)
{
{
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
layer
->
updateLayerContent
();
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_disposeLayer
(
JNIEnv
*
env
,
jobject
canvas
)
{
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
layerStorage
->
erase
(
layer
);
layer
->
disposeLayer
(
env
);
delete
layer
;
}
}
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle
(
JNIEnv
*
env
,
jobject
canvas
)
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle
(
JNIEnv
*
env
,
jobject
canvas
)
...
@@ -214,11 +41,6 @@ extern "C"
...
@@ -214,11 +41,6 @@ extern "C"
return
-
1
;
return
-
1
;
}
}
if
(
jvm
==
NULL
)
{
env
->
GetJavaVM
(
&
jvm
);
}
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
lock
=
ds
->
Lock
(
ds
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
...
@@ -274,11 +96,6 @@ extern "C"
...
@@ -274,11 +96,6 @@ extern "C"
return
-
1
;
return
-
1
;
}
}
if
(
jvm
==
NULL
)
{
env
->
GetJavaVM
(
&
jvm
);
}
ds
=
awt
.
GetDrawingSurface
(
env
,
component
);
ds
=
awt
.
GetDrawingSurface
(
env
,
component
);
lock
=
ds
->
Lock
(
ds
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
...
...
skiko/src/jvmMain/cpp/linux/redrawer.cc
0 → 100644
View file @
620547af
#include <jawt_md.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <cstdlib>
#include <unistd.h>
#include <stdio.h>
typedef
GLXContext
(
*
glXCreateContextAttribsARBProc
)(
Display
*
,
GLXFBConfig
,
GLXContext
,
Bool
,
const
int
*
);
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
extern
"C"
{
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_lockDrawingSurfaceNative
(
JNIEnv
*
env
,
jobject
redrawer
,
jobject
layer
)
{
JAWT
awt
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
if
(
!
Skiko_GetAWT
(
env
,
&
awt
))
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
0
;
}
JAWT_DrawingSurface
*
ds
=
awt
.
GetDrawingSurface
(
env
,
layer
);
ds
->
Lock
(
ds
);
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
ds
));
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_unlockDrawingSurfaceNative
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
drawingSurfacePtr
)
{
JAWT_DrawingSurface
*
ds
=
reinterpret_cast
<
JAWT_DrawingSurface
*>
(
static_cast
<
uintptr_t
>
(
drawingSurfacePtr
));
JAWT
awt
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
if
(
!
Skiko_GetAWT
(
env
,
&
awt
))
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
0
;
}
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
ds
));
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_getDisplay
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
drawingSurfacePtr
)
{
JAWT_DrawingSurface
*
ds
=
reinterpret_cast
<
JAWT_DrawingSurface
*>
(
static_cast
<
uintptr_t
>
(
drawingSurfacePtr
));
JAWT_DrawingSurfaceInfo
*
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
JAWT_X11DrawingSurfaceInfo
*
dsi_x11
=
(
JAWT_X11DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
Display
*
display
=
dsi_x11
->
display
;
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
display
));
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_getWindow
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
drawingSurfacePtr
)
{
JAWT_DrawingSurface
*
ds
=
reinterpret_cast
<
JAWT_DrawingSurface
*>
(
static_cast
<
uintptr_t
>
(
drawingSurfacePtr
));
JAWT_DrawingSurfaceInfo
*
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
JAWT_X11DrawingSurfaceInfo
*
dsi_x11
=
(
JAWT_X11DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
Window
window
=
dsi_x11
->
drawable
;
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
window
));
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_setSwapInterval
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
displayPtr
,
jlong
windowPtr
,
jint
interval
)
{
Display
*
display
=
reinterpret_cast
<
Display
*>
(
static_cast
<
uintptr_t
>
(
displayPtr
));
Window
window
=
reinterpret_cast
<
Window
>
(
static_cast
<
uintptr_t
>
(
windowPtr
));
// according to:
// https://opengl.gpuinfo.org/listreports.php?extension=GLX_EXT_swap_control
// https://opengl.gpuinfo.org/listreports.php?extension=GLX_MESA_swap_control
// https://opengl.gpuinfo.org/listreports.php?extension=GLX_SGI_swap_control
// there is no Linux that doesn't support at least one of these extensions
static
PFNGLXSWAPINTERVALEXTPROC
glXSwapIntervalEXT
=
(
PFNGLXSWAPINTERVALEXTPROC
)
glXGetProcAddress
((
const
GLubyte
*
)
"glXSwapIntervalEXT"
);
if
(
glXSwapIntervalEXT
!=
NULL
)
{
glXSwapIntervalEXT
(
display
,
window
,
interval
);
}
else
{
static
PFNGLXSWAPINTERVALMESAPROC
glXSwapIntervalMESA
=
(
PFNGLXSWAPINTERVALMESAPROC
)
glXGetProcAddress
((
const
GLubyte
*
)
"glXSwapIntervalMESA"
);
if
(
glXSwapIntervalMESA
!=
NULL
)
{
glXSwapIntervalMESA
(
interval
);
}
else
{
static
PFNGLXSWAPINTERVALSGIPROC
glXSwapIntervalSGI
=
(
PFNGLXSWAPINTERVALSGIPROC
)
glXGetProcAddress
((
const
GLubyte
*
)
"glXSwapIntervalSGI"
);
if
(
glXSwapIntervalSGI
!=
NULL
)
{
glXSwapIntervalSGI
(
interval
);
}
}
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_swapBuffers
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
displayPtr
,
jlong
windowPtr
)
{
Display
*
display
=
reinterpret_cast
<
Display
*>
(
static_cast
<
uintptr_t
>
(
displayPtr
));
Window
window
=
reinterpret_cast
<
Window
>
(
static_cast
<
uintptr_t
>
(
windowPtr
));
glXSwapBuffers
(
display
,
window
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_makeCurrent
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
displayPtr
,
jlong
windowPtr
,
jlong
contextPtr
)
{
Display
*
display
=
reinterpret_cast
<
Display
*>
(
static_cast
<
uintptr_t
>
(
displayPtr
));
Window
window
=
reinterpret_cast
<
Window
>
(
static_cast
<
uintptr_t
>
(
windowPtr
));
GLXContext
*
context
=
reinterpret_cast
<
GLXContext
*>
(
static_cast
<
uintptr_t
>
(
contextPtr
));
glXMakeCurrent
(
display
,
window
,
*
context
);
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_createContext
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
displayPtr
)
{
Display
*
display
=
reinterpret_cast
<
Display
*>
(
static_cast
<
uintptr_t
>
(
displayPtr
));
GLint
att
[]
=
{
GLX_RGBA
,
GLX_DOUBLEBUFFER
,
True
,
None
};
XVisualInfo
*
vi
=
glXChooseVisual
(
display
,
0
,
att
);
GLXContext
*
context
=
new
GLXContext
(
glXCreateContext
(
display
,
vi
,
NULL
,
GL_TRUE
));
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
context
));
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_LinuxRedrawerKt_destroyContext
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
displayPtr
,
jlong
contextPtr
)
{
Display
*
display
=
reinterpret_cast
<
Display
*>
(
static_cast
<
uintptr_t
>
(
displayPtr
));
GLXContext
*
context
=
reinterpret_cast
<
GLXContext
*>
(
static_cast
<
uintptr_t
>
(
contextPtr
));
glXDestroyContext
(
display
,
*
context
);
delete
context
;
}
}
\ No newline at end of file
skiko/src/jvmMain/cpp/windows/drawlayer.cc
View file @
620547af
// drawcanvas.cpp : Defines the exported functions for the DLL application.
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl/GL.h>
#include <jawt_md.h>
#include <jawt_md.h>
#include <set>
#include <Shellscalingapi.h>
#include <stdio.h>
#include <Wingdi.h>
using
namespace
std
;
JavaVM
*
jvm
=
NULL
;
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
class
LayerHandler
{
public
:
jobject
canvasGlobalRef
;
HGLRC
context
;
HDC
device
;
void
updateLayerContent
()
{
draw
();
}
void
disposeLayer
(
JNIEnv
*
env
)
{
env
->
DeleteGlobalRef
(
canvasGlobalRef
);
canvasGlobalRef
=
NULL
;
context
=
NULL
;
device
=
NULL
;
}
private
:
void
draw
()
{
if
(
jvm
!=
NULL
)
{
JNIEnv
*
env
;
jvm
->
GetEnv
((
void
**
)
&
env
,
JNI_VERSION_10
);
wglMakeCurrent
(
device
,
context
);
static
jclass
wndClass
=
NULL
;
if
(
!
wndClass
)
wndClass
=
env
->
GetObjectClass
(
canvasGlobalRef
);
static
jmethodID
drawMethod
=
NULL
;
if
(
!
drawMethod
)
drawMethod
=
env
->
GetMethodID
(
wndClass
,
"draw"
,
"()V"
);
if
(
NULL
==
drawMethod
)
{
fprintf
(
stderr
,
"The method Window.draw() not found!
\n
"
);
return
;
}
env
->
CallVoidMethod
(
canvasGlobalRef
,
drawMethod
);
glFinish
();
SwapBuffers
(
device
);
}
}
};
set
<
LayerHandler
*>
*
layerStorage
=
NULL
;
LayerHandler
*
findByObject
(
JNIEnv
*
env
,
jobject
object
)
{
if
(
layerStorage
==
NULL
)
{
return
NULL
;
}
for
(
auto
&
layer
:
*
layerStorage
)
{
if
(
env
->
IsSameObject
(
object
,
layer
->
canvasGlobalRef
)
==
JNI_TRUE
)
{
return
layer
;
}
}
return
NULL
;
}
extern
"C"
extern
"C"
{
{
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_updateLayer
(
JNIEnv
*
env
,
jobject
canvas
)
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_init
(
JNIEnv
*
env
,
jobject
canvas
)
{
if
(
layerStorage
!=
NULL
)
{
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
return
;
}
}
else
{
{
layerStorage
=
new
set
<
LayerHandler
*>
();
}
}
JAWT
awt
;
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_dispose
(
JNIEnv
*
env
,
jobject
canvas
)
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
PIXELFORMATDESCRIPTOR
pixFormatDscr
;
HGLRC
context
=
NULL
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
JAWT_Win32DrawingSurfaceInfo
*
dsi_win
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
result
=
Skiko_GetAWT
(
env
,
&
awt
);
if
(
result
==
JNI_FALSE
)
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
;
}
if
(
jvm
==
NULL
)
{
env
->
GetJavaVM
(
&
jvm
);
}
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi_win
=
(
JAWT_Win32DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
HWND
hwnd
=
dsi_win
->
hwnd
;
HDC
device
=
GetDC
(
hwnd
);
if
(
dsi
!=
NULL
)
{
memset
(
&
pixFormatDscr
,
0
,
sizeof
(
PIXELFORMATDESCRIPTOR
));
pixFormatDscr
.
nSize
=
sizeof
(
PIXELFORMATDESCRIPTOR
);
pixFormatDscr
.
nVersion
=
1
;
pixFormatDscr
.
dwFlags
=
PFD_DRAW_TO_WINDOW
|
PFD_SUPPORT_OPENGL
|
PFD_DOUBLEBUFFER
;
pixFormatDscr
.
iPixelType
=
PFD_TYPE_RGBA
;
pixFormatDscr
.
cColorBits
=
32
;
int
iPixelFormat
=
ChoosePixelFormat
(
device
,
&
pixFormatDscr
);
SetPixelFormat
(
device
,
iPixelFormat
,
&
pixFormatDscr
);
DescribePixelFormat
(
device
,
iPixelFormat
,
sizeof
(
PIXELFORMATDESCRIPTOR
),
&
pixFormatDscr
);
context
=
wglCreateContext
(
device
);
LayerHandler
*
layer
=
new
LayerHandler
();
layerStorage
->
insert
(
layer
);
jobject
canvasRef
=
env
->
NewGlobalRef
(
canvas
);
layer
->
canvasGlobalRef
=
canvasRef
;
layer
->
context
=
context
;
layer
->
device
=
device
;
}
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_redrawLayer
(
JNIEnv
*
env
,
jobject
canvas
)
{
{
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
layer
->
updateLayerContent
();
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_disposeLayer
(
JNIEnv
*
env
,
jobject
canvas
)
{
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
layerStorage
->
erase
(
layer
);
layer
->
disposeLayer
(
env
);
delete
layer
;
}
}
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle
(
JNIEnv
*
env
,
jobject
canvas
)
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle
(
JNIEnv
*
env
,
jobject
canvas
)
...
@@ -182,8 +18,6 @@ extern "C"
...
@@ -182,8 +18,6 @@ extern "C"
JAWT
awt
;
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
PIXELFORMATDESCRIPTOR
pixFormatDscr
;
HGLRC
context
=
NULL
;
jboolean
result
=
JNI_FALSE
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
jint
lock
=
0
;
...
@@ -198,11 +32,6 @@ extern "C"
...
@@ -198,11 +32,6 @@ extern "C"
return
-
1
;
return
-
1
;
}
}
if
(
jvm
==
NULL
)
{
env
->
GetJavaVM
(
&
jvm
);
}
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
lock
=
ds
->
Lock
(
ds
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
...
...
skiko/src/jvmMain/cpp/windows/redrawer.cc
0 → 100644
View file @
620547af
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl/GL.h>
#include <jawt_md.h>
#include <dwmapi.h>
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
extern
"C"
{
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_getDevice
(
JNIEnv
*
env
,
jobject
redrawer
,
jobject
layer
)
{
JAWT
awt
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
if
(
!
Skiko_GetAWT
(
env
,
&
awt
))
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
0
;
}
JAWT_DrawingSurface
*
ds
=
awt
.
GetDrawingSurface
(
env
,
layer
);
ds
->
Lock
(
ds
);
JAWT_DrawingSurfaceInfo
*
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
JAWT_Win32DrawingSurfaceInfo
*
dsi_win
=
(
JAWT_Win32DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
HWND
hwnd
=
dsi_win
->
hwnd
;
HDC
device
=
GetDC
(
hwnd
);
if
(
dsi
!=
NULL
)
{
PIXELFORMATDESCRIPTOR
pixFormatDscr
;
memset
(
&
pixFormatDscr
,
0
,
sizeof
(
PIXELFORMATDESCRIPTOR
));
pixFormatDscr
.
nSize
=
sizeof
(
PIXELFORMATDESCRIPTOR
);
pixFormatDscr
.
nVersion
=
1
;
pixFormatDscr
.
dwFlags
=
PFD_DRAW_TO_WINDOW
|
PFD_SUPPORT_OPENGL
|
PFD_DOUBLEBUFFER
;
pixFormatDscr
.
iPixelType
=
PFD_TYPE_RGBA
;
pixFormatDscr
.
cColorBits
=
32
;
int
iPixelFormat
=
ChoosePixelFormat
(
device
,
&
pixFormatDscr
);
SetPixelFormat
(
device
,
iPixelFormat
,
&
pixFormatDscr
);
DescribePixelFormat
(
device
,
iPixelFormat
,
sizeof
(
PIXELFORMATDESCRIPTOR
),
&
pixFormatDscr
);
}
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
device
));
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_setSwapInterval
(
JNIEnv
*
env
,
jobject
redrawer
,
jint
interval
)
{
typedef
BOOL
(
WINAPI
*
PFNWGLSWAPINTERVALEXTPROC
)(
int
interval
);
// according to [https://opengl.gpuinfo.org/listreports.php?extension=WGL_EXT_swap_control&option=not] (filter by OS=windows)
// there a very few devices that doesn't support swap control
static
PFNWGLSWAPINTERVALEXTPROC
wglSwapIntervalEXT
=
(
PFNWGLSWAPINTERVALEXTPROC
)
wglGetProcAddress
(
"wglSwapIntervalEXT"
);
if
(
wglSwapIntervalEXT
!=
NULL
)
{
wglSwapIntervalEXT
(
interval
);
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_swapBuffers
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
)
{
HDC
device
=
reinterpret_cast
<
HDC
>
(
static_cast
<
uintptr_t
>
(
devicePtr
));
SwapBuffers
(
device
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_makeCurrent
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
,
jlong
contextPtr
)
{
HDC
device
=
reinterpret_cast
<
HDC
>
(
static_cast
<
uintptr_t
>
(
devicePtr
));
HGLRC
context
=
reinterpret_cast
<
HGLRC
>
(
static_cast
<
uintptr_t
>
(
contextPtr
));
wglMakeCurrent
(
device
,
context
);
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_createContext
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
devicePtr
)
{
HDC
device
=
reinterpret_cast
<
HDC
>
(
static_cast
<
uintptr_t
>
(
devicePtr
));
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
wglCreateContext
(
device
)));
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_deleteContext
(
JNIEnv
*
env
,
jobject
redrawer
,
jlong
contextPtr
)
{
HGLRC
context
=
reinterpret_cast
<
HGLRC
>
(
static_cast
<
uintptr_t
>
(
contextPtr
));
wglDeleteContext
(
context
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_WindowsRedrawerKt_dwmFlush
(
JNIEnv
*
env
,
jobject
redrawer
)
{
DwmFlush
();
}
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Drawable.kt
deleted
100755 → 0
View file @
f970ae3d
package
org.jetbrains.skiko
interface
Drawable
{
fun
redrawLayer
()
fun
updateLayer
()
fun
disposeLayer
()
val
windowHandle
:
Long
val
contentScale
:
Float
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/FrameDispatcher.kt
0 → 100644
View file @
620547af
package
org.jetbrains.skiko
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.yield
import
kotlin.coroutines.CoroutineContext
/**
* Dispatch frame after call of [scheduleFrame]
*/
class
FrameDispatcher
(
context
:
CoroutineContext
,
private
val
onFrame
:
suspend
()
->
Unit
)
{
private
var
needFrame
=
CompletableDeferred
<
Unit
>()
private
val
job
=
GlobalScope
.
launch
(
context
)
{
while
(
true
)
{
needFrame
.
await
()
needFrame
=
CompletableDeferred
()
onFrame
()
yield
()
}
}
fun
cancel
()
{
job
.
cancel
()
}
fun
scheduleFrame
()
{
needFrame
.
complete
(
Unit
)
}
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/HardwareLayer.kt
View file @
620547af
...
@@ -3,10 +3,8 @@ package org.jetbrains.skiko
...
@@ -3,10 +3,8 @@ package org.jetbrains.skiko
import
java.awt.Canvas
import
java.awt.Canvas
import
java.awt.Graphics
import
java.awt.Graphics
import
java.awt.event.HierarchyEvent
import
java.awt.event.HierarchyEvent
import
javax.swing.SwingUtilities.convertPoint
import
javax.swing.SwingUtilities.getRootPane
abstract
class
HardwareLayer
:
Canvas
()
,
Drawable
{
abstract
class
HardwareLayer
:
Canvas
()
{
companion
object
{
companion
object
{
init
{
init
{
Library
.
load
()
Library
.
load
()
...
@@ -29,10 +27,14 @@ abstract class HardwareLayer : Canvas(), Drawable {
...
@@ -29,10 +27,14 @@ abstract class HardwareLayer : Canvas(), Drawable {
private
fun
checkIsShowing
()
{
private
fun
checkIsShowing
()
{
if
(!
isInit
&&
isShowing
)
{
if
(!
isInit
&&
isShowing
)
{
_contentScale
=
platformOperations
.
getDpiScale
(
this
)
_contentScale
=
platformOperations
.
getDpiScale
(
this
)
init
()
isInit
=
true
isInit
=
true
}
}
}
}
protected
open
external
fun
init
()
open
external
fun
dispose
()
protected
open
fun
contentScaleChanged
()
=
Unit
protected
open
fun
contentScaleChanged
()
=
Unit
override
fun
paint
(
g
:
Graphics
)
{
override
fun
paint
(
g
:
Graphics
)
{
...
@@ -41,34 +43,20 @@ abstract class HardwareLayer : Canvas(), Drawable {
...
@@ -41,34 +43,20 @@ abstract class HardwareLayer : Canvas(), Drawable {
_contentScale
=
contentScale
_contentScale
=
contentScale
contentScaleChanged
()
contentScaleChanged
()
}
}
display
()
}
open
fun
display
()
{
this
.
updateLayer
()
this
.
redrawLayer
()
}
}
open
fun
draw
()
{}
// Should be called in Swing thread
internal
abstract
suspend
fun
update
(
nanoTime
:
Long
)
external
override
fun
redrawLayer
()
external
override
fun
updateLayer
()
// Should be called in the OpenGL thread, and only once after update
internal
abstract
fun
draw
()
external
override
fun
disposeLayer
()
val
windowHandle
:
Long
override
val
windowHandle
:
Long
external
get
external
get
override
val
contentScale
:
Float
val
contentScale
:
Float
get
()
=
_contentScale
!!
get
()
=
_contentScale
!!
val
absoluteX
:
Int
get
()
=
convertPoint
(
this
,
x
,
y
,
getRootPane
(
this
)).
x
val
absoluteY
:
Int
get
()
=
convertPoint
(
this
,
x
,
y
,
getRootPane
(
this
)).
y
var
fullscreen
:
Boolean
var
fullscreen
:
Boolean
get
()
=
platformOperations
.
isFullscreen
(
this
)
get
()
=
platformOperations
.
isFullscreen
(
this
)
set
(
value
)
=
platformOperations
.
setFullscreen
(
this
,
value
)
set
(
value
)
=
platformOperations
.
setFullscreen
(
this
,
value
)
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/PlatformOperations.kt
View file @
620547af
package
org.jetbrains.skiko
package
org.jetbrains.skiko
import
org.jetbrains.skiko.redrawer.LinuxRedrawer
import
org.jetbrains.skiko.redrawer.MacOsRedrawer
import
org.jetbrains.skiko.redrawer.Redrawer
import
org.jetbrains.skiko.redrawer.WindowsRedrawer
import
java.awt.Component
import
java.awt.Component
import
java.awt.Window
import
java.awt.Window
import
javax.swing.SwingUtilities
import
javax.swing.SwingUtilities
...
@@ -8,6 +12,7 @@ internal interface PlatformOperations {
...
@@ -8,6 +12,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
createHardwareRedrawer
(
layer
:
HardwareLayer
):
Redrawer
}
}
internal
val
platformOperations
:
PlatformOperations
by
lazy
{
internal
val
platformOperations
:
PlatformOperations
by
lazy
{
...
@@ -24,6 +29,8 @@ internal val platformOperations: PlatformOperations by lazy {
...
@@ -24,6 +29,8 @@ internal val platformOperations: PlatformOperations by lazy {
override
fun
getDpiScale
(
component
:
Component
):
Float
{
override
fun
getDpiScale
(
component
:
Component
):
Float
{
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
MacOsRedrawer
(
layer
)
}
}
OS
.
Windows
->
{
OS
.
Windows
->
{
object
:
PlatformOperations
{
object
:
PlatformOperations
{
...
@@ -42,6 +49,8 @@ internal val platformOperations: PlatformOperations by lazy {
...
@@ -42,6 +49,8 @@ internal val platformOperations: PlatformOperations by lazy {
override
fun
getDpiScale
(
component
:
Component
):
Float
{
override
fun
getDpiScale
(
component
:
Component
):
Float
{
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
return
component
.
graphicsConfiguration
.
defaultTransform
.
scaleX
.
toFloat
()
}
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
WindowsRedrawer
(
layer
)
}
}
}
}
OS
.
Linux
->
{
OS
.
Linux
->
{
...
@@ -61,6 +70,8 @@ internal val platformOperations: PlatformOperations by lazy {
...
@@ -61,6 +70,8 @@ internal val platformOperations: PlatformOperations by lazy {
override
fun
getDpiScale
(
component
:
Component
):
Float
{
override
fun
getDpiScale
(
component
:
Component
):
Float
{
return
linuxGetDpiScaleNative
(
component
)
return
linuxGetDpiScaleNative
(
component
)
}
}
override
fun
createHardwareRedrawer
(
layer
:
HardwareLayer
)
=
LinuxRedrawer
(
layer
)
}
}
}
}
}
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt
View file @
620547af
package
org.jetbrains.skiko
package
org.jetbrains.skiko
import
kotlinx.coroutines.runBlocking
import
org.jetbrains.skija.*
import
org.jetbrains.skija.*
import
org.jetbrains.skiko.redrawer.Redrawer
import
java.awt.Graphics
import
javax.swing.SwingUtilities.isEventDispatchThread
import
javax.swing.SwingUtilities.isEventDispatchThread
private
class
SkijaState
{
private
class
SkijaState
{
...
@@ -33,19 +34,40 @@ open class SkiaLayer : HardwareLayer() {
...
@@ -33,19 +34,40 @@ open class SkiaLayer : HardwareLayer() {
@Volatile
@Volatile
private
var
isDisposed
=
false
private
var
isDisposed
=
false
private
var
redrawer
:
Redrawer
?
=
null
@Volatile
@Volatile
private
var
picture
:
PictureHolder
?
=
null
private
var
picture
:
PictureHolder
?
=
null
private
val
pictureRecorder
=
PictureRecorder
()
private
val
pictureRecorder
=
PictureRecorder
()
private
val
pictureLock
=
Any
()
private
val
pictureLock
=
Any
()
override
fun
disposeLayer
()
{
override
fun
init
()
{
redrawer
=
platformOperations
.
createHardwareRedrawer
(
this
)
redrawer
?.
syncSize
()
needRedraw
()
}
override
fun
dispose
()
{
check
(!
isDisposed
)
check
(!
isDisposed
)
check
(
isEventDispatchThread
())
check
(
isEventDispatchThread
())
redrawer
?.
dispose
()
picture
?.
instance
?.
close
()
picture
?.
instance
?.
close
()
pictureRecorder
.
close
()
pictureRecorder
.
close
()
isDisposed
=
true
isDisposed
=
true
super
.
disposeLayer
()
super
.
dispose
()
}
override
fun
paint
(
g
:
Graphics
)
{
super
.
paint
(
g
)
// we don't have to call it in setBounds method, because paint will always be called after setBounds
redrawer
?.
syncSize
()
needRedraw
()
}
fun
needRedraw
()
{
check
(!
isDisposed
)
check
(
isEventDispatchThread
())
redrawer
?.
needRedraw
()
}
}
private
val
fpsCounter
=
FPSCounter
(
private
val
fpsCounter
=
FPSCounter
(
...
@@ -53,16 +75,9 @@ open class SkiaLayer : HardwareLayer() {
...
@@ -53,16 +75,9 @@ open class SkiaLayer : HardwareLayer() {
probability
=
System
.
getProperty
(
"skiko.fps.probability"
)
?.
toDouble
()
?:
0.97
probability
=
System
.
getProperty
(
"skiko.fps.probability"
)
?.
toDouble
()
?:
0.97
)
)
override
fun
draw
()
{
override
suspend
fun
update
(
nanoTime
:
Long
)
{
runBlocking
{
performUpdate
(
System
.
nanoTime
())
}
performDraw
()
}
private
suspend
fun
performUpdate
(
nanoTime
:
Long
)
{
check
(!
isDisposed
)
check
(!
isDisposed
)
//check(isEventDispatchThread()) // TODO run from AWT Thread
check
(
isEventDispatchThread
())
if
(
System
.
getProperty
(
"skiko.fps.enabled"
)
==
"true"
)
{
if
(
System
.
getProperty
(
"skiko.fps.enabled"
)
==
"true"
)
{
fpsCounter
.
tick
()
fpsCounter
.
tick
()
...
@@ -88,7 +103,7 @@ open class SkiaLayer : HardwareLayer() {
...
@@ -88,7 +103,7 @@ open class SkiaLayer : HardwareLayer() {
}
}
}
}
private
fun
performD
raw
()
{
override
fun
d
raw
()
{
check
(!
isDisposed
)
check
(!
isDisposed
)
if
(
skijaState
.
context
==
null
)
{
if
(
skijaState
.
context
==
null
)
{
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaWindow.kt
View file @
620547af
...
@@ -10,8 +10,4 @@ open class SkiaWindow : JFrame() {
...
@@ -10,8 +10,4 @@ open class SkiaWindow : JFrame() {
init
{
init
{
contentPane
.
add
(
layer
)
contentPane
.
add
(
layer
)
}
}
fun
display
()
{
layer
.
display
()
}
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/LinuxRedrawer.kt
0 → 100644
View file @
620547af
package
org.jetbrains.skiko.redrawer
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.swing.Swing
import
org.jetbrains.skiko.FrameDispatcher
import
org.jetbrains.skiko.HardwareLayer
import
org.jetbrains.skiko.OpenGLApi
internal
class
LinuxRedrawer
(
private
val
layer
:
HardwareLayer
)
:
Redrawer
{
private
val
context
=
layer
.
lockDrawingSurface
{
val
context
=
it
.
createContext
()
it
.
makeCurrent
(
context
)
it
.
setSwapInterval
(
1
)
context
}
private
var
isDisposed
=
false
override
fun
dispose
()
{
check
(!
isDisposed
)
layer
.
lockDrawingSurface
{
it
.
destroyContext
(
context
)
}
isDisposed
=
true
}
override
fun
needRedraw
()
{
toRedraw
.
add
(
this
)
frameDispatcher
.
scheduleFrame
()
}
companion
object
{
private
val
toRedraw
=
mutableSetOf
<
LinuxRedrawer
>()
private
val
toRedrawCopy
=
mutableSetOf
<
LinuxRedrawer
>()
private
val
toRedrawAlive
=
toRedrawCopy
.
asSequence
().
filterNot
(
LinuxRedrawer
::
isDisposed
)
private
val
frameDispatcher
=
FrameDispatcher
(
Dispatchers
.
Swing
)
{
toRedrawCopy
.
clear
()
toRedrawCopy
.
addAll
(
toRedraw
)
toRedraw
.
clear
()
val
nanoTime
=
System
.
nanoTime
()
for
(
redrawer
in
toRedrawAlive
)
{
redrawer
.
layer
.
update
(
nanoTime
)
}
val
drawingSurfaces
=
toRedrawAlive
.
map
{
lockDrawingSurface
(
it
.
layer
)
}.
toList
()
try
{
toRedrawAlive
.
forEachIndexed
{
index
,
redrawer
->
drawingSurfaces
[
index
].
makeCurrent
(
redrawer
.
context
)
redrawer
.
layer
.
draw
()
}
toRedrawAlive
.
forEachIndexed
{
index
,
_
->
drawingSurfaces
[
index
].
swapBuffers
()
}
toRedrawAlive
.
forEachIndexed
{
index
,
redrawer
->
drawingSurfaces
[
index
].
makeCurrent
(
redrawer
.
context
)
OpenGLApi
.
instance
.
glFinish
()
}
}
finally
{
drawingSurfaces
.
forEach
(
::
unlockDrawingSurface
)
}
}
}
}
private
inline
fun
<
T
>
HardwareLayer
.
lockDrawingSurface
(
action
:
(
DrawingSurface
)
->
T
):
T
{
val
drawingSurface
=
lockDrawingSurface
(
this
)
try
{
return
action
(
drawingSurface
)
}
finally
{
unlockDrawingSurface
(
drawingSurface
)
}
}
private
fun
lockDrawingSurface
(
layer
:
HardwareLayer
):
DrawingSurface
{
val
ptr
=
lockDrawingSurfaceNative
(
layer
)
return
DrawingSurface
(
ptr
,
getDisplay
(
ptr
),
getWindow
(
ptr
))
}
private
fun
unlockDrawingSurface
(
drawingSurface
:
DrawingSurface
)
{
unlockDrawingSurfaceNative
(
drawingSurface
.
ptr
)
}
private
class
DrawingSurface
(
val
ptr
:
Long
,
val
display
:
Long
,
val
window
:
Long
)
{
fun
createContext
()
=
createContext
(
display
)
fun
destroyContext
(
context
:
Long
)
=
destroyContext
(
display
,
context
)
fun
makeCurrent
(
context
:
Long
)
=
makeCurrent
(
display
,
window
,
context
)
fun
swapBuffers
()
=
swapBuffers
(
display
,
window
)
fun
setSwapInterval
(
interval
:
Int
)
=
setSwapInterval
(
display
,
window
,
interval
)
}
private
external
fun
lockDrawingSurfaceNative
(
layer
:
HardwareLayer
):
Long
private
external
fun
unlockDrawingSurfaceNative
(
drawingSurface
:
Long
)
private
external
fun
getDisplay
(
drawingSurface
:
Long
):
Long
private
external
fun
getWindow
(
drawingSurface
:
Long
):
Long
private
external
fun
makeCurrent
(
display
:
Long
,
window
:
Long
,
context
:
Long
)
private
external
fun
createContext
(
display
:
Long
):
Long
private
external
fun
destroyContext
(
display
:
Long
,
context
:
Long
)
private
external
fun
setSwapInterval
(
display
:
Long
,
window
:
Long
,
interval
:
Int
)
private
external
fun
swapBuffers
(
display
:
Long
,
window
:
Long
)
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/MacOsRedrawer.kt
0 → 100644
View file @
620547af
package
org.jetbrains.skiko.redrawer
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.swing.Swing
import
org.jetbrains.skiko.FrameDispatcher
import
org.jetbrains.skiko.HardwareLayer
import
org.jetbrains.skiko.OpenGLApi
import
javax.swing.SwingUtilities.convertPoint
import
javax.swing.SwingUtilities.getRootPane
internal
class
MacOsRedrawer
(
private
val
layer
:
HardwareLayer
)
:
Redrawer
{
private
val
containerLayerPtr
=
initContainer
(
layer
)
private
val
drawLayer
=
object
:
AWTGLLayer
(
containerLayerPtr
)
{
override
fun
draw
()
=
layer
.
draw
()
}
// use separate layer for vsync, because with single layer we cannot asynchronously update layer
// `update` is suspend, and runBlocking(Dispatchers.Swing) causes dead lock with AppKit Thread.
// AWT has internal method to avoid dead locks but it is internal (sun.lwawt.macosx.LWCToolkit.invokeAndWait)
private
val
vsyncLayer
=
object
:
AWTGLLayer
(
containerLayerPtr
)
{
@Volatile
private
var
needDraw
:
CompletableDeferred
<
Unit
>?
=
null
init
{
setFrame
(
0
,
0
,
1
,
1
)
// if frame has zero size then it will be not drawn at all
}
override
fun
draw
()
{
// Clear layer with transparent color, so it will be not pink color.
val
opengl
=
OpenGLApi
.
instance
opengl
.
glClearColor
(
0f
,
0f
,
0f
,
0f
)
opengl
.
glClear
(
opengl
.
GL_COLOR_BUFFER_BIT
)
needDraw
!!
.
complete
(
Unit
)
}
override
fun
canDraw
():
Boolean
{
val
canDraw
=
needDraw
!=
null
if
(!
canDraw
)
{
isAsynchronous
=
false
// stop asynchronous mode so we don't waste CPU cycles
}
return
canDraw
}
suspend
fun
sync
()
{
check
(
needDraw
==
null
)
needDraw
=
CompletableDeferred
()
// Use asynchronous mode instead of just setNeedsDisplay,
// so Core Animation will wait for the next frame in vsync signal
//
// Asynchronous mode means that Core Animation will automatically
// call canDraw/draw every vsync signal (~16.7ms on 60Hz monitor)
//
// Similar is implemented in Chromium:
// https://chromium.googlesource.com/chromium/chromium/+/0489078bf98350b00876070cf2fdce230905f47e/content/browser/renderer_host/compositing_iosurface_layer_mac.mm#57
if
(!
isAsynchronous
)
{
isAsynchronous
=
true
super
.
setNeedsDisplay
()
}
needDraw
!!
.
await
()
needDraw
=
null
}
}
private
val
frameDispatcher
=
FrameDispatcher
(
Dispatchers
.
Swing
)
{
layer
.
update
(
System
.
nanoTime
())
drawLayer
.
setNeedsDisplay
()
vsyncLayer
.
sync
()
}
override
fun
dispose
()
{
frameDispatcher
.
cancel
()
vsyncLayer
.
dispose
()
drawLayer
.
dispose
()
}
override
fun
syncSize
()
{
val
globalPosition
=
convertPoint
(
layer
,
layer
.
x
,
layer
.
y
,
getRootPane
(
layer
))
setContentScale
(
containerLayerPtr
,
layer
.
contentScale
)
setContentScale
(
drawLayer
.
ptr
,
layer
.
contentScale
)
drawLayer
.
setFrame
(
globalPosition
.
x
,
globalPosition
.
y
,
layer
.
width
,
layer
.
height
)
}
override
fun
needRedraw
()
{
frameDispatcher
.
scheduleFrame
()
}
}
private
open
class
AWTGLLayer
(
private
val
containerPtr
:
Long
)
{
@Suppress
(
"LeakingThis"
)
val
ptr
=
initAWTGLLayer
(
containerPtr
,
this
)
fun
setFrame
(
x
:
Int
,
y
:
Int
,
width
:
Int
,
height
:
Int
)
{
setFrame
(
containerPtr
,
ptr
,
x
.
toFloat
(),
y
.
toFloat
(),
width
.
toFloat
(),
height
.
toFloat
())
}
// Called in AWT Thread
open
fun
dispose
()
=
disposeAWTGLLayer
(
ptr
)
var
isAsynchronous
:
Boolean
get
()
=
isAsynchronous
(
ptr
)
set
(
value
)
=
setAsynchronous
(
ptr
,
value
)
open
fun
setNeedsDisplay
()
=
setNeedsDisplayOnMainThread
(
ptr
)
// Called in AppKit Thread
protected
open
fun
canDraw
()
=
true
// Called in AppKit Thread, shouldn't be called if canDraw returned false
protected
open
fun
draw
()
=
Unit
private
external
fun
isAsynchronous
(
ptr
:
Long
):
Boolean
private
external
fun
setAsynchronous
(
ptr
:
Long
,
isAsynchronous
:
Boolean
)
private
external
fun
setNeedsDisplayOnMainThread
(
nativePtr
:
Long
)
protected
external
fun
setFrame
(
containerPtr
:
Long
,
ptr
:
Long
,
x
:
Float
,
y
:
Float
,
width
:
Float
,
height
:
Float
)
}
private
external
fun
initContainer
(
layer
:
HardwareLayer
):
Long
private
external
fun
setContentScale
(
layerNativePtr
:
Long
,
contentScale
:
Float
)
private
external
fun
initAWTGLLayer
(
containerPtr
:
Long
,
layer
:
AWTGLLayer
):
Long
private
external
fun
disposeAWTGLLayer
(
ptr
:
Long
)
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/Redrawer.kt
0 → 100644
View file @
620547af
package
org.jetbrains.skiko.redrawer
interface
Redrawer
{
fun
dispose
()
fun
needRedraw
()
fun
syncSize
()
=
Unit
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/redrawer/WindowsRedrawer.kt
0 → 100644
View file @
620547af
package
org.jetbrains.skiko.redrawer
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.swing.Swing
import
kotlinx.coroutines.withContext
import
org.jetbrains.skiko.FrameDispatcher
import
org.jetbrains.skiko.HardwareLayer
import
org.jetbrains.skiko.OpenGLApi
internal
class
WindowsRedrawer
(
private
val
layer
:
HardwareLayer
)
:
Redrawer
{
private
val
device
=
getDevice
(
layer
)
private
val
context
=
createContext
(
device
)
private
var
isDisposed
=
false
init
{
makeCurrent
()
// For vsync we will use dwmFlush instead of swapInterval,
// because it isn't reliable with DWM (Desktop Windows Manager): interval between frames isn't stable (14-19ms).
// With dwmFlush it is stable (16.6-16.8 ms)
// GLFW also uses dwmFlush (https://www.glfw.org/docs/3.0/window.html#window_swap)
setSwapInterval
(
0
)
}
override
fun
dispose
()
{
check
(!
isDisposed
)
deleteContext
(
context
)
isDisposed
=
true
}
override
fun
needRedraw
()
{
toRedraw
.
add
(
this
)
frameDispatcher
.
scheduleFrame
()
}
private
fun
makeCurrent
()
=
makeCurrent
(
device
,
context
)
private
fun
swapBuffers
()
=
swapBuffers
(
device
)
companion
object
{
private
val
toRedraw
=
mutableSetOf
<
WindowsRedrawer
>()
private
val
toRedrawCopy
=
mutableSetOf
<
WindowsRedrawer
>()
private
val
toRedrawAlive
=
toRedrawCopy
.
asSequence
().
filterNot
(
WindowsRedrawer
::
isDisposed
)
private
val
frameDispatcher
=
FrameDispatcher
(
Dispatchers
.
Swing
)
{
toRedrawCopy
.
clear
()
toRedrawCopy
.
addAll
(
toRedraw
)
toRedraw
.
clear
()
val
nanoTime
=
System
.
nanoTime
()
for
(
redrawer
in
toRedrawAlive
)
{
redrawer
.
layer
.
update
(
nanoTime
)
}
for
(
redrawer
in
toRedrawAlive
)
{
redrawer
.
makeCurrent
()
redrawer
.
layer
.
draw
()
}
for
(
redrawer
in
toRedrawAlive
)
{
redrawer
.
swapBuffers
()
}
for
(
redrawer
in
toRedrawAlive
)
{
redrawer
.
makeCurrent
()
OpenGLApi
.
instance
.
glFinish
()
}
withContext
(
Dispatchers
.
IO
)
{
dwmFlush
()
// wait for vsync
}
}
}
}
private
external
fun
makeCurrent
(
device
:
Long
,
context
:
Long
)
private
external
fun
getDevice
(
layer
:
HardwareLayer
):
Long
private
external
fun
createContext
(
device
:
Long
):
Long
private
external
fun
deleteContext
(
context
:
Long
)
private
external
fun
setSwapInterval
(
interval
:
Int
)
private
external
fun
swapBuffers
(
device
:
Long
)
// TODO according to https://bugs.chromium.org/p/chromium/issues/detail?id=467617 dwmFlush has lag 3 ms after vsync.
// Maybe we should use D3DKMTWaitForVerticalBlankEvent? See also https://www.vsynctester.com/chromeisbroken.html
// TODO should we support Windows 7? DWM can be disabled on Windows 7.
// it that case there will be a crash or just no frame limit (I don't know exactly).
private
external
fun
dwmFlush
()
\ No newline at end of file
skiko/src/jvmMain/objectiveC/macos/drawlayer.m
View file @
620547af
...
@@ -7,69 +7,13 @@
...
@@ -7,69 +7,13 @@
#import <Cocoa/Cocoa.h>
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGL/gl3.h>
#import <Metal/Metal.h>
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
#import <QuartzCore/CAMetalLayer.h>
#import <pthread.h>
JavaVM
*
jvm
=
NULL
;
@interface
AWTGLLayer
:
CAOpenGLLayer
@property
jobject
canvasGlobalRef
;
@end
@implementation
AWTGLLayer
-
(
id
)
init
{
self
=
[
super
init
];
if
(
self
)
{
[
self
removeAllAnimations
];
[
self
setAutoresizingMask
:
(
kCALayerWidthSizable
|
kCALayerHeightSizable
)];
[
self
setNeedsDisplayOnBoundsChange
:
YES
];
self
.
canvasGlobalRef
=
NULL
;
}
return
self
;
}
-
(
void
)
drawInCGLContext
:
(
CGLContextObj
)
ctx
pixelFormat
:
(
CGLPixelFormatObj
)
pf
forLayerTime
:
(
CFTimeInterval
)
t
displayTime
:
(
const
CVTimeStamp
*
)
ts
{
CGLSetCurrentContext
(
ctx
);
if
(
jvm
!=
NULL
)
{
JNIEnv
*
env
;
(
*
jvm
)
->
AttachCurrentThread
(
jvm
,
(
void
**
)
&
env
,
NULL
);
static
jclass
wndClass
=
NULL
;
if
(
!
wndClass
)
wndClass
=
(
*
env
)
->
GetObjectClass
(
env
,
self
.
canvasGlobalRef
);
static
jmethodID
drawMethod
=
NULL
;
if
(
!
drawMethod
)
drawMethod
=
(
*
env
)
->
GetMethodID
(
env
,
wndClass
,
"draw"
,
"()V"
);
if
(
NULL
==
drawMethod
)
{
NSLog
(
@"The method HardwareLayer.draw() not found!"
);
return
;
}
(
*
env
)
->
CallVoidMethod
(
env
,
self
.
canvasGlobalRef
,
drawMethod
);
}
[
super
drawInCGLContext
:
ctx
pixelFormat
:
pf
forLayerTime
:
t
displayTime
:
ts
];
}
@end
@interface
LayerHandler
:
NSObject
@interface
LayerHandler
:
NSObject
@property
jobject
canvasGlobalRef
;
@property
(
retain
,
strong
)
CALayer
*
container
;
@property
(
retain
,
strong
)
CALayer
*
container
;
@property
(
retain
,
strong
)
AWTGLLayer
*
glLayer
;
@property
(
retain
,
strong
)
NSWindow
*
window
;
@property
(
retain
,
strong
)
NSWindow
*
window
;
@end
@end
...
@@ -82,107 +26,18 @@ JavaVM *jvm = NULL;
...
@@ -82,107 +26,18 @@ JavaVM *jvm = NULL;
if
(
self
)
if
(
self
)
{
{
self
.
canvasGlobalRef
=
NULL
;
self
.
container
=
NULL
;
self
.
container
=
NULL
;
self
.
glLayer
=
NULL
;
self
.
window
=
NULL
;
self
.
window
=
NULL
;
}
}
return
self
;
return
self
;
}
}
-
(
void
)
syncLayersSize
{
if
(
jvm
!=
NULL
)
{
JNIEnv
*
env
;
(
*
jvm
)
->
AttachCurrentThread
(
jvm
,
(
void
**
)
&
env
,
NULL
);
static
jclass
wndClass
=
NULL
;
if
(
!
wndClass
)
{
wndClass
=
(
*
env
)
->
GetObjectClass
(
env
,
self
.
glLayer
.
canvasGlobalRef
);
}
// scale factor
static
jmethodID
contentScaleMethod
=
NULL
;
if
(
!
contentScaleMethod
)
{
contentScaleMethod
=
(
*
env
)
->
GetMethodID
(
env
,
wndClass
,
"getContentScale"
,
"()F"
);
}
if
(
NULL
==
contentScaleMethod
)
{
NSLog
(
@"The method HardwareLayer.getContentScale() not found!"
);
return
;
}
float
scaleFactor
=
(
*
env
)
->
CallFloatMethod
(
env
,
self
.
glLayer
.
canvasGlobalRef
,
contentScaleMethod
);
assert
(
scaleFactor
!=
0
);
self
.
container
.
contentsScale
=
scaleFactor
;
self
.
glLayer
.
contentsScale
=
scaleFactor
;
// size & position
static
jmethodID
getXMethod
=
NULL
;
if
(
!
getXMethod
)
{
getXMethod
=
(
*
env
)
->
GetMethodID
(
env
,
wndClass
,
"getAbsoluteX"
,
"()I"
);
}
if
(
NULL
==
getXMethod
)
{
NSLog
(
@"The method HardwareLayer.getAbsoluteX() not found!"
);
return
;
}
static
jmethodID
getYMethod
=
NULL
;
if
(
!
getYMethod
)
{
getYMethod
=
(
*
env
)
->
GetMethodID
(
env
,
wndClass
,
"getAbsoluteY"
,
"()I"
);
}
if
(
NULL
==
getYMethod
)
{
NSLog
(
@"The method HardwareLayer.getAbsoluteY() not found!"
);
return
;
}
static
jmethodID
getWidthMethod
=
NULL
;
if
(
!
getWidthMethod
)
{
getWidthMethod
=
(
*
env
)
->
GetMethodID
(
env
,
wndClass
,
"getWidth"
,
"()I"
);
}
if
(
NULL
==
getWidthMethod
)
{
NSLog
(
@"The method HardwareLayer.getWidth() not found!"
);
return
;
}
static
jmethodID
getHeightMethod
=
NULL
;
if
(
!
getHeightMethod
)
{
getHeightMethod
=
(
*
env
)
->
GetMethodID
(
env
,
wndClass
,
"getHeight"
,
"()I"
);
}
if
(
NULL
==
getHeightMethod
)
{
NSLog
(
@"The method HardwareLayer.getHeight() not found!"
);
return
;
}
int
x
=
(
*
env
)
->
CallIntMethod
(
env
,
self
.
glLayer
.
canvasGlobalRef
,
getXMethod
);
int
y
=
(
*
env
)
->
CallIntMethod
(
env
,
self
.
glLayer
.
canvasGlobalRef
,
getYMethod
);
int
w
=
(
*
env
)
->
CallIntMethod
(
env
,
self
.
glLayer
.
canvasGlobalRef
,
getWidthMethod
);
int
h
=
(
*
env
)
->
CallIntMethod
(
env
,
self
.
glLayer
.
canvasGlobalRef
,
getHeightMethod
);
y
=
(
int
)
self
.
container
.
frame
.
size
.
height
-
y
-
h
;
CGRect
boundsRect
=
CGRectMake
(
x
,
y
,
w
,
h
);
self
.
glLayer
.
frame
=
boundsRect
;
}
}
-
(
void
)
updateLayerContent
{
[
self
.
glLayer
performSelectorOnMainThread
:
@selector
(
setNeedsDisplay
)
withObject
:
0
waitUntilDone
:
NO
];
}
-
(
void
)
disposeLayer
:
(
JNIEnv
*
)
env
-
(
void
)
disposeLayer
:
(
JNIEnv
*
)
env
{
{
[
self
.
glLayer
removeFromSuperlayer
];
(
*
env
)
->
DeleteGlobalRef
(
env
,
self
.
canvasGlobalRef
);
(
*
env
)
->
DeleteGlobalRef
(
env
,
self
.
glLayer
.
canvasGlobalRef
);
self
.
canvasGlobalRef
=
NULL
;
self
.
glLayer
.
canvasGlobalRef
=
NULL
;
self
.
glLayer
=
NULL
;
self
.
container
=
NULL
;
self
.
container
=
NULL
;
self
.
window
=
NULL
;
self
.
window
=
NULL
;
}
}
...
@@ -209,15 +64,6 @@ JavaVM *jvm = NULL;
...
@@ -209,15 +64,6 @@ JavaVM *jvm = NULL;
NSMutableArray
*
unknownWindows
=
nil
;
NSMutableArray
*
unknownWindows
=
nil
;
NSMutableSet
*
layerStorage
=
nil
;
NSMutableSet
*
layerStorage
=
nil
;
pthread_mutex_t
layerStorageMutex
=
{
0
};
void
lockLayers
()
{
pthread_mutex_lock
(
&
layerStorageMutex
);
}
void
unlockLayers
()
{
pthread_mutex_unlock
(
&
layerStorageMutex
);
}
LayerHandler
*
findByObject
(
JNIEnv
*
env
,
jobject
object
)
LayerHandler
*
findByObject
(
JNIEnv
*
env
,
jobject
object
)
{
{
...
@@ -227,7 +73,7 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
...
@@ -227,7 +73,7 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
}
}
for
(
LayerHandler
*
layer
in
layerStorage
)
for
(
LayerHandler
*
layer
in
layerStorage
)
{
{
if
((
*
env
)
->
IsSameObject
(
env
,
object
,
layer
.
glLayer
.
canvasGlobalRef
)
==
JNI_TRUE
)
if
((
*
env
)
->
IsSameObject
(
env
,
object
,
layer
.
canvasGlobalRef
)
==
JNI_TRUE
)
{
{
return
layer
;
return
layer
;
}
}
...
@@ -237,20 +83,9 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
...
@@ -237,20 +83,9 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
extern
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
extern
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_
updateLayer
(
JNIEnv
*
env
,
jobject
canvas
)
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_
init
(
JNIEnv
*
env
,
jobject
canvas
)
{
{
lockLayers
();
if
(
layerStorage
==
nil
)
if
(
layerStorage
!=
nil
)
{
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
[
layer
syncLayersSize
];
unlockLayers
();
return
;
}
}
else
{
{
layerStorage
=
[[
NSMutableSet
alloc
]
init
];
layerStorage
=
[[
NSMutableSet
alloc
]
init
];
}
}
...
@@ -258,8 +93,6 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
...
@@ -258,8 +93,6 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
JAWT
awt
;
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
CGLPixelFormatObj
pixFormatObj
=
NULL
;
CGLContextObj
context
;
jboolean
result
=
JNI_FALSE
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
jint
lock
=
0
;
...
@@ -269,8 +102,6 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
...
@@ -269,8 +102,6 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
result
=
Skiko_GetAWT
(
env
,
&
awt
);
result
=
Skiko_GetAWT
(
env
,
&
awt
);
assert
(
result
!=
JNI_FALSE
);
assert
(
result
!=
JNI_FALSE
);
(
*
env
)
->
GetJavaVM
(
env
,
&
jvm
);
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
assert
(
ds
!=
NULL
);
assert
(
ds
!=
NULL
);
...
@@ -286,18 +117,8 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
...
@@ -286,18 +117,8 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
LayerHandler
*
layersSet
=
[[
LayerHandler
alloc
]
init
];
LayerHandler
*
layersSet
=
[[
LayerHandler
alloc
]
init
];
layersSet
.
container
=
[
dsi_mac
windowLayer
];
layersSet
.
container
=
[
dsi_mac
windowLayer
];
[
layersSet
.
container
removeAllAnimations
];
[
layersSet
.
container
setAutoresizingMask
:
(
kCALayerWidthSizable
|
kCALayerHeightSizable
)];
[
layersSet
.
container
setNeedsDisplayOnBoundsChange
:
YES
];
layersSet
.
glLayer
=
[
AWTGLLayer
new
];
[
layersSet
.
container
addSublayer
:
layersSet
.
glLayer
];
jobject
canvasGlobalRef
=
(
*
env
)
->
NewGlobalRef
(
env
,
canvas
);
jobject
canvasGlobalRef
=
(
*
env
)
->
NewGlobalRef
(
env
,
canvas
);
[
layersSet
setCanvasGlobalRef
:
canvasGlobalRef
];
[
layersSet
.
glLayer
setCanvasGlobalRef
:
canvasGlobalRef
];
[
layersSet
syncLayersSize
];
if
(
unknownWindows
==
nil
)
if
(
unknownWindows
==
nil
)
{
{
...
@@ -332,25 +153,11 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
...
@@ -332,25 +153,11 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
unlockLayers
();
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_redrawLayer
(
JNIEnv
*
env
,
jobject
canvas
)
{
lockLayers
();
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
unlockLayers
();
if
(
layer
!=
NULL
)
{
[
layer
updateLayerContent
];
}
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_dispose
Layer
(
JNIEnv
*
env
,
jobject
canvas
)
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_dispose
(
JNIEnv
*
env
,
jobject
canvas
)
{
{
lockLayers
();
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
LayerHandler
*
layer
=
findByObject
(
env
,
canvas
);
unlockLayers
();
if
(
layer
!=
NULL
)
if
(
layer
!=
NULL
)
{
{
[
layerStorage
removeObject
:
layer
];
[
layerStorage
removeObject
:
layer
];
...
@@ -365,9 +172,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle(J
...
@@ -365,9 +172,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle(J
JNIEXPORT
jboolean
JNICALL
Java_org_jetbrains_skiko_PlatformOperationsKt_osxIsFullscreenNative
(
JNIEnv
*
env
,
jobject
properties
,
jobject
component
)
JNIEXPORT
jboolean
JNICALL
Java_org_jetbrains_skiko_PlatformOperationsKt_osxIsFullscreenNative
(
JNIEnv
*
env
,
jobject
properties
,
jobject
component
)
{
{
lockLayers
();
LayerHandler
*
layer
=
findByObject
(
env
,
component
);
LayerHandler
*
layer
=
findByObject
(
env
,
component
);
unlockLayers
();
if
(
layer
!=
NULL
)
if
(
layer
!=
NULL
)
{
{
return
[
layer
isFullScreen
];
return
[
layer
isFullScreen
];
...
@@ -377,9 +182,7 @@ JNIEXPORT jboolean JNICALL Java_org_jetbrains_skiko_PlatformOperationsKt_osxIsFu
...
@@ -377,9 +182,7 @@ JNIEXPORT jboolean JNICALL Java_org_jetbrains_skiko_PlatformOperationsKt_osxIsFu
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_PlatformOperationsKt_osxSetFullscreenNative
(
JNIEnv
*
env
,
jobject
properties
,
jobject
component
,
jboolean
value
)
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_PlatformOperationsKt_osxSetFullscreenNative
(
JNIEnv
*
env
,
jobject
properties
,
jobject
component
,
jboolean
value
)
{
{
lockLayers
();
LayerHandler
*
layer
=
findByObject
(
env
,
component
);
LayerHandler
*
layer
=
findByObject
(
env
,
component
);
unlockLayers
();
if
(
layer
!=
NULL
)
if
(
layer
!=
NULL
)
{
{
[
layer
makeFullscreen
:
value
];
[
layer
makeFullscreen
:
value
];
...
...
skiko/src/jvmMain/objectiveC/macos/redrawer.m
0 → 100644
View file @
620547af
#import "jawt.h"
#import "jawt_md.h"
#define GL_SILENCE_DEPRECATION
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGL/gl3.h>
extern
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
JavaVM
*
jvm
=
NULL
;
@interface
AWTGLLayer
:
CAOpenGLLayer
@property
jobject
javaRef
;
@end
@implementation
AWTGLLayer
-
(
id
)
init
{
self
=
[
super
init
];
assert
(
self
!=
NULL
);
[
self
removeAllAnimations
];
[
self
setAutoresizingMask
:
(
kCALayerWidthSizable
|
kCALayerHeightSizable
)];
[
self
setNeedsDisplayOnBoundsChange
:
YES
];
return
self
;
}
-
(
BOOL
)
canDrawInCGLContext
:
(
CGLContextObj
)
ctx
pixelFormat
:
(
CGLPixelFormatObj
)
pf
forLayerTime
:
(
CFTimeInterval
)
t
displayTime
:
(
const
CVTimeStamp
*
)
ts
{
assert
(
jvm
!=
NULL
);
JNIEnv
*
env
;
(
*
jvm
)
->
AttachCurrentThread
(
jvm
,
(
void
**
)
&
env
,
NULL
);
static
jclass
cls
=
NULL
;
static
jmethodID
method
=
NULL
;
if
(
!
cls
)
cls
=
(
*
env
)
->
GetObjectClass
(
env
,
self
.
javaRef
);
if
(
!
method
)
method
=
(
*
env
)
->
GetMethodID
(
env
,
cls
,
"canDraw"
,
"()Z"
);
return
(
*
env
)
->
CallBooleanMethod
(
env
,
self
.
javaRef
,
method
);
}
-
(
void
)
drawInCGLContext
:
(
CGLContextObj
)
ctx
pixelFormat
:
(
CGLPixelFormatObj
)
pf
forLayerTime
:
(
CFTimeInterval
)
t
displayTime
:
(
const
CVTimeStamp
*
)
ts
{
CGLSetCurrentContext
(
ctx
);
assert
(
jvm
!=
NULL
);
JNIEnv
*
env
;
(
*
jvm
)
->
AttachCurrentThread
(
jvm
,
(
void
**
)
&
env
,
NULL
);
static
jclass
cls
=
NULL
;
static
jmethodID
method
=
NULL
;
if
(
!
cls
)
cls
=
(
*
env
)
->
GetObjectClass
(
env
,
self
.
javaRef
);
if
(
!
method
)
method
=
(
*
env
)
->
GetMethodID
(
env
,
cls
,
"draw"
,
"()V"
);
(
*
env
)
->
CallVoidMethod
(
env
,
self
.
javaRef
,
method
);
[
super
drawInCGLContext
:
ctx
pixelFormat
:
pf
forLayerTime
:
t
displayTime
:
ts
];
}
@end
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initContainer
(
JNIEnv
*
env
,
jobject
redrawer
,
jobject
layer
)
{
JAWT
awt
;
awt
.
version
=
JAWT_VERSION_9
;
jboolean
result
=
Skiko_GetAWT
(
env
,
&
awt
);
assert
(
result
!=
JNI_FALSE
);
(
*
env
)
->
GetJavaVM
(
env
,
&
jvm
);
JAWT_DrawingSurface
*
ds
=
awt
.
GetDrawingSurface
(
env
,
layer
);
assert
(
ds
!=
NULL
);
jint
lock
=
ds
->
Lock
(
ds
);
assert
((
lock
&
JAWT_LOCK_ERROR
)
==
0
);
JAWT_DrawingSurfaceInfo
*
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
assert
(
dsi
!=
NULL
);
NSObject
<
JAWT_SurfaceLayers
>*
dsi_mac
=
(
__bridge
NSObject
<
JAWT_SurfaceLayers
>
*
)
dsi
->
platformInfo
;
CALayer
*
container
=
[
dsi_mac
windowLayer
];
[
container
removeAllAnimations
];
[
container
setAutoresizingMask
:
(
kCALayerWidthSizable
|
kCALayerHeightSizable
)];
[
container
setNeedsDisplayOnBoundsChange
:
YES
];
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
return
(
jlong
)
container
;
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_setContentScale
(
JNIEnv
*
env
,
jobject
obj
,
jlong
layerPtr
,
jfloat
contentScale
)
{
CALayer
*
layer
=
(
CALayer
*
)
layerPtr
;
assert
(
contentScale
!=
0
);
layer
.
contentsScale
=
contentScale
;
}
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_initAWTGLLayer
(
JNIEnv
*
env
,
jobject
obj
,
jlong
containerPtr
,
jobject
layer
)
{
CALayer
*
container
=
(
CALayer
*
)
containerPtr
;
AWTGLLayer
*
glLayer
=
[
AWTGLLayer
new
];
glLayer
.
javaRef
=
(
*
env
)
->
NewGlobalRef
(
env
,
layer
);
[
container
addSublayer
:
glLayer
];
return
(
jlong
)
glLayer
;
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_MacOsRedrawerKt_disposeAWTGLLayer
(
JNIEnv
*
env
,
jobject
obj
,
jlong
ptr
)
{
AWTGLLayer
*
glLayer
=
(
AWTGLLayer
*
)
ptr
;
[
glLayer
removeFromSuperlayer
];
(
*
env
)
->
DeleteGlobalRef
(
env
,
glLayer
.
javaRef
);
[
glLayer
release
];
}
JNIEXPORT
jboolean
JNICALL
Java_org_jetbrains_skiko_redrawer_AWTGLLayer_isAsynchronous
(
JNIEnv
*
env
,
jobject
obj
,
jlong
ptr
)
{
AWTGLLayer
*
glLayer
=
(
AWTGLLayer
*
)
ptr
;
return
glLayer
.
isAsynchronous
;
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_AWTGLLayer_setAsynchronous
(
JNIEnv
*
env
,
jobject
obj
,
jlong
ptr
,
jboolean
isAsynchronous
)
{
AWTGLLayer
*
glLayer
=
(
AWTGLLayer
*
)
ptr
;
[
glLayer
setAsynchronous
:
isAsynchronous
];
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_AWTGLLayer_setNeedsDisplayOnMainThread
(
JNIEnv
*
env
,
jobject
obj
,
jlong
ptr
)
{
AWTGLLayer
*
glLayer
=
(
AWTGLLayer
*
)
ptr
;
[
glLayer
performSelectorOnMainThread
:
@selector
(
setNeedsDisplay
)
withObject
:
0
waitUntilDone
:
NO
];
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_redrawer_AWTGLLayer_setFrame
(
JNIEnv
*
env
,
jobject
obj
,
jlong
containerPtr
,
jlong
ptr
,
jfloat
x
,
jfloat
y
,
jfloat
width
,
jfloat
height
)
{
CALayer
*
container
=
(
AWTGLLayer
*
)
containerPtr
;
AWTGLLayer
*
glLayer
=
(
AWTGLLayer
*
)
ptr
;
y
=
(
int
)
container
.
frame
.
size
.
height
-
y
-
height
;
[
CATransaction
begin
];
[
CATransaction
setValue
:(
id
)
kCFBooleanTrue
forKey
:
kCATransactionDisableActions
];
// disable animations
glLayer
.
frame
=
CGRectMake
(
x
,
y
,
width
,
height
);
[
CATransaction
commit
];
}
\ 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