diff --git a/thirdparty/sokol/sokol_app.h b/thirdparty/sokol/sokol_app.h old mode 100755 new mode 100644 index 254a44b16e..da91a2db1f --- a/thirdparty/sokol/sokol_app.h +++ b/thirdparty/sokol/sokol_app.h @@ -73,10 +73,19 @@ - on macOS with GL: Cocoa, QuartzCore, OpenGL - on iOS with Metal: UIKit, Metal, MetalKit - on iOS with GL: UIKit, OpenGLES, GLKit - - on Linux: X11, Xi, Xcursor, GL, dl, m(?) + - on Linux: X11, Xi, Xcursor, GL, dl, pthread, m(?) - on Android: GLESv3, EGL, log, android - on Windows: no action needed, libs are defined in-source via pragma-comment-lib + On Linux, you also need to use the -pthread compiler and linker option, otherwise weird + things will happen, see here for details: https://github.com/floooh/sokol/issues/376 + + Building for UWP requires a recent Visual Studio toolchain and Windows SDK + (at least VS2019 and Windows SDK 10.0.19041.0). When the UWP backend is + selected, the sokol_app.h implementation must be compiled as C++17. + + On macOS and iOS, the implementation must be compiled as Objective-C. + FEATURE OVERVIEW ================ sokol_app.h provides a minimalistic cross-platform API which @@ -91,48 +100,51 @@ FEATURE/PLATFORM MATRIX ======================= - | Windows | macOS | Linux | iOS | Android | Raspi | HTML5 - --------------------+---------+-------+-------+-------+---------+-------+------- - gl 3.x | YES | YES | YES | --- | --- | --- | --- - gles2/webgl | --- | --- | --- | YES | YES | TODO | YES - gles3/webgl2 | --- | --- | --- | YES | YES | --- | YES - metal | --- | YES | --- | YES | --- | --- | --- - d3d11 | YES | --- | --- | --- | --- | --- | --- - KEY_DOWN | YES | YES | YES | SOME | TODO | TODO | YES - KEY_UP | YES | YES | YES | SOME | TODO | TODO | YES - CHAR | YES | YES | YES | YES | TODO | TODO | YES - MOUSE_DOWN | YES | YES | YES | --- | --- | TODO | YES - MOUSE_UP | YES | YES | YES | --- | --- | TODO | YES - MOUSE_SCROLL | YES | YES | YES | --- | --- | TODO | YES - MOUSE_MOVE | YES | YES | YES | --- | --- | TODO | YES - MOUSE_ENTER | YES | YES | YES | --- | --- | TODO | YES - MOUSE_LEAVE | YES | YES | YES | --- | --- | TODO | YES - TOUCHES_BEGAN | --- | --- | --- | YES | YES | --- | YES - TOUCHES_MOVED | --- | --- | --- | YES | YES | --- | YES - TOUCHES_ENDED | --- | --- | --- | YES | YES | --- | YES - TOUCHES_CANCELLED | --- | --- | --- | YES | YES | --- | YES - RESIZED | YES | YES | YES | YES | YES | --- | YES - ICONIFIED | YES | YES | YES | --- | --- | --- | --- - RESTORED | YES | YES | YES | --- | --- | --- | --- - SUSPENDED | --- | --- | --- | YES | YES | --- | TODO - RESUMED | --- | --- | --- | YES | YES | --- | TODO - QUIT_REQUESTED | YES | YES | YES | --- | --- | TODO | YES - UPDATE_CURSOR | YES | YES | TODO | --- | --- | --- | TODO - IME | TODO | TODO? | TODO | ??? | TODO | ??? | ??? - key repeat flag | YES | YES | YES | --- | --- | TODO | YES - windowed | YES | YES | YES | --- | --- | TODO | YES - fullscreen | YES | YES | YES | YES | YES | TODO | --- - mouse hide | YES | YES | YES | --- | --- | TODO | TODO - mouse lock | YES | YES | YES | --- | --- | TODO | YES - screen keyboard | --- | --- | --- | YES | TODO | --- | YES - swap interval | YES | YES | YES | YES | TODO | TODO | YES - high-dpi | YES | YES | TODO | YES | YES | TODO | YES - clipboard | YES | YES | TODO | --- | --- | --- | YES + | Windows | macOS | Linux | iOS | Android | UWP | Raspi | HTML5 + --------------------+---------+-------+-------+-------+---------+------+-------+------- + gl 3.x | YES | YES | YES | --- | --- | --- | --- | --- + gles2/webgl | --- | --- | --- | YES | YES | --- | TODO | YES + gles3/webgl2 | --- | --- | --- | YES | YES | --- | --- | YES + metal | --- | YES | --- | YES | --- | --- | --- | --- + d3d11 | YES | --- | --- | --- | --- | YES | --- | --- + KEY_DOWN | YES | YES | YES | SOME | TODO | YES | TODO | YES + KEY_UP | YES | YES | YES | SOME | TODO | YES | TODO | YES + CHAR | YES | YES | YES | YES | TODO | YES | TODO | YES + MOUSE_DOWN | YES | YES | YES | --- | --- | YES | TODO | YES + MOUSE_UP | YES | YES | YES | --- | --- | YES | TODO | YES + MOUSE_SCROLL | YES | YES | YES | --- | --- | YES | TODO | YES + MOUSE_MOVE | YES | YES | YES | --- | --- | YES | TODO | YES + MOUSE_ENTER | YES | YES | YES | --- | --- | YES | TODO | YES + MOUSE_LEAVE | YES | YES | YES | --- | --- | YES | TODO | YES + TOUCHES_BEGAN | --- | --- | --- | YES | YES | TODO | --- | YES + TOUCHES_MOVED | --- | --- | --- | YES | YES | TODO | --- | YES + TOUCHES_ENDED | --- | --- | --- | YES | YES | TODO | --- | YES + TOUCHES_CANCELLED | --- | --- | --- | YES | YES | TODO | --- | YES + RESIZED | YES | YES | YES | YES | YES | YES | --- | YES + ICONIFIED | YES | YES | YES | --- | --- | YES | --- | --- + RESTORED | YES | YES | YES | --- | --- | YES | --- | --- + SUSPENDED | --- | --- | --- | YES | YES | YES | --- | TODO + RESUMED | --- | --- | --- | YES | YES | YES | --- | TODO + QUIT_REQUESTED | YES | YES | YES | --- | --- | --- | TODO | YES + UPDATE_CURSOR | YES | YES | TODO | --- | --- | TODO | --- | TODO + IME | TODO | TODO? | TODO | ??? | TODO | --- | ??? | ??? + key repeat flag | YES | YES | YES | --- | --- | YES | TODO | YES + windowed | YES | YES | YES | --- | --- | YES | TODO | YES + fullscreen | YES | YES | YES | YES | YES | YES | TODO | --- + mouse hide | YES | YES | YES | --- | --- | YES | TODO | TODO + mouse lock | YES | YES | YES | --- | --- | TODO | TODO | YES + screen keyboard | --- | --- | --- | YES | TODO | TODO | --- | YES + swap interval | YES | YES | YES | YES | TODO | --- | TODO | YES + high-dpi | YES | YES | TODO | YES | YES | YES | TODO | YES + clipboard | YES | YES | TODO | --- | --- | TODO | --- | YES + MSAA | YES | YES | YES | YES | YES | TODO | TODO | YES TODO ==== - Linux: - clipboard support + - UWP: + - clipboard, mouselock, MSAA support - sapp_consume_event() on non-web platforms? STEP BY STEP @@ -1014,6 +1026,8 @@ SOKOL_API_DECL uint64_t sapp_frame_count(void); SOKOL_API_DECL void sapp_set_clipboard_string(const char* str); /* read string from clipboard (usually during SAPP_EVENTTYPE_CLIPBOARD_PASTED) */ SOKOL_API_DECL const char* sapp_get_clipboard_string(void); +/* set the window title (only on desktop platforms) */ +SOKOL_API_DECL void sapp_set_window_title(const char* str); /* special run-function for SOKOL_NO_ENTRY (in standard mode this is an empty stub) */ SOKOL_API_DECL int sapp_run(const sapp_desc* desc); @@ -1032,8 +1046,6 @@ SOKOL_API_DECL const void* sapp_metal_get_renderpass_descriptor(void); SOKOL_API_DECL const void* sapp_metal_get_drawable(void); /* macOS: get bridged pointer to macOS NSWindow */ SOKOL_API_DECL const void* sapp_macos_get_window(void); -/* macOS: set window title */ -SOKOL_API_DECL void sapp_macos_set_title(const char* title); /* iOS: get bridged pointer to iOS UIWindow */ SOKOL_API_DECL const void* sapp_ios_get_window(void); @@ -1067,6 +1079,15 @@ SOKOL_API_DECL const void* sapp_android_get_native_activity(void); inline int sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } #endif + +// this WinRT specific hack is required when wWinMain is in a static library +#if defined(_MSC_VER) && defined(UNICODE) +#include +#if defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#pragma comment(linker, "/include:wWinMain") +#endif +#endif + #endif // SOKOL_APP_INCLUDED /*-- IMPLEMENTATION ----------------------------------------------------------*/ @@ -1106,9 +1127,20 @@ inline int sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } #endif #elif defined(_WIN32) /* Windows (D3D11 or GL) */ - #define _SAPP_WIN32 (1) - #if !defined(SOKOL_D3D11) && !defined(SOKOL_GLCORE33) - #error("sokol_app.h: unknown 3D API selected for Win32, must be SOKOL_D3D11 or SOKOL_GLCORE33") + #include + #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) + #define _SAPP_UWP (1) + #if !defined(SOKOL_D3D11) + #error("sokol_app.h: unknown 3D API selected for UWP, must be SOKOL_D3D11") + #endif + #if !defined(__cplusplus) + #error("UWP bindings require C++/17") + #endif + #else + #define _SAPP_WIN32 (1) + #if !defined(SOKOL_D3D11) && !defined(SOKOL_GLCORE33) + #error("sokol_app.h: unknown 3D API selected for Win32, must be SOKOL_D3D11 or SOKOL_GLCORE33") + #endif #endif #elif defined(__ANDROID__) /* Android */ @@ -1236,39 +1268,62 @@ inline int sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } #include #include #include - #pragma comment (lib, "Shell32.lib") #if !defined(SOKOL_WIN32_FORCE_MAIN) #pragma comment (linker, "/subsystem:windows") #endif - #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) - #pragma comment (lib, "WindowsApp.lib") - #else - #pragma comment (lib, "user32.lib") - #if defined(SOKOL_D3D11) - #pragma comment (lib, "dxgi.lib") - #pragma comment (lib, "d3d11.lib") - #pragma comment (lib, "dxguid.lib") - #endif - #if defined(SOKOL_GLCORE33) - #pragma comment (lib, "gdi32.lib") - #endif + + #pragma comment (lib, "user32.lib") + #pragma comment (lib, "Shell32.lib") + #if defined(SOKOL_D3D11) + #pragma comment (lib, "dxgi.lib") + #pragma comment (lib, "d3d11.lib") + #pragma comment (lib, "dxguid.lib") #endif + #if defined(SOKOL_GLCORE33) + #pragma comment (lib, "gdi32.lib") + #endif + #if defined(SOKOL_D3D11) #ifndef D3D11_NO_HELPERS #define D3D11_NO_HELPERS #endif - #ifndef CINTERFACE - #define CINTERFACE - #endif - #ifndef COBJMACROS - #define COBJMACROS - #endif #include #include #endif #ifndef WM_MOUSEHWHEEL /* see https://github.com/floooh/sokol/issues/138 */ #define WM_MOUSEHWHEEL (0x020E) #endif +#elif defined(_SAPP_UWP) + #ifndef NOMINMAX + #define NOMINMAX + #endif + + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4201) /* nonstandard extension used: nameless struct/union */ + #pragma warning(disable:4054) /* 'type cast': from function pointer */ + #pragma warning(disable:4055) /* 'type cast': from data pointer */ + #pragma warning(disable:4505) /* unreferenced local function has been removed */ + #pragma warning(disable:4115) /* /W4: 'ID3D11ModuleInstance': named type definition in parentheses (in d3d11.h) */ + #endif + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #pragma comment (lib, "WindowsApp.lib") + #pragma comment (lib, "dxguid.lib") #elif defined(_SAPP_ANDROID) #include #include @@ -1316,6 +1371,7 @@ inline int sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } typedef struct { uint32_t flags_changed_store; + uint8_t mouse_buttons; NSWindow* window; NSTrackingArea* tracking_area; _sapp_macos_app_delegate* app_dlg; @@ -1391,6 +1447,20 @@ typedef struct { } _sapp_emsc_t; #endif // _SAPP_EMSCRIPTEN +/*== WIN32 DECLARATIONS ======================================================*/ +#if defined(SOKOL_D3D11) && (defined(_SAPP_WIN32) || defined(_SAPP_UWP)) +typedef struct { + ID3D11Device* device; + ID3D11DeviceContext* device_context; + ID3D11Texture2D* rt; + ID3D11RenderTargetView* rtv; + ID3D11Texture2D* ds; + ID3D11DepthStencilView* dsv; + DXGI_SWAP_CHAIN_DESC swap_chain_desc; + IDXGISwapChain* swap_chain; +} _sapp_d3d11_t; +#endif + /*== WIN32 DECLARATIONS ======================================================*/ #if defined(_SAPP_WIN32) @@ -1423,6 +1493,7 @@ typedef struct { bool in_create_window; bool iconified; bool mouse_tracked; + uint8_t mouse_capture_mask; _sapp_win32_dpi_t dpi; bool raw_input_mousepos_valid; LONG raw_input_mousepos_x; @@ -1430,19 +1501,6 @@ typedef struct { uint8_t raw_input_data[256]; } _sapp_win32_t; -#if defined(SOKOL_D3D11) -typedef struct { - ID3D11Device* device; - ID3D11DeviceContext* device_context; - ID3D11Texture2D* rt; - ID3D11RenderTargetView* rtv; - ID3D11Texture2D* ds; - ID3D11DepthStencilView* dsv; - DXGI_SWAP_CHAIN_DESC swap_chain_desc; - IDXGISwapChain* swap_chain; -} _sapp_d3d11_t; -#endif - #if defined(SOKOL_GLCORE33) #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_SUPPORT_OPENGL_ARB 0x2010 @@ -1504,6 +1562,23 @@ typedef struct { #endif // _SAPP_WIN32 +/*== UWP DECLARATIONS ======================================================*/ +#if defined(_SAPP_UWP) + +typedef struct { + float content_scale; + float window_scale; + float mouse_scale; +} _sapp_uwp_dpi_t; + +typedef struct { + bool mouse_tracked; + uint8_t mouse_buttons; + _sapp_uwp_dpi_t dpi; +} _sapp_uwp_t; + +#endif // _SAPP_UWP + /*== ANDROID DECLARATIONS ====================================================*/ #if defined(_SAPP_ANDROID) @@ -1608,6 +1683,7 @@ typedef struct { } _sapp_xi_t; typedef struct { + uint8_t mouse_buttons; Display* display; int screen; Window root; @@ -1743,6 +1819,11 @@ typedef struct { #elif defined(SOKOL_GLCORE33) _sapp_wgl_t wgl; #endif + #elif defined(_SAPP_UWP) + _sapp_uwp_t uwp; + #if defined(SOKOL_D3D11) + _sapp_d3d11_t d3d11; + #endif #elif defined(_SAPP_ANDROID) _sapp_android_t android; #elif defined(_SAPP_LINUX) @@ -2548,6 +2629,10 @@ _SOKOL_PRIVATE const char* _sapp_macos_get_clipboard_string(void) { return _sapp.clipboard.buffer; } +_SOKOL_PRIVATE void _sapp_macos_update_window_title(void) { + [_sapp.macos.window setTitle: [NSString stringWithUTF8String:_sapp.window_title]]; +} + _SOKOL_PRIVATE void _sapp_macos_update_mouse(void) { if (!_sapp.mouse.locked) { const NSPoint mouse_pos = [_sapp.macos.window mouseLocationOutsideOfEventStream]; @@ -2845,34 +2930,55 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) { [super updateTrackingAreas]; } - (void)mouseEntered:(NSEvent*)event { - _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + /* don't send mouse enter/leave while dragging (so that it behaves the same as + on Windows while SetCapture is active + */ + if (0 == _sapp.macos.mouse_buttons) { + _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + } } - (void)mouseExited:(NSEvent*)event { - _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + if (0 == _sapp.macos.mouse_buttons) { + _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); + } } - (void)mouseDown:(NSEvent*)event { _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_LEFT, _sapp_macos_mod(event.modifierFlags)); + _sapp.macos.mouse_buttons |= (1< 1)); + memset(dst, 0, dst_num_bytes); + const int dst_chars = dst_num_bytes / sizeof(wchar_t); + const int dst_needed = MultiByteToWideChar(CP_UTF8, 0, src, -1, 0, 0); + if ((dst_needed > 0) && (dst_needed < dst_chars)) { + MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, dst_chars); + return true; + } + else { + /* input string doesn't fit into destination buffer */ + return false; + } +} + +_SOKOL_PRIVATE void _sapp_win32_uwp_app_event(sapp_event_type type) { + if (_sapp_events_enabled()) { + _sapp_init_event(type); + _sapp_call_event(&_sapp.event); + } +} + +_SOKOL_PRIVATE void _sapp_win32_uwp_init_keytable(void) { + /* same as GLFW */ + _sapp.keycodes[0x00B] = SAPP_KEYCODE_0; + _sapp.keycodes[0x002] = SAPP_KEYCODE_1; + _sapp.keycodes[0x003] = SAPP_KEYCODE_2; + _sapp.keycodes[0x004] = SAPP_KEYCODE_3; + _sapp.keycodes[0x005] = SAPP_KEYCODE_4; + _sapp.keycodes[0x006] = SAPP_KEYCODE_5; + _sapp.keycodes[0x007] = SAPP_KEYCODE_6; + _sapp.keycodes[0x008] = SAPP_KEYCODE_7; + _sapp.keycodes[0x009] = SAPP_KEYCODE_8; + _sapp.keycodes[0x00A] = SAPP_KEYCODE_9; + _sapp.keycodes[0x01E] = SAPP_KEYCODE_A; + _sapp.keycodes[0x030] = SAPP_KEYCODE_B; + _sapp.keycodes[0x02E] = SAPP_KEYCODE_C; + _sapp.keycodes[0x020] = SAPP_KEYCODE_D; + _sapp.keycodes[0x012] = SAPP_KEYCODE_E; + _sapp.keycodes[0x021] = SAPP_KEYCODE_F; + _sapp.keycodes[0x022] = SAPP_KEYCODE_G; + _sapp.keycodes[0x023] = SAPP_KEYCODE_H; + _sapp.keycodes[0x017] = SAPP_KEYCODE_I; + _sapp.keycodes[0x024] = SAPP_KEYCODE_J; + _sapp.keycodes[0x025] = SAPP_KEYCODE_K; + _sapp.keycodes[0x026] = SAPP_KEYCODE_L; + _sapp.keycodes[0x032] = SAPP_KEYCODE_M; + _sapp.keycodes[0x031] = SAPP_KEYCODE_N; + _sapp.keycodes[0x018] = SAPP_KEYCODE_O; + _sapp.keycodes[0x019] = SAPP_KEYCODE_P; + _sapp.keycodes[0x010] = SAPP_KEYCODE_Q; + _sapp.keycodes[0x013] = SAPP_KEYCODE_R; + _sapp.keycodes[0x01F] = SAPP_KEYCODE_S; + _sapp.keycodes[0x014] = SAPP_KEYCODE_T; + _sapp.keycodes[0x016] = SAPP_KEYCODE_U; + _sapp.keycodes[0x02F] = SAPP_KEYCODE_V; + _sapp.keycodes[0x011] = SAPP_KEYCODE_W; + _sapp.keycodes[0x02D] = SAPP_KEYCODE_X; + _sapp.keycodes[0x015] = SAPP_KEYCODE_Y; + _sapp.keycodes[0x02C] = SAPP_KEYCODE_Z; + _sapp.keycodes[0x028] = SAPP_KEYCODE_APOSTROPHE; + _sapp.keycodes[0x02B] = SAPP_KEYCODE_BACKSLASH; + _sapp.keycodes[0x033] = SAPP_KEYCODE_COMMA; + _sapp.keycodes[0x00D] = SAPP_KEYCODE_EQUAL; + _sapp.keycodes[0x029] = SAPP_KEYCODE_GRAVE_ACCENT; + _sapp.keycodes[0x01A] = SAPP_KEYCODE_LEFT_BRACKET; + _sapp.keycodes[0x00C] = SAPP_KEYCODE_MINUS; + _sapp.keycodes[0x034] = SAPP_KEYCODE_PERIOD; + _sapp.keycodes[0x01B] = SAPP_KEYCODE_RIGHT_BRACKET; + _sapp.keycodes[0x027] = SAPP_KEYCODE_SEMICOLON; + _sapp.keycodes[0x035] = SAPP_KEYCODE_SLASH; + _sapp.keycodes[0x056] = SAPP_KEYCODE_WORLD_2; + _sapp.keycodes[0x00E] = SAPP_KEYCODE_BACKSPACE; + _sapp.keycodes[0x153] = SAPP_KEYCODE_DELETE; + _sapp.keycodes[0x14F] = SAPP_KEYCODE_END; + _sapp.keycodes[0x01C] = SAPP_KEYCODE_ENTER; + _sapp.keycodes[0x001] = SAPP_KEYCODE_ESCAPE; + _sapp.keycodes[0x147] = SAPP_KEYCODE_HOME; + _sapp.keycodes[0x152] = SAPP_KEYCODE_INSERT; + _sapp.keycodes[0x15D] = SAPP_KEYCODE_MENU; + _sapp.keycodes[0x151] = SAPP_KEYCODE_PAGE_DOWN; + _sapp.keycodes[0x149] = SAPP_KEYCODE_PAGE_UP; + _sapp.keycodes[0x045] = SAPP_KEYCODE_PAUSE; + _sapp.keycodes[0x146] = SAPP_KEYCODE_PAUSE; + _sapp.keycodes[0x039] = SAPP_KEYCODE_SPACE; + _sapp.keycodes[0x00F] = SAPP_KEYCODE_TAB; + _sapp.keycodes[0x03A] = SAPP_KEYCODE_CAPS_LOCK; + _sapp.keycodes[0x145] = SAPP_KEYCODE_NUM_LOCK; + _sapp.keycodes[0x046] = SAPP_KEYCODE_SCROLL_LOCK; + _sapp.keycodes[0x03B] = SAPP_KEYCODE_F1; + _sapp.keycodes[0x03C] = SAPP_KEYCODE_F2; + _sapp.keycodes[0x03D] = SAPP_KEYCODE_F3; + _sapp.keycodes[0x03E] = SAPP_KEYCODE_F4; + _sapp.keycodes[0x03F] = SAPP_KEYCODE_F5; + _sapp.keycodes[0x040] = SAPP_KEYCODE_F6; + _sapp.keycodes[0x041] = SAPP_KEYCODE_F7; + _sapp.keycodes[0x042] = SAPP_KEYCODE_F8; + _sapp.keycodes[0x043] = SAPP_KEYCODE_F9; + _sapp.keycodes[0x044] = SAPP_KEYCODE_F10; + _sapp.keycodes[0x057] = SAPP_KEYCODE_F11; + _sapp.keycodes[0x058] = SAPP_KEYCODE_F12; + _sapp.keycodes[0x064] = SAPP_KEYCODE_F13; + _sapp.keycodes[0x065] = SAPP_KEYCODE_F14; + _sapp.keycodes[0x066] = SAPP_KEYCODE_F15; + _sapp.keycodes[0x067] = SAPP_KEYCODE_F16; + _sapp.keycodes[0x068] = SAPP_KEYCODE_F17; + _sapp.keycodes[0x069] = SAPP_KEYCODE_F18; + _sapp.keycodes[0x06A] = SAPP_KEYCODE_F19; + _sapp.keycodes[0x06B] = SAPP_KEYCODE_F20; + _sapp.keycodes[0x06C] = SAPP_KEYCODE_F21; + _sapp.keycodes[0x06D] = SAPP_KEYCODE_F22; + _sapp.keycodes[0x06E] = SAPP_KEYCODE_F23; + _sapp.keycodes[0x076] = SAPP_KEYCODE_F24; + _sapp.keycodes[0x038] = SAPP_KEYCODE_LEFT_ALT; + _sapp.keycodes[0x01D] = SAPP_KEYCODE_LEFT_CONTROL; + _sapp.keycodes[0x02A] = SAPP_KEYCODE_LEFT_SHIFT; + _sapp.keycodes[0x15B] = SAPP_KEYCODE_LEFT_SUPER; + _sapp.keycodes[0x137] = SAPP_KEYCODE_PRINT_SCREEN; + _sapp.keycodes[0x138] = SAPP_KEYCODE_RIGHT_ALT; + _sapp.keycodes[0x11D] = SAPP_KEYCODE_RIGHT_CONTROL; + _sapp.keycodes[0x036] = SAPP_KEYCODE_RIGHT_SHIFT; + _sapp.keycodes[0x15C] = SAPP_KEYCODE_RIGHT_SUPER; + _sapp.keycodes[0x150] = SAPP_KEYCODE_DOWN; + _sapp.keycodes[0x14B] = SAPP_KEYCODE_LEFT; + _sapp.keycodes[0x14D] = SAPP_KEYCODE_RIGHT; + _sapp.keycodes[0x148] = SAPP_KEYCODE_UP; + _sapp.keycodes[0x052] = SAPP_KEYCODE_KP_0; + _sapp.keycodes[0x04F] = SAPP_KEYCODE_KP_1; + _sapp.keycodes[0x050] = SAPP_KEYCODE_KP_2; + _sapp.keycodes[0x051] = SAPP_KEYCODE_KP_3; + _sapp.keycodes[0x04B] = SAPP_KEYCODE_KP_4; + _sapp.keycodes[0x04C] = SAPP_KEYCODE_KP_5; + _sapp.keycodes[0x04D] = SAPP_KEYCODE_KP_6; + _sapp.keycodes[0x047] = SAPP_KEYCODE_KP_7; + _sapp.keycodes[0x048] = SAPP_KEYCODE_KP_8; + _sapp.keycodes[0x049] = SAPP_KEYCODE_KP_9; + _sapp.keycodes[0x04E] = SAPP_KEYCODE_KP_ADD; + _sapp.keycodes[0x053] = SAPP_KEYCODE_KP_DECIMAL; + _sapp.keycodes[0x135] = SAPP_KEYCODE_KP_DIVIDE; + _sapp.keycodes[0x11C] = SAPP_KEYCODE_KP_ENTER; + _sapp.keycodes[0x037] = SAPP_KEYCODE_KP_MULTIPLY; + _sapp.keycodes[0x04A] = SAPP_KEYCODE_KP_SUBTRACT; +} +#endif // _SAPP_WIN32 || _SAPP_UWP + +/*== WINDOWS DESKTOP===========================================================*/ #if defined(_SAPP_WIN32) #if defined(SOKOL_D3D11) -#define _SAPP_SAFE_RELEASE(class, obj) if (obj) { class##_Release(obj); obj=0; } + +#if defined(__cplusplus) +#define _sapp_d3d11_Release(self) (self)->Release() +#else +#define _sapp_d3d11_Release(self) (self)->lpVtbl->Release(self) +#endif + +#define _SAPP_SAFE_RELEASE(class, obj) if (obj) { _sapp_d3d11_Release(obj); obj=0; } + +static inline HRESULT _sapp_dxgi_GetBuffer(IDXGISwapChain* self, UINT Buffer, REFIID riid, void** ppSurface) { + #if defined(__cplusplus) + return self->GetBuffer(Buffer, riid, ppSurface); + #else + return self->lpVtbl->GetBuffer(self, Buffer, riid, ppSurface); + #endif +} + +static inline HRESULT _sapp_d3d11_CreateRenderTargetView(ID3D11Device* self, ID3D11Resource *pResource, const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, ID3D11RenderTargetView** ppRTView) { + #if defined(__cplusplus) + return self->CreateRenderTargetView(pResource, pDesc, ppRTView); + #else + return self->lpVtbl->CreateRenderTargetView(self, pResource, pDesc, ppRTView); + #endif +} + +static inline HRESULT _sapp_d3d11_CreateTexture2D(ID3D11Device* self, const D3D11_TEXTURE2D_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Texture2D** ppTexture2D) { + #if defined(__cplusplus) + return self->CreateTexture2D(pDesc, pInitialData, ppTexture2D); + #else + return self->lpVtbl->CreateTexture2D(self, pDesc, pInitialData, ppTexture2D); + #endif +} + +static inline HRESULT _sapp_d3d11_CreateDepthStencilView(ID3D11Device* self, ID3D11Resource* pResource, const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D11DepthStencilView** ppDepthStencilView) { + #if defined(__cplusplus) + return self->CreateDepthStencilView(pResource, pDesc, ppDepthStencilView); + #else + return self->lpVtbl->CreateDepthStencilView(self, pResource, pDesc, ppDepthStencilView); + #endif +} + +static inline HRESULT _sapp_dxgi_ResizeBuffers(IDXGISwapChain* self, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) { + #if defined(__cplusplus) + return self->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags); + #else + return self->lpVtbl->ResizeBuffers(self, BufferCount, Width, Height, NewFormat, SwapChainFlags); + #endif +} + +static inline HRESULT _sapp_dxgi_Present(IDXGISwapChain* self, UINT SyncInterval, UINT Flags) { + #if defined(__cplusplus) + return self->Present(SyncInterval, Flags); + #else + return self->lpVtbl->Present(self, SyncInterval, Flags); + #endif +} _SOKOL_PRIVATE void _sapp_d3d11_create_device_and_swapchain(void) { DXGI_SWAP_CHAIN_DESC* sc_desc = &_sapp.d3d11.swap_chain_desc; @@ -4440,12 +4763,12 @@ _SOKOL_PRIVATE void _sapp_d3d11_destroy_device_and_swapchain(void) { _SOKOL_PRIVATE void _sapp_d3d11_create_default_render_target(void) { HRESULT hr; #ifdef __cplusplus - hr = IDXGISwapChain_GetBuffer(_sapp.d3d11.swap_chain, 0, IID_ID3D11Texture2D, (void**)&_sapp.d3d11.rt); + hr = _sapp_dxgi_GetBuffer(_sapp.d3d11.swap_chain, 0, IID_ID3D11Texture2D, (void**)&_sapp.d3d11.rt); #else - hr = IDXGISwapChain_GetBuffer(_sapp.d3d11.swap_chain, 0, &IID_ID3D11Texture2D, (void**)&_sapp.d3d11.rt); + hr = _sapp_dxgi_GetBuffer(_sapp.d3d11.swap_chain, 0, &IID_ID3D11Texture2D, (void**)&_sapp.d3d11.rt); #endif SOKOL_ASSERT(SUCCEEDED(hr) && _sapp.d3d11.rt); - hr = ID3D11Device_CreateRenderTargetView(_sapp.d3d11.device, (ID3D11Resource*)_sapp.d3d11.rt, NULL, &_sapp.d3d11.rtv); + hr = _sapp_d3d11_CreateRenderTargetView(_sapp.d3d11.device, (ID3D11Resource*)_sapp.d3d11.rt, NULL, &_sapp.d3d11.rtv); SOKOL_ASSERT(SUCCEEDED(hr) && _sapp.d3d11.rtv); D3D11_TEXTURE2D_DESC ds_desc; memset(&ds_desc, 0, sizeof(ds_desc)); @@ -4457,13 +4780,13 @@ _SOKOL_PRIVATE void _sapp_d3d11_create_default_render_target(void) { ds_desc.SampleDesc = _sapp.d3d11.swap_chain_desc.SampleDesc; ds_desc.Usage = D3D11_USAGE_DEFAULT; ds_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - hr = ID3D11Device_CreateTexture2D(_sapp.d3d11.device, &ds_desc, NULL, &_sapp.d3d11.ds); + hr = _sapp_d3d11_CreateTexture2D(_sapp.d3d11.device, &ds_desc, NULL, &_sapp.d3d11.ds); SOKOL_ASSERT(SUCCEEDED(hr) && _sapp.d3d11.ds); D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc; memset(&dsv_desc, 0, sizeof(dsv_desc)); dsv_desc.Format = ds_desc.Format; dsv_desc.ViewDimension = _sapp.sample_count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; - hr = ID3D11Device_CreateDepthStencilView(_sapp.d3d11.device, (ID3D11Resource*)_sapp.d3d11.ds, &dsv_desc, &_sapp.d3d11.dsv); + hr = _sapp_d3d11_CreateDepthStencilView(_sapp.d3d11.device, (ID3D11Resource*)_sapp.d3d11.ds, &dsv_desc, &_sapp.d3d11.dsv); SOKOL_ASSERT(SUCCEEDED(hr) && _sapp.d3d11.dsv); } @@ -4477,7 +4800,7 @@ _SOKOL_PRIVATE void _sapp_d3d11_destroy_default_render_target(void) { _SOKOL_PRIVATE void _sapp_d3d11_resize_default_render_target(void) { if (_sapp.d3d11.swap_chain) { _sapp_d3d11_destroy_default_render_target(); - IDXGISwapChain_ResizeBuffers(_sapp.d3d11.swap_chain, 1, _sapp.framebuffer_width, _sapp.framebuffer_height, DXGI_FORMAT_B8G8R8A8_UNORM, 0); + _sapp_dxgi_ResizeBuffers(_sapp.d3d11.swap_chain, 1, _sapp.framebuffer_width, _sapp.framebuffer_height, DXGI_FORMAT_B8G8R8A8_UNORM, 0); _sapp_d3d11_create_default_render_target(); } } @@ -4729,21 +5052,6 @@ _SOKOL_PRIVATE void _sapp_wgl_swap_buffers(void) { } #endif /* SOKOL_GLCORE33 */ -_SOKOL_PRIVATE bool _sapp_win32_utf8_to_wide(const char* src, wchar_t* dst, int dst_num_bytes) { - SOKOL_ASSERT(src && dst && (dst_num_bytes > 1)); - memset(dst, 0, dst_num_bytes); - const int dst_chars = dst_num_bytes / sizeof(wchar_t); - const int dst_needed = MultiByteToWideChar(CP_UTF8, 0, src, -1, 0, 0); - if ((dst_needed > 0) && (dst_needed < dst_chars)) { - MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, dst_chars); - return true; - } - else { - /* input string doesn't fit into destination buffer */ - return false; - } -} - _SOKOL_PRIVATE bool _sapp_win32_wide_to_utf8(const wchar_t* src, char* dst, int dst_num_bytes) { SOKOL_ASSERT(src && dst && (dst_num_bytes > 1)); memset(dst, 0, dst_num_bytes); @@ -4792,6 +5100,22 @@ _SOKOL_PRIVATE void _sapp_win32_show_mouse(bool visible) { ShowCursor((BOOL)visible); } +_SOKOL_PRIVATE void _sapp_win32_capture_mouse(uint8_t btn_mask) { + if (0 == _sapp.win32.mouse_capture_mask) { + SetCapture(_sapp.win32.hwnd); + } + _sapp.win32.mouse_capture_mask |= btn_mask; +} + +_SOKOL_PRIVATE void _sapp_win32_release_mouse(uint8_t btn_mask) { + if (0 != _sapp.win32.mouse_capture_mask) { + _sapp.win32.mouse_capture_mask &= ~btn_mask; + if (0 == _sapp.win32.mouse_capture_mask) { + ReleaseCapture(); + } + } +} + _SOKOL_PRIVATE void _sapp_win32_lock_mouse(bool lock) { if (lock == _sapp.mouse.locked) { return; @@ -4799,6 +5123,7 @@ _SOKOL_PRIVATE void _sapp_win32_lock_mouse(bool lock) { _sapp.mouse.dx = 0.0f; _sapp.mouse.dy = 0.0f; _sapp.mouse.locked = lock; + _sapp_win32_release_mouse(0xFF); if (_sapp.mouse.locked) { /* store the current mouse position, so it can be restored when unlocked */ POINT pos; @@ -4854,128 +5179,6 @@ _SOKOL_PRIVATE void _sapp_win32_lock_mouse(bool lock) { } } -_SOKOL_PRIVATE void _sapp_win32_init_keytable(void) { - /* same as GLFW */ - _sapp.keycodes[0x00B] = SAPP_KEYCODE_0; - _sapp.keycodes[0x002] = SAPP_KEYCODE_1; - _sapp.keycodes[0x003] = SAPP_KEYCODE_2; - _sapp.keycodes[0x004] = SAPP_KEYCODE_3; - _sapp.keycodes[0x005] = SAPP_KEYCODE_4; - _sapp.keycodes[0x006] = SAPP_KEYCODE_5; - _sapp.keycodes[0x007] = SAPP_KEYCODE_6; - _sapp.keycodes[0x008] = SAPP_KEYCODE_7; - _sapp.keycodes[0x009] = SAPP_KEYCODE_8; - _sapp.keycodes[0x00A] = SAPP_KEYCODE_9; - _sapp.keycodes[0x01E] = SAPP_KEYCODE_A; - _sapp.keycodes[0x030] = SAPP_KEYCODE_B; - _sapp.keycodes[0x02E] = SAPP_KEYCODE_C; - _sapp.keycodes[0x020] = SAPP_KEYCODE_D; - _sapp.keycodes[0x012] = SAPP_KEYCODE_E; - _sapp.keycodes[0x021] = SAPP_KEYCODE_F; - _sapp.keycodes[0x022] = SAPP_KEYCODE_G; - _sapp.keycodes[0x023] = SAPP_KEYCODE_H; - _sapp.keycodes[0x017] = SAPP_KEYCODE_I; - _sapp.keycodes[0x024] = SAPP_KEYCODE_J; - _sapp.keycodes[0x025] = SAPP_KEYCODE_K; - _sapp.keycodes[0x026] = SAPP_KEYCODE_L; - _sapp.keycodes[0x032] = SAPP_KEYCODE_M; - _sapp.keycodes[0x031] = SAPP_KEYCODE_N; - _sapp.keycodes[0x018] = SAPP_KEYCODE_O; - _sapp.keycodes[0x019] = SAPP_KEYCODE_P; - _sapp.keycodes[0x010] = SAPP_KEYCODE_Q; - _sapp.keycodes[0x013] = SAPP_KEYCODE_R; - _sapp.keycodes[0x01F] = SAPP_KEYCODE_S; - _sapp.keycodes[0x014] = SAPP_KEYCODE_T; - _sapp.keycodes[0x016] = SAPP_KEYCODE_U; - _sapp.keycodes[0x02F] = SAPP_KEYCODE_V; - _sapp.keycodes[0x011] = SAPP_KEYCODE_W; - _sapp.keycodes[0x02D] = SAPP_KEYCODE_X; - _sapp.keycodes[0x015] = SAPP_KEYCODE_Y; - _sapp.keycodes[0x02C] = SAPP_KEYCODE_Z; - _sapp.keycodes[0x028] = SAPP_KEYCODE_APOSTROPHE; - _sapp.keycodes[0x02B] = SAPP_KEYCODE_BACKSLASH; - _sapp.keycodes[0x033] = SAPP_KEYCODE_COMMA; - _sapp.keycodes[0x00D] = SAPP_KEYCODE_EQUAL; - _sapp.keycodes[0x029] = SAPP_KEYCODE_GRAVE_ACCENT; - _sapp.keycodes[0x01A] = SAPP_KEYCODE_LEFT_BRACKET; - _sapp.keycodes[0x00C] = SAPP_KEYCODE_MINUS; - _sapp.keycodes[0x034] = SAPP_KEYCODE_PERIOD; - _sapp.keycodes[0x01B] = SAPP_KEYCODE_RIGHT_BRACKET; - _sapp.keycodes[0x027] = SAPP_KEYCODE_SEMICOLON; - _sapp.keycodes[0x035] = SAPP_KEYCODE_SLASH; - _sapp.keycodes[0x056] = SAPP_KEYCODE_WORLD_2; - _sapp.keycodes[0x00E] = SAPP_KEYCODE_BACKSPACE; - _sapp.keycodes[0x153] = SAPP_KEYCODE_DELETE; - _sapp.keycodes[0x14F] = SAPP_KEYCODE_END; - _sapp.keycodes[0x01C] = SAPP_KEYCODE_ENTER; - _sapp.keycodes[0x001] = SAPP_KEYCODE_ESCAPE; - _sapp.keycodes[0x147] = SAPP_KEYCODE_HOME; - _sapp.keycodes[0x152] = SAPP_KEYCODE_INSERT; - _sapp.keycodes[0x15D] = SAPP_KEYCODE_MENU; - _sapp.keycodes[0x151] = SAPP_KEYCODE_PAGE_DOWN; - _sapp.keycodes[0x149] = SAPP_KEYCODE_PAGE_UP; - _sapp.keycodes[0x045] = SAPP_KEYCODE_PAUSE; - _sapp.keycodes[0x146] = SAPP_KEYCODE_PAUSE; - _sapp.keycodes[0x039] = SAPP_KEYCODE_SPACE; - _sapp.keycodes[0x00F] = SAPP_KEYCODE_TAB; - _sapp.keycodes[0x03A] = SAPP_KEYCODE_CAPS_LOCK; - _sapp.keycodes[0x145] = SAPP_KEYCODE_NUM_LOCK; - _sapp.keycodes[0x046] = SAPP_KEYCODE_SCROLL_LOCK; - _sapp.keycodes[0x03B] = SAPP_KEYCODE_F1; - _sapp.keycodes[0x03C] = SAPP_KEYCODE_F2; - _sapp.keycodes[0x03D] = SAPP_KEYCODE_F3; - _sapp.keycodes[0x03E] = SAPP_KEYCODE_F4; - _sapp.keycodes[0x03F] = SAPP_KEYCODE_F5; - _sapp.keycodes[0x040] = SAPP_KEYCODE_F6; - _sapp.keycodes[0x041] = SAPP_KEYCODE_F7; - _sapp.keycodes[0x042] = SAPP_KEYCODE_F8; - _sapp.keycodes[0x043] = SAPP_KEYCODE_F9; - _sapp.keycodes[0x044] = SAPP_KEYCODE_F10; - _sapp.keycodes[0x057] = SAPP_KEYCODE_F11; - _sapp.keycodes[0x058] = SAPP_KEYCODE_F12; - _sapp.keycodes[0x064] = SAPP_KEYCODE_F13; - _sapp.keycodes[0x065] = SAPP_KEYCODE_F14; - _sapp.keycodes[0x066] = SAPP_KEYCODE_F15; - _sapp.keycodes[0x067] = SAPP_KEYCODE_F16; - _sapp.keycodes[0x068] = SAPP_KEYCODE_F17; - _sapp.keycodes[0x069] = SAPP_KEYCODE_F18; - _sapp.keycodes[0x06A] = SAPP_KEYCODE_F19; - _sapp.keycodes[0x06B] = SAPP_KEYCODE_F20; - _sapp.keycodes[0x06C] = SAPP_KEYCODE_F21; - _sapp.keycodes[0x06D] = SAPP_KEYCODE_F22; - _sapp.keycodes[0x06E] = SAPP_KEYCODE_F23; - _sapp.keycodes[0x076] = SAPP_KEYCODE_F24; - _sapp.keycodes[0x038] = SAPP_KEYCODE_LEFT_ALT; - _sapp.keycodes[0x01D] = SAPP_KEYCODE_LEFT_CONTROL; - _sapp.keycodes[0x02A] = SAPP_KEYCODE_LEFT_SHIFT; - _sapp.keycodes[0x15B] = SAPP_KEYCODE_LEFT_SUPER; - _sapp.keycodes[0x137] = SAPP_KEYCODE_PRINT_SCREEN; - _sapp.keycodes[0x138] = SAPP_KEYCODE_RIGHT_ALT; - _sapp.keycodes[0x11D] = SAPP_KEYCODE_RIGHT_CONTROL; - _sapp.keycodes[0x036] = SAPP_KEYCODE_RIGHT_SHIFT; - _sapp.keycodes[0x15C] = SAPP_KEYCODE_RIGHT_SUPER; - _sapp.keycodes[0x150] = SAPP_KEYCODE_DOWN; - _sapp.keycodes[0x14B] = SAPP_KEYCODE_LEFT; - _sapp.keycodes[0x14D] = SAPP_KEYCODE_RIGHT; - _sapp.keycodes[0x148] = SAPP_KEYCODE_UP; - _sapp.keycodes[0x052] = SAPP_KEYCODE_KP_0; - _sapp.keycodes[0x04F] = SAPP_KEYCODE_KP_1; - _sapp.keycodes[0x050] = SAPP_KEYCODE_KP_2; - _sapp.keycodes[0x051] = SAPP_KEYCODE_KP_3; - _sapp.keycodes[0x04B] = SAPP_KEYCODE_KP_4; - _sapp.keycodes[0x04C] = SAPP_KEYCODE_KP_5; - _sapp.keycodes[0x04D] = SAPP_KEYCODE_KP_6; - _sapp.keycodes[0x047] = SAPP_KEYCODE_KP_7; - _sapp.keycodes[0x048] = SAPP_KEYCODE_KP_8; - _sapp.keycodes[0x049] = SAPP_KEYCODE_KP_9; - _sapp.keycodes[0x04E] = SAPP_KEYCODE_KP_ADD; - _sapp.keycodes[0x053] = SAPP_KEYCODE_KP_DECIMAL; - _sapp.keycodes[0x135] = SAPP_KEYCODE_KP_DIVIDE; - _sapp.keycodes[0x11C] = SAPP_KEYCODE_KP_ENTER; - _sapp.keycodes[0x037] = SAPP_KEYCODE_KP_MULTIPLY; - _sapp.keycodes[0x04A] = SAPP_KEYCODE_KP_SUBTRACT; -} - /* updates current window and framebuffer size from the window's client rect, returns true if size has changed */ _SOKOL_PRIVATE bool _sapp_win32_update_dimensions(void) { RECT rect; @@ -5069,15 +5272,7 @@ _SOKOL_PRIVATE void _sapp_win32_char_event(uint32_t c, bool repeat) { } } -_SOKOL_PRIVATE void _sapp_win32_app_event(sapp_event_type type) { - if (_sapp_events_enabled()) { - _sapp_init_event(type); - _sapp_call_event(&_sapp.event); - } -} - _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - /* FIXME: refresh rendering during resize with a WM_TIMER event */ if (!_sapp.win32.in_create_window) { switch (uMsg) { case WM_CLOSE: @@ -5087,7 +5282,7 @@ _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM a change to intervene via sapp_cancel_quit() */ _sapp.quit_requested = true; - _sapp_win32_app_event(SAPP_EVENTTYPE_QUIT_REQUESTED); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_QUIT_REQUESTED); /* if user code hasn't intervened, quit the app */ if (_sapp.quit_requested) { _sapp.quit_ordered = true; @@ -5119,10 +5314,10 @@ _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM if (iconified != _sapp.win32.iconified) { _sapp.win32.iconified = iconified; if (iconified) { - _sapp_win32_app_event(SAPP_EVENTTYPE_ICONIFIED); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_ICONIFIED); } else { - _sapp_win32_app_event(SAPP_EVENTTYPE_RESTORED); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_RESTORED); } } } @@ -5130,28 +5325,34 @@ _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM case WM_SETCURSOR: if (_sapp.desc.user_cursor) { if (LOWORD(lParam) == HTCLIENT) { - _sapp_win32_app_event(SAPP_EVENTTYPE_UPDATE_CURSOR); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_UPDATE_CURSOR); return 1; } } break; case WM_LBUTTONDOWN: _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_LEFT); + _sapp_win32_capture_mouse(1<= 32)) { + _sapp_init_event(SAPP_EVENTTYPE_CHAR); + _sapp.event.modifiers = _sapp_uwp_mods(sender_window); + _sapp.event.char_code = c; + _sapp.event.key_repeat = repeat; + _sapp_call_event(&_sapp.event); + } +} + +_SOKOL_PRIVATE void _sapp_uwp_toggle_fullscreen(void) { + auto appView = winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView(); + _sapp.fullscreen = appView.IsFullScreenMode(); + if (!_sapp.fullscreen) { + appView.TryEnterFullScreenMode(); + } + else { + appView.ExitFullScreenMode(); + } + _sapp.fullscreen = appView.IsFullScreenMode(); +} + +namespace {/* Empty namespace to ensure internal linkage (same as _SOKOL_PRIVATE) */ + +// Controls all the DirectX device resources. +class DeviceResources { +public: + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + DeviceResources(); + ~DeviceResources(); + void SetWindow(winrt::Windows::UI::Core::CoreWindow const& window); + void SetLogicalSize(winrt::Windows::Foundation::Size logicalSize); + void SetCurrentOrientation(winrt::Windows::Graphics::Display::DisplayOrientations currentOrientation); + void SetDpi(float dpi); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify); + void Trim(); + void Present(); + winrt::Windows::Foundation::Size GetOutputSize() const { return m_outputSize; } + winrt::Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; } + ID3D11Device3* GetD3DDevice() const { return m_d3dDevice.get(); } + ID3D11DeviceContext3* GetD3DDeviceContext() const { return m_d3dContext.get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView1* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.get(); } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } + +private: + + // Swapchain Rotation Matrices (Z-rotation) + static inline const DirectX::XMFLOAT4X4 DeviceResources::m_rotation0 = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + static inline const DirectX::XMFLOAT4X4 DeviceResources::m_rotation90 = { + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + static inline const DirectX::XMFLOAT4X4 DeviceResources::m_rotation180 = { + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + static inline const DirectX::XMFLOAT4X4 DeviceResources::m_rotation270 = { + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void UpdateRenderTargetSize(); + DXGI_MODE_ROTATION ComputeDisplayRotation(); + bool SdkLayersAvailable(); + + // Direct3D objects. + winrt::com_ptr m_d3dDevice; + winrt::com_ptr m_d3dContext; + winrt::com_ptr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + winrt::com_ptr m_d3dRenderTarget; + winrt::com_ptr m_d3dRenderTargetView; + winrt::com_ptr m_d3dDepthStencil; + winrt::com_ptr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport = { }; + + // Cached reference to the Window. + winrt::agile_ref< winrt::Windows::UI::Core::CoreWindow> m_window; + + // Cached device properties. + D3D_FEATURE_LEVEL m_d3dFeatureLevel = D3D_FEATURE_LEVEL_9_1; + winrt::Windows::Foundation::Size m_d3dRenderTargetSize = { }; + winrt::Windows::Foundation::Size m_outputSize = { }; + winrt::Windows::Foundation::Size m_logicalSize = { }; + winrt::Windows::Graphics::Display::DisplayOrientations m_nativeOrientation = winrt::Windows::Graphics::Display::DisplayOrientations::None; + winrt::Windows::Graphics::Display::DisplayOrientations m_currentOrientation = winrt::Windows::Graphics::Display::DisplayOrientations::None; + float m_dpi = -1.0f; + + // Transforms used for display orientation. + DirectX::XMFLOAT4X4 m_orientationTransform3D; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify = nullptr; +}; + +// Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events. +struct App : winrt::implements { +public: + // IFrameworkViewSource Methods + winrt::Windows::ApplicationModel::Core::IFrameworkView CreateView() { return *this; } + + // IFrameworkView Methods. + virtual void Initialize(winrt::Windows::ApplicationModel::Core::CoreApplicationView const& applicationView); + virtual void SetWindow(winrt::Windows::UI::Core::CoreWindow const& window); + virtual void Load(winrt::hstring const& entryPoint); + virtual void Run(); + virtual void Uninitialize(); + +protected: + // Application lifecycle event handlers + void OnActivated(winrt::Windows::ApplicationModel::Core::CoreApplicationView const& applicationView, winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs const& args); + void OnSuspending(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::ApplicationModel::SuspendingEventArgs const& args); + void OnResuming(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::Foundation::IInspectable const& args); + + // Window event handlers + void OnWindowSizeChanged(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::WindowSizeChangedEventArgs const& args); + void OnVisibilityChanged(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::VisibilityChangedEventArgs const& args); + + // Navigation event handlers + void OnBackRequested(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Core::BackRequestedEventArgs const& args); + + // Input event handlers + void OnKeyDown(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::KeyEventArgs const& args); + void OnKeyUp(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::KeyEventArgs const& args); + void OnCharacterReceived(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::CharacterReceivedEventArgs const& args); + + // Pointer event handlers + void OnPointerEntered(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + void OnPointerExited(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + void OnPointerPressed(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + void OnPointerReleased(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + void OnPointerMoved(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + void OnPointerWheelChanged(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + + // DisplayInformation event handlers. + void OnDpiChanged(winrt::Windows::Graphics::Display::DisplayInformation const& sender, winrt::Windows::Foundation::IInspectable const& args); + void OnOrientationChanged(winrt::Windows::Graphics::Display::DisplayInformation const& sender, winrt::Windows::Foundation::IInspectable const& args); + void OnDisplayContentsInvalidated(winrt::Windows::Graphics::Display::DisplayInformation const& sender, winrt::Windows::Foundation::IInspectable const& args); + +private: + std::unique_ptr m_deviceResources; + bool m_windowVisible = true; +}; + +DeviceResources::DeviceResources() { + CreateDeviceResources(); +} + +DeviceResources::~DeviceResources() { + // Cleanup Sokol Context + _sapp.d3d11.device = nullptr; + _sapp.d3d11.device_context = nullptr; +} + +void DeviceResources::CreateDeviceResources() { + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + + #if defined(_DEBUG) + if (SdkLayersAvailable()) { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } + #endif + + // This array defines the set of DirectX hardware feature levels this app will support. + // Note the ordering should be preserved. + // Don't forget to declare your application's minimum required feature level in its + // description. All applications are assumed to support 9.1 unless otherwise stated. + D3D_FEATURE_LEVEL featureLevels[] = { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + + // Create the Direct3D 11 API device object and a corresponding context. + winrt::com_ptr device; + winrt::com_ptr context; + + HRESULT hr = D3D11CreateDevice( + nullptr, // Specify nullptr to use the default adapter. + D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver. + 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. + creationFlags, // Set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), // Size of the list above. + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Microsoft Store apps. + device.put(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.put() // Returns the device immediate context. + ); + + if (FAILED(hr)) { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // https://go.microsoft.com/fwlink/?LinkId=286690 + winrt::check_hresult( + D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. + 0, + creationFlags, + featureLevels, + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, + device.put(), + &m_d3dFeatureLevel, + context.put() + ) + ); + } + + // Store pointers to the Direct3D 11.3 API device and immediate context. + m_d3dDevice = device.as(); + m_d3dContext = context.as(); + + // Setup Sokol Context + _sapp.d3d11.device = m_d3dDevice.get(); + _sapp.d3d11.device_context = m_d3dContext.get(); +} + +void DeviceResources::CreateWindowSizeDependentResources() { + // Cleanup Sokol Context + _sapp.d3d11.rt = nullptr; + _sapp.d3d11.rtv = nullptr; + _sapp.d3d11.ds = nullptr; + _sapp.d3d11.dsv = nullptr; + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = { nullptr }; + m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); + m_d3dRenderTarget = nullptr; + m_d3dRenderTargetView = nullptr; + m_d3dDepthStencilView = nullptr; + m_d3dDepthStencil = nullptr; + m_d3dContext->Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr); + + UpdateRenderTargetSize(); + + // The width and height of the swap chain must be based on the window's + // natively-oriented width and height. If the window is not in the native + // orientation, the dimensions must be reversed. + DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation(); + + bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270; + m_d3dRenderTargetSize.Width = swapDimensions ? m_outputSize.Height : m_outputSize.Width; + m_d3dRenderTargetSize.Height = swapDimensions ? m_outputSize.Width : m_outputSize.Height; + + if (m_swapChain != nullptr) { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + 2, // Double-buffered swap chain. + lround(m_d3dRenderTargetSize.Width), + lround(m_d3dRenderTargetSize.Height), + DXGI_FORMAT_B8G8R8A8_UNORM, + 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) { + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else { + winrt::check_hresult(hr); + } + } + else { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + DXGI_SCALING scaling = (_sapp.uwp.dpi.content_scale == _sapp.uwp.dpi.window_scale) ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH; + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + + swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Match the size of the window. + swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height); + swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format. + swapChainDesc.Stereo = false; + swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling. + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency. + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Microsoft Store apps must use this SwapEffect. + swapChainDesc.Flags = 0; + swapChainDesc.Scaling = scaling; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + winrt::com_ptr dxgiDevice = m_d3dDevice.as(); + winrt::com_ptr dxgiAdapter; + winrt::check_hresult(dxgiDevice->GetAdapter(dxgiAdapter.put())); + winrt::com_ptr dxgiFactory; + winrt::check_hresult(dxgiAdapter->GetParent(__uuidof(IDXGIFactory4), dxgiFactory.put_void())); + winrt::com_ptr swapChain; + winrt::check_hresult(dxgiFactory->CreateSwapChainForCoreWindow(m_d3dDevice.get(), m_window.get().as<::IUnknown>().get(), &swapChainDesc, nullptr, swapChain.put())); + m_swapChain = swapChain.as(); + + // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and + // ensures that the application will only render after each VSync, minimizing power consumption. + winrt::check_hresult(dxgiDevice->SetMaximumFrameLatency(1)); + + // Setup Sokol Context + winrt::check_hresult(swapChain->GetDesc(&_sapp.d3d11.swap_chain_desc)); + _sapp.d3d11.swap_chain = m_swapChain.as().detach(); + } + + // Set the proper orientation for the swap chain, and generate 2D and + // 3D matrix transformations for rendering to the rotated swap chain. + // Note the rotation angle for the 2D and 3D transforms are different. + // This is due to the difference in coordinate spaces. Additionally, + // the 3D matrix is specified explicitly to avoid rounding errors. + switch (displayRotation) { + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = m_rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = m_rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = m_rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = m_rotation90; + break; + } + winrt::check_hresult(m_swapChain->SetRotation(displayRotation)); + + // Create a render target view of the swap chain back buffer. + winrt::check_hresult(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&m_d3dRenderTarget))); + winrt::check_hresult(m_d3dDevice->CreateRenderTargetView1(m_d3dRenderTarget.get(), nullptr, m_d3dRenderTargetView.put())); + + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC1 depthStencilDesc( + DXGI_FORMAT_D24_UNORM_S8_UINT, + lround(m_d3dRenderTargetSize.Width), + lround(m_d3dRenderTargetSize.Height), + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + winrt::check_hresult(m_d3dDevice->CreateTexture2D1(&depthStencilDesc, nullptr, m_d3dDepthStencil.put())); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + winrt::check_hresult( + m_d3dDevice->CreateDepthStencilView( + m_d3dDepthStencil.get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.put() + ) + ); + + // Set sokol window and framebuffer sizes + _sapp.window_width = (int) m_logicalSize.Width; + _sapp.window_height = (int) m_logicalSize.Height; + _sapp.framebuffer_width = lround(m_d3dRenderTargetSize.Width); + _sapp.framebuffer_height = lround(m_d3dRenderTargetSize.Height); + + // Setup Sokol Context + _sapp.d3d11.rt = m_d3dRenderTarget.as().get(); + _sapp.d3d11.rtv = m_d3dRenderTargetView.as().get(); + _sapp.d3d11.ds = m_d3dDepthStencil.as().get(); + _sapp.d3d11.dsv = m_d3dDepthStencilView.get(); + + // Sokol app is now valid + _sapp.valid = true; +} + +// Determine the dimensions of the render target and whether it will be scaled down. +void DeviceResources::UpdateRenderTargetSize() { + // Calculate the necessary render target size in pixels. + m_outputSize.Width = m_logicalSize.Width * _sapp.uwp.dpi.content_scale; + m_outputSize.Height = m_logicalSize.Height * _sapp.uwp.dpi.content_scale; + + // Prevent zero size DirectX content from being created. + m_outputSize.Width = std::max(m_outputSize.Width, 1.0f); + m_outputSize.Height = std::max(m_outputSize.Height, 1.0f); +} + +// This method is called when the CoreWindow is created (or re-created). +void DeviceResources::SetWindow(winrt::Windows::UI::Core::CoreWindow const& window) { + auto currentDisplayInformation = winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView(); + m_window = window; + m_logicalSize = winrt::Windows::Foundation::Size(window.Bounds().Width, window.Bounds().Height); + m_nativeOrientation = currentDisplayInformation.NativeOrientation(); + m_currentOrientation = currentDisplayInformation.CurrentOrientation(); + m_dpi = currentDisplayInformation.LogicalDpi(); + _sapp_uwp_configure_dpi(m_dpi); + CreateWindowSizeDependentResources(); +} + +// This method is called in the event handler for the SizeChanged event. +void DeviceResources::SetLogicalSize(winrt::Windows::Foundation::Size logicalSize) { + if (m_logicalSize != logicalSize) { + m_logicalSize = logicalSize; + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the DpiChanged event. +void DeviceResources::SetDpi(float dpi) { + if (dpi != m_dpi) { + m_dpi = dpi; + _sapp_uwp_configure_dpi(m_dpi); + // When the display DPI changes, the logical size of the window (measured in Dips) also changes and needs to be updated. + auto window = m_window.get(); + m_logicalSize = winrt::Windows::Foundation::Size(window.Bounds().Width, window.Bounds().Height); + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the OrientationChanged event. +void DeviceResources::SetCurrentOrientation(winrt::Windows::Graphics::Display::DisplayOrientations currentOrientation) { + if (m_currentOrientation != currentOrientation) { + m_currentOrientation = currentOrientation; + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DeviceResources::ValidateDevice() { + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + // First, get the information for the default adapter from when the device was created. + winrt::com_ptr dxgiDevice = m_d3dDevice.as< IDXGIDevice3>(); + winrt::com_ptr deviceAdapter; + winrt::check_hresult(dxgiDevice->GetAdapter(deviceAdapter.put())); + winrt::com_ptr deviceFactory; + winrt::check_hresult(deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory))); + winrt::com_ptr previousDefaultAdapter; + winrt::check_hresult(deviceFactory->EnumAdapters1(0, previousDefaultAdapter.put())); + DXGI_ADAPTER_DESC1 previousDesc; + winrt::check_hresult(previousDefaultAdapter->GetDesc1(&previousDesc)); + + // Next, get the information for the current default adapter. + winrt::com_ptr currentFactory; + winrt::check_hresult(CreateDXGIFactory1(IID_PPV_ARGS(¤tFactory))); + winrt::com_ptr currentDefaultAdapter; + winrt::check_hresult(currentFactory->EnumAdapters1(0, currentDefaultAdapter.put())); + DXGI_ADAPTER_DESC1 currentDesc; + winrt::check_hresult(currentDefaultAdapter->GetDesc1(¤tDesc)); + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart || + previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart || + FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { + // Release references to resources related to the old device. + dxgiDevice = nullptr; + deviceAdapter = nullptr; + deviceFactory = nullptr; + previousDefaultAdapter = nullptr; + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DeviceResources::HandleDeviceLost() { + m_swapChain = nullptr; + if (m_deviceNotify != nullptr) { + m_deviceNotify->OnDeviceLost(); + } + CreateDeviceResources(); + CreateWindowSizeDependentResources(); + if (m_deviceNotify != nullptr) { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Register our DeviceNotify to be informed on device lost and creation. +void DeviceResources::RegisterDeviceNotify(IDeviceNotify* deviceNotify) { + m_deviceNotify = deviceNotify; +} + +// Call this method when the app suspends. It provides a hint to the driver that the app +// is entering an idle state and that temporary buffers can be reclaimed for use by other apps. +void DeviceResources::Trim() { + m_d3dDevice.as()->Trim(); +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() { + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + DXGI_PRESENT_PARAMETERS parameters = { 0 }; + HRESULT hr = m_swapChain->Present1(1, 0, ¶meters); + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be entirely + // overwritten. If dirty or scroll rects are used, this call should be removed. + m_d3dContext->DiscardView1(m_d3dRenderTargetView.get(), nullptr, 0); + + // Discard the contents of the depth stencil. + m_d3dContext->DiscardView1(m_d3dDepthStencilView.get(), nullptr, 0); + + // If the device was removed either by a disconnection or a driver upgrade, we + // must recreate all device resources. + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) { + HandleDeviceLost(); + } + else { + winrt::check_hresult(hr); + } +} + +// This method determines the rotation between the display device's native orientation and the +// current display orientation. +DXGI_MODE_ROTATION DeviceResources::ComputeDisplayRotation() { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + // Note: NativeOrientation can only be Landscape or Portrait even though + // the DisplayOrientations enum has other values. + switch (m_nativeOrientation) { + case winrt::Windows::Graphics::Display::DisplayOrientations::Landscape: + switch (m_currentOrientation) { + case winrt::Windows::Graphics::Display::DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case winrt::Windows::Graphics::Display::DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case winrt::Windows::Graphics::Display::DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case winrt::Windows::Graphics::Display::DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case winrt::Windows::Graphics::Display::DisplayOrientations::Portrait: + switch (m_currentOrientation) { + case winrt::Windows::Graphics::Display::DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case winrt::Windows::Graphics::Display::DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case winrt::Windows::Graphics::Display::DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case winrt::Windows::Graphics::Display::DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + return rotation; +} + +// Check for SDK Layer support. +bool DeviceResources::SdkLayersAvailable() { + #if defined(_DEBUG) + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Microsoft Store apps. + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + return SUCCEEDED(hr); + #else + return false; + #endif +} + +// The first method called when the IFrameworkView is being created. +void App::Initialize(winrt::Windows::ApplicationModel::Core::CoreApplicationView const& applicationView) { + // Register event handlers for app lifecycle. This example includes Activated, so that we + // can make the CoreWindow active and start rendering on the window. + applicationView.Activated({ this, &App::OnActivated }); + + winrt::Windows::ApplicationModel::Core::CoreApplication::Suspending({ this, &App::OnSuspending }); + winrt::Windows::ApplicationModel::Core::CoreApplication::Resuming({ this, &App::OnResuming }); + + // At this point we have access to the device. + // We can create the device-dependent resources. + m_deviceResources = std::make_unique(); +} + +// Called when the CoreWindow object is created (or re-created). +void App::SetWindow(winrt::Windows::UI::Core::CoreWindow const& window) { + window.SizeChanged({ this, &App::OnWindowSizeChanged }); + window.VisibilityChanged({ this, &App::OnVisibilityChanged }); + + window.KeyDown({ this, &App::OnKeyDown }); + window.KeyUp({ this, &App::OnKeyUp }); + window.CharacterReceived({ this, &App::OnCharacterReceived }); + + window.PointerEntered({ this, &App::OnPointerEntered }); + window.PointerExited({ this, &App::OnPointerExited }); + window.PointerPressed({ this, &App::OnPointerPressed }); + window.PointerReleased({ this, &App::OnPointerReleased }); + window.PointerMoved({ this, &App::OnPointerMoved }); + window.PointerWheelChanged({ this, &App::OnPointerWheelChanged }); + + auto currentDisplayInformation = winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView(); + + currentDisplayInformation.DpiChanged({ this, &App::OnDpiChanged }); + currentDisplayInformation.OrientationChanged({ this, &App::OnOrientationChanged }); + winrt::Windows::Graphics::Display::DisplayInformation::DisplayContentsInvalidated({ this, &App::OnDisplayContentsInvalidated }); + + winrt::Windows::UI::Core::SystemNavigationManager::GetForCurrentView().BackRequested({ this, &App::OnBackRequested }); + + m_deviceResources->SetWindow(window); +} + +// Initializes scene resources, or loads a previously saved app state. +void App::Load(winrt::hstring const& entryPoint) { + _SOKOL_UNUSED(entryPoint); +} + +// This method is called after the window becomes active. +void App::Run() { + // NOTE: UWP will simply terminate an application, it's not possible to detect when an application is being closed + while (true) { + if (m_windowVisible) { + winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(winrt::Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); + _sapp_frame(); + m_deviceResources->Present(); + } + else { + winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(winrt::Windows::UI::Core::CoreProcessEventsOption::ProcessOneAndAllPending); + } + } +} + +// Required for IFrameworkView. +// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView +// class is torn down while the app is in the foreground. +void App::Uninitialize() { + // empty +} + +// Application lifecycle event handlers. +void App::OnActivated(winrt::Windows::ApplicationModel::Core::CoreApplicationView const& applicationView, winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs const& args) { + _SOKOL_UNUSED(args); + _SOKOL_UNUSED(applicationView); + auto appView = winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView(); + auto targetSize = winrt::Windows::Foundation::Size((float)_sapp.desc.width, (float)_sapp.desc.height); + appView.SetPreferredMinSize(targetSize); + appView.TryResizeView(targetSize); + + // Disabling this since it can only append the title to the app name (Title - Appname). + // There's no way of just setting a string to be the window title. + //appView.Title(_sapp.window_title_wide); + + // Run() won't start until the CoreWindow is activated. + winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().Activate(); + if (_sapp.desc.fullscreen) { + appView.TryEnterFullScreenMode(); + } + _sapp.fullscreen = appView.IsFullScreenMode(); +} + +void App::OnSuspending(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::ApplicationModel::SuspendingEventArgs const& args) { + _SOKOL_UNUSED(sender); + _SOKOL_UNUSED(args); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_SUSPENDED); +} + +void App::OnResuming(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::Foundation::IInspectable const& args) { + _SOKOL_UNUSED(args); + _SOKOL_UNUSED(sender); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_RESUMED); +} + +void App::OnWindowSizeChanged(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::WindowSizeChangedEventArgs const& args) { + _SOKOL_UNUSED(args); + m_deviceResources->SetLogicalSize(winrt::Windows::Foundation::Size(sender.Bounds().Width, sender.Bounds().Height)); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_RESIZED); +} + +void App::OnVisibilityChanged(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::VisibilityChangedEventArgs const& args) { + _SOKOL_UNUSED(sender); + m_windowVisible = args.Visible(); + _sapp_win32_uwp_app_event(m_windowVisible ? SAPP_EVENTTYPE_RESTORED : SAPP_EVENTTYPE_ICONIFIED); +} + +void App::OnBackRequested(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Core::BackRequestedEventArgs const& args) { + _SOKOL_UNUSED(sender); + args.Handled(true); +} + +void App::OnKeyDown(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::KeyEventArgs const& args) { + auto status = args.KeyStatus(); + _sapp_uwp_key_event(SAPP_EVENTTYPE_KEY_DOWN, sender, args); +} + +void App::OnKeyUp(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::KeyEventArgs const& args) { + auto status = args.KeyStatus(); + _sapp_uwp_key_event(SAPP_EVENTTYPE_KEY_UP, sender, args); +} + +void App::OnCharacterReceived(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::CharacterReceivedEventArgs const& args) { + _sapp_uwp_char_event(args.KeyCode(), args.KeyStatus().WasKeyDown, sender); +} + +void App::OnPointerEntered(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args) { + _SOKOL_UNUSED(args); + _sapp.uwp.mouse_tracked = true; + _sapp_uwp_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, sender); +} + +void App::OnPointerExited(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args) { + _SOKOL_UNUSED(args); + _sapp.uwp.mouse_tracked = false; + _sapp_uwp_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, sender); +} + +void App::OnPointerPressed(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args) { + _sapp_uwp_extract_mouse_button_events(sender, args); +} + +// NOTE: for some reason this event handler is never called?? +void App::OnPointerReleased(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args) { + _sapp_uwp_extract_mouse_button_events(sender, args); +} + +void App::OnPointerMoved(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args) { + auto position = args.CurrentPoint().Position(); + const float new_x = (float)(int)(position.X * _sapp.uwp.dpi.mouse_scale + 0.5f); + const float new_y = (float)(int)(position.Y * _sapp.uwp.dpi.mouse_scale + 0.5f); + // don't update dx/dy in the very first event + if (_sapp.mouse.pos_valid) { + _sapp.mouse.dx = new_x - _sapp.mouse.x; + _sapp.mouse.dy = new_y - _sapp.mouse.y; + } + _sapp.mouse.x = new_x; + _sapp.mouse.y = new_y; + _sapp.mouse.pos_valid = true; + if (!_sapp.uwp.mouse_tracked) { + _sapp.uwp.mouse_tracked = true; + _sapp_uwp_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, sender); + } + _sapp_uwp_mouse_event(SAPP_EVENTTYPE_MOUSE_MOVE, SAPP_MOUSEBUTTON_INVALID, sender); + + // HACK for detecting multiple mouse button presses + _sapp_uwp_extract_mouse_button_events(sender, args); +} + +void App::OnPointerWheelChanged(winrt::Windows::UI::Core::CoreWindow const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args) { + auto properties = args.CurrentPoint().Properties(); + _sapp_uwp_scroll_event((float)properties.MouseWheelDelta(), properties.IsHorizontalMouseWheel(), sender); +} + +void App::OnDpiChanged(winrt::Windows::Graphics::Display::DisplayInformation const& sender, winrt::Windows::Foundation::IInspectable const& args) { + // NOTE: UNTESTED + _SOKOL_UNUSED(args); + m_deviceResources->SetDpi(sender.LogicalDpi()); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_RESIZED); +} + +void App::OnOrientationChanged(winrt::Windows::Graphics::Display::DisplayInformation const& sender, winrt::Windows::Foundation::IInspectable const& args) { + // NOTE: UNTESTED + _SOKOL_UNUSED(args); + m_deviceResources->SetCurrentOrientation(sender.CurrentOrientation()); + _sapp_win32_uwp_app_event(SAPP_EVENTTYPE_RESIZED); +} + +void App::OnDisplayContentsInvalidated(winrt::Windows::Graphics::Display::DisplayInformation const& sender, winrt::Windows::Foundation::IInspectable const& args) { + // NOTE: UNTESTED + _SOKOL_UNUSED(args); + _SOKOL_UNUSED(sender); + m_deviceResources->ValidateDevice(); +} + +} /* End empty namespace */ + +_SOKOL_PRIVATE void _sapp_uwp_run(const sapp_desc* desc) { + _sapp_init_state(desc); + _sapp_win32_uwp_init_keytable(); + _sapp_win32_uwp_utf8_to_wide(_sapp.window_title, _sapp.window_title_wide, sizeof(_sapp.window_title_wide)); + winrt::Windows::ApplicationModel::Core::CoreApplication::Run(winrt::make()); +} + +#if !defined(SOKOL_NO_ENTRY) +#if defined(UNICODE) +int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { +#else +int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { +#endif + _SOKOL_UNUSED(hInstance); + _SOKOL_UNUSED(hPrevInstance); + _SOKOL_UNUSED(lpCmdLine); + _SOKOL_UNUSED(nCmdShow); + sapp_desc desc = sokol_main(0, nullptr); + _sapp_uwp_run(&desc); + return 0; +} +#endif /* SOKOL_NO_ENTRY */ +#endif /* _SAPP_UWP */ + /*== Android ================================================================*/ #if defined(_SAPP_ANDROID) @@ -7931,6 +9139,7 @@ _SOKOL_PRIVATE void _sapp_x11_process_event(XEvent* event) { const uint32_t mods = _sapp_x11_mod(event->xbutton.state); if (btn != SAPP_MOUSEBUTTON_INVALID) { _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, btn, mods); + _sapp.x11.mouse_buttons |= (1 << btn); } else { /* might be a scroll event */ @@ -7948,14 +9157,20 @@ _SOKOL_PRIVATE void _sapp_x11_process_event(XEvent* event) { const sapp_mousebutton btn = _sapp_x11_translate_button(event); if (btn != SAPP_MOUSEBUTTON_INVALID) { _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, btn, _sapp_x11_mod(event->xbutton.state)); + _sapp.x11.mouse_buttons &= ~(1 << btn); } } break; case EnterNotify: - _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + /* don't send enter/leave events while mouse button held down */ + if (0 == _sapp.x11.mouse_buttons) { + _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + } break; case LeaveNotify: - _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + if (0 == _sapp.x11.mouse_buttons) { + _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); + } break; case MotionNotify: if (!_sapp.mouse.locked) { @@ -8089,6 +9304,8 @@ SOKOL_API_IMPL int sapp_run(const sapp_desc* desc) { _sapp_emsc_run(desc); #elif defined(_SAPP_WIN32) _sapp_win32_run(desc); + #elif defined(_SAPP_UWP) + _sapp_uwp_run(desc); #elif defined(_SAPP_LINUX) _sapp_linux_run(desc); #else @@ -8201,6 +9418,8 @@ SOKOL_API_DECL void sapp_toggle_fullscreen(void) { _sapp_macos_toggle_fullscreen(); #elif defined(_SAPP_WIN32) _sapp_win32_toggle_fullscreen(); + #elif defined(_SAPP_UWP) + _sapp_uwp_toggle_fullscreen(); #elif defined(_SAPP_LINUX) _sapp_x11_toggle_fullscreen(); #endif @@ -8215,6 +9434,8 @@ SOKOL_API_IMPL void sapp_show_mouse(bool show) { _sapp_win32_show_mouse(show); #elif defined(_SAPP_LINUX) _sapp_x11_show_mouse(show); + #elif defined(_SAPP_UWP) + _sapp_uwp_show_mouse(show); #endif _sapp.mouse.shown = show; } @@ -8292,6 +9513,18 @@ SOKOL_API_IMPL const char* sapp_get_clipboard_string(void) { #endif } +SOKOL_API_IMPL void sapp_set_window_title(const char* title) { + SOKOL_ASSERT(title); + _sapp_strcpy(title, _sapp.window_title, sizeof(_sapp.window_title)); + #if defined(_SAPP_MACOS) + _sapp_macos_update_window_title(); + #elif defined(_SAPP_WIN32) + _sapp_win32_update_window_title(); + #elif defined(_SAPP_LINUX) + _sapp_x11_update_window_title(); + #endif +} + SOKOL_API_IMPL const void* sapp_metal_get_device(void) { SOKOL_ASSERT(_sapp.valid); #if defined(SOKOL_METAL) @@ -8347,12 +9580,6 @@ SOKOL_API_IMPL const void* sapp_macos_get_window(void) { #endif } -SOKOL_API_IMPL void sapp_macos_set_title(const char* title) { - #if defined(__APPLE__) && !TARGET_OS_IPHONE - [_sapp.macos.window setTitle: [NSString stringWithUTF8String:title]]; - #endif -} - SOKOL_API_IMPL const void* sapp_ios_get_window(void) { #if defined(_SAPP_IOS) const void* obj = (__bridge const void*) _sapp.ios.window; diff --git a/thirdparty/sokol/sokol_audio.h b/thirdparty/sokol/sokol_audio.h index dd6d2d63e2..baf74eaf31 100644 --- a/thirdparty/sokol/sokol_audio.h +++ b/thirdparty/sokol/sokol_audio.h @@ -62,8 +62,8 @@ callback function running in a separate thread, for such cases Sokol Audio provides the push-model as a convenience. - SOKOL AUDIO AND SOLOUD - ====================== + SOKOL AUDIO, SOLOUD AND MINIAUDIO + ================================= The WASAPI, ALSA, OpenSLES and CoreAudio backend code has been taken from the SoLoud library (with some modifications, so any bugs in there are most likely my fault). If you need a more fully-featured audio solution, check @@ -71,6 +71,11 @@ https://github.com/jarikomppa/soloud + Another alternative which feature-wise is somewhere inbetween SoLoud and + sokol-audio might be MiniAudio: + + https://github.com/mackron/miniaudio + GLOSSARY ======== - stream buffer: @@ -480,8 +485,16 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc); #endif #include #include - #pragma comment (lib, "kernel32.lib") - #pragma comment (lib, "ole32.lib") + #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) + #define SOKOL_WIN32_NO_MMDEVICE + #pragma comment (lib, "WindowsApp.lib") + #else + #pragma comment (lib, "kernel32.lib") + #pragma comment (lib, "ole32.lib") + #if defined(SOKOL_WIN32_NO_MMDEVICE) + #pragma comment (lib, "mmdevapi.lib") + #endif + #endif #endif #if defined(SOKOL_DUMMY_BACKEND) @@ -509,6 +522,8 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc); static const IID _saudio_IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35, { 0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6 } }; static const CLSID _saudio_CLSID_IMMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c, { 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e } }; static const IID _saudio_IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483,{ 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2 } }; + static const IID _saudio_IID_Devinterface_Audio_Render = { 0xe6327cad, 0xdcec, 0x4949, {0xae, 0x8a, 0x99, 0x1e, 0x97, 0x6a, 0x79, 0xd2 } }; + static const IID _saudio_IID_IActivateAudioInterface_Completion_Handler = { 0x94ea2b94, 0xe9cc, 0x49e0, {0xc0, 0xff, 0xee, 0x64, 0xca, 0x8f, 0x5b, 0x90} }; #if defined(__cplusplus) #define _SOKOL_AUDIO_WIN32COM_ID(x) (x) #else @@ -634,8 +649,15 @@ typedef struct { } _saudio_wasapi_thread_data_t; typedef struct { +#if defined(SOKOL_WIN32_NO_MMDEVICE) + LPOLESTR interface_activation_audio_interface_uid_string; + IActivateAudioInterfaceAsyncOperation* interface_activation_operation; + BOOL interface_activation_success; + HANDLE interface_activation_mutex; +#else IMMDeviceEnumerator* device_enumerator; IMMDevice* device; +#endif IAudioClient* audio_client; IAudioRenderClient* render_client; int si16_bytes_per_frame; @@ -1099,6 +1121,48 @@ _SOKOL_PRIVATE void _saudio_backend_shutdown(void) { /*=== WASAPI BACKEND IMPLEMENTATION ==========================================*/ #elif defined(_WIN32) +#if defined(SOKOL_WIN32_NO_MMDEVICE) +/* Minimal implementation of an IActivateAudioInterfaceCompletionHandler COM object in plain C. + Meant to be a static singleton (always one reference when add/remove reference) + and implements IUnknown and IActivateAudioInterfaceCompletionHandler when queryinterface'd + + Do not know why but IActivateAudioInterfaceCompletionHandler's GUID is not the one system queries for, + so I'm advertising the one actually requested. +*/ +_SOKOL_PRIVATE HRESULT STDMETHODCALLTYPE _saudio_interface_completion_handler_queryinterface(IActivateAudioInterfaceCompletionHandler* instance, REFIID riid, void** ppvObject) { + if (!ppvObject) { + return E_POINTER; + } + + if (IsEqualIID(riid, _SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IActivateAudioInterface_Completion_Handler)) || IsEqualIID(riid, _SOKOL_AUDIO_WIN32COM_ID(IID_IUnknown))) + { + *ppvObject = (void*)instance; + return S_OK; + } + + *ppvObject = NULL; + return E_NOINTERFACE; +} + +_SOKOL_PRIVATE ULONG STDMETHODCALLTYPE _saudio_interface_completion_handler_addref_release(IActivateAudioInterfaceCompletionHandler* instance) { + _SOKOL_UNUSED(instance); + return 1; +} + +_SOKOL_PRIVATE HRESULT STDMETHODCALLTYPE _saudio_backend_activate_audio_interface_cb(IActivateAudioInterfaceCompletionHandler* instance, IActivateAudioInterfaceAsyncOperation* activateOperation) { + _SOKOL_UNUSED(instance); + WaitForSingleObject(_saudio.backend.interface_activation_mutex, INFINITE); + _saudio.backend.interface_activation_success = TRUE; + HRESULT activation_result; + if (FAILED(activateOperation->lpVtbl->GetActivateResult(activateOperation, &activation_result, (IUnknown**)(&_saudio.backend.audio_client))) || FAILED(activation_result)) { + _saudio.backend.interface_activation_success = FALSE; + } + + ReleaseMutex(_saudio.backend.interface_activation_mutex); + return S_OK; +} +#endif + /* fill intermediate buffer with new data and reset buffer_pos */ _SOKOL_PRIVATE void _saudio_wasapi_fill_buffer(void) { if (_saudio_has_callback()) { @@ -1172,6 +1236,16 @@ _SOKOL_PRIVATE void _saudio_wasapi_release(void) { IAudioClient_Release(_saudio.backend.audio_client); _saudio.backend.audio_client = 0; } +#if defined(SOKOL_WIN32_NO_MMDEVICE) + if (_saudio.backend.interface_activation_audio_interface_uid_string) { + CoTaskMemFree(_saudio.backend.interface_activation_audio_interface_uid_string); + _saudio.backend.interface_activation_audio_interface_uid_string = 0; + } + if (_saudio.backend.interface_activation_operation) { + IActivateAudioInterfaceAsyncOperation_Release(_saudio.backend.interface_activation_operation); + _saudio.backend.interface_activation_operation = 0; + } +#else if (_saudio.backend.device) { IMMDevice_Release(_saudio.backend.device); _saudio.backend.device = 0; @@ -1180,6 +1254,7 @@ _SOKOL_PRIVATE void _saudio_wasapi_release(void) { IMMDeviceEnumerator_Release(_saudio.backend.device_enumerator); _saudio.backend.device_enumerator = 0; } +#endif if (0 != _saudio.backend.thread.buffer_end_event) { CloseHandle(_saudio.backend.thread.buffer_end_event); _saudio.backend.thread.buffer_end_event = 0; @@ -1188,15 +1263,57 @@ _SOKOL_PRIVATE void _saudio_wasapi_release(void) { _SOKOL_PRIVATE bool _saudio_backend_init(void) { REFERENCE_TIME dur; - if (FAILED(CoInitializeEx(0, COINIT_MULTITHREADED))) { - SOKOL_LOG("sokol_audio wasapi: CoInitializeEx failed"); - return false; - } + /* UWP Threads are CoInitialized by default with a different threading model, and this call fails + See https://github.com/Microsoft/cppwinrt/issues/6#issuecomment-253930637 */ +#if (defined(WINAPI_FAMILY_PARTITION) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) + /* CoInitializeEx could have been called elsewhere already, in which + case the function returns with S_FALSE (thus it doesn't make much + sense to check the result) + */ + HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED); + _SOKOL_UNUSED(hr); +#endif _saudio.backend.thread.buffer_end_event = CreateEvent(0, FALSE, FALSE, 0); if (0 == _saudio.backend.thread.buffer_end_event) { SOKOL_LOG("sokol_audio wasapi: failed to create buffer_end_event"); goto error; } +#if defined(SOKOL_WIN32_NO_MMDEVICE) + _saudio.backend.interface_activation_mutex = CreateMutexA(NULL, FALSE, "interface_activation_mutex"); + if (_saudio.backend.interface_activation_mutex == NULL) { + SOKOL_LOG("sokol_audio wasapi: failed to create interface activation mutex"); + goto error; + } + if (FAILED(StringFromIID(_SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_Devinterface_Audio_Render), &_saudio.backend.interface_activation_audio_interface_uid_string))) { + SOKOL_LOG("sokol_audio wasapi: failed to get default audio device ID string"); + goto error; + } + + /* static instance of the fake COM object */ + static IActivateAudioInterfaceCompletionHandlerVtbl completion_handler_interface_vtable = { + _saudio_interface_completion_handler_queryinterface, + _saudio_interface_completion_handler_addref_release, + _saudio_interface_completion_handler_addref_release, + _saudio_backend_activate_audio_interface_cb + }; + static IActivateAudioInterfaceCompletionHandler completion_handler_interface = { &completion_handler_interface_vtable }; + + if (FAILED(ActivateAudioInterfaceAsync(_saudio.backend.interface_activation_audio_interface_uid_string, _SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IAudioClient), NULL, &completion_handler_interface, &_saudio.backend.interface_activation_operation))) { + SOKOL_LOG("sokol_audio wasapi: failed to get default audio device ID string"); + goto error; + } + while (!(_saudio.backend.audio_client)) { + if (WaitForSingleObject(_saudio.backend.interface_activation_mutex, 10) != WAIT_TIMEOUT) { + ReleaseMutex(_saudio.backend.interface_activation_mutex); + } + } + + if (!(_saudio.backend.interface_activation_success)) { + SOKOL_LOG("sokol_audio wasapi: interface activation failed. Unable to get audio client"); + goto error; + } + +#else if (FAILED(CoCreateInstance(_SOKOL_AUDIO_WIN32COM_ID(_saudio_CLSID_IMMDeviceEnumerator), 0, CLSCTX_ALL, _SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IMMDeviceEnumerator), @@ -1220,6 +1337,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) { SOKOL_LOG("sokol_audio wasapi: device activate failed"); goto error; } +#endif WAVEFORMATEX fmt; memset(&fmt, 0, sizeof(fmt)); fmt.nChannels = (WORD) _saudio.num_channels; @@ -1286,7 +1404,10 @@ _SOKOL_PRIVATE void _saudio_backend_shutdown(void) { IAudioClient_Stop(_saudio.backend.audio_client); } _saudio_wasapi_release(); + +#if (defined(WINAPI_FAMILY_PARTITION) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) CoUninitialize(); +#endif } /*=== EMSCRIPTEN BACKEND IMPLEMENTATION ======================================*/ diff --git a/thirdparty/sokol/sokol_gfx.h b/thirdparty/sokol/sokol_gfx.h old mode 100755 new mode 100644 index 21f2a0101e..57cde6cb05 --- a/thirdparty/sokol/sokol_gfx.h +++ b/thirdparty/sokol/sokol_gfx.h @@ -2027,6 +2027,11 @@ typedef struct sg_pass_info { The sg_desc struct contains configuration values for sokol_gfx, it is used as parameter to the sg_setup() call. + NOTE that all callback function pointers come in two versions, one without + a userdata pointer, and one with a userdata pointer. You would + either initialize one or the other depending on whether you pass data + to your callbacks. + FIXME: explain the various configuration options The default configuration is: @@ -2065,13 +2070,18 @@ typedef struct sg_pass_info { .context.metal.device a pointer to the MTLDevice object .context.metal.renderpass_descriptor_cb - a C callback function to obtain the MTLRenderPassDescriptor for the + .context.metal_renderpass_descriptor_userdata_cb + A C callback function to obtain the MTLRenderPassDescriptor for the current frame when rendering to the default framebuffer, will be called - in sg_begin_default_pass() + in sg_begin_default_pass(). .context.metal.drawable_cb + .context.metal.drawable_userdata_cb a C callback function to obtain a MTLDrawable for the current frame when rendering to the default framebuffer, will be called in sg_end_pass() of the default pass + .context.metal.user_data + optional user data pointer passed to the userdata versions of + callback functions D3D11 specific: .context.d3d11.device @@ -2080,15 +2090,20 @@ typedef struct sg_pass_info { .context.d3d11.device_context a pointer to the ID3D11DeviceContext object .context.d3d11.render_target_view_cb + .context.d3d11.render_target_view_userdata_cb a C callback function to obtain a pointer to the current ID3D11RenderTargetView object of the default framebuffer, this function will be called in sg_begin_pass() when rendering to the default framebuffer .context.d3d11.depth_stencil_view_cb + .context.d3d11.depth_stencil_view_userdata_cb a C callback function to obtain a pointer to the current ID3D11DepthStencilView object of the default framebuffer, this function will be called in sg_begin_pass() when rendering to the default framebuffer + .context.metal.user_data + optional user data pointer passed to the userdata versions of + callback functions WebGPU specific: .context.wgpu.device @@ -2096,14 +2111,20 @@ typedef struct sg_pass_info { .context.wgpu.render_format WGPUTextureFormat of the swap chain surface .context.wgpu.render_view_cb + .context.wgpu.render_view_userdata_cb callback to get the current WGPUTextureView of the swapchain's rendering attachment (may be an MSAA surface) .context.wgpu.resolve_view_cb + .context.wgpu.resolve_view_userdata_cb callback to get the current WGPUTextureView of the swapchain's MSAA-resolve-target surface, must return 0 if not MSAA rendering .context.wgpu.depth_stencil_view_cb + .context.wgpu.depth_stencil_view_userdata_cb callback to get current default-pass depth-stencil-surface WGPUTextureView the pixel format of the default WGPUTextureView must be WGPUTextureFormat_Depth24Plus8 + .context.metal.user_data + optional user data pointer passed to the userdata versions of + callback functions When using sokol_gfx.h and sokol_app.h together, consider using the helper function sapp_sgcontext() in the sokol_glue.h header to @@ -2118,21 +2139,31 @@ typedef struct sg_gl_context_desc { typedef struct sg_mtl_context_desc { const void* device; const void* (*renderpass_descriptor_cb)(void); + const void* (*renderpass_descriptor_userdata_cb)(void*); const void* (*drawable_cb)(void); + const void* (*drawable_userdata_cb)(void*); + void* user_data; } sg_metal_context_desc; typedef struct sg_d3d11_context_desc { const void* device; const void* device_context; const void* (*render_target_view_cb)(void); + const void* (*render_target_view_userdata_cb)(void*); const void* (*depth_stencil_view_cb)(void); + const void* (*depth_stencil_view_userdata_cb)(void*); + void* user_data; } sg_d3d11_context_desc; typedef struct sg_wgpu_context_desc { const void* device; /* WGPUDevice */ const void* (*render_view_cb)(void); /* returns WGPUTextureView */ + const void* (*render_view_userdata_cb)(void*); const void* (*resolve_view_cb)(void); /* returns WGPUTextureView */ + const void* (*resolve_view_userdata_cb)(void*); const void* (*depth_stencil_view_cb)(void); /* returns WGPUTextureView, must be WGPUTextureFormat_Depth24Plus8 */ + const void* (*depth_stencil_view_userdata_cb)(void*); + void* user_data; } sg_wgpu_context_desc; typedef struct sg_context_desc { @@ -2497,12 +2528,6 @@ inline void sg_init_pass(sg_pass pass_id, const sg_pass_desc& desc) { return sg_ #ifndef D3D11_NO_HELPERS #define D3D11_NO_HELPERS #endif - #ifndef CINTERFACE - #define CINTERFACE - #endif - #ifndef COBJMACROS - #define COBJMACROS - #endif #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -3166,7 +3191,10 @@ typedef struct { ID3D11Device* dev; ID3D11DeviceContext* ctx; const void* (*rtv_cb)(void); + const void* (*rtv_userdata_cb)(void*); const void* (*dsv_cb)(void); + const void* (*dsv_userdata_cb)(void*); + void* user_data; bool in_pass; bool use_indexed_draw; int cur_width; @@ -3310,7 +3338,10 @@ typedef struct { typedef struct { bool valid; const void*(*renderpass_descriptor_cb)(void); + const void*(*renderpass_descriptor_userdata_cb)(void*); const void*(*drawable_cb)(void); + const void*(*drawable_userdata_cb)(void*); + void* user_data; uint32_t frame_index; uint32_t cur_frame_rotate_index; uint32_t ub_size; @@ -3444,8 +3475,12 @@ typedef struct { int cur_height; WGPUDevice dev; WGPUTextureView (*render_view_cb)(void); + WGPUTextureView (*render_view_userdata_cb)(void*); WGPUTextureView (*resolve_view_cb)(void); + WGPUTextureView (*resolve_view_userdata_cb)(void*); WGPUTextureView (*depth_stencil_view_cb)(void); + WGPUTextureView (*depth_stencil_view_userdata_cb)(void*); + void* user_data; WGPUQueue queue; WGPUCommandEncoder render_cmd_enc; WGPUCommandEncoder staging_cmd_enc; @@ -6847,6 +6882,371 @@ _SOKOL_PRIVATE void _sg_gl_update_image(_sg_image_t* img, const sg_image_content /*== D3D11 BACKEND IMPLEMENTATION ============================================*/ #elif defined(SOKOL_D3D11) +#if defined(__cplusplus) +#define _sg_d3d11_AddRef(self) (self)->AddRef() +#else +#define _sg_d3d11_AddRef(self) (self)->lpVtbl->AddRef(self) +#endif + +#if defined(__cplusplus) +#define _sg_d3d11_Release(self) (self)->Release() +#else +#define _sg_d3d11_Release(self) (self)->lpVtbl->Release(self) +#endif + +/*-- D3D11 C/C++ wrappers ----------------------------------------------------*/ +static inline HRESULT _sg_d3d11_CheckFormatSupport(ID3D11Device* self, DXGI_FORMAT Format, UINT* pFormatSupport) { + #if defined(__cplusplus) + return self->CheckFormatSupport(Format, pFormatSupport); + #else + return self->lpVtbl->CheckFormatSupport(self, Format, pFormatSupport); + #endif +} + +static inline void _sg_d3d11_OMSetRenderTargets(ID3D11DeviceContext* self, UINT NumViews, ID3D11RenderTargetView* const* ppRenderTargetViews, ID3D11DepthStencilView *pDepthStencilView) { + #if defined(__cplusplus) + self->OMSetRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView); + #else + self->lpVtbl->OMSetRenderTargets(self, NumViews, ppRenderTargetViews, pDepthStencilView); + #endif +} + +static inline void _sg_d3d11_RSSetState(ID3D11DeviceContext* self, ID3D11RasterizerState* pRasterizerState) { + #if defined(__cplusplus) + self->RSSetState(pRasterizerState); + #else + self->lpVtbl->RSSetState(self, pRasterizerState); + #endif +} + +static inline void _sg_d3d11_OMSetDepthStencilState(ID3D11DeviceContext* self, ID3D11DepthStencilState* pDepthStencilState, UINT StencilRef) { + #if defined(__cplusplus) + self->OMSetDepthStencilState(pDepthStencilState, StencilRef); + #else + self->lpVtbl->OMSetDepthStencilState(self, pDepthStencilState, StencilRef); + #endif +} + +static inline void _sg_d3d11_OMSetBlendState(ID3D11DeviceContext* self, ID3D11BlendState* pBlendState, const FLOAT BlendFactor[4], UINT SampleMask) { + #if defined(__cplusplus) + self->OMSetBlendState(pBlendState, BlendFactor, SampleMask); + #else + self->lpVtbl->OMSetBlendState(self, pBlendState, BlendFactor, SampleMask); + #endif +} + +static inline void _sg_d3d11_IASetVertexBuffers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppVertexBuffers, const UINT* pStrides, const UINT* pOffsets) { + #if defined(__cplusplus) + self->IASetVertexBuffers(StartSlot, NumBuffers, ppVertexBuffers, pStrides, pOffsets); + #else + self->lpVtbl->IASetVertexBuffers(self, StartSlot, NumBuffers, ppVertexBuffers, pStrides, pOffsets); + #endif +} + +static inline void _sg_d3d11_IASetIndexBuffer(ID3D11DeviceContext* self, ID3D11Buffer* pIndexBuffer, DXGI_FORMAT Format, UINT Offset) { + #if defined(__cplusplus) + self->IASetIndexBuffer(pIndexBuffer, Format, Offset); + #else + self->lpVtbl->IASetIndexBuffer(self, pIndexBuffer, Format, Offset); + #endif +} + +static inline void _sg_d3d11_IASetInputLayout(ID3D11DeviceContext* self, ID3D11InputLayout* pInputLayout) { + #if defined(__cplusplus) + self->IASetInputLayout(pInputLayout); + #else + self->lpVtbl->IASetInputLayout(self, pInputLayout); + #endif +} + +static inline void _sg_d3d11_VSSetShader(ID3D11DeviceContext* self, ID3D11VertexShader* pVertexShader, ID3D11ClassInstance* const* ppClassInstances, UINT NumClassInstances) { + #if defined(__cplusplus) + self->VSSetShader(pVertexShader, ppClassInstances, NumClassInstances); + #else + self->lpVtbl->VSSetShader(self, pVertexShader, ppClassInstances, NumClassInstances); + #endif +} + +static inline void _sg_d3d11_PSSetShader(ID3D11DeviceContext* self, ID3D11PixelShader* pPixelShader, ID3D11ClassInstance* const* ppClassInstances, UINT NumClassInstances) { + #if defined(__cplusplus) + self->PSSetShader(pPixelShader, ppClassInstances, NumClassInstances); + #else + self->lpVtbl->PSSetShader(self, pPixelShader, ppClassInstances, NumClassInstances); + #endif +} + +static inline void _sg_d3d11_VSSetConstantBuffers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers) { + #if defined(__cplusplus) + self->VSSetConstantBuffers(StartSlot, NumBuffers, ppConstantBuffers); + #else + self->lpVtbl->VSSetConstantBuffers(self, StartSlot, NumBuffers, ppConstantBuffers); + #endif +} + +static inline void _sg_d3d11_PSSetConstantBuffers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers) { + #if defined(__cplusplus) + self->PSSetConstantBuffers(StartSlot, NumBuffers, ppConstantBuffers); + #else + self->lpVtbl->PSSetConstantBuffers(self, StartSlot, NumBuffers, ppConstantBuffers); + #endif +} + +static inline void _sg_d3d11_VSSetShaderResources(ID3D11DeviceContext* self, UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView* const* ppShaderResourceViews) { + #if defined(__cplusplus) + self->VSSetShaderResources(StartSlot, NumViews, ppShaderResourceViews); + #else + self->lpVtbl->VSSetShaderResources(self, StartSlot, NumViews, ppShaderResourceViews); + #endif +} + +static inline void _sg_d3d11_PSSetShaderResources(ID3D11DeviceContext* self, UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView* const* ppShaderResourceViews) { + #if defined(__cplusplus) + self->PSSetShaderResources(StartSlot, NumViews, ppShaderResourceViews); + #else + self->lpVtbl->PSSetShaderResources(self, StartSlot, NumViews, ppShaderResourceViews); + #endif +} + +static inline void _sg_d3d11_VSSetSamplers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumSamplers, ID3D11SamplerState* const* ppSamplers) { + #if defined(__cplusplus) + self->VSSetSamplers(StartSlot, NumSamplers, ppSamplers); + #else + self->lpVtbl->VSSetSamplers(self, StartSlot, NumSamplers, ppSamplers); + #endif +} + +static inline void _sg_d3d11_PSSetSamplers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumSamplers, ID3D11SamplerState* const* ppSamplers) { + #if defined(__cplusplus) + self->PSSetSamplers(StartSlot, NumSamplers, ppSamplers); + #else + self->lpVtbl->PSSetSamplers(self, StartSlot, NumSamplers, ppSamplers); + #endif +} + +static inline HRESULT _sg_d3d11_CreateBuffer(ID3D11Device* self, const D3D11_BUFFER_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Buffer** ppBuffer) { + #if defined(__cplusplus) + return self->CreateBuffer(pDesc, pInitialData, ppBuffer); + #else + return self->lpVtbl->CreateBuffer(self, pDesc, pInitialData, ppBuffer); + #endif +} + +static inline HRESULT _sg_d3d11_CreateTexture2D(ID3D11Device* self, const D3D11_TEXTURE2D_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Texture2D** ppTexture2D) { + #if defined(__cplusplus) + return self->CreateTexture2D(pDesc, pInitialData, ppTexture2D); + #else + return self->lpVtbl->CreateTexture2D(self, pDesc, pInitialData, ppTexture2D); + #endif +} + +static inline HRESULT _sg_d3d11_CreateShaderResourceView(ID3D11Device* self, ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRView) { + #if defined(__cplusplus) + return self->CreateShaderResourceView(pResource, pDesc, ppSRView); + #else + return self->lpVtbl->CreateShaderResourceView(self, pResource, pDesc, ppSRView); + #endif +} + +static inline HRESULT _sg_d3d11_CreateTexture3D(ID3D11Device* self, const D3D11_TEXTURE3D_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Texture3D** ppTexture3D) { + #if defined(__cplusplus) + return self->CreateTexture3D(pDesc, pInitialData, ppTexture3D); + #else + return self->lpVtbl->CreateTexture3D(self, pDesc, pInitialData, ppTexture3D); + #endif +} + +static inline HRESULT _sg_d3d11_CreateSamplerState(ID3D11Device* self, const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState) { + #if defined(__cplusplus) + return self->CreateSamplerState(pSamplerDesc, ppSamplerState); + #else + return self->lpVtbl->CreateSamplerState(self, pSamplerDesc, ppSamplerState); + #endif +} + +static inline LPVOID _sg_d3d11_GetBufferPointer(ID3D10Blob* self) { + #if defined(__cplusplus) + return self->GetBufferPointer(); + #else + return self->lpVtbl->GetBufferPointer(self); + #endif +} + +static inline SIZE_T _sg_d3d11_GetBufferSize(ID3D10Blob* self) { + #if defined(__cplusplus) + return self->GetBufferSize(); + #else + return self->lpVtbl->GetBufferSize(self); + #endif +} + +static inline HRESULT _sg_d3d11_CreateVertexShader(ID3D11Device* self, const void* pShaderBytecode, SIZE_T BytecodeLength, ID3D11ClassLinkage* pClassLinkage, ID3D11VertexShader** ppVertexShader) { + #if defined(__cplusplus) + return self->CreateVertexShader(pShaderBytecode, BytecodeLength, pClassLinkage, ppVertexShader); + #else + return self->lpVtbl->CreateVertexShader(self, pShaderBytecode, BytecodeLength, pClassLinkage, ppVertexShader); + #endif +} + +static inline HRESULT _sg_d3d11_CreatePixelShader(ID3D11Device* self, const void* pShaderBytecode, SIZE_T BytecodeLength, ID3D11ClassLinkage* pClassLinkage, ID3D11PixelShader** ppPixelShader) { + #if defined(__cplusplus) + return self->CreatePixelShader(pShaderBytecode, BytecodeLength, pClassLinkage, ppPixelShader); + #else + return self->lpVtbl->CreatePixelShader(self, pShaderBytecode, BytecodeLength, pClassLinkage, ppPixelShader); + #endif +} + +static inline HRESULT _sg_d3d11_CreateInputLayout(ID3D11Device* self, const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, UINT NumElements, const void* pShaderBytecodeWithInputSignature, SIZE_T BytecodeLength, ID3D11InputLayout **ppInputLayout) { + #if defined(__cplusplus) + return self->CreateInputLayout(pInputElementDescs, NumElements, pShaderBytecodeWithInputSignature, BytecodeLength, ppInputLayout); + #else + return self->lpVtbl->CreateInputLayout(self, pInputElementDescs, NumElements, pShaderBytecodeWithInputSignature, BytecodeLength, ppInputLayout); + #endif +} + +static inline HRESULT _sg_d3d11_CreateRasterizerState(ID3D11Device* self, const D3D11_RASTERIZER_DESC* pRasterizerDesc, ID3D11RasterizerState** ppRasterizerState) { + #if defined(__cplusplus) + return self->CreateRasterizerState(pRasterizerDesc, ppRasterizerState); + #else + return self->lpVtbl->CreateRasterizerState(self, pRasterizerDesc, ppRasterizerState); + #endif +} + +static inline HRESULT _sg_d3d11_CreateDepthStencilState(ID3D11Device* self, const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, ID3D11DepthStencilState** ppDepthStencilState) { + #if defined(__cplusplus) + return self->CreateDepthStencilState(pDepthStencilDesc, ppDepthStencilState); + #else + return self->lpVtbl->CreateDepthStencilState(self, pDepthStencilDesc, ppDepthStencilState); + #endif +} + +static inline HRESULT _sg_d3d11_CreateBlendState(ID3D11Device* self, const D3D11_BLEND_DESC* pBlendStateDesc, ID3D11BlendState** ppBlendState) { + #if defined(__cplusplus) + return self->CreateBlendState(pBlendStateDesc, ppBlendState); + #else + return self->lpVtbl->CreateBlendState(self, pBlendStateDesc, ppBlendState); + #endif +} + +static inline HRESULT _sg_d3d11_CreateRenderTargetView(ID3D11Device* self, ID3D11Resource *pResource, const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, ID3D11RenderTargetView** ppRTView) { + #if defined(__cplusplus) + return self->CreateRenderTargetView(pResource, pDesc, ppRTView); + #else + return self->lpVtbl->CreateRenderTargetView(self, pResource, pDesc, ppRTView); + #endif +} + +static inline HRESULT _sg_d3d11_CreateDepthStencilView(ID3D11Device* self, ID3D11Resource* pResource, const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D11DepthStencilView** ppDepthStencilView) { + #if defined(__cplusplus) + return self->CreateDepthStencilView(pResource, pDesc, ppDepthStencilView); + #else + return self->lpVtbl->CreateDepthStencilView(self, pResource, pDesc, ppDepthStencilView); + #endif +} + +static inline void _sg_d3d11_RSSetViewports(ID3D11DeviceContext* self, UINT NumViewports, const D3D11_VIEWPORT* pViewports) { + #if defined(__cplusplus) + self->RSSetViewports(NumViewports, pViewports); + #else + self->lpVtbl->RSSetViewports(self, NumViewports, pViewports); + #endif +} + +static inline void _sg_d3d11_RSSetScissorRects(ID3D11DeviceContext* self, UINT NumRects, const D3D11_RECT* pRects) { + #if defined(__cplusplus) + self->RSSetScissorRects(NumRects, pRects); + #else + self->lpVtbl->RSSetScissorRects(self, NumRects, pRects); + #endif +} + +static inline void _sg_d3d11_ClearRenderTargetView(ID3D11DeviceContext* self, ID3D11RenderTargetView* pRenderTargetView, const FLOAT ColorRGBA[4]) { + #if defined(__cplusplus) + self->ClearRenderTargetView(pRenderTargetView, ColorRGBA); + #else + self->lpVtbl->ClearRenderTargetView(self, pRenderTargetView, ColorRGBA); + #endif +} + +static inline void _sg_d3d11_ClearDepthStencilView(ID3D11DeviceContext* self, ID3D11DepthStencilView* pDepthStencilView, UINT ClearFlags, FLOAT Depth, UINT8 Stencil) { + #if defined(__cplusplus) + self->ClearDepthStencilView(pDepthStencilView, ClearFlags, Depth, Stencil); + #else + self->lpVtbl->ClearDepthStencilView(self, pDepthStencilView, ClearFlags, Depth, Stencil); + #endif +} + +static inline void _sg_d3d11_ResolveSubresource(ID3D11DeviceContext* self, ID3D11Resource* pDstResource, UINT DstSubresource, ID3D11Resource* pSrcResource, UINT SrcSubresource, DXGI_FORMAT Format) { + #if defined(__cplusplus) + self->ResolveSubresource(pDstResource, DstSubresource, pSrcResource, SrcSubresource, Format); + #else + self->lpVtbl->ResolveSubresource(self, pDstResource, DstSubresource, pSrcResource, SrcSubresource, Format); + #endif +} + +static inline void _sg_d3d11_IASetPrimitiveTopology(ID3D11DeviceContext* self, D3D11_PRIMITIVE_TOPOLOGY Topology) { + #if defined(__cplusplus) + self->IASetPrimitiveTopology(Topology); + #else + self->lpVtbl->IASetPrimitiveTopology(self, Topology); + #endif +} + +static inline void _sg_d3d11_UpdateSubresource(ID3D11DeviceContext* self, ID3D11Resource* pDstResource, UINT DstSubresource, const D3D11_BOX* pDstBox, const void* pSrcData, UINT SrcRowPitch, UINT SrcDepthPitch) { + #if defined(__cplusplus) + self->UpdateSubresource(pDstResource, DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch); + #else + self->lpVtbl->UpdateSubresource(self, pDstResource, DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch); + #endif +} + +static inline void _sg_d3d11_DrawIndexed(ID3D11DeviceContext* self, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation) { + #if defined(__cplusplus) + self->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation); + #else + self->lpVtbl->DrawIndexed(self, IndexCount, StartIndexLocation, BaseVertexLocation); + #endif +} + +static inline void _sg_d3d11_DrawIndexedInstanced(ID3D11DeviceContext* self, UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation) { + #if defined(__cplusplus) + self->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); + #else + self->lpVtbl->DrawIndexedInstanced(self, IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); + #endif +} + +static inline void _sg_d3d11_Draw(ID3D11DeviceContext* self, UINT VertexCount, UINT StartVertexLocation) { + #if defined(__cplusplus) + self->Draw(VertexCount, StartVertexLocation); + #else + self->lpVtbl->Draw(self, VertexCount, StartVertexLocation); + #endif +} + +static inline void _sg_d3d11_DrawInstanced(ID3D11DeviceContext* self, UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation) { + #if defined(__cplusplus) + self->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation); + #else + self->lpVtbl->DrawInstanced(self, VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation); + #endif +} + +static inline HRESULT _sg_d3d11_Map(ID3D11DeviceContext* self, ID3D11Resource* pResource, UINT Subresource, D3D11_MAP MapType, UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + #if defined(__cplusplus) + return self->Map(pResource, Subresource, MapType, MapFlags, pMappedResource); + #else + return self->lpVtbl->Map(self, pResource, Subresource, MapType, MapFlags, pMappedResource); + #endif +} + +static inline void _sg_d3d11_Unmap(ID3D11DeviceContext* self, ID3D11Resource* pResource, UINT Subresource) { + #if defined(__cplusplus) + self->Unmap(pResource, Subresource); + #else + self->lpVtbl->Unmap(self, pResource, Subresource); + #endif +} + /*-- enum translation functions ----------------------------------------------*/ _SOKOL_PRIVATE D3D11_USAGE _sg_d3d11_usage(sg_usage usg) { switch (usg) { @@ -7139,7 +7539,7 @@ _SOKOL_PRIVATE void _sg_d3d11_init_caps(void) { UINT dxgi_fmt_caps = 0; const DXGI_FORMAT dxgi_fmt = _sg_d3d11_pixel_format((sg_pixel_format)fmt); if (dxgi_fmt != DXGI_FORMAT_UNKNOWN) { - HRESULT hr = ID3D11Device_CheckFormatSupport(_sg.d3d11.dev, dxgi_fmt, &dxgi_fmt_caps); + HRESULT hr = _sg_d3d11_CheckFormatSupport(_sg.d3d11.dev, dxgi_fmt, &dxgi_fmt_caps); SOKOL_ASSERT(SUCCEEDED(hr) || (E_FAIL == hr)); if (!SUCCEEDED(hr)) { dxgi_fmt_caps = 0; @@ -7163,14 +7563,16 @@ _SOKOL_PRIVATE void _sg_d3d11_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc); SOKOL_ASSERT(desc->context.d3d11.device); SOKOL_ASSERT(desc->context.d3d11.device_context); - SOKOL_ASSERT(desc->context.d3d11.render_target_view_cb); - SOKOL_ASSERT(desc->context.d3d11.depth_stencil_view_cb); - SOKOL_ASSERT(desc->context.d3d11.render_target_view_cb != desc->context.d3d11.depth_stencil_view_cb); + SOKOL_ASSERT(desc->context.d3d11.render_target_view_cb || desc->context.d3d11.render_target_view_userdata_cb); + SOKOL_ASSERT(desc->context.d3d11.depth_stencil_view_cb || desc->context.d3d11.depth_stencil_view_userdata_cb); _sg.d3d11.valid = true; _sg.d3d11.dev = (ID3D11Device*) desc->context.d3d11.device; _sg.d3d11.ctx = (ID3D11DeviceContext*) desc->context.d3d11.device_context; _sg.d3d11.rtv_cb = desc->context.d3d11.render_target_view_cb; + _sg.d3d11.rtv_userdata_cb = desc->context.d3d11.render_target_view_userdata_cb; _sg.d3d11.dsv_cb = desc->context.d3d11.depth_stencil_view_cb; + _sg.d3d11.dsv_userdata_cb = desc->context.d3d11.depth_stencil_view_userdata_cb; + _sg.d3d11.user_data = desc->context.d3d11.user_data; _sg_d3d11_init_caps(); } @@ -7181,21 +7583,21 @@ _SOKOL_PRIVATE void _sg_d3d11_discard_backend(void) { _SOKOL_PRIVATE void _sg_d3d11_clear_state(void) { /* clear all the device context state, so that resource refs don't keep stuck in the d3d device context */ - ID3D11DeviceContext_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, _sg.d3d11.zero_rtvs, NULL); - ID3D11DeviceContext_RSSetState(_sg.d3d11.ctx, NULL); - ID3D11DeviceContext_OMSetDepthStencilState(_sg.d3d11.ctx, NULL, 0); - ID3D11DeviceContext_OMSetBlendState(_sg.d3d11.ctx, NULL, NULL, 0xFFFFFFFF); - ID3D11DeviceContext_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_BUFFERS, _sg.d3d11.zero_vbs, _sg.d3d11.zero_vb_strides, _sg.d3d11.zero_vb_offsets); - ID3D11DeviceContext_IASetIndexBuffer(_sg.d3d11.ctx, NULL, DXGI_FORMAT_UNKNOWN, 0); - ID3D11DeviceContext_IASetInputLayout(_sg.d3d11.ctx, NULL); - ID3D11DeviceContext_VSSetShader(_sg.d3d11.ctx, NULL, NULL, 0); - ID3D11DeviceContext_PSSetShader(_sg.d3d11.ctx, NULL, NULL, 0); - ID3D11DeviceContext_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, _sg.d3d11.zero_cbs); - ID3D11DeviceContext_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, _sg.d3d11.zero_cbs); - ID3D11DeviceContext_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_srvs); - ID3D11DeviceContext_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_srvs); - ID3D11DeviceContext_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_smps); - ID3D11DeviceContext_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_smps); + _sg_d3d11_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, _sg.d3d11.zero_rtvs, NULL); + _sg_d3d11_RSSetState(_sg.d3d11.ctx, NULL); + _sg_d3d11_OMSetDepthStencilState(_sg.d3d11.ctx, NULL, 0); + _sg_d3d11_OMSetBlendState(_sg.d3d11.ctx, NULL, NULL, 0xFFFFFFFF); + _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_BUFFERS, _sg.d3d11.zero_vbs, _sg.d3d11.zero_vb_strides, _sg.d3d11.zero_vb_offsets); + _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, NULL, DXGI_FORMAT_UNKNOWN, 0); + _sg_d3d11_IASetInputLayout(_sg.d3d11.ctx, NULL); + _sg_d3d11_VSSetShader(_sg.d3d11.ctx, NULL, NULL, 0); + _sg_d3d11_PSSetShader(_sg.d3d11.ctx, NULL, NULL, 0); + _sg_d3d11_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, _sg.d3d11.zero_cbs); + _sg_d3d11_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, _sg.d3d11.zero_cbs); + _sg_d3d11_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_srvs); + _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_srvs); + _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_smps); + _sg_d3d11_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_smps); } _SOKOL_PRIVATE void _sg_d3d11_reset_state_cache(void) { @@ -7227,7 +7629,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_buffer(_sg_buffer_t* buf, cons const bool injected = (0 != desc->d3d11_buffer); if (injected) { buf->d3d11.buf = (ID3D11Buffer*) desc->d3d11_buffer; - ID3D11Buffer_AddRef(buf->d3d11.buf); + _sg_d3d11_AddRef(buf->d3d11.buf); } else { D3D11_BUFFER_DESC d3d11_desc; @@ -7244,7 +7646,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_buffer(_sg_buffer_t* buf, cons init_data.pSysMem = desc->content; init_data_ptr = &init_data; } - HRESULT hr = ID3D11Device_CreateBuffer(_sg.d3d11.dev, &d3d11_desc, init_data_ptr, &buf->d3d11.buf); + HRESULT hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &d3d11_desc, init_data_ptr, &buf->d3d11.buf); _SOKOL_UNUSED(hr); SOKOL_ASSERT(SUCCEEDED(hr) && buf->d3d11.buf); } @@ -7254,7 +7656,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_buffer(_sg_buffer_t* buf, cons _SOKOL_PRIVATE void _sg_d3d11_destroy_buffer(_sg_buffer_t* buf) { SOKOL_ASSERT(buf); if (buf->d3d11.buf) { - ID3D11Buffer_Release(buf->d3d11.buf); + _sg_d3d11_Release(buf->d3d11.buf); } } @@ -7318,7 +7720,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const d3d11_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; d3d11_desc.SampleDesc.Count = img->cmn.sample_count; d3d11_desc.SampleDesc.Quality = msaa ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0; - hr = ID3D11Device_CreateTexture2D(_sg.d3d11.dev, &d3d11_desc, NULL, &img->d3d11.texds); + hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_desc, NULL, &img->d3d11.texds); SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.texds); } else { @@ -7369,10 +7771,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const d3d11_tex_desc.MiscFlags = (img->cmn.type == SG_IMAGETYPE_CUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0; if (injected) { img->d3d11.tex2d = (ID3D11Texture2D*) desc->d3d11_texture; - ID3D11Texture2D_AddRef(img->d3d11.tex2d); + _sg_d3d11_AddRef(img->d3d11.tex2d); } else { - hr = ID3D11Device_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex2d); + hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex2d); SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.tex2d); } @@ -7397,7 +7799,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const default: SOKOL_UNREACHABLE; break; } - hr = ID3D11Device_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex2d, &d3d11_srv_desc, &img->d3d11.srv); + hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex2d, &d3d11_srv_desc, &img->d3d11.srv); SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.srv); } else { @@ -7431,10 +7833,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const } if (injected) { img->d3d11.tex3d = (ID3D11Texture3D*) desc->d3d11_texture; - ID3D11Texture3D_AddRef(img->d3d11.tex3d); + _sg_d3d11_AddRef(img->d3d11.tex3d); } else { - hr = ID3D11Device_CreateTexture3D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex3d); + hr = _sg_d3d11_CreateTexture3D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex3d); SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.tex3d); } @@ -7444,7 +7846,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const d3d11_srv_desc.Format = d3d11_tex_desc.Format; d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; d3d11_srv_desc.Texture3D.MipLevels = img->cmn.num_mipmaps; - hr = ID3D11Device_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex3d, &d3d11_srv_desc, &img->d3d11.srv); + hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex3d, &d3d11_srv_desc, &img->d3d11.srv); SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.srv); } @@ -7462,7 +7864,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const d3d11_tex_desc.CPUAccessFlags = 0; d3d11_tex_desc.SampleDesc.Count = img->cmn.sample_count; d3d11_tex_desc.SampleDesc.Quality = (UINT)D3D11_STANDARD_MULTISAMPLE_PATTERN; - hr = ID3D11Device_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, NULL, &img->d3d11.texmsaa); + hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, NULL, &img->d3d11.texmsaa); SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.texmsaa); } @@ -7491,7 +7893,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const d3d11_smp_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; d3d11_smp_desc.MinLOD = desc->min_lod; d3d11_smp_desc.MaxLOD = desc->max_lod; - hr = ID3D11Device_CreateSamplerState(_sg.d3d11.dev, &d3d11_smp_desc, &img->d3d11.smp); + hr = _sg_d3d11_CreateSamplerState(_sg.d3d11.dev, &d3d11_smp_desc, &img->d3d11.smp); SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.smp); } return SG_RESOURCESTATE_VALID; @@ -7500,22 +7902,22 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const _SOKOL_PRIVATE void _sg_d3d11_destroy_image(_sg_image_t* img) { SOKOL_ASSERT(img); if (img->d3d11.tex2d) { - ID3D11Texture2D_Release(img->d3d11.tex2d); + _sg_d3d11_Release(img->d3d11.tex2d); } if (img->d3d11.tex3d) { - ID3D11Texture3D_Release(img->d3d11.tex3d); + _sg_d3d11_Release(img->d3d11.tex3d); } if (img->d3d11.texds) { - ID3D11Texture2D_Release(img->d3d11.texds); + _sg_d3d11_Release(img->d3d11.texds); } if (img->d3d11.texmsaa) { - ID3D11Texture2D_Release(img->d3d11.texmsaa); + _sg_d3d11_Release(img->d3d11.texmsaa); } if (img->d3d11.srv) { - ID3D11ShaderResourceView_Release(img->d3d11.srv); + _sg_d3d11_Release(img->d3d11.srv); } if (img->d3d11.smp) { - ID3D11SamplerState_Release(img->d3d11.smp); + _sg_d3d11_Release(img->d3d11.smp); } } @@ -7567,13 +7969,13 @@ _SOKOL_PRIVATE ID3DBlob* _sg_d3d11_compile_shader(const sg_shader_stage_desc* st &output, /* ppCode */ &errors_or_warnings); /* ppErrorMsgs */ if (errors_or_warnings) { - SOKOL_LOG((LPCSTR)ID3D10Blob_GetBufferPointer(errors_or_warnings)); - ID3D10Blob_Release(errors_or_warnings); errors_or_warnings = NULL; + SOKOL_LOG((LPCSTR)_sg_d3d11_GetBufferPointer(errors_or_warnings)); + _sg_d3d11_Release(errors_or_warnings); errors_or_warnings = NULL; } if (FAILED(hr)) { /* just in case, usually output is NULL here */ if (output) { - ID3D10Blob_Release(output); + _sg_d3d11_Release(output); output = NULL; } } @@ -7610,7 +8012,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, cons cb_desc.ByteWidth = _sg_d3d11_roundup(ub->size, 16); cb_desc.Usage = D3D11_USAGE_DEFAULT; cb_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - hr = ID3D11Device_CreateBuffer(_sg.d3d11.dev, &cb_desc, NULL, &d3d11_stage->cbufs[ub_index]); + hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &cb_desc, NULL, &d3d11_stage->cbufs[ub_index]); SOKOL_ASSERT(SUCCEEDED(hr) && d3d11_stage->cbufs[ub_index]); } } @@ -7630,18 +8032,18 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, cons vs_blob = _sg_d3d11_compile_shader(&desc->vs); fs_blob = _sg_d3d11_compile_shader(&desc->fs); if (vs_blob && fs_blob) { - vs_ptr = ID3D10Blob_GetBufferPointer(vs_blob); - vs_length = ID3D10Blob_GetBufferSize(vs_blob); - fs_ptr = ID3D10Blob_GetBufferPointer(fs_blob); - fs_length = ID3D10Blob_GetBufferSize(fs_blob); + vs_ptr = _sg_d3d11_GetBufferPointer(vs_blob); + vs_length = _sg_d3d11_GetBufferSize(vs_blob); + fs_ptr = _sg_d3d11_GetBufferPointer(fs_blob); + fs_length = _sg_d3d11_GetBufferSize(fs_blob); } } sg_resource_state result = SG_RESOURCESTATE_FAILED; if (vs_ptr && fs_ptr && (vs_length > 0) && (fs_length > 0)) { /* create the D3D vertex- and pixel-shader objects */ - hr = ID3D11Device_CreateVertexShader(_sg.d3d11.dev, vs_ptr, vs_length, NULL, &shd->d3d11.vs); + hr = _sg_d3d11_CreateVertexShader(_sg.d3d11.dev, vs_ptr, vs_length, NULL, &shd->d3d11.vs); bool vs_succeeded = SUCCEEDED(hr) && shd->d3d11.vs; - hr = ID3D11Device_CreatePixelShader(_sg.d3d11.dev, fs_ptr, fs_length, NULL, &shd->d3d11.fs); + hr = _sg_d3d11_CreatePixelShader(_sg.d3d11.dev, fs_ptr, fs_length, NULL, &shd->d3d11.fs); bool fs_succeeded = SUCCEEDED(hr) && shd->d3d11.fs; /* need to store the vertex shader byte code, this is needed later in sg_create_pipeline */ @@ -7654,10 +8056,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, cons } } if (vs_blob) { - ID3D10Blob_Release(vs_blob); vs_blob = 0; + _sg_d3d11_Release(vs_blob); vs_blob = 0; } if (fs_blob) { - ID3D10Blob_Release(fs_blob); fs_blob = 0; + _sg_d3d11_Release(fs_blob); fs_blob = 0; } return result; } @@ -7665,10 +8067,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, cons _SOKOL_PRIVATE void _sg_d3d11_destroy_shader(_sg_shader_t* shd) { SOKOL_ASSERT(shd); if (shd->d3d11.vs) { - ID3D11VertexShader_Release(shd->d3d11.vs); + _sg_d3d11_Release(shd->d3d11.vs); } if (shd->d3d11.fs) { - ID3D11PixelShader_Release(shd->d3d11.fs); + _sg_d3d11_Release(shd->d3d11.fs); } if (shd->d3d11.vs_blob) { SOKOL_FREE(shd->d3d11.vs_blob); @@ -7678,7 +8080,7 @@ _SOKOL_PRIVATE void _sg_d3d11_destroy_shader(_sg_shader_t* shd) { _sg_d3d11_shader_stage_t* d3d11_stage = &shd->d3d11.stage[stage_index]; for (int ub_index = 0; ub_index < cmn_stage->num_uniform_blocks; ub_index++) { if (d3d11_stage->cbufs[ub_index]) { - ID3D11Buffer_Release(d3d11_stage->cbufs[ub_index]); + _sg_d3d11_Release(d3d11_stage->cbufs[ub_index]); } } } @@ -7734,7 +8136,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip, pip->d3d11.vb_strides[layout_index] = 0; } } - hr = ID3D11Device_CreateInputLayout(_sg.d3d11.dev, + hr = _sg_d3d11_CreateInputLayout(_sg.d3d11.dev, d3d11_comps, /* pInputElementDesc */ attr_index, /* NumElements */ shd->d3d11.vs_blob, /* pShaderByteCodeWithInputSignature */ @@ -7755,7 +8157,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip, rs_desc.ScissorEnable = TRUE; rs_desc.MultisampleEnable = desc->rasterizer.sample_count > 1; rs_desc.AntialiasedLineEnable = FALSE; - hr = ID3D11Device_CreateRasterizerState(_sg.d3d11.dev, &rs_desc, &pip->d3d11.rs); + hr = _sg_d3d11_CreateRasterizerState(_sg.d3d11.dev, &rs_desc, &pip->d3d11.rs); SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.rs); /* create depth-stencil state */ @@ -7777,7 +8179,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip, dss_desc.BackFace.StencilDepthFailOp = _sg_d3d11_stencil_op(sb->depth_fail_op); dss_desc.BackFace.StencilPassOp = _sg_d3d11_stencil_op(sb->pass_op); dss_desc.BackFace.StencilFunc = _sg_d3d11_compare_func(sb->compare_func); - hr = ID3D11Device_CreateDepthStencilState(_sg.d3d11.dev, &dss_desc, &pip->d3d11.dss); + hr = _sg_d3d11_CreateDepthStencilState(_sg.d3d11.dev, &dss_desc, &pip->d3d11.dss); SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.dss); /* create blend state */ @@ -7793,7 +8195,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip, bs_desc.RenderTarget[0].DestBlendAlpha = _sg_d3d11_blend_factor(desc->blend.dst_factor_alpha); bs_desc.RenderTarget[0].BlendOpAlpha = _sg_d3d11_blend_op(desc->blend.op_alpha); bs_desc.RenderTarget[0].RenderTargetWriteMask = _sg_d3d11_color_write_mask((sg_color_mask)desc->blend.color_write_mask); - hr = ID3D11Device_CreateBlendState(_sg.d3d11.dev, &bs_desc, &pip->d3d11.bs); + hr = _sg_d3d11_CreateBlendState(_sg.d3d11.dev, &bs_desc, &pip->d3d11.bs); SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.bs); return SG_RESOURCESTATE_VALID; @@ -7802,16 +8204,16 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip, _SOKOL_PRIVATE void _sg_d3d11_destroy_pipeline(_sg_pipeline_t* pip) { SOKOL_ASSERT(pip); if (pip->d3d11.il) { - ID3D11InputLayout_Release(pip->d3d11.il); + _sg_d3d11_Release(pip->d3d11.il); } if (pip->d3d11.rs) { - ID3D11RasterizerState_Release(pip->d3d11.rs); + _sg_d3d11_Release(pip->d3d11.rs); } if (pip->d3d11.dss) { - ID3D11DepthStencilState_Release(pip->d3d11.dss); + _sg_d3d11_Release(pip->d3d11.dss); } if (pip->d3d11.bs) { - ID3D11BlendState_Release(pip->d3d11.bs); + _sg_d3d11_Release(pip->d3d11.bs); } } @@ -7867,7 +8269,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pass(_sg_pass_t* pass, _sg_ima d3d11_rtv_desc.Texture3D.WSize = 1; } SOKOL_ASSERT(d3d11_res); - HRESULT hr = ID3D11Device_CreateRenderTargetView(_sg.d3d11.dev, d3d11_res, &d3d11_rtv_desc, &pass->d3d11.color_atts[i].rtv); + HRESULT hr = _sg_d3d11_CreateRenderTargetView(_sg.d3d11.dev, d3d11_res, &d3d11_rtv_desc, &pass->d3d11.color_atts[i].rtv); _SOKOL_UNUSED(hr); SOKOL_ASSERT(SUCCEEDED(hr) && pass->d3d11.color_atts[i].rtv); } @@ -7898,7 +8300,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pass(_sg_pass_t* pass, _sg_ima } ID3D11Resource* d3d11_res = (ID3D11Resource*) att_img->d3d11.texds; SOKOL_ASSERT(d3d11_res); - HRESULT hr = ID3D11Device_CreateDepthStencilView(_sg.d3d11.dev, d3d11_res, &d3d11_dsv_desc, &pass->d3d11.ds_att.dsv); + HRESULT hr = _sg_d3d11_CreateDepthStencilView(_sg.d3d11.dev, d3d11_res, &d3d11_dsv_desc, &pass->d3d11.ds_att.dsv); _SOKOL_UNUSED(hr); SOKOL_ASSERT(SUCCEEDED(hr) && pass->d3d11.ds_att.dsv); } @@ -7909,11 +8311,11 @@ _SOKOL_PRIVATE void _sg_d3d11_destroy_pass(_sg_pass_t* pass) { SOKOL_ASSERT(pass); for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) { if (pass->d3d11.color_atts[i].rtv) { - ID3D11RenderTargetView_Release(pass->d3d11.color_atts[i].rtv); + _sg_d3d11_Release(pass->d3d11.color_atts[i].rtv); } } if (pass->d3d11.ds_att.dsv) { - ID3D11DepthStencilView_Release(pass->d3d11.ds_att.dsv); + _sg_d3d11_Release(pass->d3d11.ds_att.dsv); } } @@ -7932,6 +8334,8 @@ _SOKOL_PRIVATE _sg_image_t* _sg_d3d11_pass_ds_image(const _sg_pass_t* pass) { _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) { SOKOL_ASSERT(action); SOKOL_ASSERT(!_sg.d3d11.in_pass); + SOKOL_ASSERT(_sg.d3d11.rtv_cb || _sg.d3d11.rtv_userdata_cb); + SOKOL_ASSERT(_sg.d3d11.dsv_cb || _sg.d3d11.dsv_userdata_cb); _sg.d3d11.in_pass = true; _sg.d3d11.cur_width = w; _sg.d3d11.cur_height = h; @@ -7952,15 +8356,25 @@ _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* _sg.d3d11.cur_pass = 0; _sg.d3d11.cur_pass_id.id = SG_INVALID_ID; _sg.d3d11.num_rtvs = 1; - _sg.d3d11.cur_rtvs[0] = (ID3D11RenderTargetView*) _sg.d3d11.rtv_cb(); + if (_sg.d3d11.rtv_cb) { + _sg.d3d11.cur_rtvs[0] = (ID3D11RenderTargetView*) _sg.d3d11.rtv_cb(); + } + else { + _sg.d3d11.cur_rtvs[0] = (ID3D11RenderTargetView*) _sg.d3d11.rtv_userdata_cb(_sg.d3d11.user_data); + } for (int i = 1; i < SG_MAX_COLOR_ATTACHMENTS; i++) { _sg.d3d11.cur_rtvs[i] = 0; } - _sg.d3d11.cur_dsv = (ID3D11DepthStencilView*) _sg.d3d11.dsv_cb(); + if (_sg.d3d11.dsv_cb) { + _sg.d3d11.cur_dsv = (ID3D11DepthStencilView*) _sg.d3d11.dsv_cb(); + } + else { + _sg.d3d11.cur_dsv = (ID3D11DepthStencilView*) _sg.d3d11.dsv_userdata_cb(_sg.d3d11.user_data); + } SOKOL_ASSERT(_sg.d3d11.cur_rtvs[0] && _sg.d3d11.cur_dsv); } /* apply the render-target- and depth-stencil-views */ - ID3D11DeviceContext_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, _sg.d3d11.cur_rtvs, _sg.d3d11.cur_dsv); + _sg_d3d11_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, _sg.d3d11.cur_rtvs, _sg.d3d11.cur_dsv); /* set viewport and scissor rect to cover whole screen */ D3D11_VIEWPORT vp; @@ -7968,18 +8382,18 @@ _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* vp.Width = (FLOAT) w; vp.Height = (FLOAT) h; vp.MaxDepth = 1.0f; - ID3D11DeviceContext_RSSetViewports(_sg.d3d11.ctx, 1, &vp); + _sg_d3d11_RSSetViewports(_sg.d3d11.ctx, 1, &vp); D3D11_RECT rect; rect.left = 0; rect.top = 0; rect.right = w; rect.bottom = h; - ID3D11DeviceContext_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect); + _sg_d3d11_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect); /* perform clear action */ for (int i = 0; i < _sg.d3d11.num_rtvs; i++) { if (action->colors[i].action == SG_ACTION_CLEAR) { - ID3D11DeviceContext_ClearRenderTargetView(_sg.d3d11.ctx, _sg.d3d11.cur_rtvs[i], action->colors[i].val); + _sg_d3d11_ClearRenderTargetView(_sg.d3d11.ctx, _sg.d3d11.cur_rtvs[i], action->colors[i].val); } } UINT ds_flags = 0; @@ -7990,7 +8404,7 @@ _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* ds_flags |= D3D11_CLEAR_STENCIL; } if ((0 != ds_flags) && _sg.d3d11.cur_dsv) { - ID3D11DeviceContext_ClearDepthStencilView(_sg.d3d11.ctx, _sg.d3d11.cur_dsv, ds_flags, action->depth.val, action->stencil.val); + _sg_d3d11_ClearDepthStencilView(_sg.d3d11.ctx, _sg.d3d11.cur_dsv, ds_flags, action->depth.val, action->stencil.val); } } @@ -8015,7 +8429,7 @@ _SOKOL_PRIVATE void _sg_d3d11_end_pass(void) { SOKOL_ASSERT(att_img->d3d11.tex2d && att_img->d3d11.texmsaa && !att_img->d3d11.tex3d); SOKOL_ASSERT(DXGI_FORMAT_UNKNOWN != att_img->d3d11.format); UINT dst_subres = _sg_d3d11_calcsubresource(cmn_att->mip_level, cmn_att->slice, att_img->cmn.num_mipmaps); - ID3D11DeviceContext_ResolveSubresource(_sg.d3d11.ctx, + _sg_d3d11_ResolveSubresource(_sg.d3d11.ctx, (ID3D11Resource*) att_img->d3d11.tex2d, /* pDstResource */ dst_subres, /* DstSubresource */ (ID3D11Resource*) att_img->d3d11.texmsaa, /* pSrcResource */ @@ -8045,7 +8459,7 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_viewport(int x, int y, int w, int h, bool or vp.Height = (FLOAT) h; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; - ID3D11DeviceContext_RSSetViewports(_sg.d3d11.ctx, 1, &vp); + _sg_d3d11_RSSetViewports(_sg.d3d11.ctx, 1, &vp); } _SOKOL_PRIVATE void _sg_d3d11_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) { @@ -8056,7 +8470,7 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_scissor_rect(int x, int y, int w, int h, boo rect.top = (origin_top_left ? y : (_sg.d3d11.cur_height - (y + h))); rect.right = x + w; rect.bottom = origin_top_left ? (y + h) : (_sg.d3d11.cur_height - y); - ID3D11DeviceContext_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect); + _sg_d3d11_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect); } _SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) { @@ -8070,15 +8484,15 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) { _sg.d3d11.cur_pipeline_id.id = pip->slot.id; _sg.d3d11.use_indexed_draw = (pip->d3d11.index_format != DXGI_FORMAT_UNKNOWN); - ID3D11DeviceContext_RSSetState(_sg.d3d11.ctx, pip->d3d11.rs); - ID3D11DeviceContext_OMSetDepthStencilState(_sg.d3d11.ctx, pip->d3d11.dss, pip->d3d11.stencil_ref); - ID3D11DeviceContext_OMSetBlendState(_sg.d3d11.ctx, pip->d3d11.bs, pip->cmn.blend_color, 0xFFFFFFFF); - ID3D11DeviceContext_IASetPrimitiveTopology(_sg.d3d11.ctx, pip->d3d11.topology); - ID3D11DeviceContext_IASetInputLayout(_sg.d3d11.ctx, pip->d3d11.il); - ID3D11DeviceContext_VSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.vs, NULL, 0); - ID3D11DeviceContext_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_VS].cbufs); - ID3D11DeviceContext_PSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.fs, NULL, 0); - ID3D11DeviceContext_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_FS].cbufs); + _sg_d3d11_RSSetState(_sg.d3d11.ctx, pip->d3d11.rs); + _sg_d3d11_OMSetDepthStencilState(_sg.d3d11.ctx, pip->d3d11.dss, pip->d3d11.stencil_ref); + _sg_d3d11_OMSetBlendState(_sg.d3d11.ctx, pip->d3d11.bs, pip->cmn.blend_color, 0xFFFFFFFF); + _sg_d3d11_IASetPrimitiveTopology(_sg.d3d11.ctx, pip->d3d11.topology); + _sg_d3d11_IASetInputLayout(_sg.d3d11.ctx, pip->d3d11.il); + _sg_d3d11_VSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.vs, NULL, 0); + _sg_d3d11_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_VS].cbufs); + _sg_d3d11_PSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.fs, NULL, 0); + _sg_d3d11_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_FS].cbufs); } _SOKOL_PRIVATE void _sg_d3d11_apply_bindings( @@ -8131,12 +8545,12 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_bindings( d3d11_fs_smps[i] = 0; } - ID3D11DeviceContext_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_BUFFERS, d3d11_vbs, pip->d3d11.vb_strides, d3d11_vb_offsets); - ID3D11DeviceContext_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, pip->d3d11.index_format, ib_offset); - ID3D11DeviceContext_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_srvs); - ID3D11DeviceContext_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_smps); - ID3D11DeviceContext_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_srvs); - ID3D11DeviceContext_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_smps); + _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_BUFFERS, d3d11_vbs, pip->d3d11.vb_strides, d3d11_vb_offsets); + _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, pip->d3d11.index_format, ib_offset); + _sg_d3d11_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_srvs); + _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_smps); + _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_srvs); + _sg_d3d11_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_smps); } _SOKOL_PRIVATE void _sg_d3d11_apply_uniforms(sg_shader_stage stage_index, int ub_index, const void* data, int num_bytes) { @@ -8151,25 +8565,25 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_uniforms(sg_shader_stage stage_index, int ub SOKOL_ASSERT(num_bytes == _sg.d3d11.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); ID3D11Buffer* cb = _sg.d3d11.cur_pipeline->shader->d3d11.stage[stage_index].cbufs[ub_index]; SOKOL_ASSERT(cb); - ID3D11DeviceContext_UpdateSubresource(_sg.d3d11.ctx, (ID3D11Resource*)cb, 0, NULL, data, 0, 0); + _sg_d3d11_UpdateSubresource(_sg.d3d11.ctx, (ID3D11Resource*)cb, 0, NULL, data, 0, 0); } _SOKOL_PRIVATE void _sg_d3d11_draw(int base_element, int num_elements, int num_instances) { SOKOL_ASSERT(_sg.d3d11.in_pass); if (_sg.d3d11.use_indexed_draw) { if (1 == num_instances) { - ID3D11DeviceContext_DrawIndexed(_sg.d3d11.ctx, num_elements, base_element, 0); + _sg_d3d11_DrawIndexed(_sg.d3d11.ctx, num_elements, base_element, 0); } else { - ID3D11DeviceContext_DrawIndexedInstanced(_sg.d3d11.ctx, num_elements, num_instances, base_element, 0, 0); + _sg_d3d11_DrawIndexedInstanced(_sg.d3d11.ctx, num_elements, num_instances, base_element, 0, 0); } } else { if (1 == num_instances) { - ID3D11DeviceContext_Draw(_sg.d3d11.ctx, num_elements, base_element); + _sg_d3d11_Draw(_sg.d3d11.ctx, num_elements, base_element); } else { - ID3D11DeviceContext_DrawInstanced(_sg.d3d11.ctx, num_elements, num_instances, base_element, 0); + _sg_d3d11_DrawInstanced(_sg.d3d11.ctx, num_elements, num_instances, base_element, 0); } } } @@ -8183,11 +8597,11 @@ _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const void* data_ SOKOL_ASSERT(_sg.d3d11.ctx); SOKOL_ASSERT(buf->d3d11.buf); D3D11_MAPPED_SUBRESOURCE d3d11_msr; - HRESULT hr = ID3D11DeviceContext_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr); + HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr); _SOKOL_UNUSED(hr); SOKOL_ASSERT(SUCCEEDED(hr)); memcpy(d3d11_msr.pData, data_ptr, data_size); - ID3D11DeviceContext_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0); + _sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0); } _SOKOL_PRIVATE uint32_t _sg_d3d11_append_buffer(_sg_buffer_t* buf, const void* data_ptr, uint32_t data_size, bool new_frame) { @@ -8196,12 +8610,12 @@ _SOKOL_PRIVATE uint32_t _sg_d3d11_append_buffer(_sg_buffer_t* buf, const void* d SOKOL_ASSERT(buf->d3d11.buf); D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE; D3D11_MAPPED_SUBRESOURCE d3d11_msr; - HRESULT hr = ID3D11DeviceContext_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, map_type, 0, &d3d11_msr); + HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, map_type, 0, &d3d11_msr); _SOKOL_UNUSED(hr); SOKOL_ASSERT(SUCCEEDED(hr)); uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData + buf->cmn.append_pos; memcpy(dst_ptr, data_ptr, data_size); - ID3D11DeviceContext_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0); + _sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0); /* NOTE: this is a requirement from WebGPU, but we want identical behaviour across all backend */ return _sg_roundup(data_size, 4); } @@ -8235,7 +8649,7 @@ _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_cont const int slice_size = subimg_content->size / num_slices; const int slice_offset = slice_size * slice_index; const uint8_t* slice_ptr = ((const uint8_t*)subimg_content->ptr) + slice_offset; - hr = ID3D11DeviceContext_Map(_sg.d3d11.ctx, d3d11_res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr); + hr = _sg_d3d11_Map(_sg.d3d11.ctx, d3d11_res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr); SOKOL_ASSERT(SUCCEEDED(hr)); /* FIXME: need to handle difference in depth-pitch for 3D textures as well! */ if (src_pitch == (int)d3d11_msr.RowPitch) { @@ -8251,7 +8665,7 @@ _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_cont dst_ptr += d3d11_msr.RowPitch; } } - ID3D11DeviceContext_Unmap(_sg.d3d11.ctx, d3d11_res, subres_index); + _sg_d3d11_Unmap(_sg.d3d11.ctx, d3d11_res, subres_index); } } } @@ -8916,15 +9330,18 @@ _SOKOL_PRIVATE void _sg_mtl_setup_backend(const sg_desc* desc) { /* assume already zero-initialized */ SOKOL_ASSERT(desc); SOKOL_ASSERT(desc->context.metal.device); - SOKOL_ASSERT(desc->context.metal.renderpass_descriptor_cb); - SOKOL_ASSERT(desc->context.metal.drawable_cb); + SOKOL_ASSERT(desc->context.metal.renderpass_descriptor_cb || desc->context.metal.renderpass_descriptor_userdata_cb); + SOKOL_ASSERT(desc->context.metal.drawable_cb || desc->context.metal.drawable_userdata_cb); SOKOL_ASSERT(desc->uniform_buffer_size > 0); _sg_mtl_init_pool(desc); _sg_mtl_init_sampler_cache(desc); _sg_mtl_clear_state_cache(); _sg.mtl.valid = true; _sg.mtl.renderpass_descriptor_cb = desc->context.metal.renderpass_descriptor_cb; + _sg.mtl.renderpass_descriptor_userdata_cb = desc->context.metal.renderpass_descriptor_userdata_cb; _sg.mtl.drawable_cb = desc->context.metal.drawable_cb; + _sg.mtl.drawable_userdata_cb = desc->context.metal.drawable_userdata_cb; + _sg.mtl.user_data = desc->context.metal.user_data; _sg.mtl.frame_index = 1; _sg.mtl.ub_size = desc->uniform_buffer_size; _sg.mtl.sem = dispatch_semaphore_create(SG_NUM_INFLIGHT_FRAMES); @@ -9073,7 +9490,7 @@ _SOKOL_PRIVATE void _sg_mtl_copy_image_content(const _sg_image_t* img, __unsafe_ for (int slice_index = 0; slice_index < num_slices; slice_index++) { const int mtl_slice_index = (img->cmn.type == SG_IMAGETYPE_CUBE) ? face_index : slice_index; const int slice_offset = slice_index * bytes_per_slice; -// SOKOL_ASSERT((slice_offset + bytes_per_slice) <= (int)content->subimage[face_index][mip_index].size); + SOKOL_ASSERT((slice_offset + bytes_per_slice) <= (int)content->subimage[face_index][mip_index].size); [mtl_tex replaceRegion:region mipmapLevel:mip_index slice:mtl_slice_index @@ -9515,7 +9932,7 @@ _SOKOL_PRIVATE void _sg_mtl_begin_pass(_sg_pass_t* pass, const sg_pass_action* a SOKOL_ASSERT(!_sg.mtl.in_pass); SOKOL_ASSERT(_sg.mtl.cmd_queue); SOKOL_ASSERT(nil == _sg.mtl.cmd_encoder); - SOKOL_ASSERT(_sg.mtl.renderpass_descriptor_cb); + SOKOL_ASSERT(_sg.mtl.renderpass_descriptor_cb || _sg.mtl.renderpass_descriptor_userdata_cb); _sg.mtl.in_pass = true; _sg.mtl.cur_width = w; _sg.mtl.cur_height = h; @@ -9541,7 +9958,12 @@ _SOKOL_PRIVATE void _sg_mtl_begin_pass(_sg_pass_t* pass, const sg_pass_action* a } else { /* default render pass, call user-provided callback to provide render pass descriptor */ - pass_desc = (__bridge MTLRenderPassDescriptor*) _sg.mtl.renderpass_descriptor_cb(); + if (_sg.mtl.renderpass_descriptor_cb) { + pass_desc = (__bridge MTLRenderPassDescriptor*) _sg.mtl.renderpass_descriptor_cb(); + } + else { + pass_desc = (__bridge MTLRenderPassDescriptor*) _sg.mtl.renderpass_descriptor_userdata_cb(_sg.mtl.user_data); + } } if (pass_desc) { @@ -9651,7 +10073,7 @@ _SOKOL_PRIVATE void _sg_mtl_end_pass(void) { _SOKOL_PRIVATE void _sg_mtl_commit(void) { SOKOL_ASSERT(!_sg.mtl.in_pass); SOKOL_ASSERT(!_sg.mtl.pass_valid); - SOKOL_ASSERT(_sg.mtl.drawable_cb); + SOKOL_ASSERT(_sg.mtl.drawable_cb || _sg.mtl.drawable_userdata_cb); SOKOL_ASSERT(nil == _sg.mtl.cmd_encoder); SOKOL_ASSERT(nil != _sg.mtl.cmd_buffer); @@ -9660,7 +10082,13 @@ _SOKOL_PRIVATE void _sg_mtl_commit(void) { #endif /* present, commit and signal semaphore when done */ - id cur_drawable = (__bridge id) _sg.mtl.drawable_cb(); + id cur_drawable = nil; + if (_sg.mtl.drawable_cb) { + cur_drawable = (__bridge id) _sg.mtl.drawable_cb(); + } + else { + cur_drawable = (__bridge id) _sg.mtl.drawable_userdata_cb(_sg.mtl.user_data); + } [_sg.mtl.cmd_buffer presentDrawable:cur_drawable]; [_sg.mtl.cmd_buffer addCompletedHandler:^(id cmd_buffer) { _SOKOL_UNUSED(cmd_buffer); @@ -10755,17 +11183,21 @@ _SOKOL_PRIVATE WGPUSampler _sg_wgpu_create_sampler(const sg_image_desc* img_desc _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc); SOKOL_ASSERT(desc->context.wgpu.device); - SOKOL_ASSERT(desc->context.wgpu.render_view_cb); - SOKOL_ASSERT(desc->context.wgpu.resolve_view_cb); - SOKOL_ASSERT(desc->context.wgpu.depth_stencil_view_cb); + SOKOL_ASSERT(desc->context.wgpu.render_view_cb || desc->context.wgpu.render_view_userdata_cb); + SOKOL_ASSERT(desc->context.wgpu.resolve_view_cb || desc->context.wgpu.resolve_view_userdata_cb); + SOKOL_ASSERT(desc->context.wgpu.depth_stencil_view_cb || desc->context.wgpu.depth_stencil_view_userdata_cb); SOKOL_ASSERT(desc->uniform_buffer_size > 0); SOKOL_ASSERT(desc->staging_buffer_size > 0); _sg.backend = SG_BACKEND_WGPU; _sg.wgpu.valid = true; _sg.wgpu.dev = (WGPUDevice) desc->context.wgpu.device; _sg.wgpu.render_view_cb = (WGPUTextureView(*)(void)) desc->context.wgpu.render_view_cb; + _sg.wgpu.render_view_userdata_cb = (WGPUTextureView(*)(void*)) desc->context.wgpu.render_view_userdata_cb; _sg.wgpu.resolve_view_cb = (WGPUTextureView(*)(void)) desc->context.wgpu.resolve_view_cb; + _sg.wgpu.resolve_view_userdata_cb = (WGPUTextureView(*)(void*)) desc->context.wgpu.resolve_view_userdata_cb; _sg.wgpu.depth_stencil_view_cb = (WGPUTextureView(*)(void)) desc->context.wgpu.depth_stencil_view_cb; + _sg.wgpu.depth_stencil_view_userdata_cb = (WGPUTextureView(*)(void*)) desc->context.wgpu.depth_stencil_view_userdata_cb; + _sg.wgpu.user_data = desc->context.wgpu.user_data; _sg.wgpu.queue = wgpuDeviceCreateQueue(_sg.wgpu.dev); SOKOL_ASSERT(_sg.wgpu.queue); @@ -11323,9 +11755,9 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* SOKOL_ASSERT(!_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); SOKOL_ASSERT(_sg.wgpu.dev); - SOKOL_ASSERT(_sg.wgpu.render_view_cb); - SOKOL_ASSERT(_sg.wgpu.resolve_view_cb); - SOKOL_ASSERT(_sg.wgpu.depth_stencil_view_cb); + SOKOL_ASSERT(_sg.wgpu.render_view_cb || _sg.wgpu.render_view_userdata_cb); + SOKOL_ASSERT(_sg.wgpu.resolve_view_cb || _sg.wgpu.resolve_view_userdata_cb); + SOKOL_ASSERT(_sg.wgpu.depth_stencil_view_cb || _sg.wgpu.depth_stencil_view_userdata_cb); _sg.wgpu.in_pass = true; _sg.wgpu.cur_width = w; _sg.wgpu.cur_height = h; @@ -11368,9 +11800,9 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* } else { /* default render pass */ - WGPUTextureView wgpu_render_view = _sg.wgpu.render_view_cb(); - WGPUTextureView wgpu_resolve_view = _sg.wgpu.resolve_view_cb(); - WGPUTextureView wgpu_depth_stencil_view = _sg.wgpu.depth_stencil_view_cb(); + WGPUTextureView wgpu_render_view = _sg.wgpu.render_view_cb ? _sg.wgpu.render_view_cb() : _sg.wgpu.render_view_userdata_cb(_sg.wgpu.user_data); + WGPUTextureView wgpu_resolve_view = _sg.wgpu.resolve_view_cb ? _sg.wgpu.resolve_view_cb() : _sg.wgpu.resolve_view_userdata_cb(_sg.wgpu.user_data); + WGPUTextureView wgpu_depth_stencil_view = _sg.wgpu.depth_stencil_view_cb ? _sg.wgpu.depth_stencil_view_cb() : _sg.wgpu.depth_stencil_view_userdata_cb(_sg.wgpu.user_data); WGPURenderPassDescriptor pass_desc; memset(&pass_desc, 0, sizeof(pass_desc)); @@ -12765,7 +13197,7 @@ _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) { if (u_desc->type != SG_UNIFORMTYPE_INVALID) { SOKOL_VALIDATE(uniforms_continuous, _SG_VALIDATE_SHADERDESC_NO_CONT_UB_MEMBERS); #if defined(SOKOL_GLES2) || defined(SOKOL_GLES3) - SOKOL_VALIDATE(u_desc->name, _SG_VALIDATE_SHADERDESC_UB_MEMBER_NAME); + SOKOL_VALIDATE(0 != u_desc->name, _SG_VALIDATE_SHADERDESC_UB_MEMBER_NAME); #endif const int array_count = u_desc->array_count; uniform_offset += _sg_uniform_size(u_desc->type, array_count); @@ -12790,7 +13222,7 @@ _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) { if (img_desc->type != _SG_IMAGETYPE_DEFAULT) { SOKOL_VALIDATE(images_continuous, _SG_VALIDATE_SHADERDESC_NO_CONT_IMGS); #if defined(SOKOL_GLES2) - SOKOL_VALIDATE(img_desc->name, _SG_VALIDATE_SHADERDESC_IMG_NAME); + SOKOL_VALIDATE(0 != img_desc->name, _SG_VALIDATE_SHADERDESC_IMG_NAME); #endif } else { @@ -12821,7 +13253,7 @@ _SOKOL_PRIVATE bool _sg_validate_pipeline_desc(const sg_pipeline_desc* desc) { } SOKOL_VALIDATE(desc->layout.attrs[0].format != SG_VERTEXFORMAT_INVALID, _SG_VALIDATE_PIPELINEDESC_NO_ATTRS); const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, desc->shader.id); - SOKOL_VALIDATE(shd, _SG_VALIDATE_PIPELINEDESC_SHADER); + SOKOL_VALIDATE(0 != shd, _SG_VALIDATE_PIPELINEDESC_SHADER); if (shd) { SOKOL_VALIDATE(shd->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_PIPELINEDESC_SHADER); bool attrs_cont = true; @@ -12867,7 +13299,7 @@ _SOKOL_PRIVATE bool _sg_validate_pass_desc(const sg_pass_desc* desc) { } SOKOL_VALIDATE(atts_cont, _SG_VALIDATE_PASSDESC_NO_CONT_COLOR_ATTS); const _sg_image_t* img = _sg_lookup_image(&_sg.pools, att->image.id); - SOKOL_VALIDATE(img && img->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_PASSDESC_IMAGE); + SOKOL_VALIDATE((0 != img) && (img->slot.state == SG_RESOURCESTATE_VALID), _SG_VALIDATE_PASSDESC_IMAGE); SOKOL_VALIDATE(att->mip_level < img->cmn.num_mipmaps, _SG_VALIDATE_PASSDESC_MIPLEVEL); if (img->cmn.type == SG_IMAGETYPE_CUBE) { SOKOL_VALIDATE(att->face < 6, _SG_VALIDATE_PASSDESC_FACE); @@ -12896,7 +13328,7 @@ _SOKOL_PRIVATE bool _sg_validate_pass_desc(const sg_pass_desc* desc) { if (desc->depth_stencil_attachment.image.id != SG_INVALID_ID) { const sg_attachment_desc* att = &desc->depth_stencil_attachment; const _sg_image_t* img = _sg_lookup_image(&_sg.pools, att->image.id); - SOKOL_VALIDATE(img && img->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_PASSDESC_IMAGE); + SOKOL_VALIDATE((0 != img) && (img->slot.state == SG_RESOURCESTATE_VALID), _SG_VALIDATE_PASSDESC_IMAGE); SOKOL_VALIDATE(att->mip_level < img->cmn.num_mipmaps, _SG_VALIDATE_PASSDESC_MIPLEVEL); if (img->cmn.type == SG_IMAGETYPE_CUBE) { SOKOL_VALIDATE(att->face < 6, _SG_VALIDATE_PASSDESC_FACE); @@ -14134,6 +14566,7 @@ SOKOL_API_IMPL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instances) { SOKOL_ASSERT(_sg.valid); + SOKOL_ASSERT((base_element >= 0) && (num_elements >= 0) && (num_instances >= 0)); #if defined(SOKOL_DEBUG) if (!_sg.bindings_valid) { SOKOL_LOG("attempting to draw without resource bindings"); @@ -14151,6 +14584,13 @@ SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instance _SG_TRACE_NOARGS(err_bindings_invalid); return; } + /* attempting to draw with zero elements or instances is not technically an + error, but might be handled as an error in the backend API (e.g. on Metal) + */ + if ((0 == num_elements) || (0 == num_instances)) { + _SG_TRACE_NOARGS(err_draw_invalid); + return; + } _sg_draw(base_element, num_elements, num_instances); _SG_TRACE_ARGS(draw, base_element, num_elements, num_instances); } diff --git a/thirdparty/sokol/util/sokol_fontstash.h b/thirdparty/sokol/util/sokol_fontstash.h old mode 100755 new mode 100644 index c923661b16..81b35a97f7 --- a/thirdparty/sokol/util/sokol_fontstash.h +++ b/thirdparty/sokol/util/sokol_fontstash.h @@ -1729,6 +1729,16 @@ static void _sfons_render_delete(void* user_ptr) { SOKOL_FREE(sfons); } +// NOTE clang analyzer will report a potential memory leak for the call +// to SOKOL_MALLOC in the sfons_create() function, this is a false positive +// (the freeing happens in _sfons_render_delete()). The following macro +// silences the false positive when compilation happens with the analyzer active +#if __clang_analyzer__ +#define _SFONS_CLANG_ANALYZER_SILENCE_POTENTIAL_LEAK_FALSE_POSITIVE(x) SOKOL_FREE(x) +#else +#define _SFONS_CLANG_ANALYZER_SILENCE_POTENTIAL_LEAK_FALSE_POSITIVE(x) +#endif + SOKOL_API_IMPL FONScontext* sfons_create(int width, int height, int flags) { SOKOL_ASSERT((width > 0) && (height > 0)); FONSparams params; @@ -1744,7 +1754,9 @@ SOKOL_API_IMPL FONScontext* sfons_create(int width, int height, int flags) { params.renderDraw = _sfons_render_draw; params.renderDelete = _sfons_render_delete; params.userPtr = sfons; - return fonsCreateInternal(¶ms); + FONScontext* ctx = fonsCreateInternal(¶ms); + _SFONS_CLANG_ANALYZER_SILENCE_POTENTIAL_LEAK_FALSE_POSITIVE(sfons); + return ctx; } SOKOL_API_IMPL void sfons_destroy(FONScontext* ctx) { diff --git a/thirdparty/sokol/util/sokol_gl.h b/thirdparty/sokol/util/sokol_gl.h old mode 100755 new mode 100644 index 15a110a4e7..e7b7b5537e --- a/thirdparty/sokol/util/sokol_gl.h +++ b/thirdparty/sokol/util/sokol_gl.h @@ -2011,8 +2011,8 @@ typedef struct { #define _SGL_INVALID_SLOT_INDEX (0) #define _SGL_MAX_STACK_DEPTH (64) #define _SGL_DEFAULT_PIPELINE_POOL_SIZE (64) -#define _SGL_DEFAULT_MAX_VERTICES (1<<17) -#define _SGL_DEFAULT_MAX_COMMANDS (1<<15) +#define _SGL_DEFAULT_MAX_VERTICES (1<<16) +#define _SGL_DEFAULT_MAX_COMMANDS (1<<14) #define _SGL_SLOT_SHIFT (16) #define _SGL_MAX_POOL_SIZE (1<<_SGL_SLOT_SHIFT) #define _SGL_SLOT_MASK (_SGL_MAX_POOL_SIZE-1)