ScummVM API documentation
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 ALCACHOFA_GRAPHICS_H
23 #define ALCACHOFA_GRAPHICS_H
24 
25 #include "common/ptr.h"
26 #include "common/stream.h"
27 #include "common/serializer.h"
28 #include "common/rect.h"
29 #include "common/span.h"
30 #include "math/vector2d.h"
31 #include "graphics/managed_surface.h"
32 
33 #include "alcachofa/camera.h"
34 #include "alcachofa/common.h"
35 
36 namespace Alcachofa {
37 
50 enum class BlendMode {
51  AdditiveAlpha, // Normal objects
52  Additive, // "Effect" objects, fades
53  Multiply, // Unused in Movie Adventure
54  Alpha, // Unused in Movie Adventure (used for debugging)
55  Tinted // Used for fonts
56 };
57 
58 class Shape;
59 
60 class ITexture {
61 public:
62  ITexture(Common::Point size);
63  virtual ~ITexture() {}
64 
65  virtual void update(const Graphics::Surface &surface) = 0;
66  inline void update(const Graphics::ManagedSurface &surface) { update(surface.rawSurface()); }
67 
68  inline Common::Point size() const { return _size; }
69 
70 private:
71  Common::Point _size;
72 };
73 
74 class IRenderer {
75 public:
76  virtual ~IRenderer() {}
77 
78  virtual Common::ScopedPtr<ITexture> createTexture(int32 w, int32 h, bool withMipmaps = true) = 0;
79  virtual Graphics::PixelFormat getPixelFormat() const = 0;
80  virtual bool requiresPoTTextures() const = 0;
81 
82  virtual void begin() = 0;
83  virtual void setTexture(ITexture *texture) = 0;
84  virtual void setBlendMode(BlendMode blendMode) = 0;
85  virtual void setLodBias(float lodBias) = 0;
86  virtual void setOutput(Graphics::Surface &surface) = 0;
87  virtual bool hasOutput() const = 0;
88  virtual void quad(
89  Math::Vector2d topLeft,
90  Math::Vector2d size,
91  Color color = kWhite,
92  Math::Angle rotation = Math::Angle(),
93  Math::Vector2d texMin = Math::Vector2d(0, 0),
94  Math::Vector2d texMax = Math::Vector2d(1, 1)) = 0;
95  virtual void end() = 0;
96 
97  static IRenderer *createOpenGLRenderer(Common::Point resolution);
98  static IRenderer *createOpenGLRendererClassic(Common::Point resolution);
99  static IRenderer *createOpenGLRendererShaders(Common::Point resolution);
100  static IRenderer *createTinyGLRenderer(Common::Point resolution);
101 };
102 
103 class IDebugRenderer : public virtual IRenderer {
104 public:
105  virtual void debugPolygon(
107  Color color = kDebugRed
108  ) = 0;
109  virtual void debugPolyline(
111  Color color = kDebugRed
112  ) = 0;
113 
114  virtual void debugShape(
115  const Shape &shape,
116  Color color = kDebugRed
117  );
118 
119  inline void debugPolyline(Common::Point a, Common::Point b, Color color = kDebugRed) {
120  Math::Vector2d points[] = { { (float)a.x, (float)a.y }, { (float)b.x, (float)b.y } };
121  debugPolygon({ points, 2 }, color);
122  }
123 };
124 
125 enum class AnimationFolder {
126  Animations,
127  Masks,
128  Backgrounds
129 };
130 
133  _center,
134  _offset;
135  uint32 _duration;
136 };
137 
150 protected:
151  AnimationBase(Common::String fileName, AnimationFolder folder = AnimationFolder::Animations);
152  ~AnimationBase();
153 
154  void load();
155  void loadMissingAnimation();
156  void freeImages();
157  Graphics::ManagedSurface *readImage(Common::SeekableReadStream &stream) const;
158  Common::Point imageSize(int32 imageI) const;
159  inline bool isLoaded() const { return _isLoaded; }
160 
161  static void fullBlend(
162  const Graphics::ManagedSurface &source,
163  Graphics::ManagedSurface &destination,
164  int offsetX,
165  int offsetY);
166 
167  static constexpr const uint kMaxSpriteIDs = 256;
168  Common::String _fileName;
169  AnimationFolder _folder;
170  bool _isLoaded = false;
171  uint32 _totalDuration = 0;
172 
173  int32 _spriteIndexMapping[kMaxSpriteIDs] = { 0 };
176  _spriteBases;
179  Common::Array<Common::Point> _imageOffsets;
180 };
181 
186 class Animation : private AnimationBase {
187 public:
188  Animation(Common::String fileName, AnimationFolder folder = AnimationFolder::Animations);
189 
190  void load();
191  void freeImages();
192 
193  using AnimationBase::isLoaded;
194  inline uint spriteCount() const { return _spriteBases.size(); }
195  inline uint frameCount() const { return _frames.size(); }
196  inline uint32 frameDuration(int32 frameI) const { return _frames[frameI]._duration; }
197  inline Common::Point frameCenter(int32 frameI) const { return _frames[frameI]._center; }
198  inline uint32 totalDuration() const { return _totalDuration; }
199  inline uint8 &premultiplyAlpha() { return _premultiplyAlpha; }
200  Common::Rect frameBounds(int32 frameI) const;
201  Common::Point totalFrameOffset(int32 frameI) const;
202  int32 frameAtTime(uint32 time) const;
203  int32 imageIndex(int32 frameI, int32 spriteI) const;
204  using AnimationBase::imageSize;
205  void outputRect2D(int32 frameI, float scale, Math::Vector2d &topLeft, Math::Vector2d &size) const;
206  void outputRect3D(int32 frameI, float scale, Math::Vector3d &topLeft, Math::Vector2d &size) const;
207 
208  void overrideTexture(const Graphics::ManagedSurface &surface);
209 
210  void draw2D(
211  int32 frameI,
212  Math::Vector2d topLeft,
213  float scale,
214  BlendMode blendMode,
215  Color color);
216  void draw3D(
217  int32 frameI,
218  Math::Vector3d topLeft,
219  float scale,
220  BlendMode blendMode,
221  Color color);
222  void drawEffect(
223  int32 frameI,
224  Math::Vector3d topLeft,
225  Math::Vector2d tiling,
226  Math::Vector2d texOffset,
227  BlendMode blendMode);
228 
229 private:
230  Common::Rect spriteBounds(int32 frameI, int32 spriteI) const;
231  Common::Rect maxFrameBounds() const;
232  void prerenderFrame(int32 frameI);
233 
234  int32_t _renderedFrameI = -1;
235  uint8 _premultiplyAlpha = 100,
236  _renderedPremultiplyAlpha = 255;
237 
238  Graphics::ManagedSurface _renderedSurface;
239  Common::ScopedPtr<ITexture> _renderedTexture;
240 };
241 
242 class Font : private AnimationBase {
243 public:
244  Font(Common::String fileName);
245 
246  void load();
247  void freeImages();
248  void drawCharacter(int32 imageI, Common::Point center, Color color);
249 
250  using AnimationBase::isLoaded;
251  using AnimationBase::imageSize;
252  inline uint imageCount() const { return _images.size(); }
253 
254 private:
255  Common::Array<Math::Vector2d> _texMins, _texMaxs;
257 };
258 
259 class Graphic {
260 public:
261  Graphic();
262  Graphic(Common::ReadStream &stream);
263  Graphic(const Graphic &other); // animation reference is taken, so keep other alive
264  Graphic &operator= (const Graphic &other);
265 
266  inline Common::Point &topLeft() { return _topLeft; }
267  inline int8 &order() { return _order; }
268  inline int16 &scale() { return _scale; }
269  inline float &depthScale() { return _depthScale; }
270  inline Color &color() { return _color; }
271  inline int32 &frameI() { return _frameI; }
272  inline uint32 &lastTime() { return _lastTime; }
273  inline bool isPaused() const { return _isPaused; }
274  inline bool hasAnimation() const { return _animation != nullptr; }
275  inline Animation &animation() {
276  assert(_animation != nullptr && _animation->isLoaded());
277  return *_animation;
278  }
279  inline uint8 &premultiplyAlpha() {
280  assert(_animation != nullptr);
281  return _animation->premultiplyAlpha();
282  }
283 
284  void loadResources();
285  void freeResources();
286  void update();
287  void start(bool looping);
288  void pause();
289  void reset();
290  void setAnimation(const Common::String &fileName, AnimationFolder folder);
291  void setAnimation(Animation *animation);
292  void syncGame(Common::Serializer &serializer);
293 
294 private:
295  friend class AnimationDrawRequest;
296  friend class SpecialEffectDrawRequest;
297  Common::ScopedPtr<Animation> _ownedAnimation;
298  Animation *_animation = nullptr;
299  Common::Point _topLeft;
300  int16 _scale = kBaseScale;
301  int8 _order = 0;
302  Color _color = kWhite;
303 
304  bool _isPaused = true,
305  _isLooping = true;
306  uint32 _lastTime = 0;
307  int32 _frameI = -1;
308  float _depthScale = 1.0f;
309 };
310 
312 public:
313  IDrawRequest(int8 order);
314  virtual ~IDrawRequest() {}
315 
316  inline int8 order() const { return _order; }
317  virtual void draw() = 0;
318 
319 private:
320  const int8 _order;
321 };
322 
324 public:
326  Graphic &graphic,
327  bool is3D,
328  BlendMode blendMode,
329  float lodBias = 0.0f);
331  Animation *animation,
332  int32 frameI,
333  Math::Vector2d center,
334  int8 order
335  );
336 
337  void draw() override;
338 
339 private:
340  bool _is3D;
341  Animation *_animation;
342  int32 _frameI;
343  Math::Vector3d _topLeft;
344  float _scale;
345  Color _color;
346  BlendMode _blendMode;
347  float _lodBias;
348 };
349 
351 public:
353  Graphic &graphic,
354  Common::Point topLeft,
355  Common::Point bottomRight,
356  Math::Vector2d texOffset,
357  BlendMode blendMode);
358 
359  void draw() override;
360 
361 private:
362  Animation *_animation;
363  int32 _frameI;
364  Math::Vector3d _topLeft;
365  Math::Vector2d
366  _size,
367  _texOffset;
368  BlendMode _blendMode;
369 };
370 
372 public:
374  Font &font,
375  const char *text,
376  Common::Point pos,
377  int maxWidth,
378  bool centered,
379  Color color,
380  int8 order);
381 
382  inline Common::Point size() const { return { (int16)_width, (int16)_height }; }
383  void draw() override;
384 
385 private:
386  static constexpr uint kMaxLines = 12;
388 
389  Font &_font;
390  int _posY, _height, _width;
391  Color _color;
392  Common::Span<TextLine> _lines;
393  Common::Span<int> _posX;
394  TextLine _allLines[kMaxLines];
395  int _allPosX[kMaxLines];
396 };
397 
398 enum class FadeType {
399  ToBlack,
400  ToWhite
401  // Originally there was a CrossFade, but it is unused for now and thus not implemented
402 };
403 
404 enum class PermanentFadeAction {
405  Nothing,
406  SetFaded,
407  UnsetFaded
408 };
409 
411 public:
412  FadeDrawRequest(FadeType type, float value, int8 order);
413 
414  void draw() override;
415 
416 private:
417  FadeType _type;
418  float _value;
419 };
420 
421 Task *fade(Process &process, FadeType fadeType,
422  float from, float to,
423  int32 duration, EasingType easingType,
424  int8 order,
425  PermanentFadeAction permanentFadeAction = PermanentFadeAction::Nothing);
426 
428 public:
429  BorderDrawRequest(Common::Rect rect, Color color);
430 
431  void draw() override;
432 
433 private:
434  Common::Rect _rect;
435  Color _color;
436 };
437 
439 public:
440  BumpAllocator(size_t pageSize);
441  ~BumpAllocator();
442 
443  template<typename T, typename... Args>
444  inline T *allocate(Args&&... args) {
445  return new(allocateRaw(sizeof(T), alignof(T))) T(Common::forward<Args>(args)...);
446  }
447  void *allocateRaw(size_t size, size_t align);
448  void deallocateAll();
449 
450 private:
451  void allocatePage();
452 
453  const size_t _pageSize;
454  size_t _pageI = 0, _used = 0;
455  Common::Array<void *> _pages;
456 };
457 
458 class DrawQueue {
459 public:
460  DrawQueue(IRenderer *renderer);
461 
462  template<typename T, typename... Args>
463  inline void add(Args&&... args) {
464  addRequest(_allocator.allocate<T>(Common::forward<Args>(args)...));
465  }
466  inline BumpAllocator &allocator() { return _allocator; }
467 
468  void clear();
469  void setLodBias(int8 orderFrom, int8 orderTo, float newLodBias);
470  void draw();
471 
472 private:
473  void addRequest(IDrawRequest *drawRequest);
474 
475  static constexpr const uint kMaxDrawRequestsPerOrder = 50;
476  IRenderer *const _renderer;
477  BumpAllocator _allocator;
478  IDrawRequest *_requestsPerOrder[kOrderCount][kMaxDrawRequestsPerOrder] = { { 0 } };
479  uint8 _requestsPerOrderCount[kOrderCount] = { 0 };
480  float _lodBiasPerOrder[kOrderCount] = { 0 };
481 };
482 
483 }
484 
485 #endif // ALCACHOFA_GRAPHICS_H
Definition: managed_surface.h:51
Definition: graphics.h:103
Definition: alcachofa.h:45
Definition: common.h:70
Definition: str.h:59
Definition: surface.h:67
Definition: scheduler.h:84
Definition: graphics.h:371
Definition: scheduler.h:164
Definition: graphics.h:259
Definition: pixelformat.h:138
Definition: graphics.h:410
Definition: rect.h:524
Definition: stream.h:745
Common::Array< uint32 > _spriteOffsets
index offset per sprite and animation frame
Definition: graphics.h:175
Definition: graphics.h:186
Definition: ptr.h:572
Definition: serializer.h:79
Definition: graphics.h:74
Definition: graphics.h:323
Graphics::Surface * scale(const Graphics::Surface &srcImage, int xSize, int ySize)
Definition: graphics.h:438
Definition: graphics.h:149
T y
Definition: rect.h:49
Definition: graphics.h:60
Definition: graphics.h:458
T x
Definition: rect.h:48
Definition: rect.h:144
const Surface & rawSurface() const
Definition: managed_surface.h:195
Definition: graphics.h:311
Definition: shape.h:118
Definition: graphics.h:242
Common::Point _offset
the offset is only used for drawing the animation frame
Definition: graphics.h:133
Definition: stream.h:385
Definition: graphics.h:427
Common::Array< Graphics::ManagedSurface * > _images
will contain nullptr for fake images
Definition: graphics.h:178
Definition: graphics.h:350
Definition: graphics.h:131
Definition: span.h:691