ScummVM API documentation
surfacesdl-graphics.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef BACKENDS_GRAPHICS_SURFACESDL_GRAPHICS_H
23 #define BACKENDS_GRAPHICS_SURFACESDL_GRAPHICS_H
24 
25 #include "backends/graphics/graphics.h"
26 #include "backends/graphics/sdl/sdl-graphics.h"
27 #include "graphics/pixelformat.h"
28 #include "graphics/scaler.h"
29 #include "graphics/scalerplugin.h"
30 #include "common/events.h"
31 #include "common/mutex.h"
32 
33 #include "backends/events/sdl/sdl-events.h"
34 
35 #include "backends/platform/sdl/sdl-sys.h"
36 
37 #ifndef RELEASE_BUILD
38 // Define this to allow for focus rectangle debugging
39 #define USE_SDL_DEBUG_FOCUSRECT
40 #endif
41 
42 enum {
43  GFX_SURFACESDL = 0
44 };
45 
46 
51 public:
52  SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window);
53  virtual ~SurfaceSdlGraphicsManager();
54 
55  bool hasFeature(OSystem::Feature f) const override;
56  void setFeatureState(OSystem::Feature f, bool enable) override;
57  bool getFeatureState(OSystem::Feature f) const override;
58 
59  const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
60  int getDefaultGraphicsMode() const override;
61  bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
62  int getGraphicsMode() const override;
63  uint getDefaultScaler() const override;
64  uint getDefaultScaleFactor() const override;
65  bool setScaler(uint mode, int factor) override;
66  uint getScaler() const override;
67  uint getScaleFactor() const override;
68 #ifdef USE_RGB_COLOR
69  Graphics::PixelFormat getScreenFormat() const override { return _screenFormat; }
70  Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
71 #endif
72 #if SDL_VERSION_ATLEAST(2, 0, 0)
73  const OSystem::GraphicsMode *getSupportedStretchModes() const override;
74  int getDefaultStretchMode() const override;
75  bool setStretchMode(int mode) override;
76  int getStretchMode() const override;
77 #endif
78  void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL) override;
79  int getScreenChangeID() const override { return _screenChangeCount; }
80 
81  void beginGFXTransaction() override;
82  OSystem::TransactionError endGFXTransaction() override;
83 
84  int16 getHeight() const override;
85  int16 getWidth() const override;
86 
87 protected:
88  // PaletteManager API
89  void setPalette(const byte *colors, uint start, uint num) override;
90  void grabPalette(byte *colors, uint start, uint num) const override;
91  virtual void initGraphicsSurface();
92 
98 #if SDL_VERSION_ATLEAST(3, 0, 0)
99  Graphics::PixelFormat convertSDLPixelFormat(SDL_PixelFormat in) const;
100 #else
101  Graphics::PixelFormat convertSDLPixelFormat(SDL_PixelFormat *in) const;
102 #endif
103 public:
104  void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
105  Graphics::Surface *lockScreen() override;
106  void unlockScreen() override;
107  void fillScreen(uint32 col) override;
108  void fillScreen(const Common::Rect &r, uint32 col) override;
109  void updateScreen() override;
110  void setFocusRectangle(const Common::Rect& rect) override;
111  void clearFocusRectangle() override;
112 
113  Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
114  void clearOverlay() override;
115  void grabOverlay(Graphics::Surface &surface) const override;
116  void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
117  int16 getOverlayHeight() const override { return _videoMode.overlayHeight; }
118  int16 getOverlayWidth() const override { return _videoMode.overlayWidth; }
119 
120  void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL, const byte *mask = NULL) override;
121  void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format, const byte *mask, bool disableKeyColor);
122  void setCursorPalette(const byte *colors, uint start, uint num) override;
123 
124 #ifdef USE_OSD
125  void displayMessageOnOSD(const Common::U32String &msg) override;
126  void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
127 #endif
128 
129  // Override from Common::EventObserver
130  bool notifyEvent(const Common::Event &event) override;
131 
132  // SdlGraphicsManager interface
133  void notifyVideoExpose() override;
134  void notifyResize(const int width, const int height) override;
135 
136 #if defined(USE_IMGUI) && (defined(USE_IMGUI_SDLRENDERER2) || defined(USE_IMGUI_SDLRENDERER3))
137  void *getImGuiTexture(const Graphics::Surface &image, const byte *palette, int palCount) override;
138  void freeImGuiTexture(void *texture) override;
139 #endif
140 
141 protected:
142 #ifdef USE_OSD
143 
144  SDL_Surface *_osdMessageSurface;
146  uint8 _osdMessageAlpha;
148  uint32 _osdMessageFadeStartTime;
150  enum {
151  kOSDFadeOutDelay = 2 * 1000,
152  kOSDFadeOutDuration = 500,
153  kOSDInitialAlpha = 80
154  };
156  SDL_Rect getOSDMessageRect() const;
158  void removeOSDMessage();
160  SDL_Surface *_osdIconSurface;
162  SDL_Rect getOSDIconRect() const;
163 
164  void updateOSD();
165  void drawOSD();
166 #endif
167 
168  class AspectRatio {
169  int _kw, _kh;
170  public:
171  AspectRatio() { _kw = _kh = 0; }
172  AspectRatio(int w, int h);
173 
174  bool isAuto() const { return (_kw | _kh) == 0; }
175 
176  int kw() const { return _kw; }
177  int kh() const { return _kh; }
178  };
179 
180  static AspectRatio getDesiredAspectRatio();
181 
182  bool gameNeedsAspectRatioCorrection() const override {
183  return _videoMode.aspectRatioCorrection;
184  }
185  int getGameRenderScale() const override {
186  return _videoMode.scaleFactor;
187  }
188 
189  void handleResizeImpl(const int width, const int height) override;
190 
191  virtual void setupHardwareSize();
192 
193  void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &width, int &height) const;
194 
195 #if SDL_VERSION_ATLEAST(2, 0, 0)
196  /* SDL2 features a different API for 2D graphics. We create a wrapper
197  * around this API to keep the code paths as close as possible. */
198  SDL_Renderer *_renderer;
199  SDL_Texture *_screenTexture;
200  void deinitializeRenderer();
201  void recreateScreenTexture();
202 
203  virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
204  virtual void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects);
205  int SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
206  int SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
207  int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
208 #endif
209 
211  SDL_Surface *_screen;
212  Graphics::PixelFormat _screenFormat;
213  Graphics::PixelFormat _cursorFormat;
214 #ifdef USE_RGB_COLOR
215  Common::List<Graphics::PixelFormat> _supportedFormats;
216 
221  void detectSupportedFormats();
222 #endif
223 
225  SDL_Surface *_tmpscreen;
227  SDL_Surface *_tmpscreen2;
228 
229  SDL_Surface *_overlayscreen;
230  bool _useOldSrc;
231  Graphics::PixelFormat _overlayFormat;
232  bool _isDoubleBuf, _isHwPalette;
233 
234  enum {
235  kTransactionNone = 0,
236  kTransactionActive = 1,
237  kTransactionRollback = 2
238  };
239 
241  bool sizeChanged;
242  bool needHotswap;
243  bool needUpdatescreen;
244 #if SDL_VERSION_ATLEAST(2, 0, 0)
245  bool needTextureUpdate;
246  bool needDisplayResize;
247 #endif
248  bool formatChanged;
249 
251  sizeChanged = false;
252  needHotswap = false;
253  needUpdatescreen = false;
254 
255 #if SDL_VERSION_ATLEAST(2, 0, 0)
256  needTextureUpdate = false;
257  needDisplayResize = false;
258 #endif
259  formatChanged = false;
260  }
261  };
262  TransactionDetails _transactionDetails;
263 
264  struct VideoState {
265  bool setup;
266 
267  bool fullscreen;
268  bool aspectRatioCorrection;
269  AspectRatio desiredAspectRatio;
270  bool filtering;
271 
272  int mode;
273 #if SDL_VERSION_ATLEAST(2, 0, 0)
274  int stretchMode;
275 #endif
276  bool vsync;
277 
278  uint scalerIndex;
279  int scaleFactor;
280 
281  int screenWidth, screenHeight;
282  int overlayWidth, overlayHeight;
283  int hardwareWidth, hardwareHeight;
284  Graphics::PixelFormat format;
285 
286  VideoState() {
287  setup = false;
288  fullscreen = false;
289  aspectRatioCorrection = false;
290  // desiredAspectRatio set to (0, 0) by AspectRatio constructor
291  filtering = false;
292 
293  mode = GFX_SURFACESDL;
294 #if SDL_VERSION_ATLEAST(2, 0, 0)
295  stretchMode = 0;
296 #endif
297  vsync = false;
298 
299  scalerIndex = 0;
300  scaleFactor = 0;
301 
302  screenWidth = 0;
303  screenHeight = 0;
304  overlayWidth = 0;
305  overlayHeight = 0;
306  hardwareWidth = 0;
307  hardwareHeight = 0;
308  // format set to 0 values by Graphics::PixelFormat constructor
309  }
310  };
311  VideoState _videoMode, _oldVideoMode;
312 
313 #if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
314 
327  uint8 _originalBitsPerPixel;
328 #endif
329 
330  int _transactionMode;
331 
332  // Indicates whether it is needed to free _hwSurface in destructor
333  bool _displayDisabled;
334 
335  const PluginList &_scalerPlugins;
336  ScalerPluginObject *_scalerPlugin;
337  Scaler *_scaler, *_mouseScaler;
338  uint _maxExtraPixels;
339  uint _extraPixels;
340 
341  bool _screenIsLocked;
342  Graphics::Surface _framebuffer;
343 
344  int _screenChangeCount;
345 
346  enum {
347  NUM_DIRTY_RECT = 100,
348  MAX_SCALING = 3
349  };
350 
351  // Dirty rect management
352  // When double-buffering we need to redraw both updates from
353  // current frame and previous frame. For convenience we copy
354  // them here before traversing the list.
355  SDL_Rect _dirtyRectList[2 * NUM_DIRTY_RECT];
356  int _numDirtyRects;
357 
358  SDL_Rect _prevDirtyRectList[NUM_DIRTY_RECT];
359  int _numPrevDirtyRects;
360 
361  struct MousePos {
362  // The size and hotspot of the original cursor image.
363  int16 w, h;
364  int16 hotX, hotY;
365 
366  // The size and hotspot of the pre-scaled cursor image, in real
367  // coordinates.
368  int16 rW, rH;
369  int16 rHotX, rHotY;
370 
371  // The size and hotspot of the pre-scaled cursor image, in game
372  // coordinates.
373  int16 vW, vH;
374  int16 vHotX, vHotY;
375 
376  MousePos() : w(0), h(0), hotX(0), hotY(0),
377  rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
378  vHotX(0), vHotY(0)
379  { }
380  };
381 
382  SDL_Rect _mouseLastRect, _mouseNextRect;
383  MousePos _mouseCurState;
384  uint32 _mouseKeyColor;
385  bool _disableMouseKeyColor;
386  byte _mappedMouseKeyColor;
387  bool _cursorDontScale;
388  bool _cursorPaletteDisabled;
389  SDL_Surface *_mouseOrigSurface;
390  SDL_Surface *_mouseSurface;
391 
392  // Shake mode
393  // This is always set to 0 when building with SDL2.
394  int _currentShakeXOffset;
395  int _currentShakeYOffset;
396 
397  // Palette data
398  SDL_Color *_currentPalette;
399  uint _paletteDirtyStart, _paletteDirtyEnd;
400 
401  SDL_Color *_overlayPalette;
402  bool _isInOverlayPalette;
403 
404  // Cursor palette data
405  SDL_Color *_cursorPalette;
406 
412 
413 #ifdef USE_SDL_DEBUG_FOCUSRECT
414  bool _enableFocusRectDebugCode;
415  bool _enableFocusRect;
416  Common::Rect _focusRect;
417 #endif
418 
419  virtual void addDirtyRect(int x, int y, int w, int h, bool inOverlay, bool realCoordinates = false);
420 
421  virtual void drawMouse();
422  virtual void undrawMouse();
423  virtual void blitCursor();
424 
425  virtual void internUpdateScreen();
426  virtual void updateScreen(SDL_Rect *dirtyRectList, int actualDirtyRects);
427 
428  virtual bool loadGFXMode();
429  virtual void unloadGFXMode();
430  virtual bool hotswapGFXMode();
431 
432  virtual void setAspectRatioCorrection(bool enable);
433  void setFilteringMode(bool enable);
434  void setVSync(bool enable);
435 
436  bool saveScreenshot(const Common::Path &filename) const override;
437  virtual void setGraphicsModeIntern();
438  virtual void getDefaultResolution(uint &w, uint &h);
439 
440  // In SurfaceSDL mode we never render in 3D and can always switch the fullscreen state
441  bool canSwitchFullscreen() const override { return true; }
442 
443 private:
444  void setFullscreenMode(bool enable);
445  void handleScalerHotkeys(uint mode, int factor);
446 
451  Common::Point convertOverlayToGame(const int x, const int y) const {
452  if (getOverlayWidth() == 0 || getOverlayHeight() == 0) {
453  error("convertOverlayToGame called without a valid overlay");
454  }
455 
456  return Common::Point(x * getWidth() / getOverlayWidth(),
457  y * getHeight() / getOverlayHeight());
458  }
459 
464  Common::Point convertGameToOverlay(const int x, const int y) const {
465  if (getWidth() == 0 || getHeight() == 0) {
466  error("convertGameToOverlay called without a valid overlay");
467  }
468 
469  return Common::Point(x * getOverlayWidth() / getWidth(),
470  y * getOverlayHeight() / getHeight());
471  }
472 
479  bool _needRestoreAfterOverlay;
480  bool _prevForceRedraw;
481  bool _prevCursorNeedsRedraw;
482 };
483 
484 #endif
Definition: surfacesdl-graphics.h:361
bool notifyEvent(const Common::Event &event) override
int getGameRenderScale() const override
Definition: surfacesdl-graphics.h:185
Definition: surfacesdl-graphics.h:264
Definition: surface.h:67
Definition: system.h:776
Definition: sdl-events.h:40
Definition: sdl-graphics.h:38
void handleResizeImpl(const int width, const int height) override
Definition: array.h:52
Definition: pixelformat.h:138
Definition: system.h:727
Feature
Definition: system.h:411
Definition: list.h:44
Definition: rect.h:524
Definition: path.h:52
void notifyVideoExpose() override
void notifyResize(const int width, const int height) override
Common::Mutex _graphicsMutex
Definition: surfacesdl-graphics.h:411
bool gameNeedsAspectRatioCorrection() const override
Definition: surfacesdl-graphics.h:182
Definition: ustr.h:57
TransactionError
Definition: system.h:1174
Definition: scalerplugin.h:150
Definition: events.h:210
Definition: mutex.h:67
Definition: rect.h:144
SDL_Surface * _screen
Definition: surfacesdl-graphics.h:211
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: surfacesdl-graphics.h:240
SDL_Surface * _tmpscreen
Definition: surfacesdl-graphics.h:225
Definition: surfacesdl-graphics.h:168
Definition: surfacesdl-graphics.h:50
void grabPalette(byte *colors, uint start, uint num) const override
SDL_Surface * _tmpscreen2
Definition: surfacesdl-graphics.h:227
void setPalette(const byte *colors, uint start, uint num) override
Definition: scalerplugin.h:28
bool canSwitchFullscreen() const override
Definition: surfacesdl-graphics.h:441
Graphics::PixelFormat convertSDLPixelFormat(SDL_PixelFormat *in) const
Definition: sdl-window.h:30