OPENGL: Add a Context class used to describe the active OpenGL context

This commit is contained in:
Bastien Bouclet 2016-01-09 08:22:26 +01:00
parent 482255032e
commit ed38c20cce
17 changed files with 276 additions and 140 deletions

View file

@ -45,7 +45,7 @@
#include "gui/EventRecorder.h"
#ifdef USE_OPENGL
#include "graphics/opengl/extensions.h"
#include "graphics/opengl/context.h"
#endif
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
@ -234,8 +234,8 @@ Graphics::PixelBuffer SurfaceSdlGraphicsManager::setupScreen(uint screenW, uint
SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=9000,9000"));
SDL_SetVideoMode(32, 32, 0, SDL_OPENGL);
SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=centered"));
OpenGL::initExtensions();
framebufferSupported = OpenGL::isExtensionSupported("GL_EXT_framebuffer_object");
OpenGLContext.initialize(OpenGL::kContextGL);
framebufferSupported = OpenGLContext.framebufferObjectSupported;
if (_fullscreen && framebufferSupported) {
screenW = _desktopW;
screenH = _desktopH;
@ -395,7 +395,7 @@ Graphics::PixelBuffer SurfaceSdlGraphicsManager::setupScreen(uint screenW, uint
_boxShader->enableVertexAttribute("texcoord", _boxVerticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
#endif
OpenGL::initExtensions();
OpenGLContext.initialize(OpenGL::kContextGL);
}
#endif
@ -1062,6 +1062,8 @@ void SurfaceSdlGraphicsManager::closeOverlay() {
SDL_FreeSurface(_subScreen);
_subScreen = nullptr;
}
OpenGL::Context::destroy();
#endif
}
}

View file

@ -43,7 +43,7 @@
#include "common/tokenizer.h"
#include "graphics/conversion.h"
#include "graphics/opengl/shader.h"
#include "graphics/opengl/extensions.h"
#include "graphics/opengl/context.h"
#include "backends/platform/android/android.h"
#include "backends/platform/android/jni.h"
@ -216,7 +216,7 @@ void OSystem_Android::initSurface() {
JNI::initSurface();
// Initialize OpenGLES context.
OpenGL::initExtensions();
OpenGLContext.initialize(OpenGL::kContextGLES2);
logExtensions();
GLESTexture::initGL();
@ -252,6 +252,8 @@ void OSystem_Android::deinitSurface() {
if (_mouse_texture)
_mouse_texture->release();
OpenGL::Context::destroy();
JNI::deinitSurface();
}

View file

@ -42,7 +42,7 @@
#include "base/main.h"
#include "graphics/surface.h"
#include "graphics/opengl/shader.h"
#include "graphics/opengl/extensions.h"
#include "graphics/opengl/context.h"
#include "common/rect.h"
#include "common/array.h"
@ -83,7 +83,7 @@ const GLfloat vertices[] = {
};
void GLESBaseTexture::initGL() {
npot_supported = OpenGL::isExtensionSupported("GL_ARB_texture_non_power_of_two");
npot_supported = OpenGLContext.NPOTSupported;
const char* attributes[] = { "position", "texcoord", NULL };
g_box_shader = OpenGL::Shader::fromStrings("control", OpenGL::BuiltinShaders::controlVertex, OpenGL::BuiltinShaders::controlFragment, attributes);

View file

@ -33,6 +33,7 @@
#if defined(USE_OPENGL) && !defined(USE_GLES2)
#include "graphics/colormasks.h"
#include "graphics/opengl/context.h"
#include "graphics/pixelbuffer.h"
#include "graphics/surface.h"
@ -47,15 +48,14 @@ Renderer *CreateGfxOpenGL(OSystem *system) {
}
OpenGLRenderer::OpenGLRenderer(OSystem *system) :
BaseRenderer(system),
_nonPowerOfTwoTexSupport(false) {
BaseRenderer(system) {
}
OpenGLRenderer::~OpenGLRenderer() {
}
Texture *OpenGLRenderer::createTexture(const Graphics::Surface *surface) {
return new OpenGLTexture(surface, _nonPowerOfTwoTexSupport);
return new OpenGLTexture(surface);
}
void OpenGLRenderer::freeTexture(Texture *texture) {
@ -71,11 +71,9 @@ void OpenGLRenderer::init() {
computeScreenViewport();
// Check the available OpenGL extensions
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
if (strstr(extensions, "GL_ARB_texture_non_power_of_two"))
_nonPowerOfTwoTexSupport = true;
else
if (!OpenGLContext.NPOTSupported) {
warning("GL_ARB_texture_non_power_of_two is not available.");
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

View file

@ -58,10 +58,6 @@ public:
virtual Graphics::Surface *getScreenshot() override;
private:
void drawFace(uint face, Texture *texture);
Math::Matrix4 _mvpMatrix;
bool _nonPowerOfTwoTexSupport;
};
} // End of namespace Myst3

View file

@ -57,7 +57,6 @@
#include "math/rect2d.h"
#include "math/quat.h"
#include "graphics/opengl/extensions.h"
#include "graphics/opengl/shader.h"
#include "engines/myst3/gfx.h"
@ -126,13 +125,7 @@ ShaderRenderer::~ShaderRenderer() {
}
Texture *ShaderRenderer::createTexture(const Graphics::Surface *surface) {
OpenGLTexture *texture = new OpenGLTexture(surface, true);
#if defined(USE_GLES2)
texture->setUnpackSubImageSupport(OpenGL::isExtensionSupported("GL_EXT_unpack_subimage"));
#endif
return texture;
return new OpenGLTexture(surface);
}
void ShaderRenderer::freeTexture(Texture *texture) {

View file

@ -26,10 +26,7 @@
#include "engines/myst3/gfx_opengl_texture.h"
#if !defined(GL_UNPACK_ROW_LENGTH)
// The Android SDK does not declare GL_UNPACK_ROW_LENGTH_EXT
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif
#include "graphics/opengl/context.h"
namespace Myst3 {
@ -45,15 +42,13 @@ static uint32 upperPowerOfTwo(uint32 v) {
return v;
}
OpenGLTexture::OpenGLTexture(const Graphics::Surface *surface, bool nonPoTSupport) :
_unpackSubImageSupport(true) {
OpenGLTexture::OpenGLTexture(const Graphics::Surface *surface) {
width = surface->w;
height = surface->h;
format = surface->format;
// Pad the textures if non power of two support is unavailable
if (nonPoTSupport) {
if (OpenGLContext.NPOTSupported) {
internalHeight = height;
internalWidth = width;
} else {
@ -101,7 +96,7 @@ void OpenGLTexture::update(const Graphics::Surface *surface) {
void OpenGLTexture::updateTexture(const Graphics::Surface* surface, const Common::Rect& rect) {
glBindTexture(GL_TEXTURE_2D, id);
if (_unpackSubImageSupport) {
if (OpenGLContext.unpackSubImageSupported) {
const Graphics::Surface subArea = surface->getSubArea(rect);
glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format.bytesPerPixel);

View file

@ -33,14 +33,12 @@ namespace Myst3 {
class OpenGLTexture : public Texture {
public:
OpenGLTexture(const Graphics::Surface *surface, bool nonPoTSupport = false);
OpenGLTexture(const Graphics::Surface *surface);
virtual ~OpenGLTexture();
void update(const Graphics::Surface *surface) override;
void updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) override;
void setUnpackSubImageSupport(bool unpackSubImageSupport) { _unpackSubImageSupport = unpackSubImageSupport; }
static void byteswapSurface(Graphics::Surface *surface);
GLuint id;
@ -51,8 +49,6 @@ public:
private:
void updateTexture(const Graphics::Surface *surface, const Common::Rect &rect);
bool _unpackSubImageSupport;
};
} // End of namespace Myst3

View file

@ -20,7 +20,6 @@
*
*/
#include <graphics/opengl/extensions.h>
#include "engines/stark/gfx/opengls.h"
#include "common/config-manager.h"

View file

@ -27,9 +27,9 @@ MODULE_OBJS := \
yuv_to_rgb.o \
yuva_to_rgba.o \
pixelbuffer.o \
opengl/context.o \
opengl/framebuffer.o \
opengl/texture.o \
opengl/extensions.o \
opengl/shader.o \
opengl/box_shaders.o \
opengl/control_shaders.o \

153
graphics/opengl/context.cpp Normal file
View file

@ -0,0 +1,153 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM 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 "graphics/opengl/context.h"
#include "common/debug.h"
#include "common/str.h"
#include "common/textconsole.h"
#include "common/tokenizer.h"
#include "graphics/opengl/system_headers.h"
#ifdef USE_OPENGL
namespace Common {
DECLARE_SINGLETON(OpenGL::Context);
}
namespace OpenGL {
Context::Context() {
reset();
}
void Context::reset() {
maxTextureSize = 0;
NPOTSupported = false;
shadersSupported = false;
framebufferObjectSupported = false;
packedDepthStencilSupported = false;
unpackSubImageSupported = false;
}
void Context::initialize(ContextType contextType) {
// Initialize default state.
reset();
type = contextType;
// Obtain maximum texture size.
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
debug(5, "OpenGL maximum texture size: %d", maxTextureSize);
const char *extString = (const char *)glGetString(GL_EXTENSIONS);
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") {
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_EXT_framebuffer_object") {
framebufferObjectSupported = true;
} else if (token == "GL_EXT_packed_depth_stencil" || token == "GL_OES_packed_depth_stencil") {
packedDepthStencilSupported = true;
} else if (token == "GL_EXT_unpack_subimage") {
unpackSubImageSupported = true;
}
}
int glslVersion = getGLSLVersion();
debug(5, "OpenGL GLSL version: %d", glslVersion);
if (type == kContextGLES2) {
// GLES2 always has (limited) NPOT support.
NPOTSupported = true;
// GLES2 always has shader support.
shadersSupported = true;
// GLES2 always has FBO support.
framebufferObjectSupported = true;
} else {
shadersSupported = ARBShaderObjects && ARBShadingLanguage100 && ARBVertexShader && ARBFragmentShader && glslVersion >= 120;
// Desktop GL always has unpack sub-image support
unpackSubImageSupported = true;
}
// Log context type.
switch (type) {
case kContextGL:
debug(5, "OpenGL: GL context initialized");
break;
case kContextGLES2:
debug(5, "OpenGL: GLES2 context initialized");
break;
}
// Log features supported by GL context.
debug(5, "OpenGL: NPOT texture support: %d", NPOTSupported);
debug(5, "OpenGL: Shader support: %d", shadersSupported);
debug(5, "OpenGL: FBO support: %d", framebufferObjectSupported);
debug(5, "OpenGL: Packed depth stencil support: %d", packedDepthStencilSupported);
debug(5, "OpenGL: Unpack subimage support: %d", unpackSubImageSupported);
}
int Context::getGLSLVersion() const {
const char *glslVersionString = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
const char *glslVersionFormat;
if (type == kContextGL) {
glslVersionFormat = "%d.%d";
} else {
glslVersionFormat = "OpenGL ES GLSL ES %d.%d";
}
int glslMajorVersion, glslMinorVersion;
if (sscanf(glslVersionString, glslVersionFormat, &glslMajorVersion, &glslMinorVersion) != 2) {
warning("Could not parse GLSL version '%s'", glslVersionString);
return 0;
}
return glslMajorVersion * 100 + glslMinorVersion;
}
} // End of namespace OpenGL
#endif

88
graphics/opengl/context.h Normal file
View file

@ -0,0 +1,88 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM 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 GRAPHICS_OPENGL_CONTEXT_H
#define GRAPHICS_OPENGL_CONTEXT_H
#include "common/singleton.h"
namespace OpenGL {
enum ContextType {
kContextGL,
kContextGLES2
};
/**
* Description structure of the OpenGL (ES) context.
*
* This class is based on LordHoto's OpenGL backend for ScummVM
*/
class Context : public Common::Singleton<Context> {
public:
Context();
/**
* Initialize the context description from currently active context.
*
* The extensions and features are marked as available according
* to the current context capabilities.
*/
void initialize(ContextType contextType);
/**
* Reset context.
*
* This marks all extensions as unavailable.
*/
void reset();
/** The type of the active context. */
ContextType type;
/** The maximum texture size supported by the context. */
int 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 FBO support is available or not. */
bool framebufferObjectSupported;
/** Whether packing the depth and stencil buffers is possible or not. */
bool packedDepthStencilSupported;
/** Whether specifying a pitch when uploading to textures is available or not */
bool unpackSubImageSupported;
int getGLSLVersion() const;
};
} // End of namespace OpenGL
/** Shortcut for accessing the active OpenGL context. */
#define OpenGLContext OpenGL::Context::instance()
#endif

View file

@ -1,52 +0,0 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM 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 "common/algorithm.h"
#include "common/list.h"
#include "common/str.h"
#include "common/tokenizer.h"
#include "graphics/opengl/system_headers.h"
#ifdef USE_OPENGL
namespace OpenGL {
static Common::List<Common::String> g_extensions;
void initExtensions() {
g_extensions.clear();
const char *exts = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
Common::StringTokenizer tokenizer(exts, " ");
while (!tokenizer.empty()) {
g_extensions.push_back(tokenizer.nextToken());
}
}
bool isExtensionSupported(const char *wanted) {
return g_extensions.end() != find(g_extensions.begin(), g_extensions.end(), wanted);
}
} // End of namespace OpenGL
#endif

View file

@ -1,33 +0,0 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM 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 GRAPHICS_EXTENSIONS_H
#define GRAPHICS_EXTENSIONS_H
namespace OpenGL {
void initExtensions();
bool isExtensionSupported(const char *extension);
}
#endif

View file

@ -42,7 +42,7 @@
#include "backends/platform/sdl/sdl-sys.h"
#endif // defined(SDL_BACKEND)
#include "graphics/opengl/extensions.h"
#include "graphics/opengl/context.h"
#ifdef USE_GLES2
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
@ -101,19 +101,13 @@ static void grabFramebufferObjectPointers() {
static bool usePackedBuffer() {
#ifdef USE_GLES2
return isExtensionSupported("GL_OES_packed_depth_stencil");
#endif
#ifndef USE_OPENGL_SHADERS
return isExtensionSupported("GL_EXT_packed_depth_stencil");
#endif
return true;
return OpenGLContext.packedDepthStencilSupported;
}
FrameBuffer::FrameBuffer(uint width, uint height) :
Texture(width, height) {
#ifdef SDL_BACKEND
if (!isExtensionSupported("GL_EXT_framebuffer_object")) {
if (!OpenGLContext.framebufferObjectSupported) {
error("GL_EXT_framebuffer_object extension is not supported!");
}
#endif

View file

@ -41,6 +41,11 @@
# define GL_BGRA GL_BGRA_EXT
#endif
#if !defined(GL_UNPACK_ROW_LENGTH)
// The Android SDK does not declare GL_UNPACK_ROW_LENGTH_EXT
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif
#elif defined(USE_GLEW)
#include <GL/glew.h>
#elif defined(SDL_BACKEND) && defined(USE_OPENGL)

View file

@ -25,7 +25,7 @@
#if defined(USE_OPENGL)
#include "graphics/opengl/texture.h"
#include "graphics/opengl/extensions.h"
#include "graphics/opengl/context.h"
namespace OpenGL {
@ -52,7 +52,7 @@ static const Graphics::PixelFormat getRGBAPixelFormat() {
Texture::Texture(const Graphics::Surface &srf) :
_managedTexture(true), _width(srf.w), _height(srf.h) {
if (isExtensionSupported("GL_ARB_texture_non_power_of_two")) {
if (OpenGLContext.NPOTSupported) {
_texWidth = _width;
_texHeight = _height;
} else {
@ -80,7 +80,7 @@ Texture::Texture(const Graphics::Surface &srf) :
Texture::Texture(uint width, uint height) :
_managedTexture(true), _width(width), _height(height) {
if (isExtensionSupported("GL_ARB_texture_non_power_of_two")) {
if (OpenGLContext.NPOTSupported) {
_texWidth = _width;
_texHeight = _height;
} else {