/*------------------------------------------------------------------------- * drawElements Quality Program Tester Core * ---------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed 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 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief OS X platform. *//*--------------------------------------------------------------------*/ #include "tcuOSXPlatform.hpp" #include "tcuRenderTarget.hpp" #include "tcuOSXVulkanPlatform.hpp" #include "gluDefs.hpp" #include "gluPlatform.hpp" #include "gluRenderContext.hpp" #include "gluRenderConfig.hpp" #include "glwFunctions.hpp" #include "glwInitFunctions.hpp" #include "deDynamicLibrary.hpp" #include "glwEnums.hpp" #include <string> #include <OpenGL/OpenGL.h> #include <OpenGL/CGLCurrent.h> #include <OpenGL/CGLContext.h> #include <OpenGL/CGLTypes.h> #include <OpenGL/CGLRenderers.h> #define OPENGL_LIBRARY_PATH "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" namespace tcu { class CGLRenderContext : public glu::RenderContext { public: CGLRenderContext (const glu::RenderConfig& config); ~CGLRenderContext (void); glu::ContextType getType (void) const { return m_type; } const glw::Functions& getFunctions (void) const { return m_functions; } const tcu::RenderTarget& getRenderTarget (void) const { return m_renderTarget; } void postIterate (void) {} private: const glu::ContextType m_type; CGLContextObj m_context; glw::Functions m_functions; RenderTarget m_renderTarget; }; class CGLContextFactory : public glu::ContextFactory { public: CGLContextFactory (void) : glu::ContextFactory("cgl", "CGL Context (surfaceless, use fbo)") { } glu::RenderContext* createContext (const glu::RenderConfig& config, const tcu::CommandLine&, const glu::RenderContext*) const { return new CGLRenderContext(config); } }; class OSXGLPlatform : public glu::Platform { public: OSXGLPlatform(void) { m_contextFactoryRegistry.registerFactory(new CGLContextFactory()); } ~OSXGLPlatform(void) {} }; class OSXPlatform : public tcu::Platform { public: OSXPlatform(void) : m_gluPlatform(), m_vkPlatform() { } ~OSXPlatform(void) { } const glu::Platform& getGLPlatform (void) const { return m_gluPlatform; } const vk::Platform& getVulkanPlatform (void) const { return m_vkPlatform; } private: OSXGLPlatform m_gluPlatform; osx::VulkanPlatform m_vkPlatform; }; namespace { class GLFunctionLoader : public glw::FunctionLoader { public: GLFunctionLoader (const char* path) : m_library(path) { } glw::GenericFuncType get (const char* name) const { return m_library.getFunction(name); } private: de::DynamicLibrary m_library; }; } // anonymous static CGLOpenGLProfile getCGLProfile (glu::ContextType type) { if (type.getAPI().getProfile() != glu::PROFILE_CORE) throw NotSupportedError("Requested OpenGL profile is not supported in CGL"); if (type.getAPI().getMajorVersion() == 4) return kCGLOGLPVersion_GL4_Core; else if (type.getAPI().getMajorVersion() == 3) return kCGLOGLPVersion_GL3_Core; else throw NotSupportedError("Requested OpenGL version is not supported in CGL"); } static glu::ApiType getVersion (const glw::Functions& gl) { int major = 0; int minor = 0; gl.getIntegerv(GL_MAJOR_VERSION, &major); gl.getIntegerv(GL_MINOR_VERSION, &minor); GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query exact GL version"); return glu::ApiType::core(major, minor); } CGLRenderContext::CGLRenderContext (const glu::RenderConfig& config) : m_type (config.type) , m_context (DE_NULL) , m_renderTarget (0, 0, tcu::PixelFormat(0,0,0,0), 0, 0, 0) { try { const CGLPixelFormatAttribute attribs[] = { kCGLPFAAccelerated, kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)getCGLProfile(config.type), (CGLPixelFormatAttribute)0 }; CGLPixelFormatObj pixelFormat; int numVScreens; if (CGLChoosePixelFormat(&attribs[0], &pixelFormat, &numVScreens) != kCGLNoError) throw NotSupportedError("No compatible pixel formats found"); try { if (CGLCreateContext(pixelFormat, DE_NULL, &m_context) != kCGLNoError) throw ResourceError("Failed to create CGL context"); if (CGLSetCurrentContext(m_context) != kCGLNoError) throw ResourceError("Failed to set current CGL context"); } catch (...) { CGLReleasePixelFormat(pixelFormat); throw; } CGLReleasePixelFormat(pixelFormat); { GLFunctionLoader loader(OPENGL_LIBRARY_PATH); glu::initFunctions(&m_functions, &loader, config.type.getAPI()); } { const glu::ApiType actualApi = getVersion(m_functions); if (!contextSupports(glu::ContextType(actualApi, glu::ContextFlags(0)), config.type.getAPI())) throw tcu::NotSupportedError("OpenGL version not supported"); } } catch (...) { if (m_context) { CGLSetCurrentContext(DE_NULL); CGLDestroyContext(m_context); } throw; } } CGLRenderContext::~CGLRenderContext (void) { CGLSetCurrentContext(DE_NULL); if (m_context) CGLDestroyContext(m_context); } } // tcu tcu::Platform* createPlatform (void) { return new tcu::OSXPlatform(); }