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