mirror of
https://github.com/minetest/irrlicht.git
synced 2025-06-30 23:30:27 +02:00
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
This commit is contained in:
497
source/Irrlicht/CWGLManager.cpp
Normal file
497
source/Irrlicht/CWGLManager.cpp
Normal file
@ -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
|
Reference in New Issue
Block a user