ScummVM API documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 #ifdef USE_RGB_COLOR
249  bool formatChanged;
250 #endif
251 
253  sizeChanged = false;
254  needHotswap = false;
255  needUpdatescreen = false;
256 
257 #if SDL_VERSION_ATLEAST(2, 0, 0)
258  needTextureUpdate = false;
259  needDisplayResize = false;
260 #endif
261 #ifdef USE_RGB_COLOR
262  formatChanged = false;
263 #endif
264  }
265  };
266  TransactionDetails _transactionDetails;
267 
268  struct VideoState {
269  bool setup;
270 
271  bool fullscreen;
272  bool aspectRatioCorrection;
273  AspectRatio desiredAspectRatio;
274  bool filtering;
275 
276  int mode;
277 #if SDL_VERSION_ATLEAST(2, 0, 0)
278  int stretchMode;
279 #endif
280  bool vsync;
281 
282  uint scalerIndex;
283  int scaleFactor;
284 
285  int screenWidth, screenHeight;
286  int overlayWidth, overlayHeight;
287  int hardwareWidth, hardwareHeight;
288 #ifdef USE_RGB_COLOR
289  Graphics::PixelFormat format;
290 #endif
291 
292  VideoState() {
293  setup = false;
294  fullscreen = false;
295  aspectRatioCorrection = false;
296  // desiredAspectRatio set to (0, 0) by AspectRatio constructor
297  filtering = false;
298 
299  mode = GFX_SURFACESDL;
300 #if SDL_VERSION_ATLEAST(2, 0, 0)
301  stretchMode = 0;
302 #endif
303  vsync = false;
304 
305  scalerIndex = 0;
306  scaleFactor = 0;
307 
308  screenWidth = 0;
309  screenHeight = 0;
310  overlayWidth = 0;
311  overlayHeight = 0;
312  hardwareWidth = 0;
313  hardwareHeight = 0;
314 #ifdef USE_RGB_COLOR
315  // format set to 0 values by Graphics::PixelFormat constructor
316 #endif
317  }
318  };
319  VideoState _videoMode, _oldVideoMode;
320 
321 #if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
322 
335  uint8 _originalBitsPerPixel;
336 #endif
337 
338  int _transactionMode;
339 
340  // Indicates whether it is needed to free _hwSurface in destructor
341  bool _displayDisabled;
342 
343  const PluginList &_scalerPlugins;
344  ScalerPluginObject *_scalerPlugin;
345  Scaler *_scaler, *_mouseScaler;
346  uint _maxExtraPixels;
347  uint _extraPixels;
348 
349  bool _screenIsLocked;
350  Graphics::Surface _framebuffer;
351 
352  int _screenChangeCount;
353 
354  enum {
355  NUM_DIRTY_RECT = 100,
356  MAX_SCALING = 3
357  };
358 
359  // Dirty rect management
360  // When double-buffering we need to redraw both updates from
361  // current frame and previous frame. For convenience we copy
362  // them here before traversing the list.
363  SDL_Rect _dirtyRectList[2 * NUM_DIRTY_RECT];
364  int _numDirtyRects;
365 
366  SDL_Rect _prevDirtyRectList[NUM_DIRTY_RECT];
367  int _numPrevDirtyRects;
368 
369  struct MousePos {
370  // The size and hotspot of the original cursor image.
371  int16 w, h;
372  int16 hotX, hotY;
373 
374  // The size and hotspot of the pre-scaled cursor image, in real
375  // coordinates.
376  int16 rW, rH;
377  int16 rHotX, rHotY;
378 
379  // The size and hotspot of the pre-scaled cursor image, in game
380  // coordinates.
381  int16 vW, vH;
382  int16 vHotX, vHotY;
383 
384  MousePos() : w(0), h(0), hotX(0), hotY(0),
385  rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
386  vHotX(0), vHotY(0)
387  { }
388  };
389 
390  SDL_Rect _mouseLastRect, _mouseNextRect;
391  MousePos _mouseCurState;
392 #ifdef USE_RGB_COLOR
393  uint32 _mouseKeyColor;
394 #else
395  byte _mouseKeyColor;
396 #endif
397  bool _disableMouseKeyColor;
398  byte _mappedMouseKeyColor;
399  bool _cursorDontScale;
400  bool _cursorPaletteDisabled;
401  SDL_Surface *_mouseOrigSurface;
402  SDL_Surface *_mouseSurface;
403 
404  // Shake mode
405  // This is always set to 0 when building with SDL2.
406  int _currentShakeXOffset;
407  int _currentShakeYOffset;
408 
409  // Palette data
410  SDL_Color *_currentPalette;
411  uint _paletteDirtyStart, _paletteDirtyEnd;
412 
413  SDL_Color *_overlayPalette;
414  bool _isInOverlayPalette;
415 
416  // Cursor palette data
417  SDL_Color *_cursorPalette;
418 
424 
425 #ifdef USE_SDL_DEBUG_FOCUSRECT
426  bool _enableFocusRectDebugCode;
427  bool _enableFocusRect;
428  Common::Rect _focusRect;
429 #endif
430 
431  virtual void addDirtyRect(int x, int y, int w, int h, bool inOverlay, bool realCoordinates = false);
432 
433  virtual void drawMouse();
434  virtual void undrawMouse();
435  virtual void blitCursor();
436 
437  virtual void internUpdateScreen();
438  virtual void updateScreen(SDL_Rect *dirtyRectList, int actualDirtyRects);
439 
440  virtual bool loadGFXMode();
441  virtual void unloadGFXMode();
442  virtual bool hotswapGFXMode();
443 
444  virtual void setAspectRatioCorrection(bool enable);
445  void setFilteringMode(bool enable);
446  void setVSync(bool enable);
447 
448  bool saveScreenshot(const Common::Path &filename) const override;
449  virtual void setGraphicsModeIntern();
450  virtual void getDefaultResolution(uint &w, uint &h);
451 
452 private:
453  void setFullscreenMode(bool enable);
454  void handleScalerHotkeys(uint mode, int factor);
455 
460  Common::Point convertOverlayToGame(const int x, const int y) const {
461  if (getOverlayWidth() == 0 || getOverlayHeight() == 0) {
462  error("convertOverlayToGame called without a valid overlay");
463  }
464 
465  return Common::Point(x * getWidth() / getOverlayWidth(),
466  y * getHeight() / getOverlayHeight());
467  }
468 
473  Common::Point convertGameToOverlay(const int x, const int y) const {
474  if (getWidth() == 0 || getHeight() == 0) {
475  error("convertGameToOverlay called without a valid overlay");
476  }
477 
478  return Common::Point(x * getOverlayWidth() / getWidth(),
479  y * getOverlayHeight() / getHeight());
480  }
481 
488  bool _needRestoreAfterOverlay;
489  bool _prevForceRedraw;
490  bool _prevCursorNeedsRedraw;
491 };
492 
493 #endif
Definition: surfacesdl-graphics.h:369
bool notifyEvent(const Common::Event &event) override
int getGameRenderScale() const override
Definition: surfacesdl-graphics.h:185
Definition: surfacesdl-graphics.h:268
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:423
bool gameNeedsAspectRatioCorrection() const override
Definition: surfacesdl-graphics.h:182
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: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
Graphics::PixelFormat convertSDLPixelFormat(SDL_PixelFormat *in) const
Definition: sdl-window.h:30