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 // as futureoptimization one could actually store these instead of converting to a surface
126 // this will reduce memory usage and might reduce render times on software renderers
127 class ImageV1 {
128 public:
130 
131  inline Common::Point drawOffset() const { return _drawOffset; }
132 
133  void render(Graphics::ManagedSurface &target, Common::Point offset, byte alpha = 255) const;
134  Graphics::ManagedSurface *render(byte alpha = 255) const;
135 
136 private:
137  struct Segment {
138  uint16 _xOffset, _width;
139  uint32 _dataOffset;
140  };
141  struct Line { // indices into _segments
142  uint _start, _end;
143  };
144 
145  Common::Point _drawOffset, _size;
146  Common::Array<byte> _pixels;
147  Common::Array<byte> _palette;
148  Common::Array<Segment> _segments;
149  Common::Array<Line> _lines;
150 };
151 
152 enum class AnimationFolder {
153  Animations,
154  Masks,
155  Backgrounds
156 };
157 
160  _center,
161  _offset;
162  uint32 _duration;
163 };
164 
177 protected:
178  AnimationBase(GameFileReference fileRef, AnimationFolder folder = AnimationFolder::Animations);
179  ~AnimationBase();
180 
181  void load();
182  void freeImages();
183  void setToEmpty();
184  void readV1(Common::SeekableReadStream &stream);
185  void readV2(Common::SeekableReadStream &stream);
186  void readV3(Common::SeekableReadStream &stream);
187  void createIndexMappingV1and2(const Common::Array<byte> &spriteOrder);
188  void readFramesV1and2(Common::SeekableReadStream &stream, uint frameCount, uint spriteCount);
189  Graphics::ManagedSurface *readImageV3(Common::SeekableReadStream &stream) const;
190  Common::Point imageSize(int32 imageI) const;
191  inline bool isLoaded() const { return _isLoaded; }
192 
193  static void fullBlend(
194  const Graphics::ManagedSurface &source,
195  Graphics::ManagedSurface &destination,
196  int offsetX,
197  int offsetY);
198 
199  static constexpr const uint kMaxSpriteIDs = 256;
200  static constexpr const uint kMaxSpriteIDsV1 = 8;
201  GameFileReference _fileRef;
202  AnimationFolder _folder;
203  bool _isLoaded = false;
204  uint32 _totalDuration = 0;
205 
206  int32 _spriteIndexMapping[kMaxSpriteIDs] = { 0 };
209  _spriteBases;
210  Common::Array<bool> _spriteEnabled;
213  Common::Array<Common::Point> _imageOffsets;
214 };
215 
220 class Animation : private AnimationBase {
221 public:
222  Animation(GameFileReference fileRef, AnimationFolder folder = AnimationFolder::Animations);
223 
224  void load();
225  void freeImages();
226 
227  using AnimationBase::isLoaded;
228  inline uint spriteCount() const { return _spriteBases.size(); }
229  inline uint frameCount() const { return _frames.size(); }
230  inline uint32 frameDuration(int32 frameI) const { return _frames[frameI]._duration; }
231  inline Common::Point frameCenter(int32 frameI) const { return _frames[frameI]._center; }
232  inline uint32 totalDuration() const { return _totalDuration; }
233  inline uint8 &premultiplyAlpha() { return _premultiplyAlpha; }
234  Common::Rect frameBounds(int32 frameI) const;
235  Common::Point totalFrameOffset(int32 frameI) const;
236  int32 frameAtTime(uint32 time) const;
237  int32 imageIndex(int32 frameI, int32 spriteI) const;
238  using AnimationBase::imageSize;
239  void outputRect2D(int32 frameI, float scale, Math::Vector2d &topLeft, Math::Vector2d &size) const;
240  void outputRect3D(int32 frameI, float scale, Math::Vector3d &topLeft, Math::Vector2d &size) const;
241 
242  void overrideTexture(const Graphics::ManagedSurface &surface);
243 
244  void draw2D(
245  int32 frameI,
246  Math::Vector2d topLeft,
247  float scale,
248  BlendMode blendMode,
249  Color color);
250  void draw3D(
251  int32 frameI,
252  Math::Vector3d topLeft,
253  float scale,
254  BlendMode blendMode,
255  Color color);
256  void drawEffect(
257  int32 frameI,
258  Math::Vector3d topLeft,
259  Math::Vector2d tiling,
260  Math::Vector2d texOffset,
261  BlendMode blendMode);
262 
263 private:
264  Common::Rect spriteBounds(int32 frameI, int32 spriteI) const;
265  Common::Rect maxFrameBounds() const;
266  void prerenderFrame(int32 frameI);
267 
268  int32_t _renderedFrameI = -1;
269  uint8 _premultiplyAlpha = 100,
270  _renderedPremultiplyAlpha = 255;
271 
272  Graphics::ManagedSurface _renderedSurface;
273  Common::ScopedPtr<ITexture> _renderedTexture;
274 };
275 
276 class Font : private AnimationBase {
277 public:
278  Font(GameFileReference fileRef);
279 
280  void load();
281  void freeImages();
282  void drawCharacter(byte ch, Common::Point center, Color color);
283 
284  using AnimationBase::isLoaded;
285  using AnimationBase::imageSize;
286  bool isVisibleChar(byte ch) const;
287  Common::Point characterSize(byte ch) const;
288  Common::Point spaceSize() const;
289  inline uint imageCount() const { return _images.size(); }
290 
291 private:
292  const byte _charToImage, _spaceImageI, _charSpacing;
293  Common::Array<Math::Vector2d> _texMins, _texMaxs;
295 };
296 
297 class Graphic {
298 public:
299  Graphic();
301  Graphic(const Graphic &other); // animation reference is taken, so keep other alive
302  Graphic(Graphic &&other) = default;
303  Graphic &operator=(const Graphic &other);
304  Graphic &operator=(Graphic &&other) = default;
305 
306  inline Common::Point &topLeft() { return _topLeft; }
307  inline int8 &order() { return _order; }
308  inline int16 &scale() { return _scale; }
309  inline float &depthScale() { return _depthScale; }
310  inline Color &color() { return _color; }
311  inline int32 &frameI() { return _frameI; }
312  inline uint32 &lastTime() { return _lastTime; }
313  inline bool isPaused() const { return _isPaused; }
314  inline bool hasAnimation() const { return _animation != nullptr; }
315  inline Animation &animation() {
316  assert(_animation != nullptr && _animation->isLoaded());
317  return *_animation;
318  }
319  inline uint8 &premultiplyAlpha() {
320  assert(_animation != nullptr);
321  return _animation->premultiplyAlpha();
322  }
323 
324  void loadResources();
325  void freeResources();
326  void update();
327  void start(bool looping);
328  void pause();
329  void reset();
330  void setAnimation(const GameFileReference &fileRef, AnimationFolder folder);
331  void setAnimation(Animation *animation);
332  void syncGame(Common::Serializer &serializer);
333 
334 private:
335  friend class AnimationDrawRequest;
336  friend class SpecialEffectDrawRequest;
337  Common::ScopedPtr<Animation> _ownedAnimation;
338  Animation *_animation = nullptr;
339  Common::Point _topLeft;
340  int16 _scale = kBaseScale;
341  int8 _order = 0;
342  Color _color = kWhite;
343 
344  bool _isPaused = true,
345  _isLooping = true;
346  uint32 _lastTime = 0;
347  int32 _frameI = -1;
348  float _depthScale = 1.0f;
349 };
350 
352 public:
353  IDrawRequest(int8 order);
354  virtual ~IDrawRequest() {}
355 
356  inline int8 order() const { return _order; }
357  virtual void draw() = 0;
358 
359 private:
360  const int8 _order;
361 };
362 
364 public:
366  Graphic &graphic,
367  bool is3D,
368  BlendMode blendMode,
369  float lodBias = 0.0f);
371  Animation *animation,
372  int32 frameI,
373  Math::Vector2d center,
374  int8 order
375  );
376 
377  void draw() override;
378 
379 private:
380  bool _is3D;
381  Animation *_animation;
382  int32 _frameI;
383  Math::Vector3d _topLeft;
384  float _scale;
385  Color _color;
386  BlendMode _blendMode;
387  float _lodBias;
388 };
389 
391 public:
393  Graphic &graphic,
394  Common::Point topLeft,
395  Common::Point bottomRight,
396  Math::Vector2d texOffset,
397  BlendMode blendMode);
398 
399  void draw() override;
400 
401 private:
402  Animation *_animation;
403  int32 _frameI;
404  Math::Vector3d _topLeft;
405  Math::Vector2d
406  _size,
407  _texOffset;
408  BlendMode _blendMode;
409 };
410 
412 public:
414  Font &font,
415  const char *text,
416  Common::Point pos,
417  int maxWidth,
418  bool centered,
419  Color color,
420  int8 order);
421 
422  inline Common::Point size() const { return { (int16)_width, (int16)_height }; }
423  void draw() override;
424 
425 private:
426  static constexpr uint kMaxLines = 12;
428 
429  Font &_font;
430  int _posY = 0, _height = 0, _width = 0;
431  Color _color;
432  Common::Span<TextLine> _lines;
433  Common::Span<int> _posX;
434  TextLine _allLines[kMaxLines];
435  int _allPosX[kMaxLines] = { 0 };
436 };
437 
438 enum class FadeType {
439  ToBlack,
440  ToWhite
441  // Originally there was a CrossFade, but it is unused for now and thus not implemented
442 };
443 
444 enum class PermanentFadeAction {
445  Nothing,
446  SetFaded,
447  UnsetFaded
448 };
449 
451 public:
452  FadeDrawRequest(FadeType type, float value, int8 order);
453 
454  void draw() override;
455 
456 private:
457  FadeType _type;
458  float _value;
459 };
460 
461 Task *fade(Process &process, FadeType fadeType,
462  float from, float to,
463  int32 duration, EasingType easingType,
464  int8 order,
465  PermanentFadeAction permanentFadeAction = PermanentFadeAction::Nothing);
466 
468 public:
469  BorderDrawRequest(Common::Rect rect, Color color);
470 
471  void draw() override;
472 
473 private:
474  Common::Rect _rect;
475  Color _color;
476 };
477 
479 public:
480  BumpAllocator(size_t pageSize);
481  ~BumpAllocator();
482 
483  template<typename T, typename... Args>
484  inline T *allocate(Args&&... args) {
485  return new(allocateRaw(sizeof(T), alignof(T))) T(Common::forward<Args>(args)...);
486  }
487  void *allocateRaw(size_t size, size_t align);
488  void deallocateAll();
489 
490 private:
491  void allocatePage();
492 
493  const size_t _pageSize;
494  size_t _pageI = 0, _used = 0;
495  Common::Array<void *> _pages;
496 };
497 
498 class DrawQueue {
499 public:
500  DrawQueue(IRenderer *renderer);
501 
502  template<typename T, typename... Args>
503  inline void add(Args&&... args) {
504  addRequest(_allocator.allocate<T>(Common::forward<Args>(args)...));
505  }
506  inline BumpAllocator &allocator() { return _allocator; }
507 
508  void clear();
509  void setLodBias(int8 orderFrom, int8 orderTo, float newLodBias);
510  void draw();
511 
512 private:
513  void addRequest(IDrawRequest *drawRequest);
514 
515  static constexpr const uint kMaxDrawRequestsPerOrder = 50;
516  IRenderer *const _renderer;
517  BumpAllocator _allocator;
518  IDrawRequest *_requestsPerOrder[kOrderCount][kMaxDrawRequestsPerOrder] = { { 0 } };
519  uint8 _requestsPerOrderCount[kOrderCount] = { 0 };
520  float _lodBiasPerOrder[kOrderCount] = { 0 };
521 };
522 
523 }
524 
525 #endif // ALCACHOFA_GRAPHICS_H
Definition: managed_surface.h:51
Definition: graphics.h:103
Definition: alcachofa.h:45
Definition: common.h:78
Definition: graphics.h:127
Definition: surface.h:67
Definition: scheduler.h:84
Definition: graphics.h:411
Definition: scheduler.h:164
Definition: graphics.h:297
Definition: pixelformat.h:138
Definition: graphics.h:450
Definition: rect.h:524
Definition: stream.h:745
Definition: graphics.h:220
Definition: ptr.h:572
Definition: serializer.h:79
Definition: graphics.h:74
Definition: graphics.h:363
Graphics::Surface * scale(const Graphics::Surface &srcImage, int xSize, int ySize)
Definition: graphics.h:478
Definition: graphics.h:176
T y
Definition: rect.h:49
References a game file either as path or as embedded byte range.
Definition: common.h:197
Definition: graphics.h:60
Definition: graphics.h:498
T x
Definition: rect.h:48
Definition: rect.h:144
Common::Array< int32 > _spriteOffsets
index offset per sprite and animation frame
Definition: graphics.h:208
const Surface & rawSurface() const
Definition: managed_surface.h:195
Definition: graphics.h:351
Definition: shape.h:118
Definition: graphics.h:276
Common::Point _offset
the offset is only used for drawing the animation frame
Definition: graphics.h:160
Definition: graphics.h:467
Common::Array< Graphics::ManagedSurface * > _images
will contain nullptr for fake images
Definition: graphics.h:212
Definition: graphics.h:390
Definition: graphics.h:158
Definition: span.h:691