libobs: Support device loss registration

Complex external systems using the D3D11 device may need to perform
their own device loss handling, the upcoming Windows Graphics Capture
support for example.
master
jpark37 2019-11-27 16:35:27 -08:00 committed by jp9000
parent 82797eb367
commit f27f858ab3
7 changed files with 66 additions and 0 deletions

View File

@ -348,6 +348,9 @@ try {
/* ----------------------------------------------------------------- */
for (gs_device_loss &callback : loss_callbacks)
callback.device_loss_release(callback.data);
gs_obj *obj = first_obj;
while (obj) {
@ -404,6 +407,7 @@ try {
state.Release();
context->ClearState();
context->Flush();
context.Release();
device.Release();
@ -506,6 +510,9 @@ try {
for (auto &state : blendStates)
state.Rebuild(dev);
for (gs_device_loss &callback : loss_callbacks)
callback.device_loss_rebuild(device.Get(), callback.data);
} catch (const char *error) {
bcrash("Failed to recreate D3D11: %s", error);

View File

@ -2798,3 +2798,22 @@ device_stagesurface_create_nv12(gs_device_t *device, uint32_t width,
return surf;
}
extern "C" EXPORT void
device_register_loss_callbacks(gs_device_t *device,
const gs_device_loss *callbacks)
{
device->loss_callbacks.emplace_back(*callbacks);
}
extern "C" EXPORT void device_unregister_loss_callbacks(gs_device_t *device,
void *data)
{
for (auto iter = device->loss_callbacks.begin();
iter != device->loss_callbacks.end(); ++iter) {
if (iter->data == data) {
device->loss_callbacks.erase(iter);
break;
}
}
}

View File

@ -946,6 +946,7 @@ struct gs_device {
matrix4 curViewMatrix;
matrix4 curViewProjMatrix;
vector<gs_device_loss> loss_callbacks;
gs_obj *first_obj = nullptr;
void InitCompiler();

View File

@ -214,6 +214,8 @@ bool load_graphics_imports(struct gs_exports *exports, void *module,
GRAPHICS_IMPORT_OPTIONAL(device_texture_release_sync);
GRAPHICS_IMPORT_OPTIONAL(device_texture_create_nv12);
GRAPHICS_IMPORT_OPTIONAL(device_stagesurface_create_nv12);
GRAPHICS_IMPORT_OPTIONAL(device_register_loss_callbacks);
GRAPHICS_IMPORT_OPTIONAL(device_unregister_loss_callbacks);
#endif
return success;

View File

@ -311,6 +311,10 @@ struct gs_exports {
gs_stagesurf_t *(*device_stagesurface_create_nv12)(gs_device_t *device,
uint32_t width,
uint32_t height);
void (*device_register_loss_callbacks)(
gs_device_t *device, const struct gs_device_loss *callbacks);
void (*device_unregister_loss_callbacks)(gs_device_t *device,
void *data);
#endif
};

View File

@ -2959,4 +2959,28 @@ gs_stagesurf_t *gs_stagesurface_create_nv12(uint32_t width, uint32_t height)
return NULL;
}
void gs_register_loss_callbacks(const struct gs_device_loss *callbacks)
{
graphics_t *graphics = thread_graphics;
if (!gs_valid("gs_register_loss_callbacks"))
return;
if (graphics->exports.device_register_loss_callbacks)
graphics->exports.device_register_loss_callbacks(
graphics->device, callbacks);
}
void gs_unregister_loss_callbacks(void *data)
{
graphics_t *graphics = thread_graphics;
if (!gs_valid("gs_unregister_loss_callbacks"))
return;
if (graphics->exports.device_unregister_loss_callbacks)
graphics->exports.device_unregister_loss_callbacks(
graphics->device, data);
}
#endif

View File

@ -169,6 +169,12 @@ enum gs_texture_type {
GS_TEXTURE_CUBE,
};
struct gs_device_loss {
void (*device_loss_release)(void *data);
void (*device_loss_rebuild)(void *device, void *data);
void *data;
};
struct gs_monitor_info {
int rotation_degrees;
long x;
@ -883,6 +889,9 @@ EXPORT bool gs_texture_create_nv12(gs_texture_t **tex_y, gs_texture_t **tex_uv,
EXPORT gs_stagesurf_t *gs_stagesurface_create_nv12(uint32_t width,
uint32_t height);
EXPORT void gs_register_loss_callbacks(const struct gs_device_loss *callbacks);
EXPORT void gs_unregister_loss_callbacks(void *data);
#endif
/* inline functions used by modules */