Skip to content

Commit

Permalink
Native, Managed, MetalContext
Browse files Browse the repository at this point in the history
  • Loading branch information
tonsky committed May 4, 2021
1 parent f5248b2 commit 74c41ff
Show file tree
Hide file tree
Showing 18 changed files with 329 additions and 46 deletions.
6 changes: 4 additions & 2 deletions macos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ else()
endif()

file(GLOB SOURCES_OBJC ${CMAKE_SOURCE_DIR}/src/*.mm)
file(GLOB SOURCES_CXX ${CMAKE_SOURCE_DIR}/src/*.cc)
add_library(jwm SHARED ${SOURCES_OBJC} ${SOURCES_CXX})
file(GLOB SOURCES_OBJC_IMPL ${CMAKE_SOURCE_DIR}/src/impl/*.mm)
add_library(jwm SHARED ${SOURCES_OBJC} ${SOURCES_OBJC_IMPL})
target_include_directories(jwm PRIVATE $ENV{JAVA_HOME}/include $ENV{JAVA_HOME}/include/darwin)
set_target_properties(jwm PROPERTIES OUTPUT_NAME "jwm_${ARCH}")

target_link_libraries(jwm
"-framework Cocoa"
"-framework AppKit"
"-framework CoreData"
"-framework QuartzCore"
"-framework Foundation"
"-framework Metal"
)
2 changes: 1 addition & 1 deletion macos/src/MainView.mm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <jni.h>
#include "Library.hh"
#include "impl/Library.hh"
#include "Window.hh"
#include "MainView.hh"

Expand Down
31 changes: 31 additions & 0 deletions macos/src/MetalContext.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once
#import <Cocoa/Cocoa.h>
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>

namespace jwm {
class MetalContext {
public:
MetalContext(bool vsync): fVsync(vsync) {}
~MetalContext();

void attach(NSView* mainView);
void swapBuffers();
void resize();

int fWidth = 0;
int fHeight = 0;
int fSampleCount = 1;
int fStencilBits = 8;
bool fVsync = true;
bool fValid = false;
id<MTLDevice> fDevice;
id<MTLCommandQueue> fQueue;
CAMetalLayer* fMetalLayer;
NSView* fMainView;
id<CAMetalDrawable> fDrawableHandle;
// id<MTLBinaryArchive> fPipelineArchive API_AVAILABLE(macos(11.0), ios(14.0));
};

void deleteMetalContext(MetalContext* instance);
}
96 changes: 96 additions & 0 deletions macos/src/MetalContext.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <jni.h>
#include "MetalContext.hh"
#import <QuartzCore/CAConstraintLayoutManager.h>

jwm::MetalContext::~MetalContext() {
// MetalWindowContext_mac
fMainView.layer = nil;
fMainView.wantsLayer = NO;

// MetalWindowContext
fMetalLayer = nil;
fValid = false;

CFRelease(fQueue);
CFRelease(fDevice);
}

void jwm::MetalContext::attach(NSView* mainView) {
fMainView = mainView;

// MetalWindowContext
fDevice = MTLCreateSystemDefaultDevice();
fQueue = [fDevice newCommandQueue];

// MetalWindowContext_mac
fMetalLayer = [CAMetalLayer layer];
fMetalLayer.device = fDevice;
fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;

this->resize();

fMetalLayer.displaySyncEnabled = fVsync ? YES : NO; // TODO: need solution for 10.12 or lower
fMetalLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
fMetalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
fMetalLayer.contentsGravity = kCAGravityTopLeft;
fMetalLayer.magnificationFilter = kCAFilterNearest;
NSColorSpace* cs = fMainView.window.colorSpace;
fMetalLayer.colorspace = cs.CGColorSpace;

fMainView.layer = fMetalLayer;
fMainView.wantsLayer = YES;

fValid = true;
}

void jwm::MetalContext::resize() {
// CGFloat backingScaleFactor = sk_app::GetBackingScaleFactor(fMainView);
NSScreen* screen = fMainView.window.screen ?: [NSScreen mainScreen];
CGFloat backingScaleFactor = screen.backingScaleFactor;

CGSize backingSize = fMainView.bounds.size;
backingSize.width *= backingScaleFactor;
backingSize.height *= backingScaleFactor;

fMetalLayer.drawableSize = backingSize;
fMetalLayer.contentsScale = backingScaleFactor;

fWidth = backingSize.width;
fHeight = backingSize.height;
}

// void jwm::MetalContext::swapBuffers() {
// id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle;

// id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]);
// commandBuffer.label = @"Present";

// [commandBuffer presentDrawable:currentDrawable];
// [commandBuffer commit];
// // ARC is off in sk_app, so we need to release the CF ref manually
// CFRelease(fDrawableHandle);
// fDrawableHandle = nil;
// }

// JNI

void jwm::deleteMetalContext(jwm::MetalContext* instance) {
delete instance;
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_jwm_MetalContext__1nGetFinalizer
(JNIEnv* env, jclass jclass) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&jwm::deleteMetalContext));
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_jwm_MetalContext__1nMake
(JNIEnv* env, jclass jclass, jboolean vsync) {
jwm::MetalContext* instance = new jwm::MetalContext(vsync);
return reinterpret_cast<jlong>(instance);
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_jwm_MetalContext__1nClose
(JNIEnv* env, jclass jclass, jboolean vsync) {
jwm::MetalContext* instance = new jwm::MetalContext(vsync);
delete instance;
}
23 changes: 6 additions & 17 deletions macos/src/Window.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,17 @@
namespace jwm {
class Window {
public:
Window(JNIEnv* env): fEnv(env) {
}

~Window() {
if (fEventListener)
fEnv->DeleteGlobalRef(fEventListener);
// this->closeWindow();
}

Window(JNIEnv* env): fEnv(env) {}
~Window();
bool init();
// void setTitle(const char*);
// void show();
// void onInval() {}
float scaleFactor() const;

// void closeWindow();

void onEvent(jobject event);

NSWindow* fNSWindow;
NSWindow* fNSWindow = nullptr;
// NSInteger fNSWindowNumber;
JNIEnv* fEnv;
JNIEnv* fEnv = nullptr;
jobject fEventListener = nullptr;
};

void deleteWindow(jwm::Window* instance);
}
35 changes: 25 additions & 10 deletions macos/src/Window.mm
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
#include <iostream>
#include <jni.h>
#include "Library.hh"
#include "impl/Library.hh"
#include "MainView.hh"
#include "MetalContext.hh"
#include <memory>
#include "Window.hh"
#include "WindowDelegate.hh"

jwm::Window::~Window() {
if (fEventListener)
fEnv->DeleteGlobalRef(fEventListener);
[fNSWindow close];
}

bool jwm::Window::init() {
// Create a delegate to track certain events
WindowDelegate* delegate = [[WindowDelegate alloc] initWithWindow:this];
if (nil == delegate) {
if (nil == delegate)
return false;
}

// Create Cocoa window
constexpr int initialWidth = 800;
Expand Down Expand Up @@ -62,6 +68,15 @@

// JNI

void jwm::deleteWindow(jwm::Window* instance) {
delete instance;
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_jwm_Window__1nGetFinalizer
(JNIEnv* env, jclass jclass) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&jwm::deleteWindow));
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_jwm_Window__1nMake
(JNIEnv* env, jclass jclass) {
std::unique_ptr<jwm::Window> instance(new jwm::Window(env));
Expand All @@ -79,17 +94,17 @@
instance->fEventListener = listener ? env->NewGlobalRef(listener) : nullptr;
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_jwm_Window__1nAttach
(JNIEnv* env, jclass jclass, jlong ptr, jlong contextPtr) {
jwm::Window* instance = reinterpret_cast<jwm::Window*>(static_cast<uintptr_t>(ptr));
jwm::MetalContext* context = reinterpret_cast<jwm::MetalContext*>(static_cast<uintptr_t>(contextPtr));
context->attach([instance->fNSWindow contentView]);
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_jwm_Window__1nShow
(JNIEnv* env, jclass jclass, jlong ptr) {
jwm::Window* instance = reinterpret_cast<jwm::Window*>(static_cast<uintptr_t>(ptr));
[instance->fNSWindow orderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
[instance->fNSWindow makeKeyAndOrderFront:NSApp];
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_jwm_Window__1nClose
(JNIEnv* env, jclass jclass, jlong ptr) {
jwm::Window* instance = reinterpret_cast<jwm::Window*>(static_cast<uintptr_t>(ptr));
[instance->fNSWindow close];
delete instance;
}
2 changes: 1 addition & 1 deletion macos/src/WindowDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <jni.h>
#include "Library.hh"
#include "impl/Library.hh"
#include "Window.hh"
#include "WindowDelegate.hh"

Expand Down
File renamed without changes.
File renamed without changes.
10 changes: 10 additions & 0 deletions macos/src/impl/Managed.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <jni.h>

typedef void (*FreeFunction)(void*);

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_jwm_impl_Managed__1nInvokeFinalizer
(JNIEnv* env, jclass jclass, jlong finalizerPtr, jlong ptr) {
void* instance = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
FreeFunction finalizer = reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(finalizerPtr));
finalizer(instance);
}
2 changes: 2 additions & 0 deletions shared/examples/SingleWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class SingleWindow {
public static void main(String[] args) {
App.init();
Window window = new Window();
MetalContext context = new MetalContext(true);
window.attach(context);
window.setEventListener(e -> {
System.out.println(e);
if (e instanceof CloseEvent) {
Expand Down
2 changes: 1 addition & 1 deletion shared/script/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def main():
common.fetch_maven('org.projectlombok', 'lombok', '1.18.20'),
common.fetch_maven('org.jetbrains', 'annotations', '19.0.0')
]
sources = glob.glob('src/*.java')
sources = glob.glob('src/impl/*.java') + glob.glob('src/*.java')
common.javac(classpath, sources, 'target/classes')
return 0

Expand Down
1 change: 1 addition & 0 deletions shared/src/App.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jetbrains.jwm;

import org.jetbrains.annotations.*;
import org.jetbrains.jwm.impl.*;

public class App {
static { Library.staticLoad(); }
Expand Down
22 changes: 22 additions & 0 deletions shared/src/MetalContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.jetbrains.jwm;

import java.util.function.*;
import lombok.*;
import org.jetbrains.annotations.*;
import org.jetbrains.jwm.impl.*;

public class MetalContext extends Managed {
static { Library.staticLoad(); }

@ApiStatus.Internal
public static class _FinalizerHolder {
public static final long PTR = _nGetFinalizer();
}

public MetalContext(boolean vsync) {
super(_nMake(vsync), _FinalizerHolder.PTR);
}

@ApiStatus.Internal public static native long _nGetFinalizer();
@ApiStatus.Internal public static native long _nMake(boolean vsync);
}
34 changes: 21 additions & 13 deletions shared/src/Window.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
import java.util.function.*;
import lombok.*;
import org.jetbrains.annotations.*;
import org.jetbrains.jwm.impl.*;

@ToString @EqualsAndHashCode
public class Window implements AutoCloseable {
public class Window extends Managed {
static { Library.staticLoad(); }

public final long _ptr;
@ApiStatus.Internal
public static class _FinalizerHolder {
public static final long PTR = _nGetFinalizer();
}

public MetalContext _context = null;

public Window() {
long ptr = _nMake();
if (ptr == 0)
throw new IllegalArgumentException("org.jetbrains.jwm.Window: Can't wrap nullptr");
_ptr = ptr;
super(_nMake(), _FinalizerHolder.PTR);
}

@NotNull @Contract("-> this")
Expand All @@ -24,18 +26,24 @@ public Window setEventListener(@NotNull Consumer<Event> eventListener) {
}

@NotNull @Contract("-> this")
public Window show() {
_nShow(_ptr);
public Window attach(MetalContext context) {
if (_context != null) {
context.close();
}
_nAttach(_ptr, context._ptr);
_context = context;
return this;
}

@Override
public void close() {
_nClose(_ptr);
@NotNull @Contract("-> this")
public Window show() {
_nShow(_ptr);
return this;
}

@ApiStatus.Internal public static native long _nGetFinalizer();
@ApiStatus.Internal public static native long _nMake();
@ApiStatus.Internal public static native void _nSetEventListener(long ptr, Consumer<Event> listener);
@ApiStatus.Internal public static native void _nAttach(long ptr, long contextPtr);
@ApiStatus.Internal public static native void _nShow(long ptr);
@ApiStatus.Internal public static native void _nClose(long ptr);
}
2 changes: 1 addition & 1 deletion shared/src/Library.java → shared/src/impl/Library.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.jetbrains.jwm;
package org.jetbrains.impl.jwm;

import java.io.*;
import java.net.*;
Expand Down
Loading

0 comments on commit 74c41ff

Please sign in to comment.