Introducing the download Framebuffer call on the context to capture a snapshot

This commit is contained in:
Sam Gateau 2015-07-23 16:15:10 -07:00
parent dc10f30d3d
commit be9d99264f
7 changed files with 31 additions and 26 deletions

View file

@ -2998,18 +2998,8 @@ PickRay Application::computePickRay(float x, float y) const {
} }
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
/* auto primaryFramebuffer = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
// clear the alpha channel so the background is transparent const int BILLBOARD_SIZE = 64;
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;
_glWidget->makeCurrent(); _glWidget->makeCurrent();
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer(); auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
@ -3020,26 +3010,18 @@ QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
batch.setFramebuffer(primaryFbo); batch.setFramebuffer(primaryFbo);
renderArgs->_context->render(batch); renderArgs->_context->render(batch);
} }
renderArgs->_renderMode = RenderArgs::MIRROR_RENDER_MODE; renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
renderRearViewMirror(renderArgs, QRect(0, /*_glWidget->getDeviceHeight() - BILLBOARD_SIZE*/ 0, renderRearViewMirror(renderArgs, QRect(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), true);
BILLBOARD_SIZE, BILLBOARD_SIZE),
false);
renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
auto selfieFbo = DependencyManager::get<FramebufferCache>()->getSelfieFramebuffer();
{ {
auto mirrorViewport = glm::ivec4(0, 0,BILLBOARD_SIZE, BILLBOARD_SIZE); auto mirrorViewport = glm::ivec4(0, 0,BILLBOARD_SIZE, BILLBOARD_SIZE);
gpu::Batch batch; gpu::Batch batch;
// batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewport);
batch.setFramebuffer(nullptr); batch.setFramebuffer(nullptr);
renderArgs->_context->render(batch); renderArgs->_context->render(batch);
} }
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); renderArgs->_context->downloadFramebuffer(primaryFbo, glm::ivec4(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), image);
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return image; return image;
} }

View file

@ -108,7 +108,6 @@ public:
void blit(const FramebufferPointer& src, const Vec4i& srcViewport, void blit(const FramebufferPointer& src, const Vec4i& srcViewport,
const FramebufferPointer& dst, const Vec4i& dstViewport); const FramebufferPointer& dst, const Vec4i& dstViewport);
// Query Section // Query Section
void beginQuery(const QueryPointer& query); void beginQuery(const QueryPointer& query);
void endQuery(const QueryPointer& query); void endQuery(const QueryPointer& query);

View file

@ -40,4 +40,8 @@ void Context::render(Batch& batch) {
void Context::syncCache() { void Context::syncCache() {
PROFILE_RANGE(__FUNCTION__); PROFILE_RANGE(__FUNCTION__);
_backend->syncCache(); _backend->syncCache();
} }
void Context::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) {
_backend->downloadFramebuffer(srcFramebuffer, region, destImage);
}

View file

@ -28,6 +28,8 @@ public:
virtual~ Backend() {}; virtual~ Backend() {};
virtual void render(Batch& batch) = 0; virtual void render(Batch& batch) = 0;
virtual void syncCache() = 0; virtual void syncCache() = 0;
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
class TransformObject { class TransformObject {
public: public:
@ -121,6 +123,10 @@ public:
void syncCache(); 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: protected:
Context(const Context& context); Context(const Context& context);

View file

@ -14,8 +14,6 @@
#include "Texture.h" #include "Texture.h"
#include <memory> #include <memory>
class QImage;
namespace gpu { namespace gpu {
typedef Element Format; typedef Element Format;

View file

@ -38,6 +38,10 @@ public:
// Let's try to avoid to do that as much as possible! // Let's try to avoid to do that as much as possible!
virtual void syncCache(); 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); static bool checkGLError(const char* name = nullptr);
// Only checks in debug builds // Only checks in debug builds

View file

@ -11,6 +11,8 @@
#include "GPULogging.h" #include "GPULogging.h"
#include "GLBackendShared.h" #include "GLBackendShared.h"
#include "qimage.h"
using namespace gpu; using namespace gpu;
GLBackend::GLFramebuffer::GLFramebuffer() {} GLBackend::GLFramebuffer::GLFramebuffer() {}
@ -191,3 +193,13 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(_output._framebuffer)); 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();
}