Commit b36a31e8 authored by Roman Sedaikin's avatar Roman Sedaikin

Refactored the source code related to native layer management and dpi scaling.

parent 2acd99da
......@@ -27,7 +27,7 @@ import javax.swing.KeyStroke
import java.awt.Toolkit
fun main(args: Array<String>) {
createWindow("First window");
createWindow("First window")
}
fun createWindow(title: String) {
......
......@@ -16,19 +16,21 @@ extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt);
JavaVM *jvm = NULL;
class LayersSet
class LayerHandler
{
public:
jobject canvasRef;
jobject canvasGlobalRef;
GLXContext context;
void update()
void updateLayerContent()
{
draw();
}
void dispose()
void disposeLayer(JNIEnv *env)
{
env->DeleteGlobalRef(canvasGlobalRef);
canvasGlobalRef = NULL;
context = NULL;
}
......@@ -56,7 +58,7 @@ private:
return;
}
ds = awt.GetDrawingSurface(env, canvasRef);
ds = awt.GetDrawingSurface(env, canvasGlobalRef);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_x11 = (JAWT_X11DrawingSurfaceInfo *)dsi->platformInfo;
......@@ -68,14 +70,16 @@ private:
glXMakeCurrent(display, window, context);
jclass wndClass = env->GetObjectClass(canvasRef);
jmethodID drawMethod = env->GetMethodID(wndClass, "draw", "()V");
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(canvasRef, drawMethod);
env->CallVoidMethod(canvasGlobalRef, drawMethod);
glFinish();
glXSwapBuffers(display, window);
}
......@@ -86,12 +90,12 @@ private:
}
};
set<LayersSet *> *windowsSet = NULL;
LayersSet *findByObject(JNIEnv *env, jobject object)
set<LayerHandler *> *layerStorage = NULL;
LayerHandler *findByObject(JNIEnv *env, jobject object)
{
for (auto &layer : *windowsSet)
for (auto &layer : *layerStorage)
{
if (env->IsSameObject(object, layer->canvasRef) == JNI_TRUE)
if (env->IsSameObject(object, layer->canvasGlobalRef) == JNI_TRUE)
{
return layer;
}
......@@ -102,19 +106,16 @@ LayersSet *findByObject(JNIEnv *env, jobject object)
extern "C"
{
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{
if (windowsSet != NULL)
if (layerStorage != NULL)
{
LayersSet *layer = findByObject(env, canvas);
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
if (layer->context == NULL)
{
env->DeleteGlobalRef(layer->canvasRef);
layer->canvasRef = NULL;
windowsSet->erase(layer);
layerStorage->erase(layer);
delete layer;
}
return;
......@@ -122,7 +123,7 @@ extern "C"
}
else
{
windowsSet = new set<LayersSet *>();
layerStorage = new set<LayerHandler *>();
}
if (jvm == NULL)
......@@ -160,12 +161,12 @@ extern "C"
XVisualInfo *vi = glXChooseVisual(display, 0, att);
GLXContext context = glXCreateContext(display, vi, NULL, GL_TRUE);
LayersSet *layer = new LayersSet();
windowsSet->insert(layer);
LayerHandler *layer = new LayerHandler();
layerStorage->insert(layer);
jobject canvasRef = env->NewGlobalRef(canvas);
layer->canvasRef = canvasRef;
layer->canvasGlobalRef = canvasRef;
layer->context = context;
}
ds->FreeDrawingSurfaceInfo(dsi);
......@@ -175,27 +176,22 @@ extern "C"
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject canvas)
{
LayersSet *layer = findByObject(env, canvas);
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
layer->update();
layer->updateLayerContent();
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject canvas)
{
LayersSet *layer = findByObject(env, canvas);
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
layer->dispose();
layer->disposeLayer(env);
}
}
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject canvas)
{
return 1.0f;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle(JNIEnv *env, jobject canvas)
{
JAWT awt;
......
......@@ -15,23 +15,23 @@ using namespace std;
JavaVM *jvm = NULL;
extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt);
class LayersSet
class LayerHandler
{
public:
jobject windowRef;
jobject canvasGlobalRef;
HGLRC context;
HWND handler;
HDC device;
void update()
void updateLayerContent()
{
draw();
}
void dispose()
void disposeLayer(JNIEnv *env)
{
env->DeleteGlobalRef(canvasGlobalRef);
canvasGlobalRef = NULL;
context = NULL;
handler = NULL;
device = NULL;
}
......@@ -44,14 +44,16 @@ private:
jvm->GetEnv((void **)&env, JNI_VERSION_10);
wglMakeCurrent(device, context);
jclass wndClass = env->GetObjectClass(windowRef);
jmethodID drawMethod = env->GetMethodID(wndClass, "draw", "()V");
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(windowRef, drawMethod);
env->CallVoidMethod(canvasGlobalRef, drawMethod);
glFinish();
SwapBuffers(device);
......@@ -59,12 +61,12 @@ private:
}
};
set<LayersSet *> *windowsSet = NULL;
LayersSet *findByObject(JNIEnv *env, jobject object)
set<LayerHandler *> *layerStorage = NULL;
LayerHandler *findByObject(JNIEnv *env, jobject object)
{
for (auto &layer : *windowsSet)
for (auto &layer : *layerStorage)
{
if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE)
if (env->IsSameObject(object, layer->canvasGlobalRef) == JNI_TRUE)
{
return layer;
}
......@@ -75,19 +77,16 @@ LayersSet *findByObject(JNIEnv *env, jobject object)
extern "C"
{
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject window)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{
if (windowsSet != NULL)
if (layerStorage != NULL)
{
LayersSet *layer = findByObject(env, window);
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
if (layer->context == NULL)
{
env->DeleteGlobalRef(layer->windowRef);
layer->windowRef = NULL;
windowsSet->erase(layer);
layerStorage->erase(layer);
delete layer;
}
return;
......@@ -95,7 +94,7 @@ extern "C"
}
else
{
windowsSet = new set<LayersSet *>();
layerStorage = new set<LayerHandler *>();
}
JAWT awt;
......@@ -122,7 +121,7 @@ extern "C"
env->GetJavaVM(&jvm);
}
ds = awt.GetDrawingSurface(env, window);
ds = awt.GetDrawingSurface(env, canvas);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
......@@ -144,14 +143,13 @@ extern "C"
DescribePixelFormat(device, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pixFormatDscr);
context = wglCreateContext(device);
LayersSet *layer = new LayersSet();
windowsSet->insert(layer);
LayerHandler *layer = new LayerHandler();
layerStorage->insert(layer);
jobject windowRef = env->NewGlobalRef(window);
jobject canvasRef = env->NewGlobalRef(canvas);
layer->windowRef = windowRef;
layer->canvasGlobalRef = canvasRef;
layer->context = context;
layer->handler = hwnd;
layer->device = device;
}
......@@ -160,42 +158,25 @@ extern "C"
awt.FreeDrawingSurface(ds);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject window)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject canvas)
{
LayersSet *layer = findByObject(env, window);
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
layer->update();
layer->updateLayerContent();
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject window)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject canvas)
{
LayersSet *layer = findByObject(env, window);
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
layer->dispose();
}
}
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window);
if (layer != NULL)
{
// get scale dpi factor of current monitor
HWND parent = GetParent(layer->handler);
if (parent != NULL)
{
UINT dpi = GetDpiForWindow(parent);
float result = dpi / 96.0;
return result;
}
layer->disposeLayer(env);
}
return 1.0f;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle(JNIEnv *env, jobject window)
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle(JNIEnv *env, jobject canvas)
{
JAWT awt;
JAWT_DrawingSurface *ds = NULL;
......@@ -221,7 +202,7 @@ extern "C"
env->GetJavaVM(&jvm);
}
ds = awt.GetDrawingSurface(env, window);
ds = awt.GetDrawingSurface(env, canvas);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
......
......@@ -18,5 +18,5 @@ open class HardwareLayer : Canvas(), Drawable {
override val windowHandle: Long
external get
override val contentScale: Float
external get
get() = graphicsConfiguration.defaultTransform.scaleX.toFloat()
}
\ No newline at end of file
......@@ -70,7 +70,7 @@ open class SkiaLayer() : HardwareLayer() {
}
private fun initSkija() {
val dpi = graphicsConfiguration.defaultTransform.scaleX.toFloat()
val dpi = contentScale
initRenderTarget(dpi)
initSurface()
scaleCanvas(dpi)
......
......@@ -15,14 +15,12 @@ JavaVM *jvm = NULL;
@interface AWTGLLayer : CAOpenGLLayer
@property jobject windowRef;
@property jobject canvasGlobalRef;
@end
@implementation AWTGLLayer
jobject windowRef;
- (id)init
{
self = [super init];
......@@ -33,7 +31,7 @@ jobject windowRef;
[self setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[self setNeedsDisplayOnBoundsChange: YES];
self.windowRef = NULL;
self.canvasGlobalRef = NULL;
}
return self;
......@@ -51,40 +49,30 @@ jobject windowRef;
(*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
static jclass wndClass = NULL;
if (!wndClass) wndClass = (*env)->GetObjectClass(env, self.windowRef);
if (!wndClass) wndClass = (*env)->GetObjectClass(env, self.canvasGlobalRef);
static jmethodID drawMethod = NULL;
if (!drawMethod) drawMethod = (*env)->GetMethodID(env, wndClass, "draw", "()V");
if (NULL == drawMethod) {
if (NULL == drawMethod)
{
NSLog(@"The method Window.draw() not found!");
return;
}
(*env)->CallVoidMethod(env, self.windowRef, drawMethod);
(*env)->CallVoidMethod(env, self.canvasGlobalRef, drawMethod);
}
[super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts];
}
- (void) dispose
{
self.windowRef = NULL;
}
@end
@interface LayersSet : NSObject
@interface LayerHandler : NSObject
@property jobject windowRef;
@property (retain, strong) CALayer *caLayer;
@property (retain, strong) CALayer *container;
@property (retain, strong) AWTGLLayer *glLayer;
@property (retain, strong) NSWindow *window;
@end
@implementation LayersSet
jobject windowRef;
CALayer *caLayer;
AWTGLLayer *glLayer;
@implementation LayerHandler
- (id) init
{
......@@ -92,49 +80,66 @@ AWTGLLayer *glLayer;
if (self)
{
self.windowRef = NULL;
self.caLayer = NULL;
self.container = NULL;
self.glLayer = NULL;
self.window = NULL;
}
return self;
}
- (void) syncSize
- (void) syncLayersSize
{
self.glLayer.bounds = self.caLayer.bounds;
self.glLayer.frame = self.caLayer.frame;
self.glLayer.bounds = self.container.bounds;
self.glLayer.frame = self.container.frame;
float scaleFactor = [[self.window screen] backingScaleFactor];
if (scaleFactor == 0) {
return;
if (jvm != NULL) {
JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
static jclass wndClass = NULL;
if (!wndClass)
{
wndClass = (*env)->GetObjectClass(env, self.glLayer.canvasGlobalRef);
}
static jmethodID contentScaleMethod = NULL;
if (!contentScaleMethod)
{
contentScaleMethod = (*env)->GetMethodID(env, wndClass, "getContentScale", "()F");
}
if (NULL == contentScaleMethod)
{
NSLog(@"The method Window.getContentScale() not found!");
return;
}
float scaleFactor = (*env)->CallFloatMethod(env, self.glLayer.canvasGlobalRef, contentScaleMethod);
assert(scaleFactor != 0);
self.container.contentsScale = scaleFactor;
self.glLayer.contentsScale = scaleFactor;
}
self.caLayer.contentsScale = scaleFactor;
self.glLayer.contentsScale = scaleFactor;
}
- (void) update
- (void) updateLayerContent
{
[self.glLayer performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:0 waitUntilDone:NO];
}
- (void) dispose
- (void) disposeLayer:(JNIEnv *) env
{
[self.glLayer dispose];
(*env)->DeleteGlobalRef(env, self.glLayer.canvasGlobalRef);
self.glLayer.canvasGlobalRef = NULL;
self.glLayer = NULL;
self.caLayer = NULL;
self.window = NULL;
self.container = NULL;
}
@end
NSMutableArray *unknownWindows = nil;
NSMutableSet *windowsSet = nil;
LayersSet * findByObject(JNIEnv *env, jobject object) {
for (LayersSet* value in windowsSet) {
if ((*env)->IsSameObject(env, object, value.windowRef) == JNI_TRUE) {
return value;
NSMutableSet *layerStorage = nil;
LayerHandler * findByObject(JNIEnv *env, jobject object)
{
for (LayerHandler* layer in layerStorage)
{
if ((*env)->IsSameObject(env, object, layer.glLayer.canvasGlobalRef) == JNI_TRUE)
{
return layer;
}
}
......@@ -143,22 +148,25 @@ LayersSet * findByObject(JNIEnv *env, jobject object) {
extern jboolean Skiko_GetAWT(JNIEnv* env, JAWT* awt);
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject window)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{
if (windowsSet != nil || [windowsSet count] > 0) {
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
if (layer.caLayer == NULL && layer.glLayer == NULL) {
(*env)->DeleteGlobalRef(env, layer.windowRef);
layer.windowRef = NULL;
[windowsSet removeObject: layer];
if (layerStorage != nil || [layerStorage count] > 0)
{
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
if (layer.container == NULL && layer.glLayer == NULL)
{
[layerStorage removeObject: layer];
return;
}
[layer syncSize];
[layer syncLayersSize];
return;
}
} else {
windowsSet = [[NSMutableSet alloc] init];
}
else
{
layerStorage = [[NSMutableSet alloc] init];
}
JAWT awt;
......@@ -177,7 +185,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
(*env)->GetJavaVM(env, &jvm);
ds = awt.GetDrawingSurface(env, window);
ds = awt.GetDrawingSurface(env, canvas);
assert(ds != NULL);
lock = ds->Lock(ds);
......@@ -189,49 +197,24 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
{
dsi_mac = ( __bridge NSObject<JAWT_SurfaceLayers> *) dsi->platformInfo;
LayersSet *layersSet = [[LayersSet alloc] init];
[windowsSet addObject: layersSet];
NSMutableArray<NSWindow *> *windows = [NSMutableArray arrayWithArray: [[NSApplication sharedApplication] windows]];
if ([windowsSet count] == 1)
{
NSWindow *mainWindow = [[NSApplication sharedApplication] mainWindow];
layersSet.window = mainWindow;
[windows removeObject: mainWindow];
unknownWindows = windows;
}
else
{
for (NSWindow* value in unknownWindows) {
[windows removeObject: value];
}
for (LayersSet* value in windowsSet) {
[windows removeObject: value.window];
}
layersSet.window = [windows firstObject];
}
LayerHandler *layersSet = [[LayerHandler alloc] init];
[layerStorage addObject: layersSet];
layersSet.caLayer = [dsi_mac windowLayer];
[layersSet.caLayer removeAllAnimations];
[layersSet.caLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[layersSet.caLayer setNeedsDisplayOnBoundsChange: YES];
layersSet.container = [dsi_mac windowLayer];
[layersSet.container removeAllAnimations];
[layersSet.container setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[layersSet.container setNeedsDisplayOnBoundsChange: YES];
layersSet.glLayer = [AWTGLLayer new];
[layersSet.caLayer addSublayer: layersSet.glLayer];
[layersSet.container addSublayer: layersSet.glLayer];
CGFloat white[] = { 1.0f, 1.0f, 1.0f, 1.0f };
layersSet.glLayer.backgroundColor = CGColorCreate(CGColorSpaceCreateDeviceRGB(), white);
jobject windowRef = (*env)->NewGlobalRef(env, window);
jobject canvasGlobalRef = (*env)->NewGlobalRef(env, canvas);
[layersSet.glLayer setWindowRef: windowRef];
[layersSet setWindowRef: windowRef];
[layersSet.glLayer setCanvasGlobalRef: canvasGlobalRef];
NSScreen *screen = [NSScreen mainScreen];
float scaleFactor = screen.backingScaleFactor;
layersSet.caLayer.contentsScale = scaleFactor;
layersSet.glLayer.contentsScale = scaleFactor;
layersSet.glLayer.bounds = layersSet.caLayer.bounds;
layersSet.glLayer.frame = layersSet.caLayer.frame;
[layersSet syncLayersSize];
}
ds->FreeDrawingSurfaceInfo(dsi);
......@@ -239,33 +222,31 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
awt.FreeDrawingSurface(ds);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject window) {
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
[layer update];
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject window) {
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
[layer dispose];
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject canvas)
{
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
[layer updateLayerContent];
}
}
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject window) {
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
return layer.caLayer.contentsScale;
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject canvas)
{
LayerHandler *layer = findByObject(env, canvas);
if (layer != NULL)
{
[layer disposeLayer: env];
}
return 1.0f;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle(JNIEnv *env, jobject window) {
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getWindowHandle(JNIEnv *env, jobject canvas)
{
return (jlong)kNullWindowHandle;
}
void getMetalDeviceAndQueue(void** device, void** queue) {
void getMetalDeviceAndQueue(void** device, void** queue)
{
id<MTLDevice> fDevice = MTLCreateSystemDefaultDevice();
id<MTLCommandQueue> fQueue = [fDevice newCommandQueue];
*device = (__bridge void*)fDevice;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment