// Copyright 2012 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #include #include "Core/Host.h" #include "VideoBackends/OGL/GLInterface/WGL.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/VertexShaderManager.h" #include "VideoCommon/VideoConfig.h" static HDC hDC = nullptr; // Private GDI Device Context static HGLRC hRC = nullptr; // Permanent Rendering Context static HINSTANCE dllHandle = nullptr; // Handle to OpenGL32.dll // typedef from wglext.h typedef BOOL(WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr; void cInterfaceWGL::SwapInterval(int Interval) { if (wglSwapIntervalEXT) wglSwapIntervalEXT(Interval); else ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); } void cInterfaceWGL::Swap() { SwapBuffers(hDC); } void* cInterfaceWGL::GetFuncAddress(const std::string& name) { void* func = (void*)wglGetProcAddress((LPCSTR)name.c_str()); if (func == nullptr) func = (void*)GetProcAddress(dllHandle, (LPCSTR)name.c_str()); return func; } // Draw messages on top of the screen bool cInterfaceWGL::PeekMessages() { // TODO: peekmessage MSG msg; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) return FALSE; TranslateMessage(&msg); DispatchMessage(&msg); } return TRUE; } // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() bool cInterfaceWGL::Create(void *window_handle, bool core) { if (window_handle == nullptr) return false; HWND window_handle_reified = reinterpret_cast(window_handle); RECT window_rect = {0}; if (!GetClientRect(window_handle_reified, &window_rect)) return false; // Control window size and picture scaling int twidth = (window_rect.right - window_rect.left); int theight = (window_rect.bottom - window_rect.top); s_backbuffer_width = twidth; s_backbuffer_height = theight; m_window_handle = window_handle_reified; #ifdef _WIN32 dllHandle = LoadLibrary(TEXT("OpenGL32.dll")); #endif PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format 32, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // 8bit Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 0, // 0Bit Z-Buffer (Depth Buffer) 0, // 0bit Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; int PixelFormat; // Holds The Results After Searching For A Match if (!(hDC = GetDC(window_handle_reified))) { PanicAlert("(1) Can't create an OpenGL Device context. Fail."); return false; } if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { PanicAlert("(2) Can't find a suitable PixelFormat."); return false; } if (!SetPixelFormat(hDC, PixelFormat, &pfd)) { PanicAlert("(3) Can't set the PixelFormat."); return false; } if (!(hRC = wglCreateContext(hDC))) { PanicAlert("(4) Can't create an OpenGL rendering context."); return false; } return true; } bool cInterfaceWGL::MakeCurrent() { bool success = wglMakeCurrent(hDC, hRC) ? true : false; if (success) { // Grab the swap interval function pointer wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)GLInterface->GetFuncAddress("wglSwapIntervalEXT"); } return success; } bool cInterfaceWGL::ClearCurrent() { return wglMakeCurrent(hDC, nullptr) ? true : false; } // Update window width, size and etc. Called from Render.cpp void cInterfaceWGL::Update() { RECT rcWindow; GetClientRect(m_window_handle, &rcWindow); // Get the new window width and height s_backbuffer_width = (rcWindow.right - rcWindow.left); s_backbuffer_height = (rcWindow.bottom - rcWindow.top); } // Close backend void cInterfaceWGL::Shutdown() { if (hRC) { if (!wglMakeCurrent(nullptr, nullptr)) NOTICE_LOG(VIDEO, "Could not release drawing context."); if (!wglDeleteContext(hRC)) ERROR_LOG(VIDEO, "Attempt to release rendering context failed."); hRC = nullptr; } if (hDC && !ReleaseDC(m_window_handle, hDC)) { ERROR_LOG(VIDEO, "Attempt to release device context failed."); hDC = nullptr; } }