Changeset View
Changeset View
Standalone View
Standalone View
intern/ghost/intern/GHOST_ContextWGL.cpp
| Show All 37 Lines | |||||
| #include <cstdio> | #include <cstdio> | ||||
| #include <cassert> | #include <cassert> | ||||
| #include <vector> | #include <vector> | ||||
| HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL; | HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL; | ||||
| int GHOST_ContextWGL::s_sharedCount = 0; | int GHOST_ContextWGL::s_sharedCount = 0; | ||||
| bool GHOST_ContextWGL::s_singleContextMode = false; | /* Some third-generation Intel video-cards are constantly bring problems */ | ||||
| /* Intel video-cards don't work fine with multiple contexts and | |||||
| * have to share the same context for all windows. | |||||
| * But if we just share context for all windows it could work incorrect | |||||
| * with multiple videocards configuration. Suppose, that Intel videocards | |||||
| * can't be in multiple-devices configuration. */ | |||||
| static bool is_crappy_intel_card() | static bool is_crappy_intel_card() | ||||
| { | { | ||||
| return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL; | return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL; | ||||
| } | } | ||||
| GHOST_ContextWGL::GHOST_ContextWGL( | GHOST_ContextWGL::GHOST_ContextWGL( | ||||
| bool stereoVisual, | bool stereoVisual, | ||||
| bool alphaBackground, | bool alphaBackground, | ||||
| GHOST_TUns16 numOfAASamples, | GHOST_TUns16 numOfAASamples, | ||||
| HWND hWnd, | HWND hWnd, | ||||
| HDC hDC, | HDC hDC, | ||||
| int contextProfileMask, | int contextProfileMask, | ||||
| int contextMajorVersion, | int contextMajorVersion, | ||||
| int contextMinorVersion, | int contextMinorVersion, | ||||
| int contextFlags, | int contextFlags, | ||||
| int contextResetNotificationStrategy) | int contextResetNotificationStrategy) | ||||
| : GHOST_Context(stereoVisual, numOfAASamples), | : GHOST_Context(stereoVisual, numOfAASamples), | ||||
| m_dummyPbuffer(NULL), | |||||
| m_hWnd(hWnd), | m_hWnd(hWnd), | ||||
| m_hDC(hDC), | m_hDC(hDC), | ||||
| m_contextProfileMask(contextProfileMask), | m_contextProfileMask(contextProfileMask), | ||||
| m_contextMajorVersion(contextMajorVersion), | m_contextMajorVersion(contextMajorVersion), | ||||
| m_contextMinorVersion(contextMinorVersion), | m_contextMinorVersion(contextMinorVersion), | ||||
| m_contextFlags(contextFlags), | m_contextFlags(contextFlags), | ||||
| m_alphaBackground(alphaBackground), | m_alphaBackground(alphaBackground), | ||||
| m_contextResetNotificationStrategy(contextResetNotificationStrategy), | m_contextResetNotificationStrategy(contextResetNotificationStrategy), | ||||
| m_hGLRC(NULL) | m_hGLRC(NULL) | ||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||
| , | , | ||||
| m_dummyVendor(NULL), | m_dummyVendor(NULL), | ||||
| m_dummyRenderer(NULL), | m_dummyRenderer(NULL), | ||||
| m_dummyVersion(NULL) | m_dummyVersion(NULL) | ||||
| #endif | #endif | ||||
| { | { | ||||
| assert(m_hWnd); | |||||
| assert(m_hDC); | |||||
| } | } | ||||
| GHOST_ContextWGL::~GHOST_ContextWGL() | GHOST_ContextWGL::~GHOST_ContextWGL() | ||||
| { | { | ||||
| if (m_hGLRC != NULL) { | if (m_hGLRC != NULL) { | ||||
| if (m_hGLRC == ::wglGetCurrentContext()) | if (m_hGLRC == ::wglGetCurrentContext()) | ||||
| WIN32_CHK(::wglMakeCurrent(NULL, NULL)); | WIN32_CHK(::wglMakeCurrent(NULL, NULL)); | ||||
| if (m_hGLRC != s_sharedHGLRC || s_sharedCount == 1) { | if (m_hGLRC != s_sharedHGLRC || s_sharedCount == 1) { | ||||
| assert(s_sharedCount > 0); | assert(s_sharedCount > 0); | ||||
| s_sharedCount--; | s_sharedCount--; | ||||
| if (s_sharedCount == 0) | if (s_sharedCount == 0) | ||||
| s_sharedHGLRC = NULL; | s_sharedHGLRC = NULL; | ||||
| WIN32_CHK(::wglDeleteContext(m_hGLRC)); | WIN32_CHK(::wglDeleteContext(m_hGLRC)); | ||||
| } | } | ||||
| if (m_dummyPbuffer) { | |||||
| if (m_hDC != NULL) | |||||
| WIN32_CHK(::wglReleasePbufferDCARB(m_dummyPbuffer, m_hDC)); | |||||
| WIN32_CHK(::wglDestroyPbufferARB(m_dummyPbuffer)); | |||||
| } | |||||
| } | } | ||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||
| if (m_dummyRenderer) { | |||||
| free((void*)m_dummyRenderer); | free((void*)m_dummyRenderer); | ||||
| free((void*)m_dummyVendor); | free((void*)m_dummyVendor); | ||||
| free((void*)m_dummyVersion); | free((void*)m_dummyVersion); | ||||
| } | |||||
| #endif | #endif | ||||
| } | } | ||||
| GHOST_TSuccess GHOST_ContextWGL::swapBuffers() | GHOST_TSuccess GHOST_ContextWGL::swapBuffers() | ||||
| { | { | ||||
| return WIN32_CHK(::SwapBuffers(m_hDC)) ? GHOST_kSuccess : GHOST_kFailure; | return WIN32_CHK(::SwapBuffers(m_hDC)) ? GHOST_kSuccess : GHOST_kFailure; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | static HWND clone_window(HWND hWnd, LPVOID lpParam) | ||||
| return hwndCloned; | return hwndCloned; | ||||
| } | } | ||||
| void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD) | void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD) | ||||
| { | { | ||||
| HWND dummyHWND = NULL; | HWND dummyHWND = NULL; | ||||
| HPBUFFERARB dummyhBuffer = NULL; | |||||
| HDC dummyHDC = NULL; | HDC dummyHDC = NULL; | ||||
| HGLRC dummyHGLRC = NULL; | HGLRC dummyHGLRC = NULL; | ||||
| HDC prevHDC; | HDC prevHDC; | ||||
| HGLRC prevHGLRC; | HGLRC prevHGLRC; | ||||
| int iPixelFormat; | int iPixelFormat; | ||||
| SetLastError(NO_ERROR); | SetLastError(NO_ERROR); | ||||
| prevHDC = ::wglGetCurrentDC(); | prevHDC = ::wglGetCurrentDC(); | ||||
| WIN32_CHK(GetLastError() == NO_ERROR); | WIN32_CHK(GetLastError() == NO_ERROR); | ||||
| prevHGLRC = ::wglGetCurrentContext(); | prevHGLRC = ::wglGetCurrentContext(); | ||||
| WIN32_CHK(GetLastError() == NO_ERROR); | WIN32_CHK(GetLastError() == NO_ERROR); | ||||
| dummyHWND = clone_window(m_hWnd, NULL); | iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD); | ||||
| if (dummyHWND == NULL) | if (iPixelFormat == 0) | ||||
| goto finalize; | goto finalize; | ||||
| dummyHDC = GetDC(dummyHWND); | PIXELFORMATDESCRIPTOR chosenPFD; | ||||
| if (!WIN32_CHK(::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD))) | |||||
| if (!WIN32_CHK(dummyHDC != NULL)) | |||||
| goto finalize; | goto finalize; | ||||
| iPixelFormat = choose_pixel_format_legacy(dummyHDC, preferredPFD); | if (m_hWnd) { | ||||
| dummyHWND = clone_window(m_hWnd, NULL); | |||||
| if (iPixelFormat == 0) | if (dummyHWND == NULL) | ||||
| goto finalize; | goto finalize; | ||||
| PIXELFORMATDESCRIPTOR chosenPFD; | dummyHDC = GetDC(dummyHWND); | ||||
| if (!WIN32_CHK(::DescribePixelFormat(dummyHDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD))) | } | ||||
| else { | |||||
| dummyhBuffer = wglCreatePbufferARB(m_hDC, iPixelFormat, 1, 1, 0); | |||||
| dummyHDC = wglGetPbufferDCARB(dummyhBuffer); | |||||
| } | |||||
| if (!WIN32_CHK(dummyHDC != NULL)) | |||||
| goto finalize; | goto finalize; | ||||
| if (!WIN32_CHK(::SetPixelFormat(dummyHDC, iPixelFormat, &chosenPFD))) | if (!WIN32_CHK(::SetPixelFormat(dummyHDC, iPixelFormat, &chosenPFD))) | ||||
| goto finalize; | goto finalize; | ||||
| dummyHGLRC = ::wglCreateContext(dummyHDC); | dummyHGLRC = ::wglCreateContext(dummyHDC); | ||||
| if (!WIN32_CHK(dummyHGLRC != NULL)) | if (!WIN32_CHK(dummyHGLRC != NULL)) | ||||
| Show All 12 Lines | #ifndef NDEBUG | ||||
| free((void*)m_dummyVendor); | free((void*)m_dummyVendor); | ||||
| free((void*)m_dummyVersion); | free((void*)m_dummyVersion); | ||||
| m_dummyRenderer = _strdup(reinterpret_cast<const char *>(glGetString(GL_RENDERER))); | m_dummyRenderer = _strdup(reinterpret_cast<const char *>(glGetString(GL_RENDERER))); | ||||
| m_dummyVendor = _strdup(reinterpret_cast<const char *>(glGetString(GL_VENDOR))); | m_dummyVendor = _strdup(reinterpret_cast<const char *>(glGetString(GL_VENDOR))); | ||||
| m_dummyVersion = _strdup(reinterpret_cast<const char *>(glGetString(GL_VERSION))); | m_dummyVersion = _strdup(reinterpret_cast<const char *>(glGetString(GL_VERSION))); | ||||
| #endif | #endif | ||||
| s_singleContextMode = is_crappy_intel_card(); | |||||
| finalize: | finalize: | ||||
| WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC)); | WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC)); | ||||
| if (dummyHGLRC != NULL) | if (dummyHGLRC != NULL) | ||||
| WIN32_CHK(::wglDeleteContext(dummyHGLRC)); | WIN32_CHK(::wglDeleteContext(dummyHGLRC)); | ||||
| if (dummyHWND != NULL) { | if (dummyHWND != NULL) { | ||||
| if (dummyHDC != NULL) | if (dummyHDC != NULL) | ||||
| WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC)); | WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC)); | ||||
| WIN32_CHK(::DestroyWindow(dummyHWND)); | WIN32_CHK(::DestroyWindow(dummyHWND)); | ||||
| } | } | ||||
| else if (dummyhBuffer != NULL) { | |||||
| if (dummyHDC != NULL) | |||||
| WIN32_CHK(::wglReleasePbufferDCARB(dummyhBuffer, dummyHDC)); | |||||
| WIN32_CHK(::wglDestroyPbufferARB(dummyhBuffer)); | |||||
| } | |||||
| } | } | ||||
| static void makeAttribList( | static void makeAttribList( | ||||
| std::vector<int>& out, | std::vector<int>& out, | ||||
| bool stereoVisual, | bool stereoVisual, | ||||
| int numOfAASamples, | int numOfAASamples, | ||||
| int swapMethod, | int swapMethod, | ||||
| ▲ Show 20 Lines • Show All 345 Lines • ▼ Show 20 Lines | GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext() | ||||
| SetLastError(NO_ERROR); | SetLastError(NO_ERROR); | ||||
| HGLRC prevHGLRC = ::wglGetCurrentContext(); | HGLRC prevHGLRC = ::wglGetCurrentContext(); | ||||
| WIN32_CHK(GetLastError() == NO_ERROR); | WIN32_CHK(GetLastError() == NO_ERROR); | ||||
| HDC prevHDC = ::wglGetCurrentDC(); | HDC prevHDC = ::wglGetCurrentDC(); | ||||
| WIN32_CHK(GetLastError() == NO_ERROR); | WIN32_CHK(GetLastError() == NO_ERROR); | ||||
| if (!WGLEW_ARB_create_context || ::GetPixelFormat(m_hDC) == 0) { | const bool create_hDC = m_hDC == NULL; | ||||
| if (!WGLEW_ARB_create_context || create_hDC || ::GetPixelFormat(m_hDC) == 0) { | |||||
| const bool needAlpha = m_alphaBackground; | const bool needAlpha = m_alphaBackground; | ||||
| #ifdef GHOST_OPENGL_STENCIL | #ifdef GHOST_OPENGL_STENCIL | ||||
| const bool needStencil = true; | const bool needStencil = true; | ||||
| #else | #else | ||||
| const bool needStencil = false; | const bool needStencil = false; | ||||
| #endif | #endif | ||||
| #ifdef GHOST_OPENGL_SRGB | #ifdef GHOST_OPENGL_SRGB | ||||
| const bool sRGB = true; | const bool sRGB = true; | ||||
| #else | #else | ||||
| const bool sRGB = false; | const bool sRGB = false; | ||||
| #endif | #endif | ||||
| int iPixelFormat; | int iPixelFormat; | ||||
| int lastPFD; | int lastPFD; | ||||
| if (create_hDC) { | |||||
| /* get a handle to a device context with graphics accelerator enabled */ | |||||
| m_hDC = wglGetCurrentDC(); | |||||
| if (m_hDC == NULL) { | |||||
| m_hDC = GetDC(NULL); | |||||
| } | |||||
| } | |||||
| PIXELFORMATDESCRIPTOR chosenPFD; | PIXELFORMATDESCRIPTOR chosenPFD; | ||||
| iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB); | iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB); | ||||
| if (iPixelFormat == 0) { | if (iPixelFormat == 0) { | ||||
| ::wglMakeCurrent(prevHDC, prevHGLRC); | goto error; | ||||
| return GHOST_kFailure; | } | ||||
| if (create_hDC) { | |||||
| /* create an off-screen pixel buffer (Pbuffer) */ | |||||
| m_dummyPbuffer = wglCreatePbufferARB(m_hDC, iPixelFormat, 1, 1, 0); | |||||
| m_hDC = wglGetPbufferDCARB(m_dummyPbuffer); | |||||
| } | } | ||||
| lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD); | lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD); | ||||
| if (!WIN32_CHK(lastPFD != 0)) { | if (!WIN32_CHK(lastPFD != 0)) { | ||||
| ::wglMakeCurrent(prevHDC, prevHGLRC); | goto error; | ||||
| return GHOST_kFailure; | |||||
| } | } | ||||
| if (needAlpha && chosenPFD.cAlphaBits == 0) | if (needAlpha && chosenPFD.cAlphaBits == 0) | ||||
| fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n"); | fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n"); | ||||
| if (needStencil && chosenPFD.cStencilBits == 0) | if (needStencil && chosenPFD.cStencilBits == 0) | ||||
| fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n"); | fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n"); | ||||
| if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) { | if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) { | ||||
| ::wglMakeCurrent(prevHDC, prevHGLRC); | goto error; | ||||
| return GHOST_kFailure; | |||||
| } | } | ||||
| } | } | ||||
| if (WGLEW_ARB_create_context) { | if (WGLEW_ARB_create_context) { | ||||
| int profileBitCore = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB; | int profileBitCore = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB; | ||||
| int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; | int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; | ||||
| #ifdef WITH_GLEW_ES | #ifdef WITH_GLEW_ES | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | if (m_contextResetNotificationStrategy != 0) { | ||||
| } | } | ||||
| else { | else { | ||||
| fprintf(stderr, "Warning! Cannot set the reset notification strategy."); | fprintf(stderr, "Warning! Cannot set the reset notification strategy."); | ||||
| } | } | ||||
| } | } | ||||
| iAttributes.push_back(0); | iAttributes.push_back(0); | ||||
| if (!s_singleContextMode || s_sharedHGLRC == NULL) | |||||
| m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0])); | m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0])); | ||||
| else | |||||
| m_hGLRC = s_sharedHGLRC; | |||||
| } | } | ||||
| if (!WIN32_CHK(m_hGLRC != NULL)) { | if (!WIN32_CHK(m_hGLRC != NULL)) { | ||||
| ::wglMakeCurrent(prevHDC, prevHGLRC); | goto error; | ||||
| return GHOST_kFailure; | |||||
| } | } | ||||
| if (s_sharedHGLRC == NULL) | |||||
| s_sharedHGLRC = m_hGLRC; | |||||
| s_sharedCount++; | s_sharedCount++; | ||||
| if (!s_singleContextMode && s_sharedHGLRC != m_hGLRC && !WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) { | if (s_sharedHGLRC == NULL) { | ||||
| ::wglMakeCurrent(prevHDC, prevHGLRC); | s_sharedHGLRC = m_hGLRC; | ||||
| return GHOST_kFailure; | } | ||||
| else if (!WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) { | |||||
| goto error; | |||||
| } | } | ||||
| if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) { | if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) { | ||||
| ::wglMakeCurrent(prevHDC, prevHGLRC); | goto error; | ||||
| return GHOST_kFailure; | |||||
| } | } | ||||
| initContextGLEW(); | initContextGLEW(); | ||||
| if (is_crappy_intel_card()) { | if (is_crappy_intel_card()) { | ||||
| /* Some Intel cards with context 4.1 or 4.2 | /* Some Intel cards with context 4.1 or 4.2 | ||||
| * don't have the point sprite enabled by default. | * don't have the point sprite enabled by default. | ||||
| * | * | ||||
| Show All 13 Lines | #ifndef NDEBUG | ||||
| reportContextString("Vendor", m_dummyVendor, vendor); | reportContextString("Vendor", m_dummyVendor, vendor); | ||||
| reportContextString("Renderer", m_dummyRenderer, renderer); | reportContextString("Renderer", m_dummyRenderer, renderer); | ||||
| reportContextString("Version", m_dummyVersion, version); | reportContextString("Version", m_dummyVersion, version); | ||||
| fprintf(stderr, "Context Version: %d.%d\n", m_contextMajorVersion, m_contextMinorVersion); | fprintf(stderr, "Context Version: %d.%d\n", m_contextMajorVersion, m_contextMinorVersion); | ||||
| #endif | #endif | ||||
| return GHOST_kSuccess; | return GHOST_kSuccess; | ||||
| error: | |||||
| if (m_dummyPbuffer) { | |||||
| if (m_hDC != NULL) | |||||
| WIN32_CHK(::wglReleasePbufferDCARB(m_dummyPbuffer, m_hDC)); | |||||
| WIN32_CHK(::wglDestroyPbufferARB(m_dummyPbuffer)); | |||||
| } | |||||
| ::wglMakeCurrent(prevHDC, prevHGLRC); | |||||
| return GHOST_kFailure; | |||||
| } | } | ||||
| GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles() | GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles() | ||||
| { | { | ||||
| GHOST_TSuccess success = m_hGLRC != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess : GHOST_kFailure; | GHOST_TSuccess success = m_hGLRC != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess : GHOST_kFailure; | ||||
| m_hWnd = NULL; | m_hWnd = NULL; | ||||
| m_hDC = NULL; | m_hDC = NULL; | ||||
| return success; | return success; | ||||
| } | } | ||||