/*-------------------------------------------------------------------------
* 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 Win32 GLES3 wrapper platform.
*//*--------------------------------------------------------------------*/
#include "tcuWin32GLES3Platform.hpp"
#include "gluRenderConfig.hpp"
#include "gluRenderContext.hpp"
#include "tcuRenderTarget.hpp"
#include "gl3Context.h"
#include "glwInitES30Direct.hpp"
struct gl3PlatformContext_s
{
tcu::wgl::Context* context;
gl3PlatformContext_s (void)
: context(DE_NULL)
{
}
};
gl3FunctionPtr gl3PlatformContext_getProcAddress (gl3PlatformContext* platformCtx, const char* procName)
{
DE_ASSERT(platformCtx && platformCtx->context);
return platformCtx->context->getGLFunction(procName);
}
namespace tcu
{
enum
{
DEFAULT_WINDOW_WIDTH = 400,
DEFAULT_WINDOW_HEIGHT = 300
};
// Win32GLES3Context
class Win32GLES3Context : public glu::RenderContext
{
public:
Win32GLES3Context (const wgl::Core& wgl, HINSTANCE instance, const glu::RenderConfig& config);
~Win32GLES3Context (void);
glu::ContextType getType (void) const { return glu::CONTEXTTYPE_ES3; }
const RenderTarget& getRenderTarget (void) const { return m_renderTarget; }
void postIterate (void);
const glw::Functions& getFunctions (void) const { return m_functions; }
private:
Win32GLES3Context (const Win32GLES3Context& other);
Win32GLES3Context& operator= (const Win32GLES3Context& other);
RenderTarget m_renderTarget;
Win32Window m_window;
gl3PlatformContext m_platformCtx;
gl3Context* m_context;
glw::Functions m_functions;
};
typedef const char* (GL_APIENTRY* glGetStringHackFunc) (GLenum str);
Win32GLES3Context::Win32GLES3Context (const wgl::Core& wgl, HINSTANCE instance, const glu::RenderConfig& config)
: m_renderTarget(config.width != glu::RenderConfig::DONT_CARE ? config.width : DEFAULT_WINDOW_WIDTH,
config.height != glu::RenderConfig::DONT_CARE ? config.height : DEFAULT_WINDOW_HEIGHT,
PixelFormat(8, 8, 8, 8), 24, 8, 0)
, m_window (instance, m_renderTarget.getWidth(), m_renderTarget.getHeight())
, m_context (DE_NULL)
{
const HDC deviceCtx = m_window.getDeviceContext();
const int pixelFormat = wgl::choosePixelFormat(wgl, deviceCtx, config);
if (pixelFormat < 0)
throw NotSupportedError("No compatible WGL pixel format found");
m_platformCtx.context = new wgl::Context(&wgl, m_window.getDeviceContext(), wgl::PROFILE_COMPATIBILITY, 3, 3, pixelFormat);
try
{
m_context = gl3Context_create(&m_platformCtx);
if (!m_context)
throw ResourceError("Failed to create GLES3 wrapper context");
gl3Context_setCurrentContext(m_context);
glw::initES30Direct(&m_functions);
m_window.setVisible(config.windowVisibility != glu::RenderConfig::VISIBILITY_HIDDEN);
{
const wgl::PixelFormatInfo info = wgl.getPixelFormatInfo(deviceCtx, pixelFormat);
const IVec2 size = m_window.getSize();
m_renderTarget = tcu::RenderTarget(size.x(), size.y(),
tcu::PixelFormat(info.redBits, info.greenBits, info.blueBits, info.alphaBits),
info.depthBits, info.stencilBits,
info.sampleBuffers ? info.samples : 0);
}
}
catch (...)
{
if (m_context)
gl3Context_destroy(m_context);
delete m_platformCtx.context;
throw;
}
}
Win32GLES3Context::~Win32GLES3Context (void)
{
if (m_context)
gl3Context_destroy(m_context);
delete m_platformCtx.context;
}
void Win32GLES3Context::postIterate (void)
{
m_platformCtx.context->swapBuffers();
}
// Win32GLES3ContextFactory
class Win32GLES3ContextFactory : public glu::ContextFactory
{
public:
Win32GLES3ContextFactory (HINSTANCE instance);
~Win32GLES3ContextFactory (void);
virtual glu::RenderContext* createContext (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const;
private:
const HINSTANCE m_instance;
wgl::Core m_wglCore;
};
Win32GLES3ContextFactory::Win32GLES3ContextFactory (HINSTANCE instance)
: glu::ContextFactory ("gles3_wrapper", "GLES3 Wrapper Context")
, m_instance (instance)
, m_wglCore (instance)
{
}
Win32GLES3ContextFactory::~Win32GLES3ContextFactory (void)
{
}
glu::RenderContext* Win32GLES3ContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
{
if (config.type == glu::CONTEXTTYPE_ES3)
return new Win32GLES3Context(m_wglCore, m_instance, config);
else
throw NotSupportedError("Unsupported rendering context type");
}
// Win32GLES3Platform
Win32GLES3Platform::Win32GLES3Platform (void)
{
const HINSTANCE instance = GetModuleHandle(NULL);
// Set priority to lower.
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
m_glContextFactoryRegistry.registerFactory(new Win32GLES3ContextFactory(instance));
}
Win32GLES3Platform::~Win32GLES3Platform (void)
{
}
bool Win32GLES3Platform::processEvents (void)
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, TRUE))
{
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
return false;
}
return true;
}
} // tcu
// Platform factory
tcu::Platform* createPlatform (void)
{
return new tcu::Win32GLES3Platform();
}