xref: /aosp_15_r20/external/deqp/framework/platform/osx/tcuOSXPlatform.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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