Skip to content

Commit

Permalink
Keep frame clock running if waiting for frame tick
Browse files Browse the repository at this point in the history
If there is something interested in synchronizing to a frame tick, then
keep the frame clock running, even if there are no updates.

This is need mainly when something starts rendering, but also when
something renders much slower than the frame clock (so it is essentially
constantly "starting"). Such an application will not draw anything until
it gets a new frame tick, which it won't get as the frame clock is
waiting for something to start drawing.
  • Loading branch information
CendioOssman committed Jun 19, 2024
1 parent d226d98 commit 5242bfb
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 5 deletions.
1 change: 1 addition & 0 deletions common/rfb/VNCServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace rfb {
virtual void unblockUpdates() = 0;

virtual uint64_t getMsc() = 0;
virtual void queueMsc(uint64_t target) = 0;

// setPixelBuffer() tells the server to use the given pixel buffer (and
// optionally a modified screen layout). If this differs in size from
Expand Down
20 changes: 16 additions & 4 deletions common/rfb/VNCServerST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
renderedCursorInvalid(false),
keyRemapper(&KeyRemapper::defInstance),
idleTimer(this), disconnectTimer(this), connectTimer(this),
msc(0), frameTimer(this)
msc(0), queuedMsc(0), frameTimer(this)
{
slog.debug("creating single-threaded server %s", name.c_str());

Expand Down Expand Up @@ -262,6 +262,14 @@ uint64_t VNCServerST::getMsc()
return msc;
}

void VNCServerST::queueMsc(uint64_t target)
{
if (target > queuedMsc)
queuedMsc = target;

startFrameClock();
}

void VNCServerST::setPixelBuffer(PixelBuffer* pb_, const ScreenSet& layout)
{
if (comparer)
Expand Down Expand Up @@ -634,13 +642,17 @@ void VNCServerST::handleTimeout(Timer* t)
{
if (t == &frameTimer) {
// We keep running until we go a full interval without any updates
if (comparer->is_empty())
return;
if (comparer->is_empty()) {
// Unless something waits for us to advance the frame count
if (queuedMsc < msc)
return;
}

// If this is the first iteration then we need to adjust the timeout
frameTimer.repeat(1000/rfb::Server::frameRate);

writeUpdate();
if (!comparer->is_empty())
writeUpdate();

msc++;
desktop->frameTick(msc);
Expand Down
3 changes: 2 additions & 1 deletion common/rfb/VNCServerST.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ namespace rfb {
virtual void blockUpdates();
virtual void unblockUpdates();
virtual uint64_t getMsc();
virtual void queueMsc(uint64_t target);
virtual void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout);
virtual void setPixelBuffer(PixelBuffer* pb);
virtual void setScreenLayout(const ScreenSet& layout);
Expand Down Expand Up @@ -207,7 +208,7 @@ namespace rfb {
Timer disconnectTimer;
Timer connectTimer;

uint64_t msc;
uint64_t msc, queuedMsc;
Timer frameTimer;
};

Expand Down
1 change: 1 addition & 0 deletions unix/xserver/hw/vnc/XserverDesktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ uint64_t XserverDesktop::getMsc()
void XserverDesktop::queueMsc(uint64_t id, uint64_t msc)
{
pendingMsc[id] = msc;
server->queueMsc(msc);
}

void XserverDesktop::abortMsc(uint64_t id)
Expand Down

0 comments on commit 5242bfb

Please sign in to comment.