OPENGL: Merge both OpenGL contexts

This commit is contained in:
Le Philousophe 2022-04-25 15:36:50 +02:00
parent 9aef2f7b98
commit 4ab044a254
39 changed files with 392 additions and 593 deletions

View file

@ -93,19 +93,22 @@ void AndroidGraphicsManager::initSurface() {
assert(!JNI::haveSurface());
JNI::initSurface();
// Notify the OpenGL code about our context.
setContextType(OpenGL::kContextGLES2);
if (JNI::egl_bits_per_pixel == 16) {
// We default to RGB565 and RGBA5551 which is closest to what we setup in Java side
notifyContextCreate(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
notifyContextCreate(OpenGL::kContextGLES2,
Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0),
Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
} else {
// If not 16, this must be 24 or 32 bpp so make use of them
notifyContextCreate(OpenGL::kContextGLES2,
#ifdef SCUMM_BIG_ENDIAN
notifyContextCreate(Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0),
Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)
#else
notifyContextCreate(Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0),
Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)
#endif
);
}
if (_touchcontrols) {
@ -203,8 +206,8 @@ void AndroidGraphicsManager::refreshScreen() {
void AndroidGraphicsManager::touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) {
_backBuffer.enableBlend(OpenGL::Framebuffer::kBlendModeTraditionalTransparency);
OpenGL::g_context.getActivePipeline()->drawTexture(_touchcontrols->getGLTexture(),
x, y, w, h, clip);
OpenGL::Pipeline::getActivePipeline()->drawTexture(_touchcontrols->getGLTexture(),
x, y, w, h, clip);
}
void AndroidGraphicsManager::touchControlNotifyChanged() {
@ -212,12 +215,6 @@ void AndroidGraphicsManager::touchControlNotifyChanged() {
_forceRedraw = true;
}
void *AndroidGraphicsManager::getProcAddress(const char *name) const {
ENTER("%s", name);
return androidGLgetProcAddress(name);
}
bool AndroidGraphicsManager::notifyMousePosition(Common::Point &mouse) {
mouse.x = CLIP<int16>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right);
mouse.y = CLIP<int16>(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom);

View file

@ -98,8 +98,6 @@ protected:
void refreshScreen() override;
void *getProcAddress(const char *name) const override;
private:
OpenGL::Surface *_touchcontrols;
int _old_touch_mode;

View file

@ -1,240 +0,0 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#define GLAD_GL_IMPLEMENTATION
#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;
majorVersion = 0;
minorVersion = 0;
NPOTSupported = false;
shadersSupported = false;
multitextureSupported = false;
framebufferObjectSupported = false;
packedPixelsSupported = false;
textureEdgeClampSupported = false;
isInitialized = false;
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;
}
#ifdef USE_GLAD
static GLADapiproc loadFunc(void *userptr, const char *name) {
OpenGLGraphicsManager *openglGraphicsManager = (OpenGLGraphicsManager *)userptr;
return (GLADapiproc)openglGraphicsManager->getProcAddress(name);
}
#endif
void OpenGLGraphicsManager::initializeGLContext() {
// Initialize default state.
g_context.reset();
#ifdef USE_GLAD
switch (g_context.type) {
case kContextGL:
gladLoadGLUserPtr(loadFunc, this);
break;
case kContextGLES:
gladLoadGLES1UserPtr(loadFunc, this);
break;
case kContextGLES2:
gladLoadGLES2UserPtr(loadFunc, this);
break;
default:
break;
}
#endif
g_context.isInitialized = true;
// 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 *verString = (const char *)glGetString(GL_VERSION);
debug(5, "OpenGL version: %s", verString);
if (g_context.type == kContextGL) {
// OpenGL version number is either of the form major.minor or major.minor.release,
// where the numbers all have one or more digits
if (sscanf(verString, "%d.%d", &g_context.majorVersion, &g_context.minorVersion) != 2) {
g_context.majorVersion = g_context.minorVersion = 0;
warning("Could not parse GL version '%s'", verString);
}
} else if (g_context.type == kContextGLES) {
// The form of the string is "OpenGL ES-<profile> <major>.<minor>",
// where <profile> is either "CM" (Common) or "CL" (Common-Lite),
// and <major> and <minor> are integers.
char profile[3];
if (sscanf(verString, "OpenGL ES-%2s %d.%d", profile,
&g_context.majorVersion, &g_context.minorVersion) != 3) {
g_context.majorVersion = g_context.minorVersion = 0;
warning("Could not parse GL ES version '%s'", verString);
}
} else if (g_context.type == kContextGLES2) {
// The version is of the form
// OpenGL<space>ES<space><version number><space><vendor-specific information>
// version number format is not defined
// There is only OpenGL ES 2.0 anyway
if (sscanf(verString, "OpenGL ES %d.%d", &g_context.majorVersion, &g_context.minorVersion) != 2) {
g_context.minorVersion = 0;
if (sscanf(verString, "OpenGL ES %d ", &g_context.majorVersion) != 1) {
g_context.majorVersion = 0;
warning("Could not parse GL ES 2 version '%s'", verString);
}
}
}
const char *extString = (const char *)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_ARB_framebuffer_object") {
g_context.framebufferObjectSupported = true;
} else if (token == "GL_EXT_packed_pixels" || token == "GL_APPLE_packed_pixels") {
g_context.packedPixelsSupported = true;
} else if (token == "GL_SGIS_texture_edge_clamp") {
g_context.textureEdgeClampSupported = 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;
}
// OpenGL 1.2 and later always has packed pixels and texture edge clamp support
if (g_context.type != kContextGL || g_context.isGLVersionOrHigher(1, 2)) {
g_context.packedPixelsSupported = true;
g_context.textureEdgeClampSupported = true;
}
// 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.
#if !USE_FORCED_GLES
if (g_context.shadersSupported)
debug(5, "GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
#endif
debug(5, "OpenGL vendor: %s", glGetString(GL_VENDOR));
debug(5, "OpenGL renderer: %s", glGetString(GL_RENDERER));
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);
debug(5, "OpenGL: Packed pixels support: %d", g_context.packedPixelsSupported);
debug(5, "OpenGL: Texture edge clamping support: %d", g_context.textureEdgeClampSupported);
}
} // End of namespace OpenGL

View file

@ -20,11 +20,12 @@
*/
#include "backends/graphics/opengl/debug.h"
#include "backends/graphics/opengl/opengl-sys.h"
#include "common/str.h"
#include "common/textconsole.h"
#include "graphics/opengl/system_headers.h"
#ifdef OPENGL_DEBUG
namespace OpenGL {

View file

@ -22,6 +22,8 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_DEBUG_H
#define BACKENDS_GRAPHICS_OPENGL_DEBUG_H
#include "graphics/opengl/context.h"
#define OPENGL_DEBUG
#ifdef OPENGL_DEBUG
@ -35,4 +37,13 @@ void checkGLError(const char *expr, const char *file, int line);
#define GL_WRAP_DEBUG(call, name) do { (call); } while (false)
#endif
#define GL_CALL(x) GL_WRAP_DEBUG(x, x)
#define GL_CALL_SAFE(func, params) \
do { \
if (OpenGLContext.type != kContextNone) { \
GL_CALL(func params); \
} \
} while (0)
#define GL_ASSIGN(var, x) GL_WRAP_DEBUG(var = x, x)
#endif

View file

@ -19,6 +19,7 @@
*
*/
#include "backends/graphics/opengl/debug.h"
#include "backends/graphics/opengl/framebuffer.h"
#include "backends/graphics/opengl/texture.h"
#include "backends/graphics/opengl/pipelines/pipeline.h"
@ -96,7 +97,7 @@ void Framebuffer::applyViewport() {
}
void Framebuffer::applyProjectionMatrix() {
g_context.getActivePipeline()->setProjectionMatrix(_projectionMatrix);
Pipeline::getActivePipeline()->setProjectionMatrix(_projectionMatrix);
}
void Framebuffer::applyClearColor() {
@ -139,7 +140,7 @@ void Framebuffer::applyScissorBox() {
void Backbuffer::activateInternal() {
#if !USE_FORCED_GLES
if (g_context.framebufferObjectSupported) {
if (OpenGLContext.framebufferObjectSupported) {
GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
}
#endif

View file

@ -22,7 +22,7 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_FRAMEBUFFER_H
#define BACKENDS_GRAPHICS_OPENGL_FRAMEBUFFER_H
#include "backends/graphics/opengl/opengl-sys.h"
#include "graphics/opengl/system_headers.h"
namespace OpenGL {

View file

@ -21,6 +21,7 @@
#include "backends/graphics/opengl/opengl-graphics.h"
#include "backends/graphics/opengl/debug.h"
#include "backends/graphics/opengl/texture.h"
#include "backends/graphics/opengl/pipelines/pipeline.h"
#include "backends/graphics/opengl/pipelines/fixed.h"
@ -79,7 +80,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
#endif
{
memset(_gamePalette, 0, sizeof(_gamePalette));
g_context.reset();
OpenGLContext.reset();
}
OpenGLGraphicsManager::~OpenGLGraphicsManager() {
@ -391,8 +392,8 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
// a context existing before, which means we don't know the maximum
// supported texture size before this. Thus, we check whether the
// requested game resolution is supported over here.
|| ( _currentState.gameWidth > (uint)g_context.maxTextureSize
|| _currentState.gameHeight > (uint)g_context.maxTextureSize)) {
|| ( _currentState.gameWidth > (uint)OpenGLContext.maxTextureSize
|| _currentState.gameHeight > (uint)OpenGLContext.maxTextureSize)) {
if (_transactionMode == kTransactionActive) {
// Try to setup the old state in case its valid and is
// actually different from the new one.
@ -587,21 +588,21 @@ void OpenGLGraphicsManager::updateScreen() {
_backBuffer.enableBlend(Framebuffer::kBlendModeDisabled);
// First step: Draw the (virtual) game screen.
g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
Pipeline::getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
// Second step: Draw the overlay if visible.
if (_overlayVisible) {
int dstX = (_windowWidth - _overlayDrawRect.width()) / 2;
int dstY = (_windowHeight - _overlayDrawRect.height()) / 2;
_backBuffer.enableBlend(Framebuffer::kBlendModeTraditionalTransparency);
g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), dstX, dstY, _overlayDrawRect.width(), _overlayDrawRect.height());
Pipeline::getActivePipeline()->drawTexture(_overlay->getGLTexture(), dstX, dstY, _overlayDrawRect.width(), _overlayDrawRect.height());
}
// Third step: Draw the cursor if visible.
if (_cursorVisible && _cursor) {
_backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
g_context.getActivePipeline()->drawTexture(_cursor->getGLTexture(),
Pipeline::getActivePipeline()->drawTexture(_cursor->getGLTexture(),
_cursorX - _cursorHotspotXScaled + _shakeOffsetScaled.x,
_cursorY - _cursorHotspotYScaled + _shakeOffsetScaled.y,
_cursorWidthScaled, _cursorHeightScaled);
@ -631,17 +632,17 @@ void OpenGLGraphicsManager::updateScreen() {
}
// Set the OSD transparency.
g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f);
Pipeline::getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f);
int dstX = (_windowWidth - _osdMessageSurface->getWidth()) / 2;
int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2;
// Draw the OSD texture.
g_context.getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(),
Pipeline::getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(),
dstX, dstY, _osdMessageSurface->getWidth(), _osdMessageSurface->getHeight());
// Reset color.
g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
Pipeline::getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
if (_osdMessageAlpha <= 0) {
delete _osdMessageSurface;
@ -658,7 +659,7 @@ void OpenGLGraphicsManager::updateScreen() {
int dstY = kOSDIconTopMargin;
// Draw the OSD icon texture.
g_context.getActivePipeline()->drawTexture(_osdIconSurface->getGLTexture(),
Pipeline::getActivePipeline()->drawTexture(_osdIconSurface->getGLTexture(),
dstX, dstY, _osdIconSurface->getWidth(), _osdIconSurface->getHeight());
}
#endif
@ -1019,15 +1020,15 @@ void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height)
// possible and then scale it to the physical display size. This sounds
// bad but actually all recent chips should support full HD resolution
// anyway. Thus, it should not be a real issue for modern hardware.
if ( overlayWidth > (uint)g_context.maxTextureSize
|| overlayHeight > (uint)g_context.maxTextureSize) {
if ( overlayWidth > (uint)OpenGLContext.maxTextureSize
|| overlayHeight > (uint)OpenGLContext.maxTextureSize) {
const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight;
if (outputAspect > (frac_t)FRAC_ONE) {
overlayWidth = g_context.maxTextureSize;
overlayWidth = OpenGLContext.maxTextureSize;
overlayHeight = intToFrac(overlayWidth) / outputAspect;
} else {
overlayHeight = g_context.maxTextureSize;
overlayHeight = OpenGLContext.maxTextureSize;
overlayWidth = fracToInt(overlayHeight * outputAspect);
}
}
@ -1065,16 +1066,17 @@ void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height)
++_screenChangeID;
}
void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) {
// Initialize context for use.
initializeGLContext();
void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
const Graphics::PixelFormat &defaultFormat,
const Graphics::PixelFormat &defaultFormatAlpha) {
// Initialize pipeline.
delete _pipeline;
_pipeline = nullptr;
OpenGLContext.initialize(type);
#if !USE_FORCED_GLES
if (g_context.shadersSupported) {
if (OpenGLContext.shadersSupported) {
ShaderMan.notifyCreate();
_pipeline = new ShaderPipeline(ShaderMan.query(ShaderManager::kDefault));
}
@ -1086,21 +1088,21 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
}
#endif
g_context.setPipeline(_pipeline);
Pipeline::setPipeline(_pipeline);
// Disable 3D properties.
GL_CALL(glDisable(GL_CULL_FACE));
GL_CALL(glDisable(GL_DEPTH_TEST));
GL_CALL(glDisable(GL_DITHER));
g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
Pipeline::getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
// Setup backbuffer state.
// Default to black as clear color.
_backBuffer.setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
g_context.getActivePipeline()->setFramebuffer(&_backBuffer);
Pipeline::getActivePipeline()->setFramebuffer(&_backBuffer);
// We use a "pack" alignment (when reading from textures) to 4 here,
// since the only place where we really use it is the BMP screenshot
@ -1165,18 +1167,18 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
#endif
#if !USE_FORCED_GLES
if (g_context.shadersSupported) {
if (OpenGLContext.shadersSupported) {
ShaderMan.notifyDestroy();
}
#endif
// Destroy rendering pipeline.
g_context.setPipeline(nullptr);
Pipeline::setPipeline(nullptr);
delete _pipeline;
_pipeline = nullptr;
// Rest our context description since the context is gone soon.
g_context.reset();
OpenGLContext.reset();
}
Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha, bool wantScaler) {
@ -1213,7 +1215,7 @@ Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &forma
}
} else if (getGLPixelFormat(format, glIntFormat, glFormat, glType)) {
return new Texture(glIntFormat, glFormat, glType, format);
} else if (g_context.packedPixelsSupported && format == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) {
} else if (OpenGLContext.packedPixelsSupported && format == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) {
// OpenGL ES does not support a texture format usable for RGB555.
// Since SCUMM uses this pixel format for some games (and there is no
// hope for this to change anytime soon) we use pixel format
@ -1244,7 +1246,7 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF
glFormat = GL_RGBA;
glType = GL_UNSIGNED_BYTE;
return true;
} else if (!g_context.packedPixelsSupported) {
} else if (!OpenGLContext.packedPixelsSupported) {
return false;
} else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565
glIntFormat = GL_RGB;

View file

@ -22,7 +22,6 @@
#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"
@ -130,28 +129,22 @@ 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);
bool isGLESContext() const { return OpenGLContext.type == kContextGLES || OpenGLContext.type == kContextGLES2; }
/**
* Notify the manager of a OpenGL context change. This should be the first
* thing to call after you created an OpenGL (ES) context!
*
* @param type Type of the OpenGL (ES) contexts created.
* @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);
void notifyContextCreate(
ContextType type,
const Graphics::PixelFormat &defaultFormat,
const Graphics::PixelFormat &defaultFormatAlpha);
/**
* Notify the manager that the OpenGL context is about to be destroyed.
@ -300,20 +293,6 @@ private:
*/
Pipeline *_pipeline;
public:
/**
* 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;
protected:
/**
* Try to determine the internal parameters for a given pixel format.

View file

@ -1,136 +0,0 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_SYS_H
#define BACKENDS_GRAPHICS_OPENGL_OPENGL_SYS_H
#include "common/scummsys.h"
#include "graphics/opengl/system_headers.h"
#include "backends/graphics/opengl/debug.h"
// 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 GLuint GLprogram;
typedef GLuint GLshader;
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;
/** Whether the context is initialized or not. */
bool isInitialized;
/**
* Reset context.
*
* This marks all extensions as unavailable and clears all function
* pointers.
*/
void reset();
/** Helper function for checking the GL version supported by the context. */
inline bool isGLVersionOrHigher(int major, int minor) {
return ((majorVersion > major) || ((majorVersion == major) && (minorVersion >= minor)));
}
/** The GL version supported by the context. */
int majorVersion, minorVersion;
/** 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;
/** Whether packed pixels support is available or not. */
bool packedPixelsSupported;
/** Whether texture coordinate edge clamping is available or not. */
bool textureEdgeClampSupported;
//
// 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(x, x)
#define GL_CALL_SAFE(func, params) \
do { \
if (g_context.isInitialized) { \
GL_CALL(func params); \
} \
} while (0)
#define GL_ASSIGN(var, x) GL_WRAP_DEBUG(var = x, x)
#endif

View file

@ -20,6 +20,7 @@
*/
#include "backends/graphics/opengl/pipelines/clut8.h"
#include "backends/graphics/opengl/debug.h"
#include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/framebuffer.h"

View file

@ -20,6 +20,7 @@
*/
#include "backends/graphics/opengl/pipelines/fixed.h"
#include "backends/graphics/opengl/debug.h"
namespace OpenGL {
@ -34,7 +35,7 @@ void FixedPipeline::activateInternal() {
GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
#if !USE_FORCED_GLES
if (g_context.multitextureSupported) {
if (OpenGLContext.multitextureSupported) {
GL_CALL(glActiveTexture(GL_TEXTURE0));
}
#endif

View file

@ -24,6 +24,8 @@
namespace OpenGL {
Pipeline *Pipeline::activePipeline = nullptr;
Pipeline::Pipeline()
: _activeFramebuffer(nullptr), _isActive(false) {
}
@ -62,4 +64,18 @@ Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
return oldFramebuffer;
}
Pipeline *Pipeline::setPipeline(Pipeline *pipeline) {
Pipeline *oldPipeline = activePipeline;
if (oldPipeline) {
oldPipeline->deactivate();
}
activePipeline = pipeline;
if (activePipeline) {
activePipeline->activate();
}
return oldPipeline;
}
} // End of namespace OpenGL

View file

@ -22,7 +22,8 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
#define BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
#include "backends/graphics/opengl/opengl-sys.h"
#include "graphics/opengl/system_headers.h"
#include "backends/graphics/opengl/texture.h"
namespace OpenGL {
@ -148,6 +149,25 @@ protected:
private:
bool _isActive;
/** Currently active rendering pipeline. */
static 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.
*/
static Pipeline *setPipeline(Pipeline *pipeline);
/**
* Query the currently active rendering pipeline.
*/
static Pipeline *getActivePipeline() { return activePipeline; }
};
} // End of namespace OpenGL

View file

@ -20,6 +20,7 @@
*/
#include "backends/graphics/opengl/pipelines/shader.h"
#include "backends/graphics/opengl/debug.h"
#include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/framebuffer.h"
@ -50,7 +51,7 @@ void ShaderPipeline::activateInternal() {
GL_CALL(glEnableVertexAttribArray(_texCoordAttribLocation));
GL_CALL(glEnableVertexAttribArray(_colorAttribLocation));
if (g_context.multitextureSupported) {
if (OpenGLContext.multitextureSupported) {
GL_CALL(glActiveTexture(GL_TEXTURE0));
}

View file

@ -20,9 +20,9 @@
*/
#include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/debug.h"
#if !USE_FORCED_GLES
#include "common/textconsole.h"
#include "common/util.h"
@ -252,7 +252,7 @@ bool Shader::setUniform(const Common::String &name, ShaderUniformValue *value) {
}
GLshader Shader::compileShader(const char *source, GLenum shaderType) {
const GLchar *versionSource = g_context.type == kContextGLES2 ? "#version 100\n" : "#version 110\n";
const GLchar *versionSource = OpenGLContext.type == kContextGLES2 ? "#version 100\n" : "#version 110\n";
const GLchar *compatSource = shaderType == GL_VERTEX_SHADER ? "" : g_precisionDefines;
GLshader handle;

View file

@ -22,7 +22,7 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_SHADER_H
#define BACKENDS_GRAPHICS_OPENGL_SHADER_H
#include "backends/graphics/opengl/opengl-sys.h"
#include "graphics/opengl/system_headers.h"
#if !USE_FORCED_GLES
@ -30,6 +30,12 @@
#include "common/hash-str.h"
#include "common/ptr.h"
// 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 GLuint GLprogram;
typedef GLuint GLshader;
namespace OpenGL {
/**

View file

@ -20,6 +20,7 @@
*/
#include "backends/graphics/opengl/texture.h"
#include "backends/graphics/opengl/debug.h"
#include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/pipelines/pipeline.h"
#include "backends/graphics/opengl/pipelines/clut8.h"
@ -80,7 +81,7 @@ void GLTexture::create() {
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));
if (g_context.textureEdgeClampSupported) {
if (OpenGLContext.textureEdgeClampSupported) {
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));
} else {
@ -106,7 +107,7 @@ void GLTexture::setSize(uint width, uint height) {
const uint oldWidth = _width;
const uint oldHeight = _height;
if (!g_context.NPOTSupported) {
if (!OpenGLContext.NPOTSupported) {
_width = Common::nextHigher2(width);
_height = Common::nextHigher2(height);
} else {
@ -734,13 +735,13 @@ void TextureCLUT8GPU::updateGLTexture() {
void TextureCLUT8GPU::lookUpColors() {
// Setup pipeline to do color look up.
Pipeline *oldPipeline = g_context.setPipeline(_clut8Pipeline);
Pipeline *oldPipeline = Pipeline::setPipeline(_clut8Pipeline);
// Do color look up.
g_context.getActivePipeline()->drawTexture(_clut8Texture, _clut8Vertices);
Pipeline::getActivePipeline()->drawTexture(_clut8Texture, _clut8Vertices);
// Restore old state.
g_context.setPipeline(oldPipeline);
Pipeline::setPipeline(oldPipeline);
}
#endif // !USE_FORCED_GLES

View file

@ -22,7 +22,8 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_TEXTURE_H
#define BACKENDS_GRAPHICS_OPENGL_TEXTURE_H
#include "backends/graphics/opengl/opengl-sys.h"
#include "graphics/opengl/system_headers.h"
#include "graphics/opengl/context.h"
#include "graphics/pixelformat.h"
#include "graphics/surface.h"
@ -405,9 +406,9 @@ public:
virtual const GLTexture &getGLTexture() const;
static bool isSupportedByContext() {
return g_context.shadersSupported
&& g_context.multitextureSupported
&& g_context.framebufferObjectSupported;
return OpenGLContext.shadersSupported
&& OpenGLContext.multitextureSupported
&& OpenGLContext.framebufferObjectSupported;
}
private:
void lookUpColors();

View file

@ -49,8 +49,6 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
// 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 {
@ -65,17 +63,17 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
};
#if USE_FORCED_GL
glContextType = OpenGL::kContextGL;
_glContextType = OpenGL::kContextGL;
_glContextProfileMask = 0;
_glContextMajor = DEFAULT_GL_MAJOR;
_glContextMinor = DEFAULT_GL_MINOR;
#elif USE_FORCED_GLES
glContextType = OpenGL::kContextGLES;
_glContextType = OpenGL::kContextGLES;
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
_glContextMajor = DEFAULT_GLES_MAJOR;
_glContextMinor = DEFAULT_GLES_MINOR;
#elif USE_FORCED_GLES2
glContextType = OpenGL::kContextGLES2;
_glContextType = OpenGL::kContextGLES2;
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
_glContextMajor = DEFAULT_GLES2_MAJOR;
_glContextMinor = DEFAULT_GLES2_MINOR;
@ -115,12 +113,12 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) {
if (_glContextMajor >= 2) {
glContextType = OpenGL::kContextGLES2;
_glContextType = OpenGL::kContextGLES2;
} else {
glContextType = OpenGL::kContextGLES;
_glContextType = OpenGL::kContextGLES;
}
} else if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_CORE) {
glContextType = OpenGL::kContextGL;
_glContextType = OpenGL::kContextGL;
// Core profile does not allow legacy functionality, which we use.
// Thus we request a standard OpenGL context.
@ -128,13 +126,11 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
_glContextMajor = DEFAULT_GL_MAJOR;
_glContextMinor = DEFAULT_GL_MINOR;
} else {
glContextType = OpenGL::kContextGL;
_glContextType = OpenGL::kContextGL;
}
#endif
setContextType(glContextType);
#else
setContextType(OpenGL::kContextGL);
_glContextType = OpenGL::kContextGL;
#endif
// Retrieve a list of working fullscreen modes
@ -426,10 +422,6 @@ void OpenGLSdlGraphicsManager::refreshScreen() {
#endif
}
void *OpenGLSdlGraphicsManager::getProcAddress(const char *name) const {
return SDL_GL_GetProcAddress(name);
}
void OpenGLSdlGraphicsManager::handleResizeImpl(const int width, const int height) {
OpenGLGraphicsManager::handleResizeImpl(width, height);
SdlGraphicsManager::handleResizeImpl(width, height);
@ -550,7 +542,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
}
#endif
notifyContextCreate(rgba8888, rgba8888);
notifyContextCreate(_glContextType, rgba8888, rgba8888);
int actualWidth, actualHeight;
getWindowSizeFromSdl(&actualWidth, &actualHeight);
@ -617,7 +609,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
_lastVideoModeLoad = SDL_GetTicks();
if (_hwScreen) {
notifyContextCreate(rgba8888, rgba8888);
notifyContextCreate(_glContextType, rgba8888, rgba8888);
handleResize(_hwScreen->w, _hwScreen->h);
}

View file

@ -55,8 +55,6 @@ protected:
void refreshScreen() override;
void *getProcAddress(const char *name) const override;
void handleResizeImpl(const int width, const int height) override;
bool saveScreenshot(const Common::String &filename) const override;
@ -66,10 +64,12 @@ private:
#if SDL_VERSION_ATLEAST(2, 0, 0)
int _glContextProfileMask, _glContextMajor, _glContextMinor;
SDL_GLContext _glContext;
#else
uint32 _lastVideoModeLoad;
#endif
OpenGL::ContextType _glContextType;
uint _lastRequestedWidth;
uint _lastRequestedHeight;

View file

@ -171,7 +171,7 @@ void AndroidGraphics3dManager::initSurface() {
_screenChangeID = JNI::surface_changeid;
// Initialize OpenGLES context.
OpenGLContext.initialize(OpenGL::kOGLContextGLES2);
OpenGLContext.initialize(OpenGL::kContextGLES2);
logExtensions();
GLESTexture::initGL();
@ -244,7 +244,7 @@ void AndroidGraphics3dManager::deinitSurface() {
_touchcontrols_texture->release();
}
OpenGL::ContextGL::destroy();
OpenGLContext.reset();
JNI::deinitSurface();
}

View file

@ -83,7 +83,7 @@ OpenGLSdlGraphics3dManager::OpenGLSdlGraphics3dManager(SdlEventSource *eventSour
};
#if USE_FORCED_GLES2
_glContextType = OpenGL::kOGLContextGLES2;
_glContextType = OpenGL::kContextGLES2;
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
_glContextMajor = DEFAULT_GLES2_MAJOR;
_glContextMinor = DEFAULT_GLES2_MINOR;
@ -123,9 +123,9 @@ OpenGLSdlGraphics3dManager::OpenGLSdlGraphics3dManager(SdlEventSource *eventSour
if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) {
// TODO: Support GLES1 for games
_glContextType = OpenGL::kOGLContextGLES2;
_glContextType = OpenGL::kContextGLES2;
} else if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_CORE) {
_glContextType = OpenGL::kOGLContextGL;
_glContextType = OpenGL::kContextGL;
// Core profile does not allow legacy functionality, which we use.
// Thus we request a standard OpenGL context.
@ -133,11 +133,11 @@ OpenGLSdlGraphics3dManager::OpenGLSdlGraphics3dManager(SdlEventSource *eventSour
_glContextMajor = DEFAULT_GL_MAJOR;
_glContextMinor = DEFAULT_GL_MINOR;
} else {
_glContextType = OpenGL::kOGLContextGL;
_glContextType = OpenGL::kContextGL;
}
#endif
#else
_glContextType = OpenGL::kOGLContextGL;
_glContextType = OpenGL::kContextGL;
#endif
}
@ -718,7 +718,7 @@ void OpenGLSdlGraphics3dManager::closeOverlay() {
delete _frameBuffer;
_frameBuffer = nullptr;
OpenGL::ContextGL::destroy();
OpenGLContext.reset();
}
int16 OpenGLSdlGraphics3dManager::getOverlayHeight() const {

View file

@ -121,7 +121,7 @@ protected:
void deinitializeRenderer();
#endif
OpenGL::ContextOGLType _glContextType;
OpenGL::ContextType _glContextType;
bool _supportsFrameBuffer;

View file

@ -123,7 +123,6 @@ 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 \

View file

@ -121,11 +121,6 @@ void checkGlError(const char *expr, const char *file, int line) {
}
#endif
void *androidGLgetProcAddress(const char *name) {
// This exists since Android 2.3 (API Level 9)
return (void *)eglGetProcAddress(name);
}
OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
_audio_sample_rate(audio_sample_rate),
_audio_buffer_size(audio_buffer_size),
@ -793,4 +788,11 @@ int OSystem_Android::getGraphicsMode() const {
return 0;
}
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *OSystem_Android::getOpenGLProcAddress(const char *name) const {
// This exists since Android 2.3 (API Level 9)
return (void *)eglGetProcAddress(name);
}
#endif
#endif

View file

@ -201,7 +201,10 @@ public:
bool setGraphicsMode(int mode, uint flags) override;
int getGraphicsMode() const override;
OpenGL::ContextOGLType getOpenGLType() const override { return OpenGL::kOGLContextGLES2; }
OpenGL::ContextType getOpenGLType() const override { return OpenGL::kContextGLES2; }
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *getOpenGLProcAddress(const char *name) const override;
#endif
#ifdef ANDROID_DEBUG_GL_CALLS
bool isRunningInMainThread() { return pthread_self() == _main_thread; }

View file

@ -112,7 +112,6 @@ bool iOS7_isBigDevice();
void iOS7_buildSharedOSystemInstance();
void iOS7_main(int argc, char **argv);
void *iOS7_getProcAddress(const char *name);
const char *iOS7_getDocumentsDir();
bool iOS7_touchpadModeEnabled();

View file

@ -124,6 +124,12 @@ bool OSystem_iOS7::touchpadModeEnabled() const {
return _touchpadModeEnabled;
}
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *OSystem_iOS7::getOpenGLProcAddress(const char *name) const {
return dlsym(RTLD_SELF, name);
}
#endif
int OSystem_iOS7::timerHandler(int t) {
DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager();
tm->handler();
@ -413,7 +419,3 @@ void iOS7_main(int argc, char **argv) {
fclose(newfp);
}
}
void *iOS7_getProcAddress(const char *name) {
return dlsym(RTLD_SELF, name);
}

View file

@ -143,6 +143,9 @@ public:
Graphics::PixelFormat getScreenFormat() const override { return _framebuffer.format; }
Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
#endif
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *getOpenGLProcAddress(const char *name) const override;
#endif
PaletteManager *getPaletteManager() override { return this; }

View file

@ -315,12 +315,12 @@ void OSystem_SDL::initBackend() {
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
void OSystem_SDL::detectOpenGLFeaturesSupport() {
_oglType = OpenGL::kOGLContextNone;
_oglType = OpenGL::kContextNone;
_supportsFrameBuffer = false;
_supportsShaders = false;
#if USE_FORCED_GLES2
// Framebuffers and shaders are always available with GLES2
_oglType = OpenGL::kOGLContextGLES2;
_oglType = OpenGL::kContextGLES2;
_supportsFrameBuffer = true;
_supportsShaders = true;
#else
@ -342,13 +342,13 @@ void OSystem_SDL::detectOpenGLFeaturesSupport() {
return;
}
if (glContextMajor == 2) {
_oglType = OpenGL::kOGLContextGLES2;
_oglType = OpenGL::kContextGLES2;
} else {
SDL_DestroyWindow(window);
return;
}
} else {
_oglType = OpenGL::kOGLContextGL;
_oglType = OpenGL::kContextGL;
}
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext) {
@ -358,7 +358,7 @@ void OSystem_SDL::detectOpenGLFeaturesSupport() {
OpenGLContext.initialize(_oglType);
_supportsFrameBuffer = OpenGLContext.framebufferObjectSupported;
_supportsShaders = OpenGLContext.shadersSupported;
_supportsShaders = OpenGLContext.enginesShadersSupported;
OpenGLContext.reset();
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
@ -367,7 +367,7 @@ void OSystem_SDL::detectOpenGLFeaturesSupport() {
SDL_SetVideoMode(32, 32, 0, SDL_OPENGL);
SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=center"));
// SDL 1.2 only supports OpenGL
_oglType = OpenGL::kOGLContextGL;
_oglType = OpenGL::kContextGL;
OpenGLContext.initialize(_oglType);
_supportsFrameBuffer = OpenGLContext.framebufferObjectSupported;
_supportsShaders = OpenGLContext.shadersSupported;
@ -522,6 +522,12 @@ Common::Array<uint> OSystem_SDL::getSupportedAntiAliasingLevels() const {
}
#endif
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *OSystem_SDL::getOpenGLProcAddress(const char *name) const {
return SDL_GL_GetProcAddress(name);
}
#endif
void OSystem_SDL::quit() {
destroy();
exit(0);

View file

@ -95,7 +95,10 @@ public:
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
Common::Array<uint> getSupportedAntiAliasingLevels() const override;
OpenGL::ContextOGLType getOpenGLType() const override { return _oglType; }
OpenGL::ContextType getOpenGLType() const override { return _oglType; }
#endif
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *getOpenGLProcAddress(const char *name) const override;
#endif
protected:
@ -137,7 +140,7 @@ protected:
void detectOpenGLFeaturesSupport();
void detectAntiAliasingSupport();
OpenGL::ContextOGLType _oglType;
OpenGL::ContextType _oglType;
bool _supportsFrameBuffer;
bool _supportsShaders;
Common::Array<uint> _antiAliasLevels;

View file

@ -745,10 +745,25 @@ public:
*
* @return the OpenGL type of context which is supported.
*/
virtual OpenGL::ContextOGLType getOpenGLType() const {
return OpenGL::kOGLContextNone;
virtual OpenGL::ContextType getOpenGLType() const {
return OpenGL::kContextNone;
}
#if defined(USE_OPENGL) && defined(USE_GLAD)
/**
* 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 *getOpenGLProcAddress(const char *name) const { return nullptr; }
#endif
/**
* Retrieve a list of all hardware shaders supported by this backend.
*

View file

@ -2215,7 +2215,7 @@ Bitmap *GfxOpenGLS::getScreenshot(int w, int h, bool useStored) {
Bitmap *bmp;
if (useStored) {
if (OpenGLContext.type == OpenGL::kOGLContextGLES2) {
if (OpenGLContext.type == OpenGL::kContextGLES2) {
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);

View file

@ -106,7 +106,7 @@ void OpenGlTexture::setLevelCount(uint32 count) {
// GLES2 does not allow setting the max provided mipmap level.
// It expects all the levels to be provided, which is not the case in TLJ.
// FIXME: Enable mipmapping on GLES2
if (OpenGLContext.type != OpenGL::kOGLContextGLES2) {
if (OpenGLContext.type != OpenGL::kContextGLES2) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, count - 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
@ -122,7 +122,7 @@ void OpenGlTexture::setLevelCount(uint32 count) {
void OpenGlTexture::addLevel(uint32 level, const Graphics::Surface *surface, const byte *palette) {
assert(level < _levelCount);
if (level == 0 || OpenGLContext.type != OpenGL::kOGLContextGLES2) {
if (level == 0 || OpenGLContext.type != OpenGL::kContextGLES2) {
updateLevel(level, surface, palette);
}
}

View file

@ -19,75 +19,62 @@
*
*/
#define GLAD_GL_IMPLEMENTATION
#include "graphics/opengl/context.h"
#include "common/debug.h"
#include "common/str.h"
#include "common/system.h"
#include "common/textconsole.h"
#include "common/tokenizer.h"
#include "graphics/opengl/system_headers.h"
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
#if defined(USE_OPENGL)
#ifdef USE_GLAD
#ifdef SDL_BACKEND
#include "backends/platform/sdl/sdl-sys.h"
static GLADapiproc loadFunc(void *userptr, const char *name) {
return (GLADapiproc)SDL_GL_GetProcAddress(name);
static GLADapiproc loadFunc(const char *name) {
return (GLADapiproc)g_system->getOpenGLProcAddress(name);
}
#elif defined(__ANDROID__)
// To keep includes light, don't include EGL here and don't include Android headers
void *androidGLgetProcAddress(const char *name);
static GLADapiproc loadFunc(void *userptr, const char *name) {
return (GLADapiproc)androidGLgetProcAddress(name);
}
#elif defined(IPHONE_IOS7)
#include "backends/platform/ios7/ios7_common.h"
static GLADapiproc loadFunc(void *userptr, const char *name) {
return (GLADapiproc)iOS7_getProcAddress(name);
}
#else
#error Not implemented
#endif
#endif
namespace Common {
DECLARE_SINGLETON(OpenGL::ContextGL);
DECLARE_SINGLETON(OpenGL::Context);
}
namespace OpenGL {
ContextGL::ContextGL() {
Context::Context() {
reset();
}
void ContextGL::reset() {
type = kOGLContextNone;
void Context::reset() {
type = kContextNone;
maxTextureSize = 0;
majorVersion = 0;
minorVersion = 0;
glslVersion = 0;
NPOTSupported = false;
shadersSupported = false;
enginesShadersSupported = false;
multitextureSupported = false;
framebufferObjectSupported = false;
framebufferObjectMultisampleSupported = false;
multisampleMaxSamples = -1;
packedPixelsSupported = false;
packedDepthStencilSupported = false;
unpackSubImageSupported = false;
framebufferObjectMultisampleSupported = false;
OESDepth24 = false;
multisampleMaxSamples = -1;
textureEdgeClampSupported = false;
}
void ContextGL::initialize(ContextOGLType contextType) {
void Context::initialize(ContextType contextType) {
// Initialize default state.
reset();
if (contextType == kOGLContextNone) {
if (contextType == kContextNone) {
return;
}
@ -95,12 +82,16 @@ void ContextGL::initialize(ContextOGLType contextType) {
#ifdef USE_GLAD
switch (type) {
case kOGLContextGL:
gladLoadGLUserPtr(loadFunc, this);
case kContextGL:
gladLoadGL(loadFunc);
break;
case kOGLContextGLES2:
gladLoadGLES2UserPtr(loadFunc, this);
case kContextGLES:
gladLoadGLES1(loadFunc);
break;
case kContextGLES2:
gladLoadGLES2(loadFunc);
break;
default:
@ -108,6 +99,42 @@ void ContextGL::initialize(ContextOGLType contextType) {
}
#endif
const char *verString = (const char *)glGetString(GL_VERSION);
debug(5, "OpenGL version: %s", verString);
if (type == kContextGL) {
// OpenGL version number is either of the form major.minor or major.minor.release,
// where the numbers all have one or more digits
if (sscanf(verString, "%d.%d", &majorVersion, &minorVersion) != 2) {
majorVersion = minorVersion = 0;
warning("Could not parse GL version '%s'", verString);
}
} else if (type == kContextGLES) {
// The form of the string is "OpenGL ES-<profile> <major>.<minor>",
// where <profile> is either "CM" (Common) or "CL" (Common-Lite),
// and <major> and <minor> are integers.
char profile[3];
if (sscanf(verString, "OpenGL ES-%2s %d.%d", profile,
&majorVersion, &minorVersion) != 3) {
majorVersion = minorVersion = 0;
warning("Could not parse GL ES version '%s'", verString);
}
} else if (type == kContextGLES2) {
// The version is of the form
// OpenGL<space>ES<space><version number><space><vendor-specific information>
// version number format is not defined
// There is only OpenGL ES 2.0 anyway
if (sscanf(verString, "OpenGL ES %d.%d", &majorVersion, &minorVersion) != 2) {
minorVersion = 0;
if (sscanf(verString, "OpenGL ES %d ", &majorVersion) != 1) {
majorVersion = 0;
warning("Could not parse GL ES 2 version '%s'", verString);
}
}
}
glslVersion = getGLSLVersion();
// Obtain maximum texture size.
glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&maxTextureSize);
debug(5, "OpenGL maximum texture size: %d", maxTextureSize);
@ -135,8 +162,12 @@ void ContextGL::initialize(ContextOGLType contextType) {
ARBVertexShader = true;
} else if (token == "GL_ARB_fragment_shader") {
ARBFragmentShader = true;
} else if (token == "GL_ARB_multitexture") {
multitextureSupported = true;
} else if (token == "GL_ARB_framebuffer_object") {
framebufferObjectSupported = true;
} else if (token == "GL_EXT_packed_pixels" || token == "GL_APPLE_packed_pixels") {
packedPixelsSupported = true;
} else if (token == "GL_EXT_packed_depth_stencil" || token == "GL_OES_packed_depth_stencil") {
packedDepthStencilSupported = true;
} else if (token == "GL_EXT_unpack_subimage") {
@ -147,19 +178,22 @@ void ContextGL::initialize(ContextOGLType contextType) {
EXTFramebufferBlit = true;
} else if (token == "GL_OES_depth24") {
OESDepth24 = true;
} else if (token == "GL_SGIS_texture_edge_clamp") {
textureEdgeClampSupported = true;
}
}
int glslVersion = getGLSLVersion();
debug(5, "OpenGL GLSL version: %d", glslVersion);
if (type == kOGLContextGLES2) {
if (type == kContextGLES2) {
// GLES2 always has (limited) NPOT support.
NPOTSupported = true;
// GLES2 always has shader support.
shadersSupported = true;
// GLES2 should always have GLSL ES 1.00 support but let's make sure
enginesShadersSupported = (glslVersion >= 100);
// GLES2 always has multi texture support.
multitextureSupported = true;
// GLES2 always has FBO support.
framebufferObjectSupported = true;
@ -167,8 +201,42 @@ void ContextGL::initialize(ContextOGLType contextType) {
// ScummVM does not support multisample FBOs with GLES2 for now
framebufferObjectMultisampleSupported = false;
multisampleMaxSamples = -1;
} else {
shadersSupported = ARBShaderObjects && ARBShadingLanguage100 && ARBVertexShader && ARBFragmentShader && glslVersion >= 120;
packedPixelsSupported = true;
textureEdgeClampSupported = true;
debug(5, "OpenGL: GLES2 context initialized");
} else if (type == kContextGLES) {
// GLES doesn't support shaders natively
// We don't do any aliasing in our code and expect standard OpenGL functions but GLAD does it
// So if we use GLAD we can check for ARB extensions and expect a GLSL of 1.00
#ifdef USE_GLAD
shadersSupported = ARBShaderObjects && ARBShadingLanguage100 && ARBVertexShader && ARBFragmentShader;
glslVersion = 100;
#endif
// We don't expect GLES to support shaders recent enough for engines
// ScummVM does not support multisample FBOs with GLES for now
framebufferObjectMultisampleSupported = false;
multisampleMaxSamples = -1;
packedPixelsSupported = true;
textureEdgeClampSupported = true;
debug(5, "OpenGL: GLES context initialized");
} else if (type == kContextGL) {
shadersSupported = glslVersion >= 100;
// We don't do any aliasing in our code and expect standard OpenGL functions but GLAD does it
// So if we use GLAD we can check for ARB extensions and expect a GLSL of 1.00
#ifdef USE_GLAD
if (!shadersSupported) {
shadersSupported = ARBShaderObjects && ARBShadingLanguage100 && ARBVertexShader && ARBFragmentShader;
if (shadersSupported) {
glslVersion = 100;
}
}
#endif
// In GL mode engines need GLSL 1.20
enginesShadersSupported = glslVersion >= 120;
// Desktop GL always has unpack sub-image support
unpackSubImageSupported = true;
@ -178,31 +246,50 @@ void ContextGL::initialize(ContextOGLType contextType) {
if (framebufferObjectMultisampleSupported) {
glGetIntegerv(GL_MAX_SAMPLES, (GLint *)&multisampleMaxSamples);
}
}
// Log context type.
switch (type) {
case kOGLContextNone:
/* Shouldn't happen */
break;
case kOGLContextGL:
debug(5, "OpenGL: GL context initialized");
break;
case kOGLContextGLES2:
debug(5, "OpenGL: GLES2 context initialized");
break;
// OpenGL 1.2 and later always has packed pixels and texture edge clamp support
if (isGLVersionOrHigher(1, 2)) {
packedPixelsSupported = true;
textureEdgeClampSupported = true;
}
debug(5, "OpenGL: GL context initialized");
} else {
warning("OpenGL: Unknown context initialized");
}
// Log features supported by GL context.
debug(5, "OpenGL vendor: %s", glGetString(GL_VENDOR));
debug(5, "OpenGL renderer: %s", glGetString(GL_RENDERER));
debug(5, "OpenGL: version %d.%d", majorVersion, minorVersion);
debug(5, "OpenGL: GLSL version: %d", glslVersion);
debug(5, "OpenGL: Max texture size: %d", maxTextureSize);
debug(5, "OpenGL: NPOT texture support: %d", NPOTSupported);
debug(5, "OpenGL: Shader support: %d", shadersSupported);
debug(5, "OpenGL: Multitexture support: %d", multitextureSupported);
debug(5, "OpenGL: FBO support: %d", framebufferObjectSupported);
debug(5, "OpenGL: Multisample FBO support: %d", framebufferObjectMultisampleSupported);
debug(5, "OpenGL: Multisample max number: %d", multisampleMaxSamples);
debug(5, "OpenGL: Packed pixels support: %d", packedPixelsSupported);
debug(5, "OpenGL: Packed depth stencil support: %d", packedDepthStencilSupported);
debug(5, "OpenGL: Unpack subimage support: %d", unpackSubImageSupported);
debug(5, "OpenGL: OpenGL ES depth 24 support: %d", OESDepth24);
debug(5, "OpenGL: Texture edge clamping support: %d", textureEdgeClampSupported);
}
int ContextGL::getGLSLVersion() const {
int Context::getGLSLVersion() const {
#if USE_FORCED_GLES
return 0;
#else
// No shader support in GLES
if (type == kContextGLES) {
return 0;
}
// No shader support in OpenGL 1.x
if (type == kContextGL && !isGLVersionOrHigher(2, 0)) {
return 0;
}
const char *glslVersionString = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
if (!glslVersionString) {
warning("Could not get GLSL version");
@ -210,7 +297,7 @@ int ContextGL::getGLSLVersion() const {
}
const char *glslVersionFormat;
if (type == kOGLContextGL) {
if (type == kContextGL) {
glslVersionFormat = "%d.%d";
} else {
glslVersionFormat = "OpenGL ES GLSL ES %d.%d";
@ -223,6 +310,7 @@ int ContextGL::getGLSLVersion() const {
}
return glslMajorVersion * 100 + glslMinorVersion;
#endif
}
} // End of namespace OpenGL

View file

@ -26,20 +26,19 @@
namespace OpenGL {
enum ContextOGLType {
kOGLContextNone,
kOGLContextGL,
kOGLContextGLES2
enum ContextType {
kContextNone,
kContextGL,
kContextGLES,
kContextGLES2
};
/**
* Description structure of the OpenGL (ES) context.
*
* This class is based on LordHoto's OpenGL backend for ScummVM
*/
class ContextGL : public Common::Singleton<ContextGL> {
class Context : public Common::Singleton<Context> {
public:
ContextGL();
Context();
/**
* Initialize the context description from currently active context.
@ -47,7 +46,7 @@ public:
* The extensions and features are marked as available according
* to the current context capabilities.
*/
void initialize(ContextOGLType contextType);
void initialize(ContextType contextType);
/**
* Reset context.
@ -57,7 +56,18 @@ public:
void reset();
/** The type of the active context. */
ContextOGLType type;
ContextType type;
/** Helper function for checking the GL version supported by the context. */
inline bool isGLVersionOrHigher(int major, int minor) const {
return ((majorVersion > major) || ((majorVersion == major) && (minorVersion >= minor)));
}
/** The GL version supported by the context. */
int majorVersion, minorVersion;
/** The GLSL version supported by the context */
int glslVersion;
/** The maximum texture size supported by the context. */
int maxTextureSize;
@ -68,6 +78,12 @@ public:
/** Whether shader support is available or not. */
bool shadersSupported;
/** Whether shader support is good enough for engines or not. */
bool enginesShadersSupported;
/** Whether multi texture support is available or not. */
bool multitextureSupported;
/** Whether FBO support is available or not. */
bool framebufferObjectSupported;
@ -80,6 +96,9 @@ public:
*/
int multisampleMaxSamples;
/** Whether packed pixels support is available or not. */
bool packedPixelsSupported;
/** Whether packing the depth and stencil buffers is possible or not. */
bool packedDepthStencilSupported;
@ -89,12 +108,20 @@ public:
/** Whether depth component 24 is supported or not */
bool OESDepth24;
/** Whether texture coordinate edge clamping is available or not. */
bool textureEdgeClampSupported;
private:
/**
* Returns the native GLSL version supported by the driver.
* This does NOT take shaders ARB extensions into account.
*/
int getGLSLVersion() const;
};
} // End of namespace OpenGL
/** Shortcut for accessing the active OpenGL context. */
#define OpenGLContext OpenGL::ContextGL::instance()
#define OpenGLContext OpenGL::Context::instance()
#endif

View file

@ -133,7 +133,7 @@ static GLuint createDirectShader(const char *shaderSource, GLenum shaderType, co
}
static GLuint createCompatShader(const char *shaderSource, GLenum shaderType, const Common::String &name) {
const GLchar *versionSource = OpenGLContext.type == kOGLContextGLES2 ? "#version 100\n" : "#version 120\n";
const GLchar *versionSource = OpenGLContext.type == kContextGLES2 ? "#version 100\n" : "#version 120\n";
const GLchar *compatSource =
shaderType == GL_VERTEX_SHADER ? compatVertex : compatFragment;
const GLchar *shaderSources[] = {

View file

@ -93,7 +93,7 @@ uint32 Renderer::getAvailableTypes() {
/* Backend either support OpenGL or OpenGL ES(2) */
#if defined(USE_OPENGL_GAME)
/* OpenGL classic is compiled in, check if hardware supports it */
if (g_system->getOpenGLType() == OpenGL::kOGLContextGL) {
if (g_system->getOpenGLType() == OpenGL::kContextGL) {
available |= kRendererTypeOpenGL;
}
#endif