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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 //=============================================================================
24 //
25 // Implementation base for graphics driver
26 //
27 //=============================================================================
28 
29 #ifndef AGS_ENGINE_GFX_GFX_DRIVER_BASE_H
30 #define AGS_ENGINE_GFX_GFX_DRIVER_BASE_H
31 
32 #include "ags/lib/std/vector.h"
33 #include "ags/engine/gfx/ddb.h"
34 #include "ags/engine/gfx/graphics_driver.h"
35 #include "ags/shared/util/scaling.h"
36 
37 namespace AGS3 {
38 namespace AGS {
39 namespace Engine {
40 
41 using Shared::Bitmap;
42 using Shared::PlaneScaling;
43 
44 // Sprite batch, defines viewport and an optional model transformation for the list of sprites
45 struct SpriteBatchDesc {
46 	// View rectangle for positioning and clipping, in resolution coordinates
47 	// (this may be screen or game frame resolution, depending on circumstances)
48 	Rect                     Viewport;
49 	// Optional model transformation, to be applied to each sprite
50 	SpriteTransform          Transform;
51 	// Global node offset applied to the whole batch as the last transform
52 	Point                    Offset;
53 	// Global node flip applied to the whole batch as the last transform
54 	GlobalFlipType           Flip;
55 	// Optional bitmap to draw sprites upon. Used exclusively by the software rendering mode.
56 	PBitmap                  Surface;
57 
SpriteBatchDescSpriteBatchDesc58 	SpriteBatchDesc() : Flip(kFlip_None) {
59 	}
60 	SpriteBatchDesc(const Rect viewport, const SpriteTransform &transform, const Point offset = Point(),
61 	                GlobalFlipType flip = kFlip_None, PBitmap surface = nullptr)
ViewportSpriteBatchDesc62 		: Viewport(viewport)
63 		, Transform(transform)
64 		, Offset(offset)
65 		, Flip(flip)
66 		, Surface(surface) {
67 	}
68 };
69 
70 typedef std::vector<SpriteBatchDesc> SpriteBatchDescs;
71 
72 // The single sprite entry in the render list
73 template<class T_DDB>
74 struct SpriteDrawListEntry {
75 	T_DDB *bitmap; // TODO: use shared pointer?
76 	int x, y; // sprite position, in camera coordinates
77 	bool skip;
78 
SpriteDrawListEntrySpriteDrawListEntry79 	SpriteDrawListEntry()
80 		: bitmap(nullptr)
81 		, x(0)
82 		, y(0)
83 		, skip(false) {
84 	}
85 
86 	SpriteDrawListEntry(T_DDB *ddb, int x_ = 0, int y_ = 0)
bitmapSpriteDrawListEntry87 		: bitmap(ddb)
88 		, x(x_)
89 		, y(y_)
90 		, skip(false) {
91 	}
92 };
93 
94 
95 // GraphicsDriverBase - is the parent class for all graphics drivers in AGS,
96 // that incapsulates the most common functionality.
97 class GraphicsDriverBase : public IGraphicsDriver {
98 public:
99 	GraphicsDriverBase();
100 
101 	bool        IsModeSet() const override;
102 	bool        IsNativeSizeValid() const override;
103 	bool        IsRenderFrameValid() const override;
104 	DisplayMode GetDisplayMode() const override;
105 	Size        GetNativeSize() const override;
106 	Rect        GetRenderDestination() const override;
107 
108 	void        BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform,
109 	                             const Point offset = Point(), GlobalFlipType flip = kFlip_None, PBitmap surface = nullptr) override;
110 	void        ClearDrawLists() override;
111 
SetCallbackForPolling(GFXDRV_CLIENTCALLBACK callback)112 	void        SetCallbackForPolling(GFXDRV_CLIENTCALLBACK callback) override {
113 		_pollingCallback = callback;
114 	}
SetCallbackToDrawScreen(GFXDRV_CLIENTCALLBACK callback,GFXDRV_CLIENTCALLBACK post_callback)115 	void        SetCallbackToDrawScreen(GFXDRV_CLIENTCALLBACK callback, GFXDRV_CLIENTCALLBACK post_callback) override {
116 		_drawScreenCallback = callback;
117 		_drawPostScreenCallback = post_callback;
118 	}
SetCallbackOnInit(GFXDRV_CLIENTCALLBACKINITGFX callback)119 	void        SetCallbackOnInit(GFXDRV_CLIENTCALLBACKINITGFX callback) override {
120 		_initGfxCallback = callback;
121 	}
SetCallbackForNullSprite(GFXDRV_CLIENTCALLBACKXY callback)122 	void        SetCallbackForNullSprite(GFXDRV_CLIENTCALLBACKXY callback) override {
123 		_nullSpriteCallback = callback;
124 	}
125 
126 protected:
127 	// Called after graphics driver was initialized for use for the first time
128 	virtual void OnInit();
129 	// Called just before graphics mode is going to be uninitialized and its
130 	// resources released
131 	virtual void OnUnInit();
132 	// Called after new mode was successfully initialized
133 	virtual void OnModeSet(const DisplayMode &mode);
134 	// Called when the new native size is set
135 	virtual void OnSetNativeRes(const GraphicResolution &native_res);
136 	// Called before display mode is going to be released
137 	virtual void OnModeReleased();
138 	// Called when new render frame is set
139 	virtual void OnSetRenderFrame(const Rect &dst_rect);
140 	// Called when the new filter is set
141 	virtual void OnSetFilter();
142 	// Initialize sprite batch and allocate necessary resources
143 	virtual void InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) = 0;
144 	// Clears sprite lists
145 	virtual void ResetAllBatches() = 0;
146 
147 	void         OnScalingChanged();
148 
149 	DisplayMode         _mode;          // display mode settings
150 	Rect                _srcRect;       // rendering source rect
151 	int                 _srcColorDepth; // rendering source color depth (in bits per pixel)
152 	Rect                _dstRect;       // rendering destination rect
153 	Rect                _filterRect;    // filter scaling destination rect (before final scaling)
154 	PlaneScaling        _scaling;       // native -> render dest coordinate transformation
155 
156 	// Callbacks
157 	GFXDRV_CLIENTCALLBACK _pollingCallback;
158 	GFXDRV_CLIENTCALLBACK _drawScreenCallback;
159 	GFXDRV_CLIENTCALLBACK _drawPostScreenCallback;
160 	GFXDRV_CLIENTCALLBACKXY _nullSpriteCallback;
161 	GFXDRV_CLIENTCALLBACKINITGFX _initGfxCallback;
162 
163 	// Sprite batch parameters
164 	SpriteBatchDescs _spriteBatchDesc; // sprite batches list
165 	size_t _actSpriteBatch; // active batch index
166 };
167 
168 
169 
170 // Generic TextureTile base
171 struct TextureTile {
172 	int x, y;
173 	int width, height;
174 };
175 
176 // Parent class for the video memory DDBs
177 class VideoMemDDB : public IDriverDependantBitmap {
178 public:
GetWidth()179 	int GetWidth() override {
180 		return _width;
181 	}
GetHeight()182 	int GetHeight() override {
183 		return _height;
184 	}
GetColorDepth()185 	int GetColorDepth() override {
186 		return _colDepth;
187 	}
188 
189 	int _width, _height;
190 	int _colDepth;
191 	bool _opaque; // no mask color
192 };
193 
194 // VideoMemoryGraphicsDriver - is the parent class for the graphic drivers
195 // which drawing method is based on passing the sprite stack into GPU,
196 // rather than blitting to flat screen bitmap.
197 class VideoMemoryGraphicsDriver : public GraphicsDriverBase {
198 public:
199 	VideoMemoryGraphicsDriver();
200 	~VideoMemoryGraphicsDriver() override;
201 
202 	bool UsesMemoryBackBuffer() override;
203 	Bitmap *GetMemoryBackBuffer() override;
204 	void SetMemoryBackBuffer(Bitmap *backBuffer) override;
205 	Bitmap *GetStageBackBuffer(bool mark_dirty) override;
206 	bool GetStageMatrixes(RenderMatrixes &rm) override;
207 	IDriverDependantBitmap *CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, bool opaque = false) override;
208 
209 protected:
210 	// Creates a "raw" DDB, without pixel initialization
211 	virtual IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque = false) = 0;
212 
213 	// Stage screens are raw bitmap buffers meant to be sent to plugins on demand
214 	// at certain drawing stages. If used at least once these buffers are then
215 	// rendered as additional sprites in their respected order.
216 	PBitmap CreateStageScreen(size_t index, const Size &sz);
217 	PBitmap GetStageScreen(size_t index);
218 	void DestroyAllStageScreens();
219 	// Use engine callback to acquire replacement for the null sprite;
220 	// returns true if the sprite was provided onto the virtual screen,
221 	// and false if this entry should be skipped.
222 	bool DoNullSpriteCallback(int x, int y);
223 
224 	// Prepare and get fx item from the pool
225 	IDriverDependantBitmap *MakeFx(int r, int g, int b);
226 	// Resets fx pool counter
227 	void ResetFxPool();
228 	// Disposes all items in the fx pool
229 	void DestroyFxPool();
230 
231 	// Prepares bitmap to be applied to the texture, copies pixels to the provided buffer
232 	void BitmapToVideoMem(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile, const VideoMemDDB *target,
233 	                      char *dst_ptr, const int dst_pitch, const bool usingLinearFiltering);
234 	// Same but optimized for opaque source bitmaps which ignore transparent "mask color"
235 	void BitmapToVideoMemOpaque(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile, const VideoMemDDB *target,
236 	                            char *dst_ptr, const int dst_pitch);
237 
238 	// Stage virtual screen is used to let plugins draw custom graphics
239 	// in between render stages (between room and GUI, after GUI, and so on)
240 	PBitmap _stageVirtualScreen;
241 	IDriverDependantBitmap *_stageVirtualScreenDDB;
242 	// Stage matrixes are used to let plugins with hardware acceleration know model matrix;
243 	// these matrixes are filled compatible with each given renderer
244 	RenderMatrixes _stageMatrixes;
245 
246 	// Color component shifts in video bitmap format (set by implementations)
247 	int _vmem_a_shift_32;
248 	int _vmem_r_shift_32;
249 	int _vmem_g_shift_32;
250 	int _vmem_b_shift_32;
251 
252 private:
253 	// Virtual screens for rendering stages (sprite batches)
254 	std::vector<PBitmap> _stageScreens;
255 	// Flag which indicates whether stage screen was drawn upon during engine
256 	// callback and has to be inserted into sprite stack.
257 	bool _stageScreenDirty;
258 
259 	// Fx quads pool (for screen overlay effects)
260 	struct ScreenFx {
261 		Bitmap *Raw = nullptr;
262 		IDriverDependantBitmap *DDB = nullptr;
263 		int Red = -1;
264 		int Green = -1;
265 		int Blue = -1;
266 	};
267 	std::vector<ScreenFx> _fxPool;
268 	size_t _fxIndex; // next free pool item
269 };
270 
271 } // namespace Engine
272 } // namespace AGS
273 } // namespace AGS3
274 
275 #endif
276