257 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // Copyright (C) 2014 Patryk Nadrowski
 | |
| // This file is part of the "Irrlicht Engine".
 | |
| // For conditions of distribution and use, see copyright notice in Irrlicht.h
 | |
| 
 | |
| #include "CNSOGLManager.h"
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_NSOGL_MANAGER_
 | |
| 
 | |
| #include <mach-o/dyld.h>
 | |
| #include "os.h"
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace video
 | |
| {
 | |
| 
 | |
| CNSOGLManager::CNSOGLManager()
 | |
| 	: PrimaryContext(SExposedVideoData(0)), PixelFormat(nil)
 | |
| {
 | |
| #ifdef _DEBUG
 | |
| 	setDebugName("CNSOGLManager");
 | |
| #endif
 | |
| }
 | |
| 
 | |
| CNSOGLManager::~CNSOGLManager()
 | |
| {
 | |
| }
 | |
| 
 | |
| bool CNSOGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata)
 | |
| {
 | |
| 	Params = params;
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void CNSOGLManager::terminate()
 | |
| {
 | |
| }
 | |
| 
 | |
| bool CNSOGLManager::generateSurface()
 | |
| {
 | |
| 	if (Params.DriverType == video::EDT_OPENGL)
 | |
| 	{
 | |
|         int alphaSize = Params.WithAlphaChannel ? 4 : 0;
 | |
|         int depthSize = Params.ZBufferBits;
 | |
| 
 | |
|         if (Params.WithAlphaChannel && Params.Bits == 32)
 | |
|             alphaSize = 8;
 | |
| 
 | |
|         NSOpenGLPixelFormatAttribute Attribs[] =
 | |
|         {
 | |
|             NSOpenGLPFANoRecovery,
 | |
|             NSOpenGLPFAAccelerated,
 | |
|             NSOpenGLPFADoubleBuffer,
 | |
|             NSOpenGLPFADepthSize, static_cast<NSOpenGLPixelFormatAttribute>(depthSize),
 | |
|             NSOpenGLPFAColorSize, Params.Bits,
 | |
|             NSOpenGLPFAAlphaSize, static_cast<NSOpenGLPixelFormatAttribute>(alphaSize),
 | |
|             NSOpenGLPFASampleBuffers, 1,
 | |
|             NSOpenGLPFASamples, Params.AntiAlias,
 | |
|             NSOpenGLPFAStencilSize, static_cast<NSOpenGLPixelFormatAttribute>(Params.Stencilbuffer ? 1 : 0),
 | |
|             //NSOpenGLPFAFullScreen,
 | |
|             0
 | |
|         };
 | |
| 
 | |
|         u32 Steps = 6;
 | |
| 
 | |
|         // Choose the best pixel format.
 | |
|         do
 | |
|         {
 | |
|             switch (Steps)
 | |
|             {
 | |
|             case 6: // decrease step.
 | |
|                 --Steps;
 | |
|                 break;
 | |
|             case 5: // samples
 | |
|                 if (Attribs[12] > 2)
 | |
|                     --Attribs[12];
 | |
|                 else
 | |
|                 {
 | |
|                     Attribs[10] = 0;
 | |
|                     Attribs[12] = 0;
 | |
|                     --Steps;
 | |
|                 }
 | |
|                 break;
 | |
|             case 4: // alpha
 | |
|                 if (Attribs[8])
 | |
|                 {
 | |
|                     Attribs[8] = 0;
 | |
| 
 | |
|                     if (Params.AntiAlias)
 | |
|                     {
 | |
|                         Attribs[10] = 1;
 | |
|                         Attribs[12] = Params.AntiAlias;
 | |
|                         Steps = 5;
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                     --Steps;
 | |
|                 break;
 | |
|             case 3: // stencil
 | |
|                 if (Attribs[14])
 | |
|                 {
 | |
|                     Attribs[14] = 0;
 | |
| 
 | |
|                     if (Params.AntiAlias)
 | |
|                     {
 | |
|                         Attribs[10] = 1;
 | |
|                         Attribs[12] = Params.AntiAlias;
 | |
|                         Steps = 5;
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                     --Steps;
 | |
|                 break;
 | |
|             case 2: // depth size
 | |
|                 if (Attribs[4] > 16)
 | |
|                 {
 | |
|                     Attribs[4] = Attribs[4] - 8;
 | |
|                 }
 | |
|                 else
 | |
|                     --Steps;
 | |
|                 break;
 | |
|             case 1: // buffer size
 | |
|                 if (Attribs[6] > 16)
 | |
|                 {
 | |
|                     Attribs[6] = Attribs[6] - 8;
 | |
|                 }
 | |
|                 else
 | |
|                     --Steps;
 | |
|                 break;
 | |
|             default:
 | |
|                 os::Printer::log("Could not get pixel format.");
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             PixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:Attribs];
 | |
|         }
 | |
|         while (PixelFormat == nil);
 | |
| 
 | |
|         if (Params.AntiAlias && !Attribs[10])
 | |
|             os::Printer::log("No multisampling.");
 | |
| 
 | |
|         if (Params.WithAlphaChannel && !Attribs[8])
 | |
|             os::Printer::log("No alpha.");
 | |
| 
 | |
|         if (Params.Stencilbuffer && !Attribs[14])
 | |
|             os::Printer::log("No stencil buffer.");
 | |
| 
 | |
|         if (Params.ZBufferBits > Attribs[4])
 | |
|             os::Printer::log("No full depth buffer.");
 | |
| 
 | |
|         if (Params.Bits > Attribs[6])
 | |
|             os::Printer::log("No full color buffer.");
 | |
| 	}
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void CNSOGLManager::destroySurface()
 | |
| {
 | |
|     [PixelFormat release];
 | |
|     PixelFormat = nil;
 | |
| }
 | |
| 
 | |
| bool CNSOGLManager::generateContext()
 | |
| {
 | |
|     NSOpenGLContext* Context = [[NSOpenGLContext alloc] initWithFormat:PixelFormat shareContext:nil];
 | |
| 
 | |
|     GLint Vsync = Params.Vsync ? 1 : 0;
 | |
|     [Context setValues:&Vsync forParameter:NSOpenGLCPSwapInterval];
 | |
| 
 | |
| 	if (Context == nil)
 | |
| 	{
 | |
| 		os::Printer::log("Could not create OpenGL context.", ELL_ERROR);
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	// set exposed data
 | |
| 	CurrentContext.OpenGLOSX.Context = Context;
 | |
| 
 | |
| 	if (!PrimaryContext.OpenGLOSX.Context)
 | |
| 		PrimaryContext.OpenGLOSX.Context = CurrentContext.OpenGLOSX.Context;
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| const SExposedVideoData& CNSOGLManager::getContext() const
 | |
| {
 | |
| 	return CurrentContext;
 | |
| }
 | |
| 
 | |
| bool CNSOGLManager::activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero)
 | |
| {
 | |
| 	//TODO: handle restorePrimaryOnZero
 | |
|     if (videoData.OpenGLOSX.Context)
 | |
|     {
 | |
|         if ((NSOpenGLContext*)videoData.OpenGLOSX.Context != [NSOpenGLContext currentContext])
 | |
|         {
 | |
|             [(NSOpenGLContext*)videoData.OpenGLOSX.Context makeCurrentContext];
 | |
| 
 | |
|             CurrentContext = videoData;
 | |
|         }
 | |
|     }
 | |
|     // set back to main context
 | |
|     else
 | |
|     {
 | |
|         if ((NSOpenGLContext*)PrimaryContext.OpenGLOSX.Context != [NSOpenGLContext currentContext])
 | |
|         {
 | |
|             [(NSOpenGLContext*)PrimaryContext.OpenGLOSX.Context makeCurrentContext];
 | |
| 
 | |
|             CurrentContext = PrimaryContext;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| void CNSOGLManager::destroyContext()
 | |
| {
 | |
| 	if (CurrentContext.OpenGLOSX.Context)
 | |
| 	{
 | |
|         if (PrimaryContext.OpenGLOSX.Context == CurrentContext.OpenGLOSX.Context)
 | |
|             PrimaryContext.OpenGLOSX.Context = nil;
 | |
| 
 | |
| 		[(NSOpenGLContext*)CurrentContext.OpenGLOSX.Context makeCurrentContext];
 | |
|         [(NSOpenGLContext *)CurrentContext.OpenGLOSX.Context clearDrawable];
 | |
|         [(NSOpenGLContext *)CurrentContext.OpenGLOSX.Context release];
 | |
| 		[NSOpenGLContext clearCurrentContext];
 | |
| 
 | |
| 		CurrentContext.OpenGLOSX.Context = nil;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // It appears that there is no separate GL proc address getter on OSX.
 | |
| // https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_entrypts/opengl_entrypts.html
 | |
| void* CNSOGLManager::getProcAddress(const std::string &procName)
 | |
| {
 | |
| 	NSSymbol symbol = NULL;
 | |
| 	// Allocate a buffer for the name, an underscore prefix, and a cstring terminator.
 | |
| 	std::string mangledName = "_" + procName;
 | |
| 	if (NSIsSymbolNameDefined(mangledName.c_str()))
 | |
| 		symbol = NSLookupAndBindSymbol(mangledName.c_str());
 | |
| 	return symbol ? NSAddressOfSymbol(symbol) : NULL;
 | |
| }
 | |
| 
 | |
| bool CNSOGLManager::swapBuffers()
 | |
| {
 | |
|     [(NSOpenGLContext*)CurrentContext.OpenGLOSX.Context flushBuffer];
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| }
 | |
| }
 | |
| 
 | |
| #endif
 |