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

View file

@ -98,8 +98,6 @@ protected:
void refreshScreen() override; void refreshScreen() override;
void *getProcAddress(const char *name) const override;
private: private:
OpenGL::Surface *_touchcontrols; OpenGL::Surface *_touchcontrols;
int _old_touch_mode; 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/debug.h"
#include "backends/graphics/opengl/opengl-sys.h"
#include "common/str.h" #include "common/str.h"
#include "common/textconsole.h" #include "common/textconsole.h"
#include "graphics/opengl/system_headers.h"
#ifdef OPENGL_DEBUG #ifdef OPENGL_DEBUG
namespace OpenGL { namespace OpenGL {

View file

@ -22,6 +22,8 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_DEBUG_H #ifndef BACKENDS_GRAPHICS_OPENGL_DEBUG_H
#define BACKENDS_GRAPHICS_OPENGL_DEBUG_H #define BACKENDS_GRAPHICS_OPENGL_DEBUG_H
#include "graphics/opengl/context.h"
#define OPENGL_DEBUG #define OPENGL_DEBUG
#ifdef 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) #define GL_WRAP_DEBUG(call, name) do { (call); } while (false)
#endif #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 #endif

View file

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

View file

@ -22,7 +22,7 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_FRAMEBUFFER_H #ifndef BACKENDS_GRAPHICS_OPENGL_FRAMEBUFFER_H
#define 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 { namespace OpenGL {

View file

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

View file

@ -22,7 +22,6 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H #ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H
#define 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/opengl/framebuffer.h"
#include "backends/graphics/windowed.h" #include "backends/graphics/windowed.h"
@ -130,28 +129,22 @@ protected:
/** /**
* Whether an GLES or GLES2 context is active. * Whether an GLES or GLES2 context is active.
*/ */
bool isGLESContext() const { return g_context.type == kContextGLES || g_context.type == kContextGLES2; } bool isGLESContext() const { return OpenGLContext.type == kContextGLES || OpenGLContext.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 * Notify the manager of a OpenGL context change. This should be the first
* thing to call after you created an OpenGL (ES) context! * 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 * @param defaultFormat The new default format for the game screen
* (this is used for the CLUT8 game screens). * (this is used for the CLUT8 game screens).
* @param defaultFormatAlpha The new default format with an alpha channel * @param defaultFormatAlpha The new default format with an alpha channel
* (this is used for the overlay and cursor). * (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. * Notify the manager that the OpenGL context is about to be destroyed.
@ -300,20 +293,6 @@ private:
*/ */
Pipeline *_pipeline; 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: protected:
/** /**
* Try to determine the internal parameters for a given pixel format. * 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/pipelines/clut8.h"
#include "backends/graphics/opengl/debug.h"
#include "backends/graphics/opengl/shader.h" #include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/framebuffer.h" #include "backends/graphics/opengl/framebuffer.h"

View file

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

View file

@ -24,6 +24,8 @@
namespace OpenGL { namespace OpenGL {
Pipeline *Pipeline::activePipeline = nullptr;
Pipeline::Pipeline() Pipeline::Pipeline()
: _activeFramebuffer(nullptr), _isActive(false) { : _activeFramebuffer(nullptr), _isActive(false) {
} }
@ -62,4 +64,18 @@ Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
return oldFramebuffer; 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 } // End of namespace OpenGL

View file

@ -22,7 +22,8 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H #ifndef BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
#define 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" #include "backends/graphics/opengl/texture.h"
namespace OpenGL { namespace OpenGL {
@ -148,6 +149,25 @@ protected:
private: private:
bool _isActive; 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 } // End of namespace OpenGL

View file

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

View file

@ -20,9 +20,9 @@
*/ */
#include "backends/graphics/opengl/shader.h" #include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/debug.h"
#if !USE_FORCED_GLES #if !USE_FORCED_GLES
#include "common/textconsole.h" #include "common/textconsole.h"
#include "common/util.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) { 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; const GLchar *compatSource = shaderType == GL_VERTEX_SHADER ? "" : g_precisionDefines;
GLshader handle; GLshader handle;

View file

@ -22,7 +22,7 @@
#ifndef BACKENDS_GRAPHICS_OPENGL_SHADER_H #ifndef BACKENDS_GRAPHICS_OPENGL_SHADER_H
#define 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 #if !USE_FORCED_GLES
@ -30,6 +30,12 @@
#include "common/hash-str.h" #include "common/hash-str.h"
#include "common/ptr.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 { namespace OpenGL {
/** /**

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -123,7 +123,6 @@ endif
# OpenGL specific source files. # OpenGL specific source files.
ifdef USE_OPENGL ifdef USE_OPENGL
MODULE_OBJS += \ MODULE_OBJS += \
graphics/opengl/context.o \
graphics/opengl/debug.o \ graphics/opengl/debug.o \
graphics/opengl/framebuffer.o \ graphics/opengl/framebuffer.o \
graphics/opengl/opengl-graphics.o \ graphics/opengl/opengl-graphics.o \

View file

@ -121,11 +121,6 @@ void checkGlError(const char *expr, const char *file, int line) {
} }
#endif #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) : OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
_audio_sample_rate(audio_sample_rate), _audio_sample_rate(audio_sample_rate),
_audio_buffer_size(audio_buffer_size), _audio_buffer_size(audio_buffer_size),
@ -793,4 +788,11 @@ int OSystem_Android::getGraphicsMode() const {
return 0; 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 #endif

View file

@ -201,7 +201,10 @@ public:
bool setGraphicsMode(int mode, uint flags) override; bool setGraphicsMode(int mode, uint flags) override;
int getGraphicsMode() const 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 #ifdef ANDROID_DEBUG_GL_CALLS
bool isRunningInMainThread() { return pthread_self() == _main_thread; } bool isRunningInMainThread() { return pthread_self() == _main_thread; }

View file

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

View file

@ -124,6 +124,12 @@ bool OSystem_iOS7::touchpadModeEnabled() const {
return _touchpadModeEnabled; 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) { int OSystem_iOS7::timerHandler(int t) {
DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager(); DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager();
tm->handler(); tm->handler();
@ -413,7 +419,3 @@ void iOS7_main(int argc, char **argv) {
fclose(newfp); 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; } Graphics::PixelFormat getScreenFormat() const override { return _framebuffer.format; }
Common::List<Graphics::PixelFormat> getSupportedFormats() const override; Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
#endif #endif
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *getOpenGLProcAddress(const char *name) const override;
#endif
PaletteManager *getPaletteManager() override { return this; } PaletteManager *getPaletteManager() override { return this; }

View file

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

View file

@ -95,7 +95,10 @@ public:
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS) #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
Common::Array<uint> getSupportedAntiAliasingLevels() const override; 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 #endif
protected: protected:
@ -137,7 +140,7 @@ protected:
void detectOpenGLFeaturesSupport(); void detectOpenGLFeaturesSupport();
void detectAntiAliasingSupport(); void detectAntiAliasingSupport();
OpenGL::ContextOGLType _oglType; OpenGL::ContextType _oglType;
bool _supportsFrameBuffer; bool _supportsFrameBuffer;
bool _supportsShaders; bool _supportsShaders;
Common::Array<uint> _antiAliasLevels; Common::Array<uint> _antiAliasLevels;

View file

@ -745,10 +745,25 @@ public:
* *
* @return the OpenGL type of context which is supported. * @return the OpenGL type of context which is supported.
*/ */
virtual OpenGL::ContextOGLType getOpenGLType() const { virtual OpenGL::ContextType getOpenGLType() const {
return OpenGL::kOGLContextNone; 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. * 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; Bitmap *bmp;
if (useStored) { if (useStored) {
if (OpenGLContext.type == OpenGL::kOGLContextGLES2) { if (OpenGLContext.type == OpenGL::kContextGLES2) {
GLuint frameBuffer; GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer); glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, 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. // 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. // It expects all the levels to be provided, which is not the case in TLJ.
// FIXME: Enable mipmapping on GLES2 // 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_MAX_LEVEL, count - 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 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) { void OpenGlTexture::addLevel(uint32 level, const Graphics::Surface *surface, const byte *palette) {
assert(level < _levelCount); assert(level < _levelCount);
if (level == 0 || OpenGLContext.type != OpenGL::kOGLContextGLES2) { if (level == 0 || OpenGLContext.type != OpenGL::kContextGLES2) {
updateLevel(level, surface, palette); updateLevel(level, surface, palette);
} }
} }

View file

@ -19,75 +19,62 @@
* *
*/ */
#define GLAD_GL_IMPLEMENTATION
#include "graphics/opengl/context.h" #include "graphics/opengl/context.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/str.h" #include "common/str.h"
#include "common/system.h"
#include "common/textconsole.h" #include "common/textconsole.h"
#include "common/tokenizer.h" #include "common/tokenizer.h"
#include "graphics/opengl/system_headers.h" #include "graphics/opengl/system_headers.h"
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS) #if defined(USE_OPENGL)
#ifdef USE_GLAD #ifdef USE_GLAD
static GLADapiproc loadFunc(const char *name) {
#ifdef SDL_BACKEND return (GLADapiproc)g_system->getOpenGLProcAddress(name);
#include "backends/platform/sdl/sdl-sys.h"
static GLADapiproc loadFunc(void *userptr, const char *name) {
return (GLADapiproc)SDL_GL_GetProcAddress(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 #endif
namespace Common { namespace Common {
DECLARE_SINGLETON(OpenGL::ContextGL); DECLARE_SINGLETON(OpenGL::Context);
} }
namespace OpenGL { namespace OpenGL {
ContextGL::ContextGL() { Context::Context() {
reset(); reset();
} }
void ContextGL::reset() { void Context::reset() {
type = kOGLContextNone; type = kContextNone;
maxTextureSize = 0; maxTextureSize = 0;
majorVersion = 0;
minorVersion = 0;
glslVersion = 0;
NPOTSupported = false; NPOTSupported = false;
shadersSupported = false; shadersSupported = false;
enginesShadersSupported = false;
multitextureSupported = false;
framebufferObjectSupported = false; framebufferObjectSupported = false;
framebufferObjectMultisampleSupported = false;
multisampleMaxSamples = -1;
packedPixelsSupported = false;
packedDepthStencilSupported = false; packedDepthStencilSupported = false;
unpackSubImageSupported = false; unpackSubImageSupported = false;
framebufferObjectMultisampleSupported = false;
OESDepth24 = false; OESDepth24 = false;
multisampleMaxSamples = -1; textureEdgeClampSupported = false;
} }
void ContextGL::initialize(ContextOGLType contextType) { void Context::initialize(ContextType contextType) {
// Initialize default state. // Initialize default state.
reset(); reset();
if (contextType == kOGLContextNone) { if (contextType == kContextNone) {
return; return;
} }
@ -95,12 +82,16 @@ void ContextGL::initialize(ContextOGLType contextType) {
#ifdef USE_GLAD #ifdef USE_GLAD
switch (type) { switch (type) {
case kOGLContextGL: case kContextGL:
gladLoadGLUserPtr(loadFunc, this); gladLoadGL(loadFunc);
break; break;
case kOGLContextGLES2: case kContextGLES:
gladLoadGLES2UserPtr(loadFunc, this); gladLoadGLES1(loadFunc);
break;
case kContextGLES2:
gladLoadGLES2(loadFunc);
break; break;
default: default:
@ -108,6 +99,42 @@ void ContextGL::initialize(ContextOGLType contextType) {
} }
#endif #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. // Obtain maximum texture size.
glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&maxTextureSize); glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&maxTextureSize);
debug(5, "OpenGL maximum texture size: %d", maxTextureSize); debug(5, "OpenGL maximum texture size: %d", maxTextureSize);
@ -135,8 +162,12 @@ void ContextGL::initialize(ContextOGLType contextType) {
ARBVertexShader = true; ARBVertexShader = true;
} else if (token == "GL_ARB_fragment_shader") { } else if (token == "GL_ARB_fragment_shader") {
ARBFragmentShader = true; ARBFragmentShader = true;
} else if (token == "GL_ARB_multitexture") {
multitextureSupported = true;
} else if (token == "GL_ARB_framebuffer_object") { } else if (token == "GL_ARB_framebuffer_object") {
framebufferObjectSupported = true; 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") { } else if (token == "GL_EXT_packed_depth_stencil" || token == "GL_OES_packed_depth_stencil") {
packedDepthStencilSupported = true; packedDepthStencilSupported = true;
} else if (token == "GL_EXT_unpack_subimage") { } else if (token == "GL_EXT_unpack_subimage") {
@ -147,19 +178,22 @@ void ContextGL::initialize(ContextOGLType contextType) {
EXTFramebufferBlit = true; EXTFramebufferBlit = true;
} else if (token == "GL_OES_depth24") { } else if (token == "GL_OES_depth24") {
OESDepth24 = true; OESDepth24 = true;
} else if (token == "GL_SGIS_texture_edge_clamp") {
textureEdgeClampSupported = true;
} }
} }
int glslVersion = getGLSLVersion(); if (type == kContextGLES2) {
debug(5, "OpenGL GLSL version: %d", glslVersion);
if (type == kOGLContextGLES2) {
// GLES2 always has (limited) NPOT support. // GLES2 always has (limited) NPOT support.
NPOTSupported = true; NPOTSupported = true;
// GLES2 always has shader support. // GLES2 always has shader support.
shadersSupported = true; 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. // GLES2 always has FBO support.
framebufferObjectSupported = true; framebufferObjectSupported = true;
@ -167,8 +201,42 @@ void ContextGL::initialize(ContextOGLType contextType) {
// ScummVM does not support multisample FBOs with GLES2 for now // ScummVM does not support multisample FBOs with GLES2 for now
framebufferObjectMultisampleSupported = false; framebufferObjectMultisampleSupported = false;
multisampleMaxSamples = -1; 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 // Desktop GL always has unpack sub-image support
unpackSubImageSupported = true; unpackSubImageSupported = true;
@ -178,31 +246,50 @@ void ContextGL::initialize(ContextOGLType contextType) {
if (framebufferObjectMultisampleSupported) { if (framebufferObjectMultisampleSupported) {
glGetIntegerv(GL_MAX_SAMPLES, (GLint *)&multisampleMaxSamples); glGetIntegerv(GL_MAX_SAMPLES, (GLint *)&multisampleMaxSamples);
} }
}
// Log context type. // OpenGL 1.2 and later always has packed pixels and texture edge clamp support
switch (type) { if (isGLVersionOrHigher(1, 2)) {
case kOGLContextNone: packedPixelsSupported = true;
/* Shouldn't happen */ textureEdgeClampSupported = true;
break; }
case kOGLContextGL: debug(5, "OpenGL: GL context initialized");
debug(5, "OpenGL: GL context initialized"); } else {
break; warning("OpenGL: Unknown context initialized");
case kOGLContextGLES2:
debug(5, "OpenGL: GLES2 context initialized");
break;
} }
// Log features supported by GL context. // 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: NPOT texture support: %d", NPOTSupported);
debug(5, "OpenGL: Shader support: %d", shadersSupported); debug(5, "OpenGL: Shader support: %d", shadersSupported);
debug(5, "OpenGL: Multitexture support: %d", multitextureSupported);
debug(5, "OpenGL: FBO support: %d", framebufferObjectSupported); 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: Packed depth stencil support: %d", packedDepthStencilSupported);
debug(5, "OpenGL: Unpack subimage support: %d", unpackSubImageSupported); 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); const char *glslVersionString = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
if (!glslVersionString) { if (!glslVersionString) {
warning("Could not get GLSL version"); warning("Could not get GLSL version");
@ -210,7 +297,7 @@ int ContextGL::getGLSLVersion() const {
} }
const char *glslVersionFormat; const char *glslVersionFormat;
if (type == kOGLContextGL) { if (type == kContextGL) {
glslVersionFormat = "%d.%d"; glslVersionFormat = "%d.%d";
} else { } else {
glslVersionFormat = "OpenGL ES GLSL ES %d.%d"; glslVersionFormat = "OpenGL ES GLSL ES %d.%d";
@ -223,6 +310,7 @@ int ContextGL::getGLSLVersion() const {
} }
return glslMajorVersion * 100 + glslMinorVersion; return glslMajorVersion * 100 + glslMinorVersion;
#endif
} }
} // End of namespace OpenGL } // End of namespace OpenGL

View file

@ -26,20 +26,19 @@
namespace OpenGL { namespace OpenGL {
enum ContextOGLType { enum ContextType {
kOGLContextNone, kContextNone,
kOGLContextGL, kContextGL,
kOGLContextGLES2 kContextGLES,
kContextGLES2
}; };
/** /**
* Description structure of the OpenGL (ES) context. * 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: public:
ContextGL(); Context();
/** /**
* Initialize the context description from currently active context. * Initialize the context description from currently active context.
@ -47,7 +46,7 @@ public:
* The extensions and features are marked as available according * The extensions and features are marked as available according
* to the current context capabilities. * to the current context capabilities.
*/ */
void initialize(ContextOGLType contextType); void initialize(ContextType contextType);
/** /**
* Reset context. * Reset context.
@ -57,7 +56,18 @@ public:
void reset(); void reset();
/** The type of the active context. */ /** 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. */ /** The maximum texture size supported by the context. */
int maxTextureSize; int maxTextureSize;
@ -68,6 +78,12 @@ public:
/** Whether shader support is available or not. */ /** Whether shader support is available or not. */
bool shadersSupported; 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. */ /** Whether FBO support is available or not. */
bool framebufferObjectSupported; bool framebufferObjectSupported;
@ -80,6 +96,9 @@ public:
*/ */
int multisampleMaxSamples; int multisampleMaxSamples;
/** Whether packed pixels support is available or not. */
bool packedPixelsSupported;
/** Whether packing the depth and stencil buffers is possible or not. */ /** Whether packing the depth and stencil buffers is possible or not. */
bool packedDepthStencilSupported; bool packedDepthStencilSupported;
@ -89,12 +108,20 @@ public:
/** Whether depth component 24 is supported or not */ /** Whether depth component 24 is supported or not */
bool OESDepth24; 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; int getGLSLVersion() const;
}; };
} // End of namespace OpenGL } // End of namespace OpenGL
/** Shortcut for accessing the active OpenGL context. */ /** Shortcut for accessing the active OpenGL context. */
#define OpenGLContext OpenGL::ContextGL::instance() #define OpenGLContext OpenGL::Context::instance()
#endif #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) { 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 = const GLchar *compatSource =
shaderType == GL_VERTEX_SHADER ? compatVertex : compatFragment; shaderType == GL_VERTEX_SHADER ? compatVertex : compatFragment;
const GLchar *shaderSources[] = { const GLchar *shaderSources[] = {

View file

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