Kaydet (Commit) 9796f792 authored tarafından Jan-Marek Glogowski's avatar Jan-Marek Glogowski

tdf#99784 OSX run GUI stuff in the main thread

The extension manager starts dialogs from its own thread. But the
OSX backend currently doesn't defer these calls to the main thread.
This implements the deference by running the called function
in the main thread, using a code ^Block, and returning the result
via a SalYieldMutex member.

Change-Id: Id8977991e3eda91da27c23d8021e028d4f4cefe5
Reviewed-on: https://gerrit.libreoffice.org/42448Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarJan-Marek Glogowski <glogow@fbihome.de>
üst 4067487e
......@@ -23,8 +23,6 @@
#include <vcl/dllapi.h>
#include <vcl/ptrstyle.hxx>
class Point;
class VCL_DLLPUBLIC Pointer
{
PointerStyle meStyle;
......
......@@ -94,7 +94,19 @@ can be added to the scheduler reasonably.
Generally the Scheduler is handled as expected, except on resize, which is
handled with different runloop-modes in MacOS. In case of a resize, the normal
runloop is suspended in sendEvent, so we can't call the scheduler via posted
main loop-events. Instead the schedule the timer again.
main loop-events. Instead the scheduler uses the timer again.
Like the Windows backend, all Cocoa / GUI handling also has to be run in
the main thread. We're emulating Windows out-of-order PeekMessage processing,
via a YieldWakeupEvent and two conditionals. When in a RUNINMAIN call, all
the DBG_TESTSOLARMUTEX calls are disabled, as we can't release the SolarMutex,
but we can prevent running any other SolarMutex based code. Same for all the
SolarMutex acquire and release calls, so the calling and the main thread
don't deadlock. Those wakeup events must be ignored to prevent busy-locks.
We can neither rely on MacOS dispatch_sync code block execution nor the
message handling, as both can't be priorized or filtered and the first
does also not allow nested execution and is just processed in sequence.
There is also a workaround for a problem for pushing tasks to an empty queue,
as [NSApp postEvent: ... atStart: NO] doesn't append the event, if the
......@@ -159,3 +171,15 @@ easy way to process just a single event).
Since the Scheduler is always handled by the system message queue, there is
really no more reasoning to stop after 100 events to prevent LO Scheduler
starvation.
== Run the LO application in its own thread ==
This would probably get rid of most of the MacOS and Windows implementation
details / workarounds, but is quite probably a large amount of work.
Instead of LO running in the main process / thread, we run it in a 2nd thread
and defer al GUI calls to the main thread. This way it'll hopefully not block
and can process system events.
That's just a theory - it definitly needs more analysis before even attemding
an implementation.
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_VCL_INC_OSX_RUNINMAIN_HXX
#define INCLUDED_VCL_INC_OSX_RUNINMAIN_HXX
/**
* Runs a command in the main thread.
*
* These macros are always used like a recursive calls, so they work like
* a closure.
*
* Uses two conditionals for a two way communication.
* The data (code block + result) is protected by the SolarMutex.
*
* There are three main macros, which act as function initializers:
* - OSX_RUNINMAIN - for all functions without return values
* - OSX_RUNINMAIN_POINTER - for all functions returning a pointer
* - OSX_RUNINMAIN_UNION - for all other return types
*
* All types used via OSX_RUNINMAIN_UNION must implement a move constructor,
* so there is no memory leak!
*/
#include <unordered_map>
#include <Block.h>
#include <osl/thread.h>
#include "saltimer.h"
#include "salframe.hxx"
union RuninmainResult
{
void* pointer;
bool boolean;
struct SalFrame::SalPointerState state;
RuninmainResult() {}
};
#define OSX_RUNINMAIN_MEMBERS \
osl::Condition m_aInMainCondition; \
osl::Condition m_aResultCondition; \
RuninmainBlock m_aCodeBlock; \
RuninmainResult m_aResult;
#define OSX_RUNINMAIN( instance, command ) \
if ( !instance->IsMainThread() ) \
{ \
DBG_TESTSOLARMUTEX(); \
SalYieldMutex *aMutex = static_cast<SalYieldMutex*>(instance->GetYieldMutex()); \
assert( !aMutex->m_aCodeBlock ); \
aMutex->m_aCodeBlock = Block_copy(^{ \
command; \
}); \
aMutex->m_aResultCondition.reset(); \
dispatch_async(dispatch_get_main_queue(),^{ \
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
}); \
aMutex->m_aInMainCondition.set(); \
osl::Condition::Result res = aMutex->m_aResultCondition.wait(); \
assert(osl::Condition::Result::result_ok == res); \
return; \
}
#define OSX_RUNINMAIN_POINTER( instance, command, type ) \
if ( !instance->IsMainThread() ) \
{ \
DBG_TESTSOLARMUTEX(); \
SalYieldMutex *aMutex = static_cast<SalYieldMutex*>(instance->GetYieldMutex()); \
assert( !aMutex->m_aCodeBlock ); \
aMutex->m_aCodeBlock = Block_copy(^{ \
aMutex->m_aResult.pointer = static_cast<void*>( command ); \
}); \
aMutex->m_aResultCondition.reset(); \
dispatch_async(dispatch_get_main_queue(),^{ \
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
}); \
aMutex->m_aInMainCondition.set(); \
osl::Condition::Result res = aMutex->m_aResultCondition.wait(); \
assert(osl::Condition::Result::result_ok == res); \
return static_cast<type>( aMutex->m_aResult.pointer ); \
}
#define OSX_RUNINMAIN_UNION( instance, command, member ) \
if ( !instance->IsMainThread() ) \
{ \
DBG_TESTSOLARMUTEX(); \
SalYieldMutex *aMutex = static_cast<SalYieldMutex*>(instance->GetYieldMutex()); \
assert( !aMutex->m_aCodeBlock ); \
aMutex->m_aCodeBlock = Block_copy(^{ \
aMutex->m_aResult.member = command; \
}); \
aMutex->m_aResultCondition.reset(); \
dispatch_async(dispatch_get_main_queue(),^{ \
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
}); \
aMutex->m_aInMainCondition.set(); \
osl::Condition::Result res = aMutex->m_aResultCondition.wait(); \
assert(osl::Condition::Result::result_ok == res); \
return std::move( aMutex->m_aResult.member ); \
}
/**
* convenience macros used from SalInstance
*/
#define OSX_INST_RUNINMAIN( command ) \
OSX_RUNINMAIN( this, command )
#define OSX_INST_RUNINMAIN_POINTER( command, type ) \
OSX_RUNINMAIN_POINTER( this, command, type )
#define OSX_INST_RUNINMAIN_UNION( command, member ) \
OSX_RUNINMAIN_UNION( this, command, member )
/**
* convenience macros using global SalData
*/
#define OSX_SALDATA_RUNINMAIN( command ) \
OSX_RUNINMAIN( GetSalData()->mpFirstInstance, command )
#define OSX_SALDATA_RUNINMAIN_POINTER( command, type ) \
OSX_RUNINMAIN_POINTER( GetSalData()->mpFirstInstance, command, type )
#define OSX_SALDATA_RUNINMAIN_UNION( command, member ) \
OSX_RUNINMAIN_UNION( GetSalData()->mpFirstInstance, command, member )
#endif // INCLUDED_VCL_INC_OSX_RUNINMAIN_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -183,22 +183,22 @@ public:
void VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen = true );
void CocoaToVCL( NSPoint& io_Point, bool bRelativeToScreen = true );
NSCursor* getCurrentCursor() const;
NSCursor* getCurrentCursor();
CGMutablePathRef getClipPath() const { return mrClippingPath; }
// called by VCL_NSApplication to indicate screen settings have changed
void screenParametersChanged();
private: // methods
private: // methods
/** do things on initial show (like centering on parent or on screen)
*/
void initShow();
void initWindowAndView();
private: // data
static AquaSalFrame* s_pCaptureFrame;
private: // data
static AquaSalFrame* s_pCaptureFrame;
AquaSalFrame( const AquaSalFrame& ) = delete;
AquaSalFrame& operator=(const AquaSalFrame&) = delete;
......
......@@ -32,16 +32,31 @@
#endif
#include "salinst.hxx"
#include "osx/runinmain.hxx"
class AquaSalFrame;
class SalFrame;
class SalObject;
class ApplicationEvent;
class Image;
enum class SalEvent;
typedef void(^RuninmainBlock)(void);
class SalYieldMutex : public comphelper::GenericSolarMutex
{
public:
OSX_RUNINMAIN_MEMBERS
protected:
virtual void doAcquire( sal_uInt32 nLockCount ) override;
virtual sal_uInt32 doRelease( bool bUnlockAll ) override;
public:
SalYieldMutex();
virtual ~SalYieldMutex() override;
virtual bool IsCurrentThread() const override;
};
class AquaSalInstance : public SalInstance
......@@ -61,12 +76,12 @@ public:
SalYieldMutex* mpSalYieldMutex; // Sal-Yield-Mutex
OUString maDefaultPrinter;
oslThreadIdentifier maMainThread;
bool mbWaitingYield;
int mnActivePrintJobs;
std::list< SalUserEvent > maUserEvents;
osl::Mutex maUserEventListMutex;
osl::Condition maWaitingYieldCond;
bool mbIsLiveResize;
bool mbNoYieldLock;
static std::list<const ApplicationEvent*> aAppEventList;
......@@ -126,9 +141,7 @@ public:
// this is needed to avoid duplicate open events through a) command line and b) NSApp's openFile
static bool isOnCommandLine( const OUString& );
void wakeupYield();
public:
public:
friend class AquaSalFrame;
void PostUserEvent( AquaSalFrame* pFrame, SalEvent nType, void* pData );
......
......@@ -203,8 +203,8 @@ using namespace ::com::sun::star::uno;
+(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point {
NSValue * value = nil;
Point aPoint( [ AquaA11yUtil nsPointToVclPoint: point ]);
const Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
css::awt::Point aPoint( [ AquaA11yUtil nsPointToVclPoint: point ]);
const css::awt::Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
aPoint.X -= screenPos.X;
aPoint.Y -= screenPos.Y;
sal_Int32 index = [ wrapper accessibleText ] -> getIndexAtPoint( aPoint );
......@@ -239,9 +239,9 @@ using namespace ::com::sun::star::uno;
}
if ( [ wrapper accessibleComponent ] ) {
// get location on screen (must be added since get CharacterBounds returns values relative to parent)
Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
Point pos ( minx + screenPos.X, miny + screenPos.Y );
Point size ( maxx - minx, maxy - miny );
css::awt::Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
css::awt::Point pos ( minx + screenPos.X, miny + screenPos.Y );
css::awt::Point size ( maxx - minx, maxy - miny );
NSValue * nsPos = [ AquaA11yUtil vclPointToNSPoint: pos ];
rect = [ NSValue valueWithRect: NSMakeRect ( [ nsPos pointValue ].x, [ nsPos pointValue ].y - size.Y, size.X, size.Y ) ];
//printf("Range: %s --- Rect: %s\n", [ NSStringFromRange ( [ range rangeValue ] ) UTF8String ], [ NSStringFromRect ( [ rect rectValue ] ) UTF8String ]);
......
This diff is collapsed.
......@@ -46,6 +46,7 @@
#include "osx/salprn.h"
#include "osx/saltimer.h"
#include "osx/vclnsapp.h"
#include "osx/runinmain.hxx"
#include "print.h"
#include "impbmp.hxx"
......@@ -259,6 +260,7 @@ void InitSalMain()
}
SalYieldMutex::SalYieldMutex()
: m_aCodeBlock( nullptr )
{
}
......@@ -266,6 +268,63 @@ SalYieldMutex::~SalYieldMutex()
{
}
void SalYieldMutex::doAcquire( sal_uInt32 nLockCount )
{
AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
if ( pInst && pInst->IsMainThread() )
{
if ( pInst->mbNoYieldLock )
return;
do {
m_aInMainCondition.reset();
if ( m_aCodeBlock )
{
assert( !pInst->mbNoYieldLock );
pInst->mbNoYieldLock = true;
m_aCodeBlock();
pInst->mbNoYieldLock = false;
Block_release( m_aCodeBlock );
m_aCodeBlock = nullptr;
m_aResultCondition.set();
}
// reset condition *before* acquiring!
if (m_aMutex.tryToAcquire())
break;
// wait for doRelease() or RUNINMAIN_* to set the condition
osl::Condition::Result res = m_aInMainCondition.wait();
assert(osl::Condition::Result::result_ok == res);
}
while ( true );
}
else
m_aMutex.acquire();
++m_nCount;
--nLockCount;
comphelper::GenericSolarMutex::doAcquire( nLockCount );
}
sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll )
{
AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
if ( pInst->mbNoYieldLock && pInst->IsMainThread() )
return 1;
sal_uInt32 nCount = comphelper::GenericSolarMutex::doRelease( bUnlockAll );
if ( 0 == m_nCount && !pInst->IsMainThread() )
m_aInMainCondition.set();
return nCount;
}
bool SalYieldMutex::IsCurrentThread() const
{
if ( !GetSalData()->mpFirstInstance->mbNoYieldLock )
return comphelper::GenericSolarMutex::IsCurrentThread();
else
return GetSalData()->mpFirstInstance->IsMainThread();
}
// some convenience functions regarding the yield mutex, aka solar mutex
bool ImplSalYieldMutexTryToAcquire()
......@@ -315,15 +374,13 @@ void DestroySalInstance( SalInstance* pInst )
}
AquaSalInstance::AquaSalInstance()
: maUserEventListMutex()
, maWaitingYieldCond()
, mbIsLiveResize( false )
: mnActivePrintJobs( 0 )
, mbIsLiveResize( false )
, mbNoYieldLock( false )
{
mpSalYieldMutex = new SalYieldMutex;
mpSalYieldMutex->acquire();
maMainThread = osl::Thread::getCurrentIdentifier();
mbWaitingYield = false;
mnActivePrintJobs = 0;
}
AquaSalInstance::~AquaSalInstance()
......@@ -332,21 +389,15 @@ AquaSalInstance::~AquaSalInstance()
delete mpSalYieldMutex;
}
void AquaSalInstance::wakeupYield()
{
// wakeup :Yield
if( mbWaitingYield )
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, YES );
}
void AquaSalInstance::PostUserEvent( AquaSalFrame* pFrame, SalEvent nType, void* pData )
{
{
osl::MutexGuard g( maUserEventListMutex );
maUserEvents.push_back( SalUserEvent( pFrame, pData, nType ) );
}
// notify main loop that an event has arrived
wakeupYield();
dispatch_async(dispatch_get_main_queue(),^{
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO );
});
}
comphelper::SolarMutex* AquaSalInstance::GetYieldMutex()
......@@ -465,7 +516,7 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
case YieldWakeupEvent:
// do nothing, fall out of Yield
break;
break;
default:
OSL_FAIL( "unhandled NSApplicationDefined event" );
......@@ -473,6 +524,14 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
};
}
static bool isWakeupEvent( NSEvent *pEvent )
{
SAL_WNODEPRECATED_DECLARATIONS_PUSH
return NSApplicationDefined == [pEvent type]
&& AquaSalInstance::YieldWakeupEvent == (int) [pEvent subtype];
SAL_WNODEPRECATED_DECLARATIONS_POP
}
bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
{
(void) nReleased;
......@@ -522,11 +581,6 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLon
// cocoa events may be only handled in the thread the NSApp was created
if( IsMainThread() && mnActivePrintJobs == 0 )
{
// we need to be woken up by a cocoa-event
// if a user event should be posted by the event handling below
bool bOldWaitingYield = mbWaitingYield;
mbWaitingYield = bWait;
// handle available events
NSEvent* pEvent = nil;
do
......@@ -543,12 +597,17 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
if( pEvent )
{
[NSApp sendEvent: pEvent];
if ( isWakeupEvent( pEvent ) )
continue;
bHadEvent = true;
}
[NSApp updateWindows];
if ( !bHandleAllCurrentEvents || !pEvent )
break;
}
while( bHandleAllCurrentEvents && pEvent );
while( true );
// if we had no event yet, wait for one if requested
if( bWait && ! bHadEvent )
......@@ -564,12 +623,14 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
inMode: NSDefaultRunLoopMode
dequeue: YES];
if( pEvent )
{
[NSApp sendEvent: pEvent];
if ( !isWakeupEvent( pEvent ) )
bHadEvent = true;
}
[NSApp updateWindows];
}
mbWaitingYield = bOldWaitingYield;
// collect update rectangles
const std::list< AquaSalFrame* > rFrames( GetSalData()->maFrames );
for( std::list< AquaSalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
......@@ -580,17 +641,17 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
(*it)->maInvalidRect.SetEmpty();
}
}
maWaitingYieldCond.set();
if ( bHadEvent )
maWaitingYieldCond.set();
}
else if( bWait )
{
// #i103162#
// wait until any thread (most likely the main thread)
// has dispatched an event, cop out at 200 ms
// wait until the main thread has dispatched an event
maWaitingYieldCond.reset();
TimeValue aVal = { 0, 200000000 };
SolarMutexReleaser aReleaser;
maWaitingYieldCond.wait( &aVal );
maWaitingYieldCond.wait();
}
// we get some apple events way too early
......@@ -629,6 +690,8 @@ bool AquaSalInstance::AnyInput( VclInputFlags nType )
return false;
}
OSX_INST_RUNINMAIN_UNION( AnyInput( nType ), boolean )
if( nType & VclInputFlags::TIMER )
{
if( AquaSalTimer::pRunningTimer )
......@@ -641,9 +704,6 @@ bool AquaSalInstance::AnyInput( VclInputFlags nType )
}
}
if (!IsMainThread())
return false;
unsigned/*NSUInteger*/ nEventMask = 0;
SAL_WNODEPRECATED_DECLARATIONS_PUSH
// 'NSFlagsChangedMask' is deprecated: first deprecated in macOS 10.12
......@@ -691,29 +751,28 @@ SalFrame* AquaSalInstance::CreateChildFrame( SystemParentData*, SalFrameStyleFla
SalFrame* AquaSalInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nSalFrameStyle )
{
SalData::ensureThreadAutoreleasePool();
SalFrame* pFrame = new AquaSalFrame( pParent, nSalFrameStyle );
return pFrame;
OSX_INST_RUNINMAIN_POINTER( CreateFrame( pParent, nSalFrameStyle ), SalFrame* )
return new AquaSalFrame( pParent, nSalFrameStyle );
}
void AquaSalInstance::DestroyFrame( SalFrame* pFrame )
{
OSX_INST_RUNINMAIN( DestroyFrame( pFrame ) )
delete pFrame;
}
SalObject* AquaSalInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool /* bShow */ )
{
AquaSalObject *pObject = nullptr;
if ( pParent )
pObject = new AquaSalObject( static_cast<AquaSalFrame*>(pParent), pWindowData );
if ( !pParent )
return nullptr;
return pObject;
OSX_INST_RUNINMAIN_POINTER( CreateObject( pParent, pWindowData, false ), SalObject* )
return new AquaSalObject( static_cast<AquaSalFrame*>(pParent), pWindowData );
}
void AquaSalInstance::DestroyObject( SalObject* pObject )
{
OSX_INST_RUNINMAIN( DestroyObject( pObject ) )
delete pObject;
}
......
......@@ -26,6 +26,7 @@
#include "osx/salframe.h"
#include "osx/salinst.h"
#include "osx/salobj.h"
#include "osx/runinmain.hxx"
#include <AppKit/NSOpenGLView.h>
......@@ -105,6 +106,8 @@ AquaSalObject::AquaSalObject( AquaSalFrame* pFrame, SystemWindowData const * pWi
AquaSalObject::~AquaSalObject()
{
assert( GetSalData()->mpFirstInstance->IsMainThread() );
if( maSysData.mpNSView )
{
NSView *pView = maSysData.mpNSView;
......@@ -194,6 +197,8 @@ void AquaSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
void AquaSalObject::setClippedPosSize()
{
OSX_SALDATA_RUNINMAIN( setClippedPosSize() )
NSRect aViewRect = { NSZeroPoint, NSMakeSize( mnWidth, mnHeight) };
if( maSysData.mpNSView )
{
......@@ -222,8 +227,12 @@ void AquaSalObject::setClippedPosSize()
void AquaSalObject::Show( bool bVisible )
{
if( mpClipView )
[mpClipView setHidden: (bVisible ? NO : YES)];
if( !mpClipView )
return;
OSX_SALDATA_RUNINMAIN( Show( bVisible ) )
[mpClipView setHidden: (bVisible ? NO : YES)];
}
const SystemEnvData* AquaSalObject::GetSystemData() const
......@@ -235,8 +244,10 @@ class AquaOpenGLContext : public OpenGLContext
{
public:
virtual bool initWindow() override;
private:
GLWindow m_aGLWin;
virtual const GLWindow& getOpenGLWindow() const override { return m_aGLWin; }
virtual GLWindow& getModifiableOpenGLWindow() override { return m_aGLWin; }
NSOpenGLView* getOpenGLView();
......@@ -250,6 +261,8 @@ private:
void AquaOpenGLContext::resetCurrent()
{
OSX_SALDATA_RUNINMAIN( resetCurrent() )
clearCurrent();
OpenGLZone aZone;
......@@ -260,6 +273,8 @@ void AquaOpenGLContext::resetCurrent()
void AquaOpenGLContext::makeCurrent()
{
OSX_SALDATA_RUNINMAIN( makeCurrent() )
if (isCurrent())
return;
......@@ -275,6 +290,8 @@ void AquaOpenGLContext::makeCurrent()
void AquaOpenGLContext::swapBuffers()
{
OSX_SALDATA_RUNINMAIN( swapBuffers() )
OpenGLZone aZone;
NSOpenGLView* pView = getOpenGLView();
......@@ -293,11 +310,14 @@ SystemWindowData AquaOpenGLContext::generateWinData(vcl::Window* /*pParent*/, bo
void AquaOpenGLContext::destroyCurrentContext()
{
OSX_SALDATA_RUNINMAIN( destroyCurrentContext() )
[NSOpenGLContext clearCurrentContext];
}
bool AquaOpenGLContext::initWindow()
{
OSX_SALDATA_RUNINMAIN_UNION( initWindow(), boolean )
if( !m_pChildWindow )
{
SystemWindowData winData = generateWinData(mpWindow, mbRequestLegacyContext);
......@@ -314,6 +334,8 @@ bool AquaOpenGLContext::initWindow()
bool AquaOpenGLContext::ImplInit()
{
OSX_SALDATA_RUNINMAIN_UNION( ImplInit(), boolean )
OpenGLZone aZone;
VCL_GL_INFO("OpenGLContext::ImplInit----start");
......@@ -332,6 +354,7 @@ NSOpenGLView* AquaOpenGLContext::getOpenGLView()
OpenGLContext* AquaSalInstance::CreateOpenGLContext()
{
OSX_SALDATA_RUNINMAIN_POINTER( CreateOpenGLContext(), OpenGLContext* )
return new AquaOpenGLContext;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment