Files
UnrealEngine/Engine/Source/Developer/StandaloneRenderer/Private/Windows/OpenGL/SlateOpenGLContext.cpp
2025-05-18 13:04:45 +08:00

156 lines
3.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "StandaloneRendererPrivate.h"
#include "OpenGL/SlateOpenGLExtensions.h"
#include "OpenGL/SlateOpenGLRenderer.h"
/**
* A dummy wndproc.
*/
static LRESULT CALLBACK DummyGLWndproc(HWND hWnd, uint32 Message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, Message, wParam, lParam);
}
/**
* Create a dummy window used to construct OpenGL contexts.
*/
static HWND CreateDummyGLWindow()
{
const TCHAR* WindowClassName = TEXT("DummyGLWindow");
// Register a dummy window class.
static bool bInitializedWindowClass = false;
if (!bInitializedWindowClass)
{
WNDCLASS wc;
bInitializedWindowClass = true;
FMemory::Memzero(wc);
wc.style = CS_OWNDC;
wc.lpfnWndProc = DummyGLWndproc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)(COLOR_MENUTEXT);
wc.lpszMenuName = NULL;
wc.lpszClassName = WindowClassName;
ATOM ClassAtom = ::RegisterClass(&wc);
check(ClassAtom);
}
// Create a dummy window.
HWND WindowHandle = CreateWindowEx(
WS_EX_WINDOWEDGE,
WindowClassName,
NULL,
WS_POPUP,
0, 0, 1, 1,
NULL, NULL, NULL, NULL);
check(WindowHandle);
return WindowHandle;
}
FSlateOpenGLContext::FSlateOpenGLContext()
: WindowHandle(NULL)
, WindowDC(NULL)
, Context(NULL)
, bReleaseWindowOnDestroy(false)
{
}
FSlateOpenGLContext::~FSlateOpenGLContext()
{
Destroy();
}
void FSlateOpenGLContext::Initialize( void* InWindow, const FSlateOpenGLContext* SharedContext )
{
WindowHandle = (HWND)InWindow;
if( WindowHandle == NULL )
{
WindowHandle = CreateDummyGLWindow();
bReleaseWindowOnDestroy = true;
}
// Create a pixel format descriptor for this window
PIXELFORMATDESCRIPTOR PFD;
FMemory::Memzero( &PFD, sizeof(PIXELFORMATDESCRIPTOR) );
PFD.nSize = sizeof(PIXELFORMATDESCRIPTOR);
PFD.nVersion = 1;
PFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL| PFD_DOUBLEBUFFER;
PFD.iPixelType = PFD_TYPE_RGBA;
PFD.cColorBits = 32;
PFD.cStencilBits = 0;
PFD.cDepthBits = 0;
PFD.iLayerType = PFD_MAIN_PLANE;
WindowDC = GetDC( WindowHandle );
check(WindowDC);
// Get the pixel format for this window based on our descriptor
uint32 PixelFormat = ChoosePixelFormat( WindowDC, &PFD );
// Ensure a pixel format could be found
check(PixelFormat);
BOOL Result = SetPixelFormat( WindowDC, PixelFormat, &PFD );
// Ensure the pixel format could be set on this window
check(Result);
Context = wglCreateContext( WindowDC );
// Make the new window active for drawing. We can't call any OpenGL functions without an active rendering context
Result = wglMakeCurrent( WindowDC, Context );
check( Result );
#pragma warning(push)
#pragma warning(disable:4191)
wglCreateContextAttribsARB = ( PFNWGLCREATECONTEXTATTRIBSARBPROC )wglGetProcAddress( "wglCreateContextAttribsARB" );
#pragma warning(pop)
check( wglCreateContextAttribsARB );
int32 ContextAttribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0
};
HGLRC OldContext = Context;
Context = wglCreateContextAttribsARB( WindowDC, SharedContext ? SharedContext->Context : NULL, ContextAttribs );
wglMakeCurrent( NULL, NULL );
wglDeleteContext( OldContext );
wglMakeCurrent( WindowDC, Context );
}
void FSlateOpenGLContext::Destroy()
{
if( WindowHandle != NULL )
{
wglMakeCurrent( NULL, NULL );
wglDeleteContext( Context );
ReleaseDC( WindowHandle, WindowDC );
WindowDC = NULL;
Context = NULL;
if( bReleaseWindowOnDestroy )
{
DestroyWindow( WindowHandle );
}
WindowHandle = NULL;
}
}
void FSlateOpenGLContext::MakeCurrent()
{
wglMakeCurrent( WindowDC, Context );
}