diff options
| author | Egor <egor.yusov@gmail.com> | 2017-12-25 22:15:18 +0000 |
|---|---|---|
| committer | Egor <egor.yusov@gmail.com> | 2017-12-25 22:15:18 +0000 |
| commit | 0d2b083616c1d1f8a0fd8882ffc0aaac270081f2 (patch) | |
| tree | 3d3a0740bd26f1b58fd3a30ed6499543e02eeb2f /unityplugin/UnityEmulator | |
| parent | Updated core & sample submodules (linux implementation) (diff) | |
| download | DiligentEngine-0d2b083616c1d1f8a0fd8882ffc0aaac270081f2.tar.gz DiligentEngine-0d2b083616c1d1f8a0fd8882ffc0aaac270081f2.zip | |
Enabled Unity Emulator on Linux. Linux platform is now fully supported
Diffstat (limited to 'unityplugin/UnityEmulator')
7 files changed, 440 insertions, 46 deletions
diff --git a/unityplugin/UnityEmulator/CMakeLists.txt b/unityplugin/UnityEmulator/CMakeLists.txt index dac8692..aa77ccb 100644 --- a/unityplugin/UnityEmulator/CMakeLists.txt +++ b/unityplugin/UnityEmulator/CMakeLists.txt @@ -84,6 +84,8 @@ elseif(PLATFORM_UNIVERSAL_WINDOWS) elseif(PLATFORM_ANDROID) list(APPEND SOURCE src/Android/AndroidMainImpl.cpp) +elseif(PLATFORM_LINUX) + list(APPEND SOURCE src/Linux/LinuxMain.cpp) else() message(FATAL_ERROR "Unknown platform") endif() diff --git a/unityplugin/UnityEmulator/include/UnityGraphicsGLCoreES_Emulator.h b/unityplugin/UnityEmulator/include/UnityGraphicsGLCoreES_Emulator.h index cc69f93..448c410 100644 --- a/unityplugin/UnityEmulator/include/UnityGraphicsGLCoreES_Emulator.h +++ b/unityplugin/UnityEmulator/include/UnityGraphicsGLCoreES_Emulator.h @@ -10,7 +10,7 @@ #if defined(PLATFORM_ANDROID) class UnityGraphicsGLESAndroid_Impl; using UnityGraphicsGL_Impl = UnityGraphicsGLESAndroid_Impl; -#elif defined( PLATFORM_WIN32 ) || defined( PLATFORM_UNIVERSAL_WINDOWS ) +#elif defined(PLATFORM_WIN32) || defined(PLATFORM_UNIVERSAL_WINDOWS) || defined(PLATFORM_LINUX) class UnityGraphicsGLCore_Impl; using UnityGraphicsGL_Impl = UnityGraphicsGLCore_Impl; #else @@ -22,7 +22,11 @@ class UnityGraphicsGLCoreES_Emulator : public UnityGraphicsEmulator { public: static UnityGraphicsGLCoreES_Emulator& GetInstance(); - void InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion); + void InitGLContext(void *pNativeWndHandle, + #ifdef PLATFORM_LINUX + void *pDisplay, + #endif + int MajorVersion, int MinorVersion); virtual void Present()override final; virtual void Release()override final; diff --git a/unityplugin/UnityEmulator/src/Linux/LinuxMain.cpp b/unityplugin/UnityEmulator/src/Linux/LinuxMain.cpp new file mode 100644 index 0000000..823d207 --- /dev/null +++ b/unityplugin/UnityEmulator/src/Linux/LinuxMain.cpp @@ -0,0 +1,294 @@ +/* Copyright 2015-2017 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include <memory> +#include <iomanip> + +#include <GL/glx.h> +#include <GL/gl.h> + + // Undef symbols defined by XLib +#ifdef Bool +# undef Bool +#endif +#ifdef True +# undef True +#endif +#ifdef False +# undef False +#endif + +#include "DeviceCaps.h" +#include "Errors.h" +#include "Timer.h" + +#include "IUnityInterface.h" +#include "UnityGraphicsGLCoreES_Emulator.h" +#include "DiligentGraphicsAdapterGL.h" +#include "UnitySceneBase.h" +#include "StringTools.h" + +using namespace Diligent; + +#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB +# define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#endif + +#ifndef GLX_CONTEXT_MINOR_VERSION_ARB +# define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#endif + +#ifndef GLX_CONTEXT_FLAGS_ARB +# define GLX_CONTEXT_FLAGS_ARB 0x2094 +#endif + +#ifndef GLX_CONTEXT_DEBUG_BIT_ARB +# define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#endif + +typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); + +extern "C" +{ + void __attribute__((visibility("default"))) UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces); + void __attribute__((visibility("default"))) UNITY_INTERFACE_API UnityPluginUnload(); + UnityRenderingEvent __attribute__((visibility("default"))) UNITY_INTERFACE_API GetRenderEventFunc(); +} + +void* LoadPluginFunction(const char* FunctionName); + +bool LoadPlugin() +{ + // Do nothing. Android automagically sets function pointers + return true; +} + +void UnloadPlugin(UnityGraphicsEmulator *GraphicsEmulator) +{ + GraphicsEmulator->InvokeDeviceEventCallback(kUnityGfxDeviceEventShutdown); + UnityPluginUnload(); +} + + +int main (int argc, char ** argv) +{ + Display *display = XOpenDisplay(0); + + static int visual_attribs[] = + { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_DOUBLEBUFFER, true, + + // The largest available total RGBA color buffer size (sum of GLX_RED_SIZE, + // GLX_GREEN_SIZE, GLX_BLUE_SIZE, and GLX_ALPHA_SIZE) of at least the minimum + // size specified for each color component is preferred. + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + + // The largest available depth buffer of at least GLX_DEPTH_SIZE size is preferred + GLX_DEPTH_SIZE, 24, + + //GLX_SAMPLE_BUFFERS, 1, + GLX_SAMPLES, 1, + None + }; + + int fbcount = 0; + GLXFBConfig *fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount); + if (!fbc) + { + LOG_ERROR_MESSAGE("Failed to retrieve a framebuffer config"); + return -1; + } + + XVisualInfo *vi = glXGetVisualFromFBConfig(display, fbc[0]); + + XSetWindowAttributes swa; + swa.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone); + swa.border_pixel = 0; + swa.event_mask = + StructureNotifyMask | + ExposureMask | + KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + PointerMotionMask; + + Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, 1024, 768, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); + if (!win) + { + LOG_ERROR_MESSAGE("Failed to create window."); + return -1; + } + + XMapWindow(display, win); + + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr; + { + // Create an oldstyle context first, to get the correct function pointer for glXCreateContextAttribsARB + GLXContext ctx_old = glXCreateContext(display, vi, 0, GL_TRUE); + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + glXMakeCurrent(display, None, NULL); + glXDestroyContext(display, ctx_old); + } + + if (glXCreateContextAttribsARB == nullptr) + { + LOG_ERROR("glXCreateContextAttribsARB entry point not found. Aborting."); + return -1; + } + + int Flags = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; +#ifdef _DEBUG + Flags |= GLX_CONTEXT_DEBUG_BIT_ARB; +#endif + + int major_version = 4; + int minor_version = 3; + static int context_attribs[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, major_version, + GLX_CONTEXT_MINOR_VERSION_ARB, minor_version, + GLX_CONTEXT_FLAGS_ARB, Flags, + None + }; + + GLXContext ctx = glXCreateContextAttribsARB(display, fbc[0], NULL, true, context_attribs); + if (!ctx) + { + LOG_ERROR("Failed to create GL context."); + return -1; + } + XFree(fbc); + + glXMakeCurrent(display, win, ctx); + + auto &GraphicsGLCoreES_Emulator = UnityGraphicsGLCoreES_Emulator::GetInstance(); + GraphicsGLCoreES_Emulator.InitGLContext(reinterpret_cast<void*>(static_cast<size_t>(win)), display, major_version, minor_version); + + std::unique_ptr<DiligentGraphicsAdapter> pDiligentGraphics(new DiligentGraphicsAdapterGL(GraphicsGLCoreES_Emulator)); + UnityGraphicsEmulator *GraphicsEmulator = &GraphicsGLCoreES_Emulator; + + std::unique_ptr<UnitySceneBase> pScene(CreateScene()); + std::string Title = pScene->GetSceneName(); + pScene->SetDiligentGraphicsAdapter(pDiligentGraphics.get()); + pScene->OnGraphicsInitialized(); + //if (DevType == DeviceType::D3D12) + //{ + // UnityGraphicsD3D12Emulator::GetInstance().SetTransitionHandler(g_pScene->GetStateTransitionHandler()); + //} + + if (!LoadPlugin()) + { + return -1; + } + + pScene->OnPluginLoad(LoadPluginFunction); + UnityPluginLoad(&GraphicsEmulator->GeUnityInterfaces()); + + auto RenderEventFunc = GetRenderEventFunc(); + + Timer timer; + auto PrevTime = timer.GetElapsedTime(); + double filteredFrameTime = 0.0; + + while (true) + { + bool EscPressed = false; + XEvent xev; + // Handle all events in the queue + while(XCheckMaskEvent(display, 0xFFFFFFFF, &xev)) + { + switch(xev.type) + { + case KeyPress: + { + KeySym keysym; + char buffer[80]; + int num_char = XLookupString((XKeyEvent *)&xev, buffer, _countof(buffer), &keysym, 0); + EscPressed = (keysym==XK_Escape); + } + + case ConfigureNotify: + { + XConfigureEvent &xce = reinterpret_cast<XConfigureEvent &>(xev); + if(GraphicsEmulator) + { + pDiligentGraphics->PreSwapChainResize(); + GraphicsEmulator->ResizeSwapChain(static_cast<Uint32>(xce.width), static_cast<Uint32>(xce.height)); + pDiligentGraphics->PostSwapChainResize(); + pScene->OnWindowResize(static_cast<Uint32>(xce.width), static_cast<Uint32>(xce.height)); + } + break; + } + + default: + { + // if (pSample != nullptr ) + // pSample->HandleNativeMessage(&xev); + } + } + } + + if(EscPressed) + break; + + GraphicsEmulator->BeginFrame(); + pDiligentGraphics->BeginFrame(); + + auto CurrTime = timer.GetElapsedTime(); + auto ElapsedTime = CurrTime - PrevTime; + PrevTime = CurrTime; + + pScene->Render(RenderEventFunc, CurrTime, ElapsedTime); + + pDiligentGraphics->EndFrame(); + GraphicsEmulator->EndFrame(); + + GraphicsEmulator->Present(); + + double filterScale = 0.2; + filteredFrameTime = filteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime; + std::stringstream fpsCounterSS; + fpsCounterSS << " - " << std::fixed << std::setprecision(1) << filteredFrameTime * 1000; + fpsCounterSS << " ms (" << 1.0 / filteredFrameTime << " fps)"; + XStoreName(display, win, (Title + fpsCounterSS.str()).c_str()); + } + + pScene->OnPluginUnload(); + pScene.reset(); + UnloadPlugin(GraphicsEmulator); + + pDiligentGraphics.reset(); + GraphicsEmulator->Release(); + + ctx = glXGetCurrentContext(); + glXMakeCurrent(display, None, NULL); + glXDestroyContext(display, ctx); + XDestroyWindow(display, win); + XCloseDisplay(display); +} diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGLCoreES_Emulator.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsGLCoreES_Emulator.cpp index 5047b32..9f17ef1 100644 --- a/unityplugin/UnityEmulator/src/UnityGraphicsGLCoreES_Emulator.cpp +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGLCoreES_Emulator.cpp @@ -16,9 +16,18 @@ UnityGraphicsGLCoreES_Emulator::UnityGraphicsGLCoreES_Emulator() //GeUnityInterfaces().RegisterInterface(IUnityGraphicsGLCoreES__GUID, GetUnityGraphicsAPIInterface()); } -void UnityGraphicsGLCoreES_Emulator::InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion) +void UnityGraphicsGLCoreES_Emulator::InitGLContext(void *pNativeWndHandle, + #ifdef PLATFORM_LINUX + void *pDisplay, + #endif + +int MajorVersion, int MinorVersion) { - m_GraphicsImpl->InitGLContext(pNativeWndHandle, MajorVersion, MinorVersion); + m_GraphicsImpl->InitGLContext(pNativeWndHandle, + #ifdef PLATFORM_LINUX + pDisplay, + #endif + MajorVersion, MinorVersion); } UnityGraphicsGLCoreES_Emulator& UnityGraphicsGLCoreES_Emulator::GetInstance() diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.cpp index 0e8c542..59a3aa0 100644 --- a/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.cpp +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.cpp @@ -3,9 +3,14 @@ #if OPENGL_SUPPORTED +#include <iostream> #include "DebugUtilities.h" #include "Errors.h" +#ifndef APIENTRY +# define APIENTRY +#endif + void APIENTRY openglCallbackFunction( GLenum source, GLenum type, GLuint id, @@ -16,47 +21,54 @@ void APIENTRY openglCallbackFunction( GLenum source, { std::stringstream MessageSS; - MessageSS << std::endl << "OPENGL DEBUG MESSAGE: " << message << std::endl; - MessageSS << "Type: "; - switch( type ) { - case GL_DEBUG_TYPE_ERROR: - MessageSS << "ERROR"; - break; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - MessageSS << "DEPRECATED_BEHAVIOR"; - break; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - MessageSS << "UNDEFINED_BEHAVIOR"; - break; - case GL_DEBUG_TYPE_PORTABILITY: - MessageSS << "PORTABILITY"; - break; - case GL_DEBUG_TYPE_PERFORMANCE: - MessageSS << "PERFORMANCE"; - break; - case GL_DEBUG_TYPE_OTHER: - MessageSS << "OTHER"; - break; + MessageSS << "OpenGL debug message ("; + switch( type ) + { + case GL_DEBUG_TYPE_ERROR: + MessageSS << "ERROR"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + MessageSS << "DEPRECATED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + MessageSS << "UNDEFINED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_PORTABILITY: + MessageSS << "PORTABILITY"; + break; + case GL_DEBUG_TYPE_PERFORMANCE: + MessageSS << "PERFORMANCE"; + break; + case GL_DEBUG_TYPE_OTHER: + MessageSS << "OTHER"; + break; } - MessageSS << std::endl; - - MessageSS << "Severity: "; - switch( severity ){ - case GL_DEBUG_SEVERITY_LOW: - MessageSS << "LOW"; - break; - case GL_DEBUG_SEVERITY_MEDIUM: - MessageSS << "MEDIUM"; - break; - case GL_DEBUG_SEVERITY_HIGH: - MessageSS << "HIGH"; - break; + + switch( severity ) + { + case GL_DEBUG_SEVERITY_LOW: + MessageSS << ", low severity"; + break; + case GL_DEBUG_SEVERITY_MEDIUM: + MessageSS << ", medium severity"; + break; + case GL_DEBUG_SEVERITY_HIGH: + MessageSS << ", HIGH severity"; + break; + case GL_DEBUG_SEVERITY_NOTIFICATION: + MessageSS << ", notification"; + break; } - MessageSS << std::endl; - //MessageSS << "Id: "<< id << std::endl; + MessageSS << ")" << std::endl << message << std::endl; +#if defined(PLATFORM_WIN32) OutputDebugStringA( MessageSS.str().c_str() ); +#elif defined(PLATFORM_LINUX) + std::cout << MessageSS.str().c_str(); +#else +# error Unknown platform +#endif } @@ -64,13 +76,24 @@ UnityGraphicsGLCore_Impl::~UnityGraphicsGLCore_Impl() { if( m_Context ) { +#if defined(PLATFORM_WIN32) wglMakeCurrent( m_WindowHandleToDeviceContext, 0 ); wglDeleteContext( m_Context ); +#elif defined(PLATFORM_LINUX) + // Do nothing. Context is managed by the app +#else +# error Unknown platform +#endif } } -void UnityGraphicsGLCore_Impl::InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion ) +void UnityGraphicsGLCore_Impl::InitGLContext(void *pNativeWndHandle, + #ifdef PLATFORM_LINUX + void *pDisplay, + #endif + int MajorVersion, int MinorVersion ) { +#if defined(PLATFORM_WIN32) HWND hWnd = reinterpret_cast<HWND>(pNativeWndHandle); RECT rc; GetClientRect( hWnd, &rc ); @@ -143,7 +166,22 @@ void UnityGraphicsGLCore_Impl::InitGLContext(void *pNativeWndHandle, int MajorVe { //It's not possible to make a GL 3.x context. Use the old style context (GL 2.1 and before) m_Context = tempContext; } - +#elif defined(PLATFORM_LINUX) + m_LinuxWindow = static_cast<Window>(reinterpret_cast<size_t>(pNativeWndHandle)); + m_Display = reinterpret_cast<Display*>(pDisplay); + m_Context = glXGetCurrentContext(); + if(m_Context == nullptr) + LOG_ERROR_AND_THROW( "No active GL context found" ); + + // Initialize GLEW + GLenum err = glewInit(); + if( GLEW_OK != err ) + LOG_ERROR_AND_THROW( "Failed to initialize GLEW" ); + +#else +# error Unsupported platform +#endif + //Checking GL version const GLubyte *GLVersionString = glGetString( GL_VERSION ); @@ -183,7 +221,13 @@ void UnityGraphicsGLCore_Impl::ResizeSwapchain(int NewWidth, int NewHeight) void UnityGraphicsGLCore_Impl::SwapBuffers() { +#if defined(PLATFORM_WIN32) ::SwapBuffers( m_WindowHandleToDeviceContext ); +#elif defined(PLATFORM_LINUX) + glXSwapBuffers(m_Display, m_LinuxWindow); +#else +# error Unsupported platform +#endif } #endif // OPENGL_SUPPORTED
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.h b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.h index 293f21d..31ec7ba 100644 --- a/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.h +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.h @@ -24,17 +24,50 @@ # endif # include "GL/glew.h" +# include <GL/glx.h> + +// Undefine beautiful defines from GL/glx.h -> X11/Xlib.h +# ifdef Bool +# undef Bool +# endif +# ifdef True +# undef True +# endif +# ifdef False +# undef False +# endif +# ifdef Status +# undef Status +# endif +# ifdef Success +# undef Success +# endif #else + # error Unsupported platform + #endif class UnityGraphicsGLCore_Impl { public: + +#if defined(PLATFORM_WIN32) + typedef HGLRC NativeGLContextType; +#elif defined(PLATFORM_LINUX) + typedef GLXContext NativeGLContextType; +#else +# error Unsupported platform +#endif + ~UnityGraphicsGLCore_Impl(); - void InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion); + void InitGLContext(void *pNativeWndHandle, + #ifdef PLATFORM_LINUX + void *pDisplay, + #endif + int MajorVersion, int MinorVersion); void ResizeSwapchain(int NewWidth, int NewHeight); @@ -44,13 +77,21 @@ public: int GetBackBufferHeight()const { return m_BackBufferHeight; } GLenum GetBackBufferFormat()const { return GL_RGBA8; } GLenum GetDepthBufferFormat()const { return GL_DEPTH_COMPONENT32F; } - HGLRC GetContext() { return m_Context; } + NativeGLContextType GetContext() { return m_Context; } private: int m_BackBufferWidth = 0; int m_BackBufferHeight = 0; + +#if defined(PLATFORM_WIN32) HDC m_WindowHandleToDeviceContext; - HGLRC m_Context; +#elif defined(PLATFORM_LINUX) + Window m_LinuxWindow; + Display *m_Display; +#else +# error Unsupported platform +#endif + NativeGLContextType m_Context; }; #endif //OPENGL_SUPPORTED diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGL_Impl.h b/unityplugin/UnityEmulator/src/UnityGraphicsGL_Impl.h index 3d33a8c..e636fc8 100644 --- a/unityplugin/UnityEmulator/src/UnityGraphicsGL_Impl.h +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGL_Impl.h @@ -4,7 +4,7 @@ #if defined(PLATFORM_ANDROID) # include "Android/UnityGraphicsGLESAndroid_Impl.h" -#elif defined( PLATFORM_WIN32 ) || defined( PLATFORM_UNIVERSAL_WINDOWS ) +#elif defined(PLATFORM_WIN32) || defined(PLATFORM_UNIVERSAL_WINDOWS) || defined(PLATFORM_LINUX) # include "UnityGraphicsGLCore_Impl.h" #else # error Unknown Platform |
