Don't require supported binary formats in negative tests. am: 7cd59a4409 am: d7b53b80...
[platform/upstream/VK-GL-CTS.git] / framework / platform / ios / tcuIOSPlatform.mm
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 iOS Platform implementation.
22  *//*--------------------------------------------------------------------*/
23
24 #include "tcuIOSPlatform.hh"
25 #include "gluRenderConfig.hpp"
26 #include "gluFboRenderContext.hpp"
27
28 #include "glwInitES20Direct.hpp"
29 #include "glwInitES30Direct.hpp"
30
31
32 namespace tcu
33 {
34 namespace ios
35 {
36
37 // ScreenManager
38
39 ScreenManager::ScreenManager (tcuEAGLView* view)
40         : m_view(view)
41 {
42 }
43
44 ScreenManager::~ScreenManager (void)
45 {
46 }
47
48 CAEAGLLayer* ScreenManager::acquireScreen (void)
49 {
50         if (!m_viewLock.tryLock())
51                 throw ResourceError("View is already is in use");
52
53         return [m_view getEAGLLayer];
54 }
55
56 void ScreenManager::releaseScreen (CAEAGLLayer* layer)
57 {
58         DE_UNREF(layer);
59         m_viewLock.unlock();
60 }
61
62 // ContextFactory
63
64 ContextFactory::ContextFactory (ScreenManager* screenManager)
65         : glu::ContextFactory   ("eagl", "iOS EAGL Context")
66         , m_screenManager               (screenManager)
67 {
68 }
69
70 ContextFactory::~ContextFactory (void)
71 {
72 }
73
74 glu::RenderContext* ContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
75 {
76         RawContext* rawContext = new RawContext(config.type);
77
78         try
79         {
80                 if (config.surfaceType == glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC)
81                         return new glu::FboRenderContext(rawContext, config);
82                 else if (config.surfaceType == glu::RenderConfig::SURFACETYPE_WINDOW)
83                         return new ScreenContext(m_screenManager, config);
84                 else
85                         throw NotSupportedError("Unsupported surface type");
86         }
87         catch (...)
88         {
89                 delete rawContext;
90                 throw;
91         }
92 }
93
94 // Platform
95
96 Platform::Platform (ScreenManager* screenManager)
97 {
98         m_contextFactoryRegistry.registerFactory(new ContextFactory(screenManager));
99 }
100
101 Platform::~Platform (void)
102 {
103 }
104
105 // RawContext
106
107 static EAGLRenderingAPI getEAGLApi (glu::ContextType type)
108 {
109         if (type.getAPI() == glu::ApiType::es(3,0))
110                 return kEAGLRenderingAPIOpenGLES3;
111         else if (type.getAPI() == glu::ApiType::es(2,0))
112                 return kEAGLRenderingAPIOpenGLES2;
113         else
114                 throw NotSupportedError("Requested GL API is not supported on iOS");
115 }
116
117 RawContext::RawContext (glu::ContextType type)
118         : m_type                (type)
119         , m_context             (DE_NULL)
120         , m_emptyTarget (0, 0, tcu::PixelFormat(0,0,0,0), 0, 0, 0)
121 {
122         const EAGLRenderingAPI eaglApi = getEAGLApi(type);
123
124         m_context = [[EAGLContext alloc] initWithAPI:eaglApi];
125         if (!m_context)
126                 throw ResourceError("Failed to create EAGL context");
127
128         try
129         {
130                 if (![EAGLContext setCurrentContext:m_context])
131                         throw ResourceError("Failed to set current EAGL context");
132
133                 if (type.getAPI() == glu::ApiType::es(3,0))
134                         glw::initES30Direct(&m_functions);
135                 else if (type.getAPI() == glu::ApiType::es(2,0))
136                         glw::initES20Direct(&m_functions);
137                 else
138                         throw InternalError("Unsupproted API for loading functions");
139         }
140         catch (...)
141         {
142                 if ([EAGLContext currentContext] == m_context)
143                         [EAGLContext setCurrentContext:nil];
144
145                 [m_context release];
146                 throw;
147         }
148 }
149
150 RawContext::~RawContext (void)
151 {
152         if ([EAGLContext currentContext] == m_context)
153                 [EAGLContext setCurrentContext:nil];
154
155         [m_context release];
156 }
157
158 void RawContext::postIterate (void)
159 {
160 }
161
162 NSString* chooseLayerColorFormat (const glu::RenderConfig& config)
163 {
164         const bool      cr              = config.redBits        != glu::RenderConfig::DONT_CARE;
165         const bool      cg              = config.greenBits      != glu::RenderConfig::DONT_CARE;
166         const bool      cb              = config.blueBits       != glu::RenderConfig::DONT_CARE;
167         const bool      ca              = config.alphaBits      != glu::RenderConfig::DONT_CARE;
168
169         if ((!cr || config.redBits              == 8) &&
170                 (!cg || config.greenBits        == 8) &&
171                 (!cb || config.blueBits         == 8) &&
172                 (!ca || config.alphaBits        == 8))
173                 return kEAGLColorFormatRGBA8;
174
175         if ((!cr || config.redBits              == 5) &&
176                 (!cg || config.greenBits        == 6) &&
177                 (!cb || config.blueBits         == 5) &&
178                 (!ca || config.alphaBits        == 0))
179                 return kEAGLColorFormatRGB565;
180
181         return nil;
182 }
183
184 // ScreenContext
185
186 ScreenContext::ScreenContext (ScreenManager* screenManager, const glu::RenderConfig& config)
187         : RawContext                    (config.type)
188         , m_screenManager               (screenManager)
189         , m_layer                               (DE_NULL)
190         , m_framebuffer                 (*this) // \note Perfectly safe to give reference to this RC as everything except postIterate() works at this point.
191         , m_colorBuffer                 (*this)
192         , m_depthStencilBuffer  (*this)
193 {
194         m_layer = m_screenManager->acquireScreen();
195         try
196         {
197                 createFramebuffer(config);
198         }
199         catch (...)
200         {
201                 m_screenManager->releaseScreen(m_layer);
202                 throw;
203         }
204 }
205
206 ScreenContext::~ScreenContext (void)
207 {
208         m_screenManager->releaseScreen(m_layer);
209 }
210
211 void ScreenContext::createFramebuffer (const glu::RenderConfig& config)
212 {
213         const glw::Functions&   gl                                      = getFunctions();
214         const NSString* const   colorFormat                     = chooseLayerColorFormat(config);
215         const deUint32                  depthStencilFormat      = chooseDepthStencilFormat(config);
216         tcu::PixelFormat                pixelFormat;
217         int                                             width                           = 0;
218         int                                             height                          = 0;
219         int                                             depthBits                       = 0;
220         int                                             stencilBits                     = 0;
221
222         if (config.numSamples > 0)
223                 throw NotSupportedError("Multisample config is not supported");
224
225         if (colorFormat == nil)
226                 throw NotSupportedError("Unsupported color attachment format");
227
228         if ((config.depthBits > 0 || config.stencilBits > 0) && depthStencilFormat == 0)
229                 throw NotSupportedError("Unsupported depth & stencil attachment format");
230
231         m_layer.opaque = TRUE;
232         m_layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
233                                                                   colorFormat, kEAGLDrawablePropertyColorFormat,
234                                                                   [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
235                                                                   nil];
236
237         gl.bindRenderbuffer(GL_RENDERBUFFER, *m_colorBuffer);
238         if (![getEAGLContext() renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)m_layer])
239                 throw ResourceError("Failed to allocate color renderbuffer");
240         GLU_EXPECT_NO_ERROR(gl.getError(), "Creating color renderbuffer");
241
242         gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,           &width);
243         gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT,          &height);
244         gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_RED_SIZE,        &pixelFormat.redBits);
245         gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_GREEN_SIZE,      &pixelFormat.greenBits);
246         gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_BLUE_SIZE,       &pixelFormat.blueBits);
247         gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_ALPHA_SIZE,      &pixelFormat.alphaBits);
248         GLU_EXPECT_NO_ERROR(gl.getError(), "Querying surface size failed");
249
250         if (depthStencilFormat != 0)
251         {
252                 gl.bindRenderbuffer(GL_RENDERBUFFER, *m_depthStencilBuffer);
253                 gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
254
255                 gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE,              &depthBits);
256                 gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE,    &stencilBits);
257
258                 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer");
259         }
260
261         gl.bindFramebuffer(GL_FRAMEBUFFER, *m_framebuffer);
262         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *m_colorBuffer);
263
264         if (depthStencilFormat != 0)
265         {
266                 if (depthBits > 0)
267                         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *m_depthStencilBuffer);
268
269                 if (stencilBits > 0)
270                         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *m_depthStencilBuffer);
271         }
272
273         GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer");
274
275         if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
276                 throw NotSupportedError("Framebuffer is not complete");
277
278         // Set up correct viewport for first test case.
279         gl.viewport(0, 0, width, height);
280
281         m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, 0);
282 }
283
284 void ScreenContext::postIterate (void)
285 {
286         const glw::Functions& gl = getFunctions();
287         gl.bindRenderbuffer(GL_RENDERBUFFER, *m_colorBuffer);
288
289         if (![getEAGLContext() presentRenderbuffer:GL_RENDERBUFFER])
290                 throw ResourceError("presentRenderbuffer() failed");
291 }
292
293 } // ios
294 } // tcu