mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 19:30:41 +02:00
fix snapshots and preview
This commit is contained in:
parent
c730e51d1e
commit
e7d12dc4f8
14 changed files with 101 additions and 85 deletions
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue