When writing the X11 (linux) implementation there was a problem with X11 defining a "Display" type and we also have a Display class in the engine. So to fix that problem and minimize the risk for running into other name conflicts. We move everything from global namespace.
182 lines
No EOL
3.7 KiB
C++
182 lines
No EOL
3.7 KiB
C++
|
|
#include "glad_wgl.h"
|
|
|
|
#include <Platform/PlatformDisplay.h>
|
|
#include <Spectre/System/Log.h>
|
|
|
|
#include "Win32Internal.h"
|
|
#include "Win32GLContext.h"
|
|
|
|
namespace sp {
|
|
|
|
// Ensure that OpenGL extensions are loaded.
|
|
static void ensureExtensionsLoaded(HDC dc)
|
|
{
|
|
static bool init = false;
|
|
|
|
if (!init) {
|
|
init = true;
|
|
|
|
if (!gladLoadWGL(dc)) {
|
|
log("Win32: Could not load WGL extensions\n");
|
|
}
|
|
|
|
if (!gladLoadGL()) {
|
|
log("Win32: Could not load OpenGL extensions\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
Win32GLContext::Win32GLContext() :
|
|
m_wnd (NULL),
|
|
m_deviceContext (NULL),
|
|
m_renderContext (NULL)
|
|
{
|
|
}
|
|
|
|
Win32GLContext::~Win32GLContext()
|
|
{
|
|
destroy();
|
|
}
|
|
|
|
bool Win32GLContext::create(const PlatformDisplay* display)
|
|
{
|
|
// If created. destroy old handles.
|
|
destroy();
|
|
|
|
m_wnd = (HWND) display->getHandle();
|
|
|
|
// Should have a valid handle here. trigger error.
|
|
if (!m_wnd) {
|
|
log("Win32 - Could not create GL context: Invalid display handle\n");
|
|
return false;
|
|
}
|
|
|
|
m_deviceContext = ::GetDC(m_wnd);
|
|
|
|
createGLContext();
|
|
|
|
if (!m_deviceContext || !m_renderContext) {
|
|
|
|
// Make sure we release all handles.
|
|
destroy();
|
|
|
|
log("Win32 - Could not create GL context: %s", Win32GetMessage(GetLastError()));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Win32GLContext::destroy()
|
|
{
|
|
if (m_wnd && m_deviceContext) {
|
|
::ReleaseDC(m_wnd, m_deviceContext);
|
|
m_deviceContext = NULL;
|
|
m_wnd = NULL;
|
|
}
|
|
|
|
if (m_renderContext) {
|
|
::wglDeleteContext(m_renderContext);
|
|
m_renderContext = NULL;
|
|
}
|
|
}
|
|
|
|
void Win32GLContext::createGLContext()
|
|
{
|
|
HGLRC tmpDC;
|
|
|
|
// First set pixel format.
|
|
if (!setPixelFormat()) {
|
|
return;
|
|
}
|
|
|
|
// This is one reason why Win32 context creation is wierd.
|
|
// I need to create some context first so that GLEW knows if
|
|
// It supports the "wglCreateContextAttribsARB". That is a 3.2+ Core function.
|
|
tmpDC = ::wglCreateContext(m_deviceContext);
|
|
::wglMakeCurrent(m_deviceContext, tmpDC);
|
|
|
|
ensureExtensionsLoaded(m_deviceContext);
|
|
|
|
// Dont need to old one anymore.
|
|
wglMakeCurrent(m_deviceContext, NULL);
|
|
::wglDeleteContext(tmpDC);
|
|
|
|
// TODO: For now.. We force 3.2 Core but this should not be implementation specific.
|
|
// The Display class should force that for all GLContext Implementations.
|
|
|
|
int attriblist[] = {
|
|
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
|
|
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
|
|
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
|
0, 0
|
|
};
|
|
|
|
// Create real context.
|
|
m_renderContext = ::wglCreateContextAttribsARB(m_deviceContext, 0, attriblist);
|
|
}
|
|
|
|
bool Win32GLContext::activate()
|
|
{
|
|
// Make sure we have dc and rc before calling MakeCurrent.
|
|
if (m_deviceContext && m_renderContext) {
|
|
return ::wglMakeCurrent(m_deviceContext, m_renderContext);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Win32GLContext::deactivate()
|
|
{
|
|
return ::wglMakeCurrent(NULL, NULL);
|
|
}
|
|
|
|
bool Win32GLContext::isActive() const
|
|
{
|
|
return ::wglGetCurrentContext() == m_renderContext;
|
|
}
|
|
|
|
bool Win32GLContext::setSwapInterval(int interval)
|
|
{
|
|
ensureExtensionsLoaded(m_deviceContext);
|
|
|
|
return wglSwapIntervalEXT(interval);
|
|
}
|
|
|
|
void Win32GLContext::setSize(unsigned int width, unsigned int height)
|
|
{
|
|
if (activate()) {
|
|
glViewport(0, 0, width, height);
|
|
}
|
|
}
|
|
|
|
void Win32GLContext::swapBuffers()
|
|
{
|
|
if (m_deviceContext) {
|
|
::SwapBuffers(m_deviceContext);
|
|
}
|
|
}
|
|
|
|
bool Win32GLContext::setPixelFormat()
|
|
{
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
int format;
|
|
|
|
// For now, always create a RGBA pixel format with double buffer.
|
|
ZeroMemory(&pfd, sizeof(pfd));
|
|
pfd.nSize = sizeof(pfd);
|
|
pfd.nVersion = 1;
|
|
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
|
|
PFD_DOUBLEBUFFER;
|
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
|
pfd.cColorBits = 32;
|
|
pfd.cDepthBits = 16;
|
|
pfd.iLayerType = PFD_MAIN_PLANE;
|
|
|
|
format = ::ChoosePixelFormat(m_deviceContext, &pfd);
|
|
if (format) {
|
|
return ::SetPixelFormat(m_deviceContext, format, &pfd);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // namespace sp
|