libobs-winrt: Fix WGC minimize handling
Illegal CopySubresourceRegion parameters were sometimes computed when minimizing and restoring WGC window captures, leading to device loss. Add robust safeties to ensure that doesn't happen.master
parent
63cbcc5dcc
commit
a4c9554739
|
@ -62,11 +62,14 @@ static winrt::com_ptr<T> GetDXGIInterfaceFromObject(
|
||||||
static bool get_client_box(HWND window, uint32_t width, uint32_t height,
|
static bool get_client_box(HWND window, uint32_t width, uint32_t height,
|
||||||
D3D11_BOX *client_box)
|
D3D11_BOX *client_box)
|
||||||
{
|
{
|
||||||
RECT client_rect, window_rect{};
|
RECT client_rect{}, window_rect{};
|
||||||
POINT upper_left{};
|
POINT upper_left{};
|
||||||
|
|
||||||
const bool client_box_available =
|
/* check iconic (minimized) twice, ABA is very unlikely */
|
||||||
GetClientRect(window, &client_rect) &&
|
bool client_box_available =
|
||||||
|
!IsIconic(window) && GetClientRect(window, &client_rect) &&
|
||||||
|
!IsIconic(window) && (client_rect.right > 0) &&
|
||||||
|
(client_rect.bottom > 0) &&
|
||||||
(DwmGetWindowAttribute(window, DWMWA_EXTENDED_FRAME_BOUNDS,
|
(DwmGetWindowAttribute(window, DWMWA_EXTENDED_FRAME_BOUNDS,
|
||||||
&window_rect,
|
&window_rect,
|
||||||
sizeof(window_rect)) == S_OK) &&
|
sizeof(window_rect)) == S_OK) &&
|
||||||
|
@ -100,6 +103,9 @@ static bool get_client_box(HWND window, uint32_t width, uint32_t height,
|
||||||
|
|
||||||
client_box->front = 0;
|
client_box->front = 0;
|
||||||
client_box->back = 1;
|
client_box->back = 1;
|
||||||
|
|
||||||
|
client_box_available = (client_box->right <= width) &&
|
||||||
|
(client_box->bottom <= height);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client_box_available;
|
return client_box_available;
|
||||||
|
@ -131,7 +137,6 @@ struct winrt_capture {
|
||||||
uint32_t texture_width;
|
uint32_t texture_width;
|
||||||
uint32_t texture_height;
|
uint32_t texture_height;
|
||||||
D3D11_BOX client_box;
|
D3D11_BOX client_box;
|
||||||
bool client_box_available;
|
|
||||||
|
|
||||||
bool thread_changed;
|
bool thread_changed;
|
||||||
bool active;
|
bool active;
|
||||||
|
@ -189,9 +194,8 @@ struct winrt_capture {
|
||||||
DestroyIcon(icon);
|
DestroyIcon(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void on_closed(
|
||||||
on_closed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const
|
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
||||||
&sender,
|
|
||||||
winrt::Windows::Foundation::IInspectable const &)
|
winrt::Windows::Foundation::IInspectable const &)
|
||||||
{
|
{
|
||||||
active = FALSE;
|
active = FALSE;
|
||||||
|
@ -216,23 +220,23 @@ struct winrt_capture {
|
||||||
D3D11_TEXTURE2D_DESC desc;
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
frame_surface->GetDesc(&desc);
|
frame_surface->GetDesc(&desc);
|
||||||
|
|
||||||
client_box_available = false;
|
if (!client_area || get_client_box(window, desc.Width,
|
||||||
|
desc.Height, &client_box)) {
|
||||||
if (client_area) {
|
if (client_area) {
|
||||||
client_box_available = get_client_box(
|
texture_width =
|
||||||
window, desc.Width, desc.Height, &client_box);
|
client_box.right - client_box.left;
|
||||||
}
|
texture_height =
|
||||||
|
client_box.bottom - client_box.top;
|
||||||
if (client_box_available) {
|
|
||||||
texture_width = client_box.right - client_box.left;
|
|
||||||
texture_height = client_box.bottom - client_box.top;
|
|
||||||
} else {
|
} else {
|
||||||
texture_width = desc.Width;
|
texture_width = desc.Width;
|
||||||
texture_height = desc.Height;
|
texture_height = desc.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture) {
|
if (texture) {
|
||||||
if (texture_width != gs_texture_get_width(texture) ||
|
if (texture_width !=
|
||||||
texture_height != gs_texture_get_height(texture)) {
|
gs_texture_get_width(texture) ||
|
||||||
|
texture_height !=
|
||||||
|
gs_texture_get_height(texture)) {
|
||||||
gs_texture_destroy(texture);
|
gs_texture_destroy(texture);
|
||||||
texture = nullptr;
|
texture = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -243,15 +247,17 @@ struct winrt_capture {
|
||||||
texture_height);
|
texture_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_box_available) {
|
if (client_area) {
|
||||||
context->CopySubresourceRegion(
|
context->CopySubresourceRegion(
|
||||||
(ID3D11Texture2D *)gs_texture_get_obj(texture),
|
(ID3D11Texture2D *)gs_texture_get_obj(
|
||||||
|
texture),
|
||||||
0, 0, 0, 0, frame_surface.get(), 0,
|
0, 0, 0, 0, frame_surface.get(), 0,
|
||||||
&client_box);
|
&client_box);
|
||||||
} else {
|
} else {
|
||||||
/* if they gave an SRV, we could avoid this copy */
|
/* if they gave an SRV, we could avoid this copy */
|
||||||
context->CopyResource(
|
context->CopyResource(
|
||||||
(ID3D11Texture2D *)gs_texture_get_obj(texture),
|
(ID3D11Texture2D *)gs_texture_get_obj(
|
||||||
|
texture),
|
||||||
frame_surface.get());
|
frame_surface.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +266,7 @@ struct winrt_capture {
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_written = true;
|
texture_written = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame_content_size.Width != last_size.Width ||
|
if (frame_content_size.Width != last_size.Width ||
|
||||||
frame_content_size.Height != last_size.Height) {
|
frame_content_size.Height != last_size.Height) {
|
||||||
|
|
Loading…
Reference in New Issue