mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-01 06:14:07 +00:00
BACKENDS: Made code less different in SDL platform backend
This commit is contained in:
parent
a3a42ee306
commit
6aa7cf6025
@ -24,6 +24,7 @@
|
||||
#define BACKEND_EVENTS_SDL_H
|
||||
|
||||
#include "backends/platform/sdl/sdl-sys.h"
|
||||
#include "backends/graphics/sdl/sdl-graphics.h"
|
||||
#include "backends/graphics3d/sdl/sdl-graphics3d.h"
|
||||
|
||||
#include "common/events.h"
|
||||
|
186
backends/graphics/opengl/context.cpp
Normal file
186
backends/graphics/opengl/context.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/* 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/opengl-sys.h"
|
||||
#include "backends/graphics/opengl/opengl-graphics.h"
|
||||
#include "backends/graphics/opengl/shader.h"
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
|
||||
#include "common/tokenizer.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
void Context::reset() {
|
||||
maxTextureSize = 0;
|
||||
|
||||
NPOTSupported = false;
|
||||
shadersSupported = false;
|
||||
multitextureSupported = false;
|
||||
framebufferObjectSupported = false;
|
||||
|
||||
#define GL_FUNC_DEF(ret, name, param) name = nullptr;
|
||||
#include "backends/graphics/opengl/opengl-func.h"
|
||||
#undef GL_FUNC_DEF
|
||||
|
||||
activePipeline = nullptr;
|
||||
}
|
||||
|
||||
Pipeline *Context::setPipeline(Pipeline *pipeline) {
|
||||
Pipeline *oldPipeline = activePipeline;
|
||||
if (oldPipeline) {
|
||||
oldPipeline->deactivate();
|
||||
}
|
||||
|
||||
activePipeline = pipeline;
|
||||
if (activePipeline) {
|
||||
activePipeline->activate();
|
||||
}
|
||||
|
||||
return oldPipeline;
|
||||
}
|
||||
|
||||
Context g_context;
|
||||
|
||||
void OpenGLGraphicsManager::setContextType(ContextType type) {
|
||||
#if USE_FORCED_GL
|
||||
type = kContextGL;
|
||||
#elif USE_FORCED_GLES
|
||||
type = kContextGLES;
|
||||
#elif USE_FORCED_GLES2
|
||||
type = kContextGLES2;
|
||||
#endif
|
||||
|
||||
g_context.type = type;
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::initializeGLContext() {
|
||||
// Initialize default state.
|
||||
g_context.reset();
|
||||
|
||||
// Load all functions.
|
||||
// We use horrible trickery to silence C++ compilers.
|
||||
// See backends/plugins/sdl/sdl-provider.cpp for more information.
|
||||
assert(sizeof(void (*)()) == sizeof(void *));
|
||||
|
||||
#define LOAD_FUNC(name, loadName) { \
|
||||
void *fn = getProcAddress(#loadName); \
|
||||
memcpy(&g_context.name, &fn, sizeof(fn)); \
|
||||
}
|
||||
|
||||
#define GL_EXT_FUNC_DEF(ret, name, param) LOAD_FUNC(name, name)
|
||||
|
||||
#ifdef USE_BUILTIN_OPENGL
|
||||
#define GL_FUNC_DEF(ret, name, param) g_context.name = &name
|
||||
#define GL_FUNC_2_DEF GL_FUNC_DEF
|
||||
#else
|
||||
#define GL_FUNC_DEF GL_EXT_FUNC_DEF
|
||||
#define GL_FUNC_2_DEF(ret, name, extName, param) \
|
||||
if (g_context.type == kContextGL) { \
|
||||
LOAD_FUNC(name, extName); \
|
||||
} else { \
|
||||
LOAD_FUNC(name, name); \
|
||||
}
|
||||
#endif
|
||||
#include "backends/graphics/opengl/opengl-func.h"
|
||||
#undef GL_FUNC_2_DEF
|
||||
#undef GL_FUNC_DEF
|
||||
#undef GL_EXT_FUNC_DEF
|
||||
#undef LOAD_FUNC
|
||||
|
||||
// Obtain maximum texture size.
|
||||
GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_context.maxTextureSize));
|
||||
debug(5, "OpenGL maximum texture size: %d", g_context.maxTextureSize);
|
||||
|
||||
const char *extString = (const char *)g_context.glGetString(GL_EXTENSIONS);
|
||||
debug(5, "OpenGL extensions: %s", extString);
|
||||
|
||||
bool ARBShaderObjects = false;
|
||||
bool ARBShadingLanguage100 = false;
|
||||
bool ARBVertexShader = false;
|
||||
bool ARBFragmentShader = false;
|
||||
|
||||
Common::StringTokenizer tokenizer(extString, " ");
|
||||
while (!tokenizer.empty()) {
|
||||
Common::String token = tokenizer.nextToken();
|
||||
|
||||
if (token == "GL_ARB_texture_non_power_of_two" || token == "GL_OES_texture_npot") {
|
||||
g_context.NPOTSupported = true;
|
||||
} else if (token == "GL_ARB_shader_objects") {
|
||||
ARBShaderObjects = true;
|
||||
} else if (token == "GL_ARB_shading_language_100") {
|
||||
ARBShadingLanguage100 = true;
|
||||
} else if (token == "GL_ARB_vertex_shader") {
|
||||
ARBVertexShader = true;
|
||||
} else if (token == "GL_ARB_fragment_shader") {
|
||||
ARBFragmentShader = true;
|
||||
} else if (token == "GL_ARB_multitexture") {
|
||||
g_context.multitextureSupported = true;
|
||||
} else if (token == "GL_EXT_framebuffer_object") {
|
||||
g_context.framebufferObjectSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_context.type == kContextGLES2) {
|
||||
// GLES2 always has (limited) NPOT support.
|
||||
g_context.NPOTSupported = true;
|
||||
|
||||
// GLES2 always has shader support.
|
||||
g_context.shadersSupported = true;
|
||||
|
||||
// GLES2 always has multi texture support.
|
||||
g_context.multitextureSupported = true;
|
||||
|
||||
// GLES2 always has FBO support.
|
||||
g_context.framebufferObjectSupported = true;
|
||||
} else {
|
||||
g_context.shadersSupported = ARBShaderObjects & ARBShadingLanguage100 & ARBVertexShader & ARBFragmentShader;
|
||||
}
|
||||
|
||||
// Log context type.
|
||||
switch (g_context.type) {
|
||||
case kContextGL:
|
||||
debug(5, "OpenGL: GL context initialized");
|
||||
break;
|
||||
|
||||
case kContextGLES:
|
||||
debug(5, "OpenGL: GLES context initialized");
|
||||
break;
|
||||
|
||||
case kContextGLES2:
|
||||
debug(5, "OpenGL: GLES2 context initialized");
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("OpenGL: Unknown context initialized");
|
||||
break;
|
||||
}
|
||||
|
||||
// Log features supported by GL context.
|
||||
debug(5, "OpenGL: NPOT texture support: %d", g_context.NPOTSupported);
|
||||
debug(5, "OpenGL: Shader support: %d", g_context.shadersSupported);
|
||||
debug(5, "OpenGL: Multitexture support: %d", g_context.multitextureSupported);
|
||||
debug(5, "OpenGL: FBO support: %d", g_context.framebufferObjectSupported);
|
||||
}
|
||||
|
||||
} // End of namespace OpenGL
|
67
backends/graphics/opengl/debug.cpp
Normal file
67
backends/graphics/opengl/debug.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/* 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/debug.h"
|
||||
#include "backends/graphics/opengl/opengl-sys.h"
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#ifdef OPENGL_DEBUG
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
namespace {
|
||||
Common::String getGLErrStr(GLenum error) {
|
||||
switch (error) {
|
||||
case GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM";
|
||||
case GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE";
|
||||
case GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION";
|
||||
case GL_STACK_OVERFLOW:
|
||||
return "GL_STACK_OVERFLOW";
|
||||
case GL_STACK_UNDERFLOW:
|
||||
return "GL_STACK_UNDERFLOW";
|
||||
case GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Common::String::format("(Unknown GL error code 0x%X)", error);
|
||||
}
|
||||
} // End of anonymous namespace
|
||||
|
||||
void checkGLError(const char *expr, const char *file, int line) {
|
||||
GLenum error;
|
||||
|
||||
while ((error = g_context.glGetError()) != GL_NO_ERROR) {
|
||||
// We cannot use error here because we do not know whether we have a
|
||||
// working screen or not.
|
||||
warning("GL ERROR: %s on %s (%s:%d)", getGLErrStr(error).c_str(), expr, file, line);
|
||||
}
|
||||
}
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
39
backends/graphics/opengl/debug.h
Normal file
39
backends/graphics/opengl/debug.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_DEBUG_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_DEBUG_H
|
||||
|
||||
#define OPENGL_DEBUG
|
||||
|
||||
#ifdef OPENGL_DEBUG
|
||||
|
||||
namespace OpenGL {
|
||||
void checkGLError(const char *expr, const char *file, int line);
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#define GL_WRAP_DEBUG(call, name) do { (call); OpenGL::checkGLError(#name, __FILE__, __LINE__); } while (false)
|
||||
#else
|
||||
#define GL_WRAP_DEBUG(call, name) do { (call); } while (false)
|
||||
#endif
|
||||
|
||||
#endif
|
269
backends/graphics/opengl/framebuffer.cpp
Normal file
269
backends/graphics/opengl/framebuffer.cpp
Normal file
@ -0,0 +1,269 @@
|
||||
/* 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"
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
Framebuffer::Framebuffer()
|
||||
: _viewport(), _projectionMatrix(), _isActive(false), _clearColor(),
|
||||
_blendState(kBlendModeDisabled), _scissorTestState(false), _scissorBox() {
|
||||
}
|
||||
|
||||
void Framebuffer::activate() {
|
||||
_isActive = true;
|
||||
|
||||
applyViewport();
|
||||
applyProjectionMatrix();
|
||||
applyClearColor();
|
||||
applyBlendState();
|
||||
applyScissorTestState();
|
||||
applyScissorBox();
|
||||
|
||||
activateInternal();
|
||||
}
|
||||
|
||||
void Framebuffer::deactivate() {
|
||||
_isActive = false;
|
||||
|
||||
deactivateInternal();
|
||||
}
|
||||
|
||||
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(BlendMode mode) {
|
||||
_blendState = mode;
|
||||
|
||||
// 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::applyProjectionMatrix() {
|
||||
g_context.getActivePipeline()->setProjectionMatrix(_projectionMatrix);
|
||||
}
|
||||
|
||||
void Framebuffer::applyClearColor() {
|
||||
GL_CALL(glClearColor(_clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]));
|
||||
}
|
||||
|
||||
void Framebuffer::applyBlendState() {
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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::activateInternal() {
|
||||
#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();
|
||||
applyProjectionMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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::activateInternal() {
|
||||
// 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();
|
||||
applyProjectionMatrix();
|
||||
}
|
||||
}
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
198
backends/graphics/opengl/framebuffer.h
Normal file
198
backends/graphics/opengl/framebuffer.h
Normal file
@ -0,0 +1,198 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_FRAMEBUFFER_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_FRAMEBUFFER_H
|
||||
|
||||
#include "backends/graphics/opengl/opengl-sys.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
/**
|
||||
* Object describing a framebuffer OpenGL can render to.
|
||||
*/
|
||||
class Framebuffer {
|
||||
friend class Pipeline;
|
||||
public:
|
||||
Framebuffer();
|
||||
virtual ~Framebuffer() {};
|
||||
|
||||
public:
|
||||
enum BlendMode {
|
||||
/**
|
||||
* Newly drawn pixels overwrite the existing contents of the framebuffer
|
||||
* without mixing with them
|
||||
*/
|
||||
kBlendModeDisabled,
|
||||
|
||||
/**
|
||||
* Newly drawn pixels mix with the framebuffer based on their alpha value
|
||||
* for transparency.
|
||||
*/
|
||||
kBlendModeTraditionalTransparency,
|
||||
|
||||
/**
|
||||
* Newly drawn pixels mix with the framebuffer based on their alpha value
|
||||
* for transparency.
|
||||
*
|
||||
* Requires the image data being drawn to have its color values pre-multipled
|
||||
* with the alpha value.
|
||||
*/
|
||||
kBlendModePremultipliedTransparency
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the clear color of the framebuffer.
|
||||
*/
|
||||
void setClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
|
||||
/**
|
||||
* Enable/disable GL_BLEND.
|
||||
*/
|
||||
void enableBlend(BlendMode mode);
|
||||
|
||||
/**
|
||||
* Enable/disable GL_SCISSOR_TEST.
|
||||
*/
|
||||
void enableScissorTest(bool enable);
|
||||
|
||||
/**
|
||||
* Set scissor box dimensions.
|
||||
*/
|
||||
void setScissorBox(GLint x, GLint y, GLsizei w, GLsizei h);
|
||||
|
||||
/**
|
||||
* Obtain projection matrix of the framebuffer.
|
||||
*/
|
||||
const GLfloat *getProjectionMatrix() const { return _projectionMatrix; }
|
||||
protected:
|
||||
bool isActive() const { return _isActive; }
|
||||
|
||||
GLint _viewport[4];
|
||||
void applyViewport();
|
||||
|
||||
GLfloat _projectionMatrix[4*4];
|
||||
void applyProjectionMatrix();
|
||||
|
||||
/**
|
||||
* Activate framebuffer.
|
||||
*
|
||||
* This is supposed to set all state associated with the framebuffer.
|
||||
*/
|
||||
virtual void activateInternal() = 0;
|
||||
|
||||
/**
|
||||
* Deactivate framebuffer.
|
||||
*
|
||||
* This is supposed to make any cleanup required when unbinding the
|
||||
* framebuffer.
|
||||
*/
|
||||
virtual void deactivateInternal() {}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Accessor to activate framebuffer for pipeline.
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/**
|
||||
* Accessor to deactivate framebuffer from pipeline.
|
||||
*/
|
||||
void deactivate();
|
||||
|
||||
private:
|
||||
bool _isActive;
|
||||
|
||||
GLfloat _clearColor[4];
|
||||
void applyClearColor();
|
||||
|
||||
BlendMode _blendState;
|
||||
void applyBlendState();
|
||||
|
||||
bool _scissorTestState;
|
||||
void applyScissorTestState();
|
||||
|
||||
GLint _scissorBox[4];
|
||||
void applyScissorBox();
|
||||
};
|
||||
|
||||
/**
|
||||
* Default back buffer implementation.
|
||||
*/
|
||||
class Backbuffer : public Framebuffer {
|
||||
public:
|
||||
/**
|
||||
* Set the dimensions (a.k.a. size) of the back buffer.
|
||||
*/
|
||||
void setDimensions(uint width, uint height);
|
||||
|
||||
protected:
|
||||
virtual void activateInternal();
|
||||
};
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
class GLTexture;
|
||||
|
||||
/**
|
||||
* Render to texture framebuffer implementation.
|
||||
*
|
||||
* This target allows to render to a texture, which can then be used for
|
||||
* further rendering.
|
||||
*/
|
||||
class TextureTarget : public Framebuffer {
|
||||
public:
|
||||
TextureTarget();
|
||||
virtual ~TextureTarget();
|
||||
|
||||
/**
|
||||
* Notify that the GL context is about to be destroyed.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Notify that the GL context has been created.
|
||||
*/
|
||||
void create();
|
||||
|
||||
/**
|
||||
* Set size of the texture target.
|
||||
*/
|
||||
void setSize(uint width, uint height);
|
||||
|
||||
/**
|
||||
* Query pointer to underlying GL texture.
|
||||
*/
|
||||
GLTexture *getTexture() const { return _texture; }
|
||||
|
||||
protected:
|
||||
virtual void activateInternal();
|
||||
|
||||
private:
|
||||
GLTexture *_texture;
|
||||
GLuint _glFBO;
|
||||
bool _needUpdate;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
262
backends/graphics/opengl/opengl-defs.h
Normal file
262
backends/graphics/opengl/opengl-defs.h
Normal file
@ -0,0 +1,262 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This file is based on Mesa 3-D's gl.h and GLES/gl.h from Khronos Registry.
|
||||
*
|
||||
* Mesa 3-D's gl.h file is distributed under the following license:
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
|
||||
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
* GLES/gl.h from Khronos Registry is distributed under the following license:
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
* 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_DEFS_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_OPENGL_DEFS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
/*
|
||||
* Datatypes
|
||||
*/
|
||||
typedef uint GLenum;
|
||||
typedef uint8 GLboolean;
|
||||
typedef uint GLbitfield;
|
||||
typedef void GLvoid;
|
||||
typedef int8 GLbyte; /* 1-byte signed */
|
||||
typedef int16 GLshort; /* 2-byte signed */
|
||||
typedef int32 GLint; /* 4-byte signed */
|
||||
typedef uint8 GLubyte; /* 1-byte unsigned */
|
||||
typedef uint16 GLushort; /* 2-byte unsigned */
|
||||
typedef uint32 GLuint; /* 4-byte unsigned */
|
||||
typedef int32 GLsizei; /* 4-byte signed */
|
||||
typedef float GLfloat; /* single precision float */
|
||||
typedef float GLclampf; /* single precision float in [0,1] */
|
||||
typedef double GLdouble; /* double precision float */
|
||||
typedef double GLclampd; /* double precision float in [0,1] */
|
||||
typedef char GLchar;
|
||||
#if defined(MACOSX)
|
||||
typedef void *GLhandleARB;
|
||||
#else
|
||||
typedef uint GLhandleARB;
|
||||
#endif
|
||||
|
||||
// This is an addition from us to alias ARB shader object extensions to
|
||||
// OpenGL (ES) 2.0 style functions. It only works when GLhandleARB and GLuint
|
||||
// are type compatible.
|
||||
typedef GLhandleARB GLprogram;
|
||||
typedef GLhandleARB GLshader;
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
/* Boolean constants */
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
|
||||
/* StringName */
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
|
||||
/* ErrorCode */
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_INVALID_ENUM 0x0500
|
||||
#define GL_INVALID_VALUE 0x0501
|
||||
#define GL_INVALID_OPERATION 0x0502
|
||||
#define GL_STACK_OVERFLOW 0x0503
|
||||
#define GL_STACK_UNDERFLOW 0x0504
|
||||
#define GL_OUT_OF_MEMORY 0x0505
|
||||
|
||||
/* ClearBufferMask */
|
||||
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
||||
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
|
||||
/* Scissor box */
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
|
||||
/* MatrixMode */
|
||||
#define GL_MATRIX_MODE 0x0BA0
|
||||
#define GL_MODELVIEW 0x1700
|
||||
#define GL_PROJECTION 0x1701
|
||||
#define GL_TEXTURE 0x1702
|
||||
|
||||
/* EnableCap */
|
||||
#define GL_FOG 0x0B60
|
||||
#define GL_LIGHTING 0x0B50
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_ALPHA_TEST 0x0BC0
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_DITHER 0x0BD0
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#define GL_COLOR_ARRAY 0x8076
|
||||
#define GL_TEXTURE_COORD_ARRAY 0x8078
|
||||
|
||||
/* ShadingModel */
|
||||
#define GL_FLAT 0x1D00
|
||||
#define GL_SMOOTH 0x1D01
|
||||
|
||||
/* HintMode */
|
||||
#define GL_DONT_CARE 0x1100
|
||||
#define GL_FASTEST 0x1101
|
||||
#define GL_NICEST 0x1102
|
||||
|
||||
/* HintTarget */
|
||||
#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
|
||||
#define GL_POINT_SMOOTH_HINT 0x0C51
|
||||
#define GL_LINE_SMOOTH_HINT 0x0C52
|
||||
#define GL_FOG_HINT 0x0C54
|
||||
#define GL_GENERATE_MIPMAP_HINT 0x8192
|
||||
|
||||
/* BlendingFactorDest */
|
||||
#define GL_ZERO 0
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_COLOR 0x0300
|
||||
#define GL_ONE_MINUS_SRC_COLOR 0x0301
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_DST_ALPHA 0x0304
|
||||
#define GL_ONE_MINUS_DST_ALPHA 0x0305
|
||||
|
||||
/* BlendingFactorSrc */
|
||||
/* GL_ZERO */
|
||||
/* GL_ONE */
|
||||
#define GL_DST_COLOR 0x0306
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x0307
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
/* GL_SRC_ALPHA */
|
||||
/* GL_ONE_MINUS_SRC_ALPHA */
|
||||
/* GL_DST_ALPHA */
|
||||
/* GL_ONE_MINUS_DST_ALPHA */
|
||||
|
||||
/* PixelFormat */
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_BGR 0x80E0
|
||||
#define GL_BGRA 0x80E1
|
||||
|
||||
#define GL_RED 0x1903
|
||||
#define GL_R8 0x8229
|
||||
|
||||
/* PixelStoreParameter */
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
|
||||
/* DataType */
|
||||
#define GL_BYTE 0x1400
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_SHORT 0x1402
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FIXED 0x140C
|
||||
|
||||
/* PixelType */
|
||||
/* GL_UNSIGNED_BYTE */
|
||||
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
|
||||
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
||||
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
||||
|
||||
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
|
||||
#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
|
||||
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
|
||||
#define GL_UNSIGNED_INT_8_8_8_8 0x8035
|
||||
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
|
||||
|
||||
/* Implementation limits */
|
||||
#define GL_MAX_TEXTURE_SIZE 0x0D33
|
||||
|
||||
/* TextureMagFilter */
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
|
||||
/* TextureParameterName */
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
|
||||
/* TextureWrapMode */
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
|
||||
/* BeginMode */
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_LOOP 0x0002
|
||||
#define GL_LINE_STRIP 0x0003
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRIANGLE_FAN 0x0006
|
||||
|
||||
/* Shaders */
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
|
||||
/* Programs */
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
|
||||
/* Textures */
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
|
||||
/* GetPName */
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_FRAMEBUFFER_BINDING 0x8CA6
|
||||
|
||||
/* Framebuffer objects */
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
|
||||
#endif
|
153
backends/graphics/opengl/opengl-func.h
Normal file
153
backends/graphics/opengl/opengl-func.h
Normal file
@ -0,0 +1,153 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This file is based on Mesa 3-D's gl.h and GLES/gl.h from Khronos Registry.
|
||||
*
|
||||
* Mesa 3-D's gl.h file is distributed under the following license:
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
|
||||
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
* GLES/gl.h from Khronos Registry is distributed under the following license:
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
* 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is a template file to be used inside specific locations in the
|
||||
* OpenGL graphics code. It is not to be included otherwise. It intentionally
|
||||
* does not contain include guards because it can be required to include it
|
||||
* multiple times in a source file.
|
||||
*
|
||||
* Functions are defined by three different user supplied macros:
|
||||
* GL_FUNC_DEF: Define a (builtin) OpenGL (ES) function.
|
||||
* GL_FUNC_2_DEF: Define a OpenGL (ES) 2.0 function which can be provided by
|
||||
* extensions in OpenGL 1.x contexts.
|
||||
* GL_EXT_FUNC_DEF: Define an OpenGL (ES) extension function.
|
||||
*/
|
||||
|
||||
#if !defined(GL_FUNC_2_DEF)
|
||||
#define GL_FUNC_2_DEF(ret, name, extName, param) GL_FUNC_DEF(ret, name, param)
|
||||
#define DEFINED_GL_FUNC_2_DEF
|
||||
#endif
|
||||
|
||||
#if !defined(GL_EXT_FUNC_DEF)
|
||||
#define GL_EXT_FUNC_DEF(ret, name, param) GL_FUNC_DEF(ret, name, param)
|
||||
#define DEFINED_GL_EXT_FUNC_DEF
|
||||
#endif
|
||||
|
||||
GL_FUNC_DEF(void, glEnable, (GLenum cap));
|
||||
GL_FUNC_DEF(void, glDisable, (GLenum cap));
|
||||
GL_FUNC_DEF(GLboolean, glIsEnabled, (GLenum cap));
|
||||
GL_FUNC_DEF(void, glClear, (GLbitfield mask));
|
||||
GL_FUNC_DEF(void, glColor4f, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha));
|
||||
GL_FUNC_DEF(void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
GL_FUNC_DEF(void, glMatrixMode, (GLenum mode));
|
||||
GL_FUNC_DEF(void, glLoadIdentity, ());
|
||||
GL_FUNC_DEF(void, glLoadMatrixf, (const GLfloat *m));
|
||||
GL_FUNC_DEF(void, glShadeModel, (GLenum mode));
|
||||
GL_FUNC_DEF(void, glHint, (GLenum target, GLenum mode));
|
||||
GL_FUNC_DEF(void, glClearColor, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
|
||||
GL_FUNC_DEF(void, glBlendFunc, (GLenum sfactor, GLenum dfactor));
|
||||
GL_FUNC_DEF(void, glEnableClientState, (GLenum array));
|
||||
GL_FUNC_DEF(void, glPixelStorei, (GLenum pname, GLint param));
|
||||
GL_FUNC_DEF(void, glScissor, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
GL_FUNC_DEF(void, glReadPixels, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels));
|
||||
GL_FUNC_DEF(void, glGetIntegerv, (GLenum pname, GLint *params));
|
||||
GL_FUNC_DEF(void, glDeleteTextures, (GLsizei n, const GLuint *textures));
|
||||
GL_FUNC_DEF(void, glGenTextures, (GLsizei n, GLuint *textures));
|
||||
GL_FUNC_DEF(void, glBindTexture, (GLenum target, GLuint texture));
|
||||
GL_FUNC_DEF(void, glTexParameteri, (GLenum target, GLenum pname, GLint param));
|
||||
GL_FUNC_DEF(void, glTexImage2D, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels));
|
||||
GL_FUNC_DEF(void, glTexCoordPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer));
|
||||
GL_FUNC_DEF(void, glVertexPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer));
|
||||
GL_FUNC_DEF(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count));
|
||||
GL_FUNC_DEF(void, glTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels));
|
||||
GL_FUNC_DEF(const GLubyte *, glGetString, (GLenum name));
|
||||
GL_FUNC_DEF(GLenum, glGetError, ());
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
GL_FUNC_2_DEF(void, glEnableVertexAttribArray, glEnableVertexAttribArrayARB, (GLuint index));
|
||||
GL_FUNC_2_DEF(void, glDisableVertexAttribArray, glDisableVertexAttribArrayARB, (GLuint index));
|
||||
GL_FUNC_2_DEF(void, glUniform1i, glUniform1iARB, (GLint location, GLint v0));
|
||||
GL_FUNC_2_DEF(void, glUniform1f, glUniform1fARB, (GLint location, GLfloat v0));
|
||||
GL_FUNC_2_DEF(void, glUniformMatrix4fv, glUniformMatrix4fvARB, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value));
|
||||
GL_FUNC_2_DEF(void, glVertexAttrib4f, glVertexAttrib4fARB, (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w));
|
||||
GL_FUNC_2_DEF(void, glVertexAttribPointer, glVertexAttribPointerARB, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer));
|
||||
|
||||
GL_FUNC_2_DEF(GLprogram, glCreateProgram, glCreateProgramObjectARB, ());
|
||||
GL_FUNC_2_DEF(void, glDeleteProgram, glDeleteObjectARB, (GLprogram program));
|
||||
GL_FUNC_2_DEF(void, glAttachShader, glAttachObjectARB, (GLprogram program, GLshader shader));
|
||||
GL_FUNC_2_DEF(void, glDetachShader, glDetachObjectARB, (GLprogram program, GLshader shader));
|
||||
GL_FUNC_2_DEF(void, glLinkProgram, glLinkProgramARB, (GLprogram program));
|
||||
GL_FUNC_2_DEF(void, glUseProgram, glUseProgramObjectARB, (GLprogram program));
|
||||
GL_FUNC_2_DEF(void, glGetProgramiv, glGetObjectParameterivARB, (GLprogram program, GLenum pname, GLint *params));
|
||||
GL_FUNC_2_DEF(void, glGetProgramInfoLog, glGetInfoLogARB, (GLprogram program, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
GL_FUNC_2_DEF(void, glBindAttribLocation, glBindAttribLocationARB, (GLprogram program, GLuint index, const GLchar *name));
|
||||
GL_FUNC_2_DEF(GLint, glGetAttribLocation, glGetAttribLocationARB, (GLprogram program, const GLchar *name));
|
||||
GL_FUNC_2_DEF(GLint, glGetUniformLocation, glGetUniformLocationARB, (GLprogram program, const GLchar *name));
|
||||
|
||||
GL_FUNC_2_DEF(GLshader, glCreateShader, glCreateShaderObjectARB, (GLenum type));
|
||||
GL_FUNC_2_DEF(void, glDeleteShader, glDeleteObjectARB, (GLshader shader));
|
||||
GL_FUNC_2_DEF(void, glGetShaderiv, glGetObjectParameterivARB, (GLshader shader, GLenum pname, GLint *params));
|
||||
GL_FUNC_2_DEF(void, glGetShaderInfoLog, glGetInfoLogARB, (GLshader shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
GL_FUNC_2_DEF(void, glShaderSource, glShaderSourceARB, (GLshader shader, GLsizei count, const GLchar *const *string, const GLint *length));
|
||||
GL_FUNC_2_DEF(void, glCompileShader, glCompileShaderARB, (GLshader shader));
|
||||
|
||||
GL_FUNC_2_DEF(void, glBindFramebuffer, glBindFramebufferEXT, (GLenum target, GLuint renderbuffer));
|
||||
GL_FUNC_2_DEF(void, glDeleteFramebuffers, glDeleteFramebuffersEXT, (GLsizei n, const GLuint *framebuffers));
|
||||
GL_FUNC_2_DEF(void, glGenFramebuffers, glGenFramebuffersEXT, (GLsizei n, GLuint *renderbuffers));
|
||||
GL_FUNC_2_DEF(void, glFramebufferTexture2D, glFramebufferTexture2DEXT, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level));
|
||||
GL_FUNC_2_DEF(GLenum, glCheckFramebufferStatus, glCheckFramebufferStatusEXT, (GLenum target));
|
||||
|
||||
GL_FUNC_2_DEF(void, glActiveTexture, glActiveTextureARB, (GLenum texture));
|
||||
#endif
|
||||
|
||||
#ifdef DEFINED_GL_EXT_FUNC_DEF
|
||||
#undef DEFINED_GL_EXT_FUNC_DEF
|
||||
#undef GL_EXT_FUNC_DEF
|
||||
#endif
|
||||
|
||||
#ifdef DEFINED_GL_FUNC_2_DEF
|
||||
#undef DEFINED_GL_FUNC_2_DEF
|
||||
#undef GL_FUNC_2_DEF
|
||||
#endif
|
1345
backends/graphics/opengl/opengl-graphics.cpp
Normal file
1345
backends/graphics/opengl/opengl-graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
478
backends/graphics/opengl/opengl-graphics.h
Normal file
478
backends/graphics/opengl/opengl-graphics.h
Normal file
@ -0,0 +1,478 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H
|
||||
|
||||
#include "backends/graphics/opengl/opengl-sys.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
#include "backends/graphics/windowed.h"
|
||||
|
||||
#include "common/frac.h"
|
||||
#include "common/mutex.h"
|
||||
#include "common/ustr.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Graphics {
|
||||
class Font;
|
||||
} // End of namespace Graphics
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
// HACK: We use glColor in the OSD code. This might not be working on GL ES but
|
||||
// we still enable it because Tizen already shipped with it. Also, the
|
||||
// SurfaceSDL backend enables it and disabling it can cause issues in sdl.cpp.
|
||||
#define USE_OSD 1
|
||||
|
||||
class Surface;
|
||||
class Pipeline;
|
||||
#if !USE_FORCED_GLES
|
||||
class Shader;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
GFX_OPENGL = 0
|
||||
};
|
||||
|
||||
class OpenGLGraphicsManager : virtual public WindowedGraphicsManager {
|
||||
public:
|
||||
OpenGLGraphicsManager();
|
||||
virtual ~OpenGLGraphicsManager();
|
||||
|
||||
// GraphicsManager API
|
||||
virtual bool hasFeature(OSystem::Feature f) const override;
|
||||
virtual void setFeatureState(OSystem::Feature f, bool enable) override;
|
||||
virtual bool getFeatureState(OSystem::Feature f) const override;
|
||||
|
||||
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
|
||||
virtual int getDefaultGraphicsMode() const override;
|
||||
virtual bool setGraphicsMode(int mode) override;
|
||||
virtual int getGraphicsMode() const override;
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
virtual Graphics::PixelFormat getScreenFormat() const override;
|
||||
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
|
||||
#endif
|
||||
|
||||
virtual const OSystem::GraphicsMode *getSupportedStretchModes() const override;
|
||||
virtual int getDefaultStretchMode() const override;
|
||||
virtual bool setStretchMode(int mode) override;
|
||||
virtual int getStretchMode() const override;
|
||||
|
||||
virtual void beginGFXTransaction() override;
|
||||
virtual OSystem::TransactionError endGFXTransaction() override;
|
||||
|
||||
virtual int getScreenChangeID() const override;
|
||||
|
||||
virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format) override;
|
||||
|
||||
virtual int16 getWidth() const override;
|
||||
virtual int16 getHeight() const override;
|
||||
|
||||
virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||
virtual void fillScreen(uint32 col) override;
|
||||
|
||||
virtual void updateScreen() override;
|
||||
|
||||
virtual Graphics::Surface *lockScreen() override;
|
||||
virtual void unlockScreen() override;
|
||||
|
||||
virtual void setFocusRectangle(const Common::Rect& rect) override;
|
||||
virtual void clearFocusRectangle() override;
|
||||
|
||||
virtual int16 getOverlayWidth() const override;
|
||||
virtual int16 getOverlayHeight() const override;
|
||||
|
||||
virtual Graphics::PixelFormat getOverlayFormat() const override;
|
||||
|
||||
virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||
virtual void clearOverlay() override;
|
||||
virtual void grabOverlay(void *buf, int pitch) const override;
|
||||
|
||||
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) override;
|
||||
virtual void setCursorPalette(const byte *colors, uint start, uint num) override;
|
||||
|
||||
virtual void displayMessageOnOSD(const Common::U32String &msg) override;
|
||||
virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
|
||||
|
||||
// PaletteManager interface
|
||||
virtual void setPalette(const byte *colors, uint start, uint num) override;
|
||||
virtual void grabPalette(byte *colors, uint start, uint num) const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Whether an GLES or GLES2 context is active.
|
||||
*/
|
||||
bool isGLESContext() const { return g_context.type == kContextGLES || g_context.type == kContextGLES2; }
|
||||
|
||||
/**
|
||||
* Sets the OpenGL (ES) type the graphics manager shall work with.
|
||||
*
|
||||
* This needs to be called at least once (and before ever calling
|
||||
* notifyContextCreate).
|
||||
*
|
||||
* @param type Type of the OpenGL (ES) contexts to be created.
|
||||
*/
|
||||
void setContextType(ContextType type);
|
||||
|
||||
/**
|
||||
* Notify the manager of a OpenGL context change. This should be the first
|
||||
* thing to call after you created an OpenGL (ES) context!
|
||||
*
|
||||
* @param defaultFormat The new default format for the game screen
|
||||
* (this is used for the CLUT8 game screens).
|
||||
* @param defaultFormatAlpha The new default format with an alpha channel
|
||||
* (this is used for the overlay and cursor).
|
||||
*/
|
||||
void notifyContextCreate(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha);
|
||||
|
||||
/**
|
||||
* Notify the manager that the OpenGL context is about to be destroyed.
|
||||
* This will free up/reset internal OpenGL related state and *must* be
|
||||
* called whenever a context might be created again after destroying a
|
||||
* context.
|
||||
*/
|
||||
void notifyContextDestroy();
|
||||
|
||||
/**
|
||||
* Create a surface with the specified pixel format.
|
||||
*
|
||||
* @param format The pixel format the Surface object should accept as
|
||||
* input.
|
||||
* @param wantAlpha For CLUT8 surfaces this marks whether an alpha
|
||||
* channel should be used.
|
||||
* @return A pointer to the surface or nullptr on failure.
|
||||
*/
|
||||
Surface *createSurface(const Graphics::PixelFormat &format, bool wantAlpha = false);
|
||||
|
||||
//
|
||||
// Transaction support
|
||||
//
|
||||
struct VideoState {
|
||||
VideoState() : valid(false), gameWidth(0), gameHeight(0),
|
||||
#ifdef USE_RGB_COLOR
|
||||
gameFormat(),
|
||||
#endif
|
||||
aspectRatioCorrection(false), graphicsMode(GFX_OPENGL), filtering(true) {
|
||||
}
|
||||
|
||||
bool valid;
|
||||
|
||||
uint gameWidth, gameHeight;
|
||||
#ifdef USE_RGB_COLOR
|
||||
Graphics::PixelFormat gameFormat;
|
||||
#endif
|
||||
bool aspectRatioCorrection;
|
||||
int graphicsMode;
|
||||
bool filtering;
|
||||
|
||||
bool operator==(const VideoState &right) {
|
||||
return gameWidth == right.gameWidth && gameHeight == right.gameHeight
|
||||
#ifdef USE_RGB_COLOR
|
||||
&& gameFormat == right.gameFormat
|
||||
#endif
|
||||
&& aspectRatioCorrection == right.aspectRatioCorrection
|
||||
&& graphicsMode == right.graphicsMode
|
||||
&& filtering == right.filtering;
|
||||
}
|
||||
|
||||
bool operator!=(const VideoState &right) {
|
||||
return !(*this == right);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The currently set up video state.
|
||||
*/
|
||||
VideoState _currentState;
|
||||
|
||||
/**
|
||||
* The old video state used when doing a transaction rollback.
|
||||
*/
|
||||
VideoState _oldState;
|
||||
|
||||
protected:
|
||||
enum TransactionMode {
|
||||
kTransactionNone = 0,
|
||||
kTransactionActive = 1,
|
||||
kTransactionRollback = 2
|
||||
};
|
||||
|
||||
TransactionMode getTransactionMode() const { return _transactionMode; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* The current transaction mode.
|
||||
*/
|
||||
TransactionMode _transactionMode;
|
||||
|
||||
/**
|
||||
* The current screen change ID.
|
||||
*/
|
||||
int _screenChangeID;
|
||||
|
||||
/**
|
||||
* The current stretch mode.
|
||||
*/
|
||||
int _stretchMode;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Set up the requested video mode. This takes parameters which describe
|
||||
* what resolution the game screen requests (this is possibly aspect ratio
|
||||
* corrected!).
|
||||
*
|
||||
* A sub-class should take these parameters as hints. It might very well
|
||||
* set up a mode which it thinks suites the situation best.
|
||||
*
|
||||
* @parma requestedWidth This is the requested actual game screen width.
|
||||
* @param requestedHeight This is the requested actual game screen height.
|
||||
* @param format This is the requested pixel format of the virtual game screen.
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0;
|
||||
|
||||
/**
|
||||
* Refresh the screen contents.
|
||||
*/
|
||||
virtual void refreshScreen() = 0;
|
||||
|
||||
/**
|
||||
* Saves a screenshot of the entire window, excluding window decorations.
|
||||
*
|
||||
* @param filename The output filename.
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool saveScreenshot(const Common::String &filename) const;
|
||||
|
||||
private:
|
||||
//
|
||||
// OpenGL utilities
|
||||
//
|
||||
|
||||
/**
|
||||
* Initialize the active context for use.
|
||||
*/
|
||||
void initializeGLContext();
|
||||
|
||||
/**
|
||||
* Render back buffer.
|
||||
*/
|
||||
Backbuffer _backBuffer;
|
||||
|
||||
/**
|
||||
* OpenGL pipeline used for rendering.
|
||||
*/
|
||||
Pipeline *_pipeline;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Query the address of an OpenGL function by name.
|
||||
*
|
||||
* This can only be used after a context has been created.
|
||||
* Please note that this function can return valid addresses even if the
|
||||
* OpenGL context does not support the function.
|
||||
*
|
||||
* @param name The name of the OpenGL function.
|
||||
* @return An function pointer for the requested OpenGL function or
|
||||
* nullptr in case of failure.
|
||||
*/
|
||||
virtual void *getProcAddress(const char *name) const = 0;
|
||||
|
||||
/**
|
||||
* Try to determine the internal parameters for a given pixel format.
|
||||
*
|
||||
* @return true when the format can be used, false otherwise.
|
||||
*/
|
||||
bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const;
|
||||
|
||||
virtual bool gameNeedsAspectRatioCorrection() const override;
|
||||
virtual void recalculateDisplayAreas() override;
|
||||
virtual void handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) override;
|
||||
|
||||
/**
|
||||
* The default pixel format of the backend.
|
||||
*/
|
||||
Graphics::PixelFormat _defaultFormat;
|
||||
|
||||
/**
|
||||
* The default pixel format with an alpha channel.
|
||||
*/
|
||||
Graphics::PixelFormat _defaultFormatAlpha;
|
||||
|
||||
/**
|
||||
* The rendering surface for the virtual game screen.
|
||||
*/
|
||||
Surface *_gameScreen;
|
||||
|
||||
/**
|
||||
* The game palette if in CLUT8 mode.
|
||||
*/
|
||||
byte _gamePalette[3 * 256];
|
||||
|
||||
//
|
||||
// Overlay
|
||||
//
|
||||
|
||||
/**
|
||||
* The rendering surface for the overlay.
|
||||
*/
|
||||
Surface *_overlay;
|
||||
|
||||
//
|
||||
// Cursor
|
||||
//
|
||||
|
||||
/**
|
||||
* Set up the correct cursor palette.
|
||||
*/
|
||||
void updateCursorPalette();
|
||||
|
||||
/**
|
||||
* The rendering surface for the mouse cursor.
|
||||
*/
|
||||
Surface *_cursor;
|
||||
|
||||
/**
|
||||
* The X offset for the cursor hotspot in unscaled game coordinates.
|
||||
*/
|
||||
int _cursorHotspotX;
|
||||
|
||||
/**
|
||||
* The Y offset for the cursor hotspot in unscaled game coordinates.
|
||||
*/
|
||||
int _cursorHotspotY;
|
||||
|
||||
/**
|
||||
* Recalculate the cursor scaling. Scaling is always done according to
|
||||
* the game screen.
|
||||
*/
|
||||
void recalculateCursorScaling();
|
||||
|
||||
/**
|
||||
* The X offset for the cursor hotspot in scaled game display area
|
||||
* coordinates.
|
||||
*/
|
||||
int _cursorHotspotXScaled;
|
||||
|
||||
/**
|
||||
* The Y offset for the cursor hotspot in scaled game display area
|
||||
* coordinates.
|
||||
*/
|
||||
int _cursorHotspotYScaled;
|
||||
|
||||
/**
|
||||
* The width of the cursor in scaled game display area coordinates.
|
||||
*/
|
||||
uint _cursorWidthScaled;
|
||||
|
||||
/**
|
||||
* The height of the cursor in scaled game display area coordinates.
|
||||
*/
|
||||
uint _cursorHeightScaled;
|
||||
|
||||
/**
|
||||
* The key color.
|
||||
*/
|
||||
uint32 _cursorKeyColor;
|
||||
|
||||
/**
|
||||
* Whether no cursor scaling should be applied.
|
||||
*/
|
||||
bool _cursorDontScale;
|
||||
|
||||
/**
|
||||
* Whether the special cursor palette is enabled.
|
||||
*/
|
||||
bool _cursorPaletteEnabled;
|
||||
|
||||
/**
|
||||
* The special cursor palette in case enabled.
|
||||
*/
|
||||
byte _cursorPalette[3 * 256];
|
||||
|
||||
#ifdef USE_OSD
|
||||
//
|
||||
// OSD
|
||||
//
|
||||
protected:
|
||||
/**
|
||||
* Returns the font used for on screen display
|
||||
*/
|
||||
virtual const Graphics::Font *getFontOSD() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Request for the OSD icon surface to be updated.
|
||||
*/
|
||||
bool _osdMessageChangeRequest;
|
||||
|
||||
/**
|
||||
* The next OSD message.
|
||||
*
|
||||
* If this value is not empty, the OSD message will be set
|
||||
* to it on the next frame.
|
||||
*/
|
||||
Common::U32String _osdMessageNextData;
|
||||
|
||||
/**
|
||||
* Set the OSD message surface with the value of the next OSD message.
|
||||
*/
|
||||
void osdMessageUpdateSurface();
|
||||
|
||||
/**
|
||||
* The OSD message's contents.
|
||||
*/
|
||||
Surface *_osdMessageSurface;
|
||||
|
||||
/**
|
||||
* Current opacity level of the OSD message.
|
||||
*/
|
||||
uint8 _osdMessageAlpha;
|
||||
|
||||
/**
|
||||
* When fading the OSD message has started.
|
||||
*/
|
||||
uint32 _osdMessageFadeStartTime;
|
||||
|
||||
enum {
|
||||
kOSDMessageFadeOutDelay = 2 * 1000,
|
||||
kOSDMessageFadeOutDuration = 500,
|
||||
kOSDMessageInitialAlpha = 80
|
||||
};
|
||||
|
||||
/**
|
||||
* The OSD background activity icon's contents.
|
||||
*/
|
||||
Surface *_osdIconSurface;
|
||||
|
||||
enum {
|
||||
kOSDIconTopMargin = 10,
|
||||
kOSDIconRightMargin = 10
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
167
backends/graphics/opengl/opengl-sys.h
Normal file
167
backends/graphics/opengl/opengl-sys.h
Normal file
@ -0,0 +1,167 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_SYS_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_OPENGL_SYS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "backends/graphics/opengl/debug.h"
|
||||
#ifdef SDL_BACKEND
|
||||
#include "backends/platform/sdl/sdl-sys.h"
|
||||
#endif
|
||||
|
||||
// On OS X we only support GL contexts. The reason is that Apple's GL interface
|
||||
// uses "void *" for GLhandleARB which is not type compatible with GLint. This
|
||||
// kills our aliasing trick for extension functions and thus would force us to
|
||||
// supply two different Shader class implementations or introduce other
|
||||
// wrappers. OS X only supports GL contexts right now anyway (at least
|
||||
// according to SDL2 sources), thus it is not much of an issue.
|
||||
#if defined(MACOSX) && (!defined(USE_GLES_MODE) || USE_GLES_MODE != 0)
|
||||
//#warning "Only forced OpenGL mode is supported on Mac OS X. Overriding settings."
|
||||
#undef USE_GLES_MODE
|
||||
#define USE_GLES_MODE 0
|
||||
#endif
|
||||
|
||||
// We allow to force GL or GLES modes on compile time.
|
||||
// For this the USE_GLES_MODE define is used. The following values represent
|
||||
// the given selection choices:
|
||||
// 0 - Force OpenGL context
|
||||
// 1 - Force OpenGL ES context
|
||||
// 2 - Force OpenGL ES 2.0 context
|
||||
#ifdef USE_GLES_MODE
|
||||
#define USE_FORCED_GL (USE_GLES_MODE == 0)
|
||||
#define USE_FORCED_GLES (USE_GLES_MODE == 1)
|
||||
#define USE_FORCED_GLES2 (USE_GLES_MODE == 2)
|
||||
#else
|
||||
#define USE_FORCED_GL 0
|
||||
#define USE_FORCED_GLES 0
|
||||
#define USE_FORCED_GLES2 0
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES/gl.h>
|
||||
#define USE_BUILTIN_OPENGL
|
||||
#else
|
||||
#include "backends/graphics/opengl/opengl-defs.h"
|
||||
#endif
|
||||
|
||||
#ifdef SDL_BACKEND
|
||||
// Win32 needs OpenGL functions declared with APIENTRY.
|
||||
// However, SDL does not define APIENTRY in it's SDL.h file on non-Windows
|
||||
// targets, thus if it is not available, we just dummy define it.
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#define GL_CALL_CONV APIENTRY
|
||||
#else
|
||||
#define GL_CALL_CONV
|
||||
#endif
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
enum ContextType {
|
||||
kContextGL,
|
||||
kContextGLES,
|
||||
kContextGLES2
|
||||
};
|
||||
|
||||
class Pipeline;
|
||||
class Framebuffer;
|
||||
|
||||
/**
|
||||
* Description structure of the OpenGL (ES) context.
|
||||
*/
|
||||
struct Context {
|
||||
/** The type of the active context. */
|
||||
ContextType type;
|
||||
|
||||
/**
|
||||
* Reset context.
|
||||
*
|
||||
* This marks all extensions as unavailable and clears all function
|
||||
* pointers.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/** The maximum texture size supported by the context. */
|
||||
GLint maxTextureSize;
|
||||
|
||||
/** Whether GL_ARB_texture_non_power_of_two is available or not. */
|
||||
bool NPOTSupported;
|
||||
|
||||
/** Whether shader support is available or not. */
|
||||
bool shadersSupported;
|
||||
|
||||
/** Whether multi texture support is available or not. */
|
||||
bool multitextureSupported;
|
||||
|
||||
/** Whether FBO support is available or not. */
|
||||
bool framebufferObjectSupported;
|
||||
|
||||
#define GL_FUNC_DEF(ret, name, param) ret (GL_CALL_CONV *name)param
|
||||
#include "backends/graphics/opengl/opengl-func.h"
|
||||
#undef GL_FUNC_DEF
|
||||
|
||||
//
|
||||
// Wrapper functionality to handle fixed-function pipelines and
|
||||
// programmable pipelines in the same fashion.
|
||||
//
|
||||
|
||||
private:
|
||||
/** Currently active rendering pipeline. */
|
||||
Pipeline *activePipeline;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Set new pipeline.
|
||||
*
|
||||
* Client is responsible for any memory management related to pipelines.
|
||||
*
|
||||
* @param pipeline Pipeline to activate.
|
||||
* @return Formerly active pipeline.
|
||||
*/
|
||||
Pipeline *setPipeline(Pipeline *pipeline);
|
||||
|
||||
/**
|
||||
* Query the currently active rendering pipeline.
|
||||
*/
|
||||
Pipeline *getActivePipeline() const { return activePipeline; }
|
||||
};
|
||||
|
||||
/**
|
||||
* The (active) OpenGL context.
|
||||
*/
|
||||
extern Context g_context;
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#define GL_CALL(x) GL_WRAP_DEBUG(g_context.x, x)
|
||||
#define GL_CALL_SAFE(func, params) \
|
||||
do { \
|
||||
if (g_context.func) { \
|
||||
GL_CALL(func params); \
|
||||
} \
|
||||
} while (0)
|
||||
#define GL_ASSIGN(var, x) GL_WRAP_DEBUG(var = g_context.x, x)
|
||||
|
||||
#endif
|
46
backends/graphics/opengl/pipelines/clut8.cpp
Normal file
46
backends/graphics/opengl/pipelines/clut8.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/* 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/pipelines/clut8.h"
|
||||
#include "backends/graphics/opengl/shader.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
CLUT8LookUpPipeline::CLUT8LookUpPipeline()
|
||||
: ShaderPipeline(ShaderMan.query(ShaderManager::kCLUT8LookUp)), _paletteTexture(nullptr) {
|
||||
}
|
||||
|
||||
void CLUT8LookUpPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates) {
|
||||
// Set the palette texture.
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE1));
|
||||
if (_paletteTexture) {
|
||||
_paletteTexture->bind();
|
||||
}
|
||||
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
ShaderPipeline::drawTexture(texture, coordinates);
|
||||
}
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
46
backends/graphics/opengl/pipelines/clut8.h
Normal file
46
backends/graphics/opengl/pipelines/clut8.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_CLUT8_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_CLUT8_H
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/shader.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
class CLUT8LookUpPipeline : public ShaderPipeline {
|
||||
public:
|
||||
CLUT8LookUpPipeline();
|
||||
|
||||
void setPaletteTexture(const GLTexture *paletteTexture) { _paletteTexture = paletteTexture; }
|
||||
|
||||
virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates);
|
||||
|
||||
private:
|
||||
const GLTexture *_paletteTexture;
|
||||
};
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
70
backends/graphics/opengl/pipelines/fixed.cpp
Normal file
70
backends/graphics/opengl/pipelines/fixed.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/* 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/pipelines/fixed.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES2
|
||||
void FixedPipeline::activateInternal() {
|
||||
GL_CALL(glDisable(GL_LIGHTING));
|
||||
GL_CALL(glDisable(GL_FOG));
|
||||
GL_CALL(glShadeModel(GL_FLAT));
|
||||
GL_CALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
|
||||
|
||||
GL_CALL(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
if (g_context.multitextureSupported) {
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
}
|
||||
#endif
|
||||
GL_CALL(glEnable(GL_TEXTURE_2D));
|
||||
}
|
||||
|
||||
void FixedPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
GL_CALL(glColor4f(r, g, b, a));
|
||||
}
|
||||
|
||||
void FixedPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates) {
|
||||
texture.bind();
|
||||
|
||||
GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texture.getTexCoords()));
|
||||
GL_CALL(glVertexPointer(2, GL_FLOAT, 0, coordinates));
|
||||
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
|
||||
void FixedPipeline::setProjectionMatrix(const GLfloat *projectionMatrix) {
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CALL(glMatrixMode(GL_PROJECTION));
|
||||
GL_CALL(glLoadMatrixf(projectionMatrix));
|
||||
|
||||
GL_CALL(glMatrixMode(GL_MODELVIEW));
|
||||
GL_CALL(glLoadIdentity());
|
||||
}
|
||||
#endif // !USE_FORCED_GLES2
|
||||
|
||||
} // End of namespace OpenGL
|
46
backends/graphics/opengl/pipelines/fixed.h
Normal file
46
backends/graphics/opengl/pipelines/fixed.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_FIXED_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_FIXED_H
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES2
|
||||
class FixedPipeline : public Pipeline {
|
||||
public:
|
||||
virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
|
||||
virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates);
|
||||
|
||||
virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
|
||||
|
||||
protected:
|
||||
virtual void activateInternal();
|
||||
};
|
||||
#endif // !USE_FORCED_GLES2
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
66
backends/graphics/opengl/pipelines/pipeline.cpp
Normal file
66
backends/graphics/opengl/pipelines/pipeline.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/* 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/pipelines/pipeline.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
Pipeline::Pipeline()
|
||||
: _activeFramebuffer(nullptr), _isActive(false) {
|
||||
}
|
||||
|
||||
void Pipeline::activate() {
|
||||
_isActive = true;
|
||||
|
||||
if (_activeFramebuffer) {
|
||||
_activeFramebuffer->activate();
|
||||
}
|
||||
|
||||
activateInternal();
|
||||
}
|
||||
|
||||
void Pipeline::deactivate() {
|
||||
deactivateInternal();
|
||||
|
||||
if (_activeFramebuffer) {
|
||||
_activeFramebuffer->deactivate();
|
||||
}
|
||||
|
||||
_isActive = false;
|
||||
}
|
||||
|
||||
Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
|
||||
Framebuffer *oldFramebuffer = _activeFramebuffer;
|
||||
if (_isActive && oldFramebuffer) {
|
||||
oldFramebuffer->deactivate();
|
||||
}
|
||||
|
||||
_activeFramebuffer = framebuffer;
|
||||
if (_isActive && _activeFramebuffer) {
|
||||
_activeFramebuffer->activate();
|
||||
}
|
||||
|
||||
return oldFramebuffer;
|
||||
}
|
||||
|
||||
} // End of namespace OpenGL
|
126
backends/graphics/opengl/pipelines/pipeline.h
Normal file
126
backends/graphics/opengl/pipelines/pipeline.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
|
||||
|
||||
#include "backends/graphics/opengl/opengl-sys.h"
|
||||
#include "backends/graphics/opengl/texture.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class Framebuffer;
|
||||
|
||||
/**
|
||||
* Interface for OpenGL pipeline functionality.
|
||||
*
|
||||
* This encapsulates differences in various rendering pipelines used for
|
||||
* OpenGL, OpenGL ES 1, and OpenGL ES 2.
|
||||
*/
|
||||
class Pipeline {
|
||||
public:
|
||||
Pipeline();
|
||||
virtual ~Pipeline() {}
|
||||
|
||||
/**
|
||||
* Activate the pipeline.
|
||||
*
|
||||
* This sets the OpenGL state to make use of drawing with the given
|
||||
* OpenGL pipeline.
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/**
|
||||
* Deactivate the pipeline.
|
||||
*/
|
||||
void deactivate();
|
||||
|
||||
/**
|
||||
* Set framebuffer to render to.
|
||||
*
|
||||
* Client is responsible for any memory management related to framebuffer.
|
||||
*
|
||||
* @param framebuffer Framebuffer to activate.
|
||||
* @return Formerly active framebuffer.
|
||||
*/
|
||||
Framebuffer *setFramebuffer(Framebuffer *framebuffer);
|
||||
|
||||
/**
|
||||
* Set modulation color.
|
||||
*
|
||||
* @param r Red component in [0,1].
|
||||
* @param g Green component in [0,1].
|
||||
* @param b Blue component in [0,1].
|
||||
* @param a Alpha component in [0,1].
|
||||
*/
|
||||
virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) = 0;
|
||||
|
||||
/**
|
||||
* Draw a texture rectangle to the currently active framebuffer.
|
||||
*
|
||||
* @param texture Texture to use for drawing.
|
||||
* @param coordinates x1, y1, x2, y2 coordinates where to draw the texture.
|
||||
*/
|
||||
virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates) = 0;
|
||||
|
||||
void drawTexture(const GLTexture &texture, GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
|
||||
const GLfloat coordinates[4*2] = {
|
||||
x, y,
|
||||
x + w, y,
|
||||
x, y + h,
|
||||
x + w, y + h
|
||||
};
|
||||
drawTexture(texture, coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the projection matrix.
|
||||
*
|
||||
* This is intended to be only ever be used by Framebuffer subclasses.
|
||||
*/
|
||||
virtual void setProjectionMatrix(const GLfloat *projectionMatrix) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Activate the pipeline.
|
||||
*
|
||||
* This sets the OpenGL state to make use of drawing with the given
|
||||
* OpenGL pipeline.
|
||||
*/
|
||||
virtual void activateInternal() = 0;
|
||||
|
||||
/**
|
||||
* Deactivate the pipeline.
|
||||
*/
|
||||
virtual void deactivateInternal() {}
|
||||
|
||||
bool isActive() const { return _isActive; }
|
||||
|
||||
Framebuffer *_activeFramebuffer;
|
||||
|
||||
private:
|
||||
bool _isActive;
|
||||
};
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
94
backends/graphics/opengl/pipelines/shader.cpp
Normal file
94
backends/graphics/opengl/pipelines/shader.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/* 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/pipelines/shader.h"
|
||||
#include "backends/graphics/opengl/shader.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
ShaderPipeline::ShaderPipeline(Shader *shader)
|
||||
: _activeShader(shader), _colorAttributes() {
|
||||
_vertexAttribLocation = shader->getAttributeLocation("position");
|
||||
_texCoordAttribLocation = shader->getAttributeLocation("texCoordIn");
|
||||
_colorAttribLocation = shader->getAttributeLocation("blendColorIn");
|
||||
|
||||
assert(_vertexAttribLocation != -1);
|
||||
assert(_texCoordAttribLocation != -1);
|
||||
assert(_colorAttribLocation != -1);
|
||||
|
||||
// One of the attributes needs to be passed through location 0, otherwise
|
||||
// we get no output for GL contexts due to GL compatibility reasons. Let's
|
||||
// check whether this ever happens. If this ever gets hit, we need to
|
||||
// enable location 0 and pass some dummy values through it to fix output.
|
||||
assert( _vertexAttribLocation == 0
|
||||
|| _texCoordAttribLocation == 0
|
||||
|| _colorAttribLocation == 0);
|
||||
}
|
||||
|
||||
void ShaderPipeline::activateInternal() {
|
||||
GL_CALL(glEnableVertexAttribArray(_vertexAttribLocation));
|
||||
GL_CALL(glEnableVertexAttribArray(_texCoordAttribLocation));
|
||||
GL_CALL(glEnableVertexAttribArray(_colorAttribLocation));
|
||||
|
||||
if (g_context.multitextureSupported) {
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
}
|
||||
|
||||
_activeShader->activate();
|
||||
|
||||
GL_CALL(glVertexAttribPointer(_colorAttribLocation, 4, GL_FLOAT, GL_FALSE, 0, _colorAttributes));
|
||||
}
|
||||
|
||||
void ShaderPipeline::deactivateInternal() {
|
||||
GL_CALL(glDisableVertexAttribArray(_vertexAttribLocation));
|
||||
GL_CALL(glDisableVertexAttribArray(_texCoordAttribLocation));
|
||||
GL_CALL(glDisableVertexAttribArray(_colorAttribLocation));
|
||||
|
||||
_activeShader->deactivate();
|
||||
}
|
||||
|
||||
void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
GLfloat *dst = _colorAttributes;
|
||||
for (uint i = 0; i < 4; ++i) {
|
||||
*dst++ = r;
|
||||
*dst++ = g;
|
||||
*dst++ = b;
|
||||
*dst++ = a;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates) {
|
||||
texture.bind();
|
||||
|
||||
GL_CALL(glVertexAttribPointer(_texCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texture.getTexCoords()));
|
||||
GL_CALL(glVertexAttribPointer(_vertexAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, coordinates));
|
||||
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
|
||||
void ShaderPipeline::setProjectionMatrix(const GLfloat *projectionMatrix) {
|
||||
_activeShader->setUniform("projection", new ShaderUniformMatrix44(projectionMatrix));
|
||||
}
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
59
backends/graphics/opengl/pipelines/shader.h
Normal file
59
backends/graphics/opengl/pipelines/shader.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_SHADER_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_SHADER_H
|
||||
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
class Shader;
|
||||
|
||||
class ShaderPipeline : public Pipeline {
|
||||
public:
|
||||
ShaderPipeline(Shader *shader);
|
||||
|
||||
virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
|
||||
virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates);
|
||||
|
||||
virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
|
||||
|
||||
protected:
|
||||
virtual void activateInternal();
|
||||
virtual void deactivateInternal();
|
||||
|
||||
GLint _vertexAttribLocation;
|
||||
GLint _texCoordAttribLocation;
|
||||
GLint _colorAttribLocation;
|
||||
|
||||
GLfloat _colorAttributes[4*4];
|
||||
|
||||
Shader *const _activeShader;
|
||||
};
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
337
backends/graphics/opengl/shader.cpp
Normal file
337
backends/graphics/opengl/shader.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
/* 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/shader.h"
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
|
||||
#include "common/textconsole.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Common {
|
||||
DECLARE_SINGLETON(OpenGL::ShaderManager);
|
||||
}
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
namespace {
|
||||
|
||||
#pragma mark - Builtin Shader Sources -
|
||||
|
||||
const char *const g_defaultVertexShader =
|
||||
"attribute vec4 position;\n"
|
||||
"attribute vec2 texCoordIn;\n"
|
||||
"attribute vec4 blendColorIn;\n"
|
||||
"\n"
|
||||
"uniform mat4 projection;\n"
|
||||
"\n"
|
||||
"varying vec2 texCoord;\n"
|
||||
"varying vec4 blendColor;\n"
|
||||
"\n"
|
||||
"void main(void) {\n"
|
||||
"\ttexCoord = texCoordIn;\n"
|
||||
"\tblendColor = blendColorIn;\n"
|
||||
"\tgl_Position = projection * position;\n"
|
||||
"}\n";
|
||||
|
||||
const char *const g_defaultFragmentShader =
|
||||
"varying vec2 texCoord;\n"
|
||||
"varying vec4 blendColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D shaderTexture;\n"
|
||||
"\n"
|
||||
"void main(void) {\n"
|
||||
"\tgl_FragColor = blendColor * texture2D(shaderTexture, texCoord);\n"
|
||||
"}\n";
|
||||
|
||||
const char *const g_lookUpFragmentShader =
|
||||
"varying vec2 texCoord;\n"
|
||||
"varying vec4 blendColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D shaderTexture;\n"
|
||||
"uniform sampler2D palette;\n"
|
||||
"\n"
|
||||
"const float adjustFactor = 255.0 / 256.0 + 1.0 / (2.0 * 256.0);"
|
||||
"\n"
|
||||
"void main(void) {\n"
|
||||
"\tvec4 index = texture2D(shaderTexture, texCoord);\n"
|
||||
"\tgl_FragColor = blendColor * texture2D(palette, vec2(index.a * adjustFactor, 0.0));\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
// Taken from: https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_03#OpenGL_ES_2_portability
|
||||
const char *const g_precisionDefines =
|
||||
"#ifdef GL_ES\n"
|
||||
"\t#if defined(GL_FRAGMENT_PRECISION_HIGH) && GL_FRAGMENT_PRECISION_HIGH == 1\n"
|
||||
"\t\tprecision highp float;\n"
|
||||
"\t#else\n"
|
||||
"\t\tprecision mediump float;\n"
|
||||
"\t#endif\n"
|
||||
"#else\n"
|
||||
"\t#define highp\n"
|
||||
"\t#define mediump\n"
|
||||
"\t#define lowp\n"
|
||||
"#endif\n";
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
||||
#pragma mark - Uniform Values -
|
||||
|
||||
void ShaderUniformInteger::set(GLint location) const {
|
||||
GL_CALL(glUniform1i(location, _value));
|
||||
}
|
||||
|
||||
void ShaderUniformFloat::set(GLint location) const {
|
||||
GL_CALL(glUniform1f(location, _value));
|
||||
}
|
||||
|
||||
void ShaderUniformMatrix44::set(GLint location) const {
|
||||
GL_CALL(glUniformMatrix4fv(location, 1, GL_FALSE, _matrix));
|
||||
}
|
||||
|
||||
#pragma mark - Shader Implementation -
|
||||
|
||||
Shader::Shader(const Common::String &vertex, const Common::String &fragment)
|
||||
: _vertex(vertex), _fragment(fragment), _isActive(false), _program(0), _uniforms() {
|
||||
recreate();
|
||||
}
|
||||
|
||||
Shader::~Shader() {
|
||||
// According to extension specification glDeleteObjectARB silently ignores
|
||||
// 0. However, with nVidia drivers this can cause GL_INVALID_VALUE, thus
|
||||
// we do not call it with 0 as parameter to avoid warnings.
|
||||
if (_program) {
|
||||
GL_CALL_SAFE(glDeleteProgram, (_program));
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::destroy() {
|
||||
// According to extension specification glDeleteObjectARB silently ignores
|
||||
// 0. However, with nVidia drivers this can cause GL_INVALID_VALUE, thus
|
||||
// we do not call it with 0 as parameter to avoid warnings.
|
||||
if (_program) {
|
||||
GL_CALL(glDeleteProgram(_program));
|
||||
_program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Shader::recreate() {
|
||||
// Make sure any old programs are destroyed properly.
|
||||
destroy();
|
||||
|
||||
GLshader vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER);
|
||||
if (!vertexShader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLshader fragmentShader = compileShader(_fragment.c_str(), GL_FRAGMENT_SHADER);
|
||||
if (!fragmentShader) {
|
||||
GL_CALL(glDeleteShader(vertexShader));
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_ASSIGN(_program, glCreateProgram());
|
||||
if (!_program) {
|
||||
GL_CALL(glDeleteShader(vertexShader));
|
||||
GL_CALL(glDeleteShader(fragmentShader));
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_CALL(glAttachShader(_program, vertexShader));
|
||||
GL_CALL(glAttachShader(_program, fragmentShader));
|
||||
|
||||
GL_CALL(glLinkProgram(_program));
|
||||
|
||||
GL_CALL(glDetachShader(_program, fragmentShader));
|
||||
GL_CALL(glDeleteShader(fragmentShader));
|
||||
|
||||
GL_CALL(glDetachShader(_program, vertexShader));
|
||||
GL_CALL(glDeleteShader(vertexShader));
|
||||
|
||||
GLint result;
|
||||
GL_CALL(glGetProgramiv(_program, GL_LINK_STATUS, &result));
|
||||
if (result == GL_FALSE) {
|
||||
GLint logSize;
|
||||
GL_CALL(glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &logSize));
|
||||
|
||||
GLchar *log = new GLchar[logSize];
|
||||
GL_CALL(glGetProgramInfoLog(_program, logSize, nullptr, log));
|
||||
warning("Could not link shader: \"%s\"", log);
|
||||
delete[] log;
|
||||
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set program object in case shader is active during recreation.
|
||||
if (_isActive) {
|
||||
GL_CALL(glUseProgram(_program));
|
||||
}
|
||||
|
||||
for (UniformMap::iterator i = _uniforms.begin(), end = _uniforms.end(); i != end; ++i) {
|
||||
i->_value.location = getUniformLocation(i->_key.c_str());
|
||||
i->_value.altered = true;
|
||||
if (_isActive) {
|
||||
i->_value.set();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shader::activate() {
|
||||
// Activate program.
|
||||
GL_CALL(glUseProgram(_program));
|
||||
|
||||
// Reset changed uniform values.
|
||||
for (UniformMap::iterator i = _uniforms.begin(), end = _uniforms.end(); i != end; ++i) {
|
||||
i->_value.set();
|
||||
}
|
||||
|
||||
_isActive = true;
|
||||
}
|
||||
|
||||
void Shader::deactivate() {
|
||||
_isActive = false;
|
||||
}
|
||||
|
||||
GLint Shader::getAttributeLocation(const char *name) const {
|
||||
GLint result = -1;
|
||||
GL_ASSIGN(result, glGetAttribLocation(_program, name));
|
||||
return result;
|
||||
}
|
||||
|
||||
GLint Shader::getUniformLocation(const char *name) const {
|
||||
GLint result = -1;
|
||||
GL_ASSIGN(result, glGetUniformLocation(_program, name));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Shader::setUniform(const Common::String &name, ShaderUniformValue *value) {
|
||||
UniformMap::iterator uniformIter = _uniforms.find(name);
|
||||
Uniform *uniform;
|
||||
|
||||
if (uniformIter == _uniforms.end()) {
|
||||
const GLint location = getUniformLocation(name.c_str());
|
||||
if (location == -1) {
|
||||
delete value;
|
||||
return false;
|
||||
}
|
||||
|
||||
uniform = &_uniforms[name];
|
||||
uniform->location = location;
|
||||
} else {
|
||||
uniform = &uniformIter->_value;
|
||||
}
|
||||
|
||||
uniform->value = Common::SharedPtr<ShaderUniformValue>(value);
|
||||
uniform->altered = true;
|
||||
if (_isActive) {
|
||||
uniform->set();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLshader Shader::compileShader(const char *source, GLenum shaderType) {
|
||||
const GLchar *versionSource = g_context.type == kContextGLES2 ? "#version 100\n" : "#version 120\n";
|
||||
GLshader handle;
|
||||
GL_ASSIGN(handle, glCreateShader(shaderType));
|
||||
if (!handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *const shaderSources[] = {
|
||||
versionSource,
|
||||
g_precisionDefines,
|
||||
source
|
||||
};
|
||||
|
||||
GL_CALL(glShaderSource(handle, ARRAYSIZE(shaderSources), shaderSources, nullptr));
|
||||
GL_CALL(glCompileShader(handle));
|
||||
|
||||
GLint result;
|
||||
GL_CALL(glGetShaderiv(handle, GL_COMPILE_STATUS, &result));
|
||||
if (result == GL_FALSE) {
|
||||
GLint logSize;
|
||||
GL_CALL(glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &logSize));
|
||||
|
||||
GLchar *log = new GLchar[logSize];
|
||||
GL_CALL(glGetShaderInfoLog(handle, logSize, nullptr, log));
|
||||
warning("Could not compile shader \"%s\": \"%s\"", source, log);
|
||||
delete[] log;
|
||||
|
||||
GL_CALL(glDeleteShader(handle));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
ShaderManager::ShaderManager() : _initializeShaders(true) {
|
||||
for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) {
|
||||
_builtIn[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ShaderManager::~ShaderManager() {
|
||||
for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) {
|
||||
delete _builtIn[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderManager::notifyDestroy() {
|
||||
for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) {
|
||||
_builtIn[i]->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderManager::notifyCreate() {
|
||||
if (_initializeShaders) {
|
||||
_initializeShaders = false;
|
||||
|
||||
_builtIn[kDefault] = new Shader(g_defaultVertexShader, g_defaultFragmentShader);
|
||||
_builtIn[kCLUT8LookUp] = new Shader(g_defaultVertexShader, g_lookUpFragmentShader);
|
||||
_builtIn[kCLUT8LookUp]->setUniform1I("palette", 1);
|
||||
|
||||
for (uint i = 0; i < kMaxUsages; ++i) {
|
||||
_builtIn[i]->setUniform1I("shaderTexture", 0);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) {
|
||||
_builtIn[i]->recreate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shader *ShaderManager::query(ShaderUsage shader) const {
|
||||
if (shader == kMaxUsages) {
|
||||
warning("OpenGL: ShaderManager::query used with kMaxUsages");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _builtIn[shader];
|
||||
}
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif // !USE_FORCED_GLES
|
288
backends/graphics/opengl/shader.h
Normal file
288
backends/graphics/opengl/shader.h
Normal file
@ -0,0 +1,288 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_SHADER_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_SHADER_H
|
||||
|
||||
#include "backends/graphics/opengl/opengl-sys.h"
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
|
||||
#include "common/singleton.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/ptr.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
/**
|
||||
* A generic uniform value interface for a shader program.
|
||||
*/
|
||||
class ShaderUniformValue {
|
||||
public:
|
||||
virtual ~ShaderUniformValue() {}
|
||||
|
||||
/**
|
||||
* Setup the the value to the given location.
|
||||
*
|
||||
* @param location Location of the uniform.
|
||||
*/
|
||||
virtual void set(GLint location) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Integer value for a shader uniform.
|
||||
*/
|
||||
class ShaderUniformInteger : public ShaderUniformValue {
|
||||
public:
|
||||
ShaderUniformInteger(GLint value) : _value(value) {}
|
||||
|
||||
virtual void set(GLint location) const override;
|
||||
|
||||
private:
|
||||
const GLint _value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Float value for a shader uniform.
|
||||
*/
|
||||
class ShaderUniformFloat : public ShaderUniformValue {
|
||||
public:
|
||||
ShaderUniformFloat(GLfloat value) : _value(value) {}
|
||||
|
||||
virtual void set(GLint location) const override;
|
||||
|
||||
private:
|
||||
const GLfloat _value;
|
||||
};
|
||||
|
||||
/**
|
||||
* 4x4 Matrix value for a shader uniform.
|
||||
*/
|
||||
class ShaderUniformMatrix44 : public ShaderUniformValue {
|
||||
public:
|
||||
ShaderUniformMatrix44(const GLfloat *mat44) {
|
||||
memcpy(_matrix, mat44, sizeof(_matrix));
|
||||
}
|
||||
|
||||
virtual void set(GLint location) const override;
|
||||
|
||||
private:
|
||||
GLfloat _matrix[4*4];
|
||||
};
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
Shader(const Common::String &vertex, const Common::String &fragment);
|
||||
~Shader();
|
||||
|
||||
/**
|
||||
* Destroy the shader program.
|
||||
*
|
||||
* This keeps the vertex and fragment shader sources around and thus
|
||||
* allows for recreating the shader on context recreation. It also keeps
|
||||
* the uniform state around.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Recreate shader program.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
bool recreate();
|
||||
|
||||
/**
|
||||
* Make shader active.
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/**
|
||||
* Make shader inactive.
|
||||
*/
|
||||
void deactivate();
|
||||
|
||||
/**
|
||||
* Return location for attribute with given name.
|
||||
*
|
||||
* @param name Name of the attribute to look up in the shader.
|
||||
* @return The loctaion of -1 if attribute was not found.
|
||||
*/
|
||||
GLint getAttributeLocation(const char *name) const;
|
||||
GLint getAttributeLocation(const Common::String &name) const {
|
||||
return getAttributeLocation(name.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return location for uniform with given name.
|
||||
*
|
||||
* @param name Name of the uniform to look up in the shader.
|
||||
* @return The location or -1 if uniform was not found.
|
||||
*/
|
||||
GLint getUniformLocation(const char *name) const;
|
||||
GLint getUniformLocation(const Common::String &name) const {
|
||||
return getUniformLocation(name.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind value to uniform.
|
||||
*
|
||||
* @param name The name of the uniform to be set.
|
||||
* @param value The value to be set.
|
||||
* @return 'false' on error (i.e. uniform unknown or otherwise),
|
||||
* 'true' otherwise.
|
||||
*/
|
||||
bool setUniform(const Common::String &name, ShaderUniformValue *value);
|
||||
|
||||
/**
|
||||
* Bind integer value to uniform.
|
||||
*
|
||||
* @param name The name of the uniform to be set.
|
||||
* @param value The value to be set.
|
||||
* @return 'false' on error (i.e. uniform unknown or otherwise),
|
||||
* 'true' otherwise.
|
||||
*/
|
||||
bool setUniform1I(const Common::String &name, GLint value) {
|
||||
return setUniform(name, new ShaderUniformInteger(value));
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* Vertex shader sources.
|
||||
*/
|
||||
const Common::String _vertex;
|
||||
|
||||
/**
|
||||
* Fragment shader sources.
|
||||
*/
|
||||
const Common::String _fragment;
|
||||
|
||||
/**
|
||||
* Whether the shader is active or not.
|
||||
*/
|
||||
bool _isActive;
|
||||
|
||||
/**
|
||||
* Shader program handle.
|
||||
*/
|
||||
GLprogram _program;
|
||||
|
||||
/**
|
||||
* A uniform descriptor.
|
||||
*
|
||||
* This stores the state of a shader uniform. The state is made up of the
|
||||
* uniform location, whether the state was altered since last set, and the
|
||||
* value of the uniform.
|
||||
*/
|
||||
struct Uniform {
|
||||
Uniform() : location(-1), altered(false), value() {}
|
||||
Uniform(GLint loc, ShaderUniformValue *val)
|
||||
: location(loc), altered(true), value(val) {}
|
||||
|
||||
/**
|
||||
* Write uniform value into currently active shader.
|
||||
*/
|
||||
void set() {
|
||||
if (altered && value) {
|
||||
value->set(location);
|
||||
altered = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The location of the uniform or -1 in case it does not exist.
|
||||
*/
|
||||
GLint location;
|
||||
|
||||
/**
|
||||
* Whether the uniform state was aletered since last 'set'.
|
||||
*/
|
||||
bool altered;
|
||||
|
||||
/**
|
||||
* The value of the uniform.
|
||||
*/
|
||||
Common::SharedPtr<ShaderUniformValue> value;
|
||||
};
|
||||
|
||||
typedef Common::HashMap<Common::String, Uniform> UniformMap;
|
||||
|
||||
/**
|
||||
* Map from uniform name to associated uniform description.
|
||||
*/
|
||||
UniformMap _uniforms;
|
||||
|
||||
/**
|
||||
* Compile a vertex or fragment shader.
|
||||
*
|
||||
* @param source Sources to the shader.
|
||||
* @param shaderType Type of shader to compile (GL_FRAGMENT_SHADER_ARB or
|
||||
* GL_VERTEX_SHADER_ARB)
|
||||
* @return The shader object or 0 on failure.
|
||||
*/
|
||||
static GLshader compileShader(const char *source, GLenum shaderType);
|
||||
};
|
||||
|
||||
class ShaderManager : public Common::Singleton<ShaderManager> {
|
||||
public:
|
||||
enum ShaderUsage {
|
||||
/** Default shader implementing the GL fixed-function pipeline. */
|
||||
kDefault = 0,
|
||||
|
||||
/** CLUT8 look up shader. */
|
||||
kCLUT8LookUp,
|
||||
|
||||
/** Number of built-in shaders. Should not be used for query. */
|
||||
kMaxUsages
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify shader manager about context destruction.
|
||||
*/
|
||||
void notifyDestroy();
|
||||
|
||||
/**
|
||||
* Notify shader manager about context creation.
|
||||
*/
|
||||
void notifyCreate();
|
||||
|
||||
/**
|
||||
* Query a built-in shader.
|
||||
*/
|
||||
Shader *query(ShaderUsage shader) const;
|
||||
|
||||
private:
|
||||
friend class Common::Singleton<SingletonBaseType>;
|
||||
ShaderManager();
|
||||
~ShaderManager();
|
||||
|
||||
bool _initializeShaders;
|
||||
|
||||
Shader *_builtIn[kMaxUsages];
|
||||
};
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
/** Shortcut for accessing the font manager. */
|
||||
#define ShaderMan (OpenGL::ShaderManager::instance())
|
||||
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
#endif
|
698
backends/graphics/opengl/texture.cpp
Normal file
698
backends/graphics/opengl/texture.cpp
Normal file
@ -0,0 +1,698 @@
|
||||
/* 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/texture.h"
|
||||
#include "backends/graphics/opengl/shader.h"
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
#include "backends/graphics/opengl/pipelines/clut8.h"
|
||||
#include "backends/graphics/opengl/framebuffer.h"
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
GLTexture::GLTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType)
|
||||
: _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType),
|
||||
_width(0), _height(0), _logicalWidth(0), _logicalHeight(0),
|
||||
_texCoords(), _glFilter(GL_NEAREST),
|
||||
_glTexture(0) {
|
||||
create();
|
||||
}
|
||||
|
||||
GLTexture::~GLTexture() {
|
||||
GL_CALL_SAFE(glDeleteTextures, (1, &_glTexture));
|
||||
}
|
||||
|
||||
void GLTexture::enableLinearFiltering(bool enable) {
|
||||
if (enable) {
|
||||
_glFilter = GL_LINEAR;
|
||||
} else {
|
||||
_glFilter = GL_NEAREST;
|
||||
}
|
||||
|
||||
bind();
|
||||
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
|
||||
}
|
||||
|
||||
void GLTexture::destroy() {
|
||||
GL_CALL(glDeleteTextures(1, &_glTexture));
|
||||
_glTexture = 0;
|
||||
}
|
||||
|
||||
void GLTexture::create() {
|
||||
// Release old texture name in case it exists.
|
||||
destroy();
|
||||
|
||||
// Get a new texture name.
|
||||
GL_CALL(glGenTextures(1, &_glTexture));
|
||||
|
||||
// Set up all texture parameters.
|
||||
bind();
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
|
||||
// If a size is specified, allocate memory for it.
|
||||
if (_width != 0 && _height != 0) {
|
||||
// Allocate storage for OpenGL texture.
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _width, _height,
|
||||
0, _glFormat, _glType, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
void GLTexture::bind() const {
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture));
|
||||
}
|
||||
|
||||
void GLTexture::setSize(uint width, uint height) {
|
||||
const uint oldWidth = _width;
|
||||
const uint oldHeight = _height;
|
||||
|
||||
if (!g_context.NPOTSupported) {
|
||||
_width = Common::nextHigher2(width);
|
||||
_height = Common::nextHigher2(height);
|
||||
} else {
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
_logicalWidth = width;
|
||||
_logicalHeight = height;
|
||||
|
||||
// If a size is specified, allocate memory for it.
|
||||
if (width != 0 && height != 0) {
|
||||
const GLfloat texWidth = (GLfloat)width / _width;
|
||||
const GLfloat texHeight = (GLfloat)height / _height;
|
||||
|
||||
_texCoords[0] = 0;
|
||||
_texCoords[1] = 0;
|
||||
|
||||
_texCoords[2] = texWidth;
|
||||
_texCoords[3] = 0;
|
||||
|
||||
_texCoords[4] = 0;
|
||||
_texCoords[5] = texHeight;
|
||||
|
||||
_texCoords[6] = texWidth;
|
||||
_texCoords[7] = texHeight;
|
||||
|
||||
// Allocate storage for OpenGL texture if necessary.
|
||||
if (oldWidth != _width || oldHeight != _height) {
|
||||
bind();
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _width,
|
||||
_height, 0, _glFormat, _glType, NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLTexture::updateArea(const Common::Rect &area, const Graphics::Surface &src) {
|
||||
// Set the texture on the active texture unit.
|
||||
bind();
|
||||
|
||||
// Update the actual texture.
|
||||
// Although we have the area of the texture buffer we want to update we
|
||||
// cannot take advantage of the left/right boundries here because it is
|
||||
// not possible to specify a pitch to glTexSubImage2D. To be precise, with
|
||||
// plain OpenGL we could set GL_UNPACK_ROW_LENGTH to achieve this. However,
|
||||
// OpenGL ES 1.0 does not support GL_UNPACK_ROW_LENGTH. Thus, we are left
|
||||
// with the following options:
|
||||
//
|
||||
// 1) (As we do right now) Simply always update the whole texture lines of
|
||||
// rect changed. This is simplest to implement. In case performance is
|
||||
// really an issue we can think of switching to another method.
|
||||
//
|
||||
// 2) Copy the dirty rect to a temporary buffer and upload that by using
|
||||
// glTexSubImage2D. This is what the Android backend does. It is more
|
||||
// complicated though.
|
||||
//
|
||||
// 3) Use glTexSubImage2D per line changed. This is what the old OpenGL
|
||||
// graphics manager did but it is much slower! Thus, we do not use it.
|
||||
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, area.top, src.w, area.height(),
|
||||
_glFormat, _glType, src.getBasePtr(0, area.top)));
|
||||
}
|
||||
|
||||
//
|
||||
// Surface
|
||||
//
|
||||
|
||||
Surface::Surface()
|
||||
: _allDirty(false), _dirtyArea() {
|
||||
}
|
||||
|
||||
void Surface::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcPtr, uint srcPitch) {
|
||||
Graphics::Surface *dstSurf = getSurface();
|
||||
assert(x + w <= dstSurf->w);
|
||||
assert(y + h <= dstSurf->h);
|
||||
|
||||
// *sigh* Common::Rect::extend behaves unexpected whenever one of the two
|
||||
// parameters is an empty rect. Thus, we check whether the current dirty
|
||||
// area is valid. In case it is not we simply use the parameters as new
|
||||
// dirty area. Otherwise, we simply call extend.
|
||||
if (_dirtyArea.isEmpty()) {
|
||||
_dirtyArea = Common::Rect(x, y, x + w, y + h);
|
||||
} else {
|
||||
_dirtyArea.extend(Common::Rect(x, y, x + w, y + h));
|
||||
}
|
||||
|
||||
const byte *src = (const byte *)srcPtr;
|
||||
byte *dst = (byte *)dstSurf->getBasePtr(x, y);
|
||||
const uint pitch = dstSurf->pitch;
|
||||
const uint bytesPerPixel = dstSurf->format.bytesPerPixel;
|
||||
|
||||
if (srcPitch == pitch && x == 0 && w == dstSurf->w) {
|
||||
memcpy(dst, src, h * pitch);
|
||||
} else {
|
||||
while (h-- > 0) {
|
||||
memcpy(dst, src, w * bytesPerPixel);
|
||||
dst += pitch;
|
||||
src += srcPitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Surface::fill(uint32 color) {
|
||||
Graphics::Surface *dst = getSurface();
|
||||
dst->fillRect(Common::Rect(dst->w, dst->h), color);
|
||||
|
||||
flagDirty();
|
||||
}
|
||||
|
||||
Common::Rect Surface::getDirtyArea() const {
|
||||
if (_allDirty) {
|
||||
return Common::Rect(getWidth(), getHeight());
|
||||
} else {
|
||||
return _dirtyArea;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Surface implementations
|
||||
//
|
||||
|
||||
Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format)
|
||||
: Surface(), _format(format), _glTexture(glIntFormat, glFormat, glType),
|
||||
_textureData(), _userPixelData() {
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
_textureData.free();
|
||||
}
|
||||
|
||||
void Texture::destroy() {
|
||||
_glTexture.destroy();
|
||||
}
|
||||
|
||||
void Texture::recreate() {
|
||||
_glTexture.create();
|
||||
|
||||
// In case image date exists assure it will be completely refreshed next
|
||||
// time.
|
||||
if (_textureData.getPixels()) {
|
||||
flagDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::enableLinearFiltering(bool enable) {
|
||||
_glTexture.enableLinearFiltering(enable);
|
||||
}
|
||||
|
||||
void Texture::allocate(uint width, uint height) {
|
||||
// Assure the texture can contain our user data.
|
||||
_glTexture.setSize(width, height);
|
||||
|
||||
// In case the needed texture dimension changed we will reinitialize the
|
||||
// texture data buffer.
|
||||
if (_glTexture.getWidth() != _textureData.w || _glTexture.getHeight() != _textureData.h) {
|
||||
// Create a buffer for the texture data.
|
||||
_textureData.create(_glTexture.getWidth(), _glTexture.getHeight(), _format);
|
||||
}
|
||||
|
||||
// Create a sub-buffer for raw access.
|
||||
_userPixelData = _textureData.getSubArea(Common::Rect(width, height));
|
||||
|
||||
// The whole texture is dirty after we changed the size. This fixes
|
||||
// multiple texture size changes without any actual update in between.
|
||||
// Without this we might try to write a too big texture into the GL
|
||||
// texture.
|
||||
flagDirty();
|
||||
}
|
||||
|
||||
void Texture::updateGLTexture() {
|
||||
if (!isDirty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Rect dirtyArea = getDirtyArea();
|
||||
|
||||
// In case we use linear filtering we might need to duplicate the last
|
||||
// pixel row/column to avoid glitches with filtering.
|
||||
if (_glTexture.isLinearFilteringEnabled()) {
|
||||
if (dirtyArea.right == _userPixelData.w && _userPixelData.w != _textureData.w) {
|
||||
uint height = dirtyArea.height();
|
||||
|
||||
const byte *src = (const byte *)_textureData.getBasePtr(_userPixelData.w - 1, dirtyArea.top);
|
||||
byte *dst = (byte *)_textureData.getBasePtr(_userPixelData.w, dirtyArea.top);
|
||||
|
||||
while (height-- > 0) {
|
||||
memcpy(dst, src, _textureData.format.bytesPerPixel);
|
||||
dst += _textureData.pitch;
|
||||
src += _textureData.pitch;
|
||||
}
|
||||
|
||||
// Extend the dirty area.
|
||||
++dirtyArea.right;
|
||||
}
|
||||
|
||||
if (dirtyArea.bottom == _userPixelData.h && _userPixelData.h != _textureData.h) {
|
||||
const byte *src = (const byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h - 1);
|
||||
byte *dst = (byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h);
|
||||
memcpy(dst, src, dirtyArea.width() * _textureData.format.bytesPerPixel);
|
||||
|
||||
// Extend the dirty area.
|
||||
++dirtyArea.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
_glTexture.updateArea(dirtyArea, _textureData);
|
||||
|
||||
// We should have handled everything, thus not dirty anymore.
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
TextureCLUT8::TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format)
|
||||
: Texture(glIntFormat, glFormat, glType, format), _clut8Data(), _palette(new byte[256 * format.bytesPerPixel]) {
|
||||
memset(_palette, 0, sizeof(byte) * format.bytesPerPixel);
|
||||
}
|
||||
|
||||
TextureCLUT8::~TextureCLUT8() {
|
||||
delete[] _palette;
|
||||
_palette = nullptr;
|
||||
_clut8Data.free();
|
||||
}
|
||||
|
||||
void TextureCLUT8::allocate(uint width, uint height) {
|
||||
Texture::allocate(width, height);
|
||||
|
||||
// We only need to reinitialize our CLUT8 surface when the output size
|
||||
// changed.
|
||||
if (width == _clut8Data.w && height == _clut8Data.h) {
|
||||
return;
|
||||
}
|
||||
|
||||
_clut8Data.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
}
|
||||
|
||||
Graphics::PixelFormat TextureCLUT8::getFormat() const {
|
||||
return Graphics::PixelFormat::createFormatCLUT8();
|
||||
}
|
||||
|
||||
void TextureCLUT8::setColorKey(uint colorKey) {
|
||||
// The key color is set to black so the color value is pre-multiplied with the alpha value
|
||||
// to avoid color fringes due to filtering.
|
||||
// Erasing the color data is not a problem as the palette is always fully re-initialized
|
||||
// before setting the key color.
|
||||
if (_format.bytesPerPixel == 2) {
|
||||
uint16 *palette = (uint16 *)_palette + colorKey;
|
||||
*palette = 0;
|
||||
} else if (_format.bytesPerPixel == 4) {
|
||||
uint32 *palette = (uint32 *)_palette + colorKey;
|
||||
*palette = 0;
|
||||
} else {
|
||||
warning("TextureCLUT8::setColorKey: Unsupported pixel depth %d", _format.bytesPerPixel);
|
||||
}
|
||||
|
||||
// A palette changes means we need to refresh the whole surface.
|
||||
flagDirty();
|
||||
}
|
||||
|
||||
namespace {
|
||||
template<typename ColorType>
|
||||
inline void convertPalette(ColorType *dst, const byte *src, uint colors, const Graphics::PixelFormat &format) {
|
||||
while (colors-- > 0) {
|
||||
*dst++ = format.RGBToColor(src[0], src[1], src[2]);
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
} // End of anonymous namespace
|
||||
|
||||
void TextureCLUT8::setPalette(uint start, uint colors, const byte *palData) {
|
||||
if (_format.bytesPerPixel == 2) {
|
||||
convertPalette<uint16>((uint16 *)_palette + start, palData, colors, _format);
|
||||
} else if (_format.bytesPerPixel == 4) {
|
||||
convertPalette<uint32>((uint32 *)_palette + start, palData, colors, _format);
|
||||
} else {
|
||||
warning("TextureCLUT8::setPalette: Unsupported pixel depth: %d", _format.bytesPerPixel);
|
||||
}
|
||||
|
||||
// A palette changes means we need to refresh the whole surface.
|
||||
flagDirty();
|
||||
}
|
||||
|
||||
namespace {
|
||||
template<typename PixelType>
|
||||
inline void doPaletteLookUp(PixelType *dst, const byte *src, uint width, uint height, uint dstPitch, uint srcPitch, const PixelType *palette) {
|
||||
uint srcAdd = srcPitch - width;
|
||||
uint dstAdd = dstPitch - width * sizeof(PixelType);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (uint x = width; x > 0; --x) {
|
||||
*dst++ = palette[*src++];
|
||||
}
|
||||
|
||||
dst = (PixelType *)((byte *)dst + dstAdd);
|
||||
src += srcAdd;
|
||||
}
|
||||
}
|
||||
} // End of anonymous namespace
|
||||
|
||||
void TextureCLUT8::updateGLTexture() {
|
||||
if (!isDirty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do the palette look up
|
||||
Graphics::Surface *outSurf = Texture::getSurface();
|
||||
|
||||
Common::Rect dirtyArea = getDirtyArea();
|
||||
|
||||
if (outSurf->format.bytesPerPixel == 2) {
|
||||
doPaletteLookUp<uint16>((uint16 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top),
|
||||
(const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top),
|
||||
dirtyArea.width(), dirtyArea.height(),
|
||||
outSurf->pitch, _clut8Data.pitch, (const uint16 *)_palette);
|
||||
} else if (outSurf->format.bytesPerPixel == 4) {
|
||||
doPaletteLookUp<uint32>((uint32 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top),
|
||||
(const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top),
|
||||
dirtyArea.width(), dirtyArea.height(),
|
||||
outSurf->pitch, _clut8Data.pitch, (const uint32 *)_palette);
|
||||
} else {
|
||||
warning("TextureCLUT8::updateGLTexture: Unsupported pixel depth: %d", outSurf->format.bytesPerPixel);
|
||||
}
|
||||
|
||||
// Do generic handling of updating the texture.
|
||||
Texture::updateGLTexture();
|
||||
}
|
||||
|
||||
#if !USE_FORCED_GL
|
||||
FakeTexture::FakeTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format)
|
||||
: Texture(glIntFormat, glFormat, glType, format),
|
||||
_rgbData() {
|
||||
}
|
||||
|
||||
FakeTexture::~FakeTexture() {
|
||||
_rgbData.free();
|
||||
}
|
||||
|
||||
void FakeTexture::allocate(uint width, uint height) {
|
||||
Texture::allocate(width, height);
|
||||
|
||||
// We only need to reinitialize our surface when the output size
|
||||
// changed.
|
||||
if (width == _rgbData.w && height == _rgbData.h) {
|
||||
return;
|
||||
}
|
||||
|
||||
warning("%s pixel format not supported by OpenGL ES, using %s instead", getFormat().toString().c_str(), _format.toString().c_str());
|
||||
_rgbData.create(width, height, getFormat());
|
||||
}
|
||||
|
||||
TextureRGB555::TextureRGB555()
|
||||
: FakeTexture(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) {
|
||||
}
|
||||
|
||||
Graphics::PixelFormat TextureRGB555::getFormat() const {
|
||||
return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
|
||||
}
|
||||
|
||||
void TextureRGB555::updateGLTexture() {
|
||||
if (!isDirty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert color space.
|
||||
Graphics::Surface *outSurf = Texture::getSurface();
|
||||
|
||||
const Common::Rect dirtyArea = getDirtyArea();
|
||||
|
||||
uint16 *dst = (uint16 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top);
|
||||
const uint dstAdd = outSurf->pitch - 2 * dirtyArea.width();
|
||||
|
||||
const uint16 *src = (const uint16 *)_rgbData.getBasePtr(dirtyArea.left, dirtyArea.top);
|
||||
const uint srcAdd = _rgbData.pitch - 2 * dirtyArea.width();
|
||||
|
||||
for (int height = dirtyArea.height(); height > 0; --height) {
|
||||
for (int width = dirtyArea.width(); width > 0; --width) {
|
||||
const uint16 color = *src++;
|
||||
|
||||
*dst++ = ((color & 0x7C00) << 1) // R
|
||||
| (((color & 0x03E0) << 1) | ((color & 0x0200) >> 4)) // G
|
||||
| (color & 0x001F); // B
|
||||
}
|
||||
|
||||
src = (const uint16 *)((const byte *)src + srcAdd);
|
||||
dst = (uint16 *)((byte *)dst + dstAdd);
|
||||
}
|
||||
|
||||
// Do generic handling of updating the texture.
|
||||
Texture::updateGLTexture();
|
||||
}
|
||||
|
||||
TextureRGBA8888Swap::TextureRGBA8888Swap()
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
: FakeTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) // ABGR8888
|
||||
#else
|
||||
: FakeTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) // RGBA8888
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
Graphics::PixelFormat TextureRGBA8888Swap::getFormat() const {
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); // RGBA8888
|
||||
#else
|
||||
return Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24); // ABGR8888
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureRGBA8888Swap::updateGLTexture() {
|
||||
if (!isDirty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert color space.
|
||||
Graphics::Surface *outSurf = Texture::getSurface();
|
||||
|
||||
const Common::Rect dirtyArea = getDirtyArea();
|
||||
|
||||
uint32 *dst = (uint32 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top);
|
||||
const uint dstAdd = outSurf->pitch - 4 * dirtyArea.width();
|
||||
|
||||
const uint32 *src = (const uint32 *)_rgbData.getBasePtr(dirtyArea.left, dirtyArea.top);
|
||||
const uint srcAdd = _rgbData.pitch - 4 * dirtyArea.width();
|
||||
|
||||
for (int height = dirtyArea.height(); height > 0; --height) {
|
||||
for (int width = dirtyArea.width(); width > 0; --width) {
|
||||
const uint32 color = *src++;
|
||||
|
||||
*dst++ = SWAP_BYTES_32(color);
|
||||
}
|
||||
|
||||
src = (const uint32 *)((const byte *)src + srcAdd);
|
||||
dst = (uint32 *)((byte *)dst + dstAdd);
|
||||
}
|
||||
|
||||
// Do generic handling of updating the texture.
|
||||
Texture::updateGLTexture();
|
||||
}
|
||||
#endif // !USE_FORCED_GL
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
|
||||
// _clut8Texture needs 8 bits internal precision, otherwise graphics glitches
|
||||
// can occur. GL_ALPHA does not have any internal precision requirements.
|
||||
// However, in practice (according to fuzzie) it's 8bit. If we run into
|
||||
// problems, we need to switch to GL_R8 and GL_RED, but that is only supported
|
||||
// for ARB_texture_rg and GLES3+ (EXT_rexture_rg does not support GL_R8).
|
||||
TextureCLUT8GPU::TextureCLUT8GPU()
|
||||
: _clut8Texture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE),
|
||||
_paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE),
|
||||
_target(new TextureTarget()), _clut8Pipeline(new CLUT8LookUpPipeline()),
|
||||
_clut8Vertices(), _clut8Data(), _userPixelData(), _palette(),
|
||||
_paletteDirty(false) {
|
||||
// Allocate space for 256 colors.
|
||||
_paletteTexture.setSize(256, 1);
|
||||
|
||||
// Setup pipeline.
|
||||
_clut8Pipeline->setFramebuffer(_target);
|
||||
_clut8Pipeline->setPaletteTexture(&_paletteTexture);
|
||||
_clut8Pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
TextureCLUT8GPU::~TextureCLUT8GPU() {
|
||||
delete _clut8Pipeline;
|
||||
delete _target;
|
||||
_clut8Data.free();
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::destroy() {
|
||||
_clut8Texture.destroy();
|
||||
_paletteTexture.destroy();
|
||||
_target->destroy();
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::recreate() {
|
||||
_clut8Texture.create();
|
||||
_paletteTexture.create();
|
||||
_target->create();
|
||||
|
||||
// In case image date exists assure it will be completely refreshed next
|
||||
// time.
|
||||
if (_clut8Data.getPixels()) {
|
||||
flagDirty();
|
||||
_paletteDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::enableLinearFiltering(bool enable) {
|
||||
_target->getTexture()->enableLinearFiltering(enable);
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::allocate(uint width, uint height) {
|
||||
// Assure the texture can contain our user data.
|
||||
_clut8Texture.setSize(width, height);
|
||||
_target->setSize(width, height);
|
||||
|
||||
// In case the needed texture dimension changed we will reinitialize the
|
||||
// texture data buffer.
|
||||
if (_clut8Texture.getWidth() != _clut8Data.w || _clut8Texture.getHeight() != _clut8Data.h) {
|
||||
// Create a buffer for the texture data.
|
||||
_clut8Data.create(_clut8Texture.getWidth(), _clut8Texture.getHeight(), Graphics::PixelFormat::createFormatCLUT8());
|
||||
}
|
||||
|
||||
// Create a sub-buffer for raw access.
|
||||
_userPixelData = _clut8Data.getSubArea(Common::Rect(width, height));
|
||||
|
||||
// Setup structures for internal rendering to _glTexture.
|
||||
_clut8Vertices[0] = 0;
|
||||
_clut8Vertices[1] = 0;
|
||||
|
||||
_clut8Vertices[2] = width;
|
||||
_clut8Vertices[3] = 0;
|
||||
|
||||
_clut8Vertices[4] = 0;
|
||||
_clut8Vertices[5] = height;
|
||||
|
||||
_clut8Vertices[6] = width;
|
||||
_clut8Vertices[7] = height;
|
||||
|
||||
// The whole texture is dirty after we changed the size. This fixes
|
||||
// multiple texture size changes without any actual update in between.
|
||||
// Without this we might try to write a too big texture into the GL
|
||||
// texture.
|
||||
flagDirty();
|
||||
}
|
||||
|
||||
Graphics::PixelFormat TextureCLUT8GPU::getFormat() const {
|
||||
return Graphics::PixelFormat::createFormatCLUT8();
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::setColorKey(uint colorKey) {
|
||||
// The key color is set to black so the color value is pre-multiplied with the alpha value
|
||||
// to avoid color fringes due to filtering.
|
||||
// Erasing the color data is not a problem as the palette is always fully re-initialized
|
||||
// before setting the key color.
|
||||
_palette[colorKey * 4 ] = 0x00;
|
||||
_palette[colorKey * 4 + 1] = 0x00;
|
||||
_palette[colorKey * 4 + 2] = 0x00;
|
||||
_palette[colorKey * 4 + 3] = 0x00;
|
||||
|
||||
_paletteDirty = true;
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::setPalette(uint start, uint colors, const byte *palData) {
|
||||
byte *dst = _palette + start * 4;
|
||||
|
||||
while (colors-- > 0) {
|
||||
memcpy(dst, palData, 3);
|
||||
dst[3] = 0xFF;
|
||||
|
||||
dst += 4;
|
||||
palData += 3;
|
||||
}
|
||||
|
||||
_paletteDirty = true;
|
||||
}
|
||||
|
||||
const GLTexture &TextureCLUT8GPU::getGLTexture() const {
|
||||
return *_target->getTexture();
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::updateGLTexture() {
|
||||
const bool needLookUp = Surface::isDirty() || _paletteDirty;
|
||||
|
||||
// Update CLUT8 texture if necessary.
|
||||
if (Surface::isDirty()) {
|
||||
_clut8Texture.updateArea(getDirtyArea(), _clut8Data);
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
// Update palette if necessary.
|
||||
if (_paletteDirty) {
|
||||
Graphics::Surface palSurface;
|
||||
palSurface.init(256, 1, 256, _palette,
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24) // ABGR8888
|
||||
#else
|
||||
Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0) // RGBA8888
|
||||
#endif
|
||||
);
|
||||
|
||||
_paletteTexture.updateArea(Common::Rect(256, 1), palSurface);
|
||||
_paletteDirty = false;
|
||||
}
|
||||
|
||||
// In case any data changed, do color look up and store result in _target.
|
||||
if (needLookUp) {
|
||||
lookUpColors();
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCLUT8GPU::lookUpColors() {
|
||||
// Setup pipeline to do color look up.
|
||||
Pipeline *oldPipeline = g_context.setPipeline(_clut8Pipeline);
|
||||
|
||||
// Do color look up.
|
||||
g_context.getActivePipeline()->drawTexture(_clut8Texture, _clut8Vertices);
|
||||
|
||||
// Restore old state.
|
||||
g_context.setPipeline(oldPipeline);
|
||||
}
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
419
backends/graphics/opengl/texture.h
Normal file
419
backends/graphics/opengl/texture.h
Normal file
@ -0,0 +1,419 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGL_TEXTURE_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_TEXTURE_H
|
||||
|
||||
#include "backends/graphics/opengl/opengl-sys.h"
|
||||
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class Shader;
|
||||
|
||||
/**
|
||||
* A simple GL texture object abstraction.
|
||||
*
|
||||
* This is used for low-level GL texture handling.
|
||||
*/
|
||||
class GLTexture {
|
||||
public:
|
||||
/**
|
||||
* Constrcut a new GL texture object.
|
||||
*
|
||||
* @param glIntFormat The internal format to use.
|
||||
* @param glFormat The input format.
|
||||
* @param glType The input type.
|
||||
*/
|
||||
GLTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType);
|
||||
~GLTexture();
|
||||
|
||||
/**
|
||||
* Enable or disable linear texture filtering.
|
||||
*
|
||||
* @param enable true to enable and false to disable.
|
||||
*/
|
||||
void enableLinearFiltering(bool enable);
|
||||
|
||||
/**
|
||||
* Test whether linear filtering is enabled.
|
||||
*/
|
||||
bool isLinearFilteringEnabled() const { return (_glFilter == GL_LINEAR); }
|
||||
|
||||
/**
|
||||
* Destroy the OpenGL texture name.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Create the OpenGL texture name.
|
||||
*/
|
||||
void create();
|
||||
|
||||
/**
|
||||
* Bind the texture to the active texture unit.
|
||||
*/
|
||||
void bind() const;
|
||||
|
||||
/**
|
||||
* Sets the size of the texture in pixels.
|
||||
*
|
||||
* The internal OpenGL texture might have a different size. To query the
|
||||
* actual size use getWidth()/getHeight().
|
||||
*
|
||||
* @param width The desired logical width.
|
||||
* @param height The desired logical height.
|
||||
*/
|
||||
void setSize(uint width, uint height);
|
||||
|
||||
/**
|
||||
* Copy image data to the texture.
|
||||
*
|
||||
* @param area The area to update.
|
||||
* @param src Surface for the whole texture containing the pixel data
|
||||
* to upload. Only the area described by area will be
|
||||
* uploaded.
|
||||
*/
|
||||
void updateArea(const Common::Rect &area, const Graphics::Surface &src);
|
||||
|
||||
/**
|
||||
* Query the GL texture's width.
|
||||
*/
|
||||
uint getWidth() const { return _width; }
|
||||
|
||||
/**
|
||||
* Query the GL texture's height.
|
||||
*/
|
||||
uint getHeight() const { return _height; }
|
||||
|
||||
/**
|
||||
* Query the logical texture's width.
|
||||
*/
|
||||
uint getLogicalWidth() const { return _logicalWidth; }
|
||||
|
||||
/**
|
||||
* Query the logical texture's height.
|
||||
*/
|
||||
uint getLogicalHeight() const { return _logicalHeight; }
|
||||
|
||||
/**
|
||||
* Obtain texture coordinates for rectangular drawing.
|
||||
*/
|
||||
const GLfloat *getTexCoords() const { return _texCoords; }
|
||||
|
||||
/**
|
||||
* Obtain texture name.
|
||||
*
|
||||
* Beware that the texture name changes whenever create is used.
|
||||
* destroy will invalidate the texture name.
|
||||
*/
|
||||
GLuint getGLTexture() const { return _glTexture; }
|
||||
private:
|
||||
const GLenum _glIntFormat;
|
||||
const GLenum _glFormat;
|
||||
const GLenum _glType;
|
||||
|
||||
uint _width, _height;
|
||||
uint _logicalWidth, _logicalHeight;
|
||||
GLfloat _texCoords[4*2];
|
||||
|
||||
GLint _glFilter;
|
||||
|
||||
GLuint _glTexture;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for OpenGL implementations of a 2D surface.
|
||||
*/
|
||||
class Surface {
|
||||
public:
|
||||
Surface();
|
||||
virtual ~Surface() {}
|
||||
|
||||
/**
|
||||
* Destroy OpenGL description of surface.
|
||||
*/
|
||||
virtual void destroy() = 0;
|
||||
|
||||
/**
|
||||
* Recreate OpenGL description of surface.
|
||||
*/
|
||||
virtual void recreate() = 0;
|
||||
|
||||
/**
|
||||
* Enable or disable linear texture filtering.
|
||||
*
|
||||
* @param enable true to enable and false to disable.
|
||||
*/
|
||||
virtual void enableLinearFiltering(bool enable) = 0;
|
||||
|
||||
/**
|
||||
* Allocate storage for surface.
|
||||
*
|
||||
* @param width The desired logical width.
|
||||
* @param height The desired logical height.
|
||||
*/
|
||||
virtual void allocate(uint width, uint height) = 0;
|
||||
|
||||
/**
|
||||
* Copy image data to the surface.
|
||||
*
|
||||
* The format of the input data needs to match the format returned by
|
||||
* getFormat.
|
||||
*
|
||||
* @param x X coordinate of upper left corner to copy data to.
|
||||
* @param y Y coordinate of upper left corner to copy data to.
|
||||
* @param w Width of the image data to copy.
|
||||
* @param h Height of the image data to copy.
|
||||
* @param src Pointer to image data.
|
||||
* @param srcPitch The number of bytes in a row of the image data.
|
||||
*/
|
||||
void copyRectToTexture(uint x, uint y, uint w, uint h, const void *src, uint srcPitch);
|
||||
|
||||
/**
|
||||
* Fill the surface with a fixed color.
|
||||
*
|
||||
* @param color Color value in format returned by getFormat.
|
||||
*/
|
||||
void fill(uint32 color);
|
||||
|
||||
void flagDirty() { _allDirty = true; }
|
||||
virtual bool isDirty() const { return _allDirty || !_dirtyArea.isEmpty(); }
|
||||
|
||||
virtual uint getWidth() const = 0;
|
||||
virtual uint getHeight() const = 0;
|
||||
|
||||
/**
|
||||
* @return The logical format of the texture data.
|
||||
*/
|
||||
virtual Graphics::PixelFormat getFormat() const = 0;
|
||||
|
||||
virtual Graphics::Surface *getSurface() = 0;
|
||||
virtual const Graphics::Surface *getSurface() const = 0;
|
||||
|
||||
/**
|
||||
* @return Whether the surface is having a palette.
|
||||
*/
|
||||
virtual bool hasPalette() const { return false; }
|
||||
|
||||
/**
|
||||
* Set color key for paletted textures.
|
||||
*
|
||||
* This needs to be called after any palette update affecting the color
|
||||
* key. Calling this multiple times will result in multiple color indices
|
||||
* to be treated as color keys.
|
||||
*/
|
||||
virtual void setColorKey(uint colorKey) {}
|
||||
virtual void setPalette(uint start, uint colors, const byte *palData) {}
|
||||
|
||||
/**
|
||||
* Update underlying OpenGL texture to reflect current state.
|
||||
*/
|
||||
virtual void updateGLTexture() = 0;
|
||||
|
||||
/**
|
||||
* Obtain underlying OpenGL texture.
|
||||
*/
|
||||
virtual const GLTexture &getGLTexture() const = 0;
|
||||
protected:
|
||||
void clearDirty() { _allDirty = false; _dirtyArea = Common::Rect(); }
|
||||
|
||||
Common::Rect getDirtyArea() const;
|
||||
private:
|
||||
bool _allDirty;
|
||||
Common::Rect _dirtyArea;
|
||||
};
|
||||
|
||||
/**
|
||||
* An OpenGL texture wrapper. It automatically takes care of all OpenGL
|
||||
* texture handling issues and also provides access to the texture data.
|
||||
*/
|
||||
class Texture : public Surface {
|
||||
public:
|
||||
/**
|
||||
* Create a new texture with the specific internal format.
|
||||
*
|
||||
* @param glIntFormat The internal format to use.
|
||||
* @param glFormat The input format.
|
||||
* @param glType The input type.
|
||||
* @param format The format used for the texture input.
|
||||
*/
|
||||
Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format);
|
||||
virtual ~Texture();
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
virtual void recreate();
|
||||
|
||||
virtual void enableLinearFiltering(bool enable);
|
||||
|
||||
virtual void allocate(uint width, uint height);
|
||||
|
||||
virtual uint getWidth() const { return _userPixelData.w; }
|
||||
virtual uint getHeight() const { return _userPixelData.h; }
|
||||
|
||||
/**
|
||||
* @return The logical format of the texture data.
|
||||
*/
|
||||
virtual Graphics::PixelFormat getFormat() const { return _format; }
|
||||
|
||||
virtual Graphics::Surface *getSurface() { return &_userPixelData; }
|
||||
virtual const Graphics::Surface *getSurface() const { return &_userPixelData; }
|
||||
|
||||
virtual void updateGLTexture();
|
||||
virtual const GLTexture &getGLTexture() const { return _glTexture; }
|
||||
protected:
|
||||
const Graphics::PixelFormat _format;
|
||||
|
||||
private:
|
||||
GLTexture _glTexture;
|
||||
|
||||
Graphics::Surface _textureData;
|
||||
Graphics::Surface _userPixelData;
|
||||
};
|
||||
|
||||
class TextureCLUT8 : public Texture {
|
||||
public:
|
||||
TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format);
|
||||
virtual ~TextureCLUT8();
|
||||
|
||||
virtual void allocate(uint width, uint height);
|
||||
|
||||
virtual Graphics::PixelFormat getFormat() const;
|
||||
|
||||
virtual bool hasPalette() const { return true; }
|
||||
|
||||
virtual void setColorKey(uint colorKey);
|
||||
virtual void setPalette(uint start, uint colors, const byte *palData);
|
||||
|
||||
virtual Graphics::Surface *getSurface() { return &_clut8Data; }
|
||||
virtual const Graphics::Surface *getSurface() const { return &_clut8Data; }
|
||||
|
||||
virtual void updateGLTexture();
|
||||
private:
|
||||
Graphics::Surface _clut8Data;
|
||||
byte *_palette;
|
||||
};
|
||||
|
||||
#if !USE_FORCED_GL
|
||||
class FakeTexture : public Texture {
|
||||
public:
|
||||
FakeTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format);
|
||||
virtual ~FakeTexture();
|
||||
|
||||
virtual void allocate(uint width, uint height);
|
||||
|
||||
virtual Graphics::PixelFormat getFormat() const = 0;
|
||||
|
||||
virtual Graphics::Surface *getSurface() { return &_rgbData; }
|
||||
virtual const Graphics::Surface *getSurface() const { return &_rgbData; }
|
||||
protected:
|
||||
Graphics::Surface _rgbData;
|
||||
};
|
||||
|
||||
class TextureRGB555 : public FakeTexture {
|
||||
public:
|
||||
TextureRGB555();
|
||||
virtual ~TextureRGB555() {};
|
||||
|
||||
virtual Graphics::PixelFormat getFormat() const;
|
||||
|
||||
virtual void updateGLTexture();
|
||||
};
|
||||
|
||||
class TextureRGBA8888Swap : public FakeTexture {
|
||||
public:
|
||||
TextureRGBA8888Swap();
|
||||
virtual ~TextureRGBA8888Swap() {};
|
||||
|
||||
virtual Graphics::PixelFormat getFormat() const;
|
||||
|
||||
virtual void updateGLTexture();
|
||||
};
|
||||
#endif // !USE_FORCED_GL
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
class TextureTarget;
|
||||
class CLUT8LookUpPipeline;
|
||||
|
||||
class TextureCLUT8GPU : public Surface {
|
||||
public:
|
||||
TextureCLUT8GPU();
|
||||
virtual ~TextureCLUT8GPU();
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
virtual void recreate();
|
||||
|
||||
virtual void enableLinearFiltering(bool enable);
|
||||
|
||||
virtual void allocate(uint width, uint height);
|
||||
|
||||
virtual bool isDirty() const { return _paletteDirty || Surface::isDirty(); }
|
||||
|
||||
virtual uint getWidth() const { return _userPixelData.w; }
|
||||
virtual uint getHeight() const { return _userPixelData.h; }
|
||||
|
||||
virtual Graphics::PixelFormat getFormat() const;
|
||||
|
||||
virtual bool hasPalette() const { return true; }
|
||||
|
||||
virtual void setColorKey(uint colorKey);
|
||||
virtual void setPalette(uint start, uint colors, const byte *palData);
|
||||
|
||||
virtual Graphics::Surface *getSurface() { return &_userPixelData; }
|
||||
virtual const Graphics::Surface *getSurface() const { return &_userPixelData; }
|
||||
|
||||
virtual void updateGLTexture();
|
||||
virtual const GLTexture &getGLTexture() const;
|
||||
|
||||
static bool isSupportedByContext() {
|
||||
return g_context.shadersSupported
|
||||
&& g_context.multitextureSupported
|
||||
&& g_context.framebufferObjectSupported;
|
||||
}
|
||||
private:
|
||||
void lookUpColors();
|
||||
|
||||
GLTexture _clut8Texture;
|
||||
GLTexture _paletteTexture;
|
||||
|
||||
TextureTarget *_target;
|
||||
CLUT8LookUpPipeline *_clut8Pipeline;
|
||||
|
||||
GLfloat _clut8Vertices[4*2];
|
||||
|
||||
Graphics::Surface _clut8Data;
|
||||
Graphics::Surface _userPixelData;
|
||||
|
||||
byte _palette[4 * 256];
|
||||
bool _paletteDirty;
|
||||
};
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
675
backends/graphics/openglsdl/openglsdl-graphics.cpp
Normal file
675
backends/graphics/openglsdl/openglsdl-graphics.cpp
Normal file
@ -0,0 +1,675 @@
|
||||
/* 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/openglsdl/openglsdl-graphics.h"
|
||||
#include "backends/graphics/opengl/texture.h"
|
||||
#include "backends/events/sdl/sdl-events.h"
|
||||
#include "backends/platform/sdl/sdl.h"
|
||||
#include "graphics/scaler/aspect.h"
|
||||
|
||||
#include "common/textconsole.h"
|
||||
#include "common/config-manager.h"
|
||||
#ifdef USE_OSD
|
||||
#include "common/translation.h"
|
||||
#endif
|
||||
|
||||
OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource, SdlWindow *window)
|
||||
: SdlGraphicsManager(eventSource, window), _lastRequestedHeight(0),
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
_glContext(),
|
||||
#else
|
||||
_lastVideoModeLoad(0),
|
||||
#endif
|
||||
_graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
|
||||
_desiredFullscreenWidth(0), _desiredFullscreenHeight(0) {
|
||||
// Setup OpenGL attributes for SDL
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
// Set up proper SDL OpenGL context creation.
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
OpenGL::ContextType glContextType;
|
||||
|
||||
// Context version 1.4 is choosen arbitrarily based on what most shader
|
||||
// extensions were written against.
|
||||
enum {
|
||||
DEFAULT_GL_MAJOR = 1,
|
||||
DEFAULT_GL_MINOR = 4,
|
||||
|
||||
DEFAULT_GLES_MAJOR = 1,
|
||||
DEFAULT_GLES_MINOR = 1,
|
||||
|
||||
DEFAULT_GLES2_MAJOR = 2,
|
||||
DEFAULT_GLES2_MINOR = 0
|
||||
};
|
||||
|
||||
#if USE_FORCED_GL
|
||||
glContextType = OpenGL::kContextGL;
|
||||
_glContextProfileMask = 0;
|
||||
_glContextMajor = DEFAULT_GL_MAJOR;
|
||||
_glContextMinor = DEFAULT_GL_MINOR;
|
||||
#elif USE_FORCED_GLES
|
||||
glContextType = OpenGL::kContextGLES;
|
||||
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
|
||||
_glContextMajor = DEFAULT_GLES_MAJOR;
|
||||
_glContextMinor = DEFAULT_GLES_MINOR;
|
||||
#elif USE_FORCED_GLES2
|
||||
glContextType = OpenGL::kContextGLES2;
|
||||
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
|
||||
_glContextMajor = DEFAULT_GLES2_MAJOR;
|
||||
_glContextMinor = DEFAULT_GLES2_MINOR;
|
||||
#else
|
||||
bool noDefaults = false;
|
||||
|
||||
// Obtain the default GL(ES) context SDL2 tries to setup.
|
||||
//
|
||||
// Please note this might not actually be SDL2's defaults when multiple
|
||||
// instances of this object have been created. But that is no issue
|
||||
// because then we already set up what we want to use.
|
||||
//
|
||||
// In case no defaults are given we prefer OpenGL over OpenGL ES.
|
||||
if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &_glContextProfileMask) != 0) {
|
||||
_glContextProfileMask = 0;
|
||||
noDefaults = true;
|
||||
}
|
||||
|
||||
if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &_glContextMajor) != 0) {
|
||||
noDefaults = true;
|
||||
}
|
||||
|
||||
if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &_glContextMinor) != 0) {
|
||||
noDefaults = true;
|
||||
}
|
||||
|
||||
if (noDefaults) {
|
||||
if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
_glContextMajor = DEFAULT_GLES_MAJOR;
|
||||
_glContextMinor = DEFAULT_GLES_MINOR;
|
||||
} else {
|
||||
_glContextProfileMask = 0;
|
||||
_glContextMajor = DEFAULT_GL_MAJOR;
|
||||
_glContextMinor = DEFAULT_GL_MINOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
if (_glContextMajor >= 2) {
|
||||
glContextType = OpenGL::kContextGLES2;
|
||||
} else {
|
||||
glContextType = OpenGL::kContextGLES;
|
||||
}
|
||||
} else if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_CORE) {
|
||||
glContextType = OpenGL::kContextGL;
|
||||
|
||||
// Core profile does not allow legacy functionality, which we use.
|
||||
// Thus we request a standard OpenGL context.
|
||||
_glContextProfileMask = 0;
|
||||
_glContextMajor = DEFAULT_GL_MAJOR;
|
||||
_glContextMinor = DEFAULT_GL_MINOR;
|
||||
} else {
|
||||
glContextType = OpenGL::kContextGL;
|
||||
}
|
||||
#endif
|
||||
|
||||
setContextType(glContextType);
|
||||
#else
|
||||
setContextType(OpenGL::kContextGL);
|
||||
#endif
|
||||
|
||||
// Retrieve a list of working fullscreen modes
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
const int numModes = SDL_GetNumDisplayModes(0);
|
||||
for (int i = 0; i < numModes; ++i) {
|
||||
SDL_DisplayMode mode;
|
||||
if (SDL_GetDisplayMode(0, i, &mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_fullscreenVideoModes.push_back(VideoMode(mode.w, mode.h));
|
||||
}
|
||||
#else
|
||||
const SDL_Rect *const *availableModes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
|
||||
// TODO: NULL means that there are no fullscreen modes supported. We
|
||||
// should probably use this information and disable any fullscreen support
|
||||
// in this case.
|
||||
if (availableModes != NULL && availableModes != (void *)-1) {
|
||||
for (;*availableModes; ++availableModes) {
|
||||
const SDL_Rect *mode = *availableModes;
|
||||
|
||||
_fullscreenVideoModes.push_back(VideoMode(mode->w, mode->h));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sort the modes in ascending order.
|
||||
Common::sort(_fullscreenVideoModes.begin(), _fullscreenVideoModes.end());
|
||||
|
||||
// Strip duplicates in video modes.
|
||||
for (uint i = 0; i + 1 < _fullscreenVideoModes.size();) {
|
||||
if (_fullscreenVideoModes[i] == _fullscreenVideoModes[i + 1]) {
|
||||
_fullscreenVideoModes.remove_at(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect desktopRes = _window->getDesktopResolution();
|
||||
|
||||
// In case SDL is fine with every mode we will force the desktop mode.
|
||||
// TODO? We could also try to add some default resolutions here.
|
||||
if (_fullscreenVideoModes.empty() && !desktopRes.isEmpty()) {
|
||||
_fullscreenVideoModes.push_back(VideoMode(desktopRes.width(), desktopRes.height()));
|
||||
}
|
||||
|
||||
// Get information about display sizes from the previous runs.
|
||||
if (ConfMan.hasKey("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain) && ConfMan.hasKey("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain)) {
|
||||
_desiredFullscreenWidth = ConfMan.getInt("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain);
|
||||
_desiredFullscreenHeight = ConfMan.getInt("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain);
|
||||
} else {
|
||||
// Use the desktop resolutions when no previous default has been setup.
|
||||
_desiredFullscreenWidth = desktopRes.width();
|
||||
_desiredFullscreenHeight = desktopRes.height();
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
notifyContextDestroy();
|
||||
SDL_GL_DeleteContext(_glContext);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) const {
|
||||
switch (f) {
|
||||
case OSystem::kFeatureFullscreenMode:
|
||||
case OSystem::kFeatureIconifyWindow:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return OpenGLGraphicsManager::hasFeature(f);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
|
||||
switch (f) {
|
||||
case OSystem::kFeatureFullscreenMode:
|
||||
assert(getTransactionMode() != kTransactionNone);
|
||||
_wantsFullScreen = enable;
|
||||
break;
|
||||
|
||||
case OSystem::kFeatureIconifyWindow:
|
||||
if (enable) {
|
||||
_window->iconifyWindow();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
OpenGLGraphicsManager::setFeatureState(f, enable);
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) const {
|
||||
switch (f) {
|
||||
case OSystem::kFeatureFullscreenMode:
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (_window) {
|
||||
return (SDL_GetWindowFlags(_window->getSDLWindow()) & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
} else {
|
||||
return _wantsFullScreen;
|
||||
}
|
||||
#else
|
||||
if (_hwScreen) {
|
||||
return (_hwScreen->flags & SDL_FULLSCREEN) != 0;
|
||||
} else {
|
||||
return _wantsFullScreen;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return OpenGLGraphicsManager::getFeatureState(f);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
|
||||
// HACK: This is stupid but the SurfaceSDL backend defaults to 2x. This
|
||||
// assures that the launcher (which requests 320x200) has a reasonable
|
||||
// size. It also makes small games have a reasonable size (i.e. at least
|
||||
// 640x400). We follow the same logic here until we have a better way to
|
||||
// give hints to our backend for that.
|
||||
if (w > 320) {
|
||||
_graphicsScale = 1;
|
||||
} else {
|
||||
_graphicsScale = 2;
|
||||
}
|
||||
|
||||
return OpenGLGraphicsManager::initSize(w, h, format);
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::updateScreen() {
|
||||
if (_ignoreResizeEvents) {
|
||||
--_ignoreResizeEvents;
|
||||
}
|
||||
|
||||
OpenGLGraphicsManager::updateScreen();
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::notifyVideoExpose() {
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::notifyResize(const int width, const int height) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
// We sometime get outdated resize events from SDL2. So check that the size we get
|
||||
// is the actual current window size. If not ignore the resize.
|
||||
// The issue for example occurs when switching from fullscreen to windowed mode or
|
||||
// when switching between different fullscreen resolutions because SDL_DestroyWindow
|
||||
// for a fullscreen window that doesn't have the SDL_WINDOW_FULLSCREEN_DESKTOP flag
|
||||
// causes a SDL_WINDOWEVENT_RESIZED event with the old resolution to be sent, and this
|
||||
// event is processed after recreating the window at the new resolution.
|
||||
int currentWidth, currentHeight;
|
||||
getWindowSizeFromSdl(¤tWidth, ¤tHeight);
|
||||
if (width != currentWidth || height != currentHeight)
|
||||
return;
|
||||
// TODO: Implement high DPI support
|
||||
handleResize(width, height, 90, 90);
|
||||
#else
|
||||
if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) {
|
||||
// We save that we handled a resize event here. We need to know this
|
||||
// so we do not overwrite the users requested window size whenever we
|
||||
// switch aspect ratio or similar.
|
||||
_gotResize = true;
|
||||
if (!setupMode(width, height)) {
|
||||
warning("OpenGLSdlGraphicsManager::notifyResize: Resize failed ('%s')", SDL_GetError());
|
||||
g_system->quit();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
|
||||
// In some cases we might not want to load the requested video mode. This
|
||||
// will assure that the window size is not altered.
|
||||
if (_ignoreLoadVideoMode) {
|
||||
_ignoreLoadVideoMode = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function should never be called from notifyResize thus we know
|
||||
// that the requested size came from somewhere else.
|
||||
_gotResize = false;
|
||||
|
||||
// Save the requested dimensions.
|
||||
_lastRequestedWidth = requestedWidth;
|
||||
_lastRequestedHeight = requestedHeight;
|
||||
|
||||
// Apply the currently saved scale setting.
|
||||
requestedWidth *= _graphicsScale;
|
||||
requestedHeight *= _graphicsScale;
|
||||
|
||||
// Set up the mode.
|
||||
return setupMode(requestedWidth, requestedHeight);
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::refreshScreen() {
|
||||
// Swap OpenGL buffers
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_GL_SwapWindow(_window->getSDLWindow());
|
||||
#else
|
||||
SDL_GL_SwapBuffers();
|
||||
#endif
|
||||
}
|
||||
|
||||
void *OpenGLSdlGraphicsManager::getProcAddress(const char *name) const {
|
||||
return SDL_GL_GetProcAddress(name);
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) {
|
||||
OpenGLGraphicsManager::handleResizeImpl(width, height, xdpi, ydpi);
|
||||
SdlGraphicsManager::handleResizeImpl(width, height, xdpi, ydpi);
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::saveScreenshot(const Common::String &filename) const {
|
||||
return OpenGLGraphicsManager::saveScreenshot(filename);
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
|
||||
// In case we request a fullscreen mode we will use the mode the user
|
||||
// has chosen last time or the biggest mode available.
|
||||
if (_wantsFullScreen) {
|
||||
if (_desiredFullscreenWidth && _desiredFullscreenHeight) {
|
||||
// In case only a distinct set of modes is available we check
|
||||
// whether the requested mode is actually available.
|
||||
if (!_fullscreenVideoModes.empty()) {
|
||||
VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(),
|
||||
_fullscreenVideoModes.end(),
|
||||
VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight));
|
||||
// It's not available fall back to default.
|
||||
if (i == _fullscreenVideoModes.end()) {
|
||||
_desiredFullscreenWidth = 0;
|
||||
_desiredFullscreenHeight = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In case no desired mode has been set we default to the biggest mode
|
||||
// available or the requested mode in case we don't know any
|
||||
// any fullscreen modes.
|
||||
if (!_desiredFullscreenWidth || !_desiredFullscreenHeight) {
|
||||
if (!_fullscreenVideoModes.empty()) {
|
||||
VideoModeArray::const_iterator i = _fullscreenVideoModes.end();
|
||||
--i;
|
||||
|
||||
_desiredFullscreenWidth = i->width;
|
||||
_desiredFullscreenHeight = i->height;
|
||||
} else {
|
||||
_desiredFullscreenWidth = width;
|
||||
_desiredFullscreenHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
// Remember our choice.
|
||||
ConfMan.setInt("last_fullscreen_mode_width", _desiredFullscreenWidth, Common::ConfigManager::kApplicationDomain);
|
||||
ConfMan.setInt("last_fullscreen_mode_height", _desiredFullscreenHeight, Common::ConfigManager::kApplicationDomain);
|
||||
}
|
||||
|
||||
// This is pretty confusing since RGBA8888 talks about the memory
|
||||
// layout here. This is a different logical layout depending on
|
||||
// whether we run on little endian or big endian. However, we can
|
||||
// only safely assume that RGBA8888 in memory layout is supported.
|
||||
// Thus, we chose this one.
|
||||
const Graphics::PixelFormat rgba8888 =
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
|
||||
#else
|
||||
Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (_glContext) {
|
||||
notifyContextDestroy();
|
||||
|
||||
SDL_GL_DeleteContext(_glContext);
|
||||
_glContext = nullptr;
|
||||
}
|
||||
|
||||
uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
||||
if (_wantsFullScreen) {
|
||||
// On Linux/X11, when toggling to fullscreen, the window manager saves
|
||||
// the window size to be able to restore it when going back to windowed mode.
|
||||
// If the user configured ScummVM to start in fullscreen mode, we first
|
||||
// create a window and then toggle it to fullscreen to give the window manager
|
||||
// a chance to save the window size. That way if the user switches back
|
||||
// to windowed mode, the window manager has a window size to apply instead
|
||||
// of leaving the window at the fullscreen resolution size.
|
||||
const char *driver = SDL_GetCurrentVideoDriver();
|
||||
if (!_window->getSDLWindow() && driver && strcmp(driver, "x11") == 0) {
|
||||
_window->createOrUpdateWindow(width, height, flags);
|
||||
}
|
||||
|
||||
width = _desiredFullscreenWidth;
|
||||
height = _desiredFullscreenHeight;
|
||||
|
||||
flags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
|
||||
// Request a OpenGL (ES) context we can use.
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, _glContextProfileMask);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);
|
||||
|
||||
if (!createOrUpdateWindow(width, height, flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_glContext = SDL_GL_CreateContext(_window->getSDLWindow());
|
||||
if (!_glContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
notifyContextCreate(rgba8888, rgba8888);
|
||||
int actualWidth, actualHeight;
|
||||
getWindowSizeFromSdl(&actualWidth, &actualHeight);
|
||||
// TODO: Implement high DPI support
|
||||
handleResize(actualWidth, actualHeight, 90, 90);
|
||||
return true;
|
||||
#else
|
||||
// WORKAROUND: Working around infamous SDL bugs when switching
|
||||
// resolutions too fast. This might cause the event system to supply
|
||||
// incorrect mouse position events otherwise.
|
||||
// Reference: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=665779
|
||||
const uint32 curTime = SDL_GetTicks();
|
||||
if (_hwScreen && (curTime < _lastVideoModeLoad || curTime - _lastVideoModeLoad < 100)) {
|
||||
for (int i = 10; i > 0; --i) {
|
||||
SDL_PumpEvents();
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 flags = SDL_OPENGL;
|
||||
if (_wantsFullScreen) {
|
||||
width = _desiredFullscreenWidth;
|
||||
height = _desiredFullscreenHeight;
|
||||
flags |= SDL_FULLSCREEN;
|
||||
} else {
|
||||
flags |= SDL_RESIZABLE;
|
||||
}
|
||||
|
||||
if (_hwScreen) {
|
||||
// When a video mode has been setup already we notify the manager that
|
||||
// the context is about to be destroyed.
|
||||
// We do this because on Windows SDL_SetVideoMode can destroy and
|
||||
// recreate the OpenGL context.
|
||||
notifyContextDestroy();
|
||||
}
|
||||
|
||||
_hwScreen = SDL_SetVideoMode(width, height, 32, flags);
|
||||
|
||||
if (!_hwScreen) {
|
||||
// We treat fullscreen requests as a "hint" for now. This means in
|
||||
// case it is not available we simply ignore it.
|
||||
if (_wantsFullScreen) {
|
||||
_hwScreen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_RESIZABLE);
|
||||
}
|
||||
}
|
||||
|
||||
// Part of the WORKAROUND mentioned above.
|
||||
_lastVideoModeLoad = SDL_GetTicks();
|
||||
|
||||
if (_hwScreen) {
|
||||
notifyContextCreate(rgba8888, rgba8888);
|
||||
handleResize(_hwScreen->w, _hwScreen->h, 90, 90);
|
||||
}
|
||||
|
||||
// Ignore resize events (from SDL) for a few frames, if this isn't
|
||||
// caused by a notification from SDL. This avoids bad resizes to a
|
||||
// (former) resolution for which we haven't processed an event yet.
|
||||
if (!_gotResize)
|
||||
_ignoreResizeEvents = 10;
|
||||
|
||||
return _hwScreen != nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
|
||||
if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START) {
|
||||
return SdlGraphicsManager::notifyEvent(event);
|
||||
}
|
||||
|
||||
switch ((CustomEventAction) event.customType) {
|
||||
case kActionIncreaseScaleFactor:
|
||||
case kActionDecreaseScaleFactor: {
|
||||
const int direction = event.customType == kActionIncreaseScaleFactor ? +1 : -1;
|
||||
|
||||
if (getFeatureState(OSystem::kFeatureFullscreenMode)) {
|
||||
// In case we are in fullscreen we will choose the previous
|
||||
// or next mode.
|
||||
|
||||
// In case no modes are available we do nothing.
|
||||
if (_fullscreenVideoModes.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look for the current mode.
|
||||
VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(),
|
||||
_fullscreenVideoModes.end(),
|
||||
VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight));
|
||||
if (i == _fullscreenVideoModes.end()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cycle through the modes in the specified direction.
|
||||
if (direction > 0) {
|
||||
++i;
|
||||
if (i == _fullscreenVideoModes.end()) {
|
||||
i = _fullscreenVideoModes.begin();
|
||||
}
|
||||
} else {
|
||||
if (i == _fullscreenVideoModes.begin()) {
|
||||
i = _fullscreenVideoModes.end();
|
||||
}
|
||||
--i;
|
||||
}
|
||||
|
||||
_desiredFullscreenWidth = i->width;
|
||||
_desiredFullscreenHeight = i->height;
|
||||
|
||||
// Try to setup the mode.
|
||||
if (!setupMode(_lastRequestedWidth, _lastRequestedHeight)) {
|
||||
warning("OpenGLSdlGraphicsManager::notifyEvent: Fullscreen resize failed ('%s')", SDL_GetError());
|
||||
g_system->quit();
|
||||
}
|
||||
} else {
|
||||
// Calculate the next scaling setting. We approximate the
|
||||
// current scale setting in case the user resized the
|
||||
// window. Then we apply the direction change.
|
||||
int windowWidth = 0, windowHeight = 0;
|
||||
getWindowSizeFromSdl(&windowWidth, &windowHeight);
|
||||
_graphicsScale = MAX<int>(windowWidth / _lastRequestedWidth, windowHeight / _lastRequestedHeight);
|
||||
_graphicsScale = MAX<int>(_graphicsScale + direction, 1);
|
||||
|
||||
// Since we overwrite a user resize here we reset its
|
||||
// flag here. This makes enabling AR smoother because it
|
||||
// will change the window size like in surface SDL.
|
||||
_gotResize = false;
|
||||
|
||||
// Try to setup the mode.
|
||||
if (!setupMode(_lastRequestedWidth * _graphicsScale, _lastRequestedHeight * _graphicsScale)) {
|
||||
warning("OpenGLSdlGraphicsManager::notifyEvent: Window resize failed ('%s')", SDL_GetError());
|
||||
g_system->quit();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_OSD
|
||||
int windowWidth = 0, windowHeight = 0;
|
||||
getWindowSizeFromSdl(&windowWidth, &windowHeight);
|
||||
const Common::U32String osdMsg = Common::U32String::format(_("Resolution: %dx%d"), windowWidth, windowHeight);
|
||||
displayMessageOnOSD(osdMsg);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case kActionToggleAspectRatioCorrection:
|
||||
// In case the user changed the window size manually we will
|
||||
// not change the window size again here.
|
||||
_ignoreLoadVideoMode = _gotResize;
|
||||
|
||||
// Toggles the aspect ratio correction state.
|
||||
beginGFXTransaction();
|
||||
setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection));
|
||||
endGFXTransaction();
|
||||
|
||||
// Make sure we do not ignore the next resize. This
|
||||
// effectively checks whether loadVideoMode has been called.
|
||||
assert(!_ignoreLoadVideoMode);
|
||||
|
||||
#ifdef USE_OSD
|
||||
if (getFeatureState(OSystem::kFeatureAspectRatioCorrection))
|
||||
displayMessageOnOSD(_("Enabled aspect ratio correction"));
|
||||
else
|
||||
displayMessageOnOSD(_("Disabled aspect ratio correction"));
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
case kActionToggleFilteredScaling:
|
||||
// Never ever try to resize the window when we simply want to enable or disable filtering.
|
||||
// This assures that the window size does not change.
|
||||
_ignoreLoadVideoMode = true;
|
||||
|
||||
// Ctrl+Alt+f toggles filtering on/off
|
||||
beginGFXTransaction();
|
||||
setFeatureState(OSystem::kFeatureFilteringMode, !getFeatureState(OSystem::kFeatureFilteringMode));
|
||||
endGFXTransaction();
|
||||
|
||||
// Make sure we do not ignore the next resize. This
|
||||
// effectively checks whether loadVideoMode has been called.
|
||||
assert(!_ignoreLoadVideoMode);
|
||||
|
||||
#ifdef USE_OSD
|
||||
if (getFeatureState(OSystem::kFeatureFilteringMode)) {
|
||||
displayMessageOnOSD(_("Filtering enabled"));
|
||||
} else {
|
||||
displayMessageOnOSD(_("Filtering disabled"));
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
case kActionCycleStretchMode: {
|
||||
// Never try to resize the window when changing the scaling mode.
|
||||
_ignoreLoadVideoMode = true;
|
||||
|
||||
// Ctrl+Alt+s cycles through stretch mode
|
||||
int index = 0;
|
||||
const OSystem::GraphicsMode *stretchModes = getSupportedStretchModes();
|
||||
const OSystem::GraphicsMode *sm = stretchModes;
|
||||
while (sm->name) {
|
||||
if (sm->id == getStretchMode())
|
||||
break;
|
||||
sm++;
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
if (!stretchModes[index].name)
|
||||
index = 0;
|
||||
beginGFXTransaction();
|
||||
setStretchMode(stretchModes[index].id);
|
||||
endGFXTransaction();
|
||||
|
||||
#ifdef USE_OSD
|
||||
Common::U32String message = Common::U32String::format("%S: %S",
|
||||
_("Stretch mode").c_str(),
|
||||
_(stretchModes[index].description).c_str()
|
||||
);
|
||||
displayMessageOnOSD(message);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return SdlGraphicsManager::notifyEvent(event);
|
||||
}
|
||||
}
|
115
backends/graphics/openglsdl/openglsdl-graphics.h
Normal file
115
backends/graphics/openglsdl/openglsdl-graphics.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H
|
||||
#define BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H
|
||||
|
||||
#include "backends/graphics/opengl/opengl-graphics.h"
|
||||
#include "backends/graphics/sdl/sdl-graphics.h"
|
||||
#include "backends/platform/sdl/sdl-sys.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/events.h"
|
||||
|
||||
class OpenGLSdlGraphicsManager : public OpenGL::OpenGLGraphicsManager, public SdlGraphicsManager {
|
||||
public:
|
||||
OpenGLSdlGraphicsManager(SdlEventSource *eventSource, SdlWindow *window);
|
||||
virtual ~OpenGLSdlGraphicsManager();
|
||||
|
||||
virtual bool hasFeature(OSystem::Feature f) const override;
|
||||
virtual void setFeatureState(OSystem::Feature f, bool enable) override;
|
||||
virtual bool getFeatureState(OSystem::Feature f) const override;
|
||||
|
||||
virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format) override;
|
||||
virtual void updateScreen() override;
|
||||
|
||||
// EventObserver API
|
||||
virtual bool notifyEvent(const Common::Event &event) override;
|
||||
|
||||
// SdlGraphicsManager API
|
||||
virtual void notifyVideoExpose() override;
|
||||
virtual void notifyResize(const int width, const int height) override;
|
||||
|
||||
protected:
|
||||
virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override;
|
||||
|
||||
virtual void refreshScreen() override;
|
||||
|
||||
virtual void *getProcAddress(const char *name) const override;
|
||||
|
||||
virtual void handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) override;
|
||||
|
||||
virtual bool saveScreenshot(const Common::String &filename) const override;
|
||||
|
||||
virtual int getGraphicsModeScale(int mode) const override { return 1; }
|
||||
|
||||
private:
|
||||
bool setupMode(uint width, uint height);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
int _glContextProfileMask, _glContextMajor, _glContextMinor;
|
||||
SDL_GLContext _glContext;
|
||||
#else
|
||||
uint32 _lastVideoModeLoad;
|
||||
#endif
|
||||
|
||||
uint _lastRequestedWidth;
|
||||
uint _lastRequestedHeight;
|
||||
uint _graphicsScale;
|
||||
bool _ignoreLoadVideoMode;
|
||||
bool _gotResize;
|
||||
|
||||
bool _wantsFullScreen;
|
||||
uint _ignoreResizeEvents;
|
||||
|
||||
struct VideoMode {
|
||||
VideoMode() : width(0), height(0) {}
|
||||
VideoMode(uint w, uint h) : width(w), height(h) {}
|
||||
|
||||
bool operator<(const VideoMode &right) const {
|
||||
if (width < right.width) {
|
||||
return true;
|
||||
} else if (width == right.width && height < right.height) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const VideoMode &right) const {
|
||||
return width == right.width && height == right.height;
|
||||
}
|
||||
|
||||
bool operator!=(const VideoMode &right) const {
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
uint width, height;
|
||||
};
|
||||
typedef Common::Array<VideoMode> VideoModeArray;
|
||||
VideoModeArray _fullscreenVideoModes;
|
||||
|
||||
uint _desiredFullscreenWidth;
|
||||
uint _desiredFullscreenHeight;
|
||||
};
|
||||
|
||||
#endif
|
450
backends/graphics/sdl/sdl-graphics.cpp
Normal file
450
backends/graphics/sdl/sdl-graphics.cpp
Normal file
@ -0,0 +1,450 @@
|
||||
/* 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/sdl/sdl-graphics.h"
|
||||
#include "backends/platform/sdl/sdl-sys.h"
|
||||
#include "backends/platform/sdl/sdl.h"
|
||||
#include "backends/events/sdl/sdl-events.h"
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymap.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "common/translation.h"
|
||||
#include "graphics/scaler/aspect.h"
|
||||
#ifdef USE_OSD
|
||||
#include "common/translation.h"
|
||||
#endif
|
||||
|
||||
SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window)
|
||||
: _eventSource(source), _window(window), _hwScreen(nullptr)
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
, _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0)
|
||||
#endif
|
||||
{
|
||||
SDL_GetMouseState(&_cursorX, &_cursorY);
|
||||
}
|
||||
|
||||
void SdlGraphicsManager::activateManager() {
|
||||
_eventSource->setGraphicsManager(dynamic_cast<SdlGraphics3dManager *>(this));
|
||||
|
||||
// Register the graphics manager as a event observer
|
||||
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
|
||||
}
|
||||
|
||||
void SdlGraphicsManager::deactivateManager() {
|
||||
// Unregister the event observer
|
||||
if (g_system->getEventManager()->getEventDispatcher()) {
|
||||
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
|
||||
}
|
||||
|
||||
_eventSource->setGraphicsManager(0);
|
||||
}
|
||||
|
||||
SdlGraphicsManager::State SdlGraphicsManager::getState() const {
|
||||
State state;
|
||||
|
||||
state.screenWidth = getWidth();
|
||||
state.screenHeight = getHeight();
|
||||
state.aspectRatio = getFeatureState(OSystem::kFeatureAspectRatioCorrection);
|
||||
state.fullscreen = getFeatureState(OSystem::kFeatureFullscreenMode);
|
||||
state.cursorPalette = getFeatureState(OSystem::kFeatureCursorPalette);
|
||||
#ifdef USE_RGB_COLOR
|
||||
state.pixelFormat = getScreenFormat();
|
||||
#endif
|
||||
return state;
|
||||
}
|
||||
|
||||
bool SdlGraphicsManager::setState(const State &state) {
|
||||
beginGFXTransaction();
|
||||
#ifdef USE_RGB_COLOR
|
||||
initSize(state.screenWidth, state.screenHeight, &state.pixelFormat);
|
||||
#else
|
||||
initSize(state.screenWidth, state.screenHeight, nullptr);
|
||||
#endif
|
||||
setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio);
|
||||
setFeatureState(OSystem::kFeatureFullscreenMode, state.fullscreen);
|
||||
setFeatureState(OSystem::kFeatureCursorPalette, state.cursorPalette);
|
||||
|
||||
if (endGFXTransaction() != OSystem::kTransactionSuccess) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SdlGraphicsManager::defaultGraphicsModeConfig() const {
|
||||
const Common::ConfigManager::Domain *transientDomain = ConfMan.getDomain(Common::ConfigManager::kTransientDomain);
|
||||
if (transientDomain && transientDomain->contains("gfx_mode")) {
|
||||
const Common::String &mode = transientDomain->getVal("gfx_mode");
|
||||
if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const Common::ConfigManager::Domain *gameDomain = ConfMan.getActiveDomain();
|
||||
if (gameDomain && gameDomain->contains("gfx_mode")) {
|
||||
const Common::String &mode = gameDomain->getVal("gfx_mode");
|
||||
if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int SdlGraphicsManager::getGraphicsModeIdByName(const Common::String &name) const {
|
||||
if (name == "normal" || name == "default") {
|
||||
return getDefaultGraphicsMode();
|
||||
}
|
||||
|
||||
const OSystem::GraphicsMode *mode = getSupportedGraphicsModes();
|
||||
while (mode && mode->name != nullptr) {
|
||||
if (name.equalsIgnoreCase(mode->name)) {
|
||||
return mode->id;
|
||||
}
|
||||
++mode;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
const bool useDefault = defaultGraphicsModeConfig();
|
||||
|
||||
int scale = getGraphicsModeScale(getGraphicsModeIdByName(ConfMan.get("gfx_mode")));
|
||||
if (scale == -1) {
|
||||
warning("Unknown scaler; defaulting to 1");
|
||||
scale = 1;
|
||||
}
|
||||
|
||||
int16 bestWidth = 0, bestHeight = 0;
|
||||
const Graphics::ModeList::const_iterator end = modes.end();
|
||||
for (Graphics::ModeList::const_iterator it = modes.begin(); it != end; ++it) {
|
||||
int16 width = it->width, height = it->height;
|
||||
|
||||
// TODO: Normalize AR correction by passing a PAR in the mode list
|
||||
// instead of checking the dimensions here like this, since not all
|
||||
// 320x200/640x400 uses are with non-square pixels (e.g. DreamWeb).
|
||||
if (ConfMan.getBool("aspect_ratio")) {
|
||||
if ((width == 320 && height == 200) || (width == 640 && height == 400)) {
|
||||
height = real2Aspect(height);
|
||||
}
|
||||
}
|
||||
|
||||
if (!useDefault || width <= 320) {
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
}
|
||||
|
||||
if (bestWidth < width) {
|
||||
bestWidth = width;
|
||||
}
|
||||
|
||||
if (bestHeight < height) {
|
||||
bestHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
_hintedWidth = bestWidth;
|
||||
_hintedHeight = bestHeight;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SdlGraphicsManager::showMouse(bool visible) {
|
||||
if (visible == _cursorVisible) {
|
||||
return visible;
|
||||
}
|
||||
|
||||
int showCursor = SDL_DISABLE;
|
||||
if (visible) {
|
||||
// _cursorX and _cursorY are currently always clipped to the active
|
||||
// area, so we need to ask SDL where the system's mouse cursor is
|
||||
// instead
|
||||
int x, y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
if (!_activeArea.drawRect.contains(Common::Point(x, y))) {
|
||||
showCursor = SDL_ENABLE;
|
||||
}
|
||||
}
|
||||
SDL_ShowCursor(showCursor);
|
||||
|
||||
return WindowedGraphicsManager::showMouse(visible);
|
||||
}
|
||||
|
||||
bool SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) {
|
||||
mouse.x = CLIP<int16>(mouse.x, 0, _windowWidth - 1);
|
||||
mouse.y = CLIP<int16>(mouse.y, 0, _windowHeight - 1);
|
||||
|
||||
int showCursor = SDL_DISABLE;
|
||||
bool valid = true;
|
||||
if (_activeArea.drawRect.contains(mouse)) {
|
||||
_cursorLastInActiveArea = true;
|
||||
} else {
|
||||
mouse.x = CLIP<int>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right - 1);
|
||||
mouse.y = CLIP<int>(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom - 1);
|
||||
|
||||
if (_window->mouseIsGrabbed() ||
|
||||
// Keep the mouse inside the game area during dragging to prevent an
|
||||
// event mismatch where the mouseup event gets lost because it is
|
||||
// performed outside of the game area
|
||||
(_cursorLastInActiveArea && SDL_GetMouseState(nullptr, nullptr) != 0)) {
|
||||
setSystemMousePosition(mouse.x, mouse.y);
|
||||
} else {
|
||||
// Allow the in-game mouse to get a final movement event to the edge
|
||||
// of the window if the mouse was moved out of the game area
|
||||
if (_cursorLastInActiveArea) {
|
||||
_cursorLastInActiveArea = false;
|
||||
} else if (_cursorVisible) {
|
||||
// Keep sending events to the game if the cursor is invisible,
|
||||
// since otherwise if a game lets you skip a cutscene by
|
||||
// clicking and the user moved the mouse outside the active
|
||||
// area, the clicks wouldn't do anything, which would be
|
||||
// confusing
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (_cursorVisible) {
|
||||
showCursor = SDL_ENABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_ShowCursor(showCursor);
|
||||
if (valid) {
|
||||
setMousePosition(mouse.x, mouse.y);
|
||||
mouse = convertWindowToVirtual(mouse.x, mouse.y);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
void SdlGraphicsManager::setSystemMousePosition(const int x, const int y) {
|
||||
assert(_window);
|
||||
if (!_window->warpMouseInWindow(x, y)) {
|
||||
const Common::Point mouse = convertWindowToVirtual(x, y);
|
||||
_eventSource->fakeWarpMouse(mouse.x, mouse.y);
|
||||
}
|
||||
}
|
||||
|
||||
void SdlGraphicsManager::handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) {
|
||||
_forceRedraw = true;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint32 flags) {
|
||||
if (!_window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only update the actual window when flags change (which usually means
|
||||
// fullscreen mode is entered/exited), when updates are forced so that we
|
||||
// do not reset the window size whenever a game makes a call to change the
|
||||
// size or pixel format of the internal game surface (since a user may have
|
||||
// resized the game window), or when the launcher is visible (since a user
|
||||
// may change the scaler, which should reset the window size)
|
||||
if (!_window->getSDLWindow() || _lastFlags != flags || _overlayVisible || _allowWindowSizeReset) {
|
||||
const bool fullscreen = (flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0;
|
||||
if (!fullscreen) {
|
||||
if (_hintedWidth) {
|
||||
width = _hintedWidth;
|
||||
}
|
||||
if (_hintedHeight) {
|
||||
height = _hintedHeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_window->createOrUpdateWindow(width, height, flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_lastFlags = flags;
|
||||
_allowWindowSizeReset = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SdlGraphicsManager::saveScreenshot() {
|
||||
Common::String filename;
|
||||
|
||||
Common::String screenshotsPath;
|
||||
OSystem_SDL *sdl_g_system = dynamic_cast<OSystem_SDL*>(g_system);
|
||||
if (sdl_g_system)
|
||||
screenshotsPath = sdl_g_system->getScreenshotsPath();
|
||||
|
||||
// Use the name of the running target as a base for screenshot file names
|
||||
Common::String currentTarget = ConfMan.getActiveDomainName();
|
||||
|
||||
#ifdef USE_PNG
|
||||
const char *extension = "png";
|
||||
#else
|
||||
const char *extension = "bmp";
|
||||
#endif
|
||||
|
||||
for (int n = 0;; n++) {
|
||||
filename = Common::String::format("scummvm%s%s-%05d.%s", currentTarget.empty() ? "" : "-",
|
||||
currentTarget.c_str(), n, extension);
|
||||
|
||||
Common::FSNode file = Common::FSNode(screenshotsPath + filename);
|
||||
if (!file.exists()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (saveScreenshot(screenshotsPath + filename)) {
|
||||
if (screenshotsPath.empty())
|
||||
debug("Saved screenshot '%s' in current directory", filename.c_str());
|
||||
else
|
||||
debug("Saved screenshot '%s' in directory '%s'", filename.c_str(), screenshotsPath.c_str());
|
||||
} else {
|
||||
if (screenshotsPath.empty())
|
||||
warning("Could not save screenshot in current directory");
|
||||
else
|
||||
warning("Could not save screenshot in directory '%s'", screenshotsPath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool SdlGraphicsManager::notifyEvent(const Common::Event &event) {
|
||||
if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ((CustomEventAction) event.customType) {
|
||||
case kActionToggleMouseCapture:
|
||||
getWindow()->toggleMouseGrab();
|
||||
return true;
|
||||
|
||||
case kActionToggleFullscreen:
|
||||
toggleFullScreen();
|
||||
return true;
|
||||
|
||||
case kActionSaveScreenshot:
|
||||
saveScreenshot();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SdlGraphicsManager::toggleFullScreen() {
|
||||
if (!g_system->hasFeature(OSystem::kFeatureFullscreenMode))
|
||||
return;
|
||||
|
||||
beginGFXTransaction();
|
||||
setFeatureState(OSystem::kFeatureFullscreenMode, !getFeatureState(OSystem::kFeatureFullscreenMode));
|
||||
endGFXTransaction();
|
||||
#ifdef USE_OSD
|
||||
if (getFeatureState(OSystem::kFeatureFullscreenMode))
|
||||
displayMessageOnOSD(_("Fullscreen mode"));
|
||||
else
|
||||
displayMessageOnOSD(_("Windowed mode"));
|
||||
#endif
|
||||
}
|
||||
|
||||
Common::Keymap *SdlGraphicsManager::getKeymap() {
|
||||
using namespace Common;
|
||||
|
||||
Keymap *keymap = new Keymap(Keymap::kKeymapTypeGlobal, "sdl-graphics", _("Graphics"));
|
||||
Action *act;
|
||||
|
||||
if (g_system->hasFeature(OSystem::kFeatureFullscreenMode)) {
|
||||
act = new Action("FULS", _("Toggle fullscreen"));
|
||||
act->addDefaultInputMapping("A+RETURN");
|
||||
act->addDefaultInputMapping("A+KP_ENTER");
|
||||
act->setCustomBackendActionEvent(kActionToggleFullscreen);
|
||||
keymap->addAction(act);
|
||||
}
|
||||
|
||||
act = new Action("CAPT", _("Toggle mouse capture"));
|
||||
act->addDefaultInputMapping("C+m");
|
||||
act->setCustomBackendActionEvent(kActionToggleMouseCapture);
|
||||
keymap->addAction(act);
|
||||
|
||||
act = new Action("SCRS", _("Save screenshot"));
|
||||
act->addDefaultInputMapping("A+s");
|
||||
act->setCustomBackendActionEvent(kActionSaveScreenshot);
|
||||
keymap->addAction(act);
|
||||
|
||||
if (hasFeature(OSystem::kFeatureAspectRatioCorrection)) {
|
||||
act = new Action("ASPT", _("Toggle aspect ratio correction"));
|
||||
act->addDefaultInputMapping("C+A+a");
|
||||
act->setCustomBackendActionEvent(kActionToggleAspectRatioCorrection);
|
||||
keymap->addAction(act);
|
||||
}
|
||||
|
||||
if (hasFeature(OSystem::kFeatureFilteringMode)) {
|
||||
act = new Action("FILT", _("Toggle linear filtered scaling"));
|
||||
act->addDefaultInputMapping("C+A+f");
|
||||
act->setCustomBackendActionEvent(kActionToggleFilteredScaling);
|
||||
keymap->addAction(act);
|
||||
}
|
||||
|
||||
if (hasFeature(OSystem::kFeatureStretchMode)) {
|
||||
act = new Action("STCH", _("Cycle through stretch modes"));
|
||||
act->addDefaultInputMapping("C+A+s");
|
||||
act->setCustomBackendActionEvent(kActionCycleStretchMode);
|
||||
keymap->addAction(act);
|
||||
}
|
||||
|
||||
act = new Action("SCL+", _("Increase the scale factor"));
|
||||
act->addDefaultInputMapping("C+A+PLUS");
|
||||
act->addDefaultInputMapping("C+A+KP_PLUS");
|
||||
act->setCustomBackendActionEvent(kActionIncreaseScaleFactor);
|
||||
keymap->addAction(act);
|
||||
|
||||
act = new Action("SCL-", _("Decrease the scale factor"));
|
||||
act->addDefaultInputMapping("C+A+MINUS");
|
||||
act->addDefaultInputMapping("C+A+KP_MINUS");
|
||||
act->setCustomBackendActionEvent(kActionDecreaseScaleFactor);
|
||||
keymap->addAction(act);
|
||||
|
||||
#ifdef USE_SCALERS
|
||||
struct ActionEntry {
|
||||
const char *id;
|
||||
const char *description;
|
||||
};
|
||||
static const ActionEntry filters[] = {
|
||||
{ "FLT1", _s("Switch to nearest neighbour scaling") },
|
||||
{ "FLT2", _s("Switch to AdvMame 2x/3x scaling") },
|
||||
#ifdef USE_HQ_SCALERS
|
||||
{ "FLT3", _s("Switch to HQ 2x/3x scaling") },
|
||||
#endif
|
||||
{ "FLT4", _s("Switch to 2xSai scaling") },
|
||||
{ "FLT5", _s("Switch to Super2xSai scaling") },
|
||||
{ "FLT6", _s("Switch to SuperEagle scaling") },
|
||||
{ "FLT7", _s("Switch to TV 2x scaling") },
|
||||
{ "FLT8", _s("Switch to DotMatrix scaling") }
|
||||
};
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(filters); i++) {
|
||||
act = new Action(filters[i].id, _(filters[i].description));
|
||||
act->addDefaultInputMapping(String::format("C+A+%d", i + 1));
|
||||
act->addDefaultInputMapping(String::format("C+A+KP%d", i + 1));
|
||||
act->setCustomBackendActionEvent(kActionSetScaleFilter1 + i);
|
||||
keymap->addAction(act);
|
||||
}
|
||||
#endif
|
||||
|
||||
return keymap;
|
||||
}
|
213
backends/graphics/sdl/sdl-graphics.h
Normal file
213
backends/graphics/sdl/sdl-graphics.h
Normal file
@ -0,0 +1,213 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H
|
||||
#define BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H
|
||||
|
||||
#include "backends/graphics/windowed.h"
|
||||
#include "backends/platform/sdl/sdl-window.h"
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
class SdlEventSource;
|
||||
|
||||
#ifndef __SYMBIAN32__
|
||||
#define USE_OSD 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Base class for a SDL based graphics manager.
|
||||
*/
|
||||
class SdlGraphicsManager : virtual public WindowedGraphicsManager, public Common::EventObserver {
|
||||
public:
|
||||
SdlGraphicsManager(SdlEventSource *source, SdlWindow *window);
|
||||
virtual ~SdlGraphicsManager() {}
|
||||
|
||||
/**
|
||||
* Makes this graphics manager active. That means it should be ready to
|
||||
* process inputs now. However, even without being active it should be
|
||||
* able to query the supported modes and other bits.
|
||||
*/
|
||||
virtual void activateManager();
|
||||
|
||||
/**
|
||||
* Makes this graphics manager inactive. This should allow another
|
||||
* graphics manager to become active again.
|
||||
*/
|
||||
virtual void deactivateManager();
|
||||
|
||||
/**
|
||||
* Notify the graphics manager that the graphics needs to be redrawn, since
|
||||
* the application window was modified.
|
||||
*
|
||||
* This is basically called when SDL_VIDEOEXPOSE was received.
|
||||
*/
|
||||
virtual void notifyVideoExpose() = 0;
|
||||
|
||||
/**
|
||||
* Notify the graphics manager about a resize event.
|
||||
*
|
||||
* It is noteworthy that the requested width/height should actually be set
|
||||
* up as is and not changed by the graphics manager, since otherwise it may
|
||||
* lead to odd behavior for certain window managers.
|
||||
*
|
||||
* It is only required to overwrite this method in case you want a
|
||||
* resizable window. The default implementation just does nothing.
|
||||
*
|
||||
* @param width Requested window width.
|
||||
* @param height Requested window height.
|
||||
*/
|
||||
virtual void notifyResize(const int width, const int height) {}
|
||||
|
||||
/**
|
||||
* Notifies the graphics manager about a mouse position change.
|
||||
*
|
||||
* The passed point *must* be converted from window coordinates to virtual
|
||||
* coordinates in order for the event to be processed correctly by the game
|
||||
* engine. Just use `convertWindowToVirtual` for this unless you need to do
|
||||
* something special.
|
||||
*
|
||||
* @param mouse The mouse position in window coordinates, which must be
|
||||
* converted synchronously to virtual coordinates.
|
||||
* @returns true if the mouse was in a valid position for the game and
|
||||
* should cause the event to be sent to the game.
|
||||
*/
|
||||
virtual bool notifyMousePosition(Common::Point &mouse);
|
||||
|
||||
virtual bool showMouse(bool visible) override;
|
||||
|
||||
virtual bool saveScreenshot(const Common::String &filename) const { return false; }
|
||||
void saveScreenshot() override;
|
||||
|
||||
// Override from Common::EventObserver
|
||||
virtual bool notifyEvent(const Common::Event &event) override;
|
||||
|
||||
/**
|
||||
* A (subset) of the graphic manager's state. This is used when switching
|
||||
* between different SDL graphic managers at runtime.
|
||||
*/
|
||||
struct State {
|
||||
int screenWidth, screenHeight;
|
||||
bool aspectRatio;
|
||||
bool fullscreen;
|
||||
bool cursorPalette;
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
Graphics::PixelFormat pixelFormat;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the current state of the graphics manager.
|
||||
*/
|
||||
State getState() const;
|
||||
|
||||
/**
|
||||
* Sets up a basic state of the graphics manager.
|
||||
*/
|
||||
bool setState(const State &state);
|
||||
|
||||
/**
|
||||
* @returns the SDL window.
|
||||
*/
|
||||
SdlWindow *getWindow() const { return _window; }
|
||||
|
||||
virtual void initSizeHint(const Graphics::ModeList &modes) override;
|
||||
|
||||
Common::Keymap *getKeymap();
|
||||
|
||||
protected:
|
||||
enum CustomEventAction {
|
||||
kActionToggleFullscreen = 100,
|
||||
kActionToggleMouseCapture,
|
||||
kActionSaveScreenshot,
|
||||
kActionToggleAspectRatioCorrection,
|
||||
kActionToggleFilteredScaling,
|
||||
kActionCycleStretchMode,
|
||||
kActionIncreaseScaleFactor,
|
||||
kActionDecreaseScaleFactor,
|
||||
kActionSetScaleFilter1,
|
||||
kActionSetScaleFilter2,
|
||||
kActionSetScaleFilter3,
|
||||
kActionSetScaleFilter4,
|
||||
kActionSetScaleFilter5,
|
||||
kActionSetScaleFilter6,
|
||||
kActionSetScaleFilter7,
|
||||
kActionSetScaleFilter8
|
||||
};
|
||||
|
||||
virtual int getGraphicsModeScale(int mode) const = 0;
|
||||
|
||||
bool defaultGraphicsModeConfig() const;
|
||||
int getGraphicsModeIdByName(const Common::String &name) const;
|
||||
|
||||
/**
|
||||
* Gets the dimensions of the window directly from SDL instead of from the
|
||||
* values stored by the graphics manager.
|
||||
*/
|
||||
void getWindowSizeFromSdl(int *width, int *height) const {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
assert(_window);
|
||||
SDL_GetWindowSize(_window->getSDLWindow(), width, height);
|
||||
#else
|
||||
assert(_hwScreen);
|
||||
|
||||
if (width) {
|
||||
*width = _hwScreen->w;
|
||||
}
|
||||
|
||||
if (height) {
|
||||
*height = _hwScreen->h;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void setSystemMousePosition(const int x, const int y) override;
|
||||
|
||||
virtual void handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) override;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
public:
|
||||
void unlockWindowSize() {
|
||||
_allowWindowSizeReset = true;
|
||||
_hintedWidth = 0;
|
||||
_hintedHeight = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
Uint32 _lastFlags;
|
||||
bool _allowWindowSizeReset;
|
||||
int _hintedWidth, _hintedHeight;
|
||||
|
||||
bool createOrUpdateWindow(const int width, const int height, const Uint32 flags);
|
||||
#endif
|
||||
|
||||
SDL_Surface *_hwScreen;
|
||||
SdlEventSource *_eventSource;
|
||||
SdlWindow *_window;
|
||||
|
||||
private:
|
||||
void toggleFullScreen();
|
||||
};
|
||||
|
||||
#endif
|
2711
backends/graphics/surfacesdl/surfacesdl-graphics.cpp
Normal file
2711
backends/graphics/surfacesdl/surfacesdl-graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
457
backends/graphics/surfacesdl/surfacesdl-graphics.h
Normal file
457
backends/graphics/surfacesdl/surfacesdl-graphics.h
Normal file
@ -0,0 +1,457 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_SURFACESDL_GRAPHICS_H
|
||||
#define BACKENDS_GRAPHICS_SURFACESDL_GRAPHICS_H
|
||||
|
||||
#include "backends/graphics/graphics.h"
|
||||
#include "backends/graphics/sdl/sdl-graphics.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "graphics/scaler.h"
|
||||
#include "common/events.h"
|
||||
#include "common/mutex.h"
|
||||
|
||||
#include "backends/events/sdl/sdl-events.h"
|
||||
|
||||
#include "backends/platform/sdl/sdl-sys.h"
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
// Define this to allow for focus rectangle debugging
|
||||
#define USE_SDL_DEBUG_FOCUSRECT
|
||||
#endif
|
||||
|
||||
enum {
|
||||
GFX_NORMAL = 0,
|
||||
GFX_DOUBLESIZE = 1,
|
||||
GFX_TRIPLESIZE = 2,
|
||||
GFX_2XSAI = 3,
|
||||
GFX_SUPER2XSAI = 4,
|
||||
GFX_SUPEREAGLE = 5,
|
||||
GFX_ADVMAME2X = 6,
|
||||
GFX_ADVMAME3X = 7,
|
||||
GFX_HQ2X = 8,
|
||||
GFX_HQ3X = 9,
|
||||
GFX_TV2X = 10,
|
||||
GFX_DOTMATRIX = 11
|
||||
};
|
||||
|
||||
|
||||
class AspectRatio {
|
||||
int _kw, _kh;
|
||||
public:
|
||||
AspectRatio() { _kw = _kh = 0; }
|
||||
AspectRatio(int w, int h);
|
||||
|
||||
bool isAuto() const { return (_kw | _kh) == 0; }
|
||||
|
||||
int kw() const { return _kw; }
|
||||
int kh() const { return _kh; }
|
||||
};
|
||||
|
||||
/**
|
||||
* SDL graphics manager
|
||||
*/
|
||||
class SurfaceSdlGraphicsManager : public SdlGraphicsManager {
|
||||
public:
|
||||
SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window);
|
||||
virtual ~SurfaceSdlGraphicsManager();
|
||||
|
||||
virtual bool hasFeature(OSystem::Feature f) const override;
|
||||
virtual void setFeatureState(OSystem::Feature f, bool enable) override;
|
||||
virtual bool getFeatureState(OSystem::Feature f) const override;
|
||||
|
||||
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
|
||||
virtual int getDefaultGraphicsMode() const override;
|
||||
virtual bool setGraphicsMode(int mode) override;
|
||||
virtual int getGraphicsMode() const override;
|
||||
virtual void resetGraphicsScale() override;
|
||||
#ifdef USE_RGB_COLOR
|
||||
virtual Graphics::PixelFormat getScreenFormat() const override { return _screenFormat; }
|
||||
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
virtual const OSystem::GraphicsMode *getSupportedStretchModes() const override;
|
||||
virtual int getDefaultStretchMode() const override;
|
||||
virtual bool setStretchMode(int mode) override;
|
||||
virtual int getStretchMode() const override;
|
||||
#endif
|
||||
virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL) override;
|
||||
virtual int getScreenChangeID() const override { return _screenChangeCount; }
|
||||
|
||||
virtual void beginGFXTransaction() override;
|
||||
virtual OSystem::TransactionError endGFXTransaction() override;
|
||||
|
||||
virtual int16 getHeight() const override;
|
||||
virtual int16 getWidth() const override;
|
||||
|
||||
protected:
|
||||
// PaletteManager API
|
||||
virtual void setPalette(const byte *colors, uint start, uint num) override;
|
||||
virtual void grabPalette(byte *colors, uint start, uint num) const override;
|
||||
|
||||
/**
|
||||
* Convert from the SDL pixel format to Graphics::PixelFormat
|
||||
* @param in The SDL pixel format to convert
|
||||
* @param out A pixel format to be written to
|
||||
*/
|
||||
Graphics::PixelFormat convertSDLPixelFormat(SDL_PixelFormat *in) const;
|
||||
public:
|
||||
virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||
virtual Graphics::Surface *lockScreen() override;
|
||||
virtual void unlockScreen() override;
|
||||
virtual void fillScreen(uint32 col) override;
|
||||
virtual void updateScreen() override;
|
||||
virtual void setFocusRectangle(const Common::Rect& rect) override;
|
||||
virtual void clearFocusRectangle() override;
|
||||
|
||||
virtual Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
|
||||
virtual void clearOverlay() override;
|
||||
virtual void grabOverlay(void *buf, int pitch) const override;
|
||||
virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||
virtual int16 getOverlayHeight() const override { return _videoMode.overlayHeight; }
|
||||
virtual int16 getOverlayWidth() const override { return _videoMode.overlayWidth; }
|
||||
|
||||
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) override;
|
||||
virtual void setCursorPalette(const byte *colors, uint start, uint num) override;
|
||||
|
||||
#ifdef USE_OSD
|
||||
virtual void displayMessageOnOSD(const Common::U32String &msg) override;
|
||||
virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
|
||||
#endif
|
||||
|
||||
// Override from Common::EventObserver
|
||||
virtual bool notifyEvent(const Common::Event &event) override;
|
||||
|
||||
// SdlGraphicsManager interface
|
||||
virtual void notifyVideoExpose() override;
|
||||
virtual void notifyResize(const int width, const int height) override;
|
||||
|
||||
protected:
|
||||
#ifdef USE_OSD
|
||||
/** Surface containing the OSD message */
|
||||
SDL_Surface *_osdMessageSurface;
|
||||
/** Transparency level of the OSD message */
|
||||
uint8 _osdMessageAlpha;
|
||||
/** When to start the fade out */
|
||||
uint32 _osdMessageFadeStartTime;
|
||||
/** Enum with OSD options */
|
||||
enum {
|
||||
kOSDFadeOutDelay = 2 * 1000, /** < Delay before the OSD is faded out (in milliseconds) */
|
||||
kOSDFadeOutDuration = 500, /** < Duration of the OSD fade out (in milliseconds) */
|
||||
kOSDInitialAlpha = 80 /** < Initial alpha level, in percent */
|
||||
};
|
||||
/** Screen rectangle where the OSD message is drawn */
|
||||
SDL_Rect getOSDMessageRect() const;
|
||||
/** Clear the currently displayed OSD message if any */
|
||||
void removeOSDMessage();
|
||||
/** Surface containing the OSD background activity icon */
|
||||
SDL_Surface *_osdIconSurface;
|
||||
/** Screen rectangle where the OSD background activity icon is drawn */
|
||||
SDL_Rect getOSDIconRect() const;
|
||||
|
||||
void updateOSD();
|
||||
void drawOSD();
|
||||
#endif
|
||||
|
||||
virtual bool gameNeedsAspectRatioCorrection() const override {
|
||||
return _videoMode.aspectRatioCorrection;
|
||||
}
|
||||
virtual int getGameRenderScale() const override {
|
||||
return _videoMode.scaleFactor;
|
||||
}
|
||||
|
||||
virtual void handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) override;
|
||||
|
||||
virtual int getGraphicsModeScale(int mode) const override;
|
||||
virtual ScalerProc *getGraphicsScalerProc(int mode) const;
|
||||
|
||||
virtual void setupHardwareSize();
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
/* SDL2 features a different API for 2D graphics. We create a wrapper
|
||||
* around this API to keep the code paths as close as possible. */
|
||||
SDL_Renderer *_renderer;
|
||||
SDL_Texture *_screenTexture;
|
||||
void deinitializeRenderer();
|
||||
void recreateScreenTexture();
|
||||
|
||||
virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
|
||||
virtual void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects);
|
||||
int SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
|
||||
int SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
|
||||
int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
|
||||
#endif
|
||||
|
||||
/** Unseen game screen */
|
||||
SDL_Surface *_screen;
|
||||
Graphics::PixelFormat _screenFormat;
|
||||
Graphics::PixelFormat _cursorFormat;
|
||||
#ifdef USE_RGB_COLOR
|
||||
Common::List<Graphics::PixelFormat> _supportedFormats;
|
||||
|
||||
/**
|
||||
* Update the list of supported pixel formats.
|
||||
* This method is invoked by loadGFXMode().
|
||||
*/
|
||||
void detectSupportedFormats();
|
||||
#endif
|
||||
|
||||
/** Temporary screen (for scalers) */
|
||||
SDL_Surface *_tmpscreen;
|
||||
/** Temporary screen (for scalers) */
|
||||
SDL_Surface *_tmpscreen2;
|
||||
|
||||
SDL_Surface *_overlayscreen;
|
||||
Graphics::PixelFormat _overlayFormat;
|
||||
|
||||
enum {
|
||||
kTransactionNone = 0,
|
||||
kTransactionActive = 1,
|
||||
kTransactionRollback = 2
|
||||
};
|
||||
|
||||
struct TransactionDetails {
|
||||
bool sizeChanged;
|
||||
bool needHotswap;
|
||||
bool needUpdatescreen;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
bool needTextureUpdate;
|
||||
bool needDisplayResize;
|
||||
#endif
|
||||
#ifdef USE_RGB_COLOR
|
||||
bool formatChanged;
|
||||
#endif
|
||||
|
||||
TransactionDetails() {
|
||||
sizeChanged = false;
|
||||
needHotswap = false;
|
||||
needUpdatescreen = false;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
needTextureUpdate = false;
|
||||
needDisplayResize = false;
|
||||
#endif
|
||||
#ifdef USE_RGB_COLOR
|
||||
formatChanged = false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
TransactionDetails _transactionDetails;
|
||||
|
||||
struct VideoState {
|
||||
bool setup;
|
||||
|
||||
bool fullscreen;
|
||||
bool aspectRatioCorrection;
|
||||
AspectRatio desiredAspectRatio;
|
||||
bool filtering;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
int stretchMode;
|
||||
#endif
|
||||
|
||||
int mode;
|
||||
int scaleFactor;
|
||||
|
||||
int screenWidth, screenHeight;
|
||||
int overlayWidth, overlayHeight;
|
||||
int hardwareWidth, hardwareHeight;
|
||||
#ifdef USE_RGB_COLOR
|
||||
Graphics::PixelFormat format;
|
||||
#endif
|
||||
|
||||
VideoState() {
|
||||
setup = false;
|
||||
fullscreen = false;
|
||||
aspectRatioCorrection = false;
|
||||
// desiredAspectRatio set to (0, 0) by AspectRatio constructor
|
||||
filtering = false;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
stretchMode = 0;
|
||||
#endif
|
||||
|
||||
mode = 0;
|
||||
scaleFactor = 0;
|
||||
|
||||
screenWidth = 0;
|
||||
screenHeight = 0;
|
||||
overlayWidth = 0;
|
||||
overlayHeight = 0;
|
||||
hardwareWidth = 0;
|
||||
hardwareHeight = 0;
|
||||
#ifdef USE_RGB_COLOR
|
||||
// format set to 0 values by Graphics::PixelFormat constructor
|
||||
#endif
|
||||
}
|
||||
};
|
||||
VideoState _videoMode, _oldVideoMode;
|
||||
|
||||
#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
/**
|
||||
* Original BPP to restore the video mode on unload.
|
||||
*
|
||||
* This is required to make listing video modes for the OpenGL output work
|
||||
* on Windows 8+. On these systems OpenGL modes are only available for
|
||||
* 32bit formats. However, we setup a 16bit format and thus mode listings
|
||||
* for OpenGL will return an empty list afterwards.
|
||||
*
|
||||
* In theory we might require this behavior on non-Win32 platforms too.
|
||||
* However, SDL sometimes gives us invalid pixel formats for X11 outputs
|
||||
* causing crashes when trying to setup the original pixel format.
|
||||
* See bug #7038 "IRIX: X BadMatch when trying to start any 640x480 game".
|
||||
*/
|
||||
uint8 _originalBitsPerPixel;
|
||||
#endif
|
||||
|
||||
ScalerProc *_scalerProc;
|
||||
int _scalerType;
|
||||
int _transactionMode;
|
||||
|
||||
// Indicates whether it is needed to free _hwSurface in destructor
|
||||
bool _displayDisabled;
|
||||
|
||||
bool _screenIsLocked;
|
||||
Graphics::Surface _framebuffer;
|
||||
|
||||
int _screenChangeCount;
|
||||
|
||||
enum {
|
||||
NUM_DIRTY_RECT = 100,
|
||||
MAX_SCALING = 3
|
||||
};
|
||||
|
||||
// Dirty rect management
|
||||
SDL_Rect _dirtyRectList[NUM_DIRTY_RECT];
|
||||
int _numDirtyRects;
|
||||
|
||||
struct MousePos {
|
||||
// The size and hotspot of the original cursor image.
|
||||
int16 w, h;
|
||||
int16 hotX, hotY;
|
||||
|
||||
// The size and hotspot of the pre-scaled cursor image, in real
|
||||
// coordinates.
|
||||
int16 rW, rH;
|
||||
int16 rHotX, rHotY;
|
||||
|
||||
// The size and hotspot of the pre-scaled cursor image, in game
|
||||
// coordinates.
|
||||
int16 vW, vH;
|
||||
int16 vHotX, vHotY;
|
||||
|
||||
MousePos() : w(0), h(0), hotX(0), hotY(0),
|
||||
rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
|
||||
vHotX(0), vHotY(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
byte *_mouseData;
|
||||
SDL_Rect _mouseBackup;
|
||||
MousePos _mouseCurState;
|
||||
#ifdef USE_RGB_COLOR
|
||||
uint32 _mouseKeyColor;
|
||||
#else
|
||||
byte _mouseKeyColor;
|
||||
#endif
|
||||
bool _cursorDontScale;
|
||||
bool _cursorPaletteDisabled;
|
||||
SDL_Surface *_mouseOrigSurface;
|
||||
SDL_Surface *_mouseSurface;
|
||||
enum {
|
||||
kMouseColorKey = 1
|
||||
};
|
||||
|
||||
// Shake mode
|
||||
// This is always set to 0 when building with SDL2.
|
||||
int _currentShakeXOffset;
|
||||
int _currentShakeYOffset;
|
||||
|
||||
// Palette data
|
||||
SDL_Color *_currentPalette;
|
||||
uint _paletteDirtyStart, _paletteDirtyEnd;
|
||||
|
||||
// Cursor palette data
|
||||
SDL_Color *_cursorPalette;
|
||||
|
||||
/**
|
||||
* Mutex which prevents multiple threads from interfering with each other
|
||||
* when accessing the screen.
|
||||
*/
|
||||
Common::Mutex _graphicsMutex;
|
||||
|
||||
#ifdef USE_SDL_DEBUG_FOCUSRECT
|
||||
bool _enableFocusRectDebugCode;
|
||||
bool _enableFocusRect;
|
||||
Common::Rect _focusRect;
|
||||
#endif
|
||||
|
||||
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false);
|
||||
|
||||
virtual void drawMouse();
|
||||
virtual void undrawMouse();
|
||||
virtual void blitCursor();
|
||||
|
||||
virtual void internUpdateScreen();
|
||||
|
||||
virtual bool loadGFXMode();
|
||||
virtual void unloadGFXMode();
|
||||
virtual bool hotswapGFXMode();
|
||||
|
||||
virtual void setAspectRatioCorrection(bool enable);
|
||||
void setFilteringMode(bool enable);
|
||||
|
||||
virtual bool saveScreenshot(const Common::String &filename) const override;
|
||||
virtual void setGraphicsModeIntern();
|
||||
|
||||
private:
|
||||
void setFullscreenMode(bool enable);
|
||||
void handleScalerHotkeys(int scalefactor, int scalerType);
|
||||
|
||||
/**
|
||||
* Converts the given point from the overlay's coordinate space to the
|
||||
* game's coordinate space.
|
||||
*/
|
||||
Common::Point convertOverlayToGame(const int x, const int y) const {
|
||||
if (getOverlayWidth() == 0 || getOverlayHeight() == 0) {
|
||||
error("convertOverlayToGame called without a valid overlay");
|
||||
}
|
||||
|
||||
return Common::Point(x * getWidth() / getOverlayWidth(),
|
||||
y * getHeight() / getOverlayHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given point from the game's coordinate space to the
|
||||
* overlay's coordinate space.
|
||||
*/
|
||||
Common::Point convertGameToOverlay(const int x, const int y) const {
|
||||
if (getWidth() == 0 || getHeight() == 0) {
|
||||
error("convertGameToOverlay called without a valid overlay");
|
||||
}
|
||||
|
||||
return Common::Point(x * getOverlayWidth() / getWidth(),
|
||||
y * getOverlayHeight() / getHeight());
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/graphics/sdl/sdl-graphics.h"
|
||||
#include "backends/graphics3d/sdl/sdl-graphics3d.h"
|
||||
#include "backends/platform/sdl/sdl-sys.h"
|
||||
#include "backends/events/sdl/resvm-sdl-events.h"
|
||||
|
@ -112,6 +112,21 @@ MODULE_OBJS += \
|
||||
vkeybd/virtual-keyboard-parser.o
|
||||
endif
|
||||
|
||||
# OpenGL specific source files.
|
||||
ifdef USE_OPENGL
|
||||
MODULE_OBJS += \
|
||||
graphics/opengl/context.o \
|
||||
graphics/opengl/debug.o \
|
||||
graphics/opengl/framebuffer.o \
|
||||
graphics/opengl/opengl-graphics.o \
|
||||
graphics/opengl/shader.o \
|
||||
graphics/opengl/texture.o \
|
||||
graphics/opengl/pipelines/clut8.o \
|
||||
graphics/opengl/pipelines/fixed.o \
|
||||
graphics/opengl/pipelines/pipeline.o \
|
||||
graphics/opengl/pipelines/shader.o
|
||||
endif
|
||||
|
||||
# SDL specific source files.
|
||||
# We cannot just check $BACKEND = sdl, as various other backends
|
||||
# derive from the SDL backend, and they all need the following files.
|
||||
@ -120,6 +135,8 @@ MODULE_OBJS += \
|
||||
events/sdl/legacy-sdl-events.o \
|
||||
events/sdl/sdl-events.o \
|
||||
events/sdl/resvm-sdl-events.o \
|
||||
graphics/sdl/sdl-graphics.o \
|
||||
graphics/surfacesdl/surfacesdl-graphics.o \
|
||||
graphics3d/sdl/sdl-graphics3d.o \
|
||||
graphics3d/surfacesdl/surfacesdl-graphics3d.o \
|
||||
mixer/sdl/sdl-mixer.o \
|
||||
@ -135,6 +152,7 @@ endif
|
||||
|
||||
ifdef USE_OPENGL
|
||||
MODULE_OBJS += \
|
||||
graphics/openglsdl/openglsdl-graphics.o \
|
||||
graphics3d/openglsdl/openglsdl-graphics3d.o
|
||||
endif
|
||||
|
||||
|
@ -49,9 +49,10 @@
|
||||
#include "backends/keymapper/hardware-input.h"
|
||||
#include "backends/mutex/sdl/sdl-mutex.h"
|
||||
#include "backends/timer/sdl/sdl-timer.h"
|
||||
#include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
|
||||
#include "backends/graphics3d/surfacesdl/surfacesdl-graphics3d.h" // ResidualVM specific
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
#include "backends/graphics/openglsdl/openglsdl-graphics.h"
|
||||
#include "backends/graphics3d/openglsdl/openglsdl-graphics3d.h" // ResidualVM specific
|
||||
#include "graphics/opengl/context.h" // ResidualVM specific
|
||||
#include "graphics/cursorman.h"
|
||||
@ -233,7 +234,6 @@ void OSystem_SDL::initBackend() {
|
||||
}
|
||||
|
||||
if (_graphicsManager == 0) {
|
||||
#if 0 // ResidualVM - not used
|
||||
#ifdef USE_OPENGL
|
||||
// Setup a list with both SDL and OpenGL graphics modes. We only do
|
||||
// this whenever the subclass did not already set up an graphics
|
||||
@ -254,7 +254,6 @@ void OSystem_SDL::initBackend() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ResidualVM
|
||||
#endif
|
||||
|
||||
if (_graphicsManager == 0) {
|
||||
@ -723,7 +722,6 @@ Common::String OSystem_SDL::getScreenshotsPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
#if 0 // ResidualVM - not used
|
||||
#ifdef USE_OPENGL
|
||||
|
||||
const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const {
|
||||
@ -772,14 +770,14 @@ bool OSystem_SDL::setGraphicsMode(int mode) {
|
||||
debug(1, "switching to plain SDL graphics");
|
||||
sdlGraphicsManager->deactivateManager();
|
||||
delete _graphicsManager;
|
||||
_graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphics3dManager(_eventSource, _window);
|
||||
_graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window);
|
||||
|
||||
switchedManager = true;
|
||||
} else if (_graphicsMode < _firstGLMode && mode >= _firstGLMode) {
|
||||
debug(1, "switching to OpenGL graphics");
|
||||
sdlGraphicsManager->deactivateManager();
|
||||
delete _graphicsManager;
|
||||
_graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphics3dManager(_eventSource, _window);
|
||||
_graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window);
|
||||
|
||||
switchedManager = true;
|
||||
}
|
||||
@ -829,7 +827,7 @@ void OSystem_SDL::setupGraphicsModes() {
|
||||
const OSystem::GraphicsMode *srcMode;
|
||||
int defaultMode;
|
||||
|
||||
GraphicsManager *manager = new SurfaceSdlGraphics3dManager(_eventSource, _window);
|
||||
GraphicsManager *manager = new SurfaceSdlGraphicsManager(_eventSource, _window);
|
||||
srcMode = manager->getSupportedGraphicsModes();
|
||||
defaultMode = manager->getDefaultGraphicsMode();
|
||||
while (srcMode->name) {
|
||||
@ -872,7 +870,6 @@ void OSystem_SDL::setupGraphicsModes() {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // ResidualVM
|
||||
|
||||
char *OSystem_SDL::convertEncoding(const char *to, const char *from, const char *string, size_t length) {
|
||||
#if SDL_VERSION_ATLEAST(1, 2, 10) && !defined(__MORPHOS__)
|
||||
|
@ -170,12 +170,11 @@ protected:
|
||||
* Creates the merged graphics modes list
|
||||
*/
|
||||
void setupGraphicsModes();
|
||||
// ResidualVM - Start
|
||||
//virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
|
||||
//virtual int getDefaultGraphicsMode() const override;
|
||||
//virtual bool setGraphicsMode(int mode) override;
|
||||
//virtual int getGraphicsMode() const override;
|
||||
// ResidualVM - End
|
||||
|
||||
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
|
||||
virtual int getDefaultGraphicsMode() const override;
|
||||
virtual bool setGraphicsMode(int mode) override;
|
||||
virtual int getGraphicsMode() const override;
|
||||
#endif
|
||||
protected:
|
||||
virtual char *convertEncoding(const char *to, const char *from, const char *string, size_t length) override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user