diff options
Diffstat (limited to 'src/graphics/WGLContext.cpp')
-rw-r--r-- | src/graphics/WGLContext.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/graphics/WGLContext.cpp b/src/graphics/WGLContext.cpp new file mode 100644 index 0000000..865f11f --- /dev/null +++ b/src/graphics/WGLContext.cpp @@ -0,0 +1,184 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "WGLContext.h" + +#include "../base/Exception.h" +#include "../base/Logger.h" + +#include <SDL/SDL.h> +#undef WIN32_LEAN_AND_MEAN +#include <SDL/SDL_syswm.h> + +#include <iostream> + + +namespace avg { + +using namespace std; +using namespace boost; + +LONG WINAPI imagingWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void registerWindowClass() +{ + static char * pClassName; + if (pClassName) { + return; + } + pClassName = "GL"; + + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + wc.style = CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)imagingWindowProc; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(hInstance, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = pClassName; + + BOOL bOK = RegisterClass(&wc); + AVG_ASSERT(bOK); +} + +WGLContext::WGLContext(const GLConfig& glConfig, const IntPoint& windowSize, + const SDL_SysWMinfo* pSDLWMInfo) + : GLContext(windowSize, pSDLWMInfo) +{ + bool bOwnsContext; + if (pSDLWMInfo) { + m_hDC = wglGetCurrentDC(); + m_Context = wglGetCurrentContext(); + setCurrent(); + bOwnsContext = false; + } else { + registerWindowClass(); + m_hwnd = CreateWindow("GL", "GL", + WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, 0, 500, 300, 0, 0, GetModuleHandle(NULL), 0); + checkWinError(m_hwnd != 0, "CreateWindow"); + + m_hDC = GetDC(m_hwnd); + checkWinError(m_hDC != 0, "GetDC"); + + PIXELFORMATDESCRIPTOR pfd; + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + pfd.cDepthBits = 32; + pfd.iLayerType = PFD_MAIN_PLANE; + + int iFormat = ChoosePixelFormat(m_hDC, &pfd); + checkWinError(iFormat != 0, "ChoosePixelFormat"); + SetPixelFormat(m_hDC, iFormat, &pfd); + m_Context = wglCreateContext(m_hDC); + checkWinError(m_Context != 0, "wglCreateContext"); + bOwnsContext = true; + } + + init(glConfig, bOwnsContext); +} + +WGLContext::~WGLContext() +{ + deleteObjects(); + if (m_Context && ownsContext()) { + wglDeleteContext(m_Context); + DeleteDC(m_hDC); + DestroyWindow(m_hwnd); + } +} + +void WGLContext::activate() +{ + BOOL bOk = wglMakeCurrent(m_hDC, m_Context); + checkWinError(bOk, "wglMakeCurrent"); + setCurrent(); +} + +bool WGLContext::initVBlank(int rate) +{ + static bool s_bVBlankActive = false; + if (rate > 0) { + if (!queryOGLExtension("WGL_EXT_swap_control") + && !queryWGLExtension("WGL_EXT_swap_control")) { + AVG_LOG_WARNING( + "Windows VBlank setup failed: OpenGL Extension not supported."); + s_bVBlankActive = false; + return false; + } + glproc::SwapIntervalEXT(rate); + s_bVBlankActive = true; + return true; + } else { + if (s_bVBlankActive) { + glproc::SwapIntervalEXT(0); + s_bVBlankActive = false; + } + return false; + } +} + +bool WGLContext::queryWGLExtension(const char *extName) +{ + if (glproc::GetExtensionsStringARB == NULL) { + return false; + } + + char *p; + size_t extNameLen = strlen(extName); + + p = (char *)glproc::GetExtensionsStringARB(m_hDC); + AVG_ASSERT(p != 0); + char * end = p + strlen(p); + + while (p < end) { + size_t n = strcspn(p, " "); + if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) { + return true; + } + p += (n + 1); + } + return false; +} + +void WGLContext::checkWinError(BOOL bOK, const string& sWhere) +{ + if (!bOK) { + char szErr[512]; + FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM), + 0, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + szErr, 512, 0); + AVG_LOG_ERROR(sWhere+":"+szErr); + AVG_ASSERT(false); + } +} + +} |