├── .clang-format ├── CMakeLists.txt ├── docs └── design-decisions.md ├── license.md ├── readme.md └── src └── CrossWindow ├── Graphics.h └── Graphics ├── DirectX11.h ├── DirectX12.h ├── Metal.h ├── OpenGL.h ├── Vulkan.h └── WebGPU.h /.clang-format: -------------------------------------------------------------------------------- 1 | # Run manually to reformat a file: 2 | # clang-format -i --style=file 3 | BasedOnStyle: llvm 4 | DerivePointerAlignment: false 5 | UseTab: Never 6 | AllowShortIfStatementsOnASingleLine: true 7 | IndentWidth: 4 8 | TabWidth: 4 9 | BreakBeforeBraces: Allman 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | Cpp11BracedListStyle: true 13 | IndentWrappedFunctionNames: true 14 | PointerAlignment: Left 15 | FixNamespaceComments: false -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project Info 2 | 3 | cmake_minimum_required(VERSION 3.6 FATAL_ERROR) 4 | cmake_policy(VERSION 3.6) 5 | project(CrossWindowGraphics 6 | VERSION 1.0.0.0 7 | LANGUAGES C CXX 8 | ) 9 | 10 | # ============================================================= 11 | 12 | # Options 13 | 14 | set(XGFX_API VULKAN CACHE STRING "The graphics API you're targeting, defaults to VULKAN, can be VULKAN, DIRECTX12, METAL, DIRECTX11, OPENGL, or NONE.") 15 | set_property( 16 | CACHE 17 | XGFX_API PROPERTY 18 | STRINGS VULKAN OPENGL DIRECTX12 DIRECTX11 METAL 19 | ) 20 | 21 | if(XGFX_API STREQUAL "DIRECTX12") 22 | set(XGFX_API_PATH "DirectX 12") 23 | elseif(XGFX_API STREQUAL "VULKAN") 24 | set(XGFX_API_PATH "Vulkan") 25 | elseif(XGFX_API STREQUAL "METAL") 26 | set(XGFX_API_PATH "Metal") 27 | elseif(XGFX_API STREQUAL "DIRECTX11") 28 | set(XGFX_API_PATH "DirectX 11") 29 | elseif(XGFX_API STREQUAL "OPENGL") 30 | set(XGFX_API_PATH "OpenGL") 31 | elseif(XGFX_API STREQUAL "NONE") 32 | set(XGFX_API_PATH "None") 33 | else() 34 | message( SEND_ERROR "XGFX_API can only be either VULKAN, DIRECTX12, METAL, DIRECTX11, OPENGL, or NONE..") 35 | endif() 36 | 37 | # ============================================================= 38 | 39 | # Finalize Library 40 | 41 | add_library(CrossWindowGraphics INTERFACE) 42 | 43 | target_include_directories( 44 | CrossWindowGraphics INTERFACE 45 | ${CMAKE_CURRENT_SOURCE_DIR}/src 46 | ) 47 | 48 | if(NOT( XGFX_API STREQUAL "NONE" )) 49 | message( STATUS "Using the " ${XGFX_API_PATH} " graphics API with CrossWindow") 50 | target_compile_definitions(CrossWindowGraphics INTERFACE XGFX_${XGFX_API}=1) 51 | else() 52 | message( STATUS "Not adding preprocessor definitions to CrossWindowGraphics") 53 | endif() 54 | 55 | -------------------------------------------------------------------------------- /docs/design-decisions.md: -------------------------------------------------------------------------------- 1 | ## Why Vulkan AND OpenGL/DirectX/Metal? Why not separate libraries for each? 2 | 3 | Since CrossWindow is a cross platform windowing abstraction layer that targets all operating systems, it would be be fair to accompany such a library with a helper library for all graphics APIs, rather than one for DirectX, one for Vulkan, one for OpenGL, etc. 4 | 5 | > In the JavaScript world, [Babel](https://babeljs.io/), a library to compile new JavaScript to older JavaScript for compatibility, underwent a major shift in version 6 where the library author split the library up into multiple libraries. This decision was met with a lot of push back but ultimately stuck. 6 | 7 | It's hard to set the limits of a library, but if connecting an individual graphics library to CrossWindow becomes too complex, perhaps separating this library to `CrossWindow-Vulkan`, `CrossWindow-DirectX`, etc. would be a good idea, especially if the library grows to support more graphics API versions, rather than the latest version of each library at the time this was written. 8 | 9 | If that's the case this library could just compose each of those individual libraries for compatibility/ease of use. -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alain Galvan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # CrossWindow-Graphics 2 | 3 | [![cmake-img]][cmake-url] 4 | [![License][license-img]][license-url] 5 | 6 | A header only library to simplify creating and managing data structures needed for graphics APIs such as a Vulkan `vk::Surface`, an OpenGL context, a DirectX `IDXGISwapChain1`, or Metal `CAMetalLayer`. 7 | 8 | ## Supports 9 | 10 | - 🌋 Vulkan 11 | - ⚪ OpenGL 12 | - ⚪ OpenGL ES 13 | - 🌐 WebGL 14 | - ❎ DirectX 12.x 15 | - ✖️ DirectX 11.x 16 | - 🤖 Metal 17 | 18 | ## Installation 19 | 20 | First add the repo as a submodule in your dependencies folder such as `external/`: 21 | 22 | ```bash 23 | cd external 24 | git submodule add https://github.com/alaingalvan/crosswindow-graphics.git 25 | ``` 26 | 27 | Then in your `CMakeLists.txt` file, include the following: 28 | 29 | ```cmake 30 | add_subdirectory(external/crosswindow-graphics) 31 | 32 | target_link_libraries( 33 | ${PROJECT_NAME} 34 | CrossWindowGraphics 35 | ) 36 | ``` 37 | 38 | ## Usage 39 | 40 | ```cpp 41 | #include "CrossWindow/CrossWindow.h" 42 | #include "CrossWindow/Graphics.h" 43 | 44 | void xmain(int argc, char** argv) 45 | { 46 | // 🖼️ Create your xwin::Window... 47 | xwin::Window window; 48 | 49 | // ... 50 | 51 | #if defined(XGFX_VULKAN) 52 | 53 | // 🌋 Vulkan Surface 54 | vk::Surface surface = xwin::createSurface(&window, instance); 55 | 56 | #elif defined(XGFX_OPENGL) 57 | 58 | // ⚪ OpenGL / OpenGL ES / 🌐 WebGL platform specific context data 59 | xgfx::OpenGLDesc desc; 60 | xgfx::OpenGLState state = xgfx::createContext(&window, desc); 61 | 62 | // ⬇️ Set the context 63 | xgfx::setContext(state); 64 | 65 | // 🔀 Refresh your window 66 | xgfx::swapBuffers(state); 67 | 68 | // ⬆️ Unset the context 69 | xgfx::unsetContext(state); 70 | 71 | // ⬅️ Destroy the context 72 | xgfx::destroyContext(state); 73 | 74 | #elif defined(XGFX_DIRECTX12) 75 | 76 | // ❎ DirectX 12.x Swapchain 77 | IDXGISwapChain1* swapchain = xgfx::createSwapchain(window, factory, commandQueue, &swapchainDesc); 78 | 79 | #elif defined(XGFX_DIRECTX11) 80 | 81 | // ✖️ DirectX 11.x Swapchain 82 | IDXGISwapChain* swapchain = xgfx::createSwapchain(window, factory, device, &swapchainDesc); 83 | 84 | #elif defined(XWIN_METAL) 85 | 86 | // 🤖 Metal Layer 87 | xgfx::createMetalLayer(&window); 88 | 89 | // 🍮 Access the layer from your window 90 | CAMetalLayer* layer = (CAMetalLayer*)window.layer; 91 | 92 | #endif 93 | } 94 | 95 | ``` 96 | 97 | ### Preprocessor Definitions 98 | 99 | | CMake Options | Description | 100 | |:-------------:|:-----------:| 101 | | `XGFX_API` | The graphics API you're targeting, defaults to `VULKAN`, can be can be `VULKAN`, `OPENGL`, `DIRECTX12`, `METAL`, or `NONE`. | 102 | 103 | Alternatively you can set the following preprocessor definitions manually: 104 | 105 | | Definition | Description | 106 | |:-------------:|:-----------:| 107 | | `XGFX_VULKAN` | Vulkan | 108 | | `XGFX_OPENGL` | OpenGL / OpenGL ES / WebGL | 109 | | `XGFX_DIRECTX12` | DirectX 12.x | 110 | | `XGFX_DIRECTX11` | DirectX 11.x | 111 | | `XGFX_METAL` | Metal | 112 | 113 | ## Design Decisions 114 | 115 | The official Khronos Group's Vulkan Samples features an [OpenGL driver info example](https://github.com/KhronosGroup/Vulkan-Samples/blob/master/samples/apps/driverinfo/driverinfo_opengl.c) and [Vulkan cube example](https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/demos/cube.c) that the OpenGL/Vulkan portions of this library pull heavily from, but diverges with the decision to separate operating systems by protocol (similar to the design of CrossWindow). 116 | 117 | You can read more [in our docs](docs/design-decisions.md). 118 | 119 | ## License 120 | 121 | CrossWindow is licensed as either **MIT** or **Apache-2.0**, whichever you would prefer. 122 | 123 | [cmake-img]: https://img.shields.io/badge/cmake-3.6-1f9948.svg?style=flat-square 124 | [cmake-url]: https://cmake.org/ 125 | [license-img]: https://img.shields.io/:license-mit-blue.svg?style=flat-square 126 | [license-url]: https://opensource.org/licenses/MIT 127 | -------------------------------------------------------------------------------- /src/CrossWindow/Graphics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if !defined(XGFX_VULKAN) && !defined(XGFX_OPENGL) && \ 4 | !defined(XGFX_DIRECTX12) && !defined(XGFX_DIRECTX11) && \ 5 | !defined(XGFX_METAL) 6 | #error \ 7 | "Define either XGFX_VULKAN, XGFX_OPENGL, XGFX_DIRECTX12, XGFX_DIRECTX11, and/or XGFX_METAL before #include \"CrossWindow/Graphics.h\"" 8 | #endif 9 | 10 | #include "Graphics/DirectX11.h" 11 | #include "Graphics/DirectX12.h" 12 | #include "Graphics/Metal.h" 13 | #include "Graphics/OpenGL.h" 14 | #include "Graphics/Vulkan.h" -------------------------------------------------------------------------------- /src/CrossWindow/Graphics/DirectX11.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if (defined(XWIN_WIN32) || defined(XWIN_UWP)) && defined(XGFX_DIRECTX11) 4 | 5 | #include "d3d11.h" 6 | #include 7 | #include 8 | 9 | #pragma comment(lib, "d3d11.lib") 10 | #pragma comment(lib, "dxgi.lib") 11 | #pragma comment(lib, "dxguid.lib") 12 | #pragma comment(lib, "d3dcompiler.lib") 13 | 14 | namespace xgfx 15 | { 16 | inline IDXGISwapChain* createSwapchain(xwin::Window* window, 17 | IDXGIFactory* factory, 18 | ID3D11Device* device, 19 | DXGI_SWAP_CHAIN_DESC* swapchainDesc) 20 | { 21 | xwin::WindowDesc desc = window->getDesc(); 22 | 23 | swapchainDesc->OutputWindow = window->getHwnd(); 24 | swapchainDesc->Windowed = !desc.fullscreen; 25 | 26 | IDXGISwapChain* swapchain = nullptr; 27 | HRESULT hr = factory->CreateSwapChain(device, swapchainDesc, &swapchain); 28 | 29 | if (!FAILED(hr)) 30 | { 31 | return swapchain; 32 | } 33 | 34 | return nullptr; 35 | } 36 | } 37 | #endif -------------------------------------------------------------------------------- /src/CrossWindow/Graphics/DirectX12.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if (defined(XWIN_WIN32) || defined(XWIN_UWP)) && defined(XGFX_DIRECTX12) 4 | 5 | #include "d3d12.h" 6 | #include 7 | 8 | #pragma comment(lib, "d3d12.lib") 9 | #pragma comment(lib, "dxgi.lib") 10 | #pragma comment(lib, "dxguid.lib") 11 | 12 | namespace xgfx 13 | { 14 | inline IDXGISwapChain1* 15 | createSwapchain(xwin::Window* window, IDXGIFactory4* factory, 16 | ID3D12CommandQueue* queue, 17 | DXGI_SWAP_CHAIN_DESC1* swapchainDesc, 18 | DXGI_SWAP_CHAIN_FULLSCREEN_DESC* fullscreenDesc = nullptr, 19 | IDXGIOutput* output = nullptr) 20 | { 21 | IDXGISwapChain1* swapchain = nullptr; 22 | HRESULT hr = factory->CreateSwapChainForHwnd( 23 | queue, window->getHwnd(), swapchainDesc, fullscreenDesc, output, &swapchain); 24 | 25 | if (!FAILED(hr)) 26 | { 27 | return swapchain; 28 | } 29 | 30 | return nullptr; 31 | } 32 | } 33 | #endif -------------------------------------------------------------------------------- /src/CrossWindow/Graphics/Metal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(XGFX_METAL) && (defined(XWIN_COCOA) || defined(XWIN_UIKIT)) 4 | 5 | namespace xgfx 6 | { 7 | inline void createMetalLayer(xwin::Window* window) 8 | { 9 | window->setLayer(xwin::Window::LayerType::Metal); 10 | } 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /src/CrossWindow/Graphics/OpenGL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(XGFX_OPENGL) 4 | 5 | #if defined(XWIN_WIN32) 6 | #pragma comment(lib, "opengl32.lib") 7 | #if !defined(OPENGL_VERSION_MAJOR) 8 | #define OPENGL_VERSION_MAJOR 4 9 | #endif 10 | #if !defined(OPENGL_VERSION_MINOR) 11 | #define OPENGL_VERSION_MINOR 5 12 | #endif 13 | #include 14 | #include 15 | #define GL_EXT_color_subtable 16 | #include 17 | #include 18 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 19 | // Apple is still at OpenGL 4.1 20 | #define OPENGL_VERSION_MAJOR 4 21 | #define OPENGL_VERSION_MINOR 1 22 | #include 23 | #define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED 24 | #include 25 | #ifndef __gl_h_ 26 | #define __gl_h_ 27 | 28 | #endif 29 | #ifndef __gl3_h_ 30 | #define __gl3_h_ 31 | #include 32 | #include 33 | #endif 34 | 35 | #elif defined(XWIN_XCB) || defined(XWIN_XLIB) 36 | #define OPENGL_VERSION_MAJOR 4 37 | #define OPENGL_VERSION_MINOR 3 38 | #elif defined(XWIN_XLIB) 39 | #include 40 | #include 41 | #include // for resolution changes 42 | #include // for fullscreen video mode 43 | #elif defined(XWIN_XCB) 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #elif defined(XWIN_ANDROID) 53 | #define OPENGL_VERSION_MAJOR 3 54 | #define OPENGL_VERSION_MINOR 1 55 | #include 56 | #include 57 | #include 58 | #include 59 | #if OPENGL_VERSION_MAJOR == 3 && OPENGL_VERSION_MINOR == 1 60 | #include 61 | #endif 62 | #include 63 | #elif defined(XWIN_WASM) 64 | #include 65 | #endif 66 | 67 | namespace xgfx 68 | { 69 | 70 | #if defined(XWIN_WIN32) 71 | inline PROC GetExtension(const char* functionName) 72 | { 73 | return wglGetProcAddress(functionName); 74 | } 75 | #elif defined(XWIN_XCB) || defined(XWIN_XLIB) || defined(XWIN_WAYLAND) || \ 76 | defined(XWIN_MIR) 77 | void (*GetExtension(const char* functionName))() 78 | { 79 | return glXGetProcAddress((const GLubyte*)functionName); 80 | } 81 | #endif 82 | 83 | #if !defined(GL_SR8_EXT) 84 | #define GL_SR8_EXT 0x8FBD 85 | #endif 86 | #if !defined(GL_SRG8_EXT) 87 | #define GL_SRG8_EXT 0x8FBE 88 | #endif 89 | #if !defined(EGL_OPENGL_ES3_BIT) 90 | #define EGL_OPENGL_ES3_BIT 0x0040 91 | #endif 92 | 93 | // Cross Platform OpenGL Context State 94 | struct OpenGLState 95 | { 96 | #if defined(XWIN_WIN32) 97 | HWND hwnd; 98 | HDC hdc; 99 | HGLRC hglrc; 100 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 101 | CGLContextObj cglContext; 102 | #elif defined(XWIN_XCB) 103 | Display* display; 104 | uint32_t screen; 105 | xcb_connection_t* connection; 106 | xcb_glx_fbconfig_t fbconfigid; 107 | xcb_visualid_t visualid; 108 | xcb_glx_drawable_t glxDrawable; 109 | xcb_glx_context_t glxContext; 110 | xcb_glx_context_tag_t glxContextTag; 111 | #elif defined(XWIN_XLIB) 112 | Display* display; 113 | int screen; 114 | uint32_t visualid; 115 | GLXFBConfig glxFBConfig; 116 | GLXDrawable glxDrawable; 117 | GLXContext glxContext; 118 | #elif defined(XWIN_ANDROID) 119 | EGLDisplay display; 120 | EGLConfig config; 121 | EGLSurface mainSurface; 122 | EGLContext context; 123 | EGLNativeWindowType hWnd; 124 | EGLContext eglContext; 125 | #elif defined(XWIN_WASM) 126 | EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context; 127 | #endif 128 | }; 129 | 130 | // OpenGL context initialization data 131 | struct OpenGLDesc 132 | { 133 | int pixelFormat; 134 | }; 135 | 136 | inline OpenGLState createContext(xwin::Window* window, const OpenGLDesc& desc) 137 | { 138 | const xwin::XWinState& xwinState = xwin::getXWinState(); 139 | 140 | OpenGLState state; 141 | 142 | #if defined(XWIN_WIN32) 143 | state.hwnd = window->getHwnd(); 144 | 145 | state.hdc = GetDC(state.hwnd); 146 | 147 | if (!state.hdc) 148 | { 149 | // Failed to acquire device context. 150 | return state; 151 | } 152 | 153 | PIXELFORMATDESCRIPTOR pfd = { 154 | sizeof(PIXELFORMATDESCRIPTOR), 155 | 1, // version 156 | PFD_DRAW_TO_WINDOW | // must support windowed 157 | PFD_SUPPORT_OPENGL | // must support OpenGL 158 | PFD_DOUBLEBUFFER, // must support double buffering 159 | PFD_TYPE_RGBA, // iPixelType 160 | 32, // cColorBits 161 | 0, 162 | 0, // cRedBits, cRedShift 163 | 0, 164 | 0, // cGreenBits, cGreenShift 165 | 0, 166 | 0, // cBlueBits, cBlueShift 167 | 0, 168 | 0, // cAlphaBits, cAlphaShift 169 | 0, // cAccumBits 170 | 0, // cAccumRedBits 171 | 0, // cAccumGreenBits 172 | 0, // cAccumBlueBits 173 | 0, // cAccumAlphaBits 174 | 0, // cDepthBits 175 | 0, // cStencilBits 176 | 0, // cAuxBuffers 177 | PFD_MAIN_PLANE, // iLayerType 178 | 0, // bReserved 179 | 0, // dwLayerMask 180 | 0, // dwVisibleMask 181 | 0 // dwDamageMask 182 | }; 183 | 184 | int pixelFormat = ChoosePixelFormat(state.hdc, &pfd); 185 | if (pixelFormat == 0) 186 | { 187 | // Failed to find a suitable PixelFormat. 188 | return state; 189 | } 190 | 191 | if (!SetPixelFormat(state.hdc, pixelFormat, &pfd)) 192 | { 193 | // Failed to set the PixelFormat. 194 | return state; 195 | } 196 | 197 | // Now that the pixel format is set, create a temporary context to get the 198 | // extensions. 199 | PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; 200 | { 201 | HGLRC hglrc = wglCreateContext(state.hdc); 202 | wglMakeCurrent(state.hdc, hglrc); 203 | 204 | wglCreateContextAttribsARB = 205 | (PFNWGLCREATECONTEXTATTRIBSARBPROC)GetExtension( 206 | "wglCreateContextAttribsARB"); 207 | 208 | wglMakeCurrent(NULL, NULL); 209 | wglDeleteContext(hglrc); 210 | } 211 | 212 | int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 213 | OPENGL_VERSION_MAJOR, 214 | WGL_CONTEXT_MINOR_VERSION_ARB, 215 | OPENGL_VERSION_MINOR, 216 | WGL_CONTEXT_PROFILE_MASK_ARB, 217 | WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 218 | WGL_CONTEXT_FLAGS_ARB, 219 | WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 220 | 0}; 221 | 222 | state.hglrc = wglCreateContextAttribsARB(state.hdc, NULL, attribs); 223 | if (!state.hglrc) 224 | { 225 | // Failed to create GL context. 226 | return state; 227 | } 228 | 229 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 230 | // Set Window layer 231 | NSOpenGLView* glView = nil; 232 | NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { 233 | NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, 234 | NSOpenGLPFAColorSize , 24 , 235 | NSOpenGLPFAAlphaSize , 8 , 236 | NSOpenGLPFADoubleBuffer , 237 | NSOpenGLPFAAccelerated , 238 | NSOpenGLPFANoRecovery , 239 | 0 240 | }; 241 | NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc]initWithAttributes:pixelFormatAttributes]; 242 | 243 | glView = [[NSOpenGLView alloc]initWithFrame:NSMakeRect(0, 0, 640, 640) pixelFormat:format]; 244 | //Set context and attach it to the window 245 | [[glView openGLContext]makeCurrentContext]; 246 | 247 | //finishing off 248 | [((NSWindow*)window->window) setContentView:glView]; 249 | [glView prepareOpenGL]; 250 | state.cglContext = [[glView openGLContext] CGLContextObj]; 251 | #elif defined(XWIN_XCB) 252 | const char* displayName = NULL; 253 | state.display = XOpenDisplay(displayName); 254 | if (!state.display) 255 | { 256 | // Unable to open X Display."); 257 | return state; 258 | } 259 | state.screen = 0; 260 | state.connection = xcb_connect(displayName, &state.screen); 261 | if (xcb_connection_has_error(state.connection)) 262 | { 263 | // Failed to open XCB connection."); 264 | return state; 265 | } 266 | 267 | xcb_glx_query_version_cookie_t glx_query_version_cookie = 268 | xcb_glx_query_version(state.connection, OPENGL_VERSION_MAJOR, 269 | OPENGL_VERSION_MINOR); 270 | xcb_glx_query_version_reply_t* glx_query_version_reply = 271 | xcb_glx_query_version_reply(state.connection, glx_query_version_cookie, 272 | NULL); 273 | if (glx_query_version_reply == NULL) 274 | { 275 | // Unable to retrieve GLX version."); 276 | return state; 277 | } 278 | free(glx_query_version_reply); 279 | 280 | xcb_glx_get_fb_configs_cookie_t get_fb_configs_cookie = 281 | xcb_glx_get_fb_configs(state.connection, state.screen); 282 | xcb_glx_get_fb_configs_reply_t* get_fb_configs_reply = 283 | xcb_glx_get_fb_configs_reply(state.connection, get_fb_configs_cookie, 284 | NULL); 285 | 286 | if (get_fb_configs_reply == NULL || 287 | get_fb_configs_reply->num_FB_configs == 0) 288 | { 289 | // No valid framebuffer configurations found."); 290 | return state; 291 | } 292 | 293 | const GpuSurfaceBits_t bits = 294 | ksGpuContext_BitsForSurfaceFormat(colorFormat, depthFormat); 295 | 296 | const uint32_t* fb_configs_properties = 297 | xcb_glx_get_fb_configs_property_list(get_fb_configs_reply); 298 | const uint32_t fb_configs_num_properties = 299 | get_fb_configs_reply->num_properties; 300 | 301 | bool foundFbConfig = false; 302 | for (int i = 0; i < get_fb_configs_reply->num_FB_configs; i++) 303 | { 304 | const uint32_t* fb_config = 305 | fb_configs_properties + i * fb_configs_num_properties * 2; 306 | 307 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 308 | GLX_FBCONFIG_ID) == 0) 309 | { 310 | continue; 311 | } 312 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 313 | GLX_VISUAL_ID) == 0) 314 | { 315 | continue; 316 | } 317 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 318 | GLX_DOUBLEBUFFER) == 0) 319 | { 320 | continue; 321 | } 322 | if ((xcb_glx_get_property(fb_config, fb_configs_num_properties, 323 | GLX_RENDER_TYPE) & 324 | GLX_RGBA_BIT) == 0) 325 | { 326 | continue; 327 | } 328 | if ((xcb_glx_get_property(fb_config, fb_configs_num_properties, 329 | GLX_DRAWABLE_TYPE) & 330 | GLX_WINDOW_BIT) == 0) 331 | { 332 | continue; 333 | } 334 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 335 | GLX_RED_SIZE) != bits.redBits) 336 | { 337 | continue; 338 | } 339 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 340 | GLX_GREEN_SIZE) != bits.greenBits) 341 | { 342 | continue; 343 | } 344 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 345 | GLX_BLUE_SIZE) != bits.blueBits) 346 | { 347 | continue; 348 | } 349 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 350 | GLX_ALPHA_SIZE) != bits.alphaBits) 351 | { 352 | continue; 353 | } 354 | if (xcb_glx_get_property(fb_config, fb_configs_num_properties, 355 | GLX_DEPTH_SIZE) != bits.depthBits) 356 | { 357 | continue; 358 | } 359 | 360 | state.fbconfigid = xcb_glx_get_property( 361 | fb_config, fb_configs_num_properties, GLX_FBCONFIG_ID); 362 | state.visualid = xcb_glx_get_property( 363 | fb_config, fb_configs_num_properties, GLX_VISUAL_ID); 364 | foundFbConfig = true; 365 | break; 366 | } 367 | 368 | free(get_fb_configs_reply); 369 | 370 | if (!foundFbConfig) 371 | { 372 | // Failed to to find desired framebuffer configuration."); 373 | return state; 374 | } 375 | 376 | state.connection = connection; 377 | 378 | // Create the context. 379 | uint32_t attribs[] = {GLX_CONTEXT_MAJOR_VERSION_ARB, 380 | OPENGL_VERSION_MAJOR, 381 | GLX_CONTEXT_MINOR_VERSION_ARB, 382 | OPENGL_VERSION_MINOR, 383 | GLX_CONTEXT_PROFILE_MASK_ARB, 384 | GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 385 | GLX_CONTEXT_FLAGS_ARB, 386 | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 387 | 0}; 388 | 389 | state.glxContext = xcb_generate_id(state.connection); 390 | xcb_glx_create_context_attribs_arb( 391 | state.connection, // xcb_connection_t * connection 392 | state.glxContext, // xcb_glx_context_t context 393 | state.fbconfigid, // xcb_glx_fbconfig_t fbconfig 394 | state.screen, // uint32_t screen 395 | 0, // xcb_glx_context_t share_list 396 | 1, // uint8_t is_direct 397 | 4, // uint32_t num_attribs 398 | attribs); // const uint32_t * attribs 399 | 400 | // Make sure the context is direct. 401 | xcb_generic_error_t* error; 402 | xcb_glx_is_direct_cookie_t glx_is_direct_cookie = 403 | xcb_glx_is_direct_unchecked(state.connection, state.glxContext); 404 | xcb_glx_is_direct_reply_t* glx_is_direct_reply = 405 | xcb_glx_is_direct_reply(state.connection, glx_is_direct_cookie, &error); 406 | const bool is_direct = 407 | (glx_is_direct_reply != NULL && glx_is_direct_reply->is_direct); 408 | free(glx_is_direct_reply); 409 | 410 | if (!is_direct) 411 | { 412 | // Unable to create direct rendering context."); 413 | return state; 414 | } 415 | 416 | #elif defined(XWIN_XLIB) 417 | 418 | const char* displayName = NULL; 419 | state.display = XOpenDisplay(displayName); 420 | if (!state.display) 421 | { 422 | // Unable to open X Display."); 423 | return state; 424 | } 425 | state.screen = XDefaultScreen(state.display); 426 | 427 | int glxErrorBase; 428 | int glxEventBase; 429 | if (!glXQueryExtension(state.display, &glxErrorBase, &glxEventBase)) 430 | { 431 | // X display does not support the GLX extension."); 432 | return state; 433 | } 434 | 435 | int glxVersionMajor; 436 | int glxVersionMinor; 437 | if (!glXQueryVersion(state.display, &glxVersionMajor, &glxVersionMinor)) 438 | { 439 | // Unable to retrieve GLX version."); 440 | return state; 441 | } 442 | 443 | int fbConfigCount = 0; 444 | GLXFBConfig* fbConfigs = 445 | glXGetFBConfigs(state.display, state.screen, &fbConfigCount); 446 | if (fbConfigCount == 0) 447 | { 448 | // No valid framebuffer configurations found."); 449 | return state; 450 | } 451 | 452 | bool foundFbConfig = false; 453 | for (int i = 0; i < fbConfigCount; i++) 454 | { 455 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], 456 | GLX_FBCONFIG_ID) == 0) 457 | { 458 | continue; 459 | } 460 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], GLX_VISUAL_ID) == 461 | 0) 462 | { 463 | continue; 464 | } 465 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], 466 | GLX_DOUBLEBUFFER) == 0) 467 | { 468 | continue; 469 | } 470 | if ((glxGetFBConfigAttrib2(state.display, fbConfigs[i], 471 | GLX_RENDER_TYPE) & 472 | GLX_RGBA_BIT) == 0) 473 | { 474 | continue; 475 | } 476 | if ((glxGetFBConfigAttrib2(state.display, fbConfigs[i], 477 | GLX_DRAWABLE_TYPE) & 478 | GLX_WINDOW_BIT) == 0) 479 | { 480 | continue; 481 | } 482 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], GLX_RED_SIZE) != 483 | 8) 484 | { 485 | continue; 486 | } 487 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], 488 | GLX_GREEN_SIZE) != 8) 489 | { 490 | continue; 491 | } 492 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], GLX_BLUE_SIZE) != 493 | 8) 494 | { 495 | continue; 496 | } 497 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], 498 | GLX_ALPHA_SIZE) != 8) 499 | { 500 | continue; 501 | } 502 | if (glxGetFBConfigAttrib2(state.display, fbConfigs[i], 503 | GLX_DEPTH_SIZE) != 0) 504 | { 505 | continue; 506 | } 507 | 508 | state.visualid = 509 | glxGetFBConfigAttrib2(state.display, fbConfigs[i], GLX_VISUAL_ID); 510 | state.glxFBConfig = fbConfigs[i]; 511 | foundFbConfig = true; 512 | break; 513 | } 514 | 515 | XFree(fbConfigs); 516 | 517 | if (!foundFbConfig) 518 | { 519 | // Failed to to find desired framebuffer configuration."); 520 | return state; 521 | } 522 | 523 | PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = 524 | (PFNGLXCREATECONTEXTATTRIBSARBPROC)GetExtension( 525 | "glXCreateContextAttribsARB"); 526 | 527 | int attribs[] = {GLX_CONTEXT_MAJOR_VERSION_ARB, 528 | OPENGL_VERSION_MAJOR, 529 | GLX_CONTEXT_MINOR_VERSION_ARB, 530 | OPENGL_VERSION_MINOR, 531 | GLX_CONTEXT_PROFILE_MASK_ARB, 532 | GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 533 | GLX_CONTEXT_FLAGS_ARB, 534 | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 535 | 0}; 536 | 537 | state.glxContext = 538 | glXCreateContextAttribsARB(state.display, // Display * dpy 539 | state.glxFBConfig, // GLXFBConfig config 540 | NULL, // GLXContext share_context 541 | True, // Bool direct 542 | attribs); // const int * attrib_list 543 | 544 | if (stateglxContext == NULL) 545 | { 546 | // Unable to create GLX context."); 547 | return state; 548 | } 549 | 550 | if (!glXIsDirect(statedisplay, stateglxContext)) 551 | { 552 | // Unable to create direct rendering context."); 553 | return state; 554 | } 555 | #elif defined(XWIN_ANDROID) 556 | 557 | EGLint majorVersion = OPENGL_VERSION_MAJOR; 558 | EGLint minorVersion = OPENGL_VERSION_MINOR; 559 | 560 | state.display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 561 | EGL(eglInitialize(state.display, &majorVersion, &minorVersion)); 562 | 563 | const int MAX_CONFIGS = 1024; 564 | EGLConfig configs[MAX_CONFIGS]; 565 | EGLint numConfigs = 0; 566 | EGL(eglGetConfigs(state.display, configs, MAX_CONFIGS, &numConfigs)); 567 | 568 | const EGLint configAttribs[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, 569 | EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, 570 | EGL_DEPTH_SIZE, 0, 571 | // EGL_STENCIL_SIZE, 0, 572 | EGL_SAMPLES, 0, EGL_NONE}; 573 | 574 | state.config = 0; 575 | for (int i = 0; i < numConfigs; i++) 576 | { 577 | EGLint value = 0; 578 | 579 | eglGetConfigAttrib(state.display, configs[i], EGL_RENDERABLE_TYPE, 580 | &value); 581 | if ((value & EGL_OPENGL_ES3_BIT) != EGL_OPENGL_ES3_BIT) 582 | { 583 | continue; 584 | } 585 | 586 | // Without EGL_KHR_surfaceless_context, the config needs to support both 587 | // pbuffers and window surfaces. 588 | eglGetConfigAttrib(state.display, configs[i], EGL_SURFACE_TYPE, &value); 589 | if ((value & (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)) != 590 | (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)) 591 | { 592 | continue; 593 | } 594 | 595 | int j = 0; 596 | for (; configAttribs[j] != EGL_NONE; j += 2) 597 | { 598 | eglGetConfigAttrib(state.display, configs[i], configAttribs[j], 599 | &value); 600 | if (value != configAttribs[j + 1]) 601 | { 602 | break; 603 | } 604 | } 605 | if (configAttribs[j] == EGL_NONE) 606 | { 607 | state.config = configs[i]; 608 | break; 609 | } 610 | } 611 | if (state.config == 0) 612 | { 613 | return state; 614 | } 615 | 616 | EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, OPENGL_VERSION_MAJOR, 617 | EGL_NONE, EGL_NONE, EGL_NONE}; 618 | state.context = eglCreateContext(state.display, state.config, 619 | EGL_NO_CONTEXT, contextAttribs); 620 | if (state.context == EGL_NO_CONTEXT) 621 | { 622 | // eglCreateContext() failed: %s", EglErrorString(eglGetError())); 623 | return state; 624 | } 625 | 626 | const EGLint surfaceAttribs[] = {EGL_WIDTH, 16, EGL_HEIGHT, 16, EGL_NONE}; 627 | state.tinySurface = 628 | eglCreatePbufferSurface(state.display, state.config, surfaceAttribs); 629 | if (state.tinySurface == EGL_NO_SURFACE) 630 | { 631 | // eglCreatePbufferSurface() failed: %s", 632 | // EglErrorString(eglGetError())); 633 | eglDestroyContext(state.display, state.context); 634 | state.context = EGL_NO_CONTEXT; 635 | return state; 636 | } 637 | state.mainSurface = state.tinySurface; 638 | #elif defined(XWIN_WASM) 639 | EmscriptenWebGLContextAttributes attribs; 640 | emscripten_webgl_init_context_attributes(&attribs); 641 | state.context = emscripten_webgl_create_context(window->getDesc().name.c_str(), &attribs); 642 | #endif 643 | 644 | return state; 645 | } 646 | 647 | inline void setContext(const OpenGLState& state) 648 | { 649 | #if defined(XWIN_WIN32) 650 | wglMakeCurrent(state.hdc, state.hglrc); 651 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 652 | CGLSetCurrentContext(state.cglContext); 653 | #elif defined(XWIN_XCB) 654 | xcb_glx_make_current_cookie_t glx_make_current_cookie = 655 | xcb_glx_make_current(state.connection, state.glxDrawable, 656 | state.glxContext, 0); 657 | xcb_glx_make_current_reply_t* glx_make_current_reply = 658 | xcb_glx_make_current_reply(state.connection, glx_make_current_cookie, 659 | NULL); 660 | state.glxContextTag = glx_make_current_reply->context_tag; 661 | free(glx_make_current_reply); 662 | #elif defined(XWIN_XLIB) 663 | glXMakeCurrent(state.display, state.glxDrawable, state.glxContext); 664 | #elif defined(XWIN_ANDROID) 665 | EGL(eglMakeCurrent(state.display, state.mainSurface, state.mainSurface, 666 | state.context)); 667 | #elif defined(XWIN_WASM) 668 | emscripten_webgl_make_context_current(state.context); 669 | #endif 670 | } 671 | 672 | inline void unsetContext(const OpenGLState& state) 673 | { 674 | #if defined(XWIN_WIN32) 675 | wglMakeCurrent(state.hdc, NULL); 676 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 677 | CGLSetCurrentContext(NULL); 678 | #elif defined(XWIN_XLIB) 679 | glXMakeCurrent(state.display, None, NULL); 680 | #elif defined(XWIN_XCB) 681 | xcb_glx_make_current(state.connection, 0, 0, 0); 682 | #elif defined(XWIN_ANDROID) 683 | EGL(eglMakeCurrent(state.display, EGL_NO_SURFACE, EGL_NO_SURFACE, 684 | EGL_NO_CONTEXT)); 685 | #elif defined(XWIN_WASM) 686 | 687 | #endif 688 | } 689 | 690 | inline void destroyContext(const OpenGLState& state) 691 | { 692 | #if defined(XWIN_WIN32) 693 | wglDeleteContext(state.hglrc); 694 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 695 | //CGLDeleteContext(); 696 | #elif defined(XWIN_XLIB) 697 | glXDeleteContext(); 698 | #elif defined(XWIN_XCB) 699 | xcb_glx_delete_current(state.connection, 0, 0, 0); 700 | #elif defined(XWIN_ANDROID) 701 | eglDeleteContext(); 702 | #elif defined(XWIN_WASM) 703 | emscripten_webgl_destroy_context(state.context); 704 | #endif 705 | } 706 | 707 | inline bool getCurrentContext(const OpenGLState& state) 708 | { 709 | #if defined(XWIN_WIN32) 710 | return (wglGetCurrentContext() == state.hglrc); 711 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 712 | return (CGLGetCurrentContext() == state.cglContext); 713 | #elif defined(XWIN_XLIB) 714 | return (glXGetCurrentContext() == state.glxContext); 715 | #elif defined(XWIN_XCB) 716 | return true; 717 | #elif defined(XWIN_ANDROID) 718 | return (eglGetCurrentContext() == state.context); 719 | #elif defined(XWIN_WASM) 720 | EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_get_current_context(); 721 | return (context == state.context); 722 | #endif 723 | } 724 | 725 | inline void swapBuffers(const OpenGLState& state) 726 | { 727 | #if defined(XWIN_WIN32) 728 | SwapBuffers(state.hdc); 729 | #elif defined(XWIN_COCOA) || defined(XWIN_UIKIT) 730 | glFlush(); 731 | CGLFlushDrawable(state.cglContext); 732 | #elif defined(XWIN_XLIB) 733 | glXSwapBuffers(state.x11.display, state.context.glx.window); 734 | #elif defined(XWIN_XCB) 735 | return true; 736 | #elif defined(XWIN_ANDROID) 737 | eglSwapBuffers(state.display, state.surface); 738 | #elif defined(XWIN_WASM) 739 | emscripten_webgl_commit_frame(); 740 | #endif 741 | } 742 | } 743 | 744 | #endif 745 | -------------------------------------------------------------------------------- /src/CrossWindow/Graphics/Vulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(XGFX_VULKAN) 4 | 5 | #if defined(XWIN_WIN32) 6 | #define VK_USE_PLATFORM_WIN32_KHR 7 | #elif defined(XWIN_COCOA) 8 | #define VK_USE_PLATFORM_MACOS_MVK 9 | #elif defined(XWIN_UIKIT) 10 | #define VK_USE_PLATFORM_IOS_MVK 11 | #elif defined(XWIN_XCB) 12 | #define VK_USE_PLATFORM_XCB_KHR 13 | #elif defined(XWIN_ANDROID) 14 | #define VK_USE_PLATFORM_ANDROID_KHR 15 | #endif 16 | 17 | #include "vulkan/vulkan.hpp" 18 | 19 | namespace xgfx 20 | { 21 | 22 | inline vk::SurfaceKHR getSurface(xwin::Window* window, vk::Instance& instance) 23 | { 24 | VkSurfaceKHR surface; 25 | VkResult result = VK_RESULT_MAX_ENUM; 26 | 27 | #if defined(VK_USE_PLATFORM_WIN32_KHR) 28 | VkWin32SurfaceCreateInfoKHR info; 29 | info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; 30 | info.pNext = NULL; 31 | info.flags = 0; 32 | info.hinstance = window->hinstance; 33 | info.hwnd = window->hwnd; 34 | 35 | result = vkCreateWin32SurfaceKHR(static_cast(instance), &info, 36 | NULL, &surface); 37 | #elif defined(VK_USE_PLATFORM_WAYLAND_KHR) 38 | VkWaylandSurfaceCreateInfoKHR info; 39 | createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; 40 | createInfo.pNext = NULL; 41 | createInfo.flags = 0; 42 | createInfo.display = window->display; 43 | createInfo.surface = window->window; 44 | 45 | result = vkCreateWaylandSurfaceKHR(static_cast(instance), &info, 46 | NULL, &surface); 47 | #elif defined(VK_USE_PLATFORM_MIR_KHR) 48 | #elif defined(VK_USE_PLATFORM_ANDROID_KHR) 49 | VkAndroidSurfaceCreateInfoKHR info; 50 | createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; 51 | createInfo.pNext = NULL; 52 | createInfo.flags = 0; 53 | createInfo.window = (ANativeWindow*)(window->window); 54 | 55 | result = vkCreateAndroidSurfaceKHR(static_cast(instance), &info, 56 | NULL, &surface); 57 | #elif defined(VK_USE_PLATFORM_XLIB_KHR) 58 | VkXlibSurfaceCreateInfoKHR createInfo; 59 | createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; 60 | createInfo.pNext = NULL; 61 | createInfo.flags = 0; 62 | createInfo.dpy = window->display; 63 | createInfo.window = window->window; 64 | 65 | result = vkCreateXlibSurfaceKHR(static_cast(instance), &info, 66 | NULL, &surface); 67 | #elif defined(VK_USE_PLATFORM_XCB_KHR) 68 | VkXcbSurfaceCreateInfoKHR createInfo; 69 | createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; 70 | createInfo.pNext = NULL; 71 | createInfo.flags = 0; 72 | createInfo.connection = window->connection; 73 | createInfo.window = window->window; 74 | 75 | result = vkCreateXcbSurfaceKHR(static_cast(instance), &info, 76 | NULL, &surface); 77 | #elif defined(VK_USE_PLATFORM_DISPLAY_KHR) 78 | err = demo_create_display_surface(demo); 79 | #elif defined(VK_USE_PLATFORM_IOS_MVK) 80 | VkIOSSurfaceCreateInfoMVK surface; 81 | surface.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK; 82 | surface.pNext = NULL; 83 | surface.flags = 0; 84 | surface.pView = window->view; 85 | 86 | result = vkCreateIOSSurfaceMVK(static_cast(instance), &info, 87 | NULL, &surface); 88 | #elif defined(VK_USE_PLATFORM_MACOS_MVK) 89 | 90 | window->setLayer(xwin::WindowDelegate::LayerType::Metal); 91 | 92 | VkMacOSSurfaceCreateInfoMVK info; 93 | info.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; 94 | info.pNext = NULL; 95 | info.flags = 0; 96 | info.pView = window->view; 97 | 98 | result = vkCreateMacOSSurfaceMVK(static_cast(instance), &info, 99 | NULL, &surface); 100 | #endif 101 | if (result == VK_SUCCESS) 102 | { 103 | return vk::SurfaceKHR(surface); 104 | } 105 | else 106 | { 107 | // throw error 108 | } 109 | return vk::SurfaceKHR(); 110 | } 111 | } 112 | #endif 113 | -------------------------------------------------------------------------------- /src/CrossWindow/Graphics/WebGPU.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(XGFX_WASM) 4 | 5 | namespace xgfx 6 | { 7 | inline void createGPUSurface(xwin::Window* window) 8 | { 9 | //... 10 | } 11 | } 12 | #endif 13 | --------------------------------------------------------------------------------