blob: 518ffdb6c824f543df282833a28af119a9229cc9 [file] [log] [blame]
//
// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "SampleApplication.h"
#ifdef _WIN32
#include "win32/Win32Timer.h"
#include "win32/Win32Window.h"
#else
#error unsupported OS.
#endif
SampleApplication::SampleApplication(const std::string& name, size_t width, size_t height,
EGLint glesMajorVersion, RendererType requestedRenderer)
: mSurface(EGL_NO_SURFACE),
mContext(EGL_NO_CONTEXT),
mClientVersion(glesMajorVersion),
mRequestedRenderer(requestedRenderer),
mWidth(width),
mHeight(height),
mName(name),
mRunning(false),
#ifdef _WIN32
mTimer(new Win32Timer()),
mWindow(new Win32Window())
#endif
{
}
SampleApplication::~SampleApplication()
{
}
bool SampleApplication::initialize()
{
return true;
}
void SampleApplication::destroy()
{
}
void SampleApplication::step(float dt, double totalTime)
{
}
void SampleApplication::draw()
{
}
void SampleApplication::swap()
{
eglSwapBuffers(mWindow->getDisplay(), mSurface);
}
Window *SampleApplication::getWindow() const
{
return mWindow.get();
}
EGLConfig SampleApplication::getConfig() const
{
return mConfig;
}
EGLSurface SampleApplication::getSurface() const
{
return mSurface;
}
EGLContext SampleApplication::getContext() const
{
return mContext;
}
int SampleApplication::run()
{
if (!mWindow->initialize(mName, mWidth, mHeight, mRequestedRenderer))
{
return -1;
}
if (!initializeGL())
{
return -1;
}
mRunning = true;
int result = 0;
if (!initialize())
{
mRunning = false;
result = -1;
}
mTimer->start();
double prevTime = 0.0;
while (mRunning)
{
double elapsedTime = mTimer->getElapsedTime();
double deltaTime = elapsedTime - prevTime;
step(static_cast<float>(deltaTime), elapsedTime);
// Clear events that the application did not process from this frame
Event event;
while (popEvent(&event))
{
// If the application did not catch a close event, close now
if (event.Type == Event::EVENT_CLOSED)
{
exit();
}
}
if (!mRunning)
{
break;
}
draw();
swap();
mWindow->messageLoop();
prevTime = elapsedTime;
}
destroy();
destroyGL();
mWindow->destroy();
return result;
}
void SampleApplication::exit()
{
mRunning = false;
}
bool SampleApplication::popEvent(Event *event)
{
return mWindow->popEvent(event);
}
bool SampleApplication::initializeGL()
{
const EGLint configAttributes[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_STENCIL_SIZE, 8,
EGL_SAMPLE_BUFFERS, EGL_DONT_CARE,
EGL_NONE
};
EGLint configCount;
if (!eglChooseConfig(mWindow->getDisplay(), configAttributes, &mConfig, 1, &configCount) || (configCount != 1))
{
destroyGL();
return false;
}
const EGLint surfaceAttributes[] =
{
EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_TRUE,
EGL_NONE, EGL_NONE,
};
mSurface = eglCreateWindowSurface(mWindow->getDisplay(), mConfig, mWindow->getNativeWindow(), surfaceAttributes);
if (mSurface == EGL_NO_SURFACE)
{
eglGetError(); // Clear error and try again
mSurface = eglCreateWindowSurface(mWindow->getDisplay(), mConfig, NULL, NULL);
}
if (eglGetError() != EGL_SUCCESS)
{
destroyGL();
return false;
}
EGLint contextAttibutes[] =
{
EGL_CONTEXT_CLIENT_VERSION, mClientVersion,
EGL_NONE
};
mContext = eglCreateContext(mWindow->getDisplay(), mConfig, NULL, contextAttibutes);
if (eglGetError() != EGL_SUCCESS)
{
destroyGL();
return false;
}
eglMakeCurrent(mWindow->getDisplay(), mSurface, mSurface, mContext);
if (eglGetError() != EGL_SUCCESS)
{
destroyGL();
return false;
}
// Turn off vsync
eglSwapInterval(mWindow->getDisplay(), 0);
return true;
}
void SampleApplication::destroyGL()
{
eglDestroySurface(mWindow->getDisplay(), mSurface);
mSurface = 0;
eglDestroyContext(mWindow->getDisplay(), mContext);
mContext = 0;
}