forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			179 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2012 Dolphin Emulator Project
 | 
						|
// Licensed under GPLv2+
 | 
						|
// Refer to the license.txt file included.
 | 
						|
 | 
						|
#include <string>
 | 
						|
#include <windows.h>
 | 
						|
 | 
						|
#include "Common/GL/GLInterface/WGL.h"
 | 
						|
#include "Common/Logging/Log.h"
 | 
						|
#include "Common/MsgHandler.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);
 | 
						|
}
 |