diff --git a/common/network/GetAPI.h b/common/network/GetAPI.h index ba22d9b..7f57d85 100644 --- a/common/network/GetAPI.h +++ b/common/network/GetAPI.h @@ -35,13 +35,15 @@ namespace network { // from main thread void mainUpdateScreen(rfb::PixelBuffer *pb); + void lockScreenshots(); + void unlockScreenshots(); void mainUpdateBottleneckStats(const char userid[], const char stats[]); void mainClearBottleneckStats(const char userid[]); void mainUpdateServerFrameStats(uint8_t changedPerc, uint32_t all, uint32_t jpeg, uint32_t webp, uint32_t analysis, uint32_t jpegarea, uint32_t webparea, uint16_t njpeg, uint16_t nwebp, - uint16_t enc, uint16_t scale, uint16_t shot, + uint16_t enc, uint16_t scale, uint16_t w, uint16_t h); void mainUpdateClientFrameStats(const char userid[], uint32_t render, uint32_t all, uint32_t ping); diff --git a/common/network/GetAPIMessager.cxx b/common/network/GetAPIMessager.cxx index 4c76a1b..d7dd62a 100644 --- a/common/network/GetAPIMessager.cxx +++ b/common/network/GetAPIMessager.cxx @@ -60,7 +60,11 @@ GetAPIMessager::GetAPIMessager(const char *passwdfile_): passwdfile(passwdfile_) ownerConnected(0), activeUsers(0), sessionsInfo( "{\"users\":[]}"){ - pthread_mutex_init(&screenMutex, NULL); + pthread_mutexattr_t screenAttr; + pthread_mutexattr_init(&screenAttr); + pthread_mutexattr_settype(&screenAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&screenMutex, &screenAttr); + pthread_mutexattr_destroy(&screenAttr); pthread_mutex_init(&userMutex, NULL); pthread_mutex_init(&statMutex, NULL); pthread_mutex_init(&frameStatMutex, NULL); @@ -71,11 +75,19 @@ GetAPIMessager::GetAPIMessager(const char *passwdfile_): passwdfile(passwdfile_) // from main thread void GetAPIMessager::mainUpdateScreen(rfb::PixelBuffer *pb_) { - if (pthread_mutex_trylock(&screenMutex)) - return; - pb = pb_; +} +void GetAPIMessager::lockScreenshots() { + pthread_mutex_lock(&screenMutex); + + screenW = screenH = 0; + screenHash = 0; + cachedW = cachedH = cachedQ = 0; + cachedJpeg.clear(); +} + +void GetAPIMessager::unlockScreenshots() { pthread_mutex_unlock(&screenMutex); } @@ -101,7 +113,7 @@ void GetAPIMessager::mainUpdateServerFrameStats(uint8_t changedPerc, uint32_t all, uint32_t jpeg, uint32_t webp, uint32_t analysis, uint32_t jpegarea, uint32_t webparea, uint16_t njpeg, uint16_t nwebp, - uint16_t enc, uint16_t scale, uint16_t shot, + uint16_t enc, uint16_t scale, uint16_t w, uint16_t h) { if (pthread_mutex_lock(&frameStatMutex)) @@ -118,7 +130,6 @@ void GetAPIMessager::mainUpdateServerFrameStats(uint8_t changedPerc, serverFrameStats.nwebp = nwebp; serverFrameStats.enc = enc; serverFrameStats.scale = scale; - serverFrameStats.shot = shot; serverFrameStats.w = w; serverFrameStats.h = h; @@ -164,11 +175,9 @@ void GetAPIMessager::mainUpdateSessionsInfo(std::string newSessionsInfo) uint8_t *GetAPIMessager::netGetScreenshot(uint16_t w, uint16_t h, const uint8_t q, const bool dedup, uint32_t &len, uint8_t *staging) { - + unsigned shottime = 0; int stride; - - if (!pb) - return nullptr; + TRACE_STOPWATCH(shotstart); uint8_t *ret = nullptr; len = 0; @@ -176,6 +185,11 @@ uint8_t *GetAPIMessager::netGetScreenshot(uint16_t w, uint16_t h, if (pthread_mutex_lock(&screenMutex)) return nullptr; + if (!pb) { + pthread_mutex_unlock(&screenMutex); + return nullptr; + } + const rdr::U8 *buf = pb->getBuffer(pb->getRect(), &stride); if (pb->width() != screenW || pb->height() != screenH) { @@ -279,6 +293,12 @@ uint8_t *GetAPIMessager::netGetScreenshot(uint16_t w, uint16_t h, pthread_mutex_unlock(&screenMutex); + shottime = msSince(&shotstart); + if (!pthread_mutex_lock(&frameStatMutex)) { + serverFrameStats.shot = shottime; + pthread_mutex_unlock(&frameStatMutex); + } + return ret; } diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index 11ac63a..92eb90e 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -507,6 +507,10 @@ void VNCServerST::setPixelBuffer(PixelBuffer* pb_, const ScreenSet& layout) renderedCursorInvalid = true; add_changed(pb->getRect()); + if (apimessager) { + apimessager->mainUpdateScreen(pb); + } + // Make sure that we have at least one screen if (screenLayout.num_screens() == 0) screenLayout.add_screen(Screen(0, 0, 0, pb->width(), pb->height(), 0)); @@ -1104,12 +1108,7 @@ void VNCServerST::writeUpdate() } DEBUG_STOPWATCH_PRINT_US(slog, perm_check); - unsigned shottime = 0; if (apimessager) { - TRACE_STOPWATCH(shotstart); - apimessager->mainUpdateScreen(pb); - shottime = msSince(&shotstart); - trackingFrameStats = 0; checkAPIMessages(apimessager, trackingFrameStats, trackingClient); } @@ -1178,7 +1177,7 @@ void VNCServerST::writeUpdate() analysisMs, jpegstats.area, webpstats.area, jpegstats.rects, webpstats.rects, - enctime, scaletime, shottime, + enctime, scaletime, pb->getRect().width(), pb->getRect().height()); } else { @@ -1372,3 +1371,15 @@ void VNCServerST::notifyUserAction(const VNCSConnectionST* newConnection, std::s logNotification.append( std::to_string(notificationsSent) + " clients"); slog.info("%s", logNotification.c_str()); } + +void VNCServerST::lockScreenBuffer() const { + if (apimessager) { + apimessager->lockScreenshots(); + } +} + +void VNCServerST::unlockScreenBuffer() const { + if (apimessager) { + apimessager->unlockScreenshots(); + } +} diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h index 42d49e7..a184c08 100644 --- a/common/rfb/VNCServerST.h +++ b/common/rfb/VNCServerST.h @@ -205,6 +205,8 @@ namespace rfb { enum UserActionType {Join, Leave}; void notifyUserAction(const VNCSConnectionST* newConnection, std::string& user_name, const UserActionType action_type); + void lockScreenBuffer() const; + void unlockScreenBuffer() const; protected: diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index 2d63628..ddc5f38 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -126,6 +126,8 @@ void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride_) { ScreenSet layout; + server->lockScreenBuffer(); + width_ = w; height_ = h; @@ -147,6 +149,7 @@ void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride_) layout = ::computeScreenLayout(&outputIdMap); server->setPixelBuffer(this, layout); + server->unlockScreenBuffer(); } void XserverDesktop::refreshScreenLayout()