2009-05-08 13:28:41 +00:00
|
|
|
/*
|
|
|
|
* OpenClonk, http://www.openclonk.org
|
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
|
|
|
|
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
|
2009-05-08 13:28:41 +00:00
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* Distributed under the terms of the ISC license; see accompanying file
|
|
|
|
* "COPYING" for details.
|
2009-05-08 13:28:41 +00:00
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
|
|
|
* See accompanying file "TRADEMARK" for details.
|
2009-05-08 13:28:41 +00:00
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* To redistribute this file separately, substitute the full license texts
|
|
|
|
* for the above references.
|
2009-05-08 13:28:41 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* OpenGL implementation of NewGfx, the context */
|
|
|
|
|
2009-10-20 03:39:24 +00:00
|
|
|
#include "C4Include.h"
|
2012-04-27 17:04:43 +00:00
|
|
|
#include <C4DrawGL.h>
|
2011-03-19 21:09:10 +00:00
|
|
|
|
2011-10-03 15:19:24 +00:00
|
|
|
#include <C4Window.h>
|
2015-01-02 20:13:26 +00:00
|
|
|
#include <C4App.h>
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2013-10-29 13:27:18 +00:00
|
|
|
#ifndef USE_CONSOLE
|
2009-05-31 00:09:15 +00:00
|
|
|
|
|
|
|
void CStdGLCtx::SelectCommon()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-31 00:09:15 +00:00
|
|
|
pGL->pCurrCtx = this;
|
|
|
|
// set some default states
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
2009-07-28 01:49:33 +00:00
|
|
|
glDepthFunc(GL_LESS);
|
2009-05-31 00:09:15 +00:00
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
//glEnable(GL_LINE_SMOOTH);
|
|
|
|
//glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
|
|
|
|
//glEnable(GL_POINT_SMOOTH);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-31 00:09:15 +00:00
|
|
|
|
2012-03-23 21:53:56 +00:00
|
|
|
#ifdef USE_WIN32_WINDOWS
|
2010-12-29 14:19:46 +00:00
|
|
|
|
|
|
|
#include <GL/wglew.h>
|
|
|
|
|
|
|
|
// 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
|
|
|
|
// the one with highest depth buffer size and lowest stencil and auxiliary
|
|
|
|
// buffer sizes since we don't use them in Clonk.
|
|
|
|
static std::vector<int> EnumeratePixelFormats(HDC hdc)
|
|
|
|
{
|
|
|
|
std::vector<int> result;
|
|
|
|
if(!wglGetPixelFormatAttribivARB) return result;
|
|
|
|
|
|
|
|
int n_formats;
|
|
|
|
int attributes = WGL_NUMBER_PIXEL_FORMATS_ARB;
|
|
|
|
if(!wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attributes, &n_formats)) return result;
|
|
|
|
|
|
|
|
for(int i = 1; i < n_formats+1; ++i)
|
|
|
|
{
|
|
|
|
int new_attributes[] = { WGL_DRAW_TO_WINDOW_ARB, WGL_SUPPORT_OPENGL_ARB, WGL_DOUBLE_BUFFER_ARB, WGL_COLOR_BITS_ARB, WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_AUX_BUFFERS_ARB, WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
|
|
|
|
const unsigned int nnew_attributes = sizeof(new_attributes)/sizeof(int);
|
|
|
|
|
|
|
|
int new_results[nnew_attributes];
|
|
|
|
if(!wglGetPixelFormatAttribivARB(hdc, i, 0, nnew_attributes, new_attributes, new_results)) continue;
|
|
|
|
if(!new_results[0] || !new_results[1] || !new_results[2]) continue;
|
|
|
|
if(new_results[3] < 16 || new_results[4] < 16) continue; // require at least 16 bits per pixel in color and depth
|
|
|
|
|
|
|
|
// For no MS we do find a pixel format with depth 32 on my (ck's) computer,
|
|
|
|
// however, when choosing it then texturing does not work anymore. I am not
|
|
|
|
// exactly sure what the cause of that is, so let's not choose that one for now.
|
|
|
|
if(new_results[4] > 24) continue;
|
|
|
|
|
|
|
|
// Multisampling with just one sample is equivalent to no-multisampling,
|
|
|
|
// so don't include that in the result.
|
|
|
|
if(new_results[7] == 1 && new_results[8] == 1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(result.empty())
|
|
|
|
{
|
|
|
|
result.push_back(i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int old_attributes[] = { WGL_COLOR_BITS_ARB };
|
|
|
|
const unsigned int nold_attributes = sizeof(old_attributes)/sizeof(int);
|
|
|
|
int old_results[nold_attributes];
|
|
|
|
|
|
|
|
if(!wglGetPixelFormatAttribivARB(hdc, result[0], 0, nold_attributes, old_attributes, old_results)) continue;
|
|
|
|
|
|
|
|
if(new_results[3] > old_results[0])
|
|
|
|
{
|
|
|
|
result.clear();
|
|
|
|
result.push_back(i);
|
|
|
|
}
|
|
|
|
else if(new_results[3] == old_results[0])
|
|
|
|
{
|
|
|
|
unsigned int j;
|
|
|
|
for(j = 0; j < result.size(); ++j)
|
|
|
|
{
|
|
|
|
int equiv_attributes[] = { WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_AUX_BUFFERS_ARB, WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
|
|
|
|
const unsigned int nequiv_attributes = sizeof(equiv_attributes)/sizeof(int);
|
|
|
|
int equiv_results[nequiv_attributes];
|
|
|
|
if(!wglGetPixelFormatAttribivARB(hdc, result[j], 0, nequiv_attributes, equiv_attributes, equiv_results)) continue;
|
|
|
|
|
|
|
|
if(new_results[7] == equiv_results[3] && new_results[8] == equiv_results[4])
|
|
|
|
{
|
|
|
|
if(new_results[4] > equiv_results[0] || (new_results[4] == equiv_results[0] && (new_results[5] < equiv_results[1] || (new_results[5] == equiv_results[1] && new_results[6] < equiv_results[2]))))
|
|
|
|
result[j] = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(j == result.size()) result.push_back(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-03-30 19:06:30 +00:00
|
|
|
static int GetPixelFormatForMS(HDC hDC, int samples)
|
2010-12-29 14:19:46 +00:00
|
|
|
{
|
|
|
|
std::vector<int> vec = EnumeratePixelFormats(hDC);
|
|
|
|
for(unsigned int i = 0; i < vec.size(); ++i)
|
|
|
|
{
|
|
|
|
int attributes[] = { WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
|
|
|
|
const unsigned int n_attributes = 2;
|
|
|
|
int results[2];
|
|
|
|
if(!wglGetPixelFormatAttribivARB(hDC, vec[i], 0, n_attributes, attributes, results)) continue;
|
|
|
|
|
|
|
|
if( (samples == 0 && results[0] == 0) ||
|
|
|
|
(samples > 0 && results[0] == 1 && results[1] == samples))
|
|
|
|
{
|
|
|
|
return vec[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize GLEW. We need to choose a pixel format for this, however we need
|
|
|
|
// GLEW initialized to enumerate pixel formats. So this creates a temporary
|
|
|
|
// window with a default pixel format, initializes glew and removes that temp
|
|
|
|
// window again. Then we can enumerate pixel formats and choose a proper one
|
|
|
|
// for the main window in CStdGLCtx::Init.
|
|
|
|
bool CStdGLCtx::InitGlew(HINSTANCE hInst)
|
|
|
|
{
|
|
|
|
static bool glewInitialized = false;
|
|
|
|
if(glewInitialized) return true;
|
|
|
|
|
|
|
|
/*WNDCLASSEXW WndClass = {0};
|
|
|
|
WndClass.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
WndClass.style = CS_DBLCLKS;
|
|
|
|
WndClass.lpfnWndProc = DefWindowProcW;
|
|
|
|
WndClass.hInstance = pApp->hInstance;
|
|
|
|
WndClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
|
|
|
|
WndClass.lpszClassName = L"C4OCTest";
|
|
|
|
WndClass.hIcon = NULL;
|
|
|
|
WndClass.hIconSm = NULL;
|
|
|
|
if(!RegisterClassExW(&WndClass)) return !!pGL->Error(" gl: Error registered class for temp wnd");
|
|
|
|
*/
|
|
|
|
// Create window
|
|
|
|
HWND hWnd = CreateWindowExW (
|
|
|
|
0,
|
|
|
|
L"STATIC", //C4FullScreenClassName,
|
|
|
|
NULL, //L"C4OCTest", //ADDL(C4ENGINENAME),
|
|
|
|
WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT,CW_USEDEFAULT,0,0,
|
|
|
|
NULL,NULL,hInst,NULL);
|
|
|
|
|
|
|
|
if(!hWnd)
|
|
|
|
{
|
|
|
|
pGL->Error(" gl: Failed to create temporary window to choose pixel format");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HDC dc = GetDC(hWnd);
|
|
|
|
|
|
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
|
|
|
|
|
|
// pixel format
|
|
|
|
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)) ;
|
|
|
|
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
|
|
|
pfd.nVersion = 1 ;
|
|
|
|
pfd.dwFlags = PFD_DOUBLEBUFFER | /*(pGL->fFullscreen ? PFD_SWAP_EXCHANGE : 0) |*/
|
|
|
|
PFD_SUPPORT_OPENGL |
|
|
|
|
PFD_DRAW_TO_WINDOW ;
|
|
|
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
|
|
|
pfd.cColorBits = pGL->iClrDpt;
|
|
|
|
pfd.cDepthBits = 0;
|
|
|
|
pfd.iLayerType = PFD_MAIN_PLANE;
|
|
|
|
int temp_fmt = ChoosePixelFormat(dc, &pfd);
|
|
|
|
|
|
|
|
if(!temp_fmt)
|
|
|
|
{
|
|
|
|
pGL->Error(" gl: Error choosing temp pixel format");
|
|
|
|
}
|
|
|
|
else if(!SetPixelFormat(dc, temp_fmt, &pfd))
|
|
|
|
{
|
|
|
|
pGL->Error(" gl: Error setting temp pixel format");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HGLRC hrc = wglCreateContext(dc);
|
|
|
|
if(!hrc)
|
|
|
|
{
|
|
|
|
pGL->Error(" gl: Error creating temp context");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(!wglMakeCurrent(dc, hrc))
|
|
|
|
{
|
|
|
|
pGL->Error(" gl: Error making temp context current");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// init extensions
|
|
|
|
GLenum err = glewInit();
|
|
|
|
if(err != GLEW_OK)
|
|
|
|
{
|
|
|
|
// Problem: glewInit failed, something is seriously wrong.
|
|
|
|
pGL->Error(reinterpret_cast<const char*>(glewGetErrorString(err)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glewInitialized = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
wglMakeCurrent(NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
wglDeleteContext(hrc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseDC(hWnd, dc);
|
|
|
|
DestroyWindow(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return glewInitialized;
|
|
|
|
}
|
|
|
|
|
2010-12-29 15:37:47 +00:00
|
|
|
CStdGLCtx::CStdGLCtx(): pWindow(0), hrc(0), hDC(0) { }
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void CStdGLCtx::Clear()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (hrc)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
Deselect();
|
|
|
|
wglDeleteContext(hrc); hrc=0;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
if (hDC)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-12-29 14:19:46 +00:00
|
|
|
ReleaseDC(pWindow ? pWindow->hRenderWindow : hWindow, hDC);
|
2009-05-08 13:28:41 +00:00
|
|
|
hDC=0;
|
|
|
|
}
|
2010-12-29 15:37:47 +00:00
|
|
|
pWindow = 0; hWindow = NULL;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-08-27 21:12:01 +00:00
|
|
|
bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *pApp, HWND hWindow)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// safety
|
|
|
|
if (!pGL) return false;
|
|
|
|
|
2010-12-29 14:19:46 +00:00
|
|
|
// Initialize GLEW so that we can choose a pixel format later
|
|
|
|
if(!InitGlew(pApp->hInstance)) return false;
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// store window
|
|
|
|
this->pWindow = pWindow;
|
|
|
|
// default HWND
|
2010-12-29 14:19:46 +00:00
|
|
|
if (pWindow)
|
|
|
|
hWindow = pWindow->hRenderWindow;
|
|
|
|
else
|
|
|
|
this->hWindow = hWindow;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// get DC
|
2010-12-29 14:19:46 +00:00
|
|
|
hDC = GetDC(hWindow);
|
|
|
|
if(!hDC)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-12-29 14:19:46 +00:00
|
|
|
pGL->Error(" gl: Error getting DC");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Choose a good pixel format.
|
|
|
|
int pixel_format;
|
|
|
|
if((pixel_format = GetPixelFormatForMS(hDC, Config.Graphics.MultiSampling)) == 0)
|
|
|
|
if((pixel_format = GetPixelFormatForMS(hDC, 0)) != 0)
|
|
|
|
Config.Graphics.MultiSampling = 0;
|
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
else if(!SetPixelFormat(hDC, pixel_format, &pfd))
|
|
|
|
{
|
|
|
|
pGL->Error(" gl: Error setting chosen pixel format");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// create context
|
|
|
|
hrc = wglCreateContext(hDC);
|
|
|
|
if(!hrc)
|
|
|
|
{
|
|
|
|
pGL->Error(" gl: Error creating gl context");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//if (this != &pGL->MainCtx) wglCopyContext(pGL->MainCtx.hrc, hrc, GL_ALL_ATTRIB_BITS);
|
|
|
|
|
|
|
|
// share textures
|
|
|
|
bool success = false;
|
|
|
|
wglMakeCurrent(NULL, 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseDC(hWindow, hDC); hDC = NULL;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-12-29 14:19:46 +00:00
|
|
|
return false;
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-12-29 14:19:46 +00:00
|
|
|
std::vector<int> CStdGLCtx::EnumerateMultiSamples() const
|
|
|
|
{
|
|
|
|
std::vector<int> result;
|
|
|
|
std::vector<int> vec = EnumeratePixelFormats(hDC);
|
|
|
|
for(unsigned int i = 0; i < vec.size(); ++i)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-12-29 14:19:46 +00:00
|
|
|
int attributes[] = { WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
|
|
|
|
const unsigned int n_attributes = 2;
|
|
|
|
int results[2];
|
|
|
|
if(!wglGetPixelFormatAttribivARB(hDC, vec[i], 0, n_attributes, attributes, results)) continue;
|
|
|
|
|
|
|
|
if(results[0] == 1) result.push_back(results[1]);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2010-12-29 14:19:46 +00:00
|
|
|
|
|
|
|
return result;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
bool CStdGLCtx::Select(bool verbose)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// safety
|
2010-03-06 14:07:30 +00:00
|
|
|
if (!pGL || !hrc) return false;
|
2009-05-08 13:28:41 +00:00
|
|
|
// make context current
|
|
|
|
if (!wglMakeCurrent (hDC, hrc)) return false;
|
2009-05-31 00:09:15 +00:00
|
|
|
SelectCommon();
|
2009-05-08 13:28:41 +00:00
|
|
|
// update clipper - might have been done by UpdateSize
|
|
|
|
// however, the wrong size might have been assumed
|
|
|
|
if (!pGL->UpdateClipper()) return false;
|
|
|
|
// success
|
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void CStdGLCtx::Deselect()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pGL && pGL->pCurrCtx == this)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
wglMakeCurrent(NULL, NULL);
|
|
|
|
pGL->pCurrCtx=NULL;
|
2010-03-06 14:07:30 +00:00
|
|
|
pGL->RenderTarget=NULL;
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
bool CStdGLCtx::PageFlip()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// flush GL buffer
|
|
|
|
glFlush();
|
|
|
|
SwapBuffers(hDC);
|
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
#elif defined(USE_X11)
|
2009-06-05 17:57:37 +00:00
|
|
|
#include <GL/glx.h>
|
2012-04-10 21:39:49 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <gdk/gdkx.h>
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-12-29 15:37:47 +00:00
|
|
|
CStdGLCtx::CStdGLCtx(): pWindow(0), ctx(0) { }
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void CStdGLCtx::Clear()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
Deselect();
|
|
|
|
if (ctx)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2012-04-10 21:39:49 +00:00
|
|
|
Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
|
|
|
|
glXDestroyContext(dpy, (GLXContext)ctx);
|
2009-05-08 13:28:41 +00:00
|
|
|
ctx = 0;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
pWindow = 0;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-08-27 21:12:01 +00:00
|
|
|
bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// safety
|
|
|
|
if (!pGL) return false;
|
|
|
|
// store window
|
|
|
|
this->pWindow = pWindow;
|
2012-04-10 21:39:49 +00:00
|
|
|
Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
|
2009-05-08 13:28:41 +00:00
|
|
|
// Create Context with sharing (if this is the main context, our ctx will be 0, so no sharing)
|
|
|
|
// try direct rendering first
|
2012-04-10 21:39:49 +00:00
|
|
|
ctx = glXCreateContext(dpy, (XVisualInfo*)pWindow->Info, (pGL->pMainCtx != this) ? (GLXContext)pGL->pMainCtx->ctx : 0, True);
|
2009-05-08 13:28:41 +00:00
|
|
|
// without, rendering will be unacceptable slow, but that's better than nothing at all
|
|
|
|
if (!ctx)
|
2012-04-10 21:39:49 +00:00
|
|
|
ctx = glXCreateContext(dpy, (XVisualInfo*)pWindow->Info, pGL->pMainCtx ? (GLXContext)pGL->pMainCtx->ctx : 0, False);
|
2009-05-08 13:28:41 +00:00
|
|
|
// No luck at all?
|
|
|
|
if (!ctx) return pGL->Error(" gl: Unable to create context");
|
|
|
|
if (!Select(true)) return pGL->Error(" gl: Unable to select context");
|
|
|
|
// init extensions
|
|
|
|
GLenum err = glewInit();
|
|
|
|
if (GLEW_OK != err)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Problem: glewInit failed, something is seriously wrong.
|
2010-01-12 20:53:47 +00:00
|
|
|
return pGL->Error(reinterpret_cast<const char*>(glewGetErrorString(err)));
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
return true;
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
bool CStdGLCtx::Select(bool verbose)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// safety
|
|
|
|
if (!pGL || !ctx)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (verbose) pGL->Error(" gl: pGL is zero");
|
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2012-04-10 21:39:49 +00:00
|
|
|
Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
|
2009-05-08 13:28:41 +00:00
|
|
|
// make context current
|
2012-04-10 21:39:49 +00:00
|
|
|
if (!pWindow->renderwnd || !glXMakeCurrent(dpy, pWindow->renderwnd, (GLXContext)ctx))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (verbose) pGL->Error(" gl: glXMakeCurrent failed");
|
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-31 00:09:15 +00:00
|
|
|
SelectCommon();
|
2009-05-08 13:28:41 +00:00
|
|
|
// update clipper - might have been done by UpdateSize
|
|
|
|
// however, the wrong size might have been assumed
|
|
|
|
if (!pGL->UpdateClipper())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (verbose) pGL->Error(" gl: UpdateClipper failed");
|
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// success
|
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void CStdGLCtx::Deselect()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pGL && pGL->pCurrCtx == this)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2012-04-10 21:39:49 +00:00
|
|
|
Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
|
|
|
|
glXMakeCurrent(dpy, None, NULL);
|
2009-05-08 13:28:41 +00:00
|
|
|
pGL->pCurrCtx = 0;
|
2010-03-06 14:07:30 +00:00
|
|
|
pGL->RenderTarget = 0;
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
bool CStdGLCtx::PageFlip()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// flush GL buffer
|
|
|
|
glFlush();
|
|
|
|
if (!pWindow || !pWindow->renderwnd) return false;
|
2012-04-10 21:39:49 +00:00
|
|
|
Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
|
|
|
|
glXSwapBuffers(dpy, pWindow->renderwnd);
|
2009-05-08 13:28:41 +00:00
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
#elif defined(USE_SDL_MAINLOOP)
|
|
|
|
|
2010-12-29 15:37:47 +00:00
|
|
|
CStdGLCtx::CStdGLCtx(): pWindow(0) { }
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void CStdGLCtx::Clear()
|
|
|
|
{
|
|
|
|
pWindow = 0;
|
|
|
|
}
|
|
|
|
|
2011-08-27 21:12:01 +00:00
|
|
|
bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *)
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
|
|
|
// safety
|
|
|
|
if (!pGL) return false;
|
|
|
|
// store window
|
|
|
|
this->pWindow = pWindow;
|
|
|
|
// No luck at all?
|
|
|
|
if (!Select(true)) return pGL->Error(" gl: Unable to select context");
|
|
|
|
// init extensions
|
|
|
|
GLenum err = glewInit();
|
|
|
|
if (GLEW_OK != err)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Problem: glewInit failed, something is seriously wrong.
|
2010-01-12 20:53:47 +00:00
|
|
|
return pGL->Error(reinterpret_cast<const char*>(glewGetErrorString(err)));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CStdGLCtx::Select(bool verbose)
|
|
|
|
{
|
2009-05-31 00:09:15 +00:00
|
|
|
SelectCommon();
|
2009-05-08 13:28:41 +00:00
|
|
|
// update clipper - might have been done by UpdateSize
|
|
|
|
// however, the wrong size might have been assumed
|
|
|
|
if (!pGL->UpdateClipper())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (verbose) pGL->Error(" gl: UpdateClipper failed");
|
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// success
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CStdGLCtx::Deselect()
|
|
|
|
{
|
|
|
|
if (pGL && pGL->pCurrCtx == this)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pGL->pCurrCtx = 0;
|
2010-03-06 14:07:30 +00:00
|
|
|
pGL->RenderTarget = 0;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CStdGLCtx::PageFlip()
|
|
|
|
{
|
|
|
|
// flush GL buffer
|
|
|
|
glFlush();
|
|
|
|
if (!pWindow) return false;
|
|
|
|
SDL_GL_SwapBuffers();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //USE_X11/USE_SDL_MAINLOOP
|
|
|
|
|
2013-10-29 13:27:18 +00:00
|
|
|
#endif // USE_CONSOLE
|