From afe93bee381313c6d0c2611ce40e53c0065c2bb6 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 4 May 2015 13:37:28 -1000 Subject: [PATCH] initial appkit window/glcontext implementation --- include/boo.hpp | 16 +- include/mac/CCGLContext.hpp | 34 ---- include/windowsys/IGraphicsContext.hpp | 52 +++++++ include/windowsys/IWindow.hpp | 34 ++++ libBoo.pri | 20 +-- src/mac/CCGLCocoaView.mm | 0 src/mac/CCGLContext.cpp | 67 -------- src/windowsys/CGraphicsContextCocoa.mm | 207 +++++++++++++++++++++++++ src/windowsys/CWindowCocoa.mm | 102 ++++++++++++ 9 files changed, 401 insertions(+), 131 deletions(-) delete mode 100644 include/mac/CCGLContext.hpp create mode 100644 include/windowsys/IGraphicsContext.hpp create mode 100644 include/windowsys/IWindow.hpp delete mode 100644 src/mac/CCGLCocoaView.mm delete mode 100644 src/mac/CCGLContext.cpp create mode 100644 src/windowsys/CGraphicsContextCocoa.mm create mode 100644 src/windowsys/CWindowCocoa.mm diff --git a/include/boo.hpp b/include/boo.hpp index c407f9e..f4f01c9 100644 --- a/include/boo.hpp +++ b/include/boo.hpp @@ -1,21 +1,7 @@ #ifndef BOO_HPP #define BOO_HPP -#if defined(_WIN32) -#include "win/CWGLContext.hpp" -namespace boo {typedef CWGLContext CGraphicsContext;} - -#elif defined(__APPLE__) -#include "mac/CCGLContext.hpp" -namespace boo {typedef CCGLContext CGraphicsContext;} - -#elif defined(__GNUC__) || defined(__clang__) -#include "x11/CGLXContext.hpp" -namespace boo {typedef CGLXContext CGraphicsContext;} - -#endif - -#include "IGraphicsContext.hpp" +#include "windowsys/IWindow.hpp" #include "inputdev/CDeviceFinder.hpp" #include "inputdev/CDolphinSmashAdapter.hpp" diff --git a/include/mac/CCGLContext.hpp b/include/mac/CCGLContext.hpp deleted file mode 100644 index 5a66f40..0000000 --- a/include/mac/CCGLContext.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef CCGLCONTEXT_HPP -#define CCGLCONTEXT_HPP - -#ifdef __APPLE__ -#include "IGraphicsContext.hpp" -#include - -namespace boo -{ - -class CCGLContext final : public IGraphicsContext -{ -public: - CCGLContext(); - virtual ~CCGLContext(); - - bool create(); - void setMinVersion (const int& min) override; - void setMajorVersion(const int& maj) override; - const std::string version() const override; - const std::string name() const override; - int depthSize() const override; - int redDepth() const override; - int greenDepth() const override; - int blueDepth() const override; -private: - int m_minVersion; - int m_majVersion; -}; - -} - -#endif // __APPLE__ -#endif // CCGLCONTEXT_HPP diff --git a/include/windowsys/IGraphicsContext.hpp b/include/windowsys/IGraphicsContext.hpp new file mode 100644 index 0000000..ebcd5c6 --- /dev/null +++ b/include/windowsys/IGraphicsContext.hpp @@ -0,0 +1,52 @@ +#ifndef IGRAPHICSCONTEXT_HPP +#define IGRAPHICSCONTEXT_HPP + +namespace boo +{ + +class IGraphicsContext +{ +public: + + enum EGraphicsAPI + { + API_NONE = 0, + API_OPENGL_3_3 = 1, + API_OPENGL_4_2 = 2, + API_OPENGLES_3 = 3, + API_VULKAN = 4, + API_D3D11 = 5, + API_METAL = 6 + }; + + enum EPixelFormat + { + PF_NONE = 0, + PF_RGBA8 = 1, /* Default */ + PF_RGBA8_Z24 = 2, + PF_RGBAF32 = 3, + PF_RGBAF32_Z24 = 4 + }; + + virtual ~IGraphicsContext() {} + + virtual EGraphicsAPI getAPI() const=0; + virtual EPixelFormat getPixelFormat() const=0; + virtual void setPixelFormat(EPixelFormat pf)=0; + virtual void setPlatformWindowHandle(void* handle)=0; + virtual void initializeContext()=0; + virtual IGraphicsContext* makeShareContext() const=0; + virtual void makeCurrent()=0; + virtual void clearCurrent()=0; + + /* Note: *all* contexts are double-buffered with + * v-sync interval; please call this */ + virtual void swapBuffer()=0; + +}; + +IGraphicsContext* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api); + +} + +#endif // IGRAPHICSCONTEXT_HPP diff --git a/include/windowsys/IWindow.hpp b/include/windowsys/IWindow.hpp new file mode 100644 index 0000000..212b44c --- /dev/null +++ b/include/windowsys/IWindow.hpp @@ -0,0 +1,34 @@ +#ifndef IWINDOW_HPP +#define IWINDOW_HPP + +#include + +namespace boo +{ + +class IWindow +{ +public: + + virtual ~IWindow() {} + + virtual void showWindow()=0; + virtual void hideWindow()=0; + + virtual std::string getTitle()=0; + virtual void setTitle(const std::string& title)=0; + + virtual void setWindowFrameDefault()=0; + virtual void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const=0; + virtual void setWindowFrame(float x, float y, float w, float h)=0; + + virtual bool isFullscreen() const=0; + virtual void setFullscreen(bool fs)=0; + +}; + +IWindow* IWindowNew(); + +} + +#endif // IWINDOW_HPP diff --git a/libBoo.pri b/libBoo.pri index f589cd3..f15161c 100644 --- a/libBoo.pri +++ b/libBoo.pri @@ -1,12 +1,7 @@ HEADERS += \ $$PWD/include/boo.hpp \ - $$PWD/include/IGraphicsContext.hpp \ - $$PWD/include/ISurface.hpp \ - $$PWD/include/CSurface.hpp \ - $$PWD/include/IRetraceWaiter.hpp \ - $$PWD/include/IInputWaiter.hpp \ - $$PWD/include/CInputRelay.hpp \ - $$PWD/include/CInputDeferredRelay.hpp \ + $$PWD/include/windowsys/IWindow.hpp \ + $$PWD/include/windowsys/IGraphicsContext.hpp \ $$PWD/include/inputdev/CDolphinSmashAdapter.hpp \ $$PWD/include/inputdev/CRevolutionPad.hpp \ $$PWD/include/inputdev/CCafeProPad.hpp \ @@ -36,7 +31,6 @@ SOURCES += \ unix:!macx { HEADERS += \ $$PWD/include/x11/CGLXContext.hpp - SOURCES += \ $$PWD/src/x11/CGLXContext.cpp } @@ -45,21 +39,17 @@ linux { SOURCES += \ $$PWD/src/inputdev/CHIDListenerUdev.cpp \ $$PWD/src/inputdev/CHIDDeviceUdev.cpp - LIBS += -ludev } macx { - HEADERS += \ - $$PWD/include/mac/CCGLContext.hpp - SOURCES += \ - $$PWD/src/mac/CCGLContext.cpp \ $$PWD/src/inputdev/CHIDDeviceIOKit.cpp \ $$PWD/src/inputdev/CHIDListenerIOKit.cpp - OBJECTIVE_SOURCES += \ - $$PWD/src/mac/CCGLCocoaView.mm + $$PWD/src/windowsys/CWindowCocoa.mm \ + $$PWD/src/windowsys/CGraphicsContextCocoa.mm + LIBS += -framework AppKit } win32 { diff --git a/src/mac/CCGLCocoaView.mm b/src/mac/CCGLCocoaView.mm deleted file mode 100644 index e69de29..0000000 diff --git a/src/mac/CCGLContext.cpp b/src/mac/CCGLContext.cpp deleted file mode 100644 index 7e3217c..0000000 --- a/src/mac/CCGLContext.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifdef __APPLE__ -#include "CCGLContext.hpp" -#include - -namespace boo -{ - -CCGLContext::CCGLContext() - : m_minVersion(3), - m_majVersion(3) -{ - std::cout << "Hello from CGL" << std::endl; -} - -CCGLContext::~CCGLContext() -{ - -} - -bool CCGLContext::create() -{ - return true; -} - -void CCGLContext::setMinVersion(const int& min) -{ - m_minVersion = min; -} - -void CCGLContext::setMajorVersion(const int& maj) -{ - m_majVersion = maj; -} - -const std::string CCGLContext::version() const -{ - return "Invalid version"; -} - -const std::string CCGLContext::name() const -{ - return "GLX Context"; -} - -int CCGLContext::depthSize() const -{ - return -1; -} - -int CCGLContext::redDepth() const -{ - return -1; -} - -int CCGLContext::greenDepth() const -{ - return -1; -} - -int CCGLContext::blueDepth() const -{ - return -1; -} - -} - -#endif \ No newline at end of file diff --git a/src/windowsys/CGraphicsContextCocoa.mm b/src/windowsys/CGraphicsContextCocoa.mm new file mode 100644 index 0000000..e217697 --- /dev/null +++ b/src/windowsys/CGraphicsContextCocoa.mm @@ -0,0 +1,207 @@ +#import +#include +#include +#include "windowsys/IGraphicsContext.hpp" + +static const NSOpenGLPixelFormatAttribute PF_RGBA8_ATTRS[] = +{ + NSOpenGLPFAAccelerated, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, +}; + +static const NSOpenGLPixelFormatAttribute PF_RGBA8_Z24_ATTRS[] = +{ + NSOpenGLPFAAccelerated, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, +}; + +static const NSOpenGLPixelFormatAttribute PF_RGBAF32_ATTRS[] = +{ + NSOpenGLPFAAccelerated, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorFloat, + NSOpenGLPFAColorSize, 96, + NSOpenGLPFAAlphaSize, 32, +}; + +static const NSOpenGLPixelFormatAttribute PF_RGBAF32_Z24_ATTRS[] = +{ + NSOpenGLPFAAccelerated, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorFloat, + NSOpenGLPFAColorSize, 96, + NSOpenGLPFAAlphaSize, 32, + NSOpenGLPFADepthSize, 24, +}; + +static const NSOpenGLPixelFormatAttribute* PF_TABLE[] = +{ + NULL, + PF_RGBA8_ATTRS, + PF_RGBA8_Z24_ATTRS, + PF_RGBAF32_ATTRS, + PF_RGBAF32_Z24_ATTRS +}; + +namespace boo {class CGraphicsContextCocoa;} +@interface CGraphicsContextCocoaInternal : NSOpenGLView +- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx; +@end + +namespace boo +{ + +class CGraphicsContextCocoa final : public IGraphicsContext +{ + + EGraphicsAPI m_api; + EPixelFormat m_pf; + NSWindow* m_parentWindow; + CGraphicsContextCocoaInternal* m_nsContext; + NSOpenGLContext* m_nsShareContext; + +public: + CGraphicsContextCocoa(EGraphicsAPI api) + : m_api(api), + m_pf(PF_RGBA8), + m_parentWindow(NULL), + m_nsContext(NULL), + m_nsShareContext(NULL) + {} + + ~CGraphicsContextCocoa() + { + [m_nsContext release]; + [m_nsShareContext release]; + } + + 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 setPlatformWindowHandle(void* handle) + { + m_parentWindow = (NSWindow*)handle; + } + + void initializeContext() + { + if (m_nsShareContext) + return; + m_nsContext = [[CGraphicsContextCocoaInternal alloc] initWithBooContext:this]; + [m_parentWindow setContentView:m_nsContext]; + } + + IGraphicsContext* makeShareContext() const + { + NSOpenGLContext* nsctx; + if (m_nsContext) + { + nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsContext pixelFormat] + shareContext:[m_nsContext openGLContext]]; + } + else if (m_nsShareContext) + { + nsctx = [[NSOpenGLContext alloc] initWithFormat:[m_nsShareContext pixelFormat] + shareContext:m_nsShareContext]; + } + else + return NULL; + if (!nsctx) + return NULL; + CGraphicsContextCocoa* newCtx = new CGraphicsContextCocoa(m_api); + newCtx->m_nsShareContext = nsctx; + return newCtx; + } + + void makeCurrent() + { + if (m_nsContext) + [[m_nsContext openGLContext] makeCurrentContext]; + else if (m_nsShareContext) + [m_nsShareContext makeCurrentContext]; + } + + void clearCurrent() + { + [NSOpenGLContext clearCurrentContext]; + } + + void swapBuffer() + { + [[m_nsContext openGLContext] flushBuffer]; + } + +}; + +IGraphicsContext* IGraphicsContextNew(IGraphicsContext::EGraphicsAPI api) +{ + if (api != IGraphicsContext::API_OPENGL_3_3 && api != IGraphicsContext::API_OPENGL_4_2) + return NULL; + + /* Create temporary context to query GL version */ + NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS]; + if (!nspf) + return NULL; + NSOpenGLContext* nsctx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:nil]; + [nspf release]; + if (!nsctx) + return NULL; + [nsctx makeCurrentContext]; + const char* glVersion = (char*)glGetString(GL_VERSION); + unsigned major = 0; + unsigned minor = 0; + if (glVersion) + { + major = glVersion[0] - '0'; + minor = glVersion[2] - '0'; + } + [NSOpenGLContext clearCurrentContext]; + [nsctx release]; + if (!glVersion) + return NULL; + + if (major > 4 || (major == 4 && minor >= 2)) + api = IGraphicsContext::API_OPENGL_4_2; + else if (major == 3 && minor >= 3) + if (api == IGraphicsContext::API_OPENGL_4_2) + return NULL; + + return new CGraphicsContextCocoa(api); +} + +} + +@implementation CGraphicsContextCocoaInternal +- (id)initWithBooContext:(boo::CGraphicsContextCocoa*)bctx +{ + boo::IGraphicsContext::EPixelFormat pf = bctx->getPixelFormat(); + NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[pf]]; + self = [self initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:nspf]; + [nspf release]; + return self; +} +@end + diff --git a/src/windowsys/CWindowCocoa.mm b/src/windowsys/CWindowCocoa.mm new file mode 100644 index 0000000..9d41c3a --- /dev/null +++ b/src/windowsys/CWindowCocoa.mm @@ -0,0 +1,102 @@ +#import +#include "windowsys/IWindow.hpp" +#include "windowsys/IGraphicsContext.hpp" + +@interface CWindowCocoaInternal : NSWindow +@end + +namespace boo +{ + +class CWindowCocoa final : public IWindow +{ + + CWindowCocoaInternal* m_nsWindow; + IGraphicsContext* m_gfxCtx; + +public: + CWindowCocoa() + { + m_nsWindow = [CWindowCocoaInternal new]; + m_gfxCtx = IGraphicsContextNew(IGraphicsContext::API_OPENGL_3_3); + m_gfxCtx->setPlatformWindowHandle(m_nsWindow); + m_gfxCtx->initializeContext(); + } + + ~CWindowCocoa() + { + [m_nsWindow orderOut:nil]; + [m_nsWindow release]; + delete m_gfxCtx; + } + + void showWindow() + { + [m_nsWindow makeKeyAndOrderFront:nil]; + } + + void hideWindow() + { + [m_nsWindow orderOut:nil]; + } + + std::string getTitle() + { + return [[m_nsWindow title] UTF8String]; + } + + void setTitle(const std::string& title) + { + [m_nsWindow setTitle:[NSString stringWithUTF8String:title.c_str()]]; + } + + void setWindowFrameDefault() + { + NSScreen* mainScreen = [NSScreen mainScreen]; + NSRect scrFrame = mainScreen.frame; + float x_off = scrFrame.size.width / 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]; + } + + void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const + { + NSRect wFrame = m_nsWindow.frame; + xOut = wFrame.origin.x; + yOut = wFrame.origin.y; + wOut = wFrame.size.width; + hOut = wFrame.size.height; + } + + void setWindowFrame(float x, float y, float w, float h) + { + NSRect wFrame = NSMakeRect(x, y, w, h); + [m_nsWindow setFrame:wFrame display:NO]; + } + + bool isFullscreen() const + { + return ([m_nsWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask; + } + + void setFullscreen(bool fs) + { + if ((fs && !isFullscreen()) || (!fs && isFullscreen())) + [m_nsWindow toggleFullScreen:nil]; + } + +}; + +IWindow* IWindowNew() +{ + return new CWindowCocoa; +} + +} + +@implementation CWindowCocoaInternal +{ + +} +@end +