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 "tcuRenderTarget.hpp"
26
27 #include "tcuOSXVulkanPlatform.hpp"
28
29 #include "gluDefs.hpp"
30 #include "gluPlatform.hpp"
31 #include "gluRenderContext.hpp"
32 #include "gluRenderConfig.hpp"
33 #include "glwFunctions.hpp"
34 #include "glwInitFunctions.hpp"
35 #include "deDynamicLibrary.hpp"
36 #include "glwEnums.hpp"
37
38 #include <string>
39
40 #include <OpenGL/OpenGL.h>
41 #include <OpenGL/CGLCurrent.h>
42 #include <OpenGL/CGLContext.h>
43 #include <OpenGL/CGLTypes.h>
44 #include <OpenGL/CGLRenderers.h>
45
46 #define OPENGL_LIBRARY_PATH "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
47
48 namespace tcu
49 {
50
51 class CGLRenderContext : public glu::RenderContext
52 {
53 public:
54 CGLRenderContext(const glu::RenderConfig &config);
55 ~CGLRenderContext(void);
56
getType(void) const57 glu::ContextType getType(void) const
58 {
59 return m_type;
60 }
getFunctions(void) const61 const glw::Functions &getFunctions(void) const
62 {
63 return m_functions;
64 }
getRenderTarget(void) const65 const tcu::RenderTarget &getRenderTarget(void) const
66 {
67 return m_renderTarget;
68 }
postIterate(void)69 void postIterate(void)
70 {
71 }
72
73 private:
74 const glu::ContextType m_type;
75 CGLContextObj m_context;
76 glw::Functions m_functions;
77 RenderTarget m_renderTarget;
78 };
79
80 class CGLContextFactory : public glu::ContextFactory
81 {
82 public:
CGLContextFactory(void)83 CGLContextFactory(void) : glu::ContextFactory("cgl", "CGL Context (surfaceless, use fbo)")
84 {
85 }
86
createContext(const glu::RenderConfig & config,const tcu::CommandLine &,const glu::RenderContext *) const87 glu::RenderContext *createContext(const glu::RenderConfig &config, const tcu::CommandLine &,
88 const glu::RenderContext *) const
89 {
90 return new CGLRenderContext(config);
91 }
92 };
93
94 class OSXGLPlatform : public glu::Platform
95 {
96 public:
OSXGLPlatform(void)97 OSXGLPlatform(void)
98 {
99 m_contextFactoryRegistry.registerFactory(new CGLContextFactory());
100 }
101
~OSXGLPlatform(void)102 ~OSXGLPlatform(void)
103 {
104 }
105 };
106
107 class OSXPlatform : public tcu::Platform
108 {
109 public:
OSXPlatform(void)110 OSXPlatform(void) : m_gluPlatform(), m_vkPlatform()
111 {
112 }
113
~OSXPlatform(void)114 ~OSXPlatform(void)
115 {
116 }
117
getGLPlatform(void) const118 const glu::Platform &getGLPlatform(void) const
119 {
120 return m_gluPlatform;
121 }
getVulkanPlatform(void) const122 const vk::Platform &getVulkanPlatform(void) const
123 {
124 return m_vkPlatform;
125 }
126
127 private:
128 OSXGLPlatform m_gluPlatform;
129 osx::VulkanPlatform m_vkPlatform;
130 };
131
132 namespace
133 {
134
135 class GLFunctionLoader : public glw::FunctionLoader
136 {
137 public:
GLFunctionLoader(const char * path)138 GLFunctionLoader(const char *path) : m_library(path)
139 {
140 }
141
get(const char * name) const142 glw::GenericFuncType get(const char *name) const
143 {
144 return m_library.getFunction(name);
145 }
146
147 private:
148 de::DynamicLibrary m_library;
149 };
150
151 } // namespace
152
getCGLProfile(glu::ContextType type)153 static CGLOpenGLProfile getCGLProfile(glu::ContextType type)
154 {
155 if (type.getAPI().getProfile() != glu::PROFILE_CORE)
156 throw NotSupportedError("Requested OpenGL profile is not supported in CGL");
157
158 if (type.getAPI().getMajorVersion() == 4)
159 return kCGLOGLPVersion_GL4_Core;
160 else if (type.getAPI().getMajorVersion() == 3)
161 return kCGLOGLPVersion_GL3_Core;
162 else
163 throw NotSupportedError("Requested OpenGL version is not supported in CGL");
164 }
165
getVersion(const glw::Functions & gl)166 static glu::ApiType getVersion(const glw::Functions &gl)
167 {
168 int major = 0;
169 int minor = 0;
170 gl.getIntegerv(GL_MAJOR_VERSION, &major);
171 gl.getIntegerv(GL_MINOR_VERSION, &minor);
172 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query exact GL version");
173 return glu::ApiType::core(major, minor);
174 }
175
CGLRenderContext(const glu::RenderConfig & config)176 CGLRenderContext::CGLRenderContext(const glu::RenderConfig &config)
177 : m_type(config.type)
178 , m_context(DE_NULL)
179 , m_renderTarget(0, 0, tcu::PixelFormat(0, 0, 0, 0), 0, 0, 0)
180 {
181 try
182 {
183 const CGLPixelFormatAttribute attribs[] = {kCGLPFAAccelerated, kCGLPFAOpenGLProfile,
184 (CGLPixelFormatAttribute)getCGLProfile(config.type),
185 (CGLPixelFormatAttribute)0};
186
187 CGLPixelFormatObj pixelFormat;
188 int numVScreens;
189
190 if (CGLChoosePixelFormat(&attribs[0], &pixelFormat, &numVScreens) != kCGLNoError)
191 throw NotSupportedError("No compatible pixel formats found");
192
193 try
194 {
195 if (CGLCreateContext(pixelFormat, DE_NULL, &m_context) != kCGLNoError)
196 throw ResourceError("Failed to create CGL context");
197
198 if (CGLSetCurrentContext(m_context) != kCGLNoError)
199 throw ResourceError("Failed to set current CGL context");
200 }
201 catch (...)
202 {
203 CGLReleasePixelFormat(pixelFormat);
204 throw;
205 }
206
207 CGLReleasePixelFormat(pixelFormat);
208
209 {
210 GLFunctionLoader loader(OPENGL_LIBRARY_PATH);
211 glu::initFunctions(&m_functions, &loader, config.type.getAPI());
212 }
213
214 {
215 const glu::ApiType actualApi = getVersion(m_functions);
216 if (!contextSupports(glu::ContextType(actualApi, glu::ContextFlags(0)), config.type.getAPI()))
217 throw tcu::NotSupportedError("OpenGL version not supported");
218 }
219 }
220 catch (...)
221 {
222 if (m_context)
223 {
224 CGLSetCurrentContext(DE_NULL);
225 CGLDestroyContext(m_context);
226 }
227 throw;
228 }
229 }
230
~CGLRenderContext(void)231 CGLRenderContext::~CGLRenderContext(void)
232 {
233 CGLSetCurrentContext(DE_NULL);
234 if (m_context)
235 CGLDestroyContext(m_context);
236 }
237
238 } // namespace tcu
239
createPlatform(void)240 tcu::Platform *createPlatform(void)
241 {
242 return new tcu::OSXPlatform();
243 }
244