2016-01-04 10:18:15 +01:00
|
|
|
/* 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"
|
2016-02-28 18:15:00 +01:00
|
|
|
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
2016-01-04 10:18:15 +01:00
|
|
|
|
|
|
|
namespace OpenGL {
|
|
|
|
|
|
|
|
Framebuffer::Framebuffer()
|
|
|
|
: _viewport(), _projectionMatrix(), _isActive(false), _clearColor(),
|
2018-08-23 07:19:12 +02:00
|
|
|
_blendState(kBlendModeDisabled), _scissorTestState(false), _scissorBox() {
|
2016-01-04 10:18:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Framebuffer::activate() {
|
|
|
|
_isActive = true;
|
|
|
|
|
|
|
|
applyViewport();
|
2016-01-04 11:38:21 +01:00
|
|
|
applyProjectionMatrix();
|
2016-01-04 10:18:15 +01:00
|
|
|
applyClearColor();
|
|
|
|
applyBlendState();
|
|
|
|
applyScissorTestState();
|
|
|
|
applyScissorBox();
|
2016-02-28 17:10:02 +01:00
|
|
|
|
|
|
|
activateInternal();
|
2016-01-04 10:18:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Framebuffer::deactivate() {
|
|
|
|
_isActive = false;
|
2016-02-28 17:10:02 +01:00
|
|
|
|
|
|
|
deactivateInternal();
|
2016-01-04 10:18:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-23 07:19:12 +02:00
|
|
|
void Framebuffer::enableBlend(BlendMode mode) {
|
|
|
|
_blendState = mode;
|
2016-01-04 10:18:15 +01:00
|
|
|
|
|
|
|
// 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]));
|
|
|
|
}
|
|
|
|
|
2016-01-04 11:38:21 +01:00
|
|
|
void Framebuffer::applyProjectionMatrix() {
|
2016-02-28 17:02:19 +01:00
|
|
|
g_context.getActivePipeline()->setProjectionMatrix(_projectionMatrix);
|
2016-01-04 11:38:21 +01:00
|
|
|
}
|
|
|
|
|
2016-01-04 10:18:15 +01:00
|
|
|
void Framebuffer::applyClearColor() {
|
|
|
|
GL_CALL(glClearColor(_clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Framebuffer::applyBlendState() {
|
2018-08-23 07:19:12 +02:00
|
|
|
switch (_blendState) {
|
|
|
|
case kBlendModeDisabled:
|
|
|
|
GL_CALL(glDisable(GL_BLEND));
|
|
|
|
break;
|
|
|
|
case kBlendModeTraditionalTransparency:
|
|
|
|
GL_CALL(glEnable(GL_BLEND));
|
|
|
|
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
|
|
|
break;
|
|
|
|
case kBlendModePremultipliedTransparency:
|
|
|
|
GL_CALL(glEnable(GL_BLEND));
|
|
|
|
GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
|
|
|
break;
|
2016-01-04 10:18:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
//
|
|
|
|
|
2016-02-28 17:10:02 +01:00
|
|
|
void Backbuffer::activateInternal() {
|
2016-01-04 10:18:15 +01:00
|
|
|
#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();
|
2016-01-04 11:38:21 +01:00
|
|
|
applyProjectionMatrix();
|
2016-01-04 10:18:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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));
|
|
|
|
}
|
|
|
|
|
2016-02-28 17:10:02 +01:00
|
|
|
void TextureTarget::activateInternal() {
|
2016-01-04 10:18:15 +01:00
|
|
|
// 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();
|
2016-01-04 11:38:21 +01:00
|
|
|
applyProjectionMatrix();
|
2016-01-04 10:18:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // !USE_FORCED_GLES
|
|
|
|
|
|
|
|
} // End of namespace OpenGL
|