Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/platform/windows/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class duplication_t {
class display_base_t : public display_t {
public:
int init(int framerate, const std::string &display_name);
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override;

std::chrono::nanoseconds delay;

Expand Down Expand Up @@ -147,15 +148,14 @@ class display_base_t : public display_t {

const char *dxgi_format_to_string(DXGI_FORMAT format);

virtual int complete_img(img_t *img, bool dummy) = 0;
virtual std::vector<DXGI_FORMAT> get_supported_sdr_capture_formats() = 0;
virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) = 0;
virtual int complete_img(img_t *img, bool dummy) = 0;
virtual std::vector<DXGI_FORMAT> get_supported_sdr_capture_formats() = 0;
};

class display_ram_t : public display_base_t {
public:
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override;
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible);

virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override;

std::shared_ptr<img_t> alloc_img() override;
int dummy_img(img_t *img) override;
Expand All @@ -171,8 +171,7 @@ class display_ram_t : public display_base_t {

class display_vram_t : public display_base_t, public std::enable_shared_from_this<display_vram_t> {
public:
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override;
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible);
virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override;

std::shared_ptr<img_t> alloc_img() override;
int dummy_img(img_t *img_base) override;
Expand Down
57 changes: 57 additions & 0 deletions src/platform/windows/display_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,63 @@ duplication_t::~duplication_t() {
release_frame();
}

capture_e display_base_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) {
auto next_frame = std::chrono::steady_clock::now();

// Use CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if supported (Windows 10 1809+)
HANDLE timer = CreateWaitableTimerEx(nullptr, nullptr, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
if(!timer) {
timer = CreateWaitableTimerEx(nullptr, nullptr, 0, TIMER_ALL_ACCESS);
if(!timer) {
auto winerr = GetLastError();
BOOST_LOG(error) << "Failed to create timer: "sv << winerr;
return capture_e::error;
}
}

auto close_timer = util::fail_guard([timer]() {
CloseHandle(timer);
});

while(img) {
auto wait_time_us = std::chrono::duration_cast<std::chrono::microseconds>(next_frame - std::chrono::steady_clock::now()).count();

// If the wait time is between 1 us and 1 second, wait the specified time
// and offset the next frame time from the exact current frame time target.
if(wait_time_us > 0 && wait_time_us < 1000000) {
LARGE_INTEGER due_time { .QuadPart = -10LL * wait_time_us };
SetWaitableTimer(timer, &due_time, 0, nullptr, nullptr, false);
WaitForSingleObject(timer, INFINITE);
next_frame += delay;
}
else {
// If the wait time is negative (meaning the frame is past due) or the
// computed wait time is beyond a second (meaning possible clock issues),
// just capture the frame now and resynchronize the frame interval with
// the current time.
next_frame = std::chrono::steady_clock::now() + delay;
}

auto status = snapshot(img.get(), 1000ms, *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
img = snapshot_cb(img, false);
break;
case platf::capture_e::ok:
img = snapshot_cb(img, true);
break;
default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int)status << ']';
return status;
}
}

return capture_e::ok;
}

int display_base_t::init(int framerate, const std::string &display_name) {
std::once_flag windows_cpp_once_flag;

Expand Down
31 changes: 0 additions & 31 deletions src/platform/windows/display_ram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,37 +165,6 @@ void blend_cursor(const cursor_t &cursor, img_t &img) {
}
}

capture_e display_ram_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) {
auto next_frame = std::chrono::steady_clock::now();

while(img) {
auto now = std::chrono::steady_clock::now();
while(next_frame > now) {
now = std::chrono::steady_clock::now();
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
img = snapshot_cb(img, false);
std::this_thread::sleep_for(1ms);
break;
case platf::capture_e::ok:
img = snapshot_cb(img, true);
break;
default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int)status << ']';
return status;
}
}

return capture_e::ok;
}

capture_e display_ram_t::snapshot(::platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) {
auto img = (img_t *)img_base;

Expand Down
31 changes: 0 additions & 31 deletions src/platform/windows/display_vram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,37 +698,6 @@ class hwdevice_t : public platf::hwdevice_t {
device_ctx_t device_ctx;
};

capture_e display_vram_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) {
auto next_frame = std::chrono::steady_clock::now();

while(img) {
auto now = std::chrono::steady_clock::now();
while(next_frame > now) {
now = std::chrono::steady_clock::now();
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
img = snapshot_cb(img, false);
std::this_thread::sleep_for(1ms);
break;
case platf::capture_e::ok:
img = snapshot_cb(img, true);
break;
default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int)status << ']';
return status;
}
}

return capture_e::ok;
}

bool set_cursor_texture(device_t::pointer device, gpu_cursor_t &cursor, util::buffer_t<std::uint8_t> &&cursor_img, DXGI_OUTDUPL_POINTER_SHAPE_INFO &shape_info) {
// This cursor image may not be used
if(cursor_img.size() == 0) {
Expand Down