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:
GLFunctionLoader(const char * path)53 GLFunctionLoader (const char* path)
54 : m_library(path)
55 {
56 }
57
get(const char * name) const58 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
getType(void) const75 glu::ContextType getType (void) const { return m_type; }
getFunctions(void) const76 const glw::Functions& getFunctions (void) const { return m_functions; }
getRenderTarget(void) const77 const tcu::RenderTarget& getRenderTarget (void) const { return m_renderTarget; }
postIterate(void)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
getCGLProfile(glu::ContextType type)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
getVersion(const glw::Functions & gl)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
CGLRenderContext(const glu::RenderConfig & config)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
~CGLRenderContext(void)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:
CGLContextFactory(void)178 CGLContextFactory (void)
179 : glu::ContextFactory("cgl", "CGL Context (surfaceless, use fbo)")
180 {
181 }
182
createContext(const glu::RenderConfig & config,const tcu::CommandLine &) const183 glu::RenderContext* createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
184 {
185 return new CGLRenderContext(config);
186 }
187 };
188
OSXPlatform(void)189 OSXPlatform::OSXPlatform (void)
190 {
191 m_contextFactoryRegistry.registerFactory(new CGLContextFactory());
192 }
193
~OSXPlatform(void)194 OSXPlatform::~OSXPlatform (void)
195 {
196 }
197
198 } // tcu
199
createPlatform(void)200 tcu::Platform* createPlatform (void)
201 {
202 return new tcu::OSXPlatform();
203 }
204