aboutsummaryrefslogtreecommitdiff
path: root/source/Irrlicht/CWGLManager.cpp
diff options
context:
space:
mode:
authorcutealien <cutealien@dfc29bdd-3216-0410-991c-e03cc46cb475>2020-01-03 19:05:16 +0000
committercutealien <cutealien@dfc29bdd-3216-0410-991c-e03cc46cb475>2020-01-03 19:05:16 +0000
commit2ae2a551a6290f46734307bbfdafea4b1a2cf2ba (patch)
treeba2f0b468640e44899fed3df2d4cc58795f4a003 /source/Irrlicht/CWGLManager.cpp
downloadirrlicht-2ae2a551a6290f46734307bbfdafea4b1a2cf2ba.tar.xz
Merging r5975 through r6036 from trunk to ogl-es branch.
GLES drivers adapted, but only did make compile-tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
Diffstat (limited to 'source/Irrlicht/CWGLManager.cpp')
-rw-r--r--source/Irrlicht/CWGLManager.cpp497
1 files changed, 497 insertions, 0 deletions
diff --git a/source/Irrlicht/CWGLManager.cpp b/source/Irrlicht/CWGLManager.cpp
new file mode 100644
index 0000000..da9fb1a
--- /dev/null
+++ b/source/Irrlicht/CWGLManager.cpp
@@ -0,0 +1,497 @@
+// Copyright (C) 2013 Christian Stehno
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in Irrlicht.h
+
+#include "CWGLManager.h"
+
+#ifdef _IRR_COMPILE_WITH_WGL_MANAGER_
+
+#include "os.h"
+
+#include <GL/gl.h>
+#include "wglext.h"
+
+#ifdef _MSC_VER
+ #pragma comment(lib, "OpenGL32.lib")
+#endif
+
+namespace irr
+{
+namespace video
+{
+
+CWGLManager::CWGLManager()
+ : PrimaryContext(SExposedVideoData(0)), PixelFormat(0)
+{
+ #ifdef _DEBUG
+ setDebugName("CWGLManager");
+ #endif
+}
+
+CWGLManager::~CWGLManager()
+{
+}
+
+bool CWGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata)
+{
+ // store params, videoData is set later as it would be overwritten else
+ Params=params;
+
+ // Create a window to test antialiasing support
+ const fschar_t* ClassName = __TEXT("CWGLManager");
+ HINSTANCE lhInstance = GetModuleHandle(0);
+
+ // Register Class
+ WNDCLASSEX wcex;
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = (WNDPROC)DefWindowProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = lhInstance;
+ wcex.hIcon = NULL;
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wcex.lpszMenuName = 0;
+ wcex.lpszClassName = ClassName;
+ wcex.hIconSm = 0;
+ wcex.hIcon = 0;
+ RegisterClassEx(&wcex);
+
+ RECT clientSize;
+ clientSize.top = 0;
+ clientSize.left = 0;
+ clientSize.right = Params.WindowSize.Width;
+ clientSize.bottom = Params.WindowSize.Height;
+
+ DWORD style = WS_POPUP;
+ if (!Params.Fullscreen)
+ style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+
+ AdjustWindowRect(&clientSize, style, FALSE);
+
+ const s32 realWidth = clientSize.right - clientSize.left;
+ const s32 realHeight = clientSize.bottom - clientSize.top;
+
+ const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2;
+ const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2;
+
+ HWND temporary_wnd=CreateWindow(ClassName, __TEXT(""), style, windowLeft,
+ windowTop, realWidth, realHeight, NULL, NULL, lhInstance, NULL);
+
+ if (!temporary_wnd)
+ {
+ os::Printer::log("Cannot create a temporary window.", ELL_ERROR);
+ UnregisterClass(ClassName, lhInstance);
+ return false;
+ }
+
+ HDC HDc = GetDC(temporary_wnd);
+
+ // Set up pixel format descriptor with desired parameters
+ PIXELFORMATDESCRIPTOR tmp_pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
+ 1, // Version Number
+ (DWORD)(PFD_DRAW_TO_WINDOW | // Format Must Support Window
+ PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
+ (Params.Doublebuffer?PFD_DOUBLEBUFFER:0) | // Must Support Double Buffering
+ (Params.Stereobuffer?PFD_STEREO:0)), // Must Support Stereo Buffer
+ PFD_TYPE_RGBA, // Request An RGBA Format
+ Params.Bits, // Select Our Color Depth
+ 0, 0, 0, 0, 0, 0, // Color Bits Ignored
+ 0, // No Alpha Buffer
+ 0, // Shift Bit Ignored
+ 0, // No Accumulation Buffer
+ 0, 0, 0, 0, // Accumulation Bits Ignored
+ Params.ZBufferBits, // Z-Buffer (Depth Buffer)
+ BYTE(Params.Stencilbuffer ? 1 : 0), // Stencil Buffer Depth
+ 0, // No Auxiliary Buffer
+ PFD_MAIN_PLANE, // Main Drawing Layer
+ 0, // Reserved
+ 0, 0, 0 // Layer Masks Ignored
+ };
+ pfd=tmp_pfd;
+
+ for (u32 i=0; i<6; ++i)
+ {
+ if (i == 1)
+ {
+ if (Params.Stencilbuffer)
+ {
+ os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING);
+ Params.Stencilbuffer = false;
+ pfd.cStencilBits = 0;
+ }
+ else
+ continue;
+ }
+ else
+ if (i == 2)
+ {
+ pfd.cDepthBits = 24;
+ }
+ else
+ if (i == 3)
+ {
+ if (Params.Bits!=16)
+ pfd.cDepthBits = 16;
+ else
+ continue;
+ }
+ else
+ if (i == 4)
+ {
+ // try single buffer
+ if (Params.Doublebuffer)
+ pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
+ else
+ continue;
+ }
+ else
+ if (i == 5)
+ {
+ os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR);
+ ReleaseDC(temporary_wnd, HDc);
+ DestroyWindow(temporary_wnd);
+ UnregisterClass(ClassName, lhInstance);
+ return false;
+ }
+
+ // choose pixelformat
+ PixelFormat = ChoosePixelFormat(HDc, &pfd);
+ if (PixelFormat)
+ break;
+ }
+
+ SetPixelFormat(HDc, PixelFormat, &pfd);
+ os::Printer::log("Create temporary GL rendering context", ELL_DEBUG);
+ HGLRC hrc=wglCreateContext(HDc);
+ if (!hrc)
+ {
+ os::Printer::log("Cannot create a temporary GL rendering context.", ELL_ERROR);
+ ReleaseDC(temporary_wnd, HDc);
+ DestroyWindow(temporary_wnd);
+ UnregisterClass(ClassName, lhInstance);
+ return false;
+ }
+
+ CurrentContext.OpenGLWin32.HDc = HDc;
+ CurrentContext.OpenGLWin32.HRc = hrc;
+ CurrentContext.OpenGLWin32.HWnd = temporary_wnd;
+
+ if (!activateContext(CurrentContext, false))
+ {
+ os::Printer::log("Cannot activate a temporary GL rendering context.", ELL_ERROR);
+ wglDeleteContext(hrc);
+ ReleaseDC(temporary_wnd, HDc);
+ DestroyWindow(temporary_wnd);
+ UnregisterClass(ClassName, lhInstance);
+ return false;
+ }
+
+ core::stringc wglExtensions;
+#ifdef WGL_ARB_extensions_string
+ PFNWGLGETEXTENSIONSSTRINGARBPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
+ if (irrGetExtensionsString)
+ wglExtensions = irrGetExtensionsString(HDc);
+#elif defined(WGL_EXT_extensions_string)
+ PFNWGLGETEXTENSIONSSTRINGEXTPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT");
+ if (irrGetExtensionsString)
+ wglExtensions = irrGetExtensionsString(HDc);
+#endif
+ const bool pixel_format_supported = (wglExtensions.find("WGL_ARB_pixel_format") != -1);
+ const bool multi_sample_supported = ((wglExtensions.find("WGL_ARB_multisample") != -1) ||
+ (wglExtensions.find("WGL_EXT_multisample") != -1) || (wglExtensions.find("WGL_3DFX_multisample") != -1) );
+#ifdef _DEBUG
+ os::Printer::log("WGL_extensions", wglExtensions);
+#endif
+
+#ifdef WGL_ARB_pixel_format
+ PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat_ARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
+ if (pixel_format_supported && wglChoosePixelFormat_ARB)
+ {
+ // This value determines the number of samples used for antialiasing
+ // My experience is that 8 does not show a big
+ // improvement over 4, but 4 shows a big improvement
+ // over 2.
+
+ if (Params.AntiAlias > 32)
+ Params.AntiAlias = 32;
+
+ f32 fAttributes[] = {0.0, 0.0};
+ s32 iAttributes[] =
+ {
+ WGL_DRAW_TO_WINDOW_ARB,1,
+ WGL_SUPPORT_OPENGL_ARB,1,
+ WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
+ WGL_COLOR_BITS_ARB,(Params.Bits==32) ? 24 : 15,
+ WGL_ALPHA_BITS_ARB,(Params.Bits==32) ? 8 : 1,
+ WGL_DEPTH_BITS_ARB,Params.ZBufferBits, // 10,11
+ WGL_STENCIL_BITS_ARB,Params.Stencilbuffer ? 1 : 0,
+ WGL_DOUBLE_BUFFER_ARB,Params.Doublebuffer ? 1 : 0,
+ WGL_STEREO_ARB,Params.Stereobuffer ? 1 : 0,
+ WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
+#ifdef WGL_ARB_multisample
+ WGL_SAMPLES_ARB,Params.AntiAlias, // 20,21
+ WGL_SAMPLE_BUFFERS_ARB, (Params.AntiAlias>0) ? 1 : 0,
+#elif defined(WGL_EXT_multisample)
+ WGL_SAMPLES_EXT,AntiAlias, // 20,21
+ WGL_SAMPLE_BUFFERS_EXT, (Params.AntiAlias>0) ? 1 : 0,
+#elif defined(WGL_3DFX_multisample)
+ WGL_SAMPLES_3DFX,AntiAlias, // 20,21
+ WGL_SAMPLE_BUFFERS_3DFX, (Params.AntiAlias>0) ? 1 : 0,
+#endif
+#ifdef WGL_ARB_framebuffer_sRGB
+ WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, Params.HandleSRGB ? 1:0,
+#elif defined(WGL_EXT_framebuffer_sRGB)
+ WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, Params.HandleSRGB ? 1:0,
+#endif
+// WGL_DEPTH_FLOAT_EXT, 1,
+ 0,0,0,0
+ };
+ int iAttrSize = sizeof(iAttributes)/sizeof(int);
+ const bool framebuffer_srgb_supported = ((wglExtensions.find("WGL_ARB_framebuffer_sRGB") != -1) ||
+ (wglExtensions.find("WGL_EXT_framebuffer_sRGB") != -1));
+ if (!framebuffer_srgb_supported)
+ {
+ memmove(&iAttributes[24],&iAttributes[26],sizeof(int)*(iAttrSize-26));
+ iAttrSize -= 2;
+ }
+ if (!multi_sample_supported)
+ {
+ memmove(&iAttributes[20],&iAttributes[24],sizeof(int)*(iAttrSize-24));
+ iAttrSize -= 4;
+ }
+
+ s32 rv=0;
+ // Try to get an acceptable pixel format
+ do
+ {
+ int pixelFormat=0;
+ UINT numFormats=0;
+ const BOOL valid = wglChoosePixelFormat_ARB(HDc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
+
+ if (valid && numFormats)
+ rv = pixelFormat;
+ else
+ iAttributes[21] -= 1;
+ }
+ while(rv==0 && iAttributes[21]>1);
+ if (rv)
+ {
+ PixelFormat=rv;
+ Params.AntiAlias=iAttributes[21];
+ }
+ }
+ else
+#endif
+ Params.AntiAlias=0;
+
+ // this only terminates the temporary HRc
+ destroyContext();
+ destroySurface();
+ terminate();
+ DestroyWindow(temporary_wnd);
+ UnregisterClass(ClassName, lhInstance);
+
+ // now get new window
+ CurrentContext.OpenGLWin32.HWnd=videodata.OpenGLWin32.HWnd;
+ // get hdc
+ if (!(CurrentContext.OpenGLWin32.HDc=GetDC((HWND)videodata.OpenGLWin32.HWnd)))
+ {
+ os::Printer::log("Cannot create a GL device context.", ELL_ERROR);
+ return false;
+ }
+ if (!PrimaryContext.OpenGLWin32.HWnd)
+ {
+ PrimaryContext.OpenGLWin32.HWnd=CurrentContext.OpenGLWin32.HWnd;
+ PrimaryContext.OpenGLWin32.HDc=CurrentContext.OpenGLWin32.HDc;
+ }
+
+ return true;
+}
+
+void CWGLManager::terminate()
+{
+ if (CurrentContext.OpenGLWin32.HDc)
+ ReleaseDC((HWND)CurrentContext.OpenGLWin32.HWnd, (HDC)CurrentContext.OpenGLWin32.HDc);
+ if (PrimaryContext.OpenGLWin32.HDc && PrimaryContext.OpenGLWin32.HDc == CurrentContext.OpenGLWin32.HDc)
+ memset(&PrimaryContext, 0, sizeof(PrimaryContext));
+ memset(&CurrentContext, 0, sizeof(CurrentContext));
+}
+
+bool CWGLManager::generateSurface()
+{
+ HDC HDc = (HDC)CurrentContext.OpenGLWin32.HDc;
+ // search for pixel format the simple way
+ if (PixelFormat==0 || (!SetPixelFormat(HDc, PixelFormat, &pfd)))
+ {
+ for (u32 i=0; i<5; ++i)
+ {
+ if (i == 1)
+ {
+ if (Params.Stencilbuffer)
+ {
+ os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING);
+ Params.Stencilbuffer = false;
+ pfd.cStencilBits = 0;
+ }
+ else
+ continue;
+ }
+ else
+ if (i == 2)
+ {
+ pfd.cDepthBits = 24;
+ }
+ if (i == 3)
+ {
+ if (Params.Bits!=16)
+ pfd.cDepthBits = 16;
+ else
+ continue;
+ }
+ else
+ if (i == 4)
+ {
+ os::Printer::log("Cannot create a GL device context", "No suitable format.", ELL_ERROR);
+ return false;
+ }
+
+ // choose pixelformat
+ PixelFormat = ChoosePixelFormat(HDc, &pfd);
+ if (PixelFormat)
+ break;
+ }
+
+ // set pixel format
+ if (!SetPixelFormat(HDc, PixelFormat, &pfd))
+ {
+ os::Printer::log("Cannot set the pixel format.", ELL_ERROR);
+ return false;
+ }
+ }
+
+ if (pfd.cAlphaBits != 0)
+ {
+ if (pfd.cRedBits == 8)
+ ColorFormat = ECF_A8R8G8B8;
+ else
+ ColorFormat = ECF_A1R5G5B5;
+ }
+ else
+ {
+ if (pfd.cRedBits == 8)
+ ColorFormat = ECF_R8G8B8;
+ else
+ ColorFormat = ECF_R5G6B5;
+ }
+ os::Printer::log("Pixel Format", core::stringc(PixelFormat).c_str(), ELL_DEBUG);
+ return true;
+}
+
+void CWGLManager::destroySurface()
+{
+}
+
+bool CWGLManager::generateContext()
+{
+ HDC HDc=(HDC)CurrentContext.OpenGLWin32.HDc;
+ HGLRC hrc;
+ // create rendering context
+#ifdef WGL_ARB_create_context
+ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs_ARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
+ if (wglCreateContextAttribs_ARB)
+ {
+ // with 3.0 all available profiles should be usable, higher versions impose restrictions
+ // we need at least 1.1
+ const int iAttribs[] =
+ {
+ WGL_CONTEXT_MAJOR_VERSION_ARB, 1,
+ WGL_CONTEXT_MINOR_VERSION_ARB, 1,
+// WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, // enable to get a debug context (depends on driver if that does anything)
+ 0
+ };
+ hrc=wglCreateContextAttribs_ARB(HDc, 0, iAttribs);
+ }
+ else
+#endif
+ hrc=wglCreateContext(HDc);
+ os::Printer::log("Irrlicht context");
+
+ if (!hrc)
+ {
+ os::Printer::log("Cannot create a GL rendering context.", ELL_ERROR);
+ return false;
+ }
+
+ // set exposed data
+ CurrentContext.OpenGLWin32.HRc = hrc;
+ if (!PrimaryContext.OpenGLWin32.HRc)
+ PrimaryContext.OpenGLWin32.HRc=CurrentContext.OpenGLWin32.HRc;
+
+ return true;
+}
+
+const SExposedVideoData& CWGLManager::getContext() const
+{
+ return CurrentContext;
+}
+
+bool CWGLManager::activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero)
+{
+ if (videoData.OpenGLWin32.HWnd && videoData.OpenGLWin32.HDc && videoData.OpenGLWin32.HRc)
+ {
+ if (!wglMakeCurrent((HDC)videoData.OpenGLWin32.HDc, (HGLRC)videoData.OpenGLWin32.HRc))
+ {
+ os::Printer::log("Render Context switch failed.");
+ return false;
+ }
+ CurrentContext=videoData;
+ }
+ else if (!restorePrimaryOnZero && !videoData.OpenGLWin32.HDc && !videoData.OpenGLWin32.HRc)
+ {
+ if (!wglMakeCurrent((HDC)0, (HGLRC)0))
+ {
+ os::Printer::log("Render Context reset failed.");
+ return false;
+ }
+ CurrentContext = videoData;
+ }
+ // set back to main context
+ else if (!videoData.OpenGLWin32.HWnd && CurrentContext.OpenGLWin32.HDc != PrimaryContext.OpenGLWin32.HDc)
+ {
+ if (!wglMakeCurrent((HDC)PrimaryContext.OpenGLWin32.HDc, (HGLRC)PrimaryContext.OpenGLWin32.HRc))
+ {
+ os::Printer::log("Render Context switch failed.");
+ return false;
+ }
+ CurrentContext=PrimaryContext;
+ }
+ return true;
+}
+
+void CWGLManager::destroyContext()
+{
+ if (CurrentContext.OpenGLWin32.HRc)
+ {
+ if (!wglMakeCurrent((HDC)CurrentContext.OpenGLWin32.HDc, 0))
+ os::Printer::log("Release of render context failed.", ELL_WARNING);
+
+ if (!wglDeleteContext((HGLRC)CurrentContext.OpenGLWin32.HRc))
+ os::Printer::log("Deletion of render context failed.", ELL_WARNING);
+ if (PrimaryContext.OpenGLWin32.HRc==CurrentContext.OpenGLWin32.HRc)
+ PrimaryContext.OpenGLWin32.HRc=0;
+ CurrentContext.OpenGLWin32.HRc=0;
+ }
+}
+
+bool CWGLManager::swapBuffers()
+{
+ return SwapBuffers((HDC)CurrentContext.OpenGLWin32.HDc) == TRUE;
+}
+
+}
+}
+
+#endif