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 32namespace tcu 33{ 34namespace ios 35{ 36 37// ScreenManager 38 39ScreenManager::ScreenManager (tcuEAGLView* view) 40 : m_view(view) 41{ 42} 43 44ScreenManager::~ScreenManager (void) 45{ 46} 47 48CAEAGLLayer* 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 56void ScreenManager::releaseScreen (CAEAGLLayer* layer) 57{ 58 DE_UNREF(layer); 59 m_viewLock.unlock(); 60} 61 62// ContextFactory 63 64ContextFactory::ContextFactory (ScreenManager* screenManager) 65 : glu::ContextFactory ("eagl", "iOS EAGL Context") 66 , m_screenManager (screenManager) 67{ 68} 69 70ContextFactory::~ContextFactory (void) 71{ 72} 73 74glu::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 96Platform::Platform (ScreenManager* screenManager) 97{ 98 m_contextFactoryRegistry.registerFactory(new ContextFactory(screenManager)); 99} 100 101Platform::~Platform (void) 102{ 103} 104 105// RawContext 106 107static 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 117RawContext::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 150RawContext::~RawContext (void) 151{ 152 if ([EAGLContext currentContext] == m_context) 153 [EAGLContext setCurrentContext:nil]; 154 155 [m_context release]; 156} 157 158void RawContext::postIterate (void) 159{ 160} 161 162NSString* 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 186ScreenContext::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 206ScreenContext::~ScreenContext (void) 207{ 208 m_screenManager->releaseScreen(m_layer); 209} 210 211void 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 284void 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 295