1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief iOS Platform implementation.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuIOSPlatform.hh"
25 #include "gluRenderConfig.hpp"
26 #include "gluFboRenderContext.hpp"
28 #include "glwInitES20Direct.hpp"
29 #include "glwInitES30Direct.hpp"
39 ScreenManager::ScreenManager (tcuEAGLView* view)
44 ScreenManager::~ScreenManager (void)
48 CAEAGLLayer* ScreenManager::acquireScreen (void)
50 if (!m_viewLock.tryLock())
51 throw ResourceError("View is already is in use");
53 return [m_view getEAGLLayer];
56 void ScreenManager::releaseScreen (CAEAGLLayer* layer)
64 ContextFactory::ContextFactory (ScreenManager* screenManager)
65 : glu::ContextFactory ("eagl", "iOS EAGL Context")
66 , m_screenManager (screenManager)
70 ContextFactory::~ContextFactory (void)
74 glu::RenderContext* ContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
76 RawContext* rawContext = new RawContext(config.type);
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);
85 throw NotSupportedError("Unsupported surface type");
96 Platform::Platform (ScreenManager* screenManager)
98 m_contextFactoryRegistry.registerFactory(new ContextFactory(screenManager));
101 Platform::~Platform (void)
107 static EAGLRenderingAPI getEAGLApi (glu::ContextType type)
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;
114 throw NotSupportedError("Requested GL API is not supported on iOS");
117 RawContext::RawContext (glu::ContextType type)
119 , m_context (DE_NULL)
120 , m_emptyTarget (0, 0, tcu::PixelFormat(0,0,0,0), 0, 0, 0)
122 const EAGLRenderingAPI eaglApi = getEAGLApi(type);
124 m_context = [[EAGLContext alloc] initWithAPI:eaglApi];
126 throw ResourceError("Failed to create EAGL context");
130 if (![EAGLContext setCurrentContext:m_context])
131 throw ResourceError("Failed to set current EAGL context");
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);
138 throw InternalError("Unsupproted API for loading functions");
142 if ([EAGLContext currentContext] == m_context)
143 [EAGLContext setCurrentContext:nil];
150 RawContext::~RawContext (void)
152 if ([EAGLContext currentContext] == m_context)
153 [EAGLContext setCurrentContext:nil];
158 void RawContext::postIterate (void)
162 NSString* chooseLayerColorFormat (const glu::RenderConfig& config)
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;
169 if ((!cr || config.redBits == 8) &&
170 (!cg || config.greenBits == 8) &&
171 (!cb || config.blueBits == 8) &&
172 (!ca || config.alphaBits == 8))
173 return kEAGLColorFormatRGBA8;
175 if ((!cr || config.redBits == 5) &&
176 (!cg || config.greenBits == 6) &&
177 (!cb || config.blueBits == 5) &&
178 (!ca || config.alphaBits == 0))
179 return kEAGLColorFormatRGB565;
186 ScreenContext::ScreenContext (ScreenManager* screenManager, const glu::RenderConfig& config)
187 : RawContext (config.type)
188 , m_screenManager (screenManager)
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)
194 m_layer = m_screenManager->acquireScreen();
197 createFramebuffer(config);
201 m_screenManager->releaseScreen(m_layer);
206 ScreenContext::~ScreenContext (void)
208 m_screenManager->releaseScreen(m_layer);
211 void ScreenContext::createFramebuffer (const glu::RenderConfig& config)
213 const glw::Functions& gl = getFunctions();
214 const NSString* const colorFormat = chooseLayerColorFormat(config);
215 const deUint32 depthStencilFormat = chooseDepthStencilFormat(config);
216 tcu::PixelFormat pixelFormat;
222 if (config.numSamples > 0)
223 throw NotSupportedError("Multisample config is not supported");
225 if (colorFormat == nil)
226 throw NotSupportedError("Unsupported color attachment format");
228 if ((config.depthBits > 0 || config.stencilBits > 0) && depthStencilFormat == 0)
229 throw NotSupportedError("Unsupported depth & stencil attachment format");
231 m_layer.opaque = TRUE;
232 m_layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
233 colorFormat, kEAGLDrawablePropertyColorFormat,
234 [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
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");
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");
250 if (depthStencilFormat != 0)
252 gl.bindRenderbuffer(GL_RENDERBUFFER, *m_depthStencilBuffer);
253 gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
255 gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, &depthBits);
256 gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &stencilBits);
258 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer");
261 gl.bindFramebuffer(GL_FRAMEBUFFER, *m_framebuffer);
262 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *m_colorBuffer);
264 if (depthStencilFormat != 0)
267 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *m_depthStencilBuffer);
270 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *m_depthStencilBuffer);
273 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer");
275 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
276 throw NotSupportedError("Framebuffer is not complete");
278 // Set up correct viewport for first test case.
279 gl.viewport(0, 0, width, height);
281 m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, 0);
284 void ScreenContext::postIterate (void)
286 const glw::Functions& gl = getFunctions();
287 gl.bindRenderbuffer(GL_RENDERBUFFER, *m_colorBuffer);
289 if (![getEAGLContext() presentRenderbuffer:GL_RENDERBUFFER])
290 throw ResourceError("presentRenderbuffer() failed");