Я столкнулся с очень странной ошибкой при компиляции с Xcode 10 против фреймворков Mojave.
Получается, что OpenGL перестает показывать. Похоже, что он действительно где-то там (слой наложения перекрывает его?) Как видимый при быстром обновлении видимой области окна (!) Или при минимизации (снимок, используемый эффектом джинна, показывает это!)
Самое странное, что я использую почти идентичный класс для другого проекта, и он прекрасно работает при сборке для Mojave!
Я вижу решения с отправкой обновления в OpenGLContext для тех, кто использует отдельный контекст, но это простой подкласс для NSOpenGLView. В этом случае разветвление SpriteBuilder для Cocos2D.
Я попытался обновить базовый контекст, настроить представление для поддержки высокого разрешения и попытаться предотвратить создание вспомогательного слоя. Пока ничего не получалось.
код:
@implementation CCGLView {
NSMutableArray *_fences;
}
- (id) initWithFrame:(NSRect)frameRect
{
self = [self initWithFrame:frameRect shareContext:nil];
return self;
}
- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context
{
NSOpenGLPixelFormatAttribute attribs[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, 24,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
if (!pixelFormat)
CCLOG(@"No OpenGL pixel format");
if ((self = [super initWithFrame:frameRect pixelFormat:pixelFormat])) {
if (context) [self setOpenGLContext:context];
}
return self;
}
- (void) prepareOpenGL
{
[super prepareOpenGL];
// Make this openGL context current to the thread
// (i.e. all openGL on this thread calls will go to this context)
[[self openGLContext] makeCurrentContext];
// Synchronize buffer swaps with vertical refresh rate
GLint swapInt = 1;
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
}
- (NSUInteger) depthFormat
{
return 24;
}
- (void) reshape
{
[self lockOpenGLContext];
NSRect rect = [self convertRectToBacking:self.bounds];
CCDirector *director = [CCDirector sharedDirector];
[director reshapeProjection: NSSizeToCGSize(rect.size) ];
if (director.runningScene) {
[director drawScene];
}
[self unlockOpenGLContext];
}
- (void)lockOpenGLContext
{
NSOpenGLContext *glContext = [self openGLContext];
NSAssert( glContext, @"FATAL: could not get openGL context");
[glContext makeCurrentContext];
CGLLockContext([glContext CGLContextObj]);
}
-(void) unlockOpenGLContext
{
NSOpenGLContext *glContext = [self openGLContext];
NSAssert( glContext, @"FATAL: could not get openGL context");
CGLUnlockContext([glContext CGLContextObj]);
}
// Find or make a fence that is ready to use.
-(CCGLViewFence *)getReadyFence
{
// First checkf oldest (first in the array) fence is ready again.
CCGLViewFence *fence = _fences.firstObject;;
if(fence.isReady){
// Remove the fence so it can be inserted at the end of the queue again.
[_fences removeObjectAtIndex:0];
return fence;
} else {
// No existing fences ready. Make a new one.
return [[CCGLViewFence alloc] init];
}
}
-(void)addFrameCompletionHandler:(dispatch_block_t)handler
{
if(_fences == nil){
_fences = [NSMutableArray arrayWithObject:[[CCGLViewFence alloc] init]];
}
CCGLViewFence *fence = _fences.lastObject;
if(!fence.isReady){
fence = [self getReadyFence];
[_fences addObject:fence];
}
[fence.handlers addObject:handler];
}
-(void)beginFrame
{
[self lockOpenGLContext];
}
-(void)presentFrame
{
{
CCGLViewFence *fence = _fences.lastObject;
if(fence.isReady){
// If the fence is ready to be added, insert a sync point for it.
[fence insertFence];
}
}
[self.openGLContext flushBuffer];
// Check the fences for completion.
for(CCGLViewFence *fence in _fences){
if(fence.isComplete){
for(dispatch_block_t handler in fence.handlers) handler();
[fence.handlers removeAllObjects];
} else {
break;
}
}
[self unlockOpenGLContext];
}
-(GLuint)fbo
{
return 0;
}
@end