BACKENDS: Made code less different in SDL platform backend

This commit is contained in:
Pawel Kolodziejski 2020-09-29 15:08:16 +02:00
parent a3a42ee306
commit 6aa7cf6025
33 changed files with 10110 additions and 14 deletions

View File

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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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(&currentWidth, &currentHeight);
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);
}
}

View 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

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

View 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

File diff suppressed because it is too large Load Diff

View 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

View File

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

View File

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

View File

@ -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__)

View File

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