scummvm/backends/graphics/opengl/opengl-graphics.h
Le Philousophe adda0dc063 BACKENDS: OPENGL: Allow the backend to specify the render target
For now only backbuffer is used.
2023-07-03 21:50:32 +02:00

519 lines
13 KiB
C++

/* 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_GRAPHICS_H
#define BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H
#include "backends/graphics/opengl/framebuffer.h"
#include "backends/graphics/windowed.h"
#include "common/frac.h"
#include "common/mutex.h"
#include "common/ustr.h"
#include "graphics/surface.h"
namespace Graphics {
class Font;
} // End of namespace Graphics
namespace OpenGL {
// HACK: We use glColor in the OSD code. This might not be working on GL ES but
// we still enable it because Tizen already shipped with it. Also, the
// SurfaceSDL backend enables it and disabling it can cause issues in sdl.cpp.
#define USE_OSD 1
class Surface;
class Pipeline;
#if !USE_FORCED_GLES
class LibRetroPipeline;
#endif
enum {
GFX_OPENGL = 0
};
class OpenGLGraphicsManager : virtual public WindowedGraphicsManager {
public:
OpenGLGraphicsManager();
virtual ~OpenGLGraphicsManager();
// GraphicsManager API
bool hasFeature(OSystem::Feature f) const override;
void setFeatureState(OSystem::Feature f, bool enable) override;
bool getFeatureState(OSystem::Feature f) const override;
const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
int getDefaultGraphicsMode() const override;
bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
int getGraphicsMode() const override;
#ifdef USE_RGB_COLOR
Graphics::PixelFormat getScreenFormat() const override;
Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
#endif
const OSystem::GraphicsMode *getSupportedStretchModes() const override;
int getDefaultStretchMode() const override;
bool setStretchMode(int mode) override;
int getStretchMode() const override;
#ifdef USE_SCALERS
uint getDefaultScaler() const override;
uint getDefaultScaleFactor() const override;
bool setScaler(uint mode, int factor) override;
uint getScaler() const override;
uint getScaleFactor() const override;
#endif
#if !USE_FORCED_GLES
bool setShader(const Common::String &fileNode) override;
#endif
void beginGFXTransaction() override;
OSystem::TransactionError endGFXTransaction() override;
int getScreenChangeID() const override;
void initSize(uint width, uint height, const Graphics::PixelFormat *format) override;
int16 getWidth() const override;
int16 getHeight() const override;
void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
void fillScreen(uint32 col) override;
void updateScreen() override;
Graphics::Surface *lockScreen() override;
void unlockScreen() override;
void setFocusRectangle(const Common::Rect& rect) override;
void clearFocusRectangle() override;
int16 getOverlayWidth() const override;
int16 getOverlayHeight() const override;
Graphics::PixelFormat getOverlayFormat() const override;
void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
void clearOverlay() override;
void grabOverlay(Graphics::Surface &surface) const override;
void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format, const byte *mask) override;
void setCursorPalette(const byte *colors, uint start, uint num) override;
void displayMessageOnOSD(const Common::U32String &msg) override;
void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
// PaletteManager interface
void setPalette(const byte *colors, uint start, uint num) override;
void grabPalette(byte *colors, uint start, uint num) const override;
protected:
void renderCursor();
/**
* Whether a GLES or GLES2 context is active.
*/
bool isGLESContext() const { return OpenGLContext.type == kContextGLES || OpenGLContext.type == kContextGLES2; }
/**
* Notify the manager of a OpenGL context change. This should be the first
* thing to call after you created an OpenGL (ES) context!
*
* @param type Type of the OpenGL (ES) contexts created.
* @param defaultFormat The new default format for the game screen
* (this is used for the CLUT8 game screens).
* @param defaultFormatAlpha The new default format with an alpha channel
* (this is used for the overlay and cursor).
*/
void notifyContextCreate(
ContextType type,
Framebuffer *target,
const Graphics::PixelFormat &defaultFormat,
const Graphics::PixelFormat &defaultFormatAlpha);
/**
* Notify the manager that the OpenGL context is about to be destroyed.
* This will free up/reset internal OpenGL related state and *must* be
* called whenever a context might be created again after destroying a
* context.
*/
void notifyContextDestroy();
/**
* Create a surface with the specified pixel format.
*
* @param format The pixel format the Surface object should accept as
* input.
* @param wantAlpha For CLUT8 surfaces this marks whether an alpha
* channel should be used.
* @param wantScaler Whether or not a software scaler should be used.
* @return A pointer to the surface or nullptr on failure.
*/
Surface *createSurface(const Graphics::PixelFormat &format, bool wantAlpha = false, bool wantScaler = false, bool wantMask = false);
//
// Transaction support
//
struct VideoState {
VideoState() : valid(false), gameWidth(0), gameHeight(0),
#ifdef USE_RGB_COLOR
gameFormat(),
#endif
aspectRatioCorrection(false), graphicsMode(GFX_OPENGL), filtering(true),
scalerIndex(0), scaleFactor(1), shader() {
}
bool valid;
uint gameWidth, gameHeight;
#ifdef USE_RGB_COLOR
Graphics::PixelFormat gameFormat;
#endif
bool aspectRatioCorrection;
int graphicsMode;
bool filtering;
uint scalerIndex;
int scaleFactor;
Common::String shader;
bool operator==(const VideoState &right) {
return gameWidth == right.gameWidth && gameHeight == right.gameHeight
#ifdef USE_RGB_COLOR
&& gameFormat == right.gameFormat
#endif
&& aspectRatioCorrection == right.aspectRatioCorrection
&& graphicsMode == right.graphicsMode
&& filtering == right.filtering
&& shader == right.shader;
}
bool operator!=(const VideoState &right) {
return !(*this == right);
}
};
/**
* The currently set up video state.
*/
VideoState _currentState;
/**
* The old video state used when doing a transaction rollback.
*/
VideoState _oldState;
protected:
enum TransactionMode {
kTransactionNone = 0,
kTransactionActive = 1,
kTransactionRollback = 2
};
TransactionMode getTransactionMode() const { return _transactionMode; }
private:
/**
* The current transaction mode.
*/
TransactionMode _transactionMode;
/**
* The current screen change ID.
*/
int _screenChangeID;
/**
* The current stretch mode.
*/
int _stretchMode;
/**
* Scaled version of _gameScreenShakeXOffset and _gameScreenShakeYOffset (as a Common::Point)
*/
Common::Point _shakeOffsetScaled;
protected:
/**
* Set up the requested video mode. This takes parameters which describe
* what resolution the game screen requests (this is possibly aspect ratio
* corrected!).
*
* A sub-class should take these parameters as hints. It might very well
* set up a mode which it thinks suites the situation best.
*
* @parma requestedWidth This is the requested actual game screen width.
* @param requestedHeight This is the requested actual game screen height.
* @param format This is the requested pixel format of the virtual game screen.
* @return true on success, false otherwise
*/
virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0;
bool loadShader(const Common::String &fileName);
/**
* Refresh the screen contents.
*/
virtual void refreshScreen() = 0;
/**
* Saves a screenshot of the entire window, excluding window decorations.
*
* @param filename The output filename.
* @return true on success, false otherwise
*/
bool saveScreenshot(const Common::String &filename) const;
// Do not hide the argument-less saveScreenshot from the base class
using WindowedGraphicsManager::saveScreenshot;
private:
//
// OpenGL utilities
//
/**
* Initialize the active context for use.
*/
void initializeGLContext();
/**
* OpenGL pipeline used for rendering.
*/
Pipeline *_pipeline;
#if !USE_FORCED_GLES
/**
* OpenGL pipeline used for post-processing.
*/
LibRetroPipeline *_libretroPipeline;
#endif
protected:
/**
* Try to determine the internal parameters for a given pixel format.
*
* @return true when the format can be used, false otherwise.
*/
bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const;
bool gameNeedsAspectRatioCorrection() const override;
int getGameRenderScale() const override;
void recalculateDisplayAreas() override;
void handleResizeImpl(const int width, const int height) override;
void updateLinearFiltering();
Pipeline *getPipeline() const { return _pipeline; }
/**
* The default pixel format of the backend.
*/
Graphics::PixelFormat _defaultFormat;
/**
* The default pixel format with an alpha channel.
*/
Graphics::PixelFormat _defaultFormatAlpha;
/**
* Render target.
*/
Framebuffer *_targetBuffer;
/**
* The rendering surface for the virtual game screen.
*/
Surface *_gameScreen;
/**
* The game palette if in CLUT8 mode.
*/
byte _gamePalette[3 * 256];
//
// Overlay
//
/**
* The rendering surface for the overlay.
*/
Surface *_overlay;
//
// Cursor
//
/**
* Set up the correct cursor palette.
*/
void updateCursorPalette();
/**
* The rendering surface for the mouse cursor.
*/
Surface *_cursor;
/**
* The rendering surface for the opacity and inversion mask (if any)
*/
Surface *_cursorMask;
/**
* The X offset for the cursor hotspot in unscaled game coordinates.
*/
int _cursorHotspotX;
/**
* The Y offset for the cursor hotspot in unscaled game coordinates.
*/
int _cursorHotspotY;
/**
* Recalculate the cursor scaling. Scaling is always done according to
* the game screen.
*/
void recalculateCursorScaling();
/**
* The X offset for the cursor hotspot in scaled game display area
* coordinates.
*/
int _cursorHotspotXScaled;
/**
* The Y offset for the cursor hotspot in scaled game display area
* coordinates.
*/
int _cursorHotspotYScaled;
/**
* The width of the cursor in scaled game display area coordinates.
*/
float _cursorWidthScaled;
/**
* The height of the cursor in scaled game display area coordinates.
*/
float _cursorHeightScaled;
/**
* The key color.
*/
uint32 _cursorKeyColor;
/**
* If true, use key color.
*/
bool _cursorUseKey;
/**
* Whether no cursor scaling should be applied.
*/
bool _cursorDontScale;
/**
* Whether the special cursor palette is enabled.
*/
bool _cursorPaletteEnabled;
/**
* The special cursor palette in case enabled.
*/
byte _cursorPalette[3 * 256];
#ifdef USE_SCALERS
/**
* The list of scaler plugins
*/
const PluginList &_scalerPlugins;
#endif
#ifdef USE_OSD
//
// OSD
//
protected:
/**
* Returns the font used for on screen display
*/
virtual const Graphics::Font *getFontOSD() const;
private:
/**
* Request for the OSD icon surface to be updated.
*/
bool _osdMessageChangeRequest;
/**
* The next OSD message.
*
* If this value is not empty, the OSD message will be set
* to it on the next frame.
*/
Common::U32String _osdMessageNextData;
/**
* Set the OSD message surface with the value of the next OSD message.
*/
void osdMessageUpdateSurface();
/**
* The OSD message's contents.
*/
Surface *_osdMessageSurface;
/**
* Current opacity level of the OSD message.
*/
uint8 _osdMessageAlpha;
/**
* When fading the OSD message has started.
*/
uint32 _osdMessageFadeStartTime;
enum {
kOSDMessageFadeOutDelay = 2 * 1000,
kOSDMessageFadeOutDuration = 500,
kOSDMessageInitialAlpha = 80
};
/**
* The OSD background activity icon's contents.
*/
Surface *_osdIconSurface;
enum {
kOSDIconTopMargin = 10,
kOSDIconRightMargin = 10
};
#endif
};
} // End of namespace OpenGL
#endif