1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
// Copyright 2012 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <string>
#include <windows.h>
#include "Common/MsgHandler.h"
#include "Common/GL/GLInterface/WGL.h"
#include "Common/Logging/Log.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<HWND>(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;
dllHandle = LoadLibrary(TEXT("OpenGL32.dll"));
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;
}
FreeLibrary(dllHandle);
}
|