mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
BACKENDS: OPENGL: Add 3D rendering support
This commit is contained in:
@@ -66,6 +66,10 @@
|
||||
#include "backends/graphics/opengl/pipelines/libretro/parser.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
#include "backends/graphics/opengl/renderer3d.h"
|
||||
#endif
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
OpenGLGraphicsManager::OpenGLGraphicsManager()
|
||||
@@ -80,6 +84,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
|
||||
#if !USE_FORCED_GLES
|
||||
, _libretroPipeline(nullptr)
|
||||
#endif
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
, _renderer3d(nullptr)
|
||||
#endif
|
||||
#ifdef USE_OSD
|
||||
, _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),
|
||||
_osdIconSurface(nullptr)
|
||||
@@ -94,6 +101,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
|
||||
|
||||
OpenGLGraphicsManager::~OpenGLGraphicsManager() {
|
||||
delete _gameScreen;
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
delete _renderer3d;
|
||||
#endif
|
||||
delete _overlay;
|
||||
delete _cursor;
|
||||
delete _cursorMask;
|
||||
@@ -121,6 +131,15 @@ bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const {
|
||||
case OSystem::kFeatureScalers:
|
||||
#endif
|
||||
return true;
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
case OSystem::kFeatureOpenGLForGame:
|
||||
// No 3D for GLES
|
||||
return OpenGLContext.type != kContextGLES;
|
||||
#endif
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
case OSystem::kFeatureShadersForGame:
|
||||
return OpenGLContext.enginesShadersSupported;
|
||||
#endif
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
case OSystem::kFeatureShaders:
|
||||
@@ -193,9 +212,17 @@ int OpenGLGraphicsManager::getDefaultGraphicsMode() const {
|
||||
bool OpenGLGraphicsManager::setGraphicsMode(int mode, uint flags) {
|
||||
assert(_transactionMode != kTransactionNone);
|
||||
|
||||
if (flags & OSystem::kGfxModeRender3d) {
|
||||
// In 3D, mode is not used
|
||||
_currentState.graphicsMode = GFX_OPENGL;
|
||||
_currentState.flags = flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case GFX_OPENGL:
|
||||
_currentState.graphicsMode = mode;
|
||||
_currentState.flags = flags;
|
||||
return true;
|
||||
|
||||
default:
|
||||
@@ -390,7 +417,8 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
|
||||
|
||||
bool setupNewGameScreen = false;
|
||||
if ( _oldState.gameWidth != _currentState.gameWidth
|
||||
|| _oldState.gameHeight != _currentState.gameHeight) {
|
||||
|| _oldState.gameHeight != _currentState.gameHeight
|
||||
|| _oldState.flags != _currentState.flags) {
|
||||
setupNewGameScreen = true;
|
||||
}
|
||||
|
||||
@@ -415,6 +443,36 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
|
||||
}
|
||||
#endif
|
||||
|
||||
const bool render3d = _currentState.flags & OSystem::kGfxModeRender3d;
|
||||
assert(!render3d || OpenGLContext.type != kContextGLES);
|
||||
const int antialiasing = render3d ? ConfMan.getInt("antialiasing") : 0;
|
||||
|
||||
// 2D engines always render on a texture that can be stretched
|
||||
const bool engineSupportsArbitraryResolutions = !g_engine || !render3d || g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
|
||||
// Prefer to render on framebuffer if antialiasing is requested: this avoids recreating the window
|
||||
// This is only needed for 3D rendering
|
||||
const bool renderToFrameBuffer = render3d && (!engineSupportsArbitraryResolutions
|
||||
#if !USE_FORCED_GLES
|
||||
|| _libretroPipeline
|
||||
#endif
|
||||
|| (antialiasing && OpenGLContext.framebufferObjectMultisampleSupported)) &&
|
||||
OpenGLContext.framebufferObjectSupported;
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
// Create the 3D renderer first to allow the platform specific code know we are in 3D
|
||||
// The creation doesn't depend on any context existing
|
||||
if (render3d && !_renderer3d) {
|
||||
_renderer3d = new Renderer3D();
|
||||
} else if (!render3d) {
|
||||
delete _renderer3d;
|
||||
_renderer3d = nullptr;
|
||||
}
|
||||
#else
|
||||
if (render3d) {
|
||||
error("3D rendering is not available");
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
const uint desiredAspect = getDesiredGameAspectRatio();
|
||||
const uint requestedWidth = _currentState.gameWidth;
|
||||
@@ -430,7 +488,8 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
|
||||
#else
|
||||
Graphics::PixelFormat::createFormatCLUT8(),
|
||||
#endif
|
||||
true, 0)
|
||||
renderToFrameBuffer || engineSupportsArbitraryResolutions,
|
||||
renderToFrameBuffer ? 0 : antialiasing)
|
||||
|| !(shaderOK = loadShader(_currentState.shader))
|
||||
// HACK: This is really nasty but we don't have any guarantees of
|
||||
// a context existing before, which means we don't know the maximum
|
||||
@@ -507,35 +566,42 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
|
||||
delete _gameScreen;
|
||||
_gameScreen = nullptr;
|
||||
|
||||
bool wantScaler = _currentState.scaleFactor > 1;
|
||||
if (render3d) {
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
_renderer3d->initSize(_currentState.gameWidth, _currentState.gameHeight, antialiasing, renderToFrameBuffer);
|
||||
_renderer3d->enter3D();
|
||||
#endif
|
||||
} else {
|
||||
const bool wantScaler = _currentState.scaleFactor > 1;
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
_gameScreen = createSurface(_currentState.gameFormat, false, wantScaler);
|
||||
_gameScreen = createSurface(_currentState.gameFormat, false, wantScaler);
|
||||
#else
|
||||
_gameScreen = createSurface(Graphics::PixelFormat::createFormatCLUT8(), false, wantScaler);
|
||||
_gameScreen = createSurface(Graphics::PixelFormat::createFormatCLUT8(), false, wantScaler);
|
||||
#endif
|
||||
assert(_gameScreen);
|
||||
if (_gameScreen->hasPalette()) {
|
||||
_gameScreen->setPalette(0, 256, _gamePalette);
|
||||
}
|
||||
assert(_gameScreen);
|
||||
if (_gameScreen->hasPalette()) {
|
||||
_gameScreen->setPalette(0, 256, _gamePalette);
|
||||
}
|
||||
|
||||
#ifdef USE_SCALERS
|
||||
if (wantScaler) {
|
||||
_gameScreen->setScaler(_currentState.scalerIndex, _currentState.scaleFactor);
|
||||
}
|
||||
if (wantScaler) {
|
||||
_gameScreen->setScaler(_currentState.scalerIndex, _currentState.scaleFactor);
|
||||
}
|
||||
#endif
|
||||
|
||||
_gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight);
|
||||
// We fill the screen to all black or index 0 for CLUT8.
|
||||
_gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight);
|
||||
// We fill the screen to all black or index 0 for CLUT8.
|
||||
#ifdef USE_RGB_COLOR
|
||||
if (_currentState.gameFormat.bytesPerPixel == 1) {
|
||||
_gameScreen->fill(0);
|
||||
} else {
|
||||
_gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0));
|
||||
}
|
||||
if (_currentState.gameFormat.bytesPerPixel == 1) {
|
||||
_gameScreen->fill(0);
|
||||
} else {
|
||||
_gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0));
|
||||
}
|
||||
#else
|
||||
_gameScreen->fill(0);
|
||||
_gameScreen->fill(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Update our display area and cursor scaling. This makes sure we pick up
|
||||
@@ -582,14 +648,17 @@ int16 OpenGLGraphicsManager::getHeight() const {
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
|
||||
assert(_gameScreen);
|
||||
_gameScreen->copyRectToTexture(x, y, w, h, buf, pitch);
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::fillScreen(uint32 col) {
|
||||
assert(_gameScreen);
|
||||
_gameScreen->fill(col);
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::fillScreen(const Common::Rect &r, uint32 col) {
|
||||
assert(_gameScreen);
|
||||
_gameScreen->fill(r, col);
|
||||
}
|
||||
|
||||
@@ -638,7 +707,11 @@ void OpenGLGraphicsManager::updateScreen() {
|
||||
rotatedHeight = _windowWidth;
|
||||
}
|
||||
|
||||
if (!_gameScreen || !_pipeline) {
|
||||
if ((!_gameScreen
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
&& !_renderer3d
|
||||
#endif
|
||||
) || !_pipeline) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -659,8 +732,11 @@ void OpenGLGraphicsManager::updateScreen() {
|
||||
|
||||
// We only update the screen when there actually have been any changes.
|
||||
if ( !_forceRedraw
|
||||
&& !_cursorNeedsRedraw
|
||||
&& !_gameScreen->isDirty()
|
||||
&& !_cursorNeedsRedraw
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
&& !_renderer3d
|
||||
#endif
|
||||
&& !_gameScreen->isDirty() // if _renderer3d is nullptr, _gameScreen is not null
|
||||
#if !USE_FORCED_GLES
|
||||
&& !(_libretroPipeline && _libretroPipeline->isAnimated())
|
||||
#endif
|
||||
@@ -673,8 +749,17 @@ void OpenGLGraphicsManager::updateScreen() {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (_renderer3d) {
|
||||
_renderer3d->leave3D();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update changes to textures.
|
||||
_gameScreen->updateGLTexture();
|
||||
if (_gameScreen) {
|
||||
_gameScreen->updateGLTexture();
|
||||
}
|
||||
|
||||
if (_cursorVisible && _cursor) {
|
||||
_cursor->updateGLTexture();
|
||||
}
|
||||
@@ -691,8 +776,13 @@ void OpenGLGraphicsManager::updateScreen() {
|
||||
|
||||
_pipeline->activate();
|
||||
|
||||
// Clear the screen buffer.
|
||||
GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
|
||||
// Clear the screen buffer (when the engine has not drawn on it directly).
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (!_renderer3d || _renderer3d->hasTexture())
|
||||
#endif
|
||||
{
|
||||
GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
|
||||
}
|
||||
|
||||
if (!_overlayVisible) {
|
||||
// The scissor test is enabled to:
|
||||
@@ -708,7 +798,14 @@ void OpenGLGraphicsManager::updateScreen() {
|
||||
_targetBuffer->enableBlend(Framebuffer::kBlendModeOpaque);
|
||||
|
||||
// First step: Draw the (virtual) game screen.
|
||||
_pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
|
||||
if (_gameScreen) {
|
||||
_pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
|
||||
}
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
else if (_renderer3d && _renderer3d->hasTexture()) {
|
||||
_pipeline->drawTexture(_renderer3d->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Second step: Draw the cursor if necessary and we are not in GUI and it
|
||||
#if !USE_FORCED_GLES
|
||||
@@ -800,13 +897,21 @@ void OpenGLGraphicsManager::updateScreen() {
|
||||
_cursorNeedsRedraw = false;
|
||||
_forceRedraw = false;
|
||||
refreshScreen();
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (_renderer3d) {
|
||||
_renderer3d->enter3D();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Graphics::Surface *OpenGLGraphicsManager::lockScreen() {
|
||||
assert(_gameScreen);
|
||||
return _gameScreen->getSurface();
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::unlockScreen() {
|
||||
assert(_gameScreen);
|
||||
_gameScreen->flagDirty();
|
||||
}
|
||||
|
||||
@@ -832,6 +937,24 @@ int16 OpenGLGraphicsManager::getOverlayHeight() const {
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::showOverlay(bool inGUI) {
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (!_overlayVisible && _renderer3d) {
|
||||
_renderer3d->showOverlay(getOverlayWidth(), getOverlayHeight());
|
||||
}
|
||||
#endif
|
||||
WindowedGraphicsManager::showOverlay(inGUI);
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::hideOverlay() {
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (_overlayVisible && _renderer3d) {
|
||||
_renderer3d->hideOverlay();
|
||||
}
|
||||
#endif
|
||||
WindowedGraphicsManager::hideOverlay();
|
||||
}
|
||||
|
||||
Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
|
||||
return _overlay->getFormat();
|
||||
}
|
||||
@@ -1251,6 +1374,7 @@ void OpenGLGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface *ic
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
|
||||
assert(_gameScreen);
|
||||
assert(_gameScreen->hasPalette());
|
||||
|
||||
memcpy(_gamePalette + start * 3, colors, num * 3);
|
||||
@@ -1261,6 +1385,7 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) const {
|
||||
assert(_gameScreen);
|
||||
assert(_gameScreen->hasPalette());
|
||||
|
||||
memcpy(colors, _gamePalette + start * 3, num * 3);
|
||||
@@ -1403,6 +1528,12 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
|
||||
_gameScreen->recreate();
|
||||
}
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (_renderer3d) {
|
||||
_renderer3d->recreate();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_overlay) {
|
||||
_overlay->recreate();
|
||||
}
|
||||
@@ -1431,6 +1562,12 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
|
||||
_gameScreen->destroy();
|
||||
}
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (_renderer3d) {
|
||||
_renderer3d->destroy();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_overlay) {
|
||||
_overlay->destroy();
|
||||
}
|
||||
@@ -1632,15 +1769,32 @@ int OpenGLGraphicsManager::getGameRenderScale() const {
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::recalculateDisplayAreas() {
|
||||
if (!_gameScreen) {
|
||||
if (!_gameScreen
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
&& !_renderer3d
|
||||
#endif
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
const bool engineSupportsArbitraryResolutions = !g_engine || g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
|
||||
if (_renderer3d && engineSupportsArbitraryResolutions) {
|
||||
_currentState.gameWidth = getOverlayWidth();
|
||||
_currentState.gameHeight = getOverlayHeight();
|
||||
_renderer3d->resize(_currentState.gameWidth, _currentState.gameHeight);
|
||||
}
|
||||
#endif
|
||||
|
||||
WindowedGraphicsManager::recalculateDisplayAreas();
|
||||
|
||||
#if !USE_FORCED_GLES
|
||||
if (_libretroPipeline) {
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
const Texture &gameScreenTexture = _gameScreen ? _gameScreen->getGLTexture() : _renderer3d->getGLTexture();
|
||||
#else
|
||||
const Texture &gameScreenTexture = _gameScreen->getGLTexture();
|
||||
#endif
|
||||
_libretroPipeline->setDisplaySizes(gameScreenTexture.getLogicalWidth(), gameScreenTexture.getLogicalHeight(),
|
||||
_gameDrawRect);
|
||||
}
|
||||
@@ -1691,7 +1845,11 @@ void OpenGLGraphicsManager::updateCursorPalette() {
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::recalculateCursorScaling() {
|
||||
if (!_cursor || !_gameScreen) {
|
||||
if (!_cursor || (!_gameScreen
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
&& !_renderer3d
|
||||
#endif
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1706,7 +1864,8 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
|
||||
|
||||
// In case scaling is actually enabled we will scale the cursor according
|
||||
// to the game screen.
|
||||
if (!_cursorDontScale) {
|
||||
// In 3D mode, there is no scaling
|
||||
if (!_cursorDontScale && _gameScreen) {
|
||||
const frac_t screenScaleFactorX = intToFrac(_gameDrawRect.width()) / _gameScreen->getWidth();
|
||||
const frac_t screenScaleFactorY = intToFrac(_gameDrawRect.height()) / _gameScreen->getHeight();
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ class Pipeline;
|
||||
#if !USE_FORCED_GLES
|
||||
class LibRetroPipeline;
|
||||
#endif
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
class Renderer3D;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
GFX_OPENGL = 0
|
||||
@@ -115,6 +118,8 @@ public:
|
||||
|
||||
int16 getOverlayWidth() const override;
|
||||
int16 getOverlayHeight() const override;
|
||||
void showOverlay(bool inGUI) override;
|
||||
void hideOverlay() override;
|
||||
|
||||
Graphics::PixelFormat getOverlayFormat() const override;
|
||||
|
||||
@@ -196,6 +201,7 @@ protected:
|
||||
#endif
|
||||
bool aspectRatioCorrection;
|
||||
int graphicsMode;
|
||||
uint flags;
|
||||
bool filtering;
|
||||
|
||||
uint scalerIndex;
|
||||
@@ -354,6 +360,13 @@ protected:
|
||||
*/
|
||||
Surface *_gameScreen;
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
/**
|
||||
* The rendering helper for 3D games.
|
||||
*/
|
||||
Renderer3D *_renderer3d;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The game palette if in CLUT8 mode.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
|
||||
#include "backends/graphics/opengl/renderer3d.h"
|
||||
#include "backends/graphics/opengl/pipelines/pipeline.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
static void setupRenderbufferStorage(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
|
||||
#if !USE_FORCED_GLES2 || defined(USE_GLAD)
|
||||
if (samples > 1) {
|
||||
glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
glRenderbufferStorage(target, internalformat, width, height);
|
||||
}
|
||||
|
||||
// This constructor must not depend on any existing GL context
|
||||
Renderer3D::Renderer3D() :
|
||||
_texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, false),
|
||||
_renderBuffers{0, 0, 0}, _frameBuffers{0, 0}, _renderToFrameBuffer(false),
|
||||
_samples(0), _stackLevel(0), _inOverlay(false),
|
||||
_pendingScreenChangeWidth(-1), _pendingScreenChangeHeight(-1) {
|
||||
_texture.enableLinearFiltering(true);
|
||||
}
|
||||
|
||||
void Renderer3D::destroy() {
|
||||
while (_stackLevel) {
|
||||
enter3D();
|
||||
}
|
||||
|
||||
if (_frameBuffers[0]) {
|
||||
// Check that we did allocated some framebuffer before destroying them
|
||||
// This avoids to call glDeleteFramebuffers and glDeleteRenderbuffers
|
||||
// on platforms not supporting it
|
||||
glDeleteFramebuffers(ARRAYSIZE(_frameBuffers), _frameBuffers);
|
||||
glDeleteRenderbuffers(ARRAYSIZE(_renderBuffers), _renderBuffers);
|
||||
memset(_renderBuffers, 0, sizeof(_renderBuffers));
|
||||
memset(_frameBuffers, 0, sizeof(_frameBuffers));
|
||||
}
|
||||
|
||||
_texture.destroy();
|
||||
}
|
||||
|
||||
void Renderer3D::initSize(uint w, uint h, int samples, bool renderToFrameBuffer) {
|
||||
_samples = samples;
|
||||
_renderToFrameBuffer = renderToFrameBuffer;
|
||||
|
||||
if (!renderToFrameBuffer) {
|
||||
destroy();
|
||||
_texture.setSize(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
_texture.setSize(w, h, true);
|
||||
recreate();
|
||||
}
|
||||
|
||||
void Renderer3D::resize(uint w, uint h) {
|
||||
assert(!_stackLevel);
|
||||
|
||||
if (!_renderToFrameBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_inOverlay) {
|
||||
// While the (GUI) overlay is active, the game doesn't renders
|
||||
// So, instead of loosing the contents of the FBO because of a resize,
|
||||
// just delay it to when we close the GUI.
|
||||
_pendingScreenChangeWidth = w;
|
||||
_pendingScreenChangeHeight = h;
|
||||
return;
|
||||
}
|
||||
|
||||
_texture.setSize(w, h, true);
|
||||
setup();
|
||||
|
||||
// Rebind the framebuffer
|
||||
if (_frameBuffers[1]) {
|
||||
// We are using multisampling
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, _frameBuffers[1]);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _frameBuffers[0]);
|
||||
} else if (_frameBuffers[0]) {
|
||||
// Draw on framebuffer if one was setup
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer3D::recreate() {
|
||||
destroy();
|
||||
|
||||
if (!_renderToFrameBuffer) {
|
||||
// No framebuffer was requested
|
||||
return;
|
||||
}
|
||||
|
||||
// A 1x antialiasing is not an antialiasing
|
||||
if (_samples > 1) {
|
||||
#if !USE_FORCED_GLES2 || defined(USE_GLAD)
|
||||
if (!OpenGLContext.framebufferObjectMultisampleSupported) {
|
||||
warning("The current OpenGL context does not support multisample framebuffer objects");
|
||||
_samples = 0;
|
||||
}
|
||||
if (_samples > OpenGLContext.multisampleMaxSamples) {
|
||||
warning("Requested anti-aliasing with '%d' samples, but the current OpenGL context supports '%d' samples at most",
|
||||
_samples, OpenGLContext.multisampleMaxSamples);
|
||||
_samples = OpenGLContext.multisampleMaxSamples;
|
||||
}
|
||||
#else
|
||||
warning("multisample framebuffer objects support is not compiled in");
|
||||
_samples = 0;
|
||||
#endif
|
||||
} else {
|
||||
_samples = 0;
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
// Context got destroyed
|
||||
_stackLevel = 0;
|
||||
}
|
||||
|
||||
void Renderer3D::setup() {
|
||||
const bool multiSample = _samples > 1;
|
||||
const uint w = _texture.getLogicalWidth();
|
||||
const uint h = _texture.getLogicalHeight();
|
||||
|
||||
if (!_texture.getGLTexture()) {
|
||||
_texture.create();
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if (!_frameBuffers[0]) {
|
||||
glGenFramebuffers(multiSample ? 2 : 1, _frameBuffers);
|
||||
glGenRenderbuffers(multiSample ? 3 : 2, _renderBuffers);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[multiSample ? 1 : 0]);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture.getGLTexture(), 0);
|
||||
|
||||
if (multiSample) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[0]);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[2]);
|
||||
setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_RGBA8, w, h);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffers[2]);
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
// See https://www.khronos.org/registry/webgl/specs/latest/1.0/#FBO_ATTACHMENTS
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
|
||||
setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_DEPTH_STENCIL, w, h);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
|
||||
#else
|
||||
if (OpenGLContext.packedDepthStencilSupported) {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
|
||||
setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_DEPTH24_STENCIL8, w, h);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
|
||||
} else {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
|
||||
setupRenderbufferStorage(GL_RENDERBUFFER, _samples, OpenGLContext.OESDepth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, w, h);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[1]);
|
||||
setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_STENCIL_INDEX8, w, h);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[1]);
|
||||
}
|
||||
#endif
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
error("Framebuffer is not complete! status: %d", status);
|
||||
}
|
||||
|
||||
if (multiSample) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[1]);
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
error("Target framebuffer is not complete! status: %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void Renderer3D::leave3D() {
|
||||
if (OpenGLContext.type == kContextGL) {
|
||||
// Save current state (only available on OpenGL)
|
||||
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT |
|
||||
GL_LIGHTING_BIT | GL_PIXEL_MODE_BIT | GL_SCISSOR_BIT |
|
||||
GL_TEXTURE_BIT | GL_TRANSFORM_BIT | GL_VIEWPORT_BIT);
|
||||
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT | GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
|
||||
// prepare view
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glPushMatrix();
|
||||
} else {
|
||||
// Save context by ourselves
|
||||
#define CTX_STATE(gl_param) _save ## gl_param = glIsEnabled(gl_param)
|
||||
#define CTX_BOOLEAN(gl_param) glGetBooleanv(gl_param, &_save ## gl_param)
|
||||
#define CTX_INTEGER(gl_param, count) glGetIntegerv(gl_param, _save ## gl_param)
|
||||
|
||||
CTX_STATE(GL_BLEND);
|
||||
CTX_STATE(GL_CULL_FACE);
|
||||
CTX_STATE(GL_DEPTH_TEST);
|
||||
CTX_STATE(GL_DITHER);
|
||||
CTX_STATE(GL_POLYGON_OFFSET_FILL);
|
||||
CTX_STATE(GL_SCISSOR_TEST);
|
||||
CTX_STATE(GL_STENCIL_TEST);
|
||||
|
||||
CTX_BOOLEAN(GL_DEPTH_WRITEMASK);
|
||||
|
||||
CTX_INTEGER(GL_BLEND_SRC_RGB, 1);
|
||||
CTX_INTEGER(GL_BLEND_DST_RGB, 1);
|
||||
CTX_INTEGER(GL_BLEND_SRC_ALPHA, 1);
|
||||
CTX_INTEGER(GL_BLEND_DST_ALPHA, 1);
|
||||
|
||||
CTX_INTEGER(GL_SCISSOR_BOX, 4);
|
||||
CTX_INTEGER(GL_VIEWPORT, 4);
|
||||
|
||||
#undef CTX_INTEGER
|
||||
#undef CTX_BOOLEAN
|
||||
#undef CTX_STATE
|
||||
}
|
||||
_stackLevel++;
|
||||
|
||||
if (_frameBuffers[1]) {
|
||||
// Frambuffer blit is impacted by scissor test, disable it
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
// We are using multisampling
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, _frameBuffers[0]);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _frameBuffers[1]);
|
||||
const uint w = _texture.getLogicalWidth();
|
||||
const uint h = _texture.getLogicalHeight();
|
||||
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
} else if (_frameBuffers[0]) {
|
||||
// Don't mess with the framebuffer if one was setup
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer3D::enter3D() {
|
||||
if (_frameBuffers[1]) {
|
||||
// We are using multisampling
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, _frameBuffers[1]);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _frameBuffers[0]);
|
||||
} else if (_frameBuffers[0]) {
|
||||
// Draw on framebuffer if one was setup
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[0]);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
Pipeline::disable();
|
||||
|
||||
if (_stackLevel) {
|
||||
if (OpenGLContext.type == kContextGL) {
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopClientAttrib();
|
||||
glPopAttrib();
|
||||
} else {
|
||||
#define CTX_STATE(gl_param) _save ## gl_param ? glEnable(gl_param) : glDisable(gl_param)
|
||||
|
||||
CTX_STATE(GL_BLEND);
|
||||
CTX_STATE(GL_CULL_FACE);
|
||||
CTX_STATE(GL_DEPTH_TEST);
|
||||
CTX_STATE(GL_DITHER);
|
||||
CTX_STATE(GL_POLYGON_OFFSET_FILL);
|
||||
CTX_STATE(GL_SCISSOR_TEST);
|
||||
CTX_STATE(GL_STENCIL_TEST);
|
||||
|
||||
glDepthMask(_saveGL_DEPTH_WRITEMASK);
|
||||
|
||||
glBlendFuncSeparate(_saveGL_BLEND_SRC_RGB[0], _saveGL_BLEND_DST_RGB[0],
|
||||
_saveGL_BLEND_SRC_ALPHA[0], _saveGL_BLEND_DST_ALPHA[0]);
|
||||
|
||||
glScissor(_saveGL_SCISSOR_BOX[0], _saveGL_SCISSOR_BOX[1],
|
||||
_saveGL_SCISSOR_BOX[2], _saveGL_SCISSOR_BOX[3]);
|
||||
|
||||
glViewport(_saveGL_VIEWPORT[0], _saveGL_VIEWPORT[1],
|
||||
_saveGL_VIEWPORT[2], _saveGL_VIEWPORT[3]);
|
||||
#undef CTX_STATE
|
||||
}
|
||||
_stackLevel--;
|
||||
} else {
|
||||
// 3D engine just starts, make sure the state is clean
|
||||
glDisable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
glEnable(GL_DITHER);
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(0.f, 0.f);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glScissor(0, 0, g_system->getWidth(), g_system->getHeight());
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_ALWAYS, 0, -1u);
|
||||
glStencilMask(-1u);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glLineWidth(1.f);
|
||||
|
||||
glViewport(0, 0, g_system->getWidth(), g_system->getHeight());
|
||||
|
||||
if (OpenGLContext.type == kContextGL) {
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_ALWAYS, 0);
|
||||
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
glDisable(GL_FOG);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glDisable(GL_NORMALIZE);
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable(GL_TEXTURE_1D);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
glDisable(GL_TEXTURE_GEN_Q);
|
||||
glDisable(GL_TEXTURE_GEN_R);
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_EDGE_FLAG_ARRAY);
|
||||
glDisableClientState(GL_FOG_COORD_ARRAY);
|
||||
glDisableClientState(GL_INDEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
// The others targets are not modified by engines
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
|
||||
glLogicOp(GL_COPY);
|
||||
glPointSize(1.f);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer3D::showOverlay(uint w, uint h) {
|
||||
_inOverlay = true;
|
||||
|
||||
if (_frameBuffers[0]) {
|
||||
// We have a framebuffer: the texture already contains an image
|
||||
return;
|
||||
}
|
||||
|
||||
_texture.create();
|
||||
_texture.setSize(w, h, true);
|
||||
Graphics::Surface background;
|
||||
background.create(w, h, Texture::getRGBAPixelFormat());
|
||||
glReadPixels(0, 0, background.w, background.h, GL_RGBA, GL_UNSIGNED_BYTE, background.getPixels());
|
||||
_texture.updateArea(Common::Rect(w, h), background);
|
||||
background.free();
|
||||
}
|
||||
|
||||
void Renderer3D::hideOverlay() {
|
||||
_inOverlay = false;
|
||||
|
||||
if (!_frameBuffers[0]) {
|
||||
// We don't have a framebuffer: destroy the texture we used to store the background
|
||||
_texture.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// We have a framebuffer: resize the screen if we have a pending change
|
||||
if (_pendingScreenChangeWidth >= 0 && _pendingScreenChangeHeight >= 0) {
|
||||
resize(_pendingScreenChangeWidth, _pendingScreenChangeHeight);
|
||||
_pendingScreenChangeWidth = -1;
|
||||
_pendingScreenChangeHeight = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/* 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_RENDERER3D_H
|
||||
#define BACKENDS_GRAPHICS_OPENGL_RENDERER3D_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
|
||||
#include "graphics/opengl/texture.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class Renderer3D {
|
||||
public:
|
||||
Renderer3D();
|
||||
~Renderer3D() { destroy(); }
|
||||
|
||||
void initSize(uint w, uint h, int samples, bool renderToFrameBuffer);
|
||||
void resize(uint w, uint h);
|
||||
void recreate();
|
||||
void destroy();
|
||||
|
||||
void leave3D();
|
||||
void enter3D();
|
||||
|
||||
void showOverlay(uint w, uint h);
|
||||
void hideOverlay();
|
||||
|
||||
const Texture &getGLTexture() const { return _texture; }
|
||||
bool hasTexture() const { return _texture.getGLTexture() != 0; }
|
||||
|
||||
protected:
|
||||
void setup();
|
||||
|
||||
int _stackLevel;
|
||||
bool _inOverlay;
|
||||
int _pendingScreenChangeWidth;
|
||||
int _pendingScreenChangeHeight;
|
||||
|
||||
bool _renderToFrameBuffer;
|
||||
int _samples;
|
||||
Texture _texture;
|
||||
GLuint _renderBuffers[3];
|
||||
GLuint _frameBuffers[2];
|
||||
|
||||
#define CTX_STATE(gl_param) GLboolean _save ## gl_param
|
||||
#define CTX_BOOLEAN(gl_param) GLboolean _save ## gl_param
|
||||
#define CTX_INTEGER(gl_param, count) GLint _save ## gl_param[count]
|
||||
|
||||
CTX_STATE(GL_BLEND);
|
||||
CTX_STATE(GL_CULL_FACE);
|
||||
CTX_STATE(GL_DEPTH_TEST);
|
||||
CTX_STATE(GL_DITHER);
|
||||
CTX_STATE(GL_POLYGON_OFFSET_FILL);
|
||||
CTX_STATE(GL_SCISSOR_TEST);
|
||||
CTX_STATE(GL_STENCIL_TEST);
|
||||
|
||||
CTX_BOOLEAN(GL_DEPTH_WRITEMASK);
|
||||
|
||||
CTX_INTEGER(GL_BLEND_SRC_RGB, 1);
|
||||
CTX_INTEGER(GL_BLEND_DST_RGB, 1);
|
||||
CTX_INTEGER(GL_BLEND_SRC_ALPHA, 1);
|
||||
CTX_INTEGER(GL_BLEND_DST_ALPHA, 1);
|
||||
CTX_INTEGER(GL_SCISSOR_BOX, 4);
|
||||
CTX_INTEGER(GL_VIEWPORT, 4);
|
||||
|
||||
#undef CTX_INTEGER
|
||||
#undef CTX_BOOLEAN
|
||||
#undef CTX_STATE
|
||||
};
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif // defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
|
||||
#endif
|
||||
@@ -789,7 +789,11 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
|
||||
height = _desiredFullscreenHeight;
|
||||
flags |= SDL_FULLSCREEN;
|
||||
}
|
||||
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
|
||||
if (_resizable && !_renderer3d) {
|
||||
#else
|
||||
if (_resizable) {
|
||||
#endif
|
||||
// In SDL1.2, resizing the window may invalidate the context
|
||||
// This would kill all the engine objects
|
||||
flags |= SDL_RESIZABLE;
|
||||
|
||||
@@ -176,6 +176,7 @@ ifdef USE_OPENGL
|
||||
MODULE_OBJS += \
|
||||
graphics/opengl/framebuffer.o \
|
||||
graphics/opengl/opengl-graphics.o \
|
||||
graphics/opengl/renderer3d.o \
|
||||
graphics/opengl/shader.o \
|
||||
graphics/opengl/texture.o \
|
||||
graphics/opengl/pipelines/clut8.o \
|
||||
|
||||
Reference in New Issue
Block a user