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