1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program Tester Core 3 * ---------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief OS X platform. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "tcuOSXPlatform.hpp" 25 #include "gluRenderContext.hpp" 26 #include "gluRenderConfig.hpp" 27 #include "tcuRenderTarget.hpp" 28 #include "glwFunctions.hpp" 29 #include "glwInitFunctions.hpp" 30 #include "deDynamicLibrary.hpp" 31 #include "glwEnums.hpp" 32 #include "gluDefs.hpp" 33 34 #include <string> 35 36 #include <OpenGL/OpenGL.h> 37 #include <OpenGL/CGLCurrent.h> 38 #include <OpenGL/CGLContext.h> 39 #include <OpenGL/CGLTypes.h> 40 #include <OpenGL/CGLRenderers.h> 41 42 #define OPENGL_LIBRARY_PATH "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" 43 44 namespace tcu 45 { 46 47 namespace 48 { 49 50 class GLFunctionLoader : public glw::FunctionLoader 51 { 52 public: 53 GLFunctionLoader (const char* path) 54 : m_library(path) 55 { 56 } 57 58 glw::GenericFuncType get (const char* name) const 59 { 60 return m_library.getFunction(name); 61 } 62 63 private: 64 de::DynamicLibrary m_library; 65 }; 66 67 } // anonymous 68 69 class CGLRenderContext : public glu::RenderContext 70 { 71 public: 72 CGLRenderContext (const glu::RenderConfig& config); 73 ~CGLRenderContext (void); 74 75 glu::ContextType getType (void) const { return m_type; } 76 const glw::Functions& getFunctions (void) const { return m_functions; } 77 const tcu::RenderTarget& getRenderTarget (void) const { return m_renderTarget; } 78 void postIterate (void) {} 79 80 private: 81 const glu::ContextType m_type; 82 CGLContextObj m_context; 83 glw::Functions m_functions; 84 RenderTarget m_renderTarget; 85 }; 86 87 static CGLOpenGLProfile getCGLProfile (glu::ContextType type) 88 { 89 if (type.getAPI().getProfile() != glu::PROFILE_CORE) 90 throw NotSupportedError("Requested OpenGL profile is not supported in CGL"); 91 92 if (type.getAPI().getMajorVersion() == 4) 93 return kCGLOGLPVersion_GL4_Core; 94 else if (type.getAPI().getMajorVersion() == 3) 95 return kCGLOGLPVersion_GL3_Core; 96 else 97 throw NotSupportedError("Requested OpenGL version is not supported in CGL"); 98 } 99 100 static glu::ApiType getVersion (const glw::Functions& gl) 101 { 102 int major = 0; 103 int minor = 0; 104 gl.getIntegerv(GL_MAJOR_VERSION, &major); 105 gl.getIntegerv(GL_MINOR_VERSION, &minor); 106 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query exact GL version"); 107 return glu::ApiType::core(major, minor); 108 } 109 110 CGLRenderContext::CGLRenderContext (const glu::RenderConfig& config) 111 : m_type (config.type) 112 , m_context (DE_NULL) 113 , m_renderTarget (0, 0, tcu::PixelFormat(0,0,0,0), 0, 0, 0) 114 { 115 try 116 { 117 const CGLPixelFormatAttribute attribs[] = 118 { 119 kCGLPFAAccelerated, 120 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)getCGLProfile(config.type), 121 (CGLPixelFormatAttribute)0 122 }; 123 124 CGLPixelFormatObj pixelFormat; 125 int numVScreens; 126 127 if (CGLChoosePixelFormat(&attribs[0], &pixelFormat, &numVScreens) != kCGLNoError) 128 throw NotSupportedError("No compatible pixel formats found"); 129 130 try 131 { 132 if (CGLCreateContext(pixelFormat, DE_NULL, &m_context) != kCGLNoError) 133 throw ResourceError("Failed to create CGL context"); 134 135 if (CGLSetCurrentContext(m_context) != kCGLNoError) 136 throw ResourceError("Failed to set current CGL context"); 137 } 138 catch (...) 139 { 140 CGLReleasePixelFormat(pixelFormat); 141 throw; 142 } 143 144 CGLReleasePixelFormat(pixelFormat); 145 146 { 147 GLFunctionLoader loader(OPENGL_LIBRARY_PATH); 148 glu::initFunctions(&m_functions, &loader, config.type.getAPI()); 149 } 150 151 { 152 const glu::ApiType actualApi = getVersion(m_functions); 153 if (!contextSupports(glu::ContextType(actualApi, glu::ContextFlags(0)), config.type.getAPI())) 154 throw tcu::NotSupportedError("OpenGL version not supported"); 155 } 156 } 157 catch (...) 158 { 159 if (m_context) 160 { 161 CGLSetCurrentContext(DE_NULL); 162 CGLDestroyContext(m_context); 163 } 164 throw; 165 } 166 } 167 168 CGLRenderContext::~CGLRenderContext (void) 169 { 170 CGLSetCurrentContext(DE_NULL); 171 if (m_context) 172 CGLDestroyContext(m_context); 173 } 174 175 class CGLContextFactory : public glu::ContextFactory 176 { 177 public: 178 CGLContextFactory (void) 179 : glu::ContextFactory("cgl", "CGL Context (surfaceless, use fbo)") 180 { 181 } 182 183 glu::RenderContext* createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const 184 { 185 return new CGLRenderContext(config); 186 } 187 }; 188 189 OSXPlatform::OSXPlatform (void) 190 { 191 m_contextFactoryRegistry.registerFactory(new CGLContextFactory()); 192 } 193 194 OSXPlatform::~OSXPlatform (void) 195 { 196 } 197 198 } // tcu 199 200 tcu::Platform* createPlatform (void) 201 { 202 return new tcu::OSXPlatform(); 203 } 204