ScummVM API documentation
atari-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_ATARI_H
23 #define BACKENDS_GRAPHICS_ATARI_H
24 
25 #include "backends/graphics/graphics.h"
26 #include "common/events.h"
27 
28 #include <mint/osbind.h>
29 #include <mint/ostruct.h>
30 #include <unordered_set>
31 
32 #include "common/rect.h"
33 #include "graphics/surface.h"
34 
35 template<>
36 struct std::hash<Common::Rect>
37 {
38  std::size_t operator()(Common::Rect const& rect) const noexcept
39  {
40  return 31 * (31 * (31 * rect.left + rect.top) + rect.right) + rect.bottom;
41  }
42 };
43 
45 
47 public:
49  virtual ~AtariGraphicsManager();
50 
51  bool hasFeature(OSystem::Feature f) const override;
52  void setFeatureState(OSystem::Feature f, bool enable) override;
53  bool getFeatureState(OSystem::Feature f) const override;
54 
55  const OSystem::GraphicsMode *getSupportedGraphicsModes() const override {
56  static const OSystem::GraphicsMode graphicsModes[] = {
57  { "direct", "Direct rendering", (int)GraphicsMode::DirectRendering },
58  { "single", "Single buffering", (int)GraphicsMode::SingleBuffering },
59  { "triple", "Triple buffering", (int)GraphicsMode::TripleBuffering },
60  { nullptr, nullptr, 0 }
61  };
62  return graphicsModes;
63  }
64  int getDefaultGraphicsMode() const override { return (int)GraphicsMode::TripleBuffering; }
65  bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
66  int getGraphicsMode() const override { return (int)_currentState.mode; }
67 
68  void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) override;
69 
70  int getScreenChangeID() const override { return 0; }
71 
72  void beginGFXTransaction() override;
73  OSystem::TransactionError endGFXTransaction() override;
74 
75  int16 getHeight() const override { return _currentState.height; }
76  int16 getWidth() const override { return _currentState.width; }
77  void setPalette(const byte *colors, uint start, uint num) override;
78  void grabPalette(byte *colors, uint start, uint num) const override;
79  void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
80  Graphics::Surface *lockScreen() override;
81  void unlockScreen() override;
82  void fillScreen(uint32 col) override;
83  void fillScreen(const Common::Rect &r, uint32 col) override;
84  void updateScreen() override;
85  void setShakePos(int shakeXOffset, int shakeYOffset) override;
86  void setFocusRectangle(const Common::Rect& rect) override {}
87  void clearFocusRectangle() override {}
88 
89  void showOverlay(bool inGUI) override;
90  void hideOverlay() override;
91  bool isOverlayVisible() const override { return _overlayVisible; }
92  Graphics::PixelFormat getOverlayFormat() const override;
93  void clearOverlay() override;
94  void grabOverlay(Graphics::Surface &surface) const override;
95  void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
96  int16 getOverlayHeight() const override { return 480; }
97  int16 getOverlayWidth() const override { return _vgaMonitor ? 640 : 640*1.2; }
98 
99  bool showMouse(bool visible) override;
100  void warpMouse(int x, int y) override;
101  void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor,
102  bool dontScale = false, const Graphics::PixelFormat *format = NULL, const byte *mask = NULL) override;
103  void setCursorPalette(const byte *colors, uint start, uint num) override;
104 
105  Common::Point getMousePosition() const { return _cursor.getPosition(); }
106  void updateMousePosition(int deltaX, int deltaY);
107 
108  bool notifyEvent(const Common::Event &event) override;
109  Common::Keymap *getKeymap() const;
110 
111 protected:
112  typedef void* (*AtariMemAlloc)(size_t bytes);
113  typedef void (*AtariMemFree)(void *ptr);
114 
115  void allocateSurfaces();
116  void freeSurfaces();
117 
118  enum class GraphicsMode : int {
119  DirectRendering = 0,
120  SingleBuffering = 1,
121  TripleBuffering = 3
122  };
123 
124  struct GraphicsState {
125  GraphicsState(GraphicsMode mode_)
126  : mode(mode_)
127  , width(0)
128  , height(0) {
129  }
130 
131  GraphicsMode mode;
132  int width;
133  int height;
134  Graphics::PixelFormat format;
135  };
136  GraphicsState _pendingState{ (GraphicsMode)getDefaultGraphicsMode() };
137 
138 private:
139  using DirtyRects = std::unordered_set<Common::Rect>;
140 
141  enum CustomEventAction {
142  kActionToggleAspectRatioCorrection = 100,
143  };
144 
145  enum SteTtRezValue {
146  kRezValueSTLow = 0, // 320x200@4bpp, ST palette
147  kRezValueSTMid = 1, // 640x200@2bpp, ST palette
148  kRezValueSTHigh = 2, // 640x400@1bpp, ST palette
149  kRezValueTTLow = 7, // 320x480@8bpp, TT palette
150  kRezValueTTMid = 4, // 640x480@4bpp, TT palette
151  kRezValueTTHigh = 6 // 1280x960@1bpp, TT palette
152  };
153 
154  int16 getMaximumScreenHeight() const { return 480; }
155  int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 640 : 640*1.2); }
156 
157  template <bool directRendering>
158  bool updateScreenInternal(const Graphics::Surface &srcSurface);
159 
160  void copyRectToScreenInternal(const void *buf, int pitch, int x, int y, int w, int h,
161  const Graphics::PixelFormat &format, bool directRendering, bool tripleBuffer);
162 
163  int getBitsPerPixel(const Graphics::PixelFormat &format) const;
164 
165  bool isOverlayDirectRendering() const;
166 
167  virtual AtariMemAlloc getStRamAllocFunc() const {
168  return [](size_t bytes) { return (void*)Mxalloc(bytes, MX_STRAM); };
169  }
170  virtual AtariMemFree getStRamFreeFunc() const {
171  return [](void *ptr) { Mfree(ptr); };
172  }
173 
174  virtual void copyRectToSurface(Graphics::Surface &dstSurface, int dstBitsPerPixel, const Graphics::Surface &srcSurface,
175  int destX, int destY,
176  const Common::Rect &subRect) const {
177  dstSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
178  }
179 
180  virtual void drawMaskedSprite(Graphics::Surface &dstSurface, int dstBitsPerPixel,
181  const Graphics::Surface &srcSurface, const Graphics::Surface &srcMask,
182  int destX, int destY,
183  const Common::Rect &subRect) = 0;
184 
185  virtual Common::Rect alignRect(int x, int y, int w, int h) const = 0;
186 
187  Common::Rect alignRect(const Common::Rect &rect) const {
188  return alignRect(rect.left, rect.top, rect.width(), rect.height());
189  }
190 
191  void cursorPositionChanged() {
192  if (_overlayVisible) {
193  _screen[OVERLAY_BUFFER]->cursorPositionChanged = true;
194  } else {
195  _screen[FRONT_BUFFER]->cursorPositionChanged
196  = _screen[BACK_BUFFER1]->cursorPositionChanged
197  = _screen[BACK_BUFFER2]->cursorPositionChanged
198  = true;
199  }
200  }
201 
202  void cursorSurfaceChanged() {
203  if (_overlayVisible) {
204  _screen[OVERLAY_BUFFER]->cursorSurfaceChanged = true;
205  } else {
206  _screen[FRONT_BUFFER]->cursorSurfaceChanged
207  = _screen[BACK_BUFFER1]->cursorSurfaceChanged
208  = _screen[BACK_BUFFER2]->cursorSurfaceChanged
209  = true;
210  }
211  }
212 
213  void cursorVisibilityChanged() {
214  if (_overlayVisible) {
215  _screen[OVERLAY_BUFFER]->cursorVisibilityChanged = true;
216  } else {
217  _screen[FRONT_BUFFER]->cursorVisibilityChanged
218  = _screen[BACK_BUFFER1]->cursorVisibilityChanged
219  = _screen[BACK_BUFFER2]->cursorVisibilityChanged
220  = true;
221  }
222  }
223 
224  int getOverlayPaletteSize() const {
225 #ifndef DISABLE_FANCY_THEMES
226  return _tt ? 16 : 256;
227 #else
228  return 16;
229 #endif
230  }
231 
232  bool _vgaMonitor = true;
233  bool _tt = false;
234  bool _aspectRatioCorrection = false;
235  bool _oldAspectRatioCorrection = false;
236  bool _checkUnalignedPitch = false;
237 
238  GraphicsState _currentState{ (GraphicsMode)getDefaultGraphicsMode() };
239 
240  enum PendingScreenChange {
241  kPendingScreenChangeNone = 0,
242  kPendingScreenChangeMode = 1<<0,
243  kPendingScreenChangeScreen = 1<<1,
244  kPendingScreenChangePalette = 1<<2
245  };
246  int _pendingScreenChange = kPendingScreenChangeNone;
247 
248  enum {
249  FRONT_BUFFER,
250  BACK_BUFFER1,
251  BACK_BUFFER2,
252  OVERLAY_BUFFER,
253  BUFFER_COUNT
254  };
255 
256  class Palette {
257  public:
258  void clear() {
259  memset(data, 0, sizeof(data));
260  }
261 
262  uint16 *const tt = reinterpret_cast<uint16*>(data);
263  _RGB *const falcon = reinterpret_cast<_RGB*>(data);
264 
265  private:
266  byte data[256*4] = {};
267  };
268 
269  struct Screen {
270  Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette);
271  ~Screen();
272 
273  void reset(int width, int height, int bitsPerPixel);
274  // must be called before any rectangle drawing
275  void addDirtyRect(const Graphics::Surface &srcSurface, const Common::Rect &rect, bool directRendering);
276 
277  void clearDirtyRects() {
278  dirtyRects.clear();
279  fullRedraw = false;
280  }
281 
282  void storeBackground(const Common::Rect &rect);
283  void restoreBackground(const Common::Rect &rect);
284 
285  Graphics::Surface surf;
286  const Palette *palette;
287  bool cursorPositionChanged = true;
288  bool cursorSurfaceChanged = true;
289  bool cursorVisibilityChanged = false;
290  DirtyRects dirtyRects;
291  bool fullRedraw = false;
292  Common::Rect oldCursorRect;
293  int rez = -1;
294  int mode = -1;
295  Graphics::Surface *const offsettedSurf = &_offsettedSurf;
296 
297  int oldScreenSurfaceWidth = -1;
298  int oldScreenSurfaceHeight = -1;
299  int oldScreenSurfacePitch = -1;
300  int oldOffsettedSurfaceWidth = -1;
301  int oldOffsettedSurfaceHeight = -1;
302 
303  private:
304  static constexpr size_t ALIGN = 16; // 16 bytes
305 
306  const AtariGraphicsManager *_manager;
307 
308  Graphics::Surface _offsettedSurf;
309  // used by direct rendering
310  Graphics::Surface _cursorBackgroundSurf;
311  };
312  Screen *_screen[BUFFER_COUNT] = {};
313  Screen *_workScreen = nullptr;
314  Screen *_oldWorkScreen = nullptr; // used in hideOverlay()
315 
316  Graphics::Surface _chunkySurface;
317 
318  bool _overlayVisible = false;
319  Graphics::Surface _overlaySurface;
320 
321  struct Cursor {
322  void update(const Graphics::Surface &screen, bool isModified);
323 
324  bool visible = false;
325 
326  // position
327  Common::Point getPosition() const {
328  return Common::Point(_x, _y);
329  }
330  void setPosition(int x, int y) {
331  _x = x;
332  _y = y;
333  }
334  void updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen);
335  void swap() {
336  const int tmpX = _oldX;
337  const int tmpY = _oldY;
338 
339  _oldX = _x;
340  _oldY = _y;
341 
342  _x = tmpX;
343  _y = tmpY;
344  }
345 
346  // surface
347  void setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor);
348  template <bool isClut8>
349  void convertTo(const Graphics::PixelFormat &format);
350  Graphics::Surface surface;
351  Graphics::Surface surfaceMask;
352 
353  // rects (valid only if !outOfScreen)
354  bool isClipped() const {
355  return outOfScreen ? false : _width != srcRect.width();
356  }
357  bool outOfScreen = true;
358  Common::Rect srcRect;
359  Common::Rect dstRect;
360 
361  // palette (only used for the overlay)
362  byte palette[256*3] = {};
363 
364  private:
365  int _x = -1, _y = -1;
366  int _oldX = -1, _oldY = -1;
367 
368  // related to 'surface'
369  const byte *_buf = nullptr;
370  int _width;
371  int _height;
372  int _hotspotX;
373  int _hotspotY;
374  uint32 _keycolor;
375 
376  int _rShift, _gShift, _bShift;
377  int _rMask, _gMask, _bMask;
378  };
379  Cursor _cursor;
380 
381  Palette _palette;
382  Palette _overlayPalette;
383 };
384 
385 #endif
Definition: keymap.h:66
Definition: surface.h:66
Definition: system.h:788
Definition: pixelformat.h:138
Definition: system.h:739
Feature
Definition: system.h:417
int16 right
Definition: rect.h:146
Definition: rect.h:144
Definition: events.h:317
int16 width() const
Definition: rect.h:191
TransactionError
Definition: system.h:1148
Definition: events.h:198
Definition: algorithm.h:29
Definition: rect.h:45
int16 left
Definition: rect.h:145
Definition: graphics.h:36
Definition: atari-graphics.h:46
void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height)
int16 height() const
Definition: rect.h:192
Definition: atari-graphics.h:124