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  Graphics::PixelFormat convertSDLPixelFormat(SDL_PixelFormat *in) const;
99 public:
100  void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
101  Graphics::Surface *lockScreen() override;
102  void unlockScreen() override;
103  void fillScreen(uint32 col) override;
104  void fillScreen(const Common::Rect &r, uint32 col) override;
105  void updateScreen() override;
106  void setFocusRectangle(const Common::Rect& rect) override;
107  void clearFocusRectangle() override;
108 
109  Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
110  void clearOverlay() override;
111  void grabOverlay(Graphics::Surface &surface) const override;
112  void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
113  int16 getOverlayHeight() const override { return _videoMode.overlayHeight; }
114  int16 getOverlayWidth() const override { return _videoMode.overlayWidth; }
115 
116  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;
117  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);
118  void setCursorPalette(const byte *colors, uint start, uint num) override;
119 
120 #ifdef USE_OSD
121  void displayMessageOnOSD(const Common::U32String &msg) override;
122  void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
123 #endif
124 
125  // Override from Common::EventObserver
126  bool notifyEvent(const Common::Event &event) override;
127 
128  // SdlGraphicsManager interface
129  void notifyVideoExpose() override;
130  void notifyResize(const int width, const int height) override;
131 
132 #if defined(USE_IMGUI) && defined(USE_IMGUI_SDLRENDERER2)
133  void *getImGuiTexture(const Graphics::Surface &image, const byte *palette, int palCount) override;
134  void freeImGuiTexture(void *texture) override;
135 #endif
136 
137 protected:
138 #ifdef USE_OSD
139 
140  SDL_Surface *_osdMessageSurface;
142  uint8 _osdMessageAlpha;
144  uint32 _osdMessageFadeStartTime;
146  enum {
147  kOSDFadeOutDelay = 2 * 1000,
148  kOSDFadeOutDuration = 500,
149  kOSDInitialAlpha = 80
150  };
152  SDL_Rect getOSDMessageRect() const;
154  void removeOSDMessage();
156  SDL_Surface *_osdIconSurface;
158  SDL_Rect getOSDIconRect() const;
159 
160  void updateOSD();
161  void drawOSD();
162 #endif
163 
164  class AspectRatio {
165  int _kw, _kh;
166  public:
167  AspectRatio() { _kw = _kh = 0; }
168  AspectRatio(int w, int h);
169 
170  bool isAuto() const { return (_kw | _kh) == 0; }
171 
172  int kw() const { return _kw; }
173  int kh() const { return _kh; }
174  };
175 
176  static AspectRatio getDesiredAspectRatio();
177 
178  bool gameNeedsAspectRatioCorrection() const override {
179  return _videoMode.aspectRatioCorrection;
180  }
181  int getGameRenderScale() const override {
182  return _videoMode.scaleFactor;
183  }
184 
185  void handleResizeImpl(const int width, const int height) override;
186 
187  virtual void setupHardwareSize();
188 
189  void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &width, int &height) const;
190 
191 #if SDL_VERSION_ATLEAST(2, 0, 0)
192  /* SDL2 features a different API for 2D graphics. We create a wrapper
193  * around this API to keep the code paths as close as possible. */
194  SDL_Renderer *_renderer;
195  SDL_Texture *_screenTexture;
196  void deinitializeRenderer();
197  void recreateScreenTexture();
198 
199  virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
200  virtual void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects);
201  int SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
202  int SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
203  int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
204 #endif
205 
207  SDL_Surface *_screen;
208  Graphics::PixelFormat _screenFormat;
209  Graphics::PixelFormat _cursorFormat;
210 #ifdef USE_RGB_COLOR
211  Common::List<Graphics::PixelFormat> _supportedFormats;
212 
217  void detectSupportedFormats();
218 #endif
219 
221  SDL_Surface *_tmpscreen;
223  SDL_Surface *_tmpscreen2;
224 
225  SDL_Surface *_overlayscreen;
226  bool _useOldSrc;
227  Graphics::PixelFormat _overlayFormat;
228  bool _isDoubleBuf, _isHwPalette;
229 
230  enum {
231  kTransactionNone = 0,
232  kTransactionActive = 1,
233  kTransactionRollback = 2
234  };
235 
237  bool sizeChanged;
238  bool needHotswap;
239  bool needUpdatescreen;
240 #if SDL_VERSION_ATLEAST(2, 0, 0)
241  bool needTextureUpdate;
242  bool needDisplayResize;
243 #endif
244 #ifdef USE_RGB_COLOR
245  bool formatChanged;
246 #endif
247 
249  sizeChanged = false;
250  needHotswap = false;
251  needUpdatescreen = false;
252 
253 #if SDL_VERSION_ATLEAST(2, 0, 0)
254  needTextureUpdate = false;
255  needDisplayResize = false;
256 #endif
257 #ifdef USE_RGB_COLOR
258  formatChanged = false;
259 #endif
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 #ifdef USE_RGB_COLOR
285  Graphics::PixelFormat format;
286 #endif
287 
288  VideoState() {
289  setup = false;
290  fullscreen = false;
291  aspectRatioCorrection = false;
292  // desiredAspectRatio set to (0, 0) by AspectRatio constructor
293  filtering = false;
294 
295  mode = GFX_SURFACESDL;
296 #if SDL_VERSION_ATLEAST(2, 0, 0)
297  stretchMode = 0;
298 #endif
299  vsync = false;
300 
301  scalerIndex = 0;
302  scaleFactor = 0;
303 
304  screenWidth = 0;
305  screenHeight = 0;
306  overlayWidth = 0;
307  overlayHeight = 0;
308  hardwareWidth = 0;
309  hardwareHeight = 0;
310 #ifdef USE_RGB_COLOR
311  // format set to 0 values by Graphics::PixelFormat constructor
312 #endif
313  }
314  };
315  VideoState _videoMode, _oldVideoMode;
316 
317 #if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
318 
331  uint8 _originalBitsPerPixel;
332 #endif
333 
334  int _transactionMode;
335 
336  // Indicates whether it is needed to free _hwSurface in destructor
337  bool _displayDisabled;
338 
339  const PluginList &_scalerPlugins;
340  ScalerPluginObject *_scalerPlugin;
341  Scaler *_scaler, *_mouseScaler;
342  uint _maxExtraPixels;
343  uint _extraPixels;
344 
345  bool _screenIsLocked;
346  Graphics::Surface _framebuffer;
347 
348  int _screenChangeCount;
349 
350  enum {
351  NUM_DIRTY_RECT = 100,
352  MAX_SCALING = 3
353  };
354 
355  // Dirty rect management
356  // When double-buffering we need to redraw both updates from
357  // current frame and previous frame. For convenience we copy
358  // them here before traversing the list.
359  SDL_Rect _dirtyRectList[2 * NUM_DIRTY_RECT];
360  int _numDirtyRects;
361 
362  SDL_Rect _prevDirtyRectList[NUM_DIRTY_RECT];
363  int _numPrevDirtyRects;
364 
365  struct MousePos {
366  // The size and hotspot of the original cursor image.
367  int16 w, h;
368  int16 hotX, hotY;
369 
370  // The size and hotspot of the pre-scaled cursor image, in real
371  // coordinates.
372  int16 rW, rH;
373  int16 rHotX, rHotY;
374 
375  // The size and hotspot of the pre-scaled cursor image, in game
376  // coordinates.
377  int16 vW, vH;
378  int16 vHotX, vHotY;
379 
380  MousePos() : w(0), h(0), hotX(0), hotY(0),
381  rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
382  vHotX(0), vHotY(0)
383  { }
384  };
385 
386  SDL_Rect _mouseLastRect, _mouseNextRect;
387  MousePos _mouseCurState;
388 #ifdef USE_RGB_COLOR
389  uint32 _mouseKeyColor;
390 #else
391  byte _mouseKeyColor;
392 #endif
393  bool _disableMouseKeyColor;
394  byte _mappedMouseKeyColor;
395  bool _cursorDontScale;
396  bool _cursorPaletteDisabled;
397  SDL_Surface *_mouseOrigSurface;
398  SDL_Surface *_mouseSurface;
399 
400  // Shake mode
401  // This is always set to 0 when building with SDL2.
402  int _currentShakeXOffset;
403  int _currentShakeYOffset;
404 
405  // Palette data
406  SDL_Color *_currentPalette;
407  uint _paletteDirtyStart, _paletteDirtyEnd;
408 
409  SDL_Color *_overlayPalette;
410  bool _isInOverlayPalette;
411 
412  // Cursor palette data
413  SDL_Color *_cursorPalette;
414 
420 
421 #ifdef USE_SDL_DEBUG_FOCUSRECT
422  bool _enableFocusRectDebugCode;
423  bool _enableFocusRect;
424  Common::Rect _focusRect;
425 #endif
426 
427  virtual void addDirtyRect(int x, int y, int w, int h, bool inOverlay, bool realCoordinates = false);
428 
429  virtual void drawMouse();
430  virtual void undrawMouse();
431  virtual void blitCursor();
432 
433  virtual void internUpdateScreen();
434  virtual void updateScreen(SDL_Rect *dirtyRectList, int actualDirtyRects);
435 
436  virtual bool loadGFXMode();
437  virtual void unloadGFXMode();
438  virtual bool hotswapGFXMode();
439 
440  virtual void setAspectRatioCorrection(bool enable);
441  void setFilteringMode(bool enable);
442  void setVSync(bool enable);
443 
444  bool saveScreenshot(const Common::Path &filename) const override;
445  virtual void setGraphicsModeIntern();
446  virtual void getDefaultResolution(uint &w, uint &h);
447 
448 private:
449  void setFullscreenMode(bool enable);
450  void handleScalerHotkeys(uint mode, int factor);
451 
456  Common::Point convertOverlayToGame(const int x, const int y) const {
457  if (getOverlayWidth() == 0 || getOverlayHeight() == 0) {
458  error("convertOverlayToGame called without a valid overlay");
459  }
460 
461  return Common::Point(x * getWidth() / getOverlayWidth(),
462  y * getHeight() / getOverlayHeight());
463  }
464 
469  Common::Point convertGameToOverlay(const int x, const int y) const {
470  if (getWidth() == 0 || getHeight() == 0) {
471  error("convertGameToOverlay called without a valid overlay");
472  }
473 
474  return Common::Point(x * getOverlayWidth() / getWidth(),
475  y * getOverlayHeight() / getHeight());
476  }
477 
484  bool _needRestoreAfterOverlay;
485  bool _prevForceRedraw;
486  bool _prevCursorNeedsRedraw;
487 };
488 
489 #endif
Definition: surfacesdl-graphics.h:365
bool notifyEvent(const Common::Event &event) override
int getGameRenderScale() const override
Definition: surfacesdl-graphics.h:181
Definition: surfacesdl-graphics.h:264
Definition: surface.h:67
Definition: system.h:779
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:730
Feature
Definition: system.h:403
Definition: list.h:44
Definition: rect.h:144
Definition: path.h:52
void notifyVideoExpose() override
void notifyResize(const int width, const int height) override
Common::Mutex _graphicsMutex
Definition: surfacesdl-graphics.h:419
bool gameNeedsAspectRatioCorrection() const override
Definition: surfacesdl-graphics.h:178
Definition: ustr.h:57
TransactionError
Definition: system.h:1155
Definition: scalerplugin.h:150
Definition: events.h:199
Definition: mutex.h:67
Definition: rect.h:45
SDL_Surface * _screen
Definition: surfacesdl-graphics.h:207
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: surfacesdl-graphics.h:236
SDL_Surface * _tmpscreen
Definition: surfacesdl-graphics.h:221
Definition: surfacesdl-graphics.h:164
Definition: surfacesdl-graphics.h:50
void grabPalette(byte *colors, uint start, uint num) const override
SDL_Surface * _tmpscreen2
Definition: surfacesdl-graphics.h:223
void setPalette(const byte *colors, uint start, uint num) override
Definition: scalerplugin.h:28
Graphics::PixelFormat convertSDLPixelFormat(SDL_PixelFormat *in) const
Definition: sdl-window.h:30