OS X fixes

This commit is contained in:
Jack Andersen 2016-02-24 11:07:48 -10:00
parent d657f3c8f8
commit b11b727c4d
4 changed files with 148 additions and 148 deletions

View File

@ -27,11 +27,12 @@ class MetalDataFactory : public IGraphicsDataFactory
std::unordered_set<struct MetalData*> m_committedData; std::unordered_set<struct MetalData*> m_committedData;
std::mutex m_committedMutex; std::mutex m_committedMutex;
struct MetalContext* m_ctx; struct MetalContext* m_ctx;
uint32_t m_sampleCount;
void destroyData(IGraphicsData*); void destroyData(IGraphicsData*);
void destroyAllData(); void destroyAllData();
public: public:
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx); MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount);
~MetalDataFactory() {} ~MetalDataFactory() {}
Platform platform() const {return Platform::Metal;} Platform platform() const {return Platform::Metal;}
@ -44,11 +45,11 @@ public:
const void* data, size_t sz); const void* data, size_t sz);
GraphicsDataToken GraphicsDataToken
newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt, newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz, ITextureS** texOut); const void* data, size_t sz, ITextureS*& texOut);
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz); const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height, size_t samples); ITextureR* newRenderTexture(size_t width, size_t height);
bool bindingNeedsVertexFormat() const {return false;} bool bindingNeedsVertexFormat() const {return false;}
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);

View File

@ -648,23 +648,14 @@ struct MetalCommandQueue : IGraphicsCommandQueue
setRenderTarget(m_boundTarget); setRenderTarget(m_boundTarget);
} }
MTLPrimitiveType m_primType = MTLPrimitiveTypeTriangle;
void setDrawPrimitive(Primitive prim)
{
if (prim == Primitive::Triangles)
m_primType = MTLPrimitiveTypeTriangle;
else if (prim == Primitive::TriStrips)
m_primType = MTLPrimitiveTypeTriangleStrip;
}
void draw(size_t start, size_t count) void draw(size_t start, size_t count)
{ {
[m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count]; [m_enc drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:start vertexCount:count];
} }
void drawIndexed(size_t start, size_t count) void drawIndexed(size_t start, size_t count)
{ {
[m_enc drawIndexedPrimitives:m_primType [m_enc drawIndexedPrimitives:MTLPrimitiveTypeTriangleStrip
indexCount:count indexCount:count
indexType:MTLIndexTypeUInt32 indexType:MTLIndexTypeUInt32
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
@ -673,12 +664,13 @@ struct MetalCommandQueue : IGraphicsCommandQueue
void drawInstances(size_t start, size_t count, size_t instCount) void drawInstances(size_t start, size_t count, size_t instCount)
{ {
[m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count instanceCount:instCount]; [m_enc drawPrimitives:MTLPrimitiveTypeTriangleStrip
vertexStart:start vertexCount:count instanceCount:instCount];
} }
void drawInstancesIndexed(size_t start, size_t count, size_t instCount) void drawInstancesIndexed(size_t start, size_t count, size_t instCount)
{ {
[m_enc drawIndexedPrimitives:m_primType [m_enc drawIndexedPrimitives:MTLPrimitiveTypeTriangleStrip
indexCount:count indexCount:count
indexType:MTLIndexTypeUInt32 indexType:MTLIndexTypeUInt32
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
@ -839,8 +831,8 @@ void MetalTextureD::unmap()
m_validSlots = 0; m_validSlots = 0;
} }
MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx) MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount)
: m_parent(parent), m_ctx(ctx) {} : m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount) {}
IGraphicsBufferS* MetalDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) IGraphicsBufferS* MetalDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
{ {
@ -871,12 +863,12 @@ ITextureS* MetalDataFactory::newStaticTexture(size_t width, size_t height, size_
} }
GraphicsDataToken GraphicsDataToken
MetalDataFactory::newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt, MetalDataFactory::newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz, ITextureS** texOut) const void* data, size_t sz, ITextureS*& texOut)
{ {
MetalTextureS* retval = new MetalTextureS(m_ctx, width, height, mips, fmt, data, sz); MetalTextureS* retval = new MetalTextureS(m_ctx, width, height, mips, fmt, data, sz);
MetalData* tokData = new struct MetalData(); MetalData* tokData = new struct MetalData();
tokData->m_STexs.emplace_back(retval); tokData->m_STexs.emplace_back(retval);
*texOut = retval; texOut = retval;
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
m_committedData.insert(tokData); m_committedData.insert(tokData);
@ -900,9 +892,9 @@ ITextureD* MetalDataFactory::newDynamicTexture(size_t width, size_t height, Text
m_deferredData->m_DTexs.emplace_back(retval); m_deferredData->m_DTexs.emplace_back(retval);
return retval; return retval;
} }
ITextureR* MetalDataFactory::newRenderTexture(size_t width, size_t height, size_t samples) ITextureR* MetalDataFactory::newRenderTexture(size_t width, size_t height)
{ {
MetalTextureR* retval = new MetalTextureR(m_ctx, width, height, samples); MetalTextureR* retval = new MetalTextureR(m_ctx, width, height, m_sampleCount);
if (!m_deferredData.get()) if (!m_deferredData.get())
m_deferredData.reset(new struct MetalData()); m_deferredData.reset(new struct MetalData());
m_deferredData->m_RTexs.emplace_back(retval); m_deferredData->m_RTexs.emplace_back(retval);

View File

@ -23,9 +23,10 @@ namespace boo {class ApplicationCocoa;}
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::ApplicationCocoa"); static LogVisor::LogModule Log("boo::ApplicationCocoa");
IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx); IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx,
MetalContext* metalCtx, uint32_t sampleCount);
class ApplicationCocoa : public IApplication class ApplicationCocoa : public IApplication
{ {
public: public:
@ -36,14 +37,14 @@ private:
const SystemString m_friendlyName; const SystemString m_friendlyName;
const SystemString m_pname; const SystemString m_pname;
const std::vector<SystemString> m_args; const std::vector<SystemString> m_args;
NSPanel* aboutPanel; NSPanel* aboutPanel;
/* All windows */ /* All windows */
std::unordered_map<uintptr_t, IWindow*> m_windows; std::unordered_map<uintptr_t, IWindow*> m_windows;
MetalContext m_metalCtx; MetalContext m_metalCtx;
void _deletedWindow(IWindow* window) void _deletedWindow(IWindow* window)
{ {
m_windows.erase(window->getPlatformHandle()); m_windows.erase(window->getPlatformHandle());
@ -62,11 +63,11 @@ public:
m_args(args) m_args(args)
{ {
[[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular];
/* Delegate (OS X callbacks) */ /* Delegate (OS X callbacks) */
m_appDelegate = [[AppDelegate alloc] initWithApp:this]; m_appDelegate = [[AppDelegate alloc] initWithApp:this];
[[NSApplication sharedApplication] setDelegate:m_appDelegate]; [[NSApplication sharedApplication] setDelegate:m_appDelegate];
/* App menu */ /* App menu */
NSMenu* rootMenu = [[NSMenu alloc] initWithTitle:@"main"]; NSMenu* rootMenu = [[NSMenu alloc] initWithTitle:@"main"];
NSMenu* appMenu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]]; NSMenu* appMenu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]];
@ -82,7 +83,7 @@ public:
[[rootMenu addItemWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()] [[rootMenu addItemWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]
action:nil keyEquivalent:@""] setSubmenu:appMenu]; action:nil keyEquivalent:@""] setSubmenu:appMenu];
[[NSApplication sharedApplication] setMainMenu:rootMenu]; [[NSApplication sharedApplication] setMainMenu:rootMenu];
/* Determine which graphics API to use */ /* Determine which graphics API to use */
#if BOO_HAS_METAL #if BOO_HAS_METAL
for (const SystemString& arg : args) for (const SystemString& arg : args)
@ -99,12 +100,12 @@ public:
Log.report(LogVisor::Info, "using OpenGL renderer"); Log.report(LogVisor::Info, "using OpenGL renderer");
#endif #endif
} }
EPlatformType getPlatformType() const EPlatformType getPlatformType() const
{ {
return EPlatformType::Cocoa; return EPlatformType::Cocoa;
} }
std::thread m_clientThread; std::thread m_clientThread;
int m_clientReturn = 0; int m_clientReturn = 0;
int run() int run()
@ -114,54 +115,54 @@ public:
{ {
/* Run app */ /* Run app */
m_clientReturn = m_callback.appMain(this); m_clientReturn = m_callback.appMain(this);
/* Cleanup here */ /* Cleanup here */
std::vector<std::unique_ptr<IWindow>> toDelete; std::vector<std::unique_ptr<IWindow>> toDelete;
toDelete.reserve(m_windows.size()); toDelete.reserve(m_windows.size());
for (auto& window : m_windows) for (auto& window : m_windows)
toDelete.emplace_back(window.second); toDelete.emplace_back(window.second);
}); });
/* Already in Cocoa's event loop; return now */ /* Already in Cocoa's event loop; return now */
return 0; return 0;
} }
void quit() void quit()
{ {
[NSApp terminate:nil]; [NSApp terminate:nil];
} }
const SystemString& getUniqueName() const const SystemString& getUniqueName() const
{ {
return m_uniqueName; return m_uniqueName;
} }
const SystemString& getFriendlyName() const const SystemString& getFriendlyName() const
{ {
return m_friendlyName; return m_friendlyName;
} }
const SystemString& getProcessName() const const SystemString& getProcessName() const
{ {
return m_pname; return m_pname;
} }
const std::vector<SystemString>& getArgs() const const std::vector<SystemString>& getArgs() const
{ {
return m_args; return m_args;
} }
IWindow* newWindow(const std::string& title) IWindow* newWindow(const std::string& title, uint32_t sampleCount)
{ {
IWindow* newWindow = _WindowCocoaNew(title, m_lastGLCtx, &m_metalCtx); IWindow* newWindow = _WindowCocoaNew(title, m_lastGLCtx, &m_metalCtx, sampleCount);
m_windows[newWindow->getPlatformHandle()] = newWindow; m_windows[newWindow->getPlatformHandle()] = newWindow;
return newWindow; return newWindow;
} }
/* Last GL context */ /* Last GL context */
NSOpenGLContext* m_lastGLCtx = nullptr; NSOpenGLContext* m_lastGLCtx = nullptr;
}; };
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx) void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx)
{ {
static_cast<ApplicationCocoa*>(APP)->m_lastGLCtx = lastGLCtx; static_cast<ApplicationCocoa*>(APP)->m_lastGLCtx = lastGLCtx;
@ -189,7 +190,7 @@ int ApplicationRun(IApplication::EPlatformType platform,
return static_cast<ApplicationCocoa*>(APP)->m_clientReturn; return static_cast<ApplicationCocoa*>(APP)->m_clientReturn;
} }
} }
} }
@implementation AppDelegate @implementation AppDelegate

View File

@ -23,7 +23,7 @@ namespace boo {class WindowCocoa; class GraphicsContextCocoa;}
- (void)setFrameDefault; - (void)setFrameDefault;
- (NSRect)genFrameDefault; - (NSRect)genFrameDefault;
@end @end
/* AppKit applies OpenGL much differently than other platforms /* AppKit applies OpenGL much differently than other platforms
* the NSOpenGLView class composes together all necessary * the NSOpenGLView class composes together all necessary
* OGL context members and provides the necessary event hooks * OGL context members and provides the necessary event hooks
@ -96,7 +96,7 @@ static const NSOpenGLPixelFormatAttribute* PF_TABLE[] =
namespace boo namespace boo
{ {
class GraphicsContextCocoa : public IGraphicsContext class GraphicsContextCocoa : public IGraphicsContext
{ {
protected: protected:
@ -104,13 +104,13 @@ protected:
EPixelFormat m_pf; EPixelFormat m_pf;
IWindow* m_parentWindow; IWindow* m_parentWindow;
CVDisplayLinkRef m_dispLink = nullptr; CVDisplayLinkRef m_dispLink = nullptr;
GraphicsContextCocoa(EGraphicsAPI api, EPixelFormat pf, IWindow* parentWindow) GraphicsContextCocoa(EGraphicsAPI api, EPixelFormat pf, IWindow* parentWindow)
: m_api(api), m_pf(pf), m_parentWindow(parentWindow) {} : m_api(api), m_pf(pf), m_parentWindow(parentWindow) {}
std::mutex m_dlmt; std::mutex m_dlmt;
std::condition_variable m_dlcv; std::condition_variable m_dlcv;
static CVReturn DLCallback(CVDisplayLinkRef displayLink, static CVReturn DLCallback(CVDisplayLinkRef displayLink,
const CVTimeStamp * inNow, const CVTimeStamp * inNow,
const CVTimeStamp * inOutputTime, const CVTimeStamp * inOutputTime,
@ -121,7 +121,7 @@ protected:
ctx->m_dlcv.notify_one(); ctx->m_dlcv.notify_one();
return kCVReturnSuccess; return kCVReturnSuccess;
} }
public: public:
~GraphicsContextCocoa() ~GraphicsContextCocoa()
{ {
@ -131,7 +131,7 @@ public:
CVDisplayLinkRelease(m_dispLink); CVDisplayLinkRelease(m_dispLink);
} }
} }
IWindowCallback* m_callback = nullptr; IWindowCallback* m_callback = nullptr;
void waitForRetrace() void waitForRetrace()
{ {
@ -162,7 +162,7 @@ class GraphicsContextCocoaMetal;
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx; - (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx;
- (void)reshapeHandler; - (void)reshapeHandler;
@end @end
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::WindowCocoa"); static LogVisor::LogModule Log("boo::WindowCocoa");
@ -170,54 +170,55 @@ IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent);
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
IGraphicsContext* parent); IGraphicsContext* parent);
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx); void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
class GraphicsContextCocoaGL : public GraphicsContextCocoa class GraphicsContextCocoaGL : public GraphicsContextCocoa
{ {
GraphicsContextCocoaGLInternal* m_nsContext = nullptr; GraphicsContextCocoaGLInternal* m_nsContext = nullptr;
IGraphicsCommandQueue* m_commandQueue = nullptr; IGraphicsCommandQueue* m_commandQueue = nullptr;
IGraphicsDataFactory* m_dataFactory = nullptr; IGraphicsDataFactory* m_dataFactory = nullptr;
NSOpenGLContext* m_mainCtx = nullptr; NSOpenGLContext* m_mainCtx = nullptr;
NSOpenGLContext* m_loadCtx = nullptr; NSOpenGLContext* m_loadCtx = nullptr;
public: public:
NSOpenGLContext* m_lastCtx = nullptr; NSOpenGLContext* m_lastCtx = nullptr;
GraphicsContextCocoaGL(EGraphicsAPI api, IWindow* parentWindow, NSOpenGLContext* lastGLCtx) GraphicsContextCocoaGL(EGraphicsAPI api, IWindow* parentWindow,
NSOpenGLContext* lastGLCtx, uint32_t sampleCount)
: GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow), : GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow),
m_lastCtx(lastGLCtx) m_lastCtx(lastGLCtx)
{ {
m_dataFactory = new GLDataFactory(this); m_dataFactory = new GLDataFactory(this, sampleCount);
} }
~GraphicsContextCocoaGL() ~GraphicsContextCocoaGL()
{ {
delete m_dataFactory; delete m_dataFactory;
delete m_commandQueue; delete m_commandQueue;
} }
void _setCallback(IWindowCallback* cb) void _setCallback(IWindowCallback* cb)
{ {
m_callback = cb; m_callback = cb;
} }
EGraphicsAPI getAPI() const EGraphicsAPI getAPI() const
{ {
return m_api; return m_api;
} }
EPixelFormat getPixelFormat() const EPixelFormat getPixelFormat() const
{ {
return m_pf; return m_pf;
} }
void setPixelFormat(EPixelFormat pf) void setPixelFormat(EPixelFormat pf)
{ {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
void initializeContext() void initializeContext()
{ {
m_nsContext = [[GraphicsContextCocoaGLInternal alloc] initWithBooContext:this]; m_nsContext = [[GraphicsContextCocoaGLInternal alloc] initWithBooContext:this];
@ -229,26 +230,26 @@ public:
CVDisplayLinkStart(m_dispLink); CVDisplayLinkStart(m_dispLink);
m_commandQueue = _NewGLCommandQueue(this); m_commandQueue = _NewGLCommandQueue(this);
} }
void makeCurrent() void makeCurrent()
{ {
[[m_nsContext openGLContext] makeCurrentContext]; [[m_nsContext openGLContext] makeCurrentContext];
} }
void postInit() void postInit()
{ {
} }
IGraphicsCommandQueue* getCommandQueue() IGraphicsCommandQueue* getCommandQueue()
{ {
return m_commandQueue; return m_commandQueue;
} }
IGraphicsDataFactory* getDataFactory() IGraphicsDataFactory* getDataFactory()
{ {
return m_dataFactory; return m_dataFactory;
} }
IGraphicsDataFactory* getMainContextDataFactory() IGraphicsDataFactory* getMainContextDataFactory()
{ {
if (!m_mainCtx) if (!m_mainCtx)
@ -261,7 +262,7 @@ public:
[m_mainCtx makeCurrentContext]; [m_mainCtx makeCurrentContext];
return m_dataFactory; return m_dataFactory;
} }
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
if (!m_loadCtx) if (!m_loadCtx)
@ -274,27 +275,28 @@ public:
[m_loadCtx makeCurrentContext]; [m_loadCtx makeCurrentContext];
return m_dataFactory; return m_dataFactory;
} }
void present() void present()
{ {
[[m_nsContext openGLContext] flushBuffer]; [[m_nsContext openGLContext] flushBuffer];
} }
BooCocoaResponder* responder() const BooCocoaResponder* responder() const
{ {
if (!m_nsContext) if (!m_nsContext)
return nullptr; return nullptr;
return m_nsContext->resp; return m_nsContext->resp;
} }
}; };
IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api, IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow, NSOpenGLContext* lastGLCtx) IWindow* parentWindow, NSOpenGLContext* lastGLCtx,
uint32_t sampleCount)
{ {
if (api != IGraphicsContext::EGraphicsAPI::OpenGL3_3 && api != IGraphicsContext::EGraphicsAPI::OpenGL4_2) if (api != IGraphicsContext::EGraphicsAPI::OpenGL3_3 && api != IGraphicsContext::EGraphicsAPI::OpenGL4_2)
return NULL; return NULL;
/* Create temporary context to query GL version */ /* Create temporary context to query GL version */
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS]; NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS];
if (!nspf) if (!nspf)
@ -314,65 +316,65 @@ IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
[NSOpenGLContext clearCurrentContext]; [NSOpenGLContext clearCurrentContext];
if (!glVersion) if (!glVersion)
return NULL; return NULL;
if (major > 4 || (major == 4 && minor >= 2)) if (major > 4 || (major == 4 && minor >= 2))
api = IGraphicsContext::EGraphicsAPI::OpenGL4_2; api = IGraphicsContext::EGraphicsAPI::OpenGL4_2;
else if (major == 3 && minor >= 3) else if (major == 3 && minor >= 3)
if (api == IGraphicsContext::EGraphicsAPI::OpenGL4_2) if (api == IGraphicsContext::EGraphicsAPI::OpenGL4_2)
return NULL; return NULL;
return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx); return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx, sampleCount);
} }
#if BOO_HAS_METAL #if BOO_HAS_METAL
class GraphicsContextCocoaMetal : public GraphicsContextCocoa class GraphicsContextCocoaMetal : public GraphicsContextCocoa
{ {
GraphicsContextCocoaMetalInternal* m_nsContext = nullptr; GraphicsContextCocoaMetalInternal* m_nsContext = nullptr;
IGraphicsCommandQueue* m_commandQueue = nullptr; IGraphicsCommandQueue* m_commandQueue = nullptr;
IGraphicsDataFactory* m_dataFactory = nullptr; IGraphicsDataFactory* m_dataFactory = nullptr;
public: public:
IWindow* m_parentWindow; IWindow* m_parentWindow;
MetalContext* m_metalCtx; MetalContext* m_metalCtx;
GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow, GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow,
MetalContext* metalCtx) MetalContext* metalCtx, uint32_t sampleCount)
: GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow), : GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow),
m_parentWindow(parentWindow), m_metalCtx(metalCtx) m_parentWindow(parentWindow), m_metalCtx(metalCtx)
{ {
m_dataFactory = new MetalDataFactory(this, metalCtx); m_dataFactory = new MetalDataFactory(this, metalCtx, sampleCount);
} }
~GraphicsContextCocoaMetal() ~GraphicsContextCocoaMetal()
{ {
delete m_dataFactory; delete m_dataFactory;
delete m_commandQueue; delete m_commandQueue;
m_metalCtx->m_windows.erase(m_parentWindow); m_metalCtx->m_windows.erase(m_parentWindow);
} }
void _setCallback(IWindowCallback* cb) void _setCallback(IWindowCallback* cb)
{ {
m_callback = cb; m_callback = cb;
} }
EGraphicsAPI getAPI() const EGraphicsAPI getAPI() const
{ {
return m_api; return m_api;
} }
EPixelFormat getPixelFormat() const EPixelFormat getPixelFormat() const
{ {
return m_pf; return m_pf;
} }
void setPixelFormat(EPixelFormat pf) void setPixelFormat(EPixelFormat pf)
{ {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
void initializeContext() void initializeContext()
{ {
MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow]; MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow];
@ -386,55 +388,56 @@ public:
CVDisplayLinkStart(m_dispLink); CVDisplayLinkStart(m_dispLink);
m_commandQueue = _NewMetalCommandQueue(m_metalCtx, m_parentWindow, this); m_commandQueue = _NewMetalCommandQueue(m_metalCtx, m_parentWindow, this);
} }
void makeCurrent() void makeCurrent()
{ {
} }
void postInit() void postInit()
{ {
} }
IGraphicsCommandQueue* getCommandQueue() IGraphicsCommandQueue* getCommandQueue()
{ {
return m_commandQueue; return m_commandQueue;
} }
IGraphicsDataFactory* getDataFactory() IGraphicsDataFactory* getDataFactory()
{ {
return m_dataFactory; return m_dataFactory;
} }
IGraphicsDataFactory* getMainContextDataFactory() IGraphicsDataFactory* getMainContextDataFactory()
{ {
return m_dataFactory; return m_dataFactory;
} }
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
return m_dataFactory; return m_dataFactory;
} }
void present() void present()
{ {
} }
BooCocoaResponder* responder() const BooCocoaResponder* responder() const
{ {
if (!m_nsContext) if (!m_nsContext)
return nullptr; return nullptr;
return m_nsContext->resp; return m_nsContext->resp;
} }
}; };
IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api, IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow, IWindow* parentWindow,
MetalContext* metalCtx) MetalContext* metalCtx,
uint32_t sampleCount)
{ {
if (api != IGraphicsContext::EGraphicsAPI::Metal) if (api != IGraphicsContext::EGraphicsAPI::Metal)
return nullptr; return nullptr;
return new GraphicsContextCocoaMetal(api, parentWindow, metalCtx); return new GraphicsContextCocoaMetal(api, parentWindow, metalCtx, sampleCount);
} }
#endif #endif
@ -1047,7 +1050,7 @@ static boo::ESpecialKey translateKeycode(short code)
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::EModifierKey::Ctrl, false); booContext->m_callback->modKeyDown(boo::EModifierKey::Ctrl, false);
@ -1057,7 +1060,7 @@ static boo::ESpecialKey translateKeycode(short code)
booContext->m_callback->modKeyDown(boo::EModifierKey::Shift, false); booContext->m_callback->modKeyDown(boo::EModifierKey::Shift, false);
if (downFlags & NSCommandKeyMask) if (downFlags & NSCommandKeyMask)
booContext->m_callback->modKeyDown(boo::EModifierKey::Command, false); booContext->m_callback->modKeyDown(boo::EModifierKey::Command, false);
NSUInteger upFlags = changedFlags & ~modFlags; NSUInteger upFlags = changedFlags & ~modFlags;
if (upFlags & NSControlKeyMask) if (upFlags & NSControlKeyMask)
booContext->m_callback->modKeyUp(boo::EModifierKey::Ctrl); booContext->m_callback->modKeyUp(boo::EModifierKey::Ctrl);
@ -1067,7 +1070,7 @@ static boo::ESpecialKey translateKeycode(short code)
booContext->m_callback->modKeyUp(boo::EModifierKey::Shift); booContext->m_callback->modKeyUp(boo::EModifierKey::Shift);
if (upFlags & NSCommandKeyMask) if (upFlags & NSCommandKeyMask)
booContext->m_callback->modKeyUp(boo::EModifierKey::Command); booContext->m_callback->modKeyUp(boo::EModifierKey::Command);
lastModifiers = modFlags; lastModifiers = modFlags;
} }
[textContext handleEvent:theEvent]; [textContext handleEvent:theEvent];
@ -1084,7 +1087,7 @@ static boo::ESpecialKey translateKeycode(short code)
} }
@end @end
@implementation GraphicsContextCocoaGLInternal @implementation GraphicsContextCocoaGLInternal
- (id)initWithBooContext:(boo::GraphicsContextCocoaGL*)bctx - (id)initWithBooContext:(boo::GraphicsContextCocoaGL*)bctx
{ {
@ -1214,7 +1217,7 @@ static boo::ESpecialKey translateKeycode(short code)
namespace boo namespace boo
{ {
static NSString* ClipboardTypes[] = static NSString* ClipboardTypes[] =
{ {
0, NSPasteboardTypeString, NSPasteboardTypeString, NSPasteboardTypePNG 0, NSPasteboardTypeString, NSPasteboardTypeString, NSPasteboardTypePNG
@ -1222,7 +1225,7 @@ static NSString* ClipboardTypes[] =
class WindowCocoa : public IWindow class WindowCocoa : public IWindow
{ {
WindowCocoaInternal* m_nsWindow; WindowCocoaInternal* m_nsWindow;
GraphicsContextCocoa* m_gfxCtx; GraphicsContextCocoa* m_gfxCtx;
EMouseCursor m_cursor = EMouseCursor::None; EMouseCursor m_cursor = EMouseCursor::None;
@ -1230,26 +1233,28 @@ class WindowCocoa : public IWindow
public: public:
WindowCocoa(const std::string& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx) WindowCocoa(const std::string& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx, uint32_t sampleCount)
{ {
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];
#if BOO_HAS_METAL #if BOO_HAS_METAL
if (metalCtx->m_dev) if (metalCtx->m_dev)
m_gfxCtx = static_cast<GraphicsContextCocoa*>(_GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal, this, metalCtx)); m_gfxCtx = static_cast<GraphicsContextCocoa*>(_GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal,
this, metalCtx, sampleCount));
else else
#endif #endif
m_gfxCtx = static_cast<GraphicsContextCocoa*>(_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this, lastGLCtx)); m_gfxCtx = static_cast<GraphicsContextCocoa*>(_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3,
this, lastGLCtx, sampleCount));
m_gfxCtx->initializeContext(); m_gfxCtx->initializeContext();
}); });
} }
void _clearWindow() void _clearWindow()
{ {
m_closed = true; m_closed = true;
} }
~WindowCocoa() ~WindowCocoa()
{ {
if (!m_closed) if (!m_closed)
@ -1257,12 +1262,12 @@ public:
delete m_gfxCtx; delete m_gfxCtx;
APP->_deletedWindow(this); APP->_deletedWindow(this);
} }
void setCallback(IWindowCallback* cb) void setCallback(IWindowCallback* cb)
{ {
m_gfxCtx->_setCallback(cb); m_gfxCtx->_setCallback(cb);
} }
void showWindow() void showWindow()
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
@ -1270,7 +1275,7 @@ public:
[m_nsWindow makeKeyAndOrderFront:nil]; [m_nsWindow makeKeyAndOrderFront:nil];
}); });
} }
void hideWindow() void hideWindow()
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
@ -1278,12 +1283,12 @@ public:
[m_nsWindow orderOut:nil]; [m_nsWindow orderOut:nil];
}); });
} }
std::string getTitle() std::string getTitle()
{ {
return [[m_nsWindow title] UTF8String]; return [[m_nsWindow title] UTF8String];
} }
void setTitle(const std::string& title) void setTitle(const std::string& title)
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
@ -1291,7 +1296,7 @@ public:
[m_nsWindow setTitle:[NSString stringWithUTF8String:title.c_str()]]; [m_nsWindow setTitle:[NSString stringWithUTF8String:title.c_str()]];
}); });
} }
void setCursor(EMouseCursor cursor) void setCursor(EMouseCursor cursor)
{ {
if (cursor == m_cursor) if (cursor == m_cursor)
@ -1320,9 +1325,9 @@ public:
} }
}); });
} }
void setWaitCursor(bool wait) {} void setWaitCursor(bool wait) {}
void setWindowFrameDefault() void setWindowFrameDefault()
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
@ -1334,7 +1339,7 @@ public:
[m_nsWindow setFrame:NSMakeRect(x_off, y_off, x_off * 2.0, y_off * 2.0) display:NO]; [m_nsWindow setFrame:NSMakeRect(x_off, y_off, x_off * 2.0, y_off * 2.0) display:NO];
}); });
} }
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const
{ {
NSRect wFrame = m_nsWindow.contentView.frame; NSRect wFrame = m_nsWindow.contentView.frame;
@ -1343,7 +1348,7 @@ public:
wOut = wFrame.size.width; wOut = wFrame.size.width;
hOut = wFrame.size.height; hOut = wFrame.size.height;
} }
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const
{ {
NSRect wFrame = m_nsWindow.contentView.frame; NSRect wFrame = m_nsWindow.contentView.frame;
@ -1352,7 +1357,7 @@ public:
wOut = wFrame.size.width; wOut = wFrame.size.width;
hOut = wFrame.size.height; hOut = wFrame.size.height;
} }
void setWindowFrame(float x, float y, float w, float h) void setWindowFrame(float x, float y, float w, float h)
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
@ -1361,7 +1366,7 @@ public:
[m_nsWindow setFrameOrigin:NSMakePoint(x, y)]; [m_nsWindow setFrameOrigin:NSMakePoint(x, y)];
}); });
} }
void setWindowFrame(int x, int y, int w, int h) void setWindowFrame(int x, int y, int w, int h)
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
@ -1370,17 +1375,17 @@ public:
[m_nsWindow setFrameOrigin:NSMakePoint(x, y)]; [m_nsWindow setFrameOrigin:NSMakePoint(x, y)];
}); });
} }
float getVirtualPixelFactor() const float getVirtualPixelFactor() const
{ {
return [m_nsWindow backingScaleFactor]; return [m_nsWindow backingScaleFactor];
} }
bool isFullscreen() const bool isFullscreen() const
{ {
return ([m_nsWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask; return ([m_nsWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask;
} }
void setFullscreen(bool fs) void setFullscreen(bool fs)
{ {
if ((fs && !isFullscreen()) || (!fs && isFullscreen())) if ((fs && !isFullscreen()) || (!fs && isFullscreen()))
@ -1389,7 +1394,7 @@ public:
[m_nsWindow toggleFullScreen:nil]; [m_nsWindow toggleFullScreen:nil];
}); });
} }
void claimKeyboardFocus(const int coord[2]) void claimKeyboardFocus(const int coord[2])
{ {
BooCocoaResponder* resp = m_gfxCtx->responder(); BooCocoaResponder* resp = m_gfxCtx->responder();
@ -1404,7 +1409,7 @@ public:
}); });
} }
} }
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz)
{ {
NSPasteboard* pb = [NSPasteboard generalPasteboard]; NSPasteboard* pb = [NSPasteboard generalPasteboard];
@ -1413,7 +1418,7 @@ public:
[pb setData:d forType:ClipboardTypes[int(type)]]; [pb setData:d forType:ClipboardTypes[int(type)]];
return true; return true;
} }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz)
{ {
NSPasteboard* pb = [NSPasteboard generalPasteboard]; NSPasteboard* pb = [NSPasteboard generalPasteboard];
@ -1425,12 +1430,12 @@ public:
[d getBytes:ret.get() length:sz]; [d getBytes:ret.get() length:sz];
return ret; return ret;
} }
ETouchType getTouchType() const ETouchType getTouchType() const
{ {
return ETouchType::Trackpad; return ETouchType::Trackpad;
} }
void setStyle(EWindowStyle style) void setStyle(EWindowStyle style)
{ {
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
@ -1439,18 +1444,18 @@ public:
else else
m_nsWindow.titleVisibility = NSWindowTitleHidden; m_nsWindow.titleVisibility = NSWindowTitleHidden;
#endif #endif
if ((style & EWindowStyle::Close) != EWindowStyle::None) if ((style & EWindowStyle::Close) != EWindowStyle::None)
m_nsWindow.styleMask |= NSClosableWindowMask; m_nsWindow.styleMask |= NSClosableWindowMask;
else else
m_nsWindow.styleMask &= ~NSClosableWindowMask; m_nsWindow.styleMask &= ~NSClosableWindowMask;
if ((style & EWindowStyle::Resize) != EWindowStyle::None) if ((style & EWindowStyle::Resize) != EWindowStyle::None)
m_nsWindow.styleMask |= NSResizableWindowMask; m_nsWindow.styleMask |= NSResizableWindowMask;
else else
m_nsWindow.styleMask &= ~NSResizableWindowMask; m_nsWindow.styleMask &= ~NSResizableWindowMask;
} }
EWindowStyle getStyle() const EWindowStyle getStyle() const
{ {
EWindowStyle retval = EWindowStyle::None; EWindowStyle retval = EWindowStyle::None;
@ -1463,44 +1468,45 @@ public:
retval |= (m_nsWindow.styleMask & NSResizableWindowMask) ? EWindowStyle::Resize: EWindowStyle::None; retval |= (m_nsWindow.styleMask & NSResizableWindowMask) ? EWindowStyle::Resize: EWindowStyle::None;
return retval; return retval;
} }
void waitForRetrace() void waitForRetrace()
{ {
static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace(); static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace();
} }
uintptr_t getPlatformHandle() const uintptr_t getPlatformHandle() const
{ {
return (uintptr_t)m_nsWindow; return (uintptr_t)m_nsWindow;
} }
IGraphicsCommandQueue* getCommandQueue() IGraphicsCommandQueue* getCommandQueue()
{ {
return m_gfxCtx->getCommandQueue(); return m_gfxCtx->getCommandQueue();
} }
IGraphicsDataFactory* getDataFactory() IGraphicsDataFactory* getDataFactory()
{ {
return m_gfxCtx->getDataFactory(); return m_gfxCtx->getDataFactory();
} }
IGraphicsDataFactory* getMainContextDataFactory() IGraphicsDataFactory* getMainContextDataFactory()
{ {
return m_gfxCtx->getMainContextDataFactory(); return m_gfxCtx->getMainContextDataFactory();
} }
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
return m_gfxCtx->getLoadContextDataFactory(); return m_gfxCtx->getLoadContextDataFactory();
} }
}; };
IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx) IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx,
MetalContext* metalCtx, uint32_t sampleCount)
{ {
return new WindowCocoa(title, lastGLCtx, metalCtx); return new WindowCocoa(title, lastGLCtx, metalCtx, sampleCount);
} }
} }
@implementation WindowCocoaInternal @implementation WindowCocoaInternal