diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f954a1e2c4..616b6914e9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6911,6 +6911,12 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa }); } +void Application::takeSecondaryCameraSnapshot() { + postLambdaEvent([this] { + Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot()); + }); +} + void Application::shareSnapshot(const QString& path, const QUrl& href) { postLambdaEvent([path, href] { // not much to do here, everything is done in snapshot code... diff --git a/interface/src/Application.h b/interface/src/Application.h index dddc373c91..752d6657fb 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -274,6 +274,7 @@ public: float getAverageSimsPerSecond() const { return _simCounter.rate(); } void takeSnapshot(bool notify, bool includeAnimated = false, float aspectRatio = 0.0f); + void takeSecondaryCameraSnapshot(); void shareSnapshot(const QString& filename, const QUrl& href = QUrl("")); model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 84f4cbbbd8..277989439c 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -294,6 +294,10 @@ void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, f qApp->takeSnapshot(notify, includeAnimated, aspectRatio); } +void WindowScriptingInterface::takeSecondaryCameraSnapshot() { + qApp->takeSecondaryCameraSnapshot(); +} + void WindowScriptingInterface::shareSnapshot(const QString& path, const QUrl& href) { qApp->shareSnapshot(path, href); } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index f8ed20f42f..28f1bafa5d 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -60,6 +60,7 @@ public slots: void showAssetServer(const QString& upload = ""); void copyToClipboard(const QString& text); void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f); + void takeSecondaryCameraSnapshot(); void makeConnection(bool success, const QString& userNameOrError); void displayAnnouncement(const QString& message); void shareSnapshot(const QString& path, const QUrl& href = QUrl("")); diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index a4777b087b..6a19a34727 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -34,3 +34,7 @@ void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) { QImage NullDisplayPlugin::getScreenshot(float aspectRatio) const { return QImage(); } + +QImage NullDisplayPlugin::getSecondaryCameraScreenshot() const { + return QImage(); +} diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 8d01539e8a..97b71b5780 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -19,6 +19,7 @@ public: bool hasFocus() const override; void submitFrame(const gpu::FramePointer& newFrame) override; QImage getScreenshot(float aspectRatio = 0.0f) const override; + QImage getSecondaryCameraScreenshot() const override; void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override {}; private: static const QString NAME; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index e1259fc5fc..7144e401e4 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -775,6 +775,19 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { return screenshot.mirrored(false, true); } +QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() const { + auto textureCache = DependencyManager::get(); + auto secondaryCameraFramebuffer = textureCache->getSpectatorCameraFramebuffer(); + gpu::Vec4i region(0, 0, secondaryCameraFramebuffer->getWidth(), secondaryCameraFramebuffer->getHeight()); + + auto glBackend = const_cast(*this).getGLBackend(); + QImage screenshot(region.z, region.w, QImage::Format_ARGB32); + withMainThreadContext([&] { + glBackend->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot); + }); + return screenshot.mirrored(false, true); +} + glm::uvec2 OpenGLDisplayPlugin::getSurfacePixels() const { uvec2 result; auto window = _container->getPrimaryWidget(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 2f93fa630d..2080fa5ea6 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -60,6 +60,7 @@ public: virtual bool setDisplayTexture(const QString& name) override; virtual bool onDisplayTextureReset() { return false; }; QImage getScreenshot(float aspectRatio = 0.0f) const override; + QImage getSecondaryCameraScreenshot() const override; float presentRate() const override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 9e18ee534d..d7531e66a7 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -183,6 +183,7 @@ public: // Fetch the most recently displayed image as a QImage virtual QImage getScreenshot(float aspectRatio = 0.0f) const = 0; + virtual QImage getSecondaryCameraScreenshot() const = 0; // will query the underlying hmd api to compute the most recent head pose virtual bool beginFrameRender(uint32_t frameIndex) { return true; }