|
|
@@ -7,44 +7,9 @@
|
|
|
#include "cursor.h"
|
|
|
#include "menu.h"
|
|
|
#include <OpenGL/gl.h>
|
|
|
+#include "rendertarget.h"
|
|
|
+
|
|
|
|
|
|
-class SoftwareDrawingOperation
|
|
|
-{
|
|
|
-public:
|
|
|
- void* Data = 0;
|
|
|
- AvnFramebuffer Desc;
|
|
|
- void Alloc(NSView* view)
|
|
|
- {
|
|
|
- auto logicalSize = [view frame].size;
|
|
|
- auto pixelSize = [view convertSizeToBacking:logicalSize];
|
|
|
- int w = pixelSize.width;
|
|
|
- int h = pixelSize.height;
|
|
|
- int stride = w * 4;
|
|
|
- Data = malloc(h * stride);
|
|
|
- Desc = {
|
|
|
- .Data = Data,
|
|
|
- .Stride = stride,
|
|
|
- .Width = w,
|
|
|
- .Height = h,
|
|
|
- .PixelFormat = kAvnRgba8888,
|
|
|
- .Dpi = AvnVector { .X = w / logicalSize.width * 96, .Y = h / logicalSize.height * 96}
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- void Dealloc()
|
|
|
- {
|
|
|
- if(Data != NULL)
|
|
|
- {
|
|
|
- free(Data);
|
|
|
- Data = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ~SoftwareDrawingOperation()
|
|
|
- {
|
|
|
- Dealloc();
|
|
|
- }
|
|
|
-};
|
|
|
|
|
|
class WindowBaseImpl : public virtual ComSingleObject<IAvnWindowBase, &IID_IAvnWindowBase>, public INSWindowHolder
|
|
|
{
|
|
|
@@ -61,15 +26,18 @@ public:
|
|
|
AvnView* View;
|
|
|
AvnWindow* Window;
|
|
|
ComPtr<IAvnWindowBaseEvents> BaseEvents;
|
|
|
- SoftwareDrawingOperation CurrentSwDrawingOperation;
|
|
|
+ ComPtr<IAvnGlContext> _glContext;
|
|
|
+ NSObject<IRenderTarget>* renderTarget;
|
|
|
AvnPoint lastPositionSet;
|
|
|
NSString* _lastTitle;
|
|
|
IAvnAppMenu* _mainMenu;
|
|
|
|
|
|
- WindowBaseImpl(IAvnWindowBaseEvents* events)
|
|
|
+ WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl)
|
|
|
{
|
|
|
_mainMenu = nullptr;
|
|
|
BaseEvents = events;
|
|
|
+ _glContext = gl;
|
|
|
+ renderTarget = [[IOSurfaceRenderTarget alloc] initWithOpenGlContext: gl];
|
|
|
View = [[AvnView alloc] initWithParent:this];
|
|
|
|
|
|
Window = [[AvnWindow alloc] initWithParent:this];
|
|
|
@@ -291,29 +259,6 @@ public:
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
- virtual bool TryLock() override
|
|
|
- {
|
|
|
- @autoreleasepool
|
|
|
- {
|
|
|
- @try
|
|
|
- {
|
|
|
- return [View lockFocusIfCanDraw] == YES;
|
|
|
- }
|
|
|
- @catch (NSException*)
|
|
|
- {
|
|
|
- return NO;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- virtual void Unlock() override
|
|
|
- {
|
|
|
- @autoreleasepool
|
|
|
- {
|
|
|
- [View unlockFocus];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
virtual HRESULT BeginMoveDrag () override
|
|
|
{
|
|
|
@autoreleasepool
|
|
|
@@ -408,16 +353,6 @@ public:
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
- virtual HRESULT GetSoftwareFramebuffer(AvnFramebuffer*ret) override
|
|
|
- {
|
|
|
- if(![[NSThread currentThread] isMainThread])
|
|
|
- return E_FAIL;
|
|
|
- if(CurrentSwDrawingOperation.Data == NULL)
|
|
|
- CurrentSwDrawingOperation.Alloc(View);
|
|
|
- *ret = CurrentSwDrawingOperation.Desc;
|
|
|
- return S_OK;
|
|
|
- }
|
|
|
-
|
|
|
virtual HRESULT SetCursor(IAvnCursor* cursor) override
|
|
|
{
|
|
|
@autoreleasepool
|
|
|
@@ -451,8 +386,8 @@ public:
|
|
|
{
|
|
|
if(View == NULL)
|
|
|
return E_FAIL;
|
|
|
- *ppv = ::CreateGlRenderTarget(Window, View);
|
|
|
- return S_OK;
|
|
|
+ *ppv = [renderTarget createSurfaceRenderTarget];
|
|
|
+ return *ppv == nil ? E_FAIL : S_OK;
|
|
|
}
|
|
|
|
|
|
protected:
|
|
|
@@ -490,7 +425,7 @@ private:
|
|
|
}
|
|
|
|
|
|
ComPtr<IAvnWindowEvents> WindowEvents;
|
|
|
- WindowImpl(IAvnWindowEvents* events) : WindowBaseImpl(events)
|
|
|
+ WindowImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl)
|
|
|
{
|
|
|
WindowEvents = events;
|
|
|
[Window setCanBecomeKeyAndMain];
|
|
|
@@ -731,6 +666,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
|
|
|
NSEvent* _lastMouseDownEvent;
|
|
|
bool _lastKeyHandled;
|
|
|
AvnPixelSize _lastPixelSize;
|
|
|
+ NSObject<IRenderTarget>* _renderTarget;
|
|
|
}
|
|
|
|
|
|
- (void)onClosed
|
|
|
@@ -741,19 +677,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-- (BOOL)lockFocusIfCanDraw
|
|
|
-{
|
|
|
- @synchronized (self)
|
|
|
- {
|
|
|
- if(_parent == nullptr)
|
|
|
- {
|
|
|
- return NO;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return [super lockFocusIfCanDraw];
|
|
|
-}
|
|
|
-
|
|
|
-(AvnPixelSize) getPixelSize
|
|
|
{
|
|
|
return _lastPixelSize;
|
|
|
@@ -764,18 +687,43 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
|
|
|
return _lastMouseDownEvent;
|
|
|
}
|
|
|
|
|
|
+- (void) updateRenderTarget
|
|
|
+{
|
|
|
+ [_renderTarget resize:_lastPixelSize withScale: [[self window] backingScaleFactor]];
|
|
|
+ [self setNeedsDisplayInRect:[self frame]];
|
|
|
+}
|
|
|
+
|
|
|
-(AvnView*) initWithParent: (WindowBaseImpl*) parent
|
|
|
{
|
|
|
self = [super init];
|
|
|
- [self setWantsBestResolutionOpenGLSurface:true];
|
|
|
+ _renderTarget = parent->renderTarget;
|
|
|
[self setWantsLayer:YES];
|
|
|
+ [self setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawDuringViewResize];
|
|
|
+
|
|
|
_parent = parent;
|
|
|
_area = nullptr;
|
|
|
_lastPixelSize.Height = 100;
|
|
|
_lastPixelSize.Width = 100;
|
|
|
+
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
+- (BOOL)isFlipped
|
|
|
+{
|
|
|
+ return YES;
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)wantsUpdateLayer
|
|
|
+{
|
|
|
+ return YES;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setLayer:(CALayer *)layer
|
|
|
+{
|
|
|
+ [_renderTarget setNewLayer: layer];
|
|
|
+ [super setLayer: layer];
|
|
|
+}
|
|
|
+
|
|
|
- (BOOL)isOpaque
|
|
|
{
|
|
|
return YES;
|
|
|
@@ -823,87 +771,32 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
|
|
|
auto fsize = [self convertSizeToBacking: [self frame].size];
|
|
|
_lastPixelSize.Width = (int)fsize.width;
|
|
|
_lastPixelSize.Height = (int)fsize.height;
|
|
|
-
|
|
|
+ [self updateRenderTarget];
|
|
|
_parent->BaseEvents->Resized(AvnSize{newSize.width, newSize.height});
|
|
|
}
|
|
|
|
|
|
-- (void) drawFb: (AvnFramebuffer*) fb
|
|
|
-{
|
|
|
- auto colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
- auto dataProvider = CGDataProviderCreateWithData(NULL, fb->Data, fb->Height*fb->Stride, NULL);
|
|
|
|
|
|
-
|
|
|
- auto image = CGImageCreate(fb->Width, fb->Height, 8, 32, fb->Stride, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast,
|
|
|
- dataProvider, nullptr, false, kCGRenderingIntentDefault);
|
|
|
-
|
|
|
- auto ctx = [NSGraphicsContext currentContext];
|
|
|
-
|
|
|
- [ctx saveGraphicsState];
|
|
|
- auto cgc = [ctx CGContext];
|
|
|
-
|
|
|
- CGContextDrawImage(cgc, CGRect{0,0, fb->Width/(fb->Dpi.X/96), fb->Height/(fb->Dpi.Y/96)}, image);
|
|
|
- CGImageRelease(image);
|
|
|
- CGColorSpaceRelease(colorSpace);
|
|
|
- CGDataProviderRelease(dataProvider);
|
|
|
-
|
|
|
- [ctx restoreGraphicsState];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (void)drawRect:(NSRect)dirtyRect
|
|
|
+- (void)updateLayer
|
|
|
{
|
|
|
if (_parent == nullptr)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- _parent->BaseEvents->RunRenderPriorityJobs();
|
|
|
|
|
|
- @synchronized (self) {
|
|
|
- if(_swRenderedFrame != NULL)
|
|
|
- {
|
|
|
- [self drawFb: &_swRenderedFrameBuffer];
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- auto swOp = &_parent->CurrentSwDrawingOperation;
|
|
|
+ _parent->BaseEvents->RunRenderPriorityJobs();
|
|
|
_parent->BaseEvents->Paint();
|
|
|
- if(swOp->Data != NULL)
|
|
|
- [self drawFb: &swOp->Desc];
|
|
|
-
|
|
|
- swOp->Dealloc();
|
|
|
- return;
|
|
|
}
|
|
|
|
|
|
--(void) redrawSelf
|
|
|
+- (void)drawRect:(NSRect)dirtyRect
|
|
|
{
|
|
|
- @autoreleasepool
|
|
|
- {
|
|
|
- @synchronized(self)
|
|
|
- {
|
|
|
- if(!_queuedDisplayFromThread)
|
|
|
- return;
|
|
|
- _queuedDisplayFromThread = false;
|
|
|
- }
|
|
|
- [self setNeedsDisplayInRect:[self frame]];
|
|
|
- [self display];
|
|
|
-
|
|
|
- }
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
-(void) setSwRenderedFrame: (AvnFramebuffer*) fb dispose: (IUnknown*) dispose
|
|
|
{
|
|
|
@autoreleasepool {
|
|
|
- @synchronized (self) {
|
|
|
- _swRenderedFrame = dispose;
|
|
|
- _swRenderedFrameBuffer = *fb;
|
|
|
- if(!_queuedDisplayFromThread)
|
|
|
- {
|
|
|
- _queuedDisplayFromThread = true;
|
|
|
- [self performSelector:@selector(redrawSelf) onThread:[NSThread mainThread] withObject:NULL waitUntilDone:false modes: AllLoopModes];
|
|
|
- }
|
|
|
- }
|
|
|
+ [_renderTarget setSwFrame:fb];
|
|
|
+ dispose->Release();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -928,7 +821,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
|
|
|
auto fsize = [self convertSizeToBacking: [self frame].size];
|
|
|
_lastPixelSize.Width = (int)fsize.width;
|
|
|
_lastPixelSize.Height = (int)fsize.height;
|
|
|
-
|
|
|
+ [self updateRenderTarget];
|
|
|
_parent->BaseEvents->ScalingChanged([_parent->Window backingScaleFactor]);
|
|
|
|
|
|
[super viewDidChangeBackingProperties];
|
|
|
@@ -1478,7 +1371,7 @@ private:
|
|
|
END_INTERFACE_MAP()
|
|
|
virtual ~PopupImpl(){}
|
|
|
ComPtr<IAvnWindowEvents> WindowEvents;
|
|
|
- PopupImpl(IAvnWindowEvents* events) : WindowBaseImpl(events)
|
|
|
+ PopupImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl)
|
|
|
{
|
|
|
WindowEvents = events;
|
|
|
[Window setLevel:NSPopUpMenuWindowLevel];
|
|
|
@@ -1502,20 +1395,20 @@ protected:
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events)
|
|
|
+extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl)
|
|
|
{
|
|
|
@autoreleasepool
|
|
|
{
|
|
|
- IAvnPopup* ptr = dynamic_cast<IAvnPopup*>(new PopupImpl(events));
|
|
|
+ IAvnPopup* ptr = dynamic_cast<IAvnPopup*>(new PopupImpl(events, gl));
|
|
|
return ptr;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events)
|
|
|
+extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl)
|
|
|
{
|
|
|
@autoreleasepool
|
|
|
{
|
|
|
- IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events);
|
|
|
+ IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events, gl);
|
|
|
return ptr;
|
|
|
}
|
|
|
}
|