From 51ce3129b9c3e715ba5610d1cd98ec4be09142bd Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 13 Apr 2015 12:22:08 -0700 Subject: [PATCH] connecting the dots for a framebuffer GLBackend, need to be tested --- libraries/gpu/src/gpu/Framebuffer.cpp | 29 ++++--- libraries/gpu/src/gpu/Framebuffer.h | 14 ++-- libraries/gpu/src/gpu/GLBackendOutput.cpp | 99 +++++++++++++++++++++-- 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index de8961886b..cb33a930ca 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -36,7 +36,7 @@ Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height)); framebuffer->setRenderBuffer(0, colorTexture); - framebuffer->setDepthStencilBuffer(depthTexture); + framebuffer->setDepthStencilBuffer(depthTexture, depthStencilBufferFormat); return framebuffer; } @@ -54,10 +54,6 @@ uint32 Framebuffer::getFrameCount() const { } } -bool Framebuffer::isEmpty() const { - return (_buffersMask == 0); -} - bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 subresource) const { if (texture.getType() == Texture::TEX_1D) { return false; @@ -161,9 +157,9 @@ int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uin // update the mask int mask = (1<getDepthStencilBufferFormat(); + return _depthStencilBuffer._element; + } else { + return _depthStencilBuffer._element; + } +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 46303b0d81..9253cd021e 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -123,20 +123,24 @@ public: uint32 getFrameCount() const; // Render buffers - int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); void removeRenderBuffers(); uint32 getNumRenderBuffers() const; + const TextureViews& getRenderBuffers() const { return _renderBuffers; } + int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); TexturePointer getRenderBuffer(uint32 slot) const; uint32 getRenderBufferSubresource(uint32 slot) const; - bool setDepthStencilBuffer(const TexturePointer& texture, uint32 subresource = 0); + bool setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); TexturePointer getDepthStencilBuffer() const; uint32 getDepthStencilBufferSubresource() const; + Format getDepthStencilBufferFormat() const; // Properties - uint32 getBuffersMask() const { return _buffersMask; } - bool isEmpty() const; + uint32 getBufferMask() const { return _bufferMask; } + bool isEmpty() const { return (_bufferMask == 0); } + bool hasColor() const { return (getBufferMask() & BUFFER_COLORS); } + bool hasDepthStencil() const { return (getBufferMask() & BUFFER_DEPTHSTENCIL); } bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const; @@ -162,7 +166,7 @@ protected: uint16 _height; uint16 _numSamples; - uint32 _buffersMask; + uint32 _bufferMask; uint32 _frameCount; diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 8865008e49..877ecce950 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -35,15 +35,102 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe // need to have a gpu object? if (!object) { - object = new GLFramebuffer(); - glGenFramebuffers(1, &object->_fbo); + GLuint fbo; + glGenFramebuffers(1, &fbo); CHECK_GL_ERROR(); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + + unsigned int nbColorBuffers = 0; + GLenum colorBuffers[16]; + if (framebuffer.hasColor()) { + static const GLenum colorAttachments[] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, + GL_COLOR_ATTACHMENT4, + GL_COLOR_ATTACHMENT5, + GL_COLOR_ATTACHMENT6, + GL_COLOR_ATTACHMENT7, + GL_COLOR_ATTACHMENT8, + GL_COLOR_ATTACHMENT9, + GL_COLOR_ATTACHMENT10, + GL_COLOR_ATTACHMENT11, + GL_COLOR_ATTACHMENT12, + GL_COLOR_ATTACHMENT13, + GL_COLOR_ATTACHMENT14, + GL_COLOR_ATTACHMENT15 }; + + int unit = 0; + for (auto& b : framebuffer.getRenderBuffers()) { + auto surface = b._texture; + if (surface) { + auto gltexture = GLBackend::syncGPUObject(*surface); + if (gltexture) { + glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[unit], GL_TEXTURE_2D, gltexture->_texture, 0); + } + colorBuffers[nbColorBuffers] = colorAttachments[unit]; + nbColorBuffers++; + unit++; + } + } + } + + if (framebuffer.hasDepthStencil()) { + auto surface = framebuffer.getDepthStencilBuffer(); + if (surface) { + auto gltexture = GLBackend::syncGPUObject(*surface); + if (gltexture) { + if (surface) + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gltexture->_texture, 0); + } + } + } + + // Last but not least, define where we draw + if (nbColorBuffers > 0) { + glDrawBuffers(nbColorBuffers, colorBuffers); + } else { + glDrawBuffer( GL_NONE ); + } + + // Now check for completness + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + bool result = false; + switch (status) { + case GL_FRAMEBUFFER_COMPLETE : + // Success ! + result = true; + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT."; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT."; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER."; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER."; + break; + case GL_FRAMEBUFFER_UNSUPPORTED : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_UNSUPPORTED."; + break; + } + if (!result && fbo) { + glDeleteFramebuffers( 1, &fbo ); + return nullptr; + } + + + // All is green, assign the gpuobject to the Framebuffer + object = new GLFramebuffer(); + object->_fbo = fbo; Backend::setGPUObject(framebuffer, object); } - - CHECK_GL_ERROR(); - return object; } @@ -69,4 +156,4 @@ void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { _output._framebuffer = framebuffer; } } - +