From 88a449c1af7381163d1c01b742b30aabb0264a3c Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 12 Jul 2017 16:49:26 -0700 Subject: [PATCH] Fixes hmd preview when resizing --- interface/src/ui/ResourceImageItem.cpp | 28 +++++++------------ interface/src/ui/ResourceImageItem.h | 1 + .../display-plugins/OpenGLDisplayPlugin.cpp | 28 +++++++++++++++---- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 8 ++++-- .../src/model-networking/TextureCache.cpp | 3 +- .../src/model-networking/TextureCache.h | 3 ++ 6 files changed, 45 insertions(+), 26 deletions(-) diff --git a/interface/src/ui/ResourceImageItem.cpp b/interface/src/ui/ResourceImageItem.cpp index 2ff3121df4..7b9592fa4c 100644 --- a/interface/src/ui/ResourceImageItem.cpp +++ b/interface/src/ui/ResourceImageItem.cpp @@ -16,6 +16,10 @@ #include #include +ResourceImageItem::ResourceImageItem() : QQuickFramebufferObject() { + auto textureCache = DependencyManager::get(); + connect(textureCache.data(), SIGNAL(spectatorCameraFramebufferReset()), this, SLOT(update())); +} void ResourceImageItem::setUrl(const QString& url) { if (url != m_url) { @@ -50,32 +54,20 @@ void ResourceImageItemRenderer::onUpdateTimer() { ResourceImageItemRenderer::ResourceImageItemRenderer() : QQuickFramebufferObject::Renderer() { connect(&_updateTimer, SIGNAL(timeout()), this, SLOT(onUpdateTimer())); + auto textureCache = DependencyManager::get(); } void ResourceImageItemRenderer::synchronize(QQuickFramebufferObject* item) { ResourceImageItem* resourceImageItem = static_cast(item); resourceImageItem->setFlag(QQuickItem::ItemHasContents); - bool urlChanged = false; - if (_url != resourceImageItem->getUrl()) { - _url = resourceImageItem->getUrl(); - urlChanged = true; - } - bool readyChanged = false; - if (_ready != resourceImageItem->getReady()) { - _ready = resourceImageItem->getReady(); - readyChanged = true; - } - bool visibleChanged = false; - if (_visible != resourceImageItem->isVisible()) { - _visible = resourceImageItem->isVisible(); - visibleChanged = true; - } + + _url = resourceImageItem->getUrl(); + _ready = resourceImageItem->getReady(); + _visible = resourceImageItem->isVisible(); _window = resourceImageItem->window(); - if (_ready && _visible && !_url.isNull() && !_url.isEmpty() && (visibleChanged || urlChanged || readyChanged || !_networkTexture)) { - _networkTexture = DependencyManager::get()->getTexture(_url); - } + _networkTexture = DependencyManager::get()->getTexture(_url); static const int UPDATE_TIMER_DELAY_IN_MS = 100; // 100 ms = 10 hz for now if (_ready && _visible && !_updateTimer.isActive()) { _updateTimer.start(UPDATE_TIMER_DELAY_IN_MS); diff --git a/interface/src/ui/ResourceImageItem.h b/interface/src/ui/ResourceImageItem.h index 183e86ec63..985ab5a66e 100644 --- a/interface/src/ui/ResourceImageItem.h +++ b/interface/src/ui/ResourceImageItem.h @@ -47,6 +47,7 @@ class ResourceImageItem : public QQuickFramebufferObject { Q_PROPERTY(QString url READ getUrl WRITE setUrl) Q_PROPERTY(bool ready READ getReady WRITE setReady) public: + ResourceImageItem(); QString getUrl() const { return m_url; } void setUrl(const QString& url); bool getReady() const { return m_ready; } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 004cd05883..e1259fc5fc 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -514,13 +514,29 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.setPipeline(_presentPipeline); batch.draw(gpu::TRIANGLE_STRIP, 4); if (copyFbo) { + gpu::Vec4i copyFboRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight()); gpu::Vec4i sourceRect(scissor.x, scissor.y, scissor.x + scissor.z, scissor.y + scissor.w); - gpu::Vec4i copyRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight()); + float aspectRatio = (float)scissor.w / (float) scissor.z; // height/width + // scale width first + int xOffset = 0; + int yOffset = 0; + int newWidth = copyFbo->getWidth(); + int newHeight = std::round(aspectRatio * (float) copyFbo->getWidth()); + if (newHeight > copyFbo->getHeight()) { + // ok, so now fill height instead + newHeight = copyFbo->getHeight(); + newWidth = std::round((float)copyFbo->getHeight() / aspectRatio); + xOffset = (copyFbo->getWidth() - newWidth) / 2; + } else { + yOffset = (copyFbo->getHeight() - newHeight) / 2; + } + gpu::Vec4i copyRect(xOffset, yOffset, xOffset + newWidth, yOffset + newHeight); batch.setFramebuffer(copyFbo); + batch.resetViewTransform(); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); - batch.setViewportTransform(copyRect); - batch.setStateScissorRect(copyRect); + batch.setViewportTransform(copyFboRect); + batch.setStateScissorRect(copyFboRect); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); batch.blit(fbo, sourceRect, copyFbo, copyRect); } } @@ -862,6 +878,8 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne // setup destination fbo glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTexture, 0); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); // maintain aspect ratio, filling the width first if possible. If that makes the height too @@ -878,7 +896,7 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne } else { newY = (target->height() - newHeight) / 2; } - glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newWidth, newHeight, GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT, GL_NEAREST); // don't delete the textures! glDeleteFramebuffers(2, fbo); diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index c0937ce289..b183850e7f 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -242,6 +242,9 @@ void HmdDisplayPlugin::internalPresent() { glm::ivec4 viewport = getViewportForSourceSize(sourceSize); glm::ivec4 scissor = viewport; + + auto fbo = gpu::FramebufferPointer(); + render([&](gpu::Batch& batch) { if (_monoPreview) { @@ -284,10 +287,11 @@ void HmdDisplayPlugin::internalPresent() { viewport = ivec4(scissorOffset - scaledShiftLeftBy, viewportOffset, viewportSizeX, viewportSizeY); } + // TODO: only bother getting and passing in the hmdPreviewFramebuffer if the camera is on + fbo = DependencyManager::get()->getHmdPreviewFramebuffer(windowSize.x, windowSize.y); + viewport.z *= 2; } - // TODO: only bother getting and passing in the hmdPreviewFramebuffer if the camera is on - auto fbo = DependencyManager::get()->getHmdPreviewFramebuffer(scissor.z, scissor.w); renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor, fbo); }); swapBuffers(); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 3538080065..85bde4c2f1 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -1002,7 +1002,7 @@ NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl) } const gpu::FramebufferPointer& TextureCache::getHmdPreviewFramebuffer(int width, int height) { - if (!_hmdPreviewFramebuffer) { + if (!_hmdPreviewFramebuffer || _hmdPreviewFramebuffer->getWidth() != width || _hmdPreviewFramebuffer->getHeight() != height) { _hmdPreviewFramebuffer.reset(gpu::Framebuffer::create("hmdPreview",gpu::Element::COLOR_SRGBA_32, width, height)); } return _hmdPreviewFramebuffer; @@ -1018,4 +1018,5 @@ const gpu::FramebufferPointer& TextureCache::getSpectatorCameraFramebuffer() { void TextureCache::resetSpectatorCameraFramebuffer(int width, int height) { _spectatorCameraFramebuffer.reset(gpu::Framebuffer::create("spectatorCamera", gpu::Element::COLOR_SRGBA_32, width, height)); _spectatorCameraNetworkTexture.reset(); + emit spectatorCameraFramebufferReset(); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 2de447f573..f5a0ec5215 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -172,6 +172,9 @@ public: void resetSpectatorCameraFramebuffer(int width, int height); const gpu::FramebufferPointer& getHmdPreviewFramebuffer(int width, int height); +signals: + void spectatorCameraFramebufferReset(); + protected: // Overload ResourceCache::prefetch to allow specifying texture type for loads Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS);