OPENGL: Introduce abstraction for framebuffer.

This allows us to use various framebuffer settings easily. Now the GPU
accelerated CLUT8 surface implementation does not need to query former
framebuffer state anymore.
This commit is contained in:
Johannes Schickel 2016-01-04 10:18:15 +01:00
parent 5498982a37
commit c4e65732be
9 changed files with 488 additions and 132 deletions

View file

@ -0,0 +1,251 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "backends/graphics/opengl/framebuffer.h"
#include "backends/graphics/opengl/texture.h"
namespace OpenGL {
Framebuffer::Framebuffer()
: _viewport(), _projectionMatrix(), _isActive(false), _clearColor(),
_blendState(false), _scissorTestState(false), _scissorBox() {
}
void Framebuffer::activate() {
_isActive = true;
applyViewport();
applyClearColor();
applyBlendState();
applyScissorTestState();
applyScissorBox();
}
void Framebuffer::deactivate() {
_isActive = false;
}
void Framebuffer::setClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
_clearColor[0] = r;
_clearColor[1] = g;
_clearColor[2] = b;
_clearColor[3] = a;
// Directly apply changes when we are active.
if (isActive()) {
applyClearColor();
}
}
void Framebuffer::enableBlend(bool enable) {
_blendState = enable;
// Directly apply changes when we are active.
if (isActive()) {
applyBlendState();
}
}
void Framebuffer::enableScissorTest(bool enable) {
_scissorTestState = enable;
// Directly apply changes when we are active.
if (isActive()) {
applyScissorTestState();
}
}
void Framebuffer::setScissorBox(GLint x, GLint y, GLsizei w, GLsizei h) {
_scissorBox[0] = x;
_scissorBox[1] = y;
_scissorBox[2] = w;
_scissorBox[3] = h;
// Directly apply changes when we are active.
if (isActive()) {
applyScissorBox();
}
}
void Framebuffer::applyViewport() {
GL_CALL(glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]));
}
void Framebuffer::applyClearColor() {
GL_CALL(glClearColor(_clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]));
}
void Framebuffer::applyBlendState() {
if (_blendState) {
GL_CALL(glEnable(GL_BLEND));
} else {
GL_CALL(glDisable(GL_BLEND));
}
}
void Framebuffer::applyScissorTestState() {
if (_scissorTestState) {
GL_CALL(glEnable(GL_SCISSOR_TEST));
} else {
GL_CALL(glDisable(GL_SCISSOR_TEST));
}
}
void Framebuffer::applyScissorBox() {
GL_CALL(glScissor(_scissorBox[0], _scissorBox[1], _scissorBox[2], _scissorBox[3]));
}
//
// Backbuffer implementation
//
void Backbuffer::activate() {
Framebuffer::activate();
#if !USE_FORCED_GLES
if (g_context.framebufferObjectSupported) {
GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
}
#endif
}
void Backbuffer::setDimensions(uint width, uint height) {
// Set viewport dimensions.
_viewport[0] = 0;
_viewport[1] = 0;
_viewport[2] = width;
_viewport[3] = height;
// Setup orthogonal projection matrix.
_projectionMatrix[ 0] = 2.0f / width;
_projectionMatrix[ 1] = 0.0f;
_projectionMatrix[ 2] = 0.0f;
_projectionMatrix[ 3] = 0.0f;
_projectionMatrix[ 4] = 0.0f;
_projectionMatrix[ 5] = -2.0f / height;
_projectionMatrix[ 6] = 0.0f;
_projectionMatrix[ 7] = 0.0f;
_projectionMatrix[ 8] = 0.0f;
_projectionMatrix[ 9] = 0.0f;
_projectionMatrix[10] = 0.0f;
_projectionMatrix[11] = 0.0f;
_projectionMatrix[12] = -1.0f;
_projectionMatrix[13] = 1.0f;
_projectionMatrix[14] = 0.0f;
_projectionMatrix[15] = 1.0f;
// Directly apply changes when we are active.
if (isActive()) {
applyViewport();
}
}
//
// Render to texture target implementation
//
#if !USE_FORCED_GLES
TextureTarget::TextureTarget()
: _texture(new GLTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE)), _glFBO(0), _needUpdate(true) {
}
TextureTarget::~TextureTarget() {
delete _texture;
GL_CALL_SAFE(glDeleteFramebuffers, (1, &_glFBO));
}
void TextureTarget::activate() {
Framebuffer::activate();
// Allocate framebuffer object if necessary.
if (!_glFBO) {
GL_CALL(glGenFramebuffers(1, &_glFBO));
_needUpdate = true;
}
// Attach destination texture to FBO.
GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO));
// If required attach texture to FBO.
if (_needUpdate) {
GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getGLTexture(), 0));
_needUpdate = false;
}
}
void TextureTarget::destroy() {
GL_CALL(glDeleteFramebuffers(1, &_glFBO));
_glFBO = 0;
_texture->destroy();
}
void TextureTarget::create() {
_texture->create();
_needUpdate = true;
}
void TextureTarget::setSize(uint width, uint height) {
_texture->setSize(width, height);
const uint texWidth = _texture->getWidth();
const uint texHeight = _texture->getHeight();
// Set viewport dimensions.
_viewport[0] = 0;
_viewport[1] = 0;
_viewport[2] = texWidth;
_viewport[3] = texHeight;
// Setup orthogonal projection matrix.
_projectionMatrix[ 0] = 2.0f / texWidth;
_projectionMatrix[ 1] = 0.0f;
_projectionMatrix[ 2] = 0.0f;
_projectionMatrix[ 3] = 0.0f;
_projectionMatrix[ 4] = 0.0f;
_projectionMatrix[ 5] = 2.0f / texHeight;
_projectionMatrix[ 6] = 0.0f;
_projectionMatrix[ 7] = 0.0f;
_projectionMatrix[ 8] = 0.0f;
_projectionMatrix[ 9] = 0.0f;
_projectionMatrix[10] = 0.0f;
_projectionMatrix[11] = 0.0f;
_projectionMatrix[12] = -1.0f;
_projectionMatrix[13] = -1.0f;
_projectionMatrix[14] = 0.0f;
_projectionMatrix[15] = 1.0f;
// Directly apply changes when we are active.
if (isActive()) {
applyViewport();
}
}
#endif // !USE_FORCED_GLES
} // End of namespace OpenGL