From be9d99264feec6b26df35820a86773af18e7133f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Jul 2015 16:15:10 -0700 Subject: [PATCH] Introducing the download Framebuffer call on the context to capture a snapshot --- interface/src/Application.cpp | 26 ++++------------------- libraries/gpu/src/gpu/Batch.h | 1 - libraries/gpu/src/gpu/Context.cpp | 6 +++++- libraries/gpu/src/gpu/Context.h | 6 ++++++ libraries/gpu/src/gpu/Framebuffer.h | 2 -- libraries/gpu/src/gpu/GLBackend.h | 4 ++++ libraries/gpu/src/gpu/GLBackendOutput.cpp | 12 +++++++++++ 7 files changed, 31 insertions(+), 26 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e7479b94d8..ced6d2b301 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2998,18 +2998,8 @@ PickRay Application::computePickRay(float x, float y) const { } QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { -/* auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); - glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); - // clear the alpha channel so the background is transparent - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - */ - - // const int BILLBOARD_SIZE = 64; - const int BILLBOARD_SIZE = 256; + const int BILLBOARD_SIZE = 64; _glWidget->makeCurrent(); auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); @@ -3020,26 +3010,18 @@ QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { batch.setFramebuffer(primaryFbo); renderArgs->_context->render(batch); } - renderArgs->_renderMode = RenderArgs::MIRROR_RENDER_MODE; - renderRearViewMirror(renderArgs, QRect(0, /*_glWidget->getDeviceHeight() - BILLBOARD_SIZE*/ 0, - BILLBOARD_SIZE, BILLBOARD_SIZE), - false); - renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + renderRearViewMirror(renderArgs, QRect(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), true); - auto selfieFbo = DependencyManager::get()->getSelfieFramebuffer(); { auto mirrorViewport = glm::ivec4(0, 0,BILLBOARD_SIZE, BILLBOARD_SIZE); gpu::Batch batch; - // batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewport); batch.setFramebuffer(nullptr); renderArgs->_context->render(batch); } - QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); - glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); - glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + renderArgs->_context->downloadFramebuffer(primaryFbo, glm::ivec4(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), image); return image; } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 2f1d2e8ece..acc1f6fdac 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -108,7 +108,6 @@ public: void blit(const FramebufferPointer& src, const Vec4i& srcViewport, const FramebufferPointer& dst, const Vec4i& dstViewport); - // Query Section void beginQuery(const QueryPointer& query); void endQuery(const QueryPointer& query); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 51335f78df..604f39f46f 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -40,4 +40,8 @@ void Context::render(Batch& batch) { void Context::syncCache() { PROFILE_RANGE(__FUNCTION__); _backend->syncCache(); -} \ No newline at end of file +} + +void Context::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { + _backend->downloadFramebuffer(srcFramebuffer, region, destImage); +} diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 484c772c71..0c4ead6eae 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -28,6 +28,8 @@ public: virtual~ Backend() {}; virtual void render(Batch& batch) = 0; virtual void syncCache() = 0; + virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; + class TransformObject { public: @@ -121,6 +123,10 @@ public: void syncCache(); + // Downloading the Framebuffer is a synchronous action that is not efficient. + // It s here for convenience to easily capture a snapshot + void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage); + protected: Context(const Context& context); diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 5a1504d25c..c1b5358d3c 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -14,8 +14,6 @@ #include "Texture.h" #include -class QImage; - namespace gpu { typedef Element Format; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 0e6f181028..c924395334 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -38,6 +38,10 @@ public: // Let's try to avoid to do that as much as possible! virtual void syncCache(); + // This is the ugly "download the pixels to sysmem for taking a snapshot" + // Just avoid using it, it's ugly and will break performances + virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage); + static bool checkGLError(const char* name = nullptr); // Only checks in debug builds diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 621f04b71b..ec1b9de341 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -11,6 +11,8 @@ #include "GPULogging.h" #include "GLBackendShared.h" +#include "qimage.h" + using namespace gpu; GLBackend::GLFramebuffer::GLFramebuffer() {} @@ -191,3 +193,13 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(_output._framebuffer)); } } + + +void GLBackend::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { + + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(srcFramebuffer)); + glReadPixels(region.x, region.y, region.z, region.w, GL_BGRA, GL_UNSIGNED_BYTE, destImage.bits()); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + (void) CHECK_GL_ERROR(); +} \ No newline at end of file