connecting the dots for a framebuffer GLBackend, need to be tested

This commit is contained in:
Sam Gateau 2015-04-13 12:22:08 -07:00
parent 05689c0413
commit 51ce3129b9
3 changed files with 119 additions and 23 deletions

View file

@ -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<<slot);
_buffersMask = (_buffersMask & ~(mask));
_bufferMask = (_bufferMask & ~(mask));
if (texture) {
_buffersMask |= mask;
_bufferMask |= mask;
}
return slot;
@ -174,7 +170,7 @@ void Framebuffer::removeRenderBuffers() {
return;
}
_buffersMask = _buffersMask & BUFFER_DEPTHSTENCIL;
_bufferMask = _bufferMask & BUFFER_DEPTHSTENCIL;
for (auto renderBuffer : _renderBuffers) {
renderBuffer._texture.reset();
@ -209,7 +205,7 @@ uint32 Framebuffer::getRenderBufferSubresource(uint32 slot) const {
}
}
bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, uint32 subresource) {
bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) {
if (isSwapchain()) {
return false;
}
@ -224,11 +220,11 @@ bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, uint32 su
updateSize(texture);
// assign the new one
_depthStencilBuffer = TextureView(texture, subresource);
_depthStencilBuffer = TextureView(texture, subresource, format);
_buffersMask = ( _buffersMask & ~BUFFER_DEPTHSTENCIL);
_bufferMask = ( _bufferMask & ~BUFFER_DEPTHSTENCIL);
if (texture) {
_buffersMask |= BUFFER_DEPTHSTENCIL;
_bufferMask |= BUFFER_DEPTHSTENCIL;
}
return true;
@ -249,3 +245,12 @@ uint32 Framebuffer::getDepthStencilBufferSubresource() const {
return _depthStencilBuffer._subresource;
}
}
Format Framebuffer::getDepthStencilBufferFormat() const {
if (isSwapchain()) {
// return getSwapchain()->getDepthStencilBufferFormat();
return _depthStencilBuffer._element;
} else {
return _depthStencilBuffer._element;
}
}

View file

@ -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;

View file

@ -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;
}
}