/*------------------------------------------------------------------------- * drawElements Quality Program Tester Core * ---------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief iOS Platform implementation. *//*--------------------------------------------------------------------*/ #include "tcuIOSPlatform.hh" #include "gluRenderConfig.hpp" #include "gluFboRenderContext.hpp" #include "glwInitES20Direct.hpp" #include "glwInitES30Direct.hpp" namespace tcu { namespace ios { // ScreenManager ScreenManager::ScreenManager (tcuEAGLView* view) : m_view(view) { } ScreenManager::~ScreenManager (void) { } CAEAGLLayer* ScreenManager::acquireScreen (void) { if (!m_viewLock.tryLock()) throw ResourceError("View is already is in use"); return [m_view getEAGLLayer]; } void ScreenManager::releaseScreen (CAEAGLLayer* layer) { DE_UNREF(layer); m_viewLock.unlock(); } // ContextFactory ContextFactory::ContextFactory (ScreenManager* screenManager) : glu::ContextFactory ("eagl", "iOS EAGL Context") , m_screenManager (screenManager) { } ContextFactory::~ContextFactory (void) { } glu::RenderContext* ContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const { RawContext* rawContext = new RawContext(config.type); try { if (config.surfaceType == glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC) return new glu::FboRenderContext(rawContext, config); else if (config.surfaceType == glu::RenderConfig::SURFACETYPE_WINDOW) return new ScreenContext(m_screenManager, config); else throw NotSupportedError("Unsupported surface type"); } catch (...) { delete rawContext; throw; } } // Platform Platform::Platform (ScreenManager* screenManager) { m_contextFactoryRegistry.registerFactory(new ContextFactory(screenManager)); } Platform::~Platform (void) { } // RawContext static EAGLRenderingAPI getEAGLApi (glu::ContextType type) { if (type.getAPI() == glu::ApiType::es(3,0)) return kEAGLRenderingAPIOpenGLES3; else if (type.getAPI() == glu::ApiType::es(2,0)) return kEAGLRenderingAPIOpenGLES2; else throw NotSupportedError("Requested GL API is not supported on iOS"); } RawContext::RawContext (glu::ContextType type) : m_type (type) , m_context (DE_NULL) , m_emptyTarget (0, 0, tcu::PixelFormat(0,0,0,0), 0, 0, 0) { const EAGLRenderingAPI eaglApi = getEAGLApi(type); m_context = [[EAGLContext alloc] initWithAPI:eaglApi]; if (!m_context) throw ResourceError("Failed to create EAGL context"); try { if (![EAGLContext setCurrentContext:m_context]) throw ResourceError("Failed to set current EAGL context"); if (type.getAPI() == glu::ApiType::es(3,0)) glw::initES30Direct(&m_functions); else if (type.getAPI() == glu::ApiType::es(2,0)) glw::initES20Direct(&m_functions); else throw InternalError("Unsupproted API for loading functions"); } catch (...) { if ([EAGLContext currentContext] == m_context) [EAGLContext setCurrentContext:nil]; [m_context release]; throw; } } RawContext::~RawContext (void) { if ([EAGLContext currentContext] == m_context) [EAGLContext setCurrentContext:nil]; [m_context release]; } void RawContext::postIterate (void) { } NSString* chooseLayerColorFormat (const glu::RenderConfig& config) { const bool cr = config.redBits != glu::RenderConfig::DONT_CARE; const bool cg = config.greenBits != glu::RenderConfig::DONT_CARE; const bool cb = config.blueBits != glu::RenderConfig::DONT_CARE; const bool ca = config.alphaBits != glu::RenderConfig::DONT_CARE; if ((!cr || config.redBits == 8) && (!cg || config.greenBits == 8) && (!cb || config.blueBits == 8) && (!ca || config.alphaBits == 8)) return kEAGLColorFormatRGBA8; if ((!cr || config.redBits == 5) && (!cg || config.greenBits == 6) && (!cb || config.blueBits == 5) && (!ca || config.alphaBits == 0)) return kEAGLColorFormatRGB565; return nil; } // ScreenContext ScreenContext::ScreenContext (ScreenManager* screenManager, const glu::RenderConfig& config) : RawContext (config.type) , m_screenManager (screenManager) , m_layer (DE_NULL) , m_framebuffer (*this) // \note Perfectly safe to give reference to this RC as everything except postIterate() works at this point. , m_colorBuffer (*this) , m_depthStencilBuffer (*this) { m_layer = m_screenManager->acquireScreen(); try { createFramebuffer(config); } catch (...) { m_screenManager->releaseScreen(m_layer); throw; } } ScreenContext::~ScreenContext (void) { m_screenManager->releaseScreen(m_layer); } void ScreenContext::createFramebuffer (const glu::RenderConfig& config) { const glw::Functions& gl = getFunctions(); const NSString* const colorFormat = chooseLayerColorFormat(config); const deUint32 depthStencilFormat = chooseDepthStencilFormat(config); tcu::PixelFormat pixelFormat; int width = 0; int height = 0; int depthBits = 0; int stencilBits = 0; if (config.numSamples > 0) throw NotSupportedError("Multisample config is not supported"); if (colorFormat == nil) throw NotSupportedError("Unsupported color attachment format"); if ((config.depthBits > 0 || config.stencilBits > 0) && depthStencilFormat == 0) throw NotSupportedError("Unsupported depth & stencil attachment format"); m_layer.opaque = TRUE; m_layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: colorFormat, kEAGLDrawablePropertyColorFormat, [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, nil]; gl.bindRenderbuffer(GL_RENDERBUFFER, *m_colorBuffer); if (![getEAGLContext() renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)m_layer]) throw ResourceError("Failed to allocate color renderbuffer"); GLU_EXPECT_NO_ERROR(gl.getError(), "Creating color renderbuffer"); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_RED_SIZE, &pixelFormat.redBits); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_GREEN_SIZE, &pixelFormat.greenBits); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_BLUE_SIZE, &pixelFormat.blueBits); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_ALPHA_SIZE, &pixelFormat.alphaBits); GLU_EXPECT_NO_ERROR(gl.getError(), "Querying surface size failed"); if (depthStencilFormat != 0) { gl.bindRenderbuffer(GL_RENDERBUFFER, *m_depthStencilBuffer); gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, &depthBits); gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &stencilBits); GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer"); } gl.bindFramebuffer(GL_FRAMEBUFFER, *m_framebuffer); gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *m_colorBuffer); if (depthStencilFormat != 0) { if (depthBits > 0) gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *m_depthStencilBuffer); if (stencilBits > 0) gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *m_depthStencilBuffer); } GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer"); if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) throw NotSupportedError("Framebuffer is not complete"); // Set up correct viewport for first test case. gl.viewport(0, 0, width, height); m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, 0); } void ScreenContext::postIterate (void) { const glw::Functions& gl = getFunctions(); gl.bindRenderbuffer(GL_RENDERBUFFER, *m_colorBuffer); if (![getEAGLContext() presentRenderbuffer:GL_RENDERBUFFER]) throw ResourceError("presentRenderbuffer() failed"); } } // ios } // tcu