mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
6.0 KiB
145 lines
6.0 KiB
/* |
|
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
This file is part of Magnum. |
|
|
|
Magnum is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU Lesser General Public License version 3 |
|
only, as published by the Free Software Foundation. |
|
|
|
Magnum is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU Lesser General Public License version 3 for more details. |
|
*/ |
|
|
|
#include "Framebuffer.h" |
|
|
|
#include "BufferImage.h" |
|
#include "Context.h" |
|
#include "Extensions.h" |
|
#include "Image.h" |
|
#include "Renderbuffer.h" |
|
#include "Texture.h" |
|
|
|
#include "Implementation/State.h" |
|
#include "Implementation/FramebufferState.h" |
|
|
|
namespace Magnum { |
|
|
|
Framebuffer::RenderbufferImplementation Framebuffer::renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault; |
|
#ifndef MAGNUM_TARGET_GLES |
|
Framebuffer::Texture1DImplementation Framebuffer::texture1DImplementation = &Framebuffer::texture1DImplementationDefault; |
|
#endif |
|
Framebuffer::Texture2DImplementation Framebuffer::texture2DImplementation = &Framebuffer::texture2DImplementationDefault; |
|
Framebuffer::Texture3DImplementation Framebuffer::texture3DImplementation = &Framebuffer::texture3DImplementationDefault; |
|
|
|
Framebuffer::Framebuffer(const Vector2i& viewportPosition, const Vector2i& viewportSize) { |
|
_viewportPosition = viewportPosition; |
|
_viewportSize = viewportSize; |
|
|
|
glGenFramebuffers(1, &_id); |
|
} |
|
|
|
Framebuffer::~Framebuffer() { |
|
/* If bound, remove itself from state */ |
|
Implementation::FramebufferState* state = Context::current()->state()->framebuffer; |
|
if(state->readBinding == _id) state->readBinding = 0; |
|
if(state->drawBinding == _id) state->drawBinding = 0; |
|
|
|
glDeleteFramebuffers(1, &_id); |
|
} |
|
|
|
void Framebuffer::mapForDraw(std::initializer_list<std::pair<GLuint, std::int8_t>> attachments) { |
|
/* Max attachment location */ |
|
std::size_t max = 0; |
|
for(const auto& attachment: attachments) |
|
if(attachment.first > max) max = attachment.first; |
|
|
|
/* Create linear array from associative */ |
|
GLenum* _attachments = new GLenum[max+1]; |
|
std::fill_n(_attachments, max, GL_NONE); |
|
for(const auto& attachment: attachments) |
|
_attachments[attachment.first] = attachment.second < 0 ? GL_NONE : GL_COLOR_ATTACHMENT0 + attachment.second; |
|
|
|
(this->*drawBuffersImplementation)(max+1, _attachments); |
|
delete[] _attachments; |
|
} |
|
|
|
void Framebuffer::attachTexture2D(DepthStencilAttachment depthStencilAttachment, Texture2D* texture, GLint mipLevel) { |
|
/** @todo Check for texture target compatibility */ |
|
(this->*texture2DImplementation)(GLenum(depthStencilAttachment), GLenum(texture->target()), texture->id(), mipLevel); |
|
} |
|
|
|
void Framebuffer::attachTexture2D(std::uint8_t colorAttachment, Texture2D* texture, GLint mipLevel) { |
|
/** @todo Check for texture target compatibility */ |
|
(this->*texture2DImplementation)(GL_COLOR_ATTACHMENT0 + colorAttachment, GLenum(texture->target()), texture->id(), mipLevel); |
|
} |
|
|
|
void Framebuffer::initializeContextBasedFunctionality(Context* context) { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { |
|
Debug() << "Framebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; |
|
|
|
renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; |
|
texture1DImplementation = &Framebuffer::texture1DImplementationDSA; |
|
texture2DImplementation = &Framebuffer::texture2DImplementationDSA; |
|
texture3DImplementation = &Framebuffer::texture3DImplementationDSA; |
|
} |
|
#else |
|
static_cast<void>(context); |
|
#endif |
|
} |
|
|
|
void Framebuffer::renderbufferImplementationDefault(GLenum attachment, Renderbuffer* renderbuffer) { |
|
bindInternal(drawTarget); |
|
glFramebufferRenderbuffer(static_cast<GLenum>(drawTarget), attachment, GL_RENDERBUFFER, renderbuffer->id()); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void Framebuffer::renderbufferImplementationDSA(GLenum attachment, Renderbuffer* renderbuffer) { |
|
glNamedFramebufferRenderbufferEXT(_id, attachment, GL_RENDERBUFFER, renderbuffer->id()); |
|
} |
|
|
|
void Framebuffer::texture1DImplementationDefault(GLenum attachment, Texture1D* texture, GLint mipLevel) { |
|
bindInternal(drawTarget); |
|
glFramebufferTexture1D(static_cast<GLenum>(drawTarget), attachment, static_cast<GLenum>(texture->target()), texture->id(), mipLevel); |
|
} |
|
|
|
void Framebuffer::texture1DImplementationDSA(GLenum attachment, Texture1D* texture, GLint mipLevel) { |
|
glNamedFramebufferTexture1DEXT(_id, attachment, GLenum(texture->target()), texture->id(), mipLevel); |
|
} |
|
#endif |
|
|
|
void Framebuffer::texture2DImplementationDefault(GLenum attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) { |
|
bindInternal(drawTarget); |
|
glFramebufferTexture2D(static_cast<GLenum>(drawTarget), attachment, textureTarget, textureId, mipLevel); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void Framebuffer::texture2DImplementationDSA(GLenum attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) { |
|
glNamedFramebufferTexture2DEXT(_id, attachment, textureTarget, textureId, mipLevel); |
|
} |
|
#endif |
|
|
|
void Framebuffer::texture3DImplementationDefault(GLenum attachment, Texture3D* texture, GLint mipLevel, GLint layer) { |
|
/** @todo Check for texture target compatibility */ |
|
bindInternal(drawTarget); |
|
/** @todo Get some extension wrangler for glFramebufferTexture3D() (extension only) */ |
|
#ifndef MAGNUM_TARGET_GLES |
|
glFramebufferTexture3D(static_cast<GLenum>(drawTarget), attachment, static_cast<GLenum>(texture->target()), texture->id(), mipLevel, layer); |
|
#else |
|
static_cast<void>(attachment); |
|
static_cast<void>(texture); |
|
static_cast<void>(mipLevel); |
|
static_cast<void>(layer); |
|
#endif |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void Framebuffer::texture3DImplementationDSA(GLenum attachment, Texture3D* texture, GLint mipLevel, GLint layer) { |
|
glNamedFramebufferTexture3DEXT(_id, attachment, GLenum(texture->target()), texture->id(), mipLevel, layer); |
|
} |
|
#endif |
|
|
|
}
|
|
|