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 { return m_type; }
getFunctions(void) const58 const glw::Functions& getFunctions (void) const { return m_functions; }
getRenderTarget(void) const59 const tcu::RenderTarget& getRenderTarget (void) const { return m_renderTarget; }
postIterate(void)60 void postIterate (void) {}
61
62 private:
63 const glu::ContextType m_type;
64 CGLContextObj m_context;
65 glw::Functions m_functions;
66 RenderTarget m_renderTarget;
67 };
68
69 class CGLContextFactory : public glu::ContextFactory
70 {
71 public:
CGLContextFactory(void)72 CGLContextFactory (void)
73 : glu::ContextFactory("cgl", "CGL Context (surfaceless, use fbo)")
74 {
75 }
76
createContext(const glu::RenderConfig & config,const tcu::CommandLine &,const glu::RenderContext *) const77 glu::RenderContext* createContext (const glu::RenderConfig& config, const tcu::CommandLine&, const glu::RenderContext*) const
78 {
79 return new CGLRenderContext(config);
80 }
81 };
82
83 class OSXGLPlatform : public glu::Platform
84 {
85 public:
OSXGLPlatform(void)86 OSXGLPlatform(void)
87 {
88 m_contextFactoryRegistry.registerFactory(new CGLContextFactory());
89 }
90
~OSXGLPlatform(void)91 ~OSXGLPlatform(void) {}
92 };
93
94 class OSXPlatform : public tcu::Platform
95 {
96 public:
OSXPlatform(void)97 OSXPlatform(void)
98 : m_gluPlatform(), m_vkPlatform()
99 {
100 }
101
~OSXPlatform(void)102 ~OSXPlatform(void)
103 {
104 }
105
getGLPlatform(void) const106 const glu::Platform& getGLPlatform (void) const { return m_gluPlatform; }
getVulkanPlatform(void) const107 const vk::Platform& getVulkanPlatform (void) const { return m_vkPlatform; }
108
109 private:
110 OSXGLPlatform m_gluPlatform;
111 osx::VulkanPlatform m_vkPlatform;
112 };
113
114 namespace
115 {
116
117 class GLFunctionLoader : public glw::FunctionLoader
118 {
119 public:
GLFunctionLoader(const char * path)120 GLFunctionLoader (const char* path)
121 : m_library(path)
122 {
123 }
124
get(const char * name) const125 glw::GenericFuncType get (const char* name) const
126 {
127 return m_library.getFunction(name);
128 }
129
130 private:
131 de::DynamicLibrary m_library;
132 };
133
134 } // anonymous
135
getCGLProfile(glu::ContextType type)136 static CGLOpenGLProfile getCGLProfile (glu::ContextType type)
137 {
138 if (type.getAPI().getProfile() != glu::PROFILE_CORE)
139 throw NotSupportedError("Requested OpenGL profile is not supported in CGL");
140
141 if (type.getAPI().getMajorVersion() == 4)
142 return kCGLOGLPVersion_GL4_Core;
143 else if (type.getAPI().getMajorVersion() == 3)
144 return kCGLOGLPVersion_GL3_Core;
145 else
146 throw NotSupportedError("Requested OpenGL version is not supported in CGL");
147 }
148
getVersion(const glw::Functions & gl)149 static glu::ApiType getVersion (const glw::Functions& gl)
150 {
151 int major = 0;
152 int minor = 0;
153 gl.getIntegerv(GL_MAJOR_VERSION, &major);
154 gl.getIntegerv(GL_MINOR_VERSION, &minor);
155 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query exact GL version");
156 return glu::ApiType::core(major, minor);
157 }
158
CGLRenderContext(const glu::RenderConfig & config)159 CGLRenderContext::CGLRenderContext (const glu::RenderConfig& config)
160 : m_type (config.type)
161 , m_context (DE_NULL)
162 , m_renderTarget (0, 0, tcu::PixelFormat(0,0,0,0), 0, 0, 0)
163 {
164 try
165 {
166 const CGLPixelFormatAttribute attribs[] =
167 {
168 kCGLPFAAccelerated,
169 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)getCGLProfile(config.type),
170 (CGLPixelFormatAttribute)0
171 };
172
173 CGLPixelFormatObj pixelFormat;
174 int numVScreens;
175
176 if (CGLChoosePixelFormat(&attribs[0], &pixelFormat, &numVScreens) != kCGLNoError)
177 throw NotSupportedError("No compatible pixel formats found");
178
179 try
180 {
181 if (CGLCreateContext(pixelFormat, DE_NULL, &m_context) != kCGLNoError)
182 throw ResourceError("Failed to create CGL context");
183
184 if (CGLSetCurrentContext(m_context) != kCGLNoError)
185 throw ResourceError("Failed to set current CGL context");
186 }
187 catch (...)
188 {
189 CGLReleasePixelFormat(pixelFormat);
190 throw;
191 }
192
193 CGLReleasePixelFormat(pixelFormat);
194
195 {
196 GLFunctionLoader loader(OPENGL_LIBRARY_PATH);
197 glu::initFunctions(&m_functions, &loader, config.type.getAPI());
198 }
199
200 {
201 const glu::ApiType actualApi = getVersion(m_functions);
202 if (!contextSupports(glu::ContextType(actualApi, glu::ContextFlags(0)), config.type.getAPI()))
203 throw tcu::NotSupportedError("OpenGL version not supported");
204 }
205 }
206 catch (...)
207 {
208 if (m_context)
209 {
210 CGLSetCurrentContext(DE_NULL);
211 CGLDestroyContext(m_context);
212 }
213 throw;
214 }
215 }
216
~CGLRenderContext(void)217 CGLRenderContext::~CGLRenderContext (void)
218 {
219 CGLSetCurrentContext(DE_NULL);
220 if (m_context)
221 CGLDestroyContext(m_context);
222 }
223
224 } // tcu
225
createPlatform(void)226 tcu::Platform* createPlatform (void)
227 {
228 return new tcu::OSXPlatform();
229 }
230