Commit fe2440d9 authored by Roman Sedaikin's avatar Roman Sedaikin

Metal API prototype.

parent d0dd73ab
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>skiko-all</name>
<comment>Project skiko created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1615368795414</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>skiko</name>
<comment>Project skiko created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1615368795412</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
...@@ -283,15 +283,21 @@ tasks.withType(CppCompile::class.java).configureEach { ...@@ -283,15 +283,21 @@ tasks.withType(CppCompile::class.java).configureEach {
project.tasks.register<Exec>("objcCompile") { project.tasks.register<Exec>("objcCompile") {
val inputDir = "$projectDir/src/jvmMain/objectiveC/${targetOs.id}" val inputDir = "$projectDir/src/jvmMain/objectiveC/${targetOs.id}"
val outDir = "$buildDir/objc/$target" val outDir = "$buildDir/objc/$target"
val names = File(inputDir).listFiles()!!.map { it.name.removeSuffix(".m") } val names = File(inputDir).listFiles()!!.map { it.name.removeSuffix(".mm") }
val srcs = names.map { "$inputDir/$it.m" }.toTypedArray() val srcs = names.map { "$inputDir/$it.mm" }.toTypedArray()
val outs = names.map { "$outDir/$it.o" }.toTypedArray() val outs = names.map { "$outDir/$it.o" }.toTypedArray()
workingDir = File(outDir) workingDir = File(outDir)
val skiaDir = skiaDir.get().absolutePath
commandLine = listOf( commandLine = listOf(
"clang", "clang",
"-mmacosx-version-min=10.13", "-mmacosx-version-min=10.13",
"-I$jdkHome/include", "-I$jdkHome/include",
"-I$jdkHome/include/darwin", "-I$jdkHome/include/darwin",
"-I$skiaDir",
"-I$skiaDir/include",
"-I$skiaDir/include/gpu",
"-DSK_METAL",
"-std=c++17",
"-c", "-c",
*srcs *srcs
) )
......
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ci</name>
<comment>Project ci created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1615368795410</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
...@@ -6,6 +6,7 @@ import org.jetbrains.skiko.redrawer.SoftwareRedrawer ...@@ -6,6 +6,7 @@ import org.jetbrains.skiko.redrawer.SoftwareRedrawer
import org.jetbrains.skiko.redrawer.Redrawer import org.jetbrains.skiko.redrawer.Redrawer
import org.jetbrains.skiko.redrawer.WindowsOpenGLRedrawer import org.jetbrains.skiko.redrawer.WindowsOpenGLRedrawer
import org.jetbrains.skiko.redrawer.Direct3DRedrawer import org.jetbrains.skiko.redrawer.Direct3DRedrawer
import org.jetbrains.skiko.redrawer.MetalRedrawer
import java.awt.Component import java.awt.Component
import java.awt.Window import java.awt.Window
import javax.swing.SwingUtilities import javax.swing.SwingUtilities
...@@ -38,6 +39,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -38,6 +39,7 @@ internal val platformOperations: PlatformOperations by lazy {
properties: SkiaLayerProperties properties: SkiaLayerProperties
) = when(renderApi) { ) = when(renderApi) {
GraphicsApi.SOFTWARE -> SoftwareRedrawer(layer) GraphicsApi.SOFTWARE -> SoftwareRedrawer(layer)
GraphicsApi.METAL -> MetalRedrawer(layer, properties)
else -> MacOsOpenGLRedrawer(layer, properties) else -> MacOsOpenGLRedrawer(layer, properties)
} }
} }
......
...@@ -41,6 +41,7 @@ open class SkiaLayer( ...@@ -41,6 +41,7 @@ open class SkiaLayer(
val initialRenderApi = fallbackRenderApiQueue.removeAt(0) val initialRenderApi = fallbackRenderApiQueue.removeAt(0)
contextHandler = createContextHandler(this, initialRenderApi) contextHandler = createContextHandler(this, initialRenderApi)
redrawer = platformOperations.createRedrawer(this, initialRenderApi, properties) redrawer = platformOperations.createRedrawer(this, initialRenderApi, properties)
println("init ${redrawer == null}")
redrawer?.syncSize() redrawer?.syncSize()
redraw() redraw()
} }
...@@ -57,12 +58,14 @@ open class SkiaLayer( ...@@ -57,12 +58,14 @@ open class SkiaLayer(
} }
override fun setBounds(x: Int, y: Int, width: Int, height: Int) { override fun setBounds(x: Int, y: Int, width: Int, height: Int) {
println("setBounds: $x $y $width $height ${redrawer == null}")
super.setBounds(x, y, width, height) super.setBounds(x, y, width, height)
redrawer?.syncSize() redrawer?.syncSize()
redraw() redraw()
} }
override fun paint(g: Graphics) { override fun paint(g: Graphics) {
println("paint ${redrawer == null}")
super.paint(g) super.paint(g)
redrawer?.syncSize() redrawer?.syncSize()
redrawer?.redrawImmediately() redrawer?.redrawImmediately()
......
...@@ -43,7 +43,7 @@ internal object SkikoProperties { ...@@ -43,7 +43,7 @@ internal object SkikoProperties {
private fun bestRenderApiForCurrentOS(): GraphicsApi { private fun bestRenderApiForCurrentOS(): GraphicsApi {
when(hostOs) { when(hostOs) {
OS.MacOS -> return GraphicsApi.OPENGL OS.MacOS -> return GraphicsApi.METAL
OS.Linux -> return GraphicsApi.OPENGL OS.Linux -> return GraphicsApi.OPENGL
OS.Windows -> return GraphicsApi.DIRECT3D OS.Windows -> return GraphicsApi.DIRECT3D
} }
...@@ -54,8 +54,8 @@ internal object SkikoProperties { ...@@ -54,8 +54,8 @@ internal object SkikoProperties {
var renderApiList = mutableListOf<GraphicsApi>() var renderApiList = mutableListOf<GraphicsApi>()
when (hostOs) { when (hostOs) {
OS.MacOS -> renderApiList = mutableListOf(GraphicsApi.OPENGL, GraphicsApi.SOFTWARE)
OS.Linux -> renderApiList = mutableListOf(GraphicsApi.OPENGL, GraphicsApi.SOFTWARE) OS.Linux -> renderApiList = mutableListOf(GraphicsApi.OPENGL, GraphicsApi.SOFTWARE)
OS.MacOS -> renderApiList = mutableListOf(GraphicsApi.METAL, GraphicsApi.OPENGL, GraphicsApi.SOFTWARE)
OS.Windows -> renderApiList = mutableListOf(GraphicsApi.DIRECT3D, GraphicsApi.OPENGL, GraphicsApi.SOFTWARE) OS.Windows -> renderApiList = mutableListOf(GraphicsApi.DIRECT3D, GraphicsApi.OPENGL, GraphicsApi.SOFTWARE)
} }
renderApiList.remove(head) renderApiList.remove(head)
......
...@@ -17,6 +17,7 @@ internal fun createContextHandler(layer: SkiaLayer, renderApi: GraphicsApi): Con ...@@ -17,6 +17,7 @@ internal fun createContextHandler(layer: SkiaLayer, renderApi: GraphicsApi): Con
GraphicsApi.SOFTWARE -> SoftwareContextHandler(layer) GraphicsApi.SOFTWARE -> SoftwareContextHandler(layer)
GraphicsApi.OPENGL -> OpenGLContextHandler(layer) GraphicsApi.OPENGL -> OpenGLContextHandler(layer)
GraphicsApi.DIRECT3D -> Direct3DContextHandler(layer) GraphicsApi.DIRECT3D -> Direct3DContextHandler(layer)
GraphicsApi.METAL -> MetalContextHandler(layer)
else -> TODO("Unsupported yet.") else -> TODO("Unsupported yet.")
} }
} }
......
package org.jetbrains.skiko.context package org.jetbrains.skiko.context
import java.lang.ref.Reference
import org.jetbrains.skija.ColorSpace import org.jetbrains.skija.ColorSpace
import org.jetbrains.skija.impl.Native
import org.jetbrains.skija.Surface import org.jetbrains.skija.Surface
import org.jetbrains.skija.SurfaceColorFormat import org.jetbrains.skija.SurfaceColorFormat
import org.jetbrains.skija.SurfaceOrigin import org.jetbrains.skija.SurfaceOrigin
import org.jetbrains.skiko.GraphicsApi import org.jetbrains.skiko.GraphicsApi
import org.jetbrains.skiko.SkiaLayer import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.makeMetalContext import org.jetbrains.skiko.redrawer.MetalRedrawer
import org.jetbrains.skiko.makeMetalRenderTarget import javax.swing.SwingUtilities.convertPoint
import org.jetbrains.skiko.redrawer.Redrawer import javax.swing.SwingUtilities.getRootPane
internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer) { internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
val metalRedrawer: MetalRedrawer
get() = layer.redrawer!! as MetalRedrawer
var device: Long = 0
override fun initContext(): Boolean { override fun initContext(): Boolean {
try { try {
if (context == null) { if (context == null) {
context = makeMetalContext() device = metalRedrawer.createDevice()
if (device == 0L) {
throw Exception("Failed to create Metal device.")
}
context = metalRedrawer.makeContext(device)
} }
} catch (e: Exception) { } catch (e: Exception) {
println("Failed to create Skia Metal context!") println("${e.message}\nFailed to create Skia Metal context!")
return false return false
} }
return true return true
...@@ -30,16 +40,22 @@ internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer) { ...@@ -30,16 +40,22 @@ internal class MetalContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
val w = (layer.width * scale).toInt().coerceAtLeast(0) val w = (layer.width * scale).toInt().coerceAtLeast(0)
val h = (layer.height * scale).toInt().coerceAtLeast(0) val h = (layer.height * scale).toInt().coerceAtLeast(0)
renderTarget = makeMetalRenderTarget(w, h, 0) renderTarget = metalRedrawer.makeRenderTarget(device, w, h)
surface = Surface.makeFromBackendRenderTarget( surface = Surface.makeFromBackendRenderTarget(
context!!, context!!,
renderTarget!!, renderTarget!!,
SurfaceOrigin.BOTTOM_LEFT, SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.RGBA_8888, SurfaceColorFormat.BGRA_8888,
ColorSpace.getSRGB() ColorSpace.getSRGB()
) )
canvas = surface!!.canvas canvas = surface!!.canvas
} }
override fun flush() {
super.flush()
surface!!.flushAndSubmit()
metalRedrawer.finishFrame(device)
}
} }
...@@ -106,6 +106,7 @@ internal class MacOsOpenGLRedrawer( ...@@ -106,6 +106,7 @@ internal class MacOsOpenGLRedrawer(
} }
override fun syncSize() { override fun syncSize() {
println("syncsize")
val globalPosition = convertPoint(layer, layer.x, layer.y, getRootPane(layer)) val globalPosition = convertPoint(layer, layer.x, layer.y, getRootPane(layer))
setContentScale(containerLayerPtr, layer.contentScale) setContentScale(containerLayerPtr, layer.contentScale)
setContentScale(drawLayer.ptr, layer.contentScale) setContentScale(drawLayer.ptr, layer.contentScale)
......
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
import org.jetbrains.skiko.useDrawingSurfacePlatformInfo
import javax.swing.SwingUtilities.convertPoint
import javax.swing.SwingUtilities.getRootPane
internal class MetalRedrawer(
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())
frameDispatcher.scheduleFrame()
}
private fun update(nanoTime: Long) {
layer.update(nanoTime)
}
private fun draw() {
layer.draw()
}
override fun syncSize() {
println("syncsize")
val globalPosition = convertPoint(layer, layer.x, layer.y, getRootPane(layer))
setContentScale(device, layer.contentScale)
resizeLayers(device,
globalPosition.x,
globalPosition.y,
layer.width.coerceAtLeast(0),
layer.height.coerceAtLeast(0)
)
}
fun makeContext(device: Long) = DirectContext(
makeMetalContext(device)
)
fun makeRenderTarget(device: Long, width: Int, height: Int) = BackendRenderTarget(
makeMetalRenderTarget(device, width, height)
)
fun createDevice(): Long {
device = layer.useDrawingSurfacePlatformInfo(::createMetalDevice)
return device
}
private external fun createMetalDevice(platformInfo: Long): Long
private external fun makeMetalContext(device: Long): Long
private external fun makeMetalRenderTarget(device: Long, width: Int, height: Int): Long
private external fun disposeDevice(device: Long)
external fun finishFrame(device: Long)
external fun resizeLayers(device: Long, x: Int, y: Int, width: Int, height: Int)
external fun setContentScale(device: Long, contentScale: Float)
}
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
- (void) disposeLayer:(JNIEnv *) env - (void) disposeLayer:(JNIEnv *) env
{ {
(*env)->DeleteGlobalRef(env, self.canvasGlobalRef); env->DeleteGlobalRef(self.canvasGlobalRef);
self.canvasGlobalRef = NULL; self.canvasGlobalRef = NULL;
self.container = NULL; self.container = NULL;
self.window = NULL; self.window = NULL;
...@@ -71,7 +71,7 @@ LayerHandler * findByObject(JNIEnv *env, jobject object) ...@@ -71,7 +71,7 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
} }
for (LayerHandler* layer in layerStorage) for (LayerHandler* layer in layerStorage)
{ {
if ((*env)->IsSameObject(env, object, layer.canvasGlobalRef) == JNI_TRUE) if (env->IsSameObject(object, layer.canvasGlobalRef) == JNI_TRUE)
{ {
return layer; return layer;
} }
...@@ -79,6 +79,9 @@ LayerHandler * findByObject(JNIEnv *env, jobject object) ...@@ -79,6 +79,9 @@ LayerHandler * findByObject(JNIEnv *env, jobject object)
return NULL; return NULL;
} }
extern "C"
{
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_nativeInit(JNIEnv *env, jobject canvas, jlong platformInfoPtr) JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_nativeInit(JNIEnv *env, jobject canvas, jlong platformInfoPtr)
{ {
if (layerStorage == nil) if (layerStorage == nil)
...@@ -91,7 +94,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_nativeInit(JNIEnv ...@@ -91,7 +94,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_nativeInit(JNIEnv
LayerHandler *layersSet = [[LayerHandler alloc] init]; LayerHandler *layersSet = [[LayerHandler alloc] init];
layersSet.container = [dsi_mac windowLayer]; layersSet.container = [dsi_mac windowLayer];
jobject canvasGlobalRef = (*env)->NewGlobalRef(env, canvas); jobject canvasGlobalRef = env->NewGlobalRef(canvas);
[layersSet setCanvasGlobalRef: canvasGlobalRef]; [layersSet setCanvasGlobalRef: canvasGlobalRef];
NSMutableArray<NSWindow *> *windows = [NSMutableArray arrayWithArray: [[NSApplication sharedApplication] windows]]; NSMutableArray<NSWindow *> *windows = [NSMutableArray arrayWithArray: [[NSApplication sharedApplication] windows]];
...@@ -153,3 +156,5 @@ void getMetalDeviceAndQueue(void** device, void** queue) ...@@ -153,3 +156,5 @@ void getMetalDeviceAndQueue(void** device, void** queue)
*device = (__bridge void*)fDevice; *device = (__bridge void*)fDevice;
*queue = (__bridge void*)fQueue; *queue = (__bridge void*)fQueue;
} }
} // extern C
\ No newline at end of file
#ifdef SK_METAL
#import <jawt.h>
#import <jawt_md.h>
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
#import <GrBackendSurface.h>
#import <GrDirectContext.h>
#import <mtl/GrMtlBackendContext.h>
#import <mtl/GrMtlTypes.h>
JavaVM *jvmMetal = NULL;
@interface AWTMetalLayer : CAMetalLayer
@property jobject javaRef;
@end
@interface MetalDevice : NSObject
@property (retain, strong) CALayer *container;
@property (retain, strong) AWTMetalLayer *layer;
@property (retain, strong) id<MTLDevice> device;
@property (retain, strong) id<MTLCommandQueue> queue;
@property (retain, strong) id<CAMetalDrawable> drawableHandle;
@end
@implementation AWTMetalLayer
- (id)init
{
self = [super init];
assert(self != NULL);
[self removeAllAnimations];
[self setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[self setNeedsDisplayOnBoundsChange: YES];
return self;
}
@end
@implementation MetalDevice
- (id) init
{
self = [super init];
if (self)
{
self.layer = nil;
self.device = nil;
self.queue = nil;
self.drawableHandle = nil;
}
return self;
}
@end
extern "C"
{
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_makeMetalContext(
JNIEnv* env, jobject redrawer, jlong devicePtr)
{
MetalDevice *device = (MetalDevice *) devicePtr;
GrMtlBackendContext backendContext = {};
backendContext.fDevice.retain((GrMTLHandle) device.device);
backendContext.fQueue.retain((GrMTLHandle) device.queue);
return (jlong) GrDirectContext::MakeMetal(backendContext).release();
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_makeMetalRenderTarget(
JNIEnv * env, jobject redrawer, jlong devicePtr, jint width, jint height)
{
MetalDevice *device = (MetalDevice *) devicePtr;
device.layer.drawableSize = CGRectMake(0, 0, width, height).size;
id<CAMetalDrawable> currentDrawable = [device.layer nextDrawable];
GrMtlTextureInfo info;
info.fTexture.retain(currentDrawable.texture);
GrBackendRenderTarget* renderTarget = new GrBackendRenderTarget(width, height, 0, info);
device.drawableHandle = currentDrawable;
return (jlong) renderTarget;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMetalDevice(
JNIEnv *env, jobject redrawer, jlong platformInfoPtr)
{
MetalDevice *device = [MetalDevice new];
env->GetJavaVM(&jvmMetal);
NSObject<JAWT_SurfaceLayers>* dsi_mac = (__bridge NSObject<JAWT_SurfaceLayers> *) platformInfoPtr;
CALayer *container = [dsi_mac windowLayer];
[container removeAllAnimations];
[container setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[container setNeedsDisplayOnBoundsChange: YES];
AWTMetalLayer *layer = [AWTMetalLayer new];
[container addSublayer: layer];
layer.javaRef = env->NewGlobalRef(redrawer);
id<MTLDevice> fDevice = MTLCreateSystemDefaultDevice();
id<MTLCommandQueue> fQueue = [fDevice newCommandQueue];
device.container = container;
device.layer = layer;
device.device = fDevice;
device.queue = fQueue;
device.layer.device = device.device;
device.layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
device.layer.contentsGravity = kCAGravityTopLeft;
CGFloat transparent[] = { 0.0f, 0.0f, 0.0f, 0.0f };
device.layer.backgroundColor = CGColorCreate(CGColorSpaceCreateDeviceRGB(), transparent);
device.layer.opaque = NO;
return (jlong) device;
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_resizeLayers(
JNIEnv *env, jobject redrawer, jlong devicePtr, jint x, jint y, jint width, jint height)
{
MetalDevice *device = (MetalDevice *) devicePtr;
y = (int)device.container.frame.size.height - y - height;
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
device.layer.frame = CGRectMake(x, y, width, height);
[CATransaction commit];
[device.layer performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:0 waitUntilDone:NO];
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_setContentScale(JNIEnv *env, jobject obj, jlong devicePtr, jfloat contentScale)
{
MetalDevice *device = (MetalDevice *) devicePtr;
assert(contentScale != 0);
device.layer.contentsScale = contentScale;
device.container.contentsScale = contentScale;
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_finishFrame(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
MetalDevice *device = (MetalDevice *) devicePtr;
id<CAMetalDrawable> currentDrawable = device.drawableHandle;
id<MTLCommandBuffer> commandBuffer = [device.queue commandBuffer];
commandBuffer.label = @"Present";
[commandBuffer presentDrawable:currentDrawable];
[commandBuffer commit];
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_disposeDevice(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
MetalDevice *device = (MetalDevice *) devicePtr;
[device.layer removeFromSuperlayer];
env->DeleteGlobalRef(device.layer.javaRef);
[device.layer release];
[device release];
}
} // extern C
#endif
\ No newline at end of file
...@@ -36,13 +36,13 @@ JavaVM *jvm = NULL; ...@@ -36,13 +36,13 @@ JavaVM *jvm = NULL;
{ {
assert(jvm != NULL); assert(jvm != NULL);
JNIEnv *env; JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); jvm->AttachCurrentThread((void **)&env, NULL);
static jclass cls = NULL; static jclass cls = NULL;
static jmethodID method = NULL; static jmethodID method = NULL;
if (!cls) cls = (*env)->GetObjectClass(env, self.javaRef); if (!cls) cls = env->GetObjectClass(self.javaRef);
if (!method) method = (*env)->GetMethodID(env, cls, "canDraw", "()Z"); if (!method) method = env->GetMethodID(cls, "canDraw", "()Z");
return (*env)->CallBooleanMethod(env, self.javaRef, method); return env->CallBooleanMethod(self.javaRef, method);
} }
-(void)drawInCGLContext:(CGLContextObj)ctx -(void)drawInCGLContext:(CGLContextObj)ctx
...@@ -54,22 +54,25 @@ JavaVM *jvm = NULL; ...@@ -54,22 +54,25 @@ JavaVM *jvm = NULL;
assert(jvm != NULL); assert(jvm != NULL);
JNIEnv *env; JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); jvm->AttachCurrentThread((void **)&env, NULL);
static jclass cls = NULL; static jclass cls = NULL;
static jmethodID method = NULL; static jmethodID method = NULL;
if (!cls) cls = (*env)->GetObjectClass(env, self.javaRef); if (!cls) cls = env->GetObjectClass(self.javaRef);
if (!method) method = (*env)->GetMethodID(env, cls, "performDraw", "()V"); if (!method) method = env->GetMethodID(cls, "performDraw", "()V");
(*env)->CallVoidMethod(env, self.javaRef, method); env->CallVoidMethod(self.javaRef, method);
[super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts]; [super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts];
} }
@end @end
extern "C"
{
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_initContainer(JNIEnv *env, jobject redrawer, jlong platformInfoPtr) JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_initContainer(JNIEnv *env, jobject redrawer, jlong platformInfoPtr)
{ {
(*env)->GetJavaVM(env, &jvm); env->GetJavaVM(&jvm);
NSObject<JAWT_SurfaceLayers>* dsi_mac = (__bridge NSObject<JAWT_SurfaceLayers> *) platformInfoPtr; NSObject<JAWT_SurfaceLayers>* dsi_mac = (__bridge NSObject<JAWT_SurfaceLayers> *) platformInfoPtr;
...@@ -93,7 +96,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_ ...@@ -93,7 +96,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_
CALayer *container = (CALayer *) containerPtr; CALayer *container = (CALayer *) containerPtr;
AWTGLLayer *glLayer = [AWTGLLayer new]; AWTGLLayer *glLayer = [AWTGLLayer new];
glLayer.javaRef = (*env)->NewGlobalRef(env, layer); glLayer.javaRef = env->NewGlobalRef(layer);
[glLayer setNeedsDisplayOnBoundsChange: setNeedsDisplayOnBoundsChange]; [glLayer setNeedsDisplayOnBoundsChange: setNeedsDisplayOnBoundsChange];
[container addSublayer: glLayer]; [container addSublayer: glLayer];
...@@ -104,7 +107,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_d ...@@ -104,7 +107,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_MacOsOpenGLRedrawerKt_d
{ {
AWTGLLayer *glLayer = (AWTGLLayer *) ptr; AWTGLLayer *glLayer = (AWTGLLayer *) ptr;
[glLayer removeFromSuperlayer]; [glLayer removeFromSuperlayer];
(*env)->DeleteGlobalRef(env, glLayer.javaRef); env->DeleteGlobalRef(glLayer.javaRef);
[glLayer release]; [glLayer release];
} }
...@@ -139,3 +142,5 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AWTGLLayer_setFrame(JNI ...@@ -139,3 +142,5 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AWTGLLayer_setFrame(JNI
glLayer.frame = CGRectMake(x, y, width, height); glLayer.frame = CGRectMake(x, y, width, height);
[CATransaction commit]; [CATransaction commit];
} }
} // extern C
\ No newline at end of file
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