fix snapshots and preview

This commit is contained in:
SamGondelman 2019-04-17 15:43:05 -07:00
parent c730e51d1e
commit e7d12dc4f8
14 changed files with 101 additions and 85 deletions

View file

@ -8428,6 +8428,17 @@ bool Application::takeSnapshotOperators(std::queue<SnapshotOperator>& snapshotOp
return !snapshotOperators.empty(); return !snapshotOperators.empty();
} }
void Application::addSecondarySnapshotOperator(const SecondarySnapshotOperator& snapshotOperator) {
std::lock_guard<std::mutex> lock(_snapshotMutex);
_secondarySnapshotOperators.push(snapshotOperator);
}
bool Application::takeSecondarySnapshotOperators(std::queue<SecondarySnapshotOperator>& snapshotOperators) {
std::lock_guard<std::mutex> lock(_snapshotMutex);
_secondarySnapshotOperators.swap(snapshotOperators);
return !snapshotOperators.empty();
}
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) {
addSnapshotOperator({ [notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) { addSnapshotOperator({ [notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) {
QString path = DependencyManager::get<Snapshot>()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); QString path = DependencyManager::get<Snapshot>()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation());
@ -8439,16 +8450,17 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa
emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(path, notify); emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(path, notify);
} }
} else if (!SnapshotAnimated::isAlreadyTakingSnapshotAnimated()) { } else if (!SnapshotAnimated::isAlreadyTakingSnapshotAnimated()) {
// Get an animated GIF snapshot and save it qApp->postLambdaEvent([path, aspectRatio] {
SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, qApp, DependencyManager::get<WindowScriptingInterface>()); // Get an animated GIF snapshot and save it
SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, DependencyManager::get<WindowScriptingInterface>());
});
} }
}, aspectRatio }); }, aspectRatio });
} }
void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) { void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) {
postLambdaEvent([notify, filename, this] { addSecondarySnapshotOperator([notify, filename](const QImage& snapshot) {
QString snapshotPath = DependencyManager::get<Snapshot>()->saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename, QString snapshotPath = DependencyManager::get<Snapshot>()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation());
TestScriptingInterface::getInstance()->getTestResultsLocation());
emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, notify); emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, notify);
}); });

View file

@ -345,8 +345,11 @@ public:
#endif #endif
using SnapshotOperator = std::pair<std::function<void(const QImage&)>, float>; using SnapshotOperator = std::pair<std::function<void(const QImage&)>, float>;
using SecondarySnapshotOperator = std::function<void(const QImage&)>;
void addSnapshotOperator(const SnapshotOperator& snapshotOperator); void addSnapshotOperator(const SnapshotOperator& snapshotOperator);
bool takeSnapshotOperators(std::queue<SnapshotOperator>& snapshotOperators); bool takeSnapshotOperators(std::queue<SnapshotOperator>& snapshotOperators);
void addSecondarySnapshotOperator(const SecondarySnapshotOperator& snapshotOperator);
bool takeSecondarySnapshotOperators(std::queue<SecondarySnapshotOperator>& snapshotOperators);
signals: signals:
void svoImportRequested(const QString& url); void svoImportRequested(const QString& url);
@ -794,6 +797,7 @@ private:
SharedSoundPointer _sampleSound; SharedSoundPointer _sampleSound;
std::mutex _snapshotMutex; std::mutex _snapshotMutex;
std::queue<SnapshotOperator> _snapshotOperators; std::queue<SnapshotOperator> _snapshotOperators;
std::queue<SecondarySnapshotOperator> _secondarySnapshotOperators;
DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin; DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin;
QString _autoSwitchDisplayModeSupportedHMDPluginName; QString _autoSwitchDisplayModeSupportedHMDPluginName;

View file

@ -245,6 +245,7 @@ void GraphicsEngine::render_performFrame() {
} }
std::queue<Application::SnapshotOperator> snapshotOperators; std::queue<Application::SnapshotOperator> snapshotOperators;
std::queue<Application::SecondarySnapshotOperator> secondarySnapshotOperators;
if (!_programsCompiled.load()) { if (!_programsCompiled.load()) {
gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) {
batch.setFramebuffer(finalFramebuffer); batch.setFramebuffer(finalFramebuffer);
@ -273,12 +274,12 @@ void GraphicsEngine::render_performFrame() {
renderArgs._hudOperator = displayPlugin->getHUDOperator(); renderArgs._hudOperator = displayPlugin->getHUDOperator();
renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture(); renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture();
renderArgs._takingSnapshot = qApp->takeSnapshotOperators(snapshotOperators); renderArgs._takingSnapshot = qApp->takeSnapshotOperators(snapshotOperators);
qApp->takeSecondarySnapshotOperators(secondarySnapshotOperators);
renderArgs._blitFramebuffer = finalFramebuffer; renderArgs._blitFramebuffer = finalFramebuffer;
render_runRenderFrame(&renderArgs); render_runRenderFrame(&renderArgs);
} }
} }
qDebug() << "boop" << renderArgs._takingSnapshot << snapshotOperators.size();
auto frame = getGPUContext()->endFrame(); auto frame = getGPUContext()->endFrame();
frame->frameIndex = _renderFrameCount; frame->frameIndex = _renderFrameCount;
frame->framebuffer = finalFramebuffer; frame->framebuffer = finalFramebuffer;
@ -289,6 +290,7 @@ void GraphicsEngine::render_performFrame() {
} }
}; };
frame->snapshotOperators = snapshotOperators; frame->snapshotOperators = snapshotOperators;
frame->secondarySnapshotOperators = secondarySnapshotOperators;
// deliver final scene rendering commands to the display plugin // deliver final scene rendering commands to the display plugin
{ {
PROFILE_RANGE(render, "/pluginOutput"); PROFILE_RANGE(render, "/pluginOutput");

View file

@ -159,47 +159,57 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition,
secondaryCameraRenderConfig->setOrientation(CAMERA_ORIENTATION_DOWN); secondaryCameraRenderConfig->setOrientation(CAMERA_ORIENTATION_DOWN);
_snapshotIndex = 0; _snapshotIndex = 0;
_taking360Snapshot = true;
_snapshotTimer.start(SNAPSHOT_360_TIMER_INTERVAL); _snapshotTimer.start(SNAPSHOT_360_TIMER_INTERVAL);
} }
void Snapshot::takeNextSnapshot() { void Snapshot::takeNextSnapshot() {
SecondaryCameraJobConfig* config = if (_taking360Snapshot) {
static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera")); if (!_waitingOnSnapshot) {
_waitingOnSnapshot = true;
qApp->addSecondarySnapshotOperator([this](const QImage& snapshot) {
// Order is:
// 0. Down
// 1. Front
// 2. Left
// 3. Back
// 4. Right
// 5. Up
if (_snapshotIndex < 6) {
_imageArray[_snapshotIndex] = snapshot;
}
// Order is: SecondaryCameraJobConfig* config = static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera"));
// 0. Down if (_snapshotIndex == 0) {
// 1. Front // Setup for Front Image capture
// 2. Left config->setOrientation(CAMERA_ORIENTATION_FRONT);
// 3. Back } else if (_snapshotIndex == 1) {
// 4. Right // Setup for Left Image capture
// 5. Up config->setOrientation(CAMERA_ORIENTATION_LEFT);
if (_snapshotIndex < 6) { } else if (_snapshotIndex == 2) {
_imageArray[_snapshotIndex] = qApp->getActiveDisplayPlugin()->getSecondaryCameraScreenshot(); // Setup for Back Image capture
} config->setOrientation(CAMERA_ORIENTATION_BACK);
} else if (_snapshotIndex == 3) {
// Setup for Right Image capture
config->setOrientation(CAMERA_ORIENTATION_RIGHT);
} else if (_snapshotIndex == 4) {
// Setup for Up Image capture
config->setOrientation(CAMERA_ORIENTATION_UP);
} else if (_snapshotIndex == 5) {
_taking360Snapshot = false;
}
if (_snapshotIndex == 0) { _waitingOnSnapshot = false;
// Setup for Front Image capture _snapshotIndex++;
config->setOrientation(CAMERA_ORIENTATION_FRONT); });
} else if (_snapshotIndex == 1) { }
// Setup for Left Image capture } else {
config->setOrientation(CAMERA_ORIENTATION_LEFT);
} else if (_snapshotIndex == 2) {
// Setup for Back Image capture
config->setOrientation(CAMERA_ORIENTATION_BACK);
} else if (_snapshotIndex == 3) {
// Setup for Right Image capture
config->setOrientation(CAMERA_ORIENTATION_RIGHT);
} else if (_snapshotIndex == 4) {
// Setup for Up Image capture
config->setOrientation(CAMERA_ORIENTATION_UP);
} else if (_snapshotIndex > 5) {
_snapshotTimer.stop(); _snapshotTimer.stop();
// Reset secondary camera render config // Reset secondary camera render config
static_cast<ToneMappingConfig*>( SecondaryCameraJobConfig* config = static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera"));
qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping")) static_cast<ToneMappingConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))->setCurve(1);
->setCurve(1);
config->resetSizeSpectatorCamera(qApp->getWindow()->geometry().width(), qApp->getWindow()->geometry().height()); config->resetSizeSpectatorCamera(qApp->getWindow()->geometry().width(), qApp->getWindow()->geometry().height());
config->setProperty("attachedEntityId", _oldAttachedEntityId); config->setProperty("attachedEntityId", _oldAttachedEntityId);
config->setProperty("vFoV", _oldvFoV); config->setProperty("vFoV", _oldvFoV);
@ -217,8 +227,6 @@ void Snapshot::takeNextSnapshot() {
QtConcurrent::run([this]() { convertToEquirectangular(); }); QtConcurrent::run([this]() { convertToEquirectangular(); });
} }
} }
_snapshotIndex++;
} }
void Snapshot::convertToCubemap() { void Snapshot::convertToCubemap() {

View file

@ -97,6 +97,8 @@ private:
bool _cubemapOutputFormat; bool _cubemapOutputFormat;
QTimer _snapshotTimer; QTimer _snapshotTimer;
qint16 _snapshotIndex; qint16 _snapshotIndex;
bool _waitingOnSnapshot { false };
bool _taking360Snapshot { false };
bool _oldEnabled; bool _oldEnabled;
QVariant _oldAttachedEntityId; QVariant _oldAttachedEntityId;
QVariant _oldOrientation; QVariant _oldOrientation;

View file

@ -27,7 +27,6 @@ QString SnapshotAnimated::snapshotAnimatedPath;
QString SnapshotAnimated::snapshotStillPath; QString SnapshotAnimated::snapshotStillPath;
QVector<QImage> SnapshotAnimated::snapshotAnimatedFrameVector; QVector<QImage> SnapshotAnimated::snapshotAnimatedFrameVector;
QVector<qint64> SnapshotAnimated::snapshotAnimatedFrameDelayVector; QVector<qint64> SnapshotAnimated::snapshotAnimatedFrameDelayVector;
Application* SnapshotAnimated::app;
float SnapshotAnimated::aspectRatio; float SnapshotAnimated::aspectRatio;
QSharedPointer<WindowScriptingInterface> SnapshotAnimated::snapshotAnimatedDM; QSharedPointer<WindowScriptingInterface> SnapshotAnimated::snapshotAnimatedDM;
GifWriter SnapshotAnimated::snapshotAnimatedGifWriter; GifWriter SnapshotAnimated::snapshotAnimatedGifWriter;
@ -36,12 +35,11 @@ GifWriter SnapshotAnimated::snapshotAnimatedGifWriter;
Setting::Handle<bool> SnapshotAnimated::alsoTakeAnimatedSnapshot("alsoTakeAnimatedSnapshot", true); Setting::Handle<bool> SnapshotAnimated::alsoTakeAnimatedSnapshot("alsoTakeAnimatedSnapshot", true);
Setting::Handle<float> SnapshotAnimated::snapshotAnimatedDuration("snapshotAnimatedDuration", SNAPSNOT_ANIMATED_DURATION_SECS); Setting::Handle<float> SnapshotAnimated::snapshotAnimatedDuration("snapshotAnimatedDuration", SNAPSNOT_ANIMATED_DURATION_SECS);
void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio, Application* app, QSharedPointer<WindowScriptingInterface> dm) { void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio, QSharedPointer<WindowScriptingInterface> dm) {
// If we're not in the middle of capturing an animated snapshot... // If we're not in the middle of capturing an animated snapshot...
if (SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp == 0) { if (SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp == 0) {
SnapshotAnimated::snapshotAnimatedTimer = new QTimer(); SnapshotAnimated::snapshotAnimatedTimer = new QTimer();
SnapshotAnimated::aspectRatio = aspectRatio; SnapshotAnimated::aspectRatio = aspectRatio;
SnapshotAnimated::app = app;
SnapshotAnimated::snapshotAnimatedDM = dm; SnapshotAnimated::snapshotAnimatedDM = dm;
// Define the output location of the still and animated snapshots. // Define the output location of the still and animated snapshots.
SnapshotAnimated::snapshotStillPath = pathStill; SnapshotAnimated::snapshotStillPath = pathStill;
@ -62,7 +60,7 @@ void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio
void SnapshotAnimated::captureFrames() { void SnapshotAnimated::captureFrames() {
if (SnapshotAnimated::snapshotAnimatedTimerRunning) { if (SnapshotAnimated::snapshotAnimatedTimerRunning) {
SnapshotAnimated::app->addSnapshotOperator({ [](const QImage& snapshot) { qApp->addSnapshotOperator({ [](const QImage& snapshot) {
// Get a screenshot from the display, then scale the screenshot down, // Get a screenshot from the display, then scale the screenshot down,
// then convert it to the image format the GIF library needs, // then convert it to the image format the GIF library needs,
// then save all that to the QImage named "frame" // then save all that to the QImage named "frame"
@ -86,21 +84,21 @@ void SnapshotAnimated::captureFrames() {
// If that was the last frame... // If that was the last frame...
if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) { if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) {
SnapshotAnimated::snapshotAnimatedTimerRunning = false; SnapshotAnimated::snapshotAnimatedTimerRunning = false;
// Notify the user that we're processing the snapshot
// This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called.
emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath);
// Kick off the thread that'll pack the frames into the GIF
QtConcurrent::run(processFrames);
// Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE
// that the slot will not be called again in the future.
// See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html
SnapshotAnimated::snapshotAnimatedTimer->stop();
delete SnapshotAnimated::snapshotAnimatedTimer;
} }
} }
}, SnapshotAnimated::aspectRatio }); }, SnapshotAnimated::aspectRatio });
} else {
// Notify the user that we're processing the snapshot
// This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called.
emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath);
// Kick off the thread that'll pack the frames into the GIF
QtConcurrent::run(processFrames);
// Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE
// that the slot will not be called again in the future.
// See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html
SnapshotAnimated::snapshotAnimatedTimer->stop();
delete SnapshotAnimated::snapshotAnimatedTimer;
} }
} }

View file

@ -42,7 +42,6 @@ private:
static QVector<QImage> snapshotAnimatedFrameVector; static QVector<QImage> snapshotAnimatedFrameVector;
static QVector<qint64> snapshotAnimatedFrameDelayVector; static QVector<qint64> snapshotAnimatedFrameDelayVector;
static QSharedPointer<WindowScriptingInterface> snapshotAnimatedDM; static QSharedPointer<WindowScriptingInterface> snapshotAnimatedDM;
static Application* app;
static float aspectRatio; static float aspectRatio;
static GifWriter snapshotAnimatedGifWriter; static GifWriter snapshotAnimatedGifWriter;
@ -51,7 +50,7 @@ private:
static void processFrames(); static void processFrames();
static void clearTempVariables(); static void clearTempVariables();
public: public:
static void saveSnapshotAnimated(QString pathStill, float aspectRatio, Application* app, QSharedPointer<WindowScriptingInterface> dm); static void saveSnapshotAnimated(QString pathStill, float aspectRatio, QSharedPointer<WindowScriptingInterface> dm);
static bool isAlreadyTakingSnapshotAnimated() { return snapshotAnimatedFirstFrameTimestamp != 0; }; static bool isAlreadyTakingSnapshotAnimated() { return snapshotAnimatedFirstFrameTimestamp != 0; };
static Setting::Handle<bool> alsoTakeAnimatedSnapshot; static Setting::Handle<bool> alsoTakeAnimatedSnapshot;
static Setting::Handle<float> snapshotAnimatedDuration; static Setting::Handle<float> snapshotAnimatedDuration;

View file

@ -25,12 +25,4 @@ void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) {
if (frame) { if (frame) {
_gpuContext->consumeFrameUpdates(frame); _gpuContext->consumeFrameUpdates(frame);
} }
} }
QImage NullDisplayPlugin::getScreenshot(float aspectRatio) const {
return QImage();
}
QImage NullDisplayPlugin::getSecondaryCameraScreenshot() const {
return QImage();
}

View file

@ -17,8 +17,6 @@ public:
glm::uvec2 getRecommendedRenderSize() const override; glm::uvec2 getRecommendedRenderSize() const override;
void submitFrame(const gpu::FramePointer& newFrame) 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 {}; void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override {};
void pluginUpdate() override {}; void pluginUpdate() override {};
private: private:

View file

@ -732,6 +732,15 @@ void OpenGLDisplayPlugin::present() {
} }
} }
{ // If we have any secondary camera snapshots this frame, handle them
PROFILE_RANGE_EX(render, "secondarySnapshotOperators", 0x00ff00ff, frameId)
while (!_currentFrame->secondarySnapshotOperators.empty()) {
auto& snapshotOperator = _currentFrame->secondarySnapshotOperators.front();
snapshotOperator(getSecondaryCameraScreenshot());
_currentFrame->secondarySnapshotOperators.pop();
}
}
// Take the composite framebuffer and send it to the output device // Take the composite framebuffer and send it to the output device
{ {
PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId) PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId)
@ -796,7 +805,7 @@ bool OpenGLDisplayPlugin::setDisplayTexture(const QString& name) {
return !!_displayTexture; return !!_displayTexture;
} }
QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) {
auto size = _compositeFramebuffer->getSize(); auto size = _compositeFramebuffer->getSize();
if (isHmd()) { if (isHmd()) {
size.x /= 2; size.x /= 2;
@ -812,24 +821,18 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const {
corner.x = round((size.x - bestSize.x) / 2.0f); corner.x = round((size.x - bestSize.x) / 2.0f);
corner.y = round((size.y - bestSize.y) / 2.0f); corner.y = round((size.y - bestSize.y) / 2.0f);
} }
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32); QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32);
withOtherThreadContext([&] { getGLBackend()->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot);
glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot);
});
return screenshot.mirrored(false, true); return screenshot.mirrored(false, true);
} }
QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() const { QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() {
auto textureCache = DependencyManager::get<TextureCache>(); auto textureCache = DependencyManager::get<TextureCache>();
auto secondaryCameraFramebuffer = textureCache->getSpectatorCameraFramebuffer(); auto secondaryCameraFramebuffer = textureCache->getSpectatorCameraFramebuffer();
gpu::Vec4i region(0, 0, secondaryCameraFramebuffer->getWidth(), secondaryCameraFramebuffer->getHeight()); gpu::Vec4i region(0, 0, secondaryCameraFramebuffer->getWidth(), secondaryCameraFramebuffer->getHeight());
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
QImage screenshot(region.z, region.w, QImage::Format_ARGB32); QImage screenshot(region.z, region.w, QImage::Format_ARGB32);
withOtherThreadContext([&] { getGLBackend()->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot);
glBackend->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot);
});
return screenshot.mirrored(false, true); return screenshot.mirrored(false, true);
} }

View file

@ -60,8 +60,6 @@ public:
virtual bool setDisplayTexture(const QString& name) override; virtual bool setDisplayTexture(const QString& name) override;
virtual bool onDisplayTextureReset() { return false; }; virtual bool onDisplayTextureReset() { return false; };
QImage getScreenshot(float aspectRatio = 0.0f) const override;
QImage getSecondaryCameraScreenshot() const override;
float presentRate() const override; float presentRate() const override;
@ -185,5 +183,8 @@ protected:
// be serialized through this mutex // be serialized through this mutex
mutable Mutex _presentMutex; mutable Mutex _presentMutex;
float _hudAlpha{ 1.0f }; float _hudAlpha{ 1.0f };
QImage getScreenshot(float aspectRatio);
QImage getSecondaryCameraScreenshot();
}; };

View file

@ -199,7 +199,7 @@ void HmdDisplayPlugin::internalPresent() {
float newWidth = sourceSize.x - shiftLeftBy; float newWidth = sourceSize.x - shiftLeftBy;
// Experimentally adjusted the region presented in preview to avoid seeing the masked pixels and recenter the center... // Experimentally adjusted the region presented in preview to avoid seeing the masked pixels and recenter the center...
static float SCALE_WIDTH = 0.9f; static float SCALE_WIDTH = 0.8f;
static float SCALE_OFFSET = 2.0f; static float SCALE_OFFSET = 2.0f;
newWidth *= SCALE_WIDTH; newWidth *= SCALE_WIDTH;
shiftLeftBy *= SCALE_OFFSET; shiftLeftBy *= SCALE_OFFSET;

View file

@ -43,6 +43,7 @@ namespace gpu {
FramebufferRecycler framebufferRecycler; FramebufferRecycler framebufferRecycler;
std::queue<std::pair<std::function<void(const QImage&)>, float>> snapshotOperators; std::queue<std::pair<std::function<void(const QImage&)>, float>> snapshotOperators;
std::queue<std::function<void(const QImage&)>> secondarySnapshotOperators;
protected: protected:
friend class Deserializer; friend class Deserializer;

View file

@ -173,10 +173,6 @@ public:
return QRect(0, 0, recommendedSize.x, recommendedSize.y); return QRect(0, 0, recommendedSize.x, recommendedSize.y);
} }
// 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 // will query the underlying hmd api to compute the most recent head pose
virtual bool beginFrameRender(uint32_t frameIndex) { return true; } virtual bool beginFrameRender(uint32_t frameIndex) { return true; }