295 lines
8.4 KiB
Plaintext
295 lines
8.4 KiB
Plaintext
/*-------------------------------------------------------------------------
|
|
* 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
|