OS X event fixes and prep for Metal API

This commit is contained in:
Jack Andersen 2015-11-07 14:36:38 -10:00
parent 41cccf6b0d
commit 606e3676b1
9 changed files with 1669 additions and 124 deletions

View File

@ -40,9 +40,9 @@ elseif(APPLE)
list(APPEND PLAT_SRCS list(APPEND PLAT_SRCS
lib/mac/ApplicationCocoa.mm lib/mac/ApplicationCocoa.mm
lib/mac/WindowCocoa.mm lib/mac/WindowCocoa.mm
lib/mac/GLViewCocoa.mm
lib/inputdev/HIDListenerIOKit.cpp lib/inputdev/HIDListenerIOKit.cpp
lib/inputdev/HIDDeviceIOKit.cpp) lib/inputdev/HIDDeviceIOKit.cpp
lib/graphicsdev/Metal.mm)
list(APPEND PLAT_HDRS list(APPEND PLAT_HDRS
include/boo/graphicsdev/Metal.hpp) include/boo/graphicsdev/Metal.hpp)

View File

@ -4,7 +4,6 @@
#include "IGraphicsDataFactory.hpp" #include "IGraphicsDataFactory.hpp"
#include "IGraphicsCommandQueue.hpp" #include "IGraphicsCommandQueue.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include "glew.h"
#include <vector> #include <vector>
#include <unordered_set> #include <unordered_set>

View File

@ -2,12 +2,63 @@
#define GDEV_METAL_HPP #define GDEV_METAL_HPP
#include "IGraphicsDataFactory.hpp" #include "IGraphicsDataFactory.hpp"
#include "IGraphicsCommandQueue.hpp"
#include "boo/IGraphicsContext.hpp"
#include <vector>
#include <unordered_set>
namespace boo namespace boo
{ {
class MetalDataFactory : public IGraphicsDataFactory class MetalDataFactory : public IGraphicsDataFactory
{ {
IGraphicsContext* m_parent;
IGraphicsData* m_deferredData = nullptr;
std::unordered_set<IGraphicsData*> m_committedData;
public:
MetalDataFactory(IGraphicsContext* parent);
~MetalDataFactory() {}
Platform platform() const {return PlatformMetal;}
const char* platformName() const {return "Metal";}
IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
IGraphicsBufferS* newStaticBuffer(BufferUse use, std::unique_ptr<uint8_t[]>&& data, size_t stride, size_t count);
IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz);
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
std::unique_ptr<uint8_t[]>&& data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height, size_t samples);
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
size_t texCount, const char** texNames,
BlendFactor srcFac, BlendFactor dstFac,
bool depthTest, bool depthWrite, bool backfaceCulling);
IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* ebo,
size_t ubufCount, IGraphicsBuffer** ubufs,
size_t texCount, ITexture** texs);
void reset();
IGraphicsData* commit();
void destroyData(IGraphicsData*);
void destroyAllData();
};
struct MetalContext
{
struct Window
{
};
}; };
} }

View File

@ -1,4 +1,5 @@
#include "boo/graphicsdev/GL.hpp" #include "boo/graphicsdev/GL.hpp"
#include "boo/graphicsdev/glew.h"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include <vector> #include <vector>
#include <thread> #include <thread>

1256
lib/graphicsdev/Metal.mm Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
#include <thread> #include <thread>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/graphicsdev/Metal.hpp"
namespace boo {class ApplicationCocoa;} namespace boo {class ApplicationCocoa;}
@interface AppDelegate : NSObject <NSApplicationDelegate> @interface AppDelegate : NSObject <NSApplicationDelegate>
@ -16,7 +17,7 @@ namespace boo {class ApplicationCocoa;}
namespace boo namespace boo
{ {
IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx); IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx);
class ApplicationCocoa : public IApplication class ApplicationCocoa : public IApplication
{ {
@ -34,6 +35,8 @@ private:
/* All windows */ /* All windows */
std::unordered_map<NSWindow*, IWindow*> m_windows; std::unordered_map<NSWindow*, IWindow*> m_windows;
MetalContext m_metalCtx;
void _deletedWindow(IWindow* window) void _deletedWindow(IWindow* window)
{ {
m_windows.erase((NSWindow*)window->getPlatformHandle()); m_windows.erase((NSWindow*)window->getPlatformHandle());
@ -86,7 +89,7 @@ public:
NSText* aboutText = [[NSText alloc] initWithFrame:aboutCr]; NSText* aboutText = [[NSText alloc] initWithFrame:aboutCr];
[aboutText setEditable:NO]; [aboutText setEditable:NO];
[aboutText setAlignment:NSCenterTextAlignment]; [aboutText setAlignment:NSCenterTextAlignment];
[aboutText setString:@"\nRWK Authors\n\nJackoalan\nAntidote\n"]; [aboutText setString:@"\nBoo Authors\n\nJackoalan\nAntidote\n"];
[aboutPanel setContentView:aboutText]; [aboutPanel setContentView:aboutText];
appDelegate->aboutPanel = aboutPanel; appDelegate->aboutPanel = aboutPanel;
} }
@ -142,7 +145,7 @@ public:
IWindow* newWindow(const std::string& title) IWindow* newWindow(const std::string& title)
{ {
IWindow* newWindow = _WindowCocoaNew(title, m_lastGLCtx); IWindow* newWindow = _WindowCocoaNew(title, m_lastGLCtx, &m_metalCtx);
m_windows[(NSWindow*)newWindow->getPlatformHandle()] = newWindow; m_windows[(NSWindow*)newWindow->getPlatformHandle()] = newWindow;
return newWindow; return newWindow;
} }

View File

View File

@ -1,4 +1,6 @@
#include "boo/graphicsdev/GL.hpp" #include "boo/graphicsdev/GL.hpp"
#include "boo/graphicsdev/glew.h"
#include "boo/graphicsdev/Metal.hpp"
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#import <CoreVideo/CVDisplayLink.h> #import <CoreVideo/CVDisplayLink.h>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
@ -72,53 +74,110 @@ static const NSOpenGLPixelFormatAttribute* PF_TABLE[] =
PF_RGBAF32_Z24_ATTRS PF_RGBAF32_Z24_ATTRS
}; };
namespace boo {class GraphicsContextCocoa;} namespace boo
@interface GraphicsContextCocoaInternal : NSOpenGLView
{ {
class GraphicsContextCocoa : public IGraphicsContext
{
protected:
EGraphicsAPI m_api;
EPixelFormat m_pf;
IWindow* m_parentWindow;
CVDisplayLinkRef m_dispLink = nullptr;
GraphicsContextCocoa(EGraphicsAPI api, EPixelFormat pf, IWindow* parentWindow)
: m_api(api), m_pf(pf), m_parentWindow(parentWindow) {}
std::mutex m_dlmt;
std::condition_variable m_dlcv;
static CVReturn DLCallback(CVDisplayLinkRef CV_NONNULL displayLink,
const CVTimeStamp * CV_NONNULL inNow,
const CVTimeStamp * CV_NONNULL inOutputTime,
CVOptionFlags flagsIn,
CVOptionFlags * CV_NONNULL flagsOut,
GraphicsContextCocoa* CV_NULLABLE ctx)
{
ctx->m_dlcv.notify_one();
return kCVReturnSuccess;
}
~GraphicsContextCocoa()
{
if (m_dispLink)
{
CVDisplayLinkStop(m_dispLink);
CVDisplayLinkRelease(m_dispLink);
}
}
public:
IWindowCallback* m_callback = nullptr;
void waitForRetrace()
{
std::unique_lock<std::mutex> lk(m_dlmt);
m_dlcv.wait(lk);
}
};
class GraphicsContextCocoaGL;
class GraphicsContextCocoaMetal;
}
@interface BooCocoaResponder : NSResponder
{
@public
NSUInteger lastModifiers; NSUInteger lastModifiers;
boo::GraphicsContextCocoa* booContext; boo::GraphicsContextCocoa* booContext;
NSView* parentView;
} }
- (id)initWithBooContext:(boo::GraphicsContextCocoa*)bctx; - (id)initWithBooContext:(boo::GraphicsContextCocoa*)bctx View:(NSView*)view;
@end
@interface GraphicsContextCocoaGLInternal : NSOpenGLView
{
BooCocoaResponder* resp;
}
- (id)initWithBooContext:(boo::GraphicsContextCocoaGL*)bctx;
@end
@interface GraphicsContextCocoaMetalInternal : NSView
{
BooCocoaResponder* resp;
}
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx;
@end @end
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::WindowCocoa"); static LogVisor::LogModule Log("boo::WindowCocoa");
IGraphicsCommandQueue* _NewGLES3CommandQueue(IGraphicsContext* parent); IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent);
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, MetalContext::Window* windowCtx,
IGraphicsContext* parent);
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx); void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
class GraphicsContextCocoa : public IGraphicsContext class GraphicsContextCocoaGL : public GraphicsContextCocoa
{ {
GraphicsContextCocoaGLInternal* m_nsContext = nullptr;
EGraphicsAPI m_api;
EPixelFormat m_pf;
IWindow* m_parentWindow;
GraphicsContextCocoaInternal* m_nsContext = nullptr;
IGraphicsCommandQueue* m_commandQueue = nullptr; IGraphicsCommandQueue* m_commandQueue = nullptr;
IGraphicsDataFactory* m_dataFactory = nullptr; IGraphicsDataFactory* m_dataFactory = nullptr;
NSOpenGLContext* m_loadCtx = nullptr; NSOpenGLContext* m_loadCtx = nullptr;
CVDisplayLinkRef m_dispLink = nullptr;
public: public:
NSOpenGLContext* m_lastCtx = nullptr; NSOpenGLContext* m_lastCtx = nullptr;
IWindowCallback* m_callback = nullptr;
GraphicsContextCocoa(EGraphicsAPI api, IWindow* parentWindow, NSOpenGLContext* lastGLCtx) GraphicsContextCocoaGL(EGraphicsAPI api, IWindow* parentWindow, NSOpenGLContext* lastGLCtx)
: m_api(api), : GraphicsContextCocoa(api, PF_RGBA8, parentWindow),
m_pf(PF_RGBA8),
m_parentWindow(parentWindow),
m_lastCtx(lastGLCtx) m_lastCtx(lastGLCtx)
{} {
m_dataFactory = new GLDataFactory(this);
}
~GraphicsContextCocoa() ~GraphicsContextCocoaGL()
{ {
delete m_dataFactory; delete m_dataFactory;
delete m_commandQueue; delete m_commandQueue;
[m_nsContext release]; [m_nsContext release];
[m_loadCtx release]; [m_loadCtx release];
CVDisplayLinkStop(m_dispLink);
CVDisplayLinkRelease(m_dispLink);
} }
void _setCallback(IWindowCallback* cb) void _setCallback(IWindowCallback* cb)
@ -143,35 +202,16 @@ public:
m_pf = pf; m_pf = pf;
} }
std::mutex m_dlmt;
std::condition_variable m_dlcv;
static CVReturn DLCallback(CVDisplayLinkRef CV_NONNULL displayLink,
const CVTimeStamp * CV_NONNULL inNow,
const CVTimeStamp * CV_NONNULL inOutputTime,
CVOptionFlags flagsIn,
CVOptionFlags * CV_NONNULL flagsOut,
GraphicsContextCocoa* CV_NULLABLE ctx)
{
ctx->m_dlcv.notify_one();
return kCVReturnSuccess;
}
void waitForRetrace()
{
std::unique_lock<std::mutex> lk(m_dlmt);
m_dlcv.wait(lk);
}
void initializeContext() void initializeContext()
{ {
m_nsContext = [[GraphicsContextCocoaInternal alloc] initWithBooContext:this]; m_nsContext = [[GraphicsContextCocoaGLInternal alloc] initWithBooContext:this];
if (!m_nsContext) if (!m_nsContext)
Log.report(LogVisor::FatalError, "unable to make new NSOpenGLView"); Log.report(LogVisor::FatalError, "unable to make new NSOpenGLView");
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext]; [(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink); CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this); CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
CVDisplayLinkStart(m_dispLink); CVDisplayLinkStart(m_dispLink);
m_commandQueue = _NewGLCommandQueue(this);
} }
void makeCurrent() void makeCurrent()
@ -185,15 +225,11 @@ public:
IGraphicsCommandQueue* getCommandQueue() IGraphicsCommandQueue* getCommandQueue()
{ {
if (!m_commandQueue)
m_commandQueue = _NewGLES3CommandQueue(this);
return m_commandQueue; return m_commandQueue;
} }
IGraphicsDataFactory* getDataFactory() IGraphicsDataFactory* getDataFactory()
{ {
if (!m_dataFactory)
m_dataFactory = new GLDataFactory(this);
return m_dataFactory; return m_dataFactory;
} }
@ -208,7 +244,7 @@ public:
Log.report(LogVisor::FatalError, "unable to make load NSOpenGLContext"); Log.report(LogVisor::FatalError, "unable to make load NSOpenGLContext");
[m_loadCtx makeCurrentContext]; [m_loadCtx makeCurrentContext];
} }
return getDataFactory(); return m_dataFactory;
} }
void present() void present()
@ -218,7 +254,7 @@ public:
}; };
IGraphicsContext* _GraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api, IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow, NSOpenGLContext* lastGLCtx) IWindow* parentWindow, NSOpenGLContext* lastGLCtx)
{ {
if (api != IGraphicsContext::API_OPENGL_3_3 && api != IGraphicsContext::API_OPENGL_4_2) if (api != IGraphicsContext::API_OPENGL_3_3 && api != IGraphicsContext::API_OPENGL_4_2)
@ -252,42 +288,119 @@ IGraphicsContext* _GraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api,
if (api == IGraphicsContext::API_OPENGL_4_2) if (api == IGraphicsContext::API_OPENGL_4_2)
return NULL; return NULL;
return new GraphicsContextCocoa(api, parentWindow, lastGLCtx); return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx);
}
class GraphicsContextCocoaMetal : public GraphicsContextCocoa
{
GraphicsContextCocoaMetalInternal* m_nsContext = nullptr;
IGraphicsCommandQueue* m_commandQueue = nullptr;
IGraphicsDataFactory* m_dataFactory = nullptr;
MetalContext* m_metalCtx;
MetalContext::Window* m_metalWindowCtx;
public:
GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow,
MetalContext* metalCtx, MetalContext::Window* metalWindowCtx)
: GraphicsContextCocoa(api, PF_RGBA8, parentWindow),
m_metalCtx(metalCtx), m_metalWindowCtx(metalWindowCtx)
{
m_dataFactory = new MetalDataFactory(this);
}
~GraphicsContextCocoaMetal()
{
delete m_dataFactory;
delete m_commandQueue;
[m_nsContext release];
}
void _setCallback(IWindowCallback* cb)
{
m_callback = cb;
}
EGraphicsAPI getAPI() const
{
return m_api;
}
EPixelFormat getPixelFormat() const
{
return m_pf;
}
void setPixelFormat(EPixelFormat pf)
{
if (pf > PF_RGBAF32_Z24)
return;
m_pf = pf;
}
void initializeContext()
{
m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this];
if (!m_nsContext)
Log.report(LogVisor::FatalError, "unable to make new NSView for Metal");
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
CVDisplayLinkStart(m_dispLink);
m_commandQueue = _NewMetalCommandQueue(m_metalCtx, m_metalWindowCtx, this);
}
void makeCurrent()
{
}
void postInit()
{
}
IGraphicsCommandQueue* getCommandQueue()
{
return m_commandQueue;
}
IGraphicsDataFactory* getDataFactory()
{
return m_dataFactory;
}
IGraphicsDataFactory* getLoadContextDataFactory()
{
return m_dataFactory;
}
void present()
{
}
};
IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow,
MetalContext* metalCtx,
MetalContext::Window* metalWindowCtx)
{
if (api != IGraphicsContext::API_METAL)
return nullptr;
return new GraphicsContextCocoaMetal(api, parentWindow, metalCtx, metalWindowCtx);
} }
} }
@implementation GraphicsContextCocoaInternal @implementation BooCocoaResponder
- (id)initWithBooContext:(boo::GraphicsContextCocoa*)bctx - (id)initWithBooContext:(boo::GraphicsContextCocoa*)bctx View:(NSView*)view
{ {
lastModifiers = 0; lastModifiers = 0;
booContext = bctx; booContext = bctx;
boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat(); parentView = view;
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]];
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:nspf];
if (bctx->m_lastCtx)
{
NSOpenGLContext* sharedCtx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:bctx->m_lastCtx];
[self setOpenGLContext:sharedCtx];
[sharedCtx setView:self];
}
[nspf release];
return self; return self;
} }
- (void)reshape
{
boo::SWindowRect rect = {{int(self.frame.origin.x), int(self.frame.origin.y)},
{int(self.frame.size.width), int(self.frame.size.height)}};
booContext->m_callback->resized(rect);
[super reshape];
}
- (BOOL)acceptsTouchEvents
{
return YES;
}
static inline boo::EModifierKey getMod(NSUInteger flags) static inline boo::EModifierKey getMod(NSUInteger flags)
{ {
int ret = boo::MKEY_NONE; int ret = boo::MKEY_NONE;
@ -318,9 +431,9 @@ static inline boo::EMouseButton getButton(NSEvent* event)
{ {
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [self frame]; NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -335,9 +448,9 @@ static inline boo::EMouseButton getButton(NSEvent* event)
{ {
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [self frame]; NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -352,9 +465,9 @@ static inline boo::EMouseButton getButton(NSEvent* event)
{ {
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [self frame]; NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -369,9 +482,9 @@ static inline boo::EMouseButton getButton(NSEvent* event)
{ {
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [self frame]; NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -389,9 +502,9 @@ static inline boo::EMouseButton getButton(NSEvent* event)
boo::EMouseButton button = getButton(theEvent); boo::EMouseButton button = getButton(theEvent);
if (!button) if (!button)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [self frame]; NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -408,9 +521,9 @@ static inline boo::EMouseButton getButton(NSEvent* event)
boo::EMouseButton button = getButton(theEvent); boo::EMouseButton button = getButton(theEvent);
if (!button) if (!button)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [self frame]; NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -424,9 +537,11 @@ static inline boo::EMouseButton getButton(NSEvent* event)
{ {
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; if (theEvent.window == [parentView window] && NSPointInRect(liw, parentView.frame))
NSRect frame = [self frame]; {
float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -434,15 +549,19 @@ static inline boo::EMouseButton getButton(NSEvent* event)
{(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)} {(float)(liw.x / frame.size.width), (float)(liw.y / frame.size.height)}
}; };
booContext->m_callback->mouseMove(coord); booContext->m_callback->mouseMove(coord);
}
} }
- (void)mouseDragged:(NSEvent*)theEvent - (void)mouseDragged:(NSEvent*)theEvent
{ {
[self mouseMoved:theEvent]; [self mouseMoved:theEvent];
} }
- (void)rightMouseDragged:(NSEvent*)theEvent - (void)rightMouseDragged:(NSEvent*)theEvent
{ {
[self mouseMoved:theEvent]; [self mouseMoved:theEvent];
} }
- (void)otherMouseDragged:(NSEvent*)theEvent - (void)otherMouseDragged:(NSEvent*)theEvent
{ {
[self mouseMoved:theEvent]; [self mouseMoved:theEvent];
@ -452,9 +571,9 @@ static inline boo::EMouseButton getButton(NSEvent* event)
{ {
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSPoint liw = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil];
float pixelFactor = [[self window] backingScaleFactor]; float pixelFactor = [[parentView window] backingScaleFactor];
NSRect frame = [self frame]; NSRect frame = [parentView frame];
boo::SWindowCoord coord = boo::SWindowCoord coord =
{ {
{(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)}, {(unsigned)(liw.x * pixelFactor), (unsigned)(liw.y * pixelFactor)},
@ -641,7 +760,9 @@ static boo::ESpecialKey translateKeycode(short code)
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSString* chars = theEvent.characters; NSString* chars = theEvent.characters;
if ([chars length] == 0) if ([chars length] == 0 ||
[chars characterAtIndex:0] == '\n' ||
[chars characterAtIndex:0] == '\r')
booContext->m_callback->specialKeyDown(translateKeycode(theEvent.keyCode), booContext->m_callback->specialKeyDown(translateKeycode(theEvent.keyCode),
getMod(theEvent.modifierFlags), getMod(theEvent.modifierFlags),
theEvent.isARepeat); theEvent.isARepeat);
@ -669,20 +790,19 @@ static boo::ESpecialKey translateKeycode(short code)
if (!booContext->m_callback) if (!booContext->m_callback)
return; return;
NSUInteger modFlags = theEvent.modifierFlags; NSUInteger modFlags = theEvent.modifierFlags;
bool isRepeat = theEvent.isARepeat;
if (modFlags != lastModifiers) if (modFlags != lastModifiers)
{ {
NSUInteger changedFlags = modFlags ^ lastModifiers; NSUInteger changedFlags = modFlags ^ lastModifiers;
NSUInteger downFlags = changedFlags & modFlags; NSUInteger downFlags = changedFlags & modFlags;
if (downFlags & NSControlKeyMask) if (downFlags & NSControlKeyMask)
booContext->m_callback->modKeyDown(boo::MKEY_CTRL, isRepeat); booContext->m_callback->modKeyDown(boo::MKEY_CTRL, false);
if (downFlags & NSAlternateKeyMask) if (downFlags & NSAlternateKeyMask)
booContext->m_callback->modKeyDown(boo::MKEY_ALT, isRepeat); booContext->m_callback->modKeyDown(boo::MKEY_ALT, false);
if (downFlags & NSShiftKeyMask) if (downFlags & NSShiftKeyMask)
booContext->m_callback->modKeyDown(boo::MKEY_SHIFT, isRepeat); booContext->m_callback->modKeyDown(boo::MKEY_SHIFT, false);
if (downFlags & NSCommandKeyMask) if (downFlags & NSCommandKeyMask)
booContext->m_callback->modKeyDown(boo::MKEY_COMMAND, isRepeat); booContext->m_callback->modKeyDown(boo::MKEY_COMMAND, false);
NSUInteger upFlags = changedFlags & ~modFlags; NSUInteger upFlags = changedFlags & ~modFlags;
if (upFlags & NSControlKeyMask) if (upFlags & NSControlKeyMask)
@ -698,6 +818,94 @@ static boo::ESpecialKey translateKeycode(short code)
} }
} }
- (BOOL)acceptsTouchEvents
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
@end
@implementation GraphicsContextCocoaGLInternal
- (id)initWithBooContext:(boo::GraphicsContextCocoaGL*)bctx
{
resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self];
boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat();
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]];
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:nspf];
if (bctx->m_lastCtx)
{
NSOpenGLContext* sharedCtx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:bctx->m_lastCtx];
[self setOpenGLContext:sharedCtx];
[sharedCtx setView:self];
}
[nspf release];
return self;
}
- (void)dealloc
{
[resp release];
[super dealloc];
}
- (void)reshape
{
boo::SWindowRect rect = {{int(self.frame.origin.x), int(self.frame.origin.y)},
{int(self.frame.size.width), int(self.frame.size.height)}};
resp->booContext->m_callback->resized(rect);
[super reshape];
}
- (BOOL)acceptsTouchEvents
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (NSResponder*)nextResponder
{
return resp;
}
@end
@implementation GraphicsContextCocoaMetalInternal
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx
{
resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self];
return self;
}
- (void)dealloc
{
[resp release];
[super dealloc];
}
- (BOOL)acceptsTouchEvents
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (NSResponder*)nextResponder
{
return resp;
}
@end @end
namespace boo namespace boo
@ -711,12 +919,12 @@ class WindowCocoa : public IWindow
public: public:
WindowCocoa(const std::string& title, NSOpenGLContext* lastGLCtx) WindowCocoa(const std::string& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx)
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title]; m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title];
m_gfxCtx = _GraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this, lastGLCtx); m_gfxCtx = _GraphicsContextCocoaGLNew(IGraphicsContext::API_OPENGL_3_3, this, lastGLCtx);
m_gfxCtx->initializeContext(); m_gfxCtx->initializeContext();
}); });
} }
@ -840,6 +1048,33 @@ public:
return TOUCH_TRACKPAD; return TOUCH_TRACKPAD;
} }
void setStyle(EWindowStyle style)
{
if (style & STYLE_TITLEBAR)
m_nsWindow.titleVisibility = NSWindowTitleVisible;
else
m_nsWindow.titleVisibility = NSWindowTitleHidden;
if (style & STYLE_CLOSE)
m_nsWindow.styleMask |= NSClosableWindowMask;
else
m_nsWindow.styleMask &= ~NSClosableWindowMask;
if (style & STYLE_RESIZE)
m_nsWindow.styleMask |= NSResizableWindowMask;
else
m_nsWindow.styleMask &= ~NSResizableWindowMask;
}
EWindowStyle getStyle() const
{
int retval = 0;
retval |= m_nsWindow.titleVisibility == NSWindowTitleVisible ? STYLE_TITLEBAR : 0;
retval |= (m_nsWindow.styleMask & NSClosableWindowMask) ? STYLE_CLOSE : 0;
retval |= (m_nsWindow.styleMask & NSResizableWindowMask) ? STYLE_RESIZE: 0;
return EWindowStyle(retval);
}
void waitForRetrace() void waitForRetrace()
{ {
static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace(); static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace();
@ -867,9 +1102,9 @@ public:
}; };
IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx) IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx)
{ {
return new WindowCocoa(title, lastGLCtx); return new WindowCocoa(title, lastGLCtx, metalCtx);
} }
} }

View File

@ -457,7 +457,7 @@ int main(int argc, const boo::SystemChar** argv)
LogVisor::RegisterConsoleLogger(); LogVisor::RegisterConsoleLogger();
boo::TestApplicationCallback appCb; boo::TestApplicationCallback appCb;
int ret = ApplicationRun(boo::IApplication::PLAT_AUTO, int ret = ApplicationRun(boo::IApplication::PLAT_AUTO,
appCb, _S("rwk"), _S("RWK"), argc, argv); appCb, _S("boo"), _S("Boo"), argc, argv);
printf("IM DYING!!\n"); printf("IM DYING!!\n");
return ret; return ret;
} }