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
36namespace Alcachofa {
37
50enum 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
58class Shape;
59
60class ITexture {
61public:
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
70private:
71 Common::Point _size;
72};
73
74class IRenderer {
75public:
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
103class IDebugRenderer : public virtual IRenderer {
104public:
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
127class ImageV1 {
128public:
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
136private:
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
152enum class AnimationFolder {
153 Animations,
154 Masks,
155 Backgrounds
156};
157
162 uint32 _duration;
163};
164
177protected:
178 AnimationBase(GameFileReference fileRef, AnimationFolder folder = AnimationFolder::Animations);
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 };
210 Common::Array<bool> _spriteEnabled;
213 Common::Array<Common::Point> _imageOffsets;
214};
215
220class Animation : private AnimationBase {
221public:
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
263private:
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
276class Font : private AnimationBase {
277public:
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
291private:
292 const byte _charToImage, _spaceImageI, _charSpacing;
293 Common::Array<Math::Vector2d> _texMins, _texMaxs;
295};
296
297class Graphic {
298public:
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
334private:
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
352public:
353 IDrawRequest(int8 order);
354 virtual ~IDrawRequest() {}
355
356 inline int8 order() const { return _order; }
357 virtual void draw() = 0;
358
359private:
360 const int8 _order;
361};
362
364public:
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
379private:
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
391public:
393 Graphic &graphic,
394 Common::Point topLeft,
395 Common::Point bottomRight,
396 Math::Vector2d texOffset,
397 BlendMode blendMode);
398
399 void draw() override;
400
401private:
402 Animation *_animation;
403 int32 _frameI;
404 Math::Vector3d _topLeft;
405 Math::Vector2d
406 _size,
407 _texOffset;
408 BlendMode _blendMode;
409};
410
412public:
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
425private:
426 static constexpr uint kMaxLines = 12;
428
429 Font &_font;
430 int _posY = 0, _height = 0, _width = 0;
431 Color _color;
433 Common::Span<int> _posX;
434 TextLine _allLines[kMaxLines];
435 int _allPosX[kMaxLines] = { 0 };
436};
437
438enum class FadeType {
439 ToBlack,
440 ToWhite
441 // Originally there was a CrossFade, but it is unused for now and thus not implemented
442};
443
444enum class PermanentFadeAction {
445 Nothing,
446 SetFaded,
447 UnsetFaded
448};
449
451public:
452 FadeDrawRequest(FadeType type, float value, int8 order);
453
454 void draw() override;
455
456private:
457 FadeType _type;
458 float _value;
459};
460
461Task *fade(Process &process, FadeType fadeType,
462 float from, float to,
463 int32 duration, EasingType easingType,
464 int8 order,
465 PermanentFadeAction permanentFadeAction = PermanentFadeAction::Nothing);
466
468public:
470
471 void draw() override;
472
473private:
474 Common::Rect _rect;
475 Color _color;
476};
477
479public:
480 BumpAllocator(size_t pageSize);
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
490private:
491 void allocatePage();
492
493 const size_t _pageSize;
494 size_t _pageI = 0, _used = 0;
496};
497
499public:
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
512private:
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: graphics.h:176
Common::Array< int32 > _spriteOffsets
index offset per sprite and animation frame
Definition: graphics.h:208
Common::Array< int32 > _spriteBases
base index per sprite
Definition: graphics.h:209
int32 _spriteIndexMapping[kMaxSpriteIDs]
establishes render order back-to-front
Definition: graphics.h:206
Common::Array< Graphics::ManagedSurface * > _images
will contain nullptr for fake images
Definition: graphics.h:212
Definition: graphics.h:363
Definition: graphics.h:220
Definition: graphics.h:467
Definition: graphics.h:478
Definition: graphics.h:498
Definition: graphics.h:450
Definition: graphics.h:276
Definition: graphics.h:297
void setAnimation(Animation *animation)
no memory ownership is given, but for prerendering it has to be mutable
Definition: graphics.h:103
Definition: graphics.h:351
Definition: graphics.h:74
Definition: graphics.h:60
Definition: graphics.h:127
Definition: scheduler.h:164
Definition: shape.h:118
Definition: graphics.h:390
Definition: graphics.h:411
size_type size() const
Definition: array.h:316
Definition: ptr.h:572
Definition: stream.h:745
Definition: serializer.h:80
Definition: span.h:691
Definition: managed_surface.h:51
const Surface & rawSurface() const
Definition: managed_surface.h:195
Definition: graphics.h:158
Common::Point _offset
the offset is only used for drawing the animation frame
Definition: graphics.h:161
Common::Point _center
the center is used for more than just drawing the animation frame
Definition: graphics.h:160
Definition: common.h:78
References a game file either as path or as embedded byte range.
Definition: common.h:197
Definition: scheduler.h:84
T y
Definition: rect.h:49
T x
Definition: rect.h:48
Definition: rect.h:144
Definition: rect.h:536
Definition: pixelformat.h:138
Definition: surface.h:67