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