21 changed files with 490 additions and 375 deletions
@ -0,0 +1,166 @@ |
|||
#include "common.h" |
|||
#include <dlfcn.h> |
|||
|
|||
static CGLContextObj CreateCglContext(CGLContextObj share) |
|||
{ |
|||
int attributes[] = { |
|||
kCGLPFAAccelerated, |
|||
kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, |
|||
kCGLPFADepthSize, 8, |
|||
kCGLPFAStencilSize, 8, |
|||
kCGLPFAColorSize, 32, |
|||
0 |
|||
}; |
|||
|
|||
CGLPixelFormatObj pix; |
|||
CGLError errorCode; |
|||
GLint num; // stores the number of possible pixel formats |
|||
errorCode = CGLChoosePixelFormat( (CGLPixelFormatAttribute*)attributes, &pix, &num ); |
|||
if(errorCode != 0) |
|||
return nil; |
|||
CGLContextObj ctx = nil; |
|||
errorCode = CGLCreateContext(pix, share, &ctx ); |
|||
CGLDestroyPixelFormat( pix ); |
|||
if(errorCode != 0) |
|||
return nil; |
|||
return ctx; |
|||
}; |
|||
|
|||
|
|||
|
|||
class AvnGlContext : public virtual ComSingleObject<IAvnGlContext, &IID_IAvnGlContext> |
|||
{ |
|||
// Debug |
|||
int _usageCount = 0; |
|||
public: |
|||
CGLContextObj Context; |
|||
int SampleCount = 0, StencilBits = 0; |
|||
FORWARD_IUNKNOWN() |
|||
|
|||
class SavedGlContext : public virtual ComUnknownObject |
|||
{ |
|||
CGLContextObj _savedContext; |
|||
ComPtr<AvnGlContext> _parent; |
|||
public: |
|||
SavedGlContext(CGLContextObj saved, AvnGlContext* parent) |
|||
{ |
|||
_savedContext = saved; |
|||
_parent = parent; |
|||
_parent->_usageCount++; |
|||
} |
|||
|
|||
~SavedGlContext() |
|||
{ |
|||
if(_parent->Context == CGLGetCurrentContext()) |
|||
CGLSetCurrentContext(_savedContext); |
|||
_parent->_usageCount--; |
|||
CGLUnlockContext(_parent->Context); |
|||
} |
|||
}; |
|||
|
|||
AvnGlContext(CGLContextObj context) |
|||
{ |
|||
Context = context; |
|||
CGLPixelFormatObj fmt = CGLGetPixelFormat(context); |
|||
CGLDescribePixelFormat(fmt, 0, kCGLPFASamples, &SampleCount); |
|||
CGLDescribePixelFormat(fmt, 0, kCGLPFAStencilSize, &StencilBits); |
|||
|
|||
} |
|||
|
|||
virtual HRESULT LegacyMakeCurrent() override |
|||
{ |
|||
if(CGLSetCurrentContext(Context) != 0) |
|||
return E_FAIL; |
|||
return S_OK; |
|||
} |
|||
|
|||
virtual HRESULT MakeCurrent(IUnknown** ppv) override |
|||
{ |
|||
CGLContextObj saved = CGLGetCurrentContext(); |
|||
CGLLockContext(Context); |
|||
if(CGLSetCurrentContext(Context) != 0) |
|||
{ |
|||
CGLUnlockContext(Context); |
|||
return E_FAIL; |
|||
} |
|||
*ppv = new SavedGlContext(saved, this); |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
virtual int GetSampleCount() override |
|||
{ |
|||
return SampleCount; |
|||
} |
|||
|
|||
virtual int GetStencilSize() override |
|||
{ |
|||
return StencilBits; |
|||
} |
|||
|
|||
virtual void* GetNativeHandle() override |
|||
{ |
|||
return Context; |
|||
} |
|||
|
|||
~AvnGlContext() |
|||
{ |
|||
CGLReleaseContext(Context); |
|||
} |
|||
}; |
|||
|
|||
class AvnGlDisplay : public virtual ComSingleObject<IAvnGlDisplay, &IID_IAvnGlDisplay> |
|||
{ |
|||
void* _libgl; |
|||
|
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
|
|||
AvnGlDisplay() |
|||
{ |
|||
_libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", RTLD_LAZY); |
|||
} |
|||
|
|||
virtual void* GetProcAddress(char* proc) override |
|||
{ |
|||
return dlsym(_libgl, proc); |
|||
} |
|||
|
|||
virtual HRESULT CreateContext(IAvnGlContext* share, IAvnGlContext**ppv) override |
|||
{ |
|||
CGLContextObj shareContext = nil; |
|||
if(share != nil) |
|||
{ |
|||
AvnGlContext* shareCtx = dynamic_cast<AvnGlContext*>(share); |
|||
if(shareCtx != nil) |
|||
shareContext = shareCtx->Context; |
|||
} |
|||
CGLContextObj ctx = ::CreateCglContext(shareContext); |
|||
if(ctx == nil) |
|||
return E_FAIL; |
|||
*ppv = new AvnGlContext(ctx); |
|||
return S_OK; |
|||
} |
|||
|
|||
virtual HRESULT WrapContext(void* native, IAvnGlContext**ppv) override |
|||
{ |
|||
if(native == nil) |
|||
return E_INVALIDARG; |
|||
*ppv = new AvnGlContext((CGLContextObj) native); |
|||
return S_OK; |
|||
} |
|||
|
|||
virtual void LegacyClearCurrentContext() override |
|||
{ |
|||
CGLSetCurrentContext(nil); |
|||
} |
|||
}; |
|||
|
|||
static IAvnGlDisplay* GlDisplay = new AvnGlDisplay(); |
|||
|
|||
|
|||
extern IAvnGlDisplay* GetGlDisplay() |
|||
{ |
|||
return GlDisplay; |
|||
}; |
|||
|
|||
@ -1,261 +0,0 @@ |
|||
#include "common.h" |
|||
#include <OpenGL/gl.h> |
|||
#include <dlfcn.h> |
|||
#include "window.h" |
|||
|
|||
template <typename T, size_t N> char (&ArrayCounter(T (&a)[N]))[N]; |
|||
#define ARRAY_COUNT(a) (sizeof(ArrayCounter(a))) |
|||
|
|||
NSOpenGLPixelFormat* CreateFormat() |
|||
{ |
|||
NSOpenGLPixelFormatAttribute attribs[] = |
|||
{ |
|||
NSOpenGLPFADoubleBuffer, |
|||
NSOpenGLPFAColorSize, 32, |
|||
NSOpenGLPFAStencilSize, 8, |
|||
NSOpenGLPFADepthSize, 8, |
|||
0 |
|||
}; |
|||
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; |
|||
} |
|||
|
|||
class AvnGlContext : public virtual ComSingleObject<IAvnGlContext, &IID_IAvnGlContext> |
|||
{ |
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
NSOpenGLContext* GlContext; |
|||
GLuint Framebuffer, RenderBuffer, StencilBuffer; |
|||
AvnGlContext(NSOpenGLContext* gl, bool offscreen) |
|||
{ |
|||
Framebuffer = 0; |
|||
RenderBuffer = 0; |
|||
StencilBuffer = 0; |
|||
GlContext = gl; |
|||
if(offscreen) |
|||
{ |
|||
[GlContext makeCurrentContext]; |
|||
|
|||
glGenFramebuffersEXT(1, &Framebuffer); |
|||
glBindFramebufferEXT(GL_FRAMEBUFFER, Framebuffer); |
|||
glGenRenderbuffersEXT(1, &RenderBuffer); |
|||
glGenRenderbuffersEXT(1, &StencilBuffer); |
|||
|
|||
glBindRenderbufferEXT(GL_RENDERBUFFER, StencilBuffer); |
|||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, StencilBuffer); |
|||
glBindRenderbufferEXT(GL_RENDERBUFFER, RenderBuffer); |
|||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, RenderBuffer); |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
virtual HRESULT MakeCurrent() override |
|||
{ |
|||
[GlContext makeCurrentContext];/* |
|||
glBindFramebufferEXT(GL_FRAMEBUFFER, Framebuffer); |
|||
glBindRenderbufferEXT(GL_RENDERBUFFER, RenderBuffer); |
|||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, RenderBuffer); |
|||
glBindRenderbufferEXT(GL_RENDERBUFFER, StencilBuffer); |
|||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, StencilBuffer);*/ |
|||
return S_OK; |
|||
} |
|||
}; |
|||
|
|||
class AvnGlDisplay : public virtual ComSingleObject<IAvnGlDisplay, &IID_IAvnGlDisplay> |
|||
{ |
|||
int _sampleCount, _stencilSize; |
|||
void* _libgl; |
|||
|
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
|
|||
AvnGlDisplay(int sampleCount, int stencilSize) |
|||
{ |
|||
_sampleCount = sampleCount; |
|||
_stencilSize = stencilSize; |
|||
_libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", RTLD_LAZY); |
|||
} |
|||
|
|||
virtual HRESULT GetSampleCount(int* ret) override |
|||
{ |
|||
*ret = _sampleCount; |
|||
return S_OK; |
|||
} |
|||
virtual HRESULT GetStencilSize(int* ret) override |
|||
{ |
|||
*ret = _stencilSize; |
|||
return S_OK; |
|||
} |
|||
|
|||
virtual HRESULT ClearContext() override |
|||
{ |
|||
[NSOpenGLContext clearCurrentContext]; |
|||
return S_OK; |
|||
} |
|||
|
|||
virtual void* GetProcAddress(char* proc) override |
|||
{ |
|||
return dlsym(_libgl, proc); |
|||
} |
|||
}; |
|||
|
|||
|
|||
class GlFeature : public virtual ComSingleObject<IAvnGlFeature, &IID_IAvnGlFeature> |
|||
{ |
|||
IAvnGlDisplay* _display; |
|||
AvnGlContext *_immediate; |
|||
NSOpenGLContext* _shared; |
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
NSOpenGLPixelFormat* _format; |
|||
GlFeature(IAvnGlDisplay* display, AvnGlContext* immediate, NSOpenGLPixelFormat* format) |
|||
{ |
|||
_display = display; |
|||
_immediate = immediate; |
|||
_format = format; |
|||
_shared = [[NSOpenGLContext alloc] initWithFormat:_format shareContext:_immediate->GlContext]; |
|||
} |
|||
|
|||
NSOpenGLContext* CreateContext() |
|||
{ |
|||
return _shared; |
|||
//return [[NSOpenGLContext alloc] initWithFormat:_format shareContext:nil]; |
|||
} |
|||
|
|||
virtual HRESULT ObtainDisplay(IAvnGlDisplay**retOut) override |
|||
{ |
|||
*retOut = _display; |
|||
_display->AddRef(); |
|||
return S_OK; |
|||
} |
|||
|
|||
virtual HRESULT ObtainImmediateContext(IAvnGlContext**retOut) override |
|||
{ |
|||
*retOut = _immediate; |
|||
_immediate->AddRef(); |
|||
return S_OK; |
|||
} |
|||
}; |
|||
|
|||
static GlFeature* Feature; |
|||
|
|||
GlFeature* CreateGlFeature() |
|||
{ |
|||
auto format = CreateFormat(); |
|||
if(format == nil) |
|||
{ |
|||
NSLog(@"Unable to choose pixel format"); |
|||
return NULL; |
|||
} |
|||
|
|||
auto immediateContext = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil]; |
|||
if(immediateContext == nil) |
|||
{ |
|||
NSLog(@"Unable to create NSOpenGLContext"); |
|||
return NULL; |
|||
} |
|||
|
|||
int stencilBits = 0, sampleCount = 0; |
|||
|
|||
auto fmt = CGLGetPixelFormat([immediateContext CGLContextObj]); |
|||
CGLDescribePixelFormat(fmt, 0, kCGLPFASamples, &sampleCount); |
|||
CGLDescribePixelFormat(fmt, 0, kCGLPFAStencilSize, &stencilBits); |
|||
|
|||
auto offscreen = new AvnGlContext(immediateContext, true); |
|||
auto display = new AvnGlDisplay(sampleCount, stencilBits); |
|||
|
|||
return new GlFeature(display, offscreen, format); |
|||
} |
|||
|
|||
|
|||
static GlFeature* GetFeature() |
|||
{ |
|||
if(Feature == nil) |
|||
Feature = CreateGlFeature(); |
|||
return Feature; |
|||
} |
|||
|
|||
extern IAvnGlFeature* GetGlFeature() |
|||
{ |
|||
return GetFeature(); |
|||
} |
|||
|
|||
class AvnGlRenderingSession : public ComSingleObject<IAvnGlSurfaceRenderingSession, &IID_IAvnGlSurfaceRenderingSession> |
|||
{ |
|||
AvnView* _view; |
|||
AvnWindow* _window; |
|||
NSOpenGLContext* _context; |
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
AvnGlRenderingSession(AvnWindow*window, AvnView* view, NSOpenGLContext* context) |
|||
{ |
|||
_context = context; |
|||
_window = window; |
|||
_view = view; |
|||
} |
|||
|
|||
virtual HRESULT GetPixelSize(AvnPixelSize* ret) override |
|||
{ |
|||
*ret = [_view getPixelSize]; |
|||
return S_OK; |
|||
} |
|||
virtual HRESULT GetScaling(double* ret) override |
|||
{ |
|||
*ret = [_window getScaling]; |
|||
return S_OK; |
|||
} |
|||
|
|||
virtual ~AvnGlRenderingSession() |
|||
{ |
|||
[_context flushBuffer]; |
|||
[NSOpenGLContext clearCurrentContext]; |
|||
CGLUnlockContext([_context CGLContextObj]); |
|||
[_view unlockFocus]; |
|||
} |
|||
}; |
|||
|
|||
class AvnGlRenderTarget : public ComSingleObject<IAvnGlSurfaceRenderTarget, &IID_IAvnGlSurfaceRenderTarget> |
|||
{ |
|||
NSView* _view; |
|||
NSWindow* _window; |
|||
NSOpenGLContext* _context; |
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
AvnGlRenderTarget(NSWindow* window, NSView*view) |
|||
{ |
|||
_window = window; |
|||
_view = view; |
|||
_context = GetFeature()->CreateContext(); |
|||
} |
|||
|
|||
virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret) override |
|||
{ |
|||
auto f = GetFeature(); |
|||
if(f == NULL) |
|||
return E_FAIL; |
|||
|
|||
@try |
|||
{ |
|||
if(![_view lockFocusIfCanDraw]) |
|||
return E_ABORT; |
|||
} |
|||
@catch(NSException* exception) |
|||
{ |
|||
return E_ABORT; |
|||
} |
|||
|
|||
|
|||
auto gl = _context; |
|||
CGLLockContext([_context CGLContextObj]); |
|||
[gl setView: _view]; |
|||
[gl update]; |
|||
[gl makeCurrentContext]; |
|||
*ret = new AvnGlRenderingSession(_window, _view, gl); |
|||
return S_OK; |
|||
} |
|||
}; |
|||
|
|||
extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view) |
|||
{ |
|||
return new AvnGlRenderTarget(window, view); |
|||
} |
|||
Loading…
Reference in new issue