From 223e2b8ff8788ebe638305d241409e879a4f78b7 Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Wed, 13 Mar 2024 07:46:52 -0400 Subject: [PATCH 01/11] WIP --- src/app.c | 21 +++++++++++++++++++ src/app.h | 7 +++++++ src/gfx/mod-ctx.h | 6 +++++- src/gfx/vk/vk-ctx.c | 5 +++++ src/matoya.h | 5 +++++ src/windows/gfx/d3d11-ctx.c | 40 ++++++++++++++++++++++++++++++++++--- src/windows/gfx/d3d12-ctx.c | 5 +++++ 7 files changed, 85 insertions(+), 4 deletions(-) diff --git a/src/app.c b/src/app.c index 6890e2fb1..05149e36f 100644 --- a/src/app.c +++ b/src/app.c @@ -289,6 +289,27 @@ bool MTY_WindowSetGFX(MTY_App *app, MTY_Window window, MTY_GFX api, bool vsync) return cmn->gfx_ctx != NULL; } +static int32_t gfx_error_handler(int32_t e1, int32_t e2, void *opaque) +{ + struct window_common *cmn = (struct window_common *) opaque; + + return cmn->error_handling.handler(cmn->error_handling.app, cmn->error_handling.window, e1, e2, opaque); +} + +void MTY_WindowSetErrorHandler(MTY_App *app, MTY_Window window, MTY_WindowErrorFunc func, void *opaque) +{ + struct window_common *cmn = mty_window_get_common(app, window); + if (!cmn || cmn->api == MTY_GFX_NONE) + return; + + cmn->error_handling.app = app; + cmn->error_handling.window = window; + cmn->error_handling.handler = func; + cmn->error_handling.opaque = opaque; + + GFX_CTX_API[cmn->api].set_error_handler(cmn->gfx_ctx, gfx_error_handler, cmn); +} + void MTY_WindowSetSyncInterval(MTY_App *app, MTY_Window window, uint32_t interval) { struct window_common *cmn = mty_window_get_common(app, window); diff --git a/src/app.h b/src/app.h index c2ea807f1..894fe1227 100644 --- a/src/app.h +++ b/src/app.h @@ -22,6 +22,13 @@ struct window_common { struct gfx *gfx[APP_GFX_LAYERS]; struct gfx_ui *gfx_ui; struct gfx_ctx *gfx_ctx; + + struct window_error_handling { + MTY_App *app; + MTY_Window window; // TODO THis is SOO ugly, refactor + MTY_WindowErrorFunc handler; + void *opaque; + } error_handling; }; // App diff --git a/src/gfx/mod-ctx.h b/src/gfx/mod-ctx.h index fcc2171a9..72229d0e7 100644 --- a/src/gfx/mod-ctx.h +++ b/src/gfx/mod-ctx.h @@ -14,6 +14,8 @@ struct gfx_ctx; +typedef int32_t (*gfx_error_handler_func)(int32_t e1, int32_t e2, void *opaque); + #define GFX_CTX_PROTO(api, name) mty##api##ctx_##name #define GFX_CTX_FP(api, name) (*name) @@ -27,7 +29,8 @@ struct gfx_ctx; MTY_Surface *wrap(api, get_surface)(struct gfx_ctx *gfx_ctx); \ void wrap(api, set_sync_interval)(struct gfx_ctx *gfx_ctx, uint32_t interval); \ bool wrap(api, lock)(struct gfx_ctx *gfx_ctx); \ - void wrap(api, unlock)(void); + void wrap(api, unlock)(void); \ + void wrap(api, set_error_handler)(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque); #define GFX_CTX_PROTOTYPES(api) \ GFX_CTX_DECLARE_API(api, GFX_CTX_PROTO) @@ -44,4 +47,5 @@ struct gfx_ctx; mty##api##ctx_set_sync_interval, \ mty##api##ctx_lock, \ mty##api##ctx_unlock, \ + mty##api##ctx_set_error_handler, \ }, diff --git a/src/gfx/vk/vk-ctx.c b/src/gfx/vk/vk-ctx.c index 49258bbb5..46d385ff7 100644 --- a/src/gfx/vk/vk-ctx.c +++ b/src/gfx/vk/vk-ctx.c @@ -720,3 +720,8 @@ bool mty_vk_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_vk_ctx_unlock(void) { } + +void mty_vk_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) +{ + gfx_ctx; func; opaque; +} diff --git a/src/matoya.h b/src/matoya.h index bdebf9d27..fc76be6e4 100644 --- a/src/matoya.h +++ b/src/matoya.h @@ -77,6 +77,8 @@ typedef bool (*MTY_MenuItemCheckedFunc)(void *opaque); typedef intptr_t (*MTY_WMsgFunc)(MTY_App *app, MTY_Window window, void *hwnd, uint32_t msg, intptr_t wparam, uintptr_t lparam, bool *shouldReturn, void *opaque); +typedef int32_t (*MTY_WindowErrorFunc)(MTY_App *app, MTY_Window window, int32_t error, int32_t internal_error, void *opaque); + /// @brief 3D graphics APIs. typedef enum { MTY_GFX_NONE = 0, ///< No 3D graphics API. @@ -1062,6 +1064,9 @@ MTY_WindowCreate(MTY_App *app, const char *title, const MTY_Frame *frame, MTY_Wi MTY_EXPORT void MTY_WindowDestroy(MTY_App *app, MTY_Window window); +MTY_EXPORT void +MTY_WindowSetErrorHandler(MTY_App *app, MTY_Window window, MTY_WindowErrorFunc func, void *opaque); + /// @brief Get a window's current client area width and height. /// @param app The MTY_App. /// @param window An MTY_Window. diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index 2ad872dc9..8265ad874 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -20,6 +20,8 @@ GFX_CTX_PROTOTYPES(_d3d11_) #define D3D11_CTX_WAIT 2000 +#define D3D11_CTX_ERROR(ctx, e1, e2) ((ctx)->error_handler(e1, e2, (ctx)->error_handler_opaque)) + struct d3d11_ctx { HWND hwnd; struct sync sync; @@ -33,6 +35,9 @@ struct d3d11_ctx { IDXGISwapChain2 *swap_chain2; HANDLE waitable; UINT flags; + + gfx_error_handler_func error_handler; + void *error_handler_opaque; }; static void d3d11_ctx_get_size(struct d3d11_ctx *ctx, uint32_t *width, uint32_t *height) @@ -193,6 +198,13 @@ static bool d3d11_ctx_init(struct d3d11_ctx *ctx) return e == S_OK; } +int32_t mty_d3d11_error_handler_default(int32_t e1, int32_t e2, void *opaque) +{ + e1; e2; opaque; + + return 0; +} + struct gfx_ctx *mty_d3d11_ctx_create(void *native_window, bool vsync) { struct d3d11_ctx *ctx = MTY_Alloc(1, sizeof(struct d3d11_ctx)); @@ -203,6 +215,8 @@ struct gfx_ctx *mty_d3d11_ctx_create(void *native_window, bool vsync) d3d11_ctx_get_size(ctx, &ctx->width, &ctx->height); + mty_d3d11_ctx_set_error_handler((struct gfx_ctx *) ctx, mty_d3d11_error_handler_default, NULL); + if (!d3d11_ctx_init(ctx)) mty_d3d11_ctx_destroy((struct gfx_ctx **) &ctx); @@ -264,7 +278,12 @@ static void d3d11_ctx_refresh(struct d3d11_ctx *ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_ResizeBuffers' failed with HRESULT 0x%X", e); d3d11_ctx_free(ctx); - d3d11_ctx_init(ctx); + + int32_t retry = D3D11_CTX_ERROR(ctx, -1, e); + if (retry >= 0) { + MTY_Sleep((uint32_t) retry); + d3d11_ctx_init(ctx); + } } } } @@ -288,8 +307,10 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) } e = ID3D11Device_CreateRenderTargetView(ctx->device, resource, NULL, &ctx->back_buffer); - if (e != S_OK) + if (e != S_OK) { MTY_Log("'ID3D11Device_CreateRenderTargetView' failed with HRESULT 0x%X", e); + goto except; + } } except: @@ -336,7 +357,12 @@ void mty_d3d11_ctx_present(struct gfx_ctx *gfx_ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_Present' failed with HRESULT 0x%X", e); d3d11_ctx_free(ctx); - d3d11_ctx_init(ctx); + + int32_t retry = D3D11_CTX_ERROR(ctx, -1, e); + if (retry >= 0) { + MTY_Sleep((uint32_t) retry); + d3d11_ctx_init(ctx); + } } else { DWORD we = WaitForSingleObjectEx(ctx->waitable, D3D11_CTX_WAIT, TRUE); @@ -354,3 +380,11 @@ bool mty_d3d11_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_d3d11_ctx_unlock(void) { } + +void mty_d3d11_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) +{ + struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; + + ctx->error_handler = func; + ctx->error_handler_opaque = opaque; +} diff --git a/src/windows/gfx/d3d12-ctx.c b/src/windows/gfx/d3d12-ctx.c index 9d617e9e9..7b2ab84e7 100644 --- a/src/windows/gfx/d3d12-ctx.c +++ b/src/windows/gfx/d3d12-ctx.c @@ -508,3 +508,8 @@ bool mty_d3d12_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_d3d12_ctx_unlock(void) { } + +void mty_d3d12_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) +{ + gfx_ctx; func; opaque; +} From b63b8f583df3a186147be5575eb83f605185944e Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Fri, 15 Mar 2024 09:37:18 -0400 Subject: [PATCH 02/11] More WIP --- src/windows/gfx/d3d11-ctx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index 8265ad874..c4645e9f5 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -292,6 +292,7 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) { struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; + HRESULT e = S_OK; ID3D11Resource *resource = NULL; if (!ctx->swap_chain2) @@ -300,7 +301,7 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) if (!ctx->back_buffer) { d3d11_ctx_refresh(ctx); - HRESULT e = IDXGISwapChain2_GetBuffer(ctx->swap_chain2, 0, &IID_ID3D11Resource, &resource); + e = IDXGISwapChain2_GetBuffer(ctx->swap_chain2, 0, &IID_ID3D11Resource, &resource); if (e != S_OK) { MTY_Log("'IDXGISwapChain2_GetBuffer' failed with HRESULT 0x%X", e); goto except; @@ -318,6 +319,13 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) if (resource) ID3D11Resource_Release(resource); + if (e != S_OK) { + int32_t retry = D3D11_CTX_ERROR(ctx, -1, e); + if (retry >= 0) { + MTY_Sleep((uint32_t) retry); + } + } + return (MTY_Surface *) ctx->back_buffer; } From 8a3b5fa6de953e141c524fca05a0599ec561bf1b Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Wed, 27 Mar 2024 01:53:16 -0400 Subject: [PATCH 03/11] Better idea. WIP --- src/app.c | 12 +++++++++ src/gfx/mod-ctx.h | 4 ++- src/gfx/mod-ui.h | 4 ++- src/gfx/vk/vk-ctx.c | 5 ++++ src/gfx/vk/vk-ui.c | 5 ++++ src/matoya.h | 3 +++ src/windows/gfx/d3d11-ctx.c | 49 ++++++++++++++++++++++--------------- src/windows/gfx/d3d11-ui.c | 34 ++++++++++++++++++++----- src/windows/gfx/d3d12-ctx.c | 5 ++++ src/windows/gfx/d3d12-ui.c | 5 ++++ 10 files changed, 98 insertions(+), 28 deletions(-) diff --git a/src/app.c b/src/app.c index 05149e36f..36671fc4f 100644 --- a/src/app.c +++ b/src/app.c @@ -310,6 +310,18 @@ void MTY_WindowSetErrorHandler(MTY_App *app, MTY_Window window, MTY_WindowErrorF GFX_CTX_API[cmn->api].set_error_handler(cmn->gfx_ctx, gfx_error_handler, cmn); } +int32_t MTY_WindowGetError(MTY_App *app, MTY_Window window) +{ + struct window_common *cmn = mty_window_get_common(app, window); + if (!cmn || cmn->api == MTY_GFX_NONE) + return 0; + + int32_t e = cmn->gfx_ctx ? GFX_CTX_API[cmn->api].get_error(cmn->gfx_ctx) : 0; + if (!e && cmn->gfx_ui) + e = GFX_UI_API[cmn->api].get_error(cmn->gfx_ui); + return e; +} + void MTY_WindowSetSyncInterval(MTY_App *app, MTY_Window window, uint32_t interval) { struct window_common *cmn = mty_window_get_common(app, window); diff --git a/src/gfx/mod-ctx.h b/src/gfx/mod-ctx.h index 72229d0e7..d3f402cf5 100644 --- a/src/gfx/mod-ctx.h +++ b/src/gfx/mod-ctx.h @@ -30,7 +30,8 @@ typedef int32_t (*gfx_error_handler_func)(int32_t e1, int32_t e2, void *opaque); void wrap(api, set_sync_interval)(struct gfx_ctx *gfx_ctx, uint32_t interval); \ bool wrap(api, lock)(struct gfx_ctx *gfx_ctx); \ void wrap(api, unlock)(void); \ - void wrap(api, set_error_handler)(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque); + void wrap(api, set_error_handler)(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque); \ + int32_t wrap(api, get_error)(struct gfx_ctx *gfx_ctx); #define GFX_CTX_PROTOTYPES(api) \ GFX_CTX_DECLARE_API(api, GFX_CTX_PROTO) @@ -48,4 +49,5 @@ typedef int32_t (*gfx_error_handler_func)(int32_t e1, int32_t e2, void *opaque); mty##api##ctx_lock, \ mty##api##ctx_unlock, \ mty##api##ctx_set_error_handler, \ + mty##api##ctx_get_error, \ }, diff --git a/src/gfx/mod-ui.h b/src/gfx/mod-ui.h index e199d623d..a5e39e996 100644 --- a/src/gfx/mod-ui.h +++ b/src/gfx/mod-ui.h @@ -29,7 +29,8 @@ struct gfx_ui; void *wrap(api, create_texture)(struct gfx_ui *gfx_ui, MTY_Device *device, \ const void *rgba, uint32_t width, uint32_t height); \ void wrap(api, destroy_texture)(struct gfx_ui *gfx_ui, void **texture, \ - MTY_Device *device); + MTY_Device *device); \ + int32_t wrap(api, get_error)(struct gfx_ui *gfx_ui); #define GFX_UI_PROTOTYPES(api) \ GFX_UI_DECLARE_API(api, GFX_UI_PROTO) @@ -41,4 +42,5 @@ struct gfx_ui; mty##api##ui_render, \ mty##api##ui_create_texture, \ mty##api##ui_destroy_texture, \ + mty##api##ui_get_error, \ }, diff --git a/src/gfx/vk/vk-ctx.c b/src/gfx/vk/vk-ctx.c index 46d385ff7..8957508c1 100644 --- a/src/gfx/vk/vk-ctx.c +++ b/src/gfx/vk/vk-ctx.c @@ -725,3 +725,8 @@ void mty_vk_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_fun { gfx_ctx; func; opaque; } + +int32_t mty_vk_ctx_get_error(struct gfx_ctx *gfx_ctx) +{ + return 0; +} diff --git a/src/gfx/vk/vk-ui.c b/src/gfx/vk/vk-ui.c index fc87da36e..59abe3746 100644 --- a/src/gfx/vk/vk-ui.c +++ b/src/gfx/vk/vk-ui.c @@ -639,3 +639,8 @@ void mty_vk_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } + +int32_t mty_vk_ui_get_error(struct gfx_ui *gfx_ui) +{ + return 0; +} diff --git a/src/matoya.h b/src/matoya.h index fc76be6e4..2e7b42214 100644 --- a/src/matoya.h +++ b/src/matoya.h @@ -1064,6 +1064,9 @@ MTY_WindowCreate(MTY_App *app, const char *title, const MTY_Frame *frame, MTY_Wi MTY_EXPORT void MTY_WindowDestroy(MTY_App *app, MTY_Window window); +MTY_EXPORT int32_t +MTY_WindowGetError(MTY_App *app, MTY_Window window); + MTY_EXPORT void MTY_WindowSetErrorHandler(MTY_App *app, MTY_Window window, MTY_WindowErrorFunc func, void *opaque); diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index c4645e9f5..b770a8a8b 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -38,6 +38,7 @@ struct d3d11_ctx { gfx_error_handler_func error_handler; void *error_handler_opaque; + int32_t last_error; }; static void d3d11_ctx_get_size(struct d3d11_ctx *ctx, uint32_t *width, uint32_t *height) @@ -192,8 +193,12 @@ static bool d3d11_ctx_init(struct d3d11_ctx *ctx) if (device2) IDXGIDevice2_Release(device2); - if (e != S_OK) + if (e != S_OK) { + D3D11_CTX_ERROR(ctx, -1, e); d3d11_ctx_free(ctx); + } + + ctx->last_error = e; return e == S_OK; } @@ -277,14 +282,13 @@ static void d3d11_ctx_refresh(struct d3d11_ctx *ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_ResizeBuffers' failed with HRESULT 0x%X", e); - d3d11_ctx_free(ctx); + D3D11_CTX_ERROR(ctx, -1, e); - int32_t retry = D3D11_CTX_ERROR(ctx, -1, e); - if (retry >= 0) { - MTY_Sleep((uint32_t) retry); - d3d11_ctx_init(ctx); - } + d3d11_ctx_free(ctx); + d3d11_ctx_init(ctx); } + + ctx->last_error = e; } } @@ -319,12 +323,10 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) if (resource) ID3D11Resource_Release(resource); - if (e != S_OK) { - int32_t retry = D3D11_CTX_ERROR(ctx, -1, e); - if (retry >= 0) { - MTY_Sleep((uint32_t) retry); - } - } + if (e != S_OK) + D3D11_CTX_ERROR(ctx, -1, e); + + ctx->last_error = e; return (MTY_Surface *) ctx->back_buffer; } @@ -364,19 +366,20 @@ void mty_d3d11_ctx_present(struct gfx_ctx *gfx_ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_Present' failed with HRESULT 0x%X", e); - d3d11_ctx_free(ctx); + D3D11_CTX_ERROR(ctx, -1, e); - int32_t retry = D3D11_CTX_ERROR(ctx, -1, e); - if (retry >= 0) { - MTY_Sleep((uint32_t) retry); - d3d11_ctx_init(ctx); - } + d3d11_ctx_free(ctx); + d3d11_ctx_init(ctx); } else { DWORD we = WaitForSingleObjectEx(ctx->waitable, D3D11_CTX_WAIT, TRUE); - if (we != WAIT_OBJECT_0) + if (we != WAIT_OBJECT_0) { MTY_Log("'WaitForSingleObjectEx' failed with error 0x%X", we); + D3D11_CTX_ERROR(ctx, -1, (int32_t) we); + } } + + ctx->last_error = e; } } @@ -396,3 +399,9 @@ void mty_d3d11_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_ ctx->error_handler = func; ctx->error_handler_opaque = opaque; } + +int32_t mty_d3d11_ctx_get_error(struct gfx_ctx *gfx_ctx) +{ + struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; + return ctx->last_error; +} diff --git a/src/windows/gfx/d3d11-ui.c b/src/windows/gfx/d3d11-ui.c index 0a5621879..253ba174d 100644 --- a/src/windows/gfx/d3d11-ui.c +++ b/src/windows/gfx/d3d11-ui.c @@ -35,6 +35,8 @@ struct d3d11_ui { ID3D11RasterizerState *rs; ID3D11BlendState *bs; ID3D11DepthStencilState *dss; + + int32_t last_error; }; struct d3d11_ui_cb { @@ -149,6 +151,9 @@ struct gfx_ui *mty_d3d11_ui_create(MTY_Device *device) except: + // TODO: Need a way to bubble up this value...perhaps pass an out param to this function? + ctx->last_error = e; + if (e != S_OK) mty_d3d11_ui_destroy((struct gfx_ui **) &ctx, device); @@ -204,30 +209,32 @@ bool mty_d3d11_ui_render(struct gfx_ui *gfx_ui, MTY_Device *device, MTY_Context if (dd->displaySize.x <= 0 || dd->displaySize.y <= 0 || dd->cmdListLength == 0) return false; + bool result = false; + // Resize vertex and index buffers if necessary HRESULT e = d3d11_ui_resize_buffer(_device, &ctx->vb, dd->vtxTotalLength, GFX_UI_VTX_INCR, sizeof(MTY_Vtx), D3D11_BIND_VERTEX_BUFFER); if (e != S_OK) - return false; + goto except; e = d3d11_ui_resize_buffer(_device, &ctx->ib, dd->idxTotalLength, GFX_UI_IDX_INCR, sizeof(uint16_t), D3D11_BIND_INDEX_BUFFER); if (e != S_OK) - return false; + goto except; // Map both vertex and index buffers and bulk copy the data D3D11_MAPPED_SUBRESOURCE vtx_map = {0}; e = ID3D11DeviceContext_Map(_context, ctx->vb.res, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_map); if (e != S_OK) { MTY_Log("'ID3D11DeviceContext_Map' failed with HRESULT 0x%X", e); - return false; + goto except; } D3D11_MAPPED_SUBRESOURCE idx_map = {0}; e = ID3D11DeviceContext_Map(_context, ctx->ib.res, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_map); if (e != S_OK) { MTY_Log("'ID3D11DeviceContext_Map' failed with HRESULT 0x%X", e); - return false; + goto except; } MTY_Vtx *vtx_dst = (MTY_Vtx *) vtx_map.pData; @@ -261,7 +268,7 @@ bool mty_d3d11_ui_render(struct gfx_ui *gfx_ui, MTY_Device *device, MTY_Context D3D11_MAPPED_SUBRESOURCE cb_map = {0}; e = ID3D11DeviceContext_Map(_context, ctx->cb_res, 0, D3D11_MAP_WRITE_DISCARD, 0, &cb_map); if (e != S_OK) - return false; + goto except; struct d3d11_ui_cb *cb = (struct d3d11_ui_cb *) cb_map.pData; memcpy(&cb->proj, proj, sizeof(proj)); @@ -338,12 +345,19 @@ bool mty_d3d11_ui_render(struct gfx_ui *gfx_ui, MTY_Device *device, MTY_Context vtxOffset += cmdList->vtxLength; } - return true; + result = true; + + except: + + ctx->last_error = e; + + return result; } void *mty_d3d11_ui_create_texture(struct gfx_ui *gfx_ui, MTY_Device *device, const void *rgba, uint32_t width, uint32_t height) { + struct d3d11_ui *ctx = (struct d3d11_ui *) gfx_ui; ID3D11Device *_device = (ID3D11Device *) device; ID3D11Texture2D *tex = NULL; @@ -398,6 +412,8 @@ void *mty_d3d11_ui_create_texture(struct gfx_ui *gfx_ui, MTY_Device *device, con srv = NULL; } + ctx->last_error = e; + return srv; } @@ -461,3 +477,9 @@ void mty_d3d11_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } + +int32_t mty_d3d11_ui_get_error(struct gfx_ui *gfx_ui) +{ + struct d3d11_ui *ctx = (struct d3d11_ui *) gfx_ui; + return ctx->last_error; +} diff --git a/src/windows/gfx/d3d12-ctx.c b/src/windows/gfx/d3d12-ctx.c index 7b2ab84e7..1507400cb 100644 --- a/src/windows/gfx/d3d12-ctx.c +++ b/src/windows/gfx/d3d12-ctx.c @@ -513,3 +513,8 @@ void mty_d3d12_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_ { gfx_ctx; func; opaque; } + +int32_t mty_d3d12_ctx_get_error(struct gfx_ctx *gfx_ctx) +{ + return 0; +} diff --git a/src/windows/gfx/d3d12-ui.c b/src/windows/gfx/d3d12-ui.c index 36b1d16c8..c1a9a958b 100644 --- a/src/windows/gfx/d3d12-ui.c +++ b/src/windows/gfx/d3d12-ui.c @@ -571,3 +571,8 @@ void mty_d3d12_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } + +int32_t mty_d3d12_ui_get_error(struct gfx_ui *gfx_ui) +{ + return 0; +} From 33f73bf72de6192eb9507746ba73a265d89d71fe Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Wed, 27 Mar 2024 02:18:55 -0400 Subject: [PATCH 04/11] Add stubs for non-windows platforms. --- src/gfx/gl/gl-ui.c | 5 +++++ src/unix/apple/gfx/metal-ui.m | 5 +++++ src/unix/apple/macosx/gfx/metal-ctx.m | 10 ++++++++++ src/unix/linux/android/gfx/gl-ctx.c | 10 ++++++++++ src/unix/linux/x11/gfx/gl-ctx.c | 10 ++++++++++ src/unix/web/gfx/gl-ctx.c | 10 ++++++++++ 6 files changed, 50 insertions(+) diff --git a/src/gfx/gl/gl-ui.c b/src/gfx/gl/gl-ui.c index a80226058..483c33d04 100644 --- a/src/gfx/gl/gl-ui.c +++ b/src/gfx/gl/gl-ui.c @@ -290,3 +290,8 @@ void mty_gl_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } + +int32_t mty_gl_ui_get_error(struct gfx_ui *gfx_ui) +{ + return 0; +} diff --git a/src/unix/apple/gfx/metal-ui.m b/src/unix/apple/gfx/metal-ui.m index 6845cd524..4143f2cb3 100644 --- a/src/unix/apple/gfx/metal-ui.m +++ b/src/unix/apple/gfx/metal-ui.m @@ -236,3 +236,8 @@ void mty_metal_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } + +int32_t mty_metal_ui_get_error(struct gfx_ui *gfx_ui) +{ + return 0; +} diff --git a/src/unix/apple/macosx/gfx/metal-ctx.m b/src/unix/apple/macosx/gfx/metal-ctx.m index ffe622dcd..7d959d801 100644 --- a/src/unix/apple/macosx/gfx/metal-ctx.m +++ b/src/unix/apple/macosx/gfx/metal-ctx.m @@ -172,3 +172,13 @@ bool mty_metal_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_metal_ctx_unlock(void) { } + +void mty_metal_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) +{ + gfx_ctx; func; opaque; +} + +int32_t mty_metal_ctx_get_error(struct gfx_ctx *gfx_ctx) +{ + return 0; +} diff --git a/src/unix/linux/android/gfx/gl-ctx.c b/src/unix/linux/android/gfx/gl-ctx.c index 865494b4d..86d745270 100644 --- a/src/unix/linux/android/gfx/gl-ctx.c +++ b/src/unix/linux/android/gfx/gl-ctx.c @@ -205,3 +205,13 @@ void mty_gl_ctx_unlock(void) { mty_gfx_unlock(); } + +void mty_gl_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) +{ + gfx_ctx; func; opaque; +} + +int32_t mty_gl_ctx_get_error(struct gfx_ctx *gfx_ctx) +{ + return 0; +} diff --git a/src/unix/linux/x11/gfx/gl-ctx.c b/src/unix/linux/x11/gfx/gl-ctx.c index e9cab3951..f2b53a20b 100644 --- a/src/unix/linux/x11/gfx/gl-ctx.c +++ b/src/unix/linux/x11/gfx/gl-ctx.c @@ -119,3 +119,13 @@ bool mty_gl_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_gl_ctx_unlock(void) { } + +void mty_gl_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) +{ + gfx_ctx; func; opaque; +} + +int32_t mty_gl_ctx_get_error(struct gfx_ctx *gfx_ctx) +{ + return 0; +} diff --git a/src/unix/web/gfx/gl-ctx.c b/src/unix/web/gfx/gl-ctx.c index c5ff2c023..ca8837bb8 100644 --- a/src/unix/web/gfx/gl-ctx.c +++ b/src/unix/web/gfx/gl-ctx.c @@ -86,3 +86,13 @@ bool mty_gl_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_gl_ctx_unlock(void) { } + +void mty_gl_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) +{ + gfx_ctx; func; opaque; +} + +int32_t mty_gl_ctx_get_error(struct gfx_ctx *gfx_ctx) +{ + return 0; +} From be4ad33cd25ce9ee32c585f697fb6fe02d81b0d3 Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Wed, 3 Apr 2024 08:13:40 -0400 Subject: [PATCH 05/11] Even better idea: use a tlocal queue. Changed error to be scoped to a thread and not a window. Defined error codes so that matoya clients can action differently based on the error received while still masking the internal error details. --- GNUmakefile | 1 + makefile | 1 + src/app.c | 33 ------------------------ src/error.c | 48 +++++++++++++++++++++++++++++++++++ src/error.h | 9 +++++++ src/matoya.h | 19 +++++++++++--- src/thread.c | 11 ++++++++ src/windows/gfx/d3d11-ctx.c | 22 ++++++---------- src/windows/gfx/d3d11-error.h | 29 +++++++++++++++++++++ src/windows/gfx/d3d11-ui.c | 17 +++++++------ src/windows/threadw.c | 4 +++ 11 files changed, 136 insertions(+), 58 deletions(-) create mode 100644 src/error.c create mode 100644 src/error.h create mode 100644 src/windows/gfx/d3d11-error.h diff --git a/GNUmakefile b/GNUmakefile index 78a40ed11..bcc38d3f4 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -24,6 +24,7 @@ OBJS = \ src/async.o \ src/crypto.o \ src/dtls.o \ + src/error.o \ src/file.o \ src/hash.o \ src/http.o \ diff --git a/makefile b/makefile index cd4789d46..92a1b0e79 100644 --- a/makefile +++ b/makefile @@ -27,6 +27,7 @@ OBJS = \ src\async.obj \ src\crypto.obj \ src\dtls.obj \ + src\error.obj \ src\file.obj \ src\hash.obj \ src\http.obj \ diff --git a/src/app.c b/src/app.c index 36671fc4f..6890e2fb1 100644 --- a/src/app.c +++ b/src/app.c @@ -289,39 +289,6 @@ bool MTY_WindowSetGFX(MTY_App *app, MTY_Window window, MTY_GFX api, bool vsync) return cmn->gfx_ctx != NULL; } -static int32_t gfx_error_handler(int32_t e1, int32_t e2, void *opaque) -{ - struct window_common *cmn = (struct window_common *) opaque; - - return cmn->error_handling.handler(cmn->error_handling.app, cmn->error_handling.window, e1, e2, opaque); -} - -void MTY_WindowSetErrorHandler(MTY_App *app, MTY_Window window, MTY_WindowErrorFunc func, void *opaque) -{ - struct window_common *cmn = mty_window_get_common(app, window); - if (!cmn || cmn->api == MTY_GFX_NONE) - return; - - cmn->error_handling.app = app; - cmn->error_handling.window = window; - cmn->error_handling.handler = func; - cmn->error_handling.opaque = opaque; - - GFX_CTX_API[cmn->api].set_error_handler(cmn->gfx_ctx, gfx_error_handler, cmn); -} - -int32_t MTY_WindowGetError(MTY_App *app, MTY_Window window) -{ - struct window_common *cmn = mty_window_get_common(app, window); - if (!cmn || cmn->api == MTY_GFX_NONE) - return 0; - - int32_t e = cmn->gfx_ctx ? GFX_CTX_API[cmn->api].get_error(cmn->gfx_ctx) : 0; - if (!e && cmn->gfx_ui) - e = GFX_UI_API[cmn->api].get_error(cmn->gfx_ui); - return e; -} - void MTY_WindowSetSyncInterval(MTY_App *app, MTY_Window window, uint32_t interval) { struct window_common *cmn = mty_window_get_common(app, window); diff --git a/src/error.c b/src/error.c new file mode 100644 index 000000000..91e66fce9 --- /dev/null +++ b/src/error.c @@ -0,0 +1,48 @@ +#include "error.h" + +#include "tlocal.h" + +static TLOCAL MTY_Queue *Q = NULL; + +void error_local_init(void) +{ + error_local_clear(); + + Q = MTY_QueueCreate(10, sizeof(MTY_Error)); +} + +void error_local_clear(void) +{ + MTY_QueueDestroy(&Q); +} + + +bool error_local_get_next_error(MTY_Error *error) +{ + if (!Q) + return false; + + MTY_Error *buf = NULL; + + bool rc = MTY_QueueGetOutputBuffer(Q, 0, (void **) &buf, NULL); + if (rc) { + *error = *buf; + MTY_QueuePop(Q); + } + + return rc; +} + +void error_local_push_error(MTY_Error error) +{ + if (!Q) + return; + + // TODO: Maybe don't push onto queue when error is 0? + + MTY_Error *buf = MTY_QueueGetInputBuffer(Q); + if (buf) { + *buf = error; + MTY_QueuePush(Q, sizeof(MTY_Error)); + } +} diff --git a/src/error.h b/src/error.h new file mode 100644 index 000000000..787779beb --- /dev/null +++ b/src/error.h @@ -0,0 +1,9 @@ +#pragma once + +#include "matoya.h" + +void error_local_init(void); +void error_local_clear(void); + +bool error_local_get_next_error(MTY_Error *error); +void error_local_push_error(MTY_Error error); diff --git a/src/matoya.h b/src/matoya.h index 2e7b42214..de97a2790 100644 --- a/src/matoya.h +++ b/src/matoya.h @@ -79,6 +79,17 @@ typedef intptr_t (*MTY_WMsgFunc)(MTY_App *app, MTY_Window window, void *hwnd, ui typedef int32_t (*MTY_WindowErrorFunc)(MTY_App *app, MTY_Window window, int32_t error, int32_t internal_error, void *opaque); +/// @brief Error codes indicating the current state of the platform. +/// @details Warnings are positive, errors are negative, 0 (::MTY_ERROR_OK) means no error. +typedef enum { + MTY_ERROR_OK = 0, ///< No errors. + MTY_ERROR_GFX_INVISIBLE_CONTENT = 11, ///< Warning from the gfx driver that rendered content is hidden (for example, when app is in the UAC prompt on Windows) + MTY_ERROR_GFX_REVISIBLE_CONTENT = 12, ///< Notice from the gfx driver that rendered content that was hidden is now visible + MTY_ERROR_GFX_ERROR = -11, ///< Generic gfx error + MTY_ERROR_GFX_DEVICE_REMOVED = -21, ///< Generally indicates that the display was unplugged or disabled abruptly + MTY_ERROR_MAKE_32 = INT32_MAX, +} MTY_Error; + /// @brief 3D graphics APIs. typedef enum { MTY_GFX_NONE = 0, ///< No 3D graphics API. @@ -1064,9 +1075,6 @@ MTY_WindowCreate(MTY_App *app, const char *title, const MTY_Frame *frame, MTY_Wi MTY_EXPORT void MTY_WindowDestroy(MTY_App *app, MTY_Window window); -MTY_EXPORT int32_t -MTY_WindowGetError(MTY_App *app, MTY_Window window); - MTY_EXPORT void MTY_WindowSetErrorHandler(MTY_App *app, MTY_Window window, MTY_WindowErrorFunc func, void *opaque); @@ -2625,6 +2633,11 @@ MTY_ThreadDetach(MTY_ThreadFunc func, void *opaque); MTY_EXPORT int64_t MTY_ThreadGetID(MTY_Thread *ctx); +/// @brief Get the next error code for the given thread. +/// @param ctx An MTY_Thread. +MTY_EXPORT MTY_Error +MTY_ThreadGetError(MTY_Thread *ctx); + /// @brief Create an MTY_Mutex for synchronization. /// @details A mutex can be locked by only one thread at a time. Other threads trying /// to take the same mutex will block until it becomes unlocked. diff --git a/src/thread.c b/src/thread.c index 58689d277..d9db134e8 100644 --- a/src/thread.c +++ b/src/thread.c @@ -10,7 +10,18 @@ #include "rwlock.h" #include "tlocal.h" +#include "error.h" +// Thread + +MTY_Error MTY_ThreadGetError(MTY_Thread *ctx) +{ + ctx; // not used since errors are managed via tlocal state + + MTY_Error e = MTY_ERROR_OK; + error_local_get_next_error(&e); + return e; +} // RWLock diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index b770a8a8b..276795728 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -12,16 +12,17 @@ GFX_CTX_PROTOTYPES(_d3d11_) #include "gfx/sync.h" #include "dxgi-sync.h" +#include "d3d11-error.h" + #define DXGI_FATAL(e) ( \ (e) == DXGI_ERROR_DEVICE_REMOVED || \ + (e) == DXGI_ERROR_DRIVER_INTERNAL_ERROR || \ (e) == DXGI_ERROR_DEVICE_HUNG || \ (e) == DXGI_ERROR_DEVICE_RESET \ ) #define D3D11_CTX_WAIT 2000 -#define D3D11_CTX_ERROR(ctx, e1, e2) ((ctx)->error_handler(e1, e2, (ctx)->error_handler_opaque)) - struct d3d11_ctx { HWND hwnd; struct sync sync; @@ -194,12 +195,10 @@ static bool d3d11_ctx_init(struct d3d11_ctx *ctx) IDXGIDevice2_Release(device2); if (e != S_OK) { - D3D11_CTX_ERROR(ctx, -1, e); + d3d11_push_local_error(e); d3d11_ctx_free(ctx); } - ctx->last_error = e; - return e == S_OK; } @@ -282,13 +281,11 @@ static void d3d11_ctx_refresh(struct d3d11_ctx *ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_ResizeBuffers' failed with HRESULT 0x%X", e); - D3D11_CTX_ERROR(ctx, -1, e); + d3d11_push_local_error(e); d3d11_ctx_free(ctx); d3d11_ctx_init(ctx); } - - ctx->last_error = e; } } @@ -324,9 +321,8 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) ID3D11Resource_Release(resource); if (e != S_OK) - D3D11_CTX_ERROR(ctx, -1, e); + d3d11_push_local_error(e); - ctx->last_error = e; return (MTY_Surface *) ctx->back_buffer; } @@ -366,7 +362,7 @@ void mty_d3d11_ctx_present(struct gfx_ctx *gfx_ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_Present' failed with HRESULT 0x%X", e); - D3D11_CTX_ERROR(ctx, -1, e); + d3d11_push_local_error(e); d3d11_ctx_free(ctx); d3d11_ctx_init(ctx); @@ -375,11 +371,9 @@ void mty_d3d11_ctx_present(struct gfx_ctx *gfx_ctx) DWORD we = WaitForSingleObjectEx(ctx->waitable, D3D11_CTX_WAIT, TRUE); if (we != WAIT_OBJECT_0) { MTY_Log("'WaitForSingleObjectEx' failed with error 0x%X", we); - D3D11_CTX_ERROR(ctx, -1, (int32_t) we); + d3d11_push_local_error(e); } } - - ctx->last_error = e; } } diff --git a/src/windows/gfx/d3d11-error.h b/src/windows/gfx/d3d11-error.h new file mode 100644 index 000000000..4405aaeae --- /dev/null +++ b/src/windows/gfx/d3d11-error.h @@ -0,0 +1,29 @@ +#pragma once + +#include "matoya.h" + +#include "error.h" + +static MTY_Error d3d11_map_error(int32_t e) +{ + switch (e) { + case DXGI_ERROR_DEVICE_REMOVED: + case DXGI_ERROR_DRIVER_INTERNAL_ERROR: + return MTY_ERROR_GFX_DEVICE_REMOVED; + + case DXGI_ERROR_DEVICE_HUNG: + case DXGI_ERROR_DEVICE_RESET: + return MTY_ERROR_GFX_ERROR; + + case DXGI_STATUS_OCCLUDED: + return MTY_ERROR_GFX_INVISIBLE_CONTENT; + + case DXGI_STATUS_UNOCCLUDED: + return MTY_ERROR_GFX_REVISIBLE_CONTENT; + + default: + return MTY_ERROR_OK; + } +} + +#define d3d11_push_local_error(e) error_local_push_error(d3d11_map_error(e)) diff --git a/src/windows/gfx/d3d11-ui.c b/src/windows/gfx/d3d11-ui.c index 253ba174d..90703cc5e 100644 --- a/src/windows/gfx/d3d11-ui.c +++ b/src/windows/gfx/d3d11-ui.c @@ -17,6 +17,8 @@ static static #include "shaders/vsui.h" +#include "d3d11-error.h" + struct d3d11_ui_buffer { ID3D11Buffer *b; ID3D11Resource *res; @@ -151,11 +153,11 @@ struct gfx_ui *mty_d3d11_ui_create(MTY_Device *device) except: - // TODO: Need a way to bubble up this value...perhaps pass an out param to this function? - ctx->last_error = e; - - if (e != S_OK) + if (e != S_OK) { + d3d11_push_local_error(e); mty_d3d11_ui_destroy((struct gfx_ui **) &ctx, device); + } + return (struct gfx_ui *) ctx; } @@ -349,7 +351,8 @@ bool mty_d3d11_ui_render(struct gfx_ui *gfx_ui, MTY_Device *device, MTY_Context except: - ctx->last_error = e; + if (e != S_OK) + d3d11_push_local_error(e); return result; } @@ -357,7 +360,6 @@ bool mty_d3d11_ui_render(struct gfx_ui *gfx_ui, MTY_Device *device, MTY_Context void *mty_d3d11_ui_create_texture(struct gfx_ui *gfx_ui, MTY_Device *device, const void *rgba, uint32_t width, uint32_t height) { - struct d3d11_ui *ctx = (struct d3d11_ui *) gfx_ui; ID3D11Device *_device = (ID3D11Device *) device; ID3D11Texture2D *tex = NULL; @@ -408,12 +410,11 @@ void *mty_d3d11_ui_create_texture(struct gfx_ui *gfx_ui, MTY_Device *device, con ID3D11Texture2D_Release(tex); if (e != S_OK && srv) { + d3d11_push_local_error(e); ID3D11ShaderResourceView_Release(srv); srv = NULL; } - ctx->last_error = e; - return srv; } diff --git a/src/windows/threadw.c b/src/windows/threadw.c index 2f8c894a0..d69b3e9ae 100644 --- a/src/windows/threadw.c +++ b/src/windows/threadw.c @@ -8,6 +8,7 @@ #include +#include "error.h" // Thread @@ -51,6 +52,7 @@ static MTY_Thread *thread_create(MTY_ThreadFunc func, void *opaque, bool detach) } else { ctx->thread = thread; + error_local_init(); } return ctx; @@ -69,6 +71,8 @@ void *MTY_ThreadDestroy(MTY_Thread **thread) MTY_Thread *ctx = *thread; if (ctx->thread) { + error_local_clear(); + if (WaitForSingleObject(ctx->thread, INFINITE) == WAIT_FAILED) MTY_LogFatal("'WaitForSingleObject' failed with error 0x%X", GetLastError()); From c01406164679c6aea99cd163d4619e2380dbb5fc Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Wed, 3 Apr 2024 08:35:59 -0400 Subject: [PATCH 06/11] Cleanup --- src/app.h | 7 ------- src/error.c | 2 -- src/gfx/gl/gl-ui.c | 5 ----- src/gfx/mod-ctx.h | 8 +------- src/gfx/mod-ui.h | 4 +--- src/gfx/vk/vk-ctx.c | 10 ---------- src/gfx/vk/vk-ui.c | 5 ----- src/matoya.h | 5 ----- src/thread.c | 2 +- src/unix/apple/macosx/gfx/metal-ctx.m | 10 ---------- src/unix/linux/android/gfx/gl-ctx.c | 10 ---------- src/unix/linux/x11/gfx/gl-ctx.c | 10 ---------- src/unix/web/gfx/gl-ctx.c | 10 ---------- src/windows/gfx/d3d11-ctx.c | 20 -------------------- src/windows/gfx/d3d11-ui.c | 8 -------- src/windows/gfx/d3d12-ctx.c | 10 ---------- src/windows/gfx/d3d12-ui.c | 5 ----- 17 files changed, 3 insertions(+), 128 deletions(-) diff --git a/src/app.h b/src/app.h index 894fe1227..c2ea807f1 100644 --- a/src/app.h +++ b/src/app.h @@ -22,13 +22,6 @@ struct window_common { struct gfx *gfx[APP_GFX_LAYERS]; struct gfx_ui *gfx_ui; struct gfx_ctx *gfx_ctx; - - struct window_error_handling { - MTY_App *app; - MTY_Window window; // TODO THis is SOO ugly, refactor - MTY_WindowErrorFunc handler; - void *opaque; - } error_handling; }; // App diff --git a/src/error.c b/src/error.c index 91e66fce9..c45be3e40 100644 --- a/src/error.c +++ b/src/error.c @@ -38,8 +38,6 @@ void error_local_push_error(MTY_Error error) if (!Q) return; - // TODO: Maybe don't push onto queue when error is 0? - MTY_Error *buf = MTY_QueueGetInputBuffer(Q); if (buf) { *buf = error; diff --git a/src/gfx/gl/gl-ui.c b/src/gfx/gl/gl-ui.c index 483c33d04..a80226058 100644 --- a/src/gfx/gl/gl-ui.c +++ b/src/gfx/gl/gl-ui.c @@ -290,8 +290,3 @@ void mty_gl_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } - -int32_t mty_gl_ui_get_error(struct gfx_ui *gfx_ui) -{ - return 0; -} diff --git a/src/gfx/mod-ctx.h b/src/gfx/mod-ctx.h index d3f402cf5..fcc2171a9 100644 --- a/src/gfx/mod-ctx.h +++ b/src/gfx/mod-ctx.h @@ -14,8 +14,6 @@ struct gfx_ctx; -typedef int32_t (*gfx_error_handler_func)(int32_t e1, int32_t e2, void *opaque); - #define GFX_CTX_PROTO(api, name) mty##api##ctx_##name #define GFX_CTX_FP(api, name) (*name) @@ -29,9 +27,7 @@ typedef int32_t (*gfx_error_handler_func)(int32_t e1, int32_t e2, void *opaque); MTY_Surface *wrap(api, get_surface)(struct gfx_ctx *gfx_ctx); \ void wrap(api, set_sync_interval)(struct gfx_ctx *gfx_ctx, uint32_t interval); \ bool wrap(api, lock)(struct gfx_ctx *gfx_ctx); \ - void wrap(api, unlock)(void); \ - void wrap(api, set_error_handler)(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque); \ - int32_t wrap(api, get_error)(struct gfx_ctx *gfx_ctx); + void wrap(api, unlock)(void); #define GFX_CTX_PROTOTYPES(api) \ GFX_CTX_DECLARE_API(api, GFX_CTX_PROTO) @@ -48,6 +44,4 @@ typedef int32_t (*gfx_error_handler_func)(int32_t e1, int32_t e2, void *opaque); mty##api##ctx_set_sync_interval, \ mty##api##ctx_lock, \ mty##api##ctx_unlock, \ - mty##api##ctx_set_error_handler, \ - mty##api##ctx_get_error, \ }, diff --git a/src/gfx/mod-ui.h b/src/gfx/mod-ui.h index a5e39e996..e199d623d 100644 --- a/src/gfx/mod-ui.h +++ b/src/gfx/mod-ui.h @@ -29,8 +29,7 @@ struct gfx_ui; void *wrap(api, create_texture)(struct gfx_ui *gfx_ui, MTY_Device *device, \ const void *rgba, uint32_t width, uint32_t height); \ void wrap(api, destroy_texture)(struct gfx_ui *gfx_ui, void **texture, \ - MTY_Device *device); \ - int32_t wrap(api, get_error)(struct gfx_ui *gfx_ui); + MTY_Device *device); #define GFX_UI_PROTOTYPES(api) \ GFX_UI_DECLARE_API(api, GFX_UI_PROTO) @@ -42,5 +41,4 @@ struct gfx_ui; mty##api##ui_render, \ mty##api##ui_create_texture, \ mty##api##ui_destroy_texture, \ - mty##api##ui_get_error, \ }, diff --git a/src/gfx/vk/vk-ctx.c b/src/gfx/vk/vk-ctx.c index 8957508c1..49258bbb5 100644 --- a/src/gfx/vk/vk-ctx.c +++ b/src/gfx/vk/vk-ctx.c @@ -720,13 +720,3 @@ bool mty_vk_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_vk_ctx_unlock(void) { } - -void mty_vk_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) -{ - gfx_ctx; func; opaque; -} - -int32_t mty_vk_ctx_get_error(struct gfx_ctx *gfx_ctx) -{ - return 0; -} diff --git a/src/gfx/vk/vk-ui.c b/src/gfx/vk/vk-ui.c index 59abe3746..fc87da36e 100644 --- a/src/gfx/vk/vk-ui.c +++ b/src/gfx/vk/vk-ui.c @@ -639,8 +639,3 @@ void mty_vk_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } - -int32_t mty_vk_ui_get_error(struct gfx_ui *gfx_ui) -{ - return 0; -} diff --git a/src/matoya.h b/src/matoya.h index de97a2790..1c522353d 100644 --- a/src/matoya.h +++ b/src/matoya.h @@ -77,8 +77,6 @@ typedef bool (*MTY_MenuItemCheckedFunc)(void *opaque); typedef intptr_t (*MTY_WMsgFunc)(MTY_App *app, MTY_Window window, void *hwnd, uint32_t msg, intptr_t wparam, uintptr_t lparam, bool *shouldReturn, void *opaque); -typedef int32_t (*MTY_WindowErrorFunc)(MTY_App *app, MTY_Window window, int32_t error, int32_t internal_error, void *opaque); - /// @brief Error codes indicating the current state of the platform. /// @details Warnings are positive, errors are negative, 0 (::MTY_ERROR_OK) means no error. typedef enum { @@ -1075,9 +1073,6 @@ MTY_WindowCreate(MTY_App *app, const char *title, const MTY_Frame *frame, MTY_Wi MTY_EXPORT void MTY_WindowDestroy(MTY_App *app, MTY_Window window); -MTY_EXPORT void -MTY_WindowSetErrorHandler(MTY_App *app, MTY_Window window, MTY_WindowErrorFunc func, void *opaque); - /// @brief Get a window's current client area width and height. /// @param app The MTY_App. /// @param window An MTY_Window. diff --git a/src/thread.c b/src/thread.c index d9db134e8..301f5ac82 100644 --- a/src/thread.c +++ b/src/thread.c @@ -16,7 +16,7 @@ MTY_Error MTY_ThreadGetError(MTY_Thread *ctx) { - ctx; // not used since errors are managed via tlocal state + // `ctx` is not used since errors are managed via tlocal state MTY_Error e = MTY_ERROR_OK; error_local_get_next_error(&e); diff --git a/src/unix/apple/macosx/gfx/metal-ctx.m b/src/unix/apple/macosx/gfx/metal-ctx.m index 7d959d801..ffe622dcd 100644 --- a/src/unix/apple/macosx/gfx/metal-ctx.m +++ b/src/unix/apple/macosx/gfx/metal-ctx.m @@ -172,13 +172,3 @@ bool mty_metal_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_metal_ctx_unlock(void) { } - -void mty_metal_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) -{ - gfx_ctx; func; opaque; -} - -int32_t mty_metal_ctx_get_error(struct gfx_ctx *gfx_ctx) -{ - return 0; -} diff --git a/src/unix/linux/android/gfx/gl-ctx.c b/src/unix/linux/android/gfx/gl-ctx.c index 86d745270..865494b4d 100644 --- a/src/unix/linux/android/gfx/gl-ctx.c +++ b/src/unix/linux/android/gfx/gl-ctx.c @@ -205,13 +205,3 @@ void mty_gl_ctx_unlock(void) { mty_gfx_unlock(); } - -void mty_gl_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) -{ - gfx_ctx; func; opaque; -} - -int32_t mty_gl_ctx_get_error(struct gfx_ctx *gfx_ctx) -{ - return 0; -} diff --git a/src/unix/linux/x11/gfx/gl-ctx.c b/src/unix/linux/x11/gfx/gl-ctx.c index f2b53a20b..e9cab3951 100644 --- a/src/unix/linux/x11/gfx/gl-ctx.c +++ b/src/unix/linux/x11/gfx/gl-ctx.c @@ -119,13 +119,3 @@ bool mty_gl_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_gl_ctx_unlock(void) { } - -void mty_gl_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) -{ - gfx_ctx; func; opaque; -} - -int32_t mty_gl_ctx_get_error(struct gfx_ctx *gfx_ctx) -{ - return 0; -} diff --git a/src/unix/web/gfx/gl-ctx.c b/src/unix/web/gfx/gl-ctx.c index ca8837bb8..c5ff2c023 100644 --- a/src/unix/web/gfx/gl-ctx.c +++ b/src/unix/web/gfx/gl-ctx.c @@ -86,13 +86,3 @@ bool mty_gl_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_gl_ctx_unlock(void) { } - -void mty_gl_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) -{ - gfx_ctx; func; opaque; -} - -int32_t mty_gl_ctx_get_error(struct gfx_ctx *gfx_ctx) -{ - return 0; -} diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index 276795728..3006dca7e 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -36,10 +36,6 @@ struct d3d11_ctx { IDXGISwapChain2 *swap_chain2; HANDLE waitable; UINT flags; - - gfx_error_handler_func error_handler; - void *error_handler_opaque; - int32_t last_error; }; static void d3d11_ctx_get_size(struct d3d11_ctx *ctx, uint32_t *width, uint32_t *height) @@ -219,8 +215,6 @@ struct gfx_ctx *mty_d3d11_ctx_create(void *native_window, bool vsync) d3d11_ctx_get_size(ctx, &ctx->width, &ctx->height); - mty_d3d11_ctx_set_error_handler((struct gfx_ctx *) ctx, mty_d3d11_error_handler_default, NULL); - if (!d3d11_ctx_init(ctx)) mty_d3d11_ctx_destroy((struct gfx_ctx **) &ctx); @@ -385,17 +379,3 @@ bool mty_d3d11_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_d3d11_ctx_unlock(void) { } - -void mty_d3d11_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) -{ - struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; - - ctx->error_handler = func; - ctx->error_handler_opaque = opaque; -} - -int32_t mty_d3d11_ctx_get_error(struct gfx_ctx *gfx_ctx) -{ - struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; - return ctx->last_error; -} diff --git a/src/windows/gfx/d3d11-ui.c b/src/windows/gfx/d3d11-ui.c index 90703cc5e..0d6b9100c 100644 --- a/src/windows/gfx/d3d11-ui.c +++ b/src/windows/gfx/d3d11-ui.c @@ -37,8 +37,6 @@ struct d3d11_ui { ID3D11RasterizerState *rs; ID3D11BlendState *bs; ID3D11DepthStencilState *dss; - - int32_t last_error; }; struct d3d11_ui_cb { @@ -478,9 +476,3 @@ void mty_d3d11_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } - -int32_t mty_d3d11_ui_get_error(struct gfx_ui *gfx_ui) -{ - struct d3d11_ui *ctx = (struct d3d11_ui *) gfx_ui; - return ctx->last_error; -} diff --git a/src/windows/gfx/d3d12-ctx.c b/src/windows/gfx/d3d12-ctx.c index 1507400cb..9d617e9e9 100644 --- a/src/windows/gfx/d3d12-ctx.c +++ b/src/windows/gfx/d3d12-ctx.c @@ -508,13 +508,3 @@ bool mty_d3d12_ctx_lock(struct gfx_ctx *gfx_ctx) void mty_d3d12_ctx_unlock(void) { } - -void mty_d3d12_ctx_set_error_handler(struct gfx_ctx *gfx_ctx, gfx_error_handler_func func, void *opaque) -{ - gfx_ctx; func; opaque; -} - -int32_t mty_d3d12_ctx_get_error(struct gfx_ctx *gfx_ctx) -{ - return 0; -} diff --git a/src/windows/gfx/d3d12-ui.c b/src/windows/gfx/d3d12-ui.c index c1a9a958b..36b1d16c8 100644 --- a/src/windows/gfx/d3d12-ui.c +++ b/src/windows/gfx/d3d12-ui.c @@ -571,8 +571,3 @@ void mty_d3d12_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } - -int32_t mty_d3d12_ui_get_error(struct gfx_ui *gfx_ui) -{ - return 0; -} From b4f141247f7d26081de51ce68be3ac5bba819b90 Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Wed, 1 May 2024 09:52:58 -0400 Subject: [PATCH 07/11] Total simplification....let matoya fix itself. --- GNUmakefile | 1 - makefile | 1 - src/app.c | 2 ++ src/error.c | 46 ----------------------------- src/error.h | 9 ------ src/matoya.h | 16 ---------- src/thread.c | 11 ------- src/unix/apple/gfx/metal-ui.m | 5 ---- src/windows/gfx/d3d11-ctx.c | 55 +++++++++++++++++++++++------------ src/windows/gfx/d3d11-error.h | 29 ------------------ src/windows/gfx/d3d11-ui.c | 17 +++++------ src/windows/threadw.c | 4 --- 12 files changed, 46 insertions(+), 150 deletions(-) delete mode 100644 src/error.c delete mode 100644 src/error.h delete mode 100644 src/windows/gfx/d3d11-error.h diff --git a/GNUmakefile b/GNUmakefile index bcc38d3f4..78a40ed11 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -24,7 +24,6 @@ OBJS = \ src/async.o \ src/crypto.o \ src/dtls.o \ - src/error.o \ src/file.o \ src/hash.o \ src/http.o \ diff --git a/makefile b/makefile index 92a1b0e79..cd4789d46 100644 --- a/makefile +++ b/makefile @@ -27,7 +27,6 @@ OBJS = \ src\async.obj \ src\crypto.obj \ src\dtls.obj \ - src\error.obj \ src\file.obj \ src\hash.obj \ src\http.obj \ diff --git a/src/app.c b/src/app.c index 6890e2fb1..88650ce4e 100644 --- a/src/app.c +++ b/src/app.c @@ -213,6 +213,8 @@ bool MTY_WindowSetUITexture(MTY_App *app, MTY_Window window, uint32_t id, const return false; MTY_Device *device = gfx_ctx_get_device(cmn); + if (!device) + return false; bool r = gfx_begin_ui(cmn, device); diff --git a/src/error.c b/src/error.c deleted file mode 100644 index c45be3e40..000000000 --- a/src/error.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "error.h" - -#include "tlocal.h" - -static TLOCAL MTY_Queue *Q = NULL; - -void error_local_init(void) -{ - error_local_clear(); - - Q = MTY_QueueCreate(10, sizeof(MTY_Error)); -} - -void error_local_clear(void) -{ - MTY_QueueDestroy(&Q); -} - - -bool error_local_get_next_error(MTY_Error *error) -{ - if (!Q) - return false; - - MTY_Error *buf = NULL; - - bool rc = MTY_QueueGetOutputBuffer(Q, 0, (void **) &buf, NULL); - if (rc) { - *error = *buf; - MTY_QueuePop(Q); - } - - return rc; -} - -void error_local_push_error(MTY_Error error) -{ - if (!Q) - return; - - MTY_Error *buf = MTY_QueueGetInputBuffer(Q); - if (buf) { - *buf = error; - MTY_QueuePush(Q, sizeof(MTY_Error)); - } -} diff --git a/src/error.h b/src/error.h deleted file mode 100644 index 787779beb..000000000 --- a/src/error.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "matoya.h" - -void error_local_init(void); -void error_local_clear(void); - -bool error_local_get_next_error(MTY_Error *error); -void error_local_push_error(MTY_Error error); diff --git a/src/matoya.h b/src/matoya.h index 1c522353d..bdebf9d27 100644 --- a/src/matoya.h +++ b/src/matoya.h @@ -77,17 +77,6 @@ typedef bool (*MTY_MenuItemCheckedFunc)(void *opaque); typedef intptr_t (*MTY_WMsgFunc)(MTY_App *app, MTY_Window window, void *hwnd, uint32_t msg, intptr_t wparam, uintptr_t lparam, bool *shouldReturn, void *opaque); -/// @brief Error codes indicating the current state of the platform. -/// @details Warnings are positive, errors are negative, 0 (::MTY_ERROR_OK) means no error. -typedef enum { - MTY_ERROR_OK = 0, ///< No errors. - MTY_ERROR_GFX_INVISIBLE_CONTENT = 11, ///< Warning from the gfx driver that rendered content is hidden (for example, when app is in the UAC prompt on Windows) - MTY_ERROR_GFX_REVISIBLE_CONTENT = 12, ///< Notice from the gfx driver that rendered content that was hidden is now visible - MTY_ERROR_GFX_ERROR = -11, ///< Generic gfx error - MTY_ERROR_GFX_DEVICE_REMOVED = -21, ///< Generally indicates that the display was unplugged or disabled abruptly - MTY_ERROR_MAKE_32 = INT32_MAX, -} MTY_Error; - /// @brief 3D graphics APIs. typedef enum { MTY_GFX_NONE = 0, ///< No 3D graphics API. @@ -2628,11 +2617,6 @@ MTY_ThreadDetach(MTY_ThreadFunc func, void *opaque); MTY_EXPORT int64_t MTY_ThreadGetID(MTY_Thread *ctx); -/// @brief Get the next error code for the given thread. -/// @param ctx An MTY_Thread. -MTY_EXPORT MTY_Error -MTY_ThreadGetError(MTY_Thread *ctx); - /// @brief Create an MTY_Mutex for synchronization. /// @details A mutex can be locked by only one thread at a time. Other threads trying /// to take the same mutex will block until it becomes unlocked. diff --git a/src/thread.c b/src/thread.c index 301f5ac82..58689d277 100644 --- a/src/thread.c +++ b/src/thread.c @@ -10,18 +10,7 @@ #include "rwlock.h" #include "tlocal.h" -#include "error.h" -// Thread - -MTY_Error MTY_ThreadGetError(MTY_Thread *ctx) -{ - // `ctx` is not used since errors are managed via tlocal state - - MTY_Error e = MTY_ERROR_OK; - error_local_get_next_error(&e); - return e; -} // RWLock diff --git a/src/unix/apple/gfx/metal-ui.m b/src/unix/apple/gfx/metal-ui.m index 4143f2cb3..6845cd524 100644 --- a/src/unix/apple/gfx/metal-ui.m +++ b/src/unix/apple/gfx/metal-ui.m @@ -236,8 +236,3 @@ void mty_metal_ui_destroy(struct gfx_ui **gfx_ui, MTY_Device *device) MTY_Free(ctx); *gfx_ui = NULL; } - -int32_t mty_metal_ui_get_error(struct gfx_ui *gfx_ui) -{ - return 0; -} diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index 3006dca7e..8160d885f 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -12,8 +12,6 @@ GFX_CTX_PROTOTYPES(_d3d11_) #include "gfx/sync.h" #include "dxgi-sync.h" -#include "d3d11-error.h" - #define DXGI_FATAL(e) ( \ (e) == DXGI_ERROR_DEVICE_REMOVED || \ (e) == DXGI_ERROR_DRIVER_INTERNAL_ERROR || \ @@ -24,6 +22,7 @@ GFX_CTX_PROTOTYPES(_d3d11_) #define D3D11_CTX_WAIT 2000 struct d3d11_ctx { + bool ready; HWND hwnd; struct sync sync; struct dxgi_sync *dxgi_sync; @@ -49,6 +48,8 @@ static void d3d11_ctx_get_size(struct d3d11_ctx *ctx, uint32_t *width, uint32_t static void d3d11_ctx_free(struct d3d11_ctx *ctx) { + ctx->ready = false; + if (ctx->back_buffer) ID3D11RenderTargetView_Release(ctx->back_buffer); @@ -58,8 +59,11 @@ static void d3d11_ctx_free(struct d3d11_ctx *ctx) if (ctx->swap_chain2) IDXGISwapChain2_Release(ctx->swap_chain2); - if (ctx->context) + if (ctx->context) { + ID3D11DeviceContext_Flush(ctx->context); + ID3D11DeviceContext_ClearState(ctx->context); ID3D11DeviceContext_Release(ctx->context); + } if (ctx->device) ID3D11Device_Release(ctx->device); @@ -190,12 +194,18 @@ static bool d3d11_ctx_init(struct d3d11_ctx *ctx) if (device2) IDXGIDevice2_Release(device2); - if (e != S_OK) { - d3d11_push_local_error(e); + ctx->ready = e == S_OK; + + if (!ctx->ready) d3d11_ctx_free(ctx); - } - return e == S_OK; + return ctx->ready; +} + +static bool d3d11_ctx_reinit(struct d3d11_ctx *ctx) +{ + d3d11_ctx_free(ctx); + return d3d11_ctx_init(ctx); } int32_t mty_d3d11_error_handler_default(int32_t e1, int32_t e2, void *opaque) @@ -247,6 +257,9 @@ MTY_Device *mty_d3d11_ctx_get_device(struct gfx_ctx *gfx_ctx) { struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; + if (!ctx->ready) + d3d11_ctx_reinit(ctx); + return (MTY_Device *) ctx->device; } @@ -254,11 +267,17 @@ MTY_Context *mty_d3d11_ctx_get_context(struct gfx_ctx *gfx_ctx) { struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; + if (!ctx->ready) + d3d11_ctx_reinit(ctx); + return (MTY_Context *) ctx->context; } static void d3d11_ctx_refresh(struct d3d11_ctx *ctx) { + if (!ctx->ready && !d3d11_ctx_reinit(ctx)) + return; + uint32_t width = ctx->width; uint32_t height = ctx->height; @@ -275,10 +294,7 @@ static void d3d11_ctx_refresh(struct d3d11_ctx *ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_ResizeBuffers' failed with HRESULT 0x%X", e); - d3d11_push_local_error(e); - - d3d11_ctx_free(ctx); - d3d11_ctx_init(ctx); + ctx->ready = false; } } } @@ -287,6 +303,9 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) { struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; + if (!ctx->ready && !d3d11_ctx_reinit(ctx)) + return NULL; + HRESULT e = S_OK; ID3D11Resource *resource = NULL; @@ -314,9 +333,7 @@ MTY_Surface *mty_d3d11_ctx_get_surface(struct gfx_ctx *gfx_ctx) if (resource) ID3D11Resource_Release(resource); - if (e != S_OK) - d3d11_push_local_error(e); - + ctx->ready = e == S_OK; return (MTY_Surface *) ctx->back_buffer; } @@ -335,6 +352,9 @@ void mty_d3d11_ctx_present(struct gfx_ctx *gfx_ctx) { struct d3d11_ctx *ctx = (struct d3d11_ctx *) gfx_ctx; + if (!ctx->ready && !d3d11_ctx_reinit(ctx)) + return; + if (ctx->back_buffer) { int64_t interval = sync_next_interval(&ctx->sync); UINT flags = interval > 0 ? 0 : DXGI_PRESENT_ALLOW_TEARING; @@ -356,16 +376,13 @@ void mty_d3d11_ctx_present(struct gfx_ctx *gfx_ctx) if (DXGI_FATAL(e)) { MTY_Log("'IDXGISwapChain2_Present' failed with HRESULT 0x%X", e); - d3d11_push_local_error(e); - - d3d11_ctx_free(ctx); - d3d11_ctx_init(ctx); + ctx->ready = false; } else { DWORD we = WaitForSingleObjectEx(ctx->waitable, D3D11_CTX_WAIT, TRUE); if (we != WAIT_OBJECT_0) { MTY_Log("'WaitForSingleObjectEx' failed with error 0x%X", we); - d3d11_push_local_error(e); + ctx->ready = false; } } } diff --git a/src/windows/gfx/d3d11-error.h b/src/windows/gfx/d3d11-error.h deleted file mode 100644 index 4405aaeae..000000000 --- a/src/windows/gfx/d3d11-error.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "matoya.h" - -#include "error.h" - -static MTY_Error d3d11_map_error(int32_t e) -{ - switch (e) { - case DXGI_ERROR_DEVICE_REMOVED: - case DXGI_ERROR_DRIVER_INTERNAL_ERROR: - return MTY_ERROR_GFX_DEVICE_REMOVED; - - case DXGI_ERROR_DEVICE_HUNG: - case DXGI_ERROR_DEVICE_RESET: - return MTY_ERROR_GFX_ERROR; - - case DXGI_STATUS_OCCLUDED: - return MTY_ERROR_GFX_INVISIBLE_CONTENT; - - case DXGI_STATUS_UNOCCLUDED: - return MTY_ERROR_GFX_REVISIBLE_CONTENT; - - default: - return MTY_ERROR_OK; - } -} - -#define d3d11_push_local_error(e) error_local_push_error(d3d11_map_error(e)) diff --git a/src/windows/gfx/d3d11-ui.c b/src/windows/gfx/d3d11-ui.c index 0d6b9100c..b641a6c40 100644 --- a/src/windows/gfx/d3d11-ui.c +++ b/src/windows/gfx/d3d11-ui.c @@ -17,8 +17,6 @@ static static #include "shaders/vsui.h" -#include "d3d11-error.h" - struct d3d11_ui_buffer { ID3D11Buffer *b; ID3D11Resource *res; @@ -26,6 +24,7 @@ struct d3d11_ui_buffer { }; struct d3d11_ui { + bool ready; struct d3d11_ui_buffer vb; struct d3d11_ui_buffer ib; ID3D11VertexShader *vs; @@ -151,11 +150,10 @@ struct gfx_ui *mty_d3d11_ui_create(MTY_Device *device) except: - if (e != S_OK) { - d3d11_push_local_error(e); - mty_d3d11_ui_destroy((struct gfx_ui **) &ctx, device); - } + ctx->ready = e == S_OK; + if (!ctx->ready) + mty_d3d11_ui_destroy((struct gfx_ui **) &ctx, device); return (struct gfx_ui *) ctx; } @@ -201,6 +199,9 @@ bool mty_d3d11_ui_render(struct gfx_ui *gfx_ui, MTY_Device *device, MTY_Context const MTY_DrawData *dd, MTY_Hash *cache, MTY_Surface *dest) { struct d3d11_ui *ctx = (struct d3d11_ui *) gfx_ui; + if (!ctx->ready) + return false; + ID3D11Device *_device = (ID3D11Device *) device; ID3D11DeviceContext *_context = (ID3D11DeviceContext *) context; ID3D11RenderTargetView *_dest = (ID3D11RenderTargetView *) dest; @@ -349,8 +350,7 @@ bool mty_d3d11_ui_render(struct gfx_ui *gfx_ui, MTY_Device *device, MTY_Context except: - if (e != S_OK) - d3d11_push_local_error(e); + ctx->ready = e == S_OK; return result; } @@ -408,7 +408,6 @@ void *mty_d3d11_ui_create_texture(struct gfx_ui *gfx_ui, MTY_Device *device, con ID3D11Texture2D_Release(tex); if (e != S_OK && srv) { - d3d11_push_local_error(e); ID3D11ShaderResourceView_Release(srv); srv = NULL; } diff --git a/src/windows/threadw.c b/src/windows/threadw.c index d69b3e9ae..2f8c894a0 100644 --- a/src/windows/threadw.c +++ b/src/windows/threadw.c @@ -8,7 +8,6 @@ #include -#include "error.h" // Thread @@ -52,7 +51,6 @@ static MTY_Thread *thread_create(MTY_ThreadFunc func, void *opaque, bool detach) } else { ctx->thread = thread; - error_local_init(); } return ctx; @@ -71,8 +69,6 @@ void *MTY_ThreadDestroy(MTY_Thread **thread) MTY_Thread *ctx = *thread; if (ctx->thread) { - error_local_clear(); - if (WaitForSingleObject(ctx->thread, INFINITE) == WAIT_FAILED) MTY_LogFatal("'WaitForSingleObject' failed with error 0x%X", GetLastError()); From d2b88a944e700bbac9d1b0ecfe8025de555d04f4 Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Mon, 6 May 2024 08:53:40 -0400 Subject: [PATCH 08/11] Added logs so its clear when d3d11 ctx is reiniting. --- src/windows/gfx/d3d11-ctx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index 8160d885f..3260c0343 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -204,8 +204,13 @@ static bool d3d11_ctx_init(struct d3d11_ctx *ctx) static bool d3d11_ctx_reinit(struct d3d11_ctx *ctx) { + MTY_Log("TEMP: Reinitializing d3d11_ctx..."); d3d11_ctx_free(ctx); - return d3d11_ctx_init(ctx); + bool r = d3d11_ctx_init(ctx); + if (r) + MTY_Log("d3d11_ctx reinit ok."); + else + MTY_Log("d3d11_ctx reinit FAILED!"); } int32_t mty_d3d11_error_handler_default(int32_t e1, int32_t e2, void *opaque) From 1af162e6d55165ea3ddc3ec86653dcca8edb0cfe Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Mon, 6 May 2024 09:55:03 -0400 Subject: [PATCH 09/11] Upon d3d11 device and ctx reinit due to fatal errors, ensure that the matoya client is informed that textures need to be resubmitted. --- src/app.c | 7 ++++++- src/app.h | 2 ++ src/windows/appw.c | 10 +++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/app.c b/src/app.c index 88650ce4e..c24060ad5 100644 --- a/src/app.c +++ b/src/app.c @@ -73,6 +73,7 @@ static void gfx_set_device(struct window_common *cmn, MTY_Device *device) GFX_UI_API[cmn->api].destroy(&cmn->gfx_ui, cmn->device); cmn->device = device; + cmn->device_changed = true; } } @@ -96,8 +97,12 @@ static bool gfx_begin_ui(struct window_common *cmn, MTY_Device *device) if (!cmn->gfx_ui) cmn->gfx_ui = GFX_UI_API[cmn->api].create(device); - if (!cmn->ui_textures) + if (!cmn->gfx_ui) { + MTY_HashDestroy(&cmn->ui_textures, NULL); + + } else if (!cmn->ui_textures) { cmn->ui_textures = MTY_HashCreate(0); + } return cmn->gfx_ui != NULL; } diff --git a/src/app.h b/src/app.h index c2ea807f1..160c0d01e 100644 --- a/src/app.h +++ b/src/app.h @@ -22,6 +22,8 @@ struct window_common { struct gfx *gfx[APP_GFX_LAYERS]; struct gfx_ui *gfx_ui; struct gfx_ctx *gfx_ctx; + + bool device_changed; }; // App diff --git a/src/windows/appw.c b/src/windows/appw.c index 0cfe3b30d..c20e14a6e 100644 --- a/src/windows/appw.c +++ b/src/windows/appw.c @@ -2062,7 +2062,15 @@ void MTY_WindowWarpCursor(MTY_App *app, MTY_Window window, uint32_t x, uint32_t MTY_ContextState MTY_WindowGetContextState(MTY_App *app, MTY_Window window) { - return MTY_CONTEXT_STATE_NORMAL; + MTY_ContextState state = MTY_CONTEXT_STATE_NORMAL; + + struct window_common *cmn = mty_window_get_common(app, window); + if (cmn && cmn->api != MTY_GFX_NONE && cmn->device_changed) { + state = MTY_CONTEXT_STATE_NEW; + cmn->device_changed = false; + } + + return state; } void *MTY_WindowGetNative(MTY_App *app, MTY_Window window) From c7c3d663e6872d30279a03c9b7d5f0ce938a61da Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Mon, 6 May 2024 12:18:11 -0400 Subject: [PATCH 10/11] TEST: logs to help figure out what's going on --- src/app.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app.c b/src/app.c index c24060ad5..1251c0798 100644 --- a/src/app.c +++ b/src/app.c @@ -223,6 +223,8 @@ bool MTY_WindowSetUITexture(MTY_App *app, MTY_Window window, uint32_t id, const bool r = gfx_begin_ui(cmn, device); + MTY_Log("TEST: Trying to set UI texture id %u for window %u where texture dimensions are %ux%u (%s)", id, window, width, height, r ? "ui ok" : "ui FAILED"); + if (r) { void *texture = MTY_HashPopInt(cmn->ui_textures, id); GFX_UI_API[cmn->api].destroy_texture(cmn->gfx_ui, &texture, device); From 3066a963aa17d3f7ed00755fbbbe6f7d571b87aa Mon Sep 17 00:00:00 2001 From: Daniel Vijayakumar Date: Tue, 7 May 2024 09:02:44 -0400 Subject: [PATCH 11/11] MTY_WindowSetUITexture no longer indiscriminately deletes the existing texture for the id. It only does so if the new texture successfully was created. --- src/app.c | 22 ++++++++++++++-------- src/windows/gfx/d3d11-ctx.c | 4 +++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/app.c b/src/app.c index 1251c0798..3e5fa00d9 100644 --- a/src/app.c +++ b/src/app.c @@ -223,17 +223,23 @@ bool MTY_WindowSetUITexture(MTY_App *app, MTY_Window window, uint32_t id, const bool r = gfx_begin_ui(cmn, device); - MTY_Log("TEST: Trying to set UI texture id %u for window %u where texture dimensions are %ux%u (%s)", id, window, width, height, r ? "ui ok" : "ui FAILED"); - if (r) { - void *texture = MTY_HashPopInt(cmn->ui_textures, id); - GFX_UI_API[cmn->api].destroy_texture(cmn->gfx_ui, &texture, device); + void *texture = MTY_HashGetInt(cmn->ui_textures, id); + + if (rgba) { + void *texture_new = GFX_UI_API[cmn->api].create_texture(cmn->gfx_ui, device, rgba, width, height); + + if (texture_new) { + GFX_UI_API[cmn->api].destroy_texture(cmn->gfx_ui, &texture, device); - if (rgba) - texture = GFX_UI_API[cmn->api].create_texture(cmn->gfx_ui, device, rgba, width, height); + texture = texture_new; + MTY_HashSetInt(cmn->ui_textures, id, texture_new); + } - if (texture) - MTY_HashSetInt(cmn->ui_textures, id, texture); + } else { + GFX_UI_API[cmn->api].destroy_texture(cmn->gfx_ui, &texture, device); + MTY_HashPopInt(cmn->ui_textures, id); + } r = texture != NULL; } diff --git a/src/windows/gfx/d3d11-ctx.c b/src/windows/gfx/d3d11-ctx.c index 3260c0343..d381cd00c 100644 --- a/src/windows/gfx/d3d11-ctx.c +++ b/src/windows/gfx/d3d11-ctx.c @@ -204,13 +204,15 @@ static bool d3d11_ctx_init(struct d3d11_ctx *ctx) static bool d3d11_ctx_reinit(struct d3d11_ctx *ctx) { - MTY_Log("TEMP: Reinitializing d3d11_ctx..."); + MTY_Log("Reinitializing d3d11_ctx..."); d3d11_ctx_free(ctx); bool r = d3d11_ctx_init(ctx); if (r) MTY_Log("d3d11_ctx reinit ok."); else MTY_Log("d3d11_ctx reinit FAILED!"); + + return r; } int32_t mty_d3d11_error_handler_default(int32_t e1, int32_t e2, void *opaque)