Skip to content

Commit

Permalink
Split Renderer into separate frontend and backend
Browse files Browse the repository at this point in the history
  • Loading branch information
justindriggers committed Feb 29, 2024
1 parent 05c786f commit 641d998
Show file tree
Hide file tree
Showing 32 changed files with 417 additions and 286 deletions.
2 changes: 2 additions & 0 deletions alfredo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ target_link_libraries(alfredo PRIVATE ${APPKIT_LIBRARY})

find_library(METALKIT_LIBRARY MetalKit REQUIRED)
target_link_libraries(alfredo PRIVATE ${METALKIT_LIBRARY})

target_include_directories(alfredo PRIVATE src)
8 changes: 3 additions & 5 deletions alfredo/src/appkit/AlfredoApplicationDelegate.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
#import <Cocoa/Cocoa.h>
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import <MetalRenderer.h>
#import <MetalRenderBackend.h>

#import "../metalkit/AlfredoViewDelegate.h"
#import "metalkit/AlfredoViewDelegate.h"

@interface AlfredoApplicationDelegate : NSObject <NSApplicationDelegate> {
@private
MTKView *view;
AlfredoViewDelegate *_viewDelegate;
}
@property(nonatomic, strong) NSWindow *window;
@property(nonatomic, strong) MTKView *view;
@property(nonatomic, retain) id<MTLDevice> device;
@property(nonatomic) linguine::render::MetalTextureLoader *metalTextureLoader;
@property(nonatomic) linguine::render::MetalRenderer *metalRenderer;
@end
60 changes: 42 additions & 18 deletions alfredo/src/appkit/AlfredoApplicationDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#import "AlfredoApplicationDelegate.h"

#import "../platform/MacMetalTextureLoader.h"
#import <AudioEngineAudioManager.h>

#import "platform/MacAudioEngineFileLoader.h"
#import "platform/MacInputManager.h"
#import "platform/MacLeaderboardManager.h"
#import "platform/MacLifecycleManager.h"
#import "platform/MacLogger.h"
#import "platform/MacMetalTextureLoader.h"
#import "platform/MacSaveManager.h"
#import "platform/MacTimeManager.h"

using namespace linguine;
using namespace linguine::alfredo;

@implementation AlfredoApplicationDelegate

Expand All @@ -18,8 +30,7 @@ - (void)createMenuBar {
NSMenuItem *appMenuItem = [[NSMenuItem alloc] init];
NSMenu *appMenu = [[NSMenu alloc] init];

NSString *appName =
[[NSRunningApplication currentApplication] localizedName];
NSString *appName = [[NSRunningApplication currentApplication] localizedName];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
action:@selector(terminate:)
keyEquivalent:@"q"];
Expand Down Expand Up @@ -58,34 +69,47 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification {
defer:NO];

self.device = MTLCreateSystemDefaultDevice();
view = [[MTKView alloc] initWithFrame:frame
self.view = [[MTKView alloc] initWithFrame:frame
device:self.device];
[view setPaused:YES];
[view setEnableSetNeedsDisplay:NO];
((CAMetalLayer*)[view layer]).displaySyncEnabled = NO;
[self.view setPaused:YES];
[self.view setEnableSetNeedsDisplay:NO];
((CAMetalLayer*)[self.view layer]).displaySyncEnabled = NO;

auto mtkTextureLoader = [[MTKTextureLoader alloc] initWithDevice:self.device];
self.metalTextureLoader = new linguine::alfredo::MacMetalTextureLoader(mtkTextureLoader);
self.metalRenderer = linguine::render::MetalRenderer::create(*(__bridge MTK::View*)view, false, *self.metalTextureLoader);
auto metalTextureLoader = std::make_unique<MacMetalTextureLoader>(mtkTextureLoader);
auto metalRenderBackend = render::MetalRenderBackend::create(*(__bridge MTK::View*)self.view, std::move(metalTextureLoader));

auto audioFileLoader = std::make_unique<MacAudioEngineFileLoader>();

_viewDelegate = [[AlfredoViewDelegate alloc] initWithRenderer:self.metalRenderer];
auto logger = std::make_shared<MacLogger>();
auto audioManager = std::make_shared<audio::AudioEngineAudioManager>(std::move(audioFileLoader));
auto inputManager = std::make_shared<MacInputManager>();
auto leaderboardManager = std::make_shared<MacLeaderboardManager>();
auto lifecycleManager = std::make_shared<MacLifecycleManager>();
auto renderer = std::make_shared<Renderer>(std::move(metalRenderBackend));
auto saveManager = std::make_shared<MacSaveManager>();
auto timeManager = std::make_shared<MacTimeManager>();
auto engine = std::make_unique<Engine>(logger, audioManager, inputManager, leaderboardManager, lifecycleManager, renderer, saveManager, timeManager);

[_viewDelegate mtkView:view drawableSizeWillChange:view.bounds.size];
[view setDelegate:_viewDelegate];
_viewDelegate = [[AlfredoViewDelegate alloc] initWithEngine:std::move(engine)];

[self.window setContentView:view];
[_viewDelegate mtkView:self.view drawableSizeWillChange:self.view.bounds.size];
[self.view setDelegate:_viewDelegate];

[self.window setContentView:self.view];
[self.window setTitle:@"Alfredo"];
// [self.window center];
[self.window makeKeyAndOrderFront:nil];

[NSApp activateIgnoringOtherApps:YES];
[NSApp stop:nil];

while (lifecycleManager->isRunning()) {
[self.view draw];
}
}
}

- (void)applicationWillTerminate:(NSNotification *)notification {
delete _metalRenderer;
delete _metalTextureLoader;
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return YES;
}

@end
29 changes: 1 addition & 28 deletions alfredo/src/main.mm
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
#import <memory>

#import <Cocoa/Cocoa.h>

#import <AudioEngineAudioManager.h>
#import <Engine.h>

#import "appkit/AlfredoApplicationDelegate.h"
#import "platform/MacAudioEngineFileLoader.h"
#import "platform/MacInputManager.h"
#import "platform/MacLeaderboardManager.h"
#import "platform/MacLifecycleManager.h"
#import "platform/MacLogger.h"
#import "platform/MacSaveManager.h"
#import "platform/MacTimeManager.h"

using namespace linguine;
using namespace linguine::alfredo;

int main(int argc, const char *argv[]) {
@autoreleasepool {
Expand All @@ -26,20 +13,6 @@ int main(int argc, const char *argv[]) {

[app run];

auto audioFileLoader = std::make_unique<MacAudioEngineFileLoader>();

auto logger = std::make_shared<MacLogger>();
auto audioManager = std::make_shared<audio::AudioEngineAudioManager>(std::move(audioFileLoader));
auto inputManager = std::make_shared<MacInputManager>();
auto leaderboardManager = std::make_shared<MacLeaderboardManager>();
auto lifecycleManager = std::make_shared<MacLifecycleManager>();
auto renderer = std::shared_ptr<Renderer>(appDelegate.metalRenderer);
auto saveManager = std::make_shared<MacSaveManager>();
auto timeManager = std::make_shared<MacTimeManager>();
auto engine = Engine(logger, audioManager, inputManager, leaderboardManager, lifecycleManager, renderer, saveManager, timeManager);

engine.run();

return 0;
}
}
}
8 changes: 5 additions & 3 deletions alfredo/src/metalkit/AlfredoViewDelegate.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#import <MetalKit/MetalKit.h>

#import <MetalRenderer.h>
#import <Engine.h>

using namespace linguine;

@interface AlfredoViewDelegate : NSObject <MTKViewDelegate> {
@private
linguine::render::MetalRenderer * _renderer;
std::unique_ptr<Engine> _engine;
}

- (instancetype)initWithRenderer:(linguine::render::MetalRenderer *)renderer;
- (instancetype)initWithEngine:(std::unique_ptr<Engine>)engine;

@end
8 changes: 4 additions & 4 deletions alfredo/src/metalkit/AlfredoViewDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@

@implementation AlfredoViewDelegate

- (instancetype)initWithRenderer:(linguine::render::MetalRenderer *)renderer {
- (instancetype)initWithEngine:(std::unique_ptr<Engine>)engine {
self = [super init];

if (self) {
_renderer = renderer;
_engine = std::move(engine);
}

return self;
}

- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
_renderer->resize(static_cast<uint16_t>(size.width), static_cast<uint16_t>(size.height));
_engine->get<linguine::Renderer>().resize(static_cast<uint16_t>(size.width), static_cast<uint16_t>(size.height));
}

- (void)drawInMTKView:(nonnull MTKView *)view {
_renderer->doDraw();
_engine->tick();
}

@end
2 changes: 1 addition & 1 deletion alfredo/src/platform/MacInputManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
void MacInputManager::pollEvents() {
@autoreleasepool {
NSApplication *app = NSApplication.sharedApplication;
auto window = [app mainWindow];
auto window = app.windows.firstObject;
auto frameSize = window.contentView.frame.size;

auto toRemove = std::vector<uint64_t>();
Expand Down
123 changes: 86 additions & 37 deletions carbonara/app/src/main/cpp/ApplicationAdapter.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "ApplicationAdapter.h"

#include <AAudioAudioManager.h>
#include <OpenGLRenderer.h>
#include <OpenGLRenderBackend.h>

#include "platform/AndroidAAudioFileLoader.h"
#include "platform/AndroidInputManager.h"
Expand All @@ -15,6 +15,9 @@
namespace linguine::carbonara {

ApplicationAdapter::ApplicationAdapter(android_app& app) {
_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(_display, nullptr, nullptr);

constexpr EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
Expand All @@ -24,49 +27,32 @@ ApplicationAdapter::ApplicationAdapter(android_app& app) {
EGL_NONE
};

auto display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, nullptr, nullptr);

EGLint numConfigs;
eglChooseConfig(display, attribs, nullptr, 0, &numConfigs);
eglChooseConfig(_display, attribs, nullptr, 0, &numConfigs);

std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
eglChooseConfig(display, attribs, supportedConfigs.get(), numConfigs, &numConfigs);
auto supportedConfigs = std::vector<EGLConfig>(numConfigs);
eglChooseConfig(_display, attribs, supportedConfigs.data(), numConfigs, &numConfigs);

auto config = *std::find_if(
supportedConfigs.get(),
supportedConfigs.get() + numConfigs,
[&display](const EGLConfig &config) {
EGLint red, green, blue;
_config = *std::find_if(supportedConfigs.begin(), supportedConfigs.end(),
[this](const EGLConfig& config) {
EGLint red, green, blue;

if (eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red)
&& eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green)
&& eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue)) {
return red == 8 && green == 8 && blue == 8;
}
if (eglGetConfigAttrib(_display, config, EGL_RED_SIZE, &red)
&& eglGetConfigAttrib(_display, config, EGL_GREEN_SIZE, &green)
&& eglGetConfigAttrib(_display, config, EGL_BLUE_SIZE, &blue)) {
return red == 8 && green == 8 && blue == 8;
}

return false;
});
return false;
});

EGLint format;
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
EGLSurface surface = eglCreateWindowSurface(display, config, app.window, nullptr);
createSurface(app);
createContext();

EGLint contextAttribs[] = {
EGL_CONTEXT_MAJOR_VERSION, 3,
EGL_NONE
};
eglMakeCurrent(_display, _surface, _surface, _context);

EGLContext context = eglCreateContext(display, config, nullptr, contextAttribs);
eglMakeCurrent(display, surface, surface, context);

_display = display;
_surface = surface;
_context = context;

auto renderer = std::shared_ptr<render::OpenGLRenderer>(
render::OpenGLRenderer::create(std::make_unique<AndroidOpenGLFileLoader>(*app.activity->assetManager))
);
auto renderBackend = render::OpenGLRenderBackend::create(std::make_unique<AndroidOpenGLFileLoader>(*app.activity->assetManager));
auto renderer = std::make_shared<Renderer>(std::move(renderBackend));

auto audioManager = std::make_shared<audio::AAudioAudioManager>(
std::make_unique<AndroidAAudioFileLoader>(*app.activity->assetManager)
Expand Down Expand Up @@ -100,7 +86,7 @@ ApplicationAdapter::~ApplicationAdapter() {
}

eglTerminate(_display);
_context = EGL_NO_DISPLAY;
_display = EGL_NO_DISPLAY;
}
}

Expand All @@ -123,4 +109,67 @@ void ApplicationAdapter::tick() {
eglSwapBuffers(_display, _surface);
}

void ApplicationAdapter::onInitWindow(android_app& app) {
auto& renderer = _engine->get<Renderer>();

createSurface(app);

auto result = eglMakeCurrent(_display, _surface, _surface, _context);

if (!result) {
auto error = eglGetError();

if (error == EGL_CONTEXT_LOST) {
createContext();

eglMakeCurrent(_display, _surface, _surface, _context);

auto renderBackend = render::OpenGLRenderBackend::create(std::make_unique<AndroidOpenGLFileLoader>(*app.activity->assetManager));
renderer.setBackend(std::move(renderBackend));
} else {
auto message = "Error initializing window: " + std::to_string(error);
_engine->get<Logger>().log(message);
throw std::runtime_error(message);
}
}

EGLint width;
eglQuerySurface(_display, _surface, EGL_WIDTH, &width);

EGLint height;
eglQuerySurface(_display, _surface, EGL_HEIGHT, &height);

renderer.resize(width, height);
}

void ApplicationAdapter::onPause() {
_isPaused = true;
_engine->pause();
}

void ApplicationAdapter::onResume() {
_isPaused = false;
_engine->resume();
}

void ApplicationAdapter::onTerminateWindow() {
if (_surface != EGL_NO_SURFACE) {
eglDestroySurface(_display, _surface);
_surface = EGL_NO_SURFACE;
}
}

void ApplicationAdapter::createSurface(android_app& app) {
_surface = eglCreateWindowSurface(_display, _config, app.window, nullptr);
}

void ApplicationAdapter::createContext() {
EGLint contextAttribs[] = {
EGL_CONTEXT_MAJOR_VERSION, 3,
EGL_NONE
};

_context = eglCreateContext(_display, _config, nullptr, contextAttribs);
}

} // namespace linguine::carbonara

0 comments on commit 641d998

Please sign in to comment.