All kinds of fixes and updates

This commit is contained in:
Jack Andersen 2015-10-31 14:06:56 -10:00
parent bb2ca27ab7
commit f796d66407
10 changed files with 385 additions and 243 deletions

View File

@ -34,7 +34,8 @@ elseif(APPLE)
find_library(APPKIT_LIBRARY AppKit) find_library(APPKIT_LIBRARY AppKit)
find_library(IOKIT_LIBRARY IOKit) find_library(IOKIT_LIBRARY IOKit)
find_library(OPENGL_LIBRARY OpenGL) find_library(OPENGL_LIBRARY OpenGL)
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${OPENGL_LIBRARY}) find_library(COREVIDEO_LIBRARY CoreVideo)
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${OPENGL_LIBRARY} ${COREVIDEO_LIBRARY})
else() else()
list(APPEND PLAT_SRCS list(APPEND PLAT_SRCS
lib/x11/ApplicationUnix.cpp lib/x11/ApplicationUnix.cpp

View File

@ -14,8 +14,8 @@ class IApplication;
struct IApplicationCallback struct IApplicationCallback
{ {
virtual int appMain(IApplication*) {return 0;} virtual int appMain(IApplication*)=0;
virtual void appQuitting(IApplication*) {} virtual void appQuitting(IApplication*)=0;
virtual void appFilesOpen(IApplication*, const std::vector<SystemString>&) {} virtual void appFilesOpen(IApplication*, const std::vector<SystemString>&) {}
}; };
@ -51,12 +51,12 @@ public:
virtual const std::vector<SystemString>& getArgs() const=0; virtual const std::vector<SystemString>& getArgs() const=0;
/* Constructors/initializers for sub-objects */ /* Constructors/initializers for sub-objects */
virtual std::unique_ptr<IWindow> newWindow(const SystemString& title)=0; virtual IWindow* newWindow(const SystemString& title)=0;
}; };
std::unique_ptr<IApplication> int
ApplicationBootstrap(IApplication::EPlatformType platform, ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb, IApplicationCallback& cb,
const SystemString& uniqueName, const SystemString& uniqueName,
const SystemString& friendlyName, const SystemString& friendlyName,
@ -65,8 +65,8 @@ ApplicationBootstrap(IApplication::EPlatformType platform,
bool singleInstance=true); bool singleInstance=true);
extern IApplication* APP; extern IApplication* APP;
static inline std::unique_ptr<IApplication> static inline int
ApplicationBootstrap(IApplication::EPlatformType platform, ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb, IApplicationCallback& cb,
const SystemString& uniqueName, const SystemString& uniqueName,
const SystemString& friendlyName, const SystemString& friendlyName,
@ -74,11 +74,11 @@ ApplicationBootstrap(IApplication::EPlatformType platform,
bool singleInstance=true) bool singleInstance=true)
{ {
if (APP) if (APP)
return std::unique_ptr<IApplication>(); return 1;
std::vector<SystemString> args; std::vector<SystemString> args;
for (int i=1 ; i<argc ; ++i) for (int i=1 ; i<argc ; ++i)
args.push_back(argv[i]); args.push_back(argv[i]);
return ApplicationBootstrap(platform, cb, uniqueName, friendlyName, argv[0], args, singleInstance); return ApplicationRun(platform, cb, uniqueName, friendlyName, argv[0], args, singleInstance);
} }
} }

View File

@ -6,6 +6,7 @@
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include "glew.h" #include "glew.h"
#include <vector> #include <vector>
#include <unordered_set>
namespace boo namespace boo
{ {
@ -13,9 +14,11 @@ namespace boo
class GLES3DataFactory : public IGraphicsDataFactory class GLES3DataFactory : public IGraphicsDataFactory
{ {
IGraphicsContext* m_parent; IGraphicsContext* m_parent;
std::unique_ptr<IGraphicsData> m_deferredData; IGraphicsData* m_deferredData = nullptr;
std::unordered_set<IGraphicsData*> m_committedData;
public: public:
GLES3DataFactory(IGraphicsContext* parent); GLES3DataFactory(IGraphicsContext* parent);
~GLES3DataFactory() {}
Platform platform() const {return PlatformOGLES3;} Platform platform() const {return PlatformOGLES3;}
const char* platformName() const {return "OpenGL ES 3.0";} const char* platformName() const {return "OpenGL ES 3.0";}
@ -42,7 +45,9 @@ public:
size_t texCount, const ITexture** texs); size_t texCount, const ITexture** texs);
void reset(); void reset();
std::unique_ptr<IGraphicsData> commit(); IGraphicsData* commit();
void destroyData(IGraphicsData*);
void destroyAllData();
}; };
} }

View File

@ -115,7 +115,6 @@ struct IShaderDataBinding {};
* resource batch. */ * resource batch. */
struct IGraphicsData struct IGraphicsData
{ {
virtual ~IGraphicsData() {}
}; };
/** Used by platform shader pipeline constructors */ /** Used by platform shader pipeline constructors */
@ -173,7 +172,9 @@ struct IGraphicsDataFactory
size_t texCount, const ITexture** texs)=0; size_t texCount, const ITexture** texs)=0;
virtual void reset()=0; virtual void reset()=0;
virtual std::unique_ptr<IGraphicsData> commit()=0; virtual IGraphicsData* commit()=0;
virtual void destroyData(IGraphicsData*)=0;
virtual void destroyAllData()=0;
}; };
} }

View File

@ -85,7 +85,7 @@ const IGraphicsBufferS*
GLES3DataFactory::newStaticBuffer(BufferUse use, const void* data, size_t sz) GLES3DataFactory::newStaticBuffer(BufferUse use, const void* data, size_t sz)
{ {
GLES3GraphicsBufferS* retval = new GLES3GraphicsBufferS(use, data, sz); GLES3GraphicsBufferS* retval = new GLES3GraphicsBufferS(use, data, sz);
static_cast<GLES3Data*>(m_deferredData.get())->m_SBufs.emplace_back(retval); static_cast<GLES3Data*>(m_deferredData)->m_SBufs.emplace_back(retval);
return retval; return retval;
} }
@ -99,6 +99,11 @@ class GLES3TextureS : ITextureS
const uint8_t* dataIt = static_cast<const uint8_t*>(data); const uint8_t* dataIt = static_cast<const uint8_t*>(data);
glGenTextures(1, &m_tex); glGenTextures(1, &m_tex);
glBindTexture(GL_TEXTURE_2D, m_tex); glBindTexture(GL_TEXTURE_2D, m_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (mips > 1)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (fmt == TextureFormatRGBA8) if (fmt == TextureFormatRGBA8)
{ {
for (size_t i=0 ; i<mips ; ++i) for (size_t i=0 ; i<mips ; ++i)
@ -168,7 +173,7 @@ GLES3DataFactory::newStaticTexture(size_t width, size_t height, size_t mips, Tex
const void* data, size_t sz) const void* data, size_t sz)
{ {
GLES3TextureS* retval = new GLES3TextureS(width, height, mips, fmt, data, sz); GLES3TextureS* retval = new GLES3TextureS(width, height, mips, fmt, data, sz);
static_cast<GLES3Data*>(m_deferredData.get())->m_STexs.emplace_back(retval); static_cast<GLES3Data*>(m_deferredData)->m_STexs.emplace_back(retval);
return retval; return retval;
} }
@ -337,10 +342,12 @@ const IShaderPipeline* GLES3DataFactory::newShaderPipeline
GLint loc; GLint loc;
if ((loc = glGetUniformLocation(shader.m_prog, texNames[i])) >= 0) if ((loc = glGetUniformLocation(shader.m_prog, texNames[i])) >= 0)
glUniform1i(loc, i); glUniform1i(loc, i);
else
Log.report(LogVisor::FatalError, "unable to find sampler variable '%s'", texNames[i]);
} }
GLES3ShaderPipeline* retval = new GLES3ShaderPipeline(std::move(shader)); GLES3ShaderPipeline* retval = new GLES3ShaderPipeline(std::move(shader));
static_cast<GLES3Data*>(m_deferredData.get())->m_SPs.emplace_back(retval); static_cast<GLES3Data*>(m_deferredData)->m_SPs.emplace_back(retval);
return retval; return retval;
} }
@ -403,7 +410,7 @@ GLES3DataFactory::newShaderDataBinding(const IShaderPipeline* pipeline,
{ {
GLES3ShaderDataBinding* retval = GLES3ShaderDataBinding* retval =
new GLES3ShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs, texCount, texs); new GLES3ShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs, texCount, texs);
static_cast<GLES3Data*>(m_deferredData.get())->m_SBinds.emplace_back(retval); static_cast<GLES3Data*>(m_deferredData)->m_SBinds.emplace_back(retval);
return retval; return retval;
} }
@ -412,16 +419,32 @@ GLES3DataFactory::GLES3DataFactory(IGraphicsContext* parent)
void GLES3DataFactory::reset() void GLES3DataFactory::reset()
{ {
m_deferredData.reset(new struct GLES3Data()); delete static_cast<GLES3Data*>(m_deferredData);
m_deferredData = new struct GLES3Data();
} }
std::unique_ptr<IGraphicsData> GLES3DataFactory::commit() IGraphicsData* GLES3DataFactory::commit()
{ {
std::unique_ptr<IGraphicsData> retval(new struct GLES3Data()); IGraphicsData* retval = m_deferredData;
m_deferredData.swap(retval); m_deferredData = new struct GLES3Data();
m_committedData.insert(retval);
return retval; return retval;
} }
void GLES3DataFactory::destroyData(IGraphicsData* d)
{
GLES3Data* data = static_cast<GLES3Data*>(d);
m_committedData.erase(data);
delete data;
}
void GLES3DataFactory::destroyAllData()
{
for (IGraphicsData* data : m_committedData)
delete static_cast<GLES3Data*>(data);
m_committedData.clear();
}
static const GLint SEMANTIC_COUNT_TABLE[] = static const GLint SEMANTIC_COUNT_TABLE[] =
{ {
3, 3,
@ -533,6 +556,7 @@ struct GLES3CommandQueue : IGraphicsCommandQueue
lastEBO = desc->indexBuffer; lastEBO = desc->indexBuffer;
lastEBO->bindIndex(); lastEBO->bindIndex();
} }
glEnableVertexAttribArray(i);
glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[desc->semantic], glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[desc->semantic],
SEMANTIC_TYPE_TABLE[desc->semantic], GL_TRUE, stride, (void*)offset); SEMANTIC_TYPE_TABLE[desc->semantic], GL_TRUE, stride, (void*)offset);
offset += SEMANTIC_SIZE_TABLE[desc->semantic]; offset += SEMANTIC_SIZE_TABLE[desc->semantic];
@ -800,7 +824,7 @@ GLES3DataFactory::newDynamicBuffer(BufferUse use)
{ {
GLES3CommandQueue* q = static_cast<GLES3CommandQueue*>(m_parent->getCommandQueue()); GLES3CommandQueue* q = static_cast<GLES3CommandQueue*>(m_parent->getCommandQueue());
GLES3GraphicsBufferD* retval = new GLES3GraphicsBufferD(q, use); GLES3GraphicsBufferD* retval = new GLES3GraphicsBufferD(q, use);
static_cast<GLES3Data*>(m_deferredData.get())->m_DBufs.emplace_back(retval); static_cast<GLES3Data*>(m_deferredData)->m_DBufs.emplace_back(retval);
return retval; return retval;
} }
@ -823,7 +847,7 @@ GLES3DataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat f
{ {
GLES3CommandQueue* q = static_cast<GLES3CommandQueue*>(m_parent->getCommandQueue()); GLES3CommandQueue* q = static_cast<GLES3CommandQueue*>(m_parent->getCommandQueue());
GLES3TextureD* retval = new GLES3TextureD(q, width, height, fmt); GLES3TextureD* retval = new GLES3TextureD(q, width, height, fmt);
static_cast<GLES3Data*>(m_deferredData.get())->m_DTexs.emplace_back(retval); static_cast<GLES3Data*>(m_deferredData)->m_DTexs.emplace_back(retval);
return retval; return retval;
} }
@ -844,7 +868,7 @@ const IVertexFormat* GLES3DataFactory::newVertexFormat
{ {
GLES3CommandQueue* q = static_cast<GLES3CommandQueue*>(m_parent->getCommandQueue()); GLES3CommandQueue* q = static_cast<GLES3CommandQueue*>(m_parent->getCommandQueue());
GLES3VertexFormat* retval = new struct GLES3VertexFormat(q, elementCount, elements); GLES3VertexFormat* retval = new struct GLES3VertexFormat(q, elementCount, elements);
static_cast<GLES3Data*>(m_deferredData.get())->m_VFmts.emplace_back(retval); static_cast<GLES3Data*>(m_deferredData)->m_VFmts.emplace_back(retval);
return retval; return retval;
} }

View File

@ -30,12 +30,12 @@
** THE POSSIBILITY OF SUCH DAMAGE. ** THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <GL/glew.h> #include <boo/graphicsdev/glew.h>
#if defined(_WIN32) #if defined(_WIN32)
# include <GL/wglew.h> # include <boo/graphicsdev/wglew.h>
#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) #elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))
# include <GL/glxew.h> # include <boo/graphicsdev/glxew.h>
#endif #endif
#include <stddef.h> /* For size_t */ #include <stddef.h> /* For size_t */

View File

@ -182,7 +182,7 @@ public:
~HIDListenerIOKit() ~HIDListenerIOKit()
{ {
CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode); //CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode);
IOObjectRelease(m_llAddNotif); IOObjectRelease(m_llAddNotif);
IOObjectRelease(m_llRemoveNotif); IOObjectRelease(m_llRemoveNotif);
IONotificationPortDestroy(m_llPort); IONotificationPortDestroy(m_llPort);

View File

@ -1,82 +1,29 @@
#include <AppKit/AppKit.h> #include <AppKit/AppKit.h>
#include <thread>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
namespace boo {class ApplicationCocoa;}
@interface AppDelegate : NSObject <NSApplicationDelegate> @interface AppDelegate : NSObject <NSApplicationDelegate>
{ {
boo::IApplicationCallback* callback; boo::ApplicationCocoa* m_app;
@public @public
NSPanel* aboutPanel; NSPanel* aboutPanel;
} }
- (id)initWithCallback:(boo::IApplicationCallback*)cb; - (id)initWithApp:(boo::ApplicationCocoa*)app;
@end
@implementation AppDelegate
- (id)initWithCallback:(boo::IApplicationCallback*)cb
{
self = [super init];
callback = cb;
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
(void)notification;
callback->appMain(boo::APP);
}
- (void)applicationWillTerminate:(NSNotification*)notification
{
(void)notification;
callback->appQuitting(boo::APP);
}
- (BOOL)application:(NSApplication*)sender openFile:(NSString*)filename
{
std::vector<boo::SystemString> strVec;
strVec.push_back(boo::SystemString([filename UTF8String]));
callback->appFilesOpen(boo::APP, strVec);
return true;
}
- (void)application:(NSApplication*)sender openFiles:(NSArray*)filenames
{
std::vector<boo::SystemString> strVec;
strVec.reserve([filenames count]);
for (NSString* str in filenames)
strVec.push_back(boo::SystemString([str UTF8String]));
callback->appFilesOpen(boo::APP, strVec);
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender {
(void)sender;
return YES;
}
- (IBAction)aboutApp:(id)sender
{
(void)sender;
NSRect screenFrame = [[aboutPanel screen] frame];
CGFloat xPos = NSWidth(screenFrame)/2 - 300/2;
CGFloat yPos = NSHeight(screenFrame)/2 - 220/2;
NSRect aboutCr = NSMakeRect(xPos, yPos, 300, 220);
[aboutPanel setFrame:aboutCr display:NO];
[aboutPanel makeKeyAndOrderFront:self];
}
- (IBAction)toggleFs:(id)sender
{
(void)sender;
[[NSApp keyWindow] toggleFullScreen:nil];
}
- (IBAction)quitApp:(id)sender
{
(void)sender;
[NSApp terminate:nil];
}
@end @end
namespace boo namespace boo
{ {
IWindow* _WindowCocoaNew(const SystemString& title); IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx);
class ApplicationCocoa : public IApplication class ApplicationCocoa : public IApplication
{ {
public:
NSApplication* m_app = nullptr;
IApplicationCallback& m_callback; IApplicationCallback& m_callback;
private:
const SystemString m_uniqueName; const SystemString m_uniqueName;
const SystemString m_friendlyName; const SystemString m_friendlyName;
const SystemString m_pname; const SystemString m_pname;
@ -84,9 +31,12 @@ class ApplicationCocoa : public IApplication
NSPanel* aboutPanel; NSPanel* aboutPanel;
/* All windows */
std::unordered_map<NSWindow*, IWindow*> m_windows;
void _deletedWindow(IWindow* window) void _deletedWindow(IWindow* window)
{ {
(void)window; m_windows.erase((NSWindow*)window->getPlatformHandle());
} }
public: public:
@ -101,14 +51,12 @@ public:
m_pname(pname), m_pname(pname),
m_args(args) m_args(args)
{ {
@autoreleasepool m_app = [NSApplication sharedApplication];
{ [m_app setActivationPolicy:NSApplicationActivationPolicyRegular];
NSApplication* app = [NSApplication sharedApplication];
[app setActivationPolicy:NSApplicationActivationPolicyRegular];
/* Delegate (OS X callbacks) */ /* Delegate (OS X callbacks) */
AppDelegate* appDelegate = [[AppDelegate alloc] initWithCallback:&m_callback]; AppDelegate* appDelegate = [[AppDelegate alloc] initWithApp:this];
[app setDelegate:appDelegate]; [m_app setDelegate:appDelegate];
/* App menu */ /* App menu */
NSMenu* appMenu = [[NSMenu alloc] initWithTitle:@"main"]; NSMenu* appMenu = [[NSMenu alloc] initWithTitle:@"main"];
@ -141,9 +89,6 @@ public:
[aboutText setString:@"\nRWK Authors\n\nJackoalan\nAntidote\n"]; [aboutText setString:@"\nRWK Authors\n\nJackoalan\nAntidote\n"];
[aboutPanel setContentView:aboutText]; [aboutPanel setContentView:aboutText];
appDelegate->aboutPanel = aboutPanel; appDelegate->aboutPanel = aboutPanel;
[app run];
}
} }
EPlatformType getPlatformType() const EPlatformType getPlatformType() const
@ -151,9 +96,23 @@ public:
return PLAT_COCOA; return PLAT_COCOA;
} }
void pump() std::thread m_clientThread;
int m_clientReturn = 0;
int run()
{ {
/* Spawn client thread */
m_clientThread = std::thread([&]()
{
/* Run app */
m_clientReturn = m_callback.appMain(this);
/* Cleanup here */
for (auto& window : m_windows)
delete window.second;
});
/* Already in Cocoa's event loop; return now */
return 0;
} }
void quit() void quit()
@ -183,27 +142,102 @@ public:
IWindow* newWindow(const std::string& title) IWindow* newWindow(const std::string& title)
{ {
return _WindowCocoaNew(title); IWindow* newWindow = _WindowCocoaNew(title, m_lastGLCtx);
m_windows[(NSWindow*)newWindow->getPlatformHandle()] = newWindow;
return newWindow;
} }
/* Last GL context */
NSOpenGLContext* m_lastGLCtx = nullptr;
}; };
IApplication* APP = NULL; void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx)
std::unique_ptr<IApplication> ApplicationBootstrap(IApplication::EPlatformType platform, {
static_cast<ApplicationCocoa*>(APP)->m_lastGLCtx = lastGLCtx;
}
IApplication* APP = nullptr;
int ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb, IApplicationCallback& cb,
const SystemString& uniqueName, const SystemString& uniqueName,
const SystemString& friendlyName, const SystemString& friendlyName,
const SystemString& pname, const SystemString& pname,
const std::vector<SystemString>& args, const std::vector<SystemString>& args,
bool singleInstance) bool singleInstance)
{
@autoreleasepool
{ {
if (!APP) if (!APP)
{ {
if (platform != IApplication::PLAT_COCOA && if (platform != IApplication::PLAT_COCOA &&
platform != IApplication::PLAT_AUTO) platform != IApplication::PLAT_AUTO)
return NULL; return 1;
APP = new ApplicationCocoa(cb, uniqueName, friendlyName, pname, args); APP = new ApplicationCocoa(cb, uniqueName, friendlyName, pname, args);
} }
return std::unique_ptr<IApplication>(APP); [static_cast<ApplicationCocoa*>(APP)->m_app run];
return static_cast<ApplicationCocoa*>(APP)->m_clientReturn;
}
} }
} }
@implementation AppDelegate
- (id)initWithApp:(boo::ApplicationCocoa*)app
{
self = [super init];
m_app = app;
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
(void)notification;
m_app->run();
}
- (void)applicationWillTerminate:(NSNotification*)notification
{
(void)notification;
m_app->m_callback.appQuitting(m_app);
m_app->m_clientThread.join();
}
- (BOOL)application:(NSApplication*)sender openFile:(NSString*)filename
{
std::vector<boo::SystemString> strVec;
strVec.push_back(boo::SystemString([filename UTF8String]));
m_app->m_callback.appFilesOpen(boo::APP, strVec);
return true;
}
- (void)application:(NSApplication*)sender openFiles:(NSArray*)filenames
{
std::vector<boo::SystemString> strVec;
strVec.reserve([filenames count]);
for (NSString* str in filenames)
strVec.push_back(boo::SystemString([str UTF8String]));
m_app->m_callback.appFilesOpen(boo::APP, strVec);
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender
{
(void)sender;
return YES;
}
- (IBAction)aboutApp:(id)sender
{
(void)sender;
NSRect screenFrame = [[aboutPanel screen] frame];
CGFloat xPos = NSWidth(screenFrame)/2 - 300/2;
CGFloat yPos = NSHeight(screenFrame)/2 - 220/2;
NSRect aboutCr = NSMakeRect(xPos, yPos, 300, 220);
[aboutPanel setFrame:aboutCr display:NO];
[aboutPanel makeKeyAndOrderFront:self];
}
- (IBAction)toggleFs:(id)sender
{
(void)sender;
[[NSApp keyWindow] toggleFullScreen:nil];
}
- (IBAction)quitApp:(id)sender
{
(void)sender;
[NSApp terminate:nil];
}
@end

View File

@ -1,10 +1,12 @@
#include "boo/graphicsdev/GL.hpp"
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#include <OpenGL/OpenGL.h> #import <CoreVideo/CVDisplayLink.h>
#include <OpenGL/gl3.h>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/IWindow.hpp" #include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include <LogVisor/LogVisor.hpp>
namespace boo {class WindowCocoa;} namespace boo {class WindowCocoa;}
@interface WindowCocoaInternal : NSWindow @interface WindowCocoaInternal : NSWindow
{ {
@ -81,6 +83,9 @@ namespace boo {class GraphicsContextCocoa;}
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::WindowCocoa");
IGraphicsCommandQueue* _NewGLES3CommandQueue(IGraphicsContext* parent);
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
class GraphicsContextCocoa : public IGraphicsContext class GraphicsContextCocoa : public IGraphicsContext
{ {
@ -88,25 +93,32 @@ class GraphicsContextCocoa : public IGraphicsContext
EGraphicsAPI m_api; EGraphicsAPI m_api;
EPixelFormat m_pf; EPixelFormat m_pf;
IWindow* m_parentWindow; IWindow* m_parentWindow;
GraphicsContextCocoaInternal* m_nsContext; GraphicsContextCocoaInternal* m_nsContext = nullptr;
NSOpenGLContext* m_nsShareContext;
IGraphicsCommandQueue* m_commandQueue = nullptr;
IGraphicsDataFactory* m_dataFactory = nullptr;
NSOpenGLContext* m_loadCtx = nullptr;
CVDisplayLinkRef m_dispLink = nullptr;
public: public:
IWindowCallback* m_callback; NSOpenGLContext* m_lastCtx = nullptr;
IWindowCallback* m_callback = nullptr;
GraphicsContextCocoa(EGraphicsAPI api, IWindow* parentWindow) GraphicsContextCocoa(EGraphicsAPI api, IWindow* parentWindow, NSOpenGLContext* lastGLCtx)
: m_api(api), : m_api(api),
m_pf(PF_RGBA8), m_pf(PF_RGBA8),
m_parentWindow(parentWindow), m_parentWindow(parentWindow),
m_nsContext(NULL), m_lastCtx(lastGLCtx)
m_nsShareContext(NULL),
m_callback(NULL)
{} {}
~GraphicsContextCocoa() ~GraphicsContextCocoa()
{ {
delete m_dataFactory;
delete m_commandQueue;
[m_nsContext release]; [m_nsContext release];
[m_nsShareContext release]; [m_loadCtx release];
CVDisplayLinkStop(m_dispLink);
CVDisplayLinkRelease(m_dispLink);
} }
void _setCallback(IWindowCallback* cb) void _setCallback(IWindowCallback* cb)
@ -131,58 +143,83 @@ public:
m_pf = pf; m_pf = pf;
} }
void initializeContext() 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)
{ {
if (m_nsShareContext) ctx->m_dlcv.notify_one();
return; return kCVReturnSuccess;
m_nsContext = [[GraphicsContextCocoaInternal alloc] initWithBooContext:this];
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
} }
IGraphicsContext* makeShareContext() const void waitForRetrace()
{ {
NSOpenGLContext* nsctx; std::unique_lock<std::mutex> lk(m_dlmt);
if (m_nsContext) m_dlcv.wait(lk);
{
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsContext pixelFormat]
shareContext:[m_nsContext openGLContext]];
} }
else if (m_nsShareContext)
void initializeContext()
{ {
nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsShareContext pixelFormat] m_nsContext = [[GraphicsContextCocoaInternal alloc] initWithBooContext:this];
shareContext:m_nsShareContext]; if (!m_nsContext)
} Log.report(LogVisor::FatalError, "unable to make new NSOpenGLView");
else [(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
return NULL; CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
if (!nsctx) CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
return NULL; CVDisplayLinkStart(m_dispLink);
GraphicsContextCocoa* newCtx = new GraphicsContextCocoa(m_api, NULL);
newCtx->m_nsShareContext = nsctx;
return newCtx;
} }
void makeCurrent() void makeCurrent()
{ {
if (m_nsContext)
[[m_nsContext openGLContext] makeCurrentContext]; [[m_nsContext openGLContext] makeCurrentContext];
else if (m_nsShareContext)
[m_nsShareContext makeCurrentContext];
} }
void clearCurrent() void postInit()
{ {
[NSOpenGLContext clearCurrentContext];
} }
void swapBuffer() IGraphicsCommandQueue* getCommandQueue()
{
if (!m_commandQueue)
m_commandQueue = _NewGLES3CommandQueue(this);
return m_commandQueue;
}
IGraphicsDataFactory* getDataFactory()
{
if (!m_dataFactory)
m_dataFactory = new GLES3DataFactory(this);
return m_dataFactory;
}
IGraphicsDataFactory* getLoadContextDataFactory()
{
if (!m_loadCtx)
{
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[m_pf]];
m_loadCtx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:[m_nsContext openGLContext]];
[nspf release];
if (!m_loadCtx)
Log.report(LogVisor::FatalError, "unable to make load NSOpenGLContext");
[m_loadCtx makeCurrentContext];
}
return getDataFactory();
}
void present()
{ {
[[m_nsContext openGLContext] flushBuffer]; [[m_nsContext openGLContext] flushBuffer];
} }
}; };
IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api, IGraphicsContext* _GraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow) 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)
return NULL; return NULL;
@ -215,7 +252,7 @@ IGraphicsContext* _CGraphicsContextCocoaNew(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); return new GraphicsContextCocoa(api, parentWindow, lastGLCtx);
} }
} }
@ -228,6 +265,12 @@ IGraphicsContext* _CGraphicsContextCocoaNew(IGraphicsContext::EGraphicsAPI api,
boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat(); boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat();
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]]; NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]];
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:nspf]; 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]; [nspf release];
return self; return self;
} }
@ -660,23 +703,26 @@ class WindowCocoa : public IWindow
public: public:
WindowCocoa(const std::string& title) WindowCocoa(const std::string& title, NSOpenGLContext* lastGLCtx)
{ {
dispatch_sync(dispatch_get_main_queue(),
^{
m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title]; m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title];
m_gfxCtx = _CGraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this); m_gfxCtx = _GraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this, lastGLCtx);
m_gfxCtx->initializeContext(); m_gfxCtx->initializeContext();
});
} }
void _clearWindow() void _clearWindow()
{ {
m_nsWindow = NULL; m_nsWindow = nullptr;
} }
~WindowCocoa() ~WindowCocoa()
{ {
[m_nsWindow orderOut:nil]; [m_nsWindow orderOut:nil];
[m_nsWindow release];
delete m_gfxCtx; delete m_gfxCtx;
[m_nsWindow release];
APP->_deletedWindow(this); APP->_deletedWindow(this);
} }
@ -687,12 +733,18 @@ public:
void showWindow() void showWindow()
{ {
dispatch_sync(dispatch_get_main_queue(),
^{
[m_nsWindow makeKeyAndOrderFront:nil]; [m_nsWindow makeKeyAndOrderFront:nil];
});
} }
void hideWindow() void hideWindow()
{ {
dispatch_sync(dispatch_get_main_queue(),
^{
[m_nsWindow orderOut:nil]; [m_nsWindow orderOut:nil];
});
} }
std::string getTitle() std::string getTitle()
@ -702,16 +754,22 @@ public:
void setTitle(const std::string& title) void setTitle(const std::string& title)
{ {
dispatch_sync(dispatch_get_main_queue(),
^{
[m_nsWindow setTitle:[[NSString stringWithUTF8String:title.c_str()] autorelease]]; [m_nsWindow setTitle:[[NSString stringWithUTF8String:title.c_str()] autorelease]];
});
} }
void setWindowFrameDefault() void setWindowFrameDefault()
{ {
dispatch_sync(dispatch_get_main_queue(),
^{
NSScreen* mainScreen = [NSScreen mainScreen]; NSScreen* mainScreen = [NSScreen mainScreen];
NSRect scrFrame = mainScreen.frame; NSRect scrFrame = mainScreen.frame;
float x_off = scrFrame.size.width / 3.0; float x_off = scrFrame.size.width / 3.0;
float y_off = scrFrame.size.height / 3.0; float y_off = scrFrame.size.height / 3.0;
[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
@ -725,8 +783,11 @@ public:
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(),
^{
NSRect wFrame = NSMakeRect(x, y, w, h); NSRect wFrame = NSMakeRect(x, y, w, h);
[m_nsWindow setFrame:wFrame display:NO]; [m_nsWindow setFrame:wFrame display:NO];
});
} }
float getVirtualPixelFactor() const float getVirtualPixelFactor() const
@ -742,7 +803,10 @@ public:
void setFullscreen(bool fs) void setFullscreen(bool fs)
{ {
if ((fs && !isFullscreen()) || (!fs && isFullscreen())) if ((fs && !isFullscreen()) || (!fs && isFullscreen()))
dispatch_sync(dispatch_get_main_queue(),
^{
[m_nsWindow toggleFullScreen:nil]; [m_nsWindow toggleFullScreen:nil];
});
} }
ETouchType getTouchType() const ETouchType getTouchType() const
@ -752,7 +816,7 @@ public:
void waitForRetrace() void waitForRetrace()
{ {
static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace();
} }
uintptr_t getPlatformHandle() const uintptr_t getPlatformHandle() const
@ -760,11 +824,26 @@ public:
return (uintptr_t)m_nsWindow; return (uintptr_t)m_nsWindow;
} }
IGraphicsCommandQueue* getCommandQueue()
{
return m_gfxCtx->getCommandQueue();
}
IGraphicsDataFactory* getDataFactory()
{
return m_gfxCtx->getDataFactory();
}
IGraphicsDataFactory* getLoadContextDataFactory()
{
return m_gfxCtx->getLoadContextDataFactory();
}
}; };
IWindow* _WindowCocoaNew(const SystemString& title) IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx)
{ {
return new WindowCocoa(title); return new WindowCocoa(title, lastGLCtx);
} }
} }

View File

@ -174,7 +174,7 @@ struct CTestWindowCallback : IWindowCallback
struct TestApplicationCallback : IApplicationCallback struct TestApplicationCallback : IApplicationCallback
{ {
std::unique_ptr<IWindow> mainWindow; IWindow* mainWindow;
boo::TestDeviceFinder devFinder; boo::TestDeviceFinder devFinder;
CTestWindowCallback windowCallback; CTestWindowCallback windowCallback;
bool running = true; bool running = true;
@ -196,10 +196,10 @@ struct TestApplicationCallback : IApplicationCallback
}; };
static const Vert quad[4] = static const Vert quad[4] =
{ {
{{1.0,1.0},{1.0,1.0}}, {{0.5,0.5},{1.0,1.0}},
{{-1.0,1.0},{0.0,1.0}}, {{-0.5,0.5},{0.0,1.0}},
{{1.0,-1.0},{1.0,0.0}}, {{0.5,-0.5},{1.0,0.0}},
{{-1.0,-1.0},{0.0,0.0}} {{-0.5,-0.5},{0.0,0.0}}
}; };
const IGraphicsBuffer* vbo = const IGraphicsBuffer* vbo =
factory->newStaticBuffer(BufferUseVertex, quad, sizeof(quad)); factory->newStaticBuffer(BufferUseVertex, quad, sizeof(quad));
@ -241,15 +241,15 @@ struct TestApplicationCallback : IApplicationCallback
static const char* FS = static const char* FS =
"#version 330\n" "#version 330\n"
"precision highp float;\n" "precision highp float;\n"
"uniform sampler2D tex;\n" "uniform sampler2D smplr;\n"
"layout(location=0) out vec4 out_frag;\n" "layout(location=0) out vec4 out_frag;\n"
"in vec2 out_uv;\n" "in vec2 out_uv;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" out_frag = texture(tex, out_uv);\n" " out_frag = texture(smplr, out_uv);\n"
"}\n"; "}\n";
static const char* TexNames[] = {"tex"}; static const char* TexNames[] = {"smplr"};
const IShaderPipeline* pipeline = const IShaderPipeline* pipeline =
factory->newShaderPipeline(VS, FS, 1, TexNames, BlendFactorOne, BlendFactorZero, true, true, false); factory->newShaderPipeline(VS, FS, 1, TexNames, BlendFactorOne, BlendFactorZero, true, true, false);
@ -259,7 +259,7 @@ struct TestApplicationCallback : IApplicationCallback
factory->newShaderDataBinding(pipeline, vfmt, vbo, nullptr, 0, nullptr, 1, &texture); factory->newShaderDataBinding(pipeline, vfmt, vbo, nullptr, 0, nullptr, 1, &texture);
/* Commit objects */ /* Commit objects */
std::unique_ptr<IGraphicsData> data = factory->commit(); IGraphicsData* data = factory->commit();
/* Wait for exit */ /* Wait for exit */
while (self->running) while (self->running)
@ -301,7 +301,7 @@ struct TestApplicationCallback : IApplicationCallback
gfxQ->present(); gfxQ->present();
gfxQ->execute(); gfxQ->execute();
//fprintf(stderr, "%zu\n", frameIdx++); fprintf(stderr, "%zu\n", frameIdx);
++frameIdx; ++frameIdx;
if ((frameIdx - lastCheck) > 100) if ((frameIdx - lastCheck) > 100)
@ -344,10 +344,8 @@ int main(int argc, const char** argv)
{ {
LogVisor::RegisterConsoleLogger(); LogVisor::RegisterConsoleLogger();
boo::TestApplicationCallback appCb; boo::TestApplicationCallback appCb;
std::unique_ptr<boo::IApplication> app = int ret = ApplicationRun(boo::IApplication::PLAT_AUTO,
ApplicationBootstrap(boo::IApplication::PLAT_AUTO,
appCb, _S("rwk"), _S("RWK"), argc, argv); appCb, _S("rwk"), _S("RWK"), argc, argv);
int ret = app->run();
printf("IM DYING!!\n"); printf("IM DYING!!\n");
return ret; return ret;
} }