win32/GL: Reuse the same rendering context for everything

Some resources can't be shared across different rendering contexts while
others can. Additionally, the standard GLEW library does not support
multiple rendering contexts (that's what GLEX MX is for), even though it
might work on some (or even most) cards. WGL supports reuse of a
rendering context across multiple windows as long as the pixel formats
are the same.
Controls
Nicolas Hake 2015-03-26 15:17:51 +01:00
parent b2f742f997
commit c58e474f76
3 changed files with 39 additions and 42 deletions

View File

@ -98,12 +98,14 @@ public:
bool PageFlip(); // present scene
static void Reinitialize();
protected:
void SelectCommon();
// this handles are declared as pointers to structs
C4Window * pWindow; // window to draw in
#ifdef USE_WIN32_WINDOWS
HGLRC hrc; // rendering context
static HGLRC hrc; // rendering context
HWND hWindow; // used if pWindow==NULL
HDC hDC; // device context handle
static bool InitGlew(HINSTANCE hInst);

View File

@ -35,10 +35,23 @@ void CStdGLCtx::SelectCommon()
glEnable(GL_BLEND);
}
void CStdGLCtx::Reinitialize()
{
assert(!pGL->pCurrCtx);
#ifdef USE_WIN32_WINDOWS
if (hrc)
wglDeleteContext(hrc);
hrc = 0;
#endif
}
#ifdef USE_WIN32_WINDOWS
#include <GL/wglew.h>
decltype(CStdGLCtx::hrc) CStdGLCtx::hrc = 0;
// Enumerate available pixel formats. Choose the best pixel format in
// terms of color and depth buffer bits and then return all formats with
// different multisampling settings. If there are more then one, then choose
@ -227,15 +240,11 @@ bool CStdGLCtx::InitGlew(HINSTANCE hInst)
return glewInitialized;
}
CStdGLCtx::CStdGLCtx(): pWindow(0), hrc(0), hDC(0) { }
CStdGLCtx::CStdGLCtx(): pWindow(0), hDC(0) { }
void CStdGLCtx::Clear()
{
if (hrc)
{
Deselect();
wglDeleteContext(hrc); hrc=0;
}
Deselect();
if (hDC)
{
ReleaseDC(pWindow ? pWindow->hRenderWindow : hWindow, hDC);
@ -265,6 +274,11 @@ bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *pApp, HWND hWindow)
if(!hDC)
{
pGL->Error(" gl: Error getting DC");
return false;
}
if (hrc)
{
SetPixelFormat(hDC, pGL->iPixelFormat, &pApp->GetPFD());
}
else
{
@ -274,13 +288,13 @@ bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *pApp, HWND hWindow)
if((pixel_format = GetPixelFormatForMS(hDC, 0)) != 0)
Config.Graphics.MultiSampling = 0;
if(!pixel_format)
PIXELFORMATDESCRIPTOR pfd;
if (!pixel_format)
{
pGL->Error(" gl: Error choosing pixel format");
}
else
{
PIXELFORMATDESCRIPTOR pfd;
if(!DescribePixelFormat(hDC, pixel_format, sizeof(pfd), &pfd))
{
pGL->Error(" gl: Error describing chosen pixel format");
@ -310,43 +324,19 @@ bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *pApp, HWND hWindow)
{
pGL->Error(" gl: Error creating gl context");
}
else
{
// share textures
bool success = false;
wglMakeCurrent(hDC, NULL); pGL->pCurrCtx=NULL;
if (this != pGL->pMainCtx)
{
if(!wglShareLists(pGL->pMainCtx->hrc, hrc))
pGL->Error(" gl: Textures for secondary context not available");
else
success = true;
}
else
{
// select main context
if (!Select())
pGL->Error(" gl: Unable to select context");
else
success = true;
}
if(success)
{
pGL->iPixelFormat = pixel_format;
PIXELFORMATDESCRIPTOR &rPfd = pApp->GetPFD();
rPfd = pfd;
return true;
}
}
wglDeleteContext(hrc); hrc = NULL;
pGL->iPixelFormat = pixel_format;
pApp->GetPFD() = pfd;
}
}
ReleaseDC(hWindow, hDC); hDC = NULL;
}
if (hrc)
{
Select();
return true;
}
ReleaseDC(hWindow, hDC); hDC = NULL;
return false;
}
@ -372,7 +362,11 @@ bool CStdGLCtx::Select(bool verbose)
// safety
if (!pGL || !hrc) return false;
// make context current
if (!wglMakeCurrent (hDC, hrc)) return false;
if (!wglMakeCurrent (hDC, hrc))
{
pGL->Error("Unable to select context.");
return false;
}
SelectCommon();
// update clipper - might have been done by UpdateSize
// however, the wrong size might have been assumed

View File

@ -670,6 +670,7 @@ bool C4Window::ReInit(C4AbstractApp* pApp)
hWindow, NULL, pApp->hInstance, NULL);
if(!hNewRenderWindow) return false;
CStdGLCtx::Reinitialize();
ShowWindow(hNewRenderWindow, SW_SHOW);
DestroyWindow(hRenderWindow);
hRenderWindow = hNewRenderWindow;