libobs-d3d11: Allow multiple display captures of same monitor

This commit fixes a bug that occurs on Windows 8+ when two or more
"Display Capture" sources are active that are configured to capture the
same monitor.  Only one display capture would show, while all subsequent
display captures would display nothing.

Closes jp9000/obs-studio#1142
master
Wouter 2018-01-09 22:25:29 +01:00 committed by jp9000
parent ed917657eb
commit 65f81105f5
3 changed files with 34 additions and 2 deletions

View File

@ -16,6 +16,7 @@
******************************************************************************/
#include "d3d11-subsystem.hpp"
#include <map>
static inline bool get_monitor(gs_device_t *device, int monitor_idx,
IDXGIOutput **dxgiOutput)
@ -55,7 +56,9 @@ void gs_duplicator::Start()
gs_duplicator::gs_duplicator(gs_device_t *device_, int monitor_idx)
: gs_obj (device_, gs_type::gs_duplicator),
texture (nullptr),
idx (monitor_idx)
idx (monitor_idx),
refs (1),
updated (false)
{
Start();
}
@ -116,13 +119,30 @@ EXPORT bool device_get_duplicator_monitor_info(gs_device_t *device,
return true;
}
static std::map<int, gs_duplicator*> instances;
void reset_duplicators(void)
{
for (auto &pair : instances) {
pair.second->updated = false;
}
}
EXPORT gs_duplicator_t *device_duplicator_create(gs_device_t *device,
int monitor_idx)
{
gs_duplicator *duplicator = nullptr;
auto it = instances.find(monitor_idx);
if (it != instances.end()) {
duplicator = it->second;
duplicator->refs++;
return duplicator;
}
try {
duplicator = new gs_duplicator(device, monitor_idx);
instances[monitor_idx] = duplicator;
} catch (const char *error) {
blog(LOG_DEBUG, "device_duplicator_create: %s",
@ -140,7 +160,10 @@ EXPORT gs_duplicator_t *device_duplicator_create(gs_device_t *device,
EXPORT void gs_duplicator_destroy(gs_duplicator_t *duplicator)
{
delete duplicator;
if (--duplicator->refs == 0) {
instances.erase(duplicator->idx);
delete duplicator;
}
}
static inline void copy_texture(gs_duplicator_t *d, ID3D11Texture2D *tex)
@ -174,6 +197,9 @@ EXPORT bool gs_duplicator_update_frame(gs_duplicator_t *d)
if (!d->duplicator) {
return false;
}
if (d->updated) {
return true;
}
hr = d->duplicator->AcquireNextFrame(0, &info, res.Assign());
if (hr == DXGI_ERROR_ACCESS_LOST) {
@ -199,6 +225,7 @@ EXPORT bool gs_duplicator_update_frame(gs_duplicator_t *d)
copy_texture(d, tex);
d->duplicator->ReleaseFrame();
d->updated = true;
return true;
}

View File

@ -1456,9 +1456,12 @@ void device_present(gs_device_t *device)
}
}
extern "C" void reset_duplicators(void);
void device_flush(gs_device_t *device)
{
device->context->Flush();
reset_duplicators();
}
void device_set_cull_mode(gs_device_t *device, enum gs_cull_mode mode)

View File

@ -561,6 +561,8 @@ struct gs_duplicator : gs_obj {
ComPtr<IDXGIOutputDuplication> duplicator;
gs_texture_2d *texture;
int idx;
long refs;
bool updated;
void Start();