1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Implementation base for graphics driver
//
//=============================================================================
#ifndef AGS_ENGINE_GFX_GFX_DRIVER_BASE_H
#define AGS_ENGINE_GFX_GFX_DRIVER_BASE_H
#include "common/std/memory.h"
#include "common/std/map.h"
#include "common/std/vector.h"
#include "ags/engine/gfx/ddb.h"
#include "ags/shared/gfx/gfx_def.h"
#include "ags/engine/gfx/graphics_driver.h"
#include "ags/shared/util/scaling.h"
namespace AGS3 {
namespace AGS {
namespace Engine {
using Shared::Bitmap;
using Shared::PlaneScaling;
// Sprite batch, defines viewport and an optional model transformation for the list of sprites
struct SpriteBatchDesc {
uint32_t Parent = UINT32_MAX;
// View rectangle for positioning and clipping, in resolution coordinates
// (this may be screen or game frame resolution, depending on circumstances)
Rect Viewport;
// Optional model transformation, to be applied to each sprite
SpriteTransform Transform;
// Optional flip, applied to the whole batch as the last transform
Shared::GraphicFlip Flip = Shared::kFlip_None;
// Optional bitmap to draw sprites upon. Used exclusively by the software rendering mode.
PBitmap Surface;
// Optional filter flags; this lets to filter certain batches out during some operations,
// such as fading effects or making screenshots.
uint32_t FilterFlags = 0u;
SpriteBatchDesc() = default;
SpriteBatchDesc(uint32_t parent, const Rect viewport, const SpriteTransform & transform,
Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr, uint32_t filter_flags = 0)
: Parent(parent)
, Viewport(viewport)
, Transform(transform)
, Flip(flip)
, Surface(surface)
, FilterFlags(filter_flags) {
}
};
typedef std::vector<SpriteBatchDesc> SpriteBatchDescs;
// The single sprite entry in the render list
template<class T_DDB>
struct SpriteDrawListEntry {
T_DDB *ddb = nullptr; // TODO: use shared pointer?
uint32_t node = 0; // sprite batch / scene node index
int x = 0, y = 0; // sprite position, in local batch / node coordinates
bool skip = false;
SpriteDrawListEntry() = default;
SpriteDrawListEntry(T_DDB * ddb_, uint32_t node_, int x_, int y_)
: ddb(ddb_)
, node(node_)
, x(x_)
, y(y_)
, skip(false) {
}
};
// GraphicsDriverBase - is the parent class for all graphics drivers in AGS,
// that incapsulates the most common functionality.
class GraphicsDriverBase : public IGraphicsDriver {
public:
GraphicsDriverBase();
bool IsModeSet() const override;
bool IsNativeSizeValid() const override;
bool IsRenderFrameValid() const override;
DisplayMode GetDisplayMode() const override;
Size GetNativeSize() const override;
Rect GetRenderDestination() const override;
bool SetVsync(bool enabled) override;
bool GetVsync() const override;
void BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform,
Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr,
uint32_t filter_flags = 0) override;
void EndSpriteBatch() override;
void ClearDrawLists() override;
void SetCallbackForPolling(GFXDRV_CLIENTCALLBACK callback) override {
_pollingCallback = callback;
}
void SetCallbackToDrawScreen(GFXDRV_CLIENTCALLBACK callback, GFXDRV_CLIENTCALLBACK post_callback) override {
_drawScreenCallback = callback;
_drawPostScreenCallback = post_callback;
}
void SetCallbackOnInit(GFXDRV_CLIENTCALLBACKINITGFX callback) override {
_initGfxCallback = callback;
}
void SetCallbackOnSpriteEvt(GFXDRV_CLIENTCALLBACKEVT callback) override {
_spriteEvtCallback = callback;
}
protected:
// Special internal values, applied to DrawListEntry
static const uintptr_t DRAWENTRY_STAGECALLBACK = 0x0;
static const uintptr_t DRAWENTRY_FADE = 0x1;
static const uintptr_t DRAWENTRY_TINT = 0x2;
// Called after graphics driver was initialized for use for the first time
virtual void OnInit();
// Called just before graphics mode is going to be uninitialized and its
// resources released
virtual void OnUnInit();
// Called after new mode was successfully initialized
virtual void OnModeSet(const DisplayMode &mode);
// Called when the new native size is set
virtual void OnSetNativeRes(const GraphicResolution &native_res);
// Called before display mode is going to be released
virtual void OnModeReleased();
// Called when new render frame is set
virtual void OnSetRenderFrame(const Rect &dst_rect);
// Called when the new filter is set
virtual void OnSetFilter();
// Try changing vsync setting; fills new current mode in vsync_res,
// returns whether the new setting was set successfully.
virtual bool SetVsyncImpl(bool vsync, bool &vsync_res) { return false; }
// Initialize sprite batch and allocate necessary resources
virtual void InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) = 0;
// Gets the index of a last draw entry (sprite)
virtual size_t GetLastDrawEntryIndex() = 0;
// Clears sprite lists
virtual void ResetAllBatches() = 0;
void OnScalingChanged();
DisplayMode _mode; // display mode settings
Rect _srcRect; // rendering source rect
int _srcColorDepth; // rendering source color depth (in bits per pixel)
Rect _dstRect; // rendering destination rect
Rect _filterRect; // filter scaling destination rect (before final scaling)
PlaneScaling _scaling; // native -> render dest coordinate transformation
// Capability flags
bool _capsVsync = false; // is vsync available
// Callbacks
GFXDRV_CLIENTCALLBACK _pollingCallback;
GFXDRV_CLIENTCALLBACK _drawScreenCallback;
GFXDRV_CLIENTCALLBACK _drawPostScreenCallback;
GFXDRV_CLIENTCALLBACKEVT _spriteEvtCallback;
GFXDRV_CLIENTCALLBACKINITGFX _initGfxCallback;
// Sprite batch parameters
SpriteBatchDescs _spriteBatchDesc;
// The range of sprites in this sprite batch (counting nested sprites):
// the index of a first of the current batch, and the next index past the last one.
std::vector<std::pair<size_t, size_t>> _spriteBatchRange;
// The index of a currently filled sprite batch
size_t _actSpriteBatch;
// The index of a currently rendered sprite batch
// (or -1 / UINT32_MAX if we are outside of the render pass)
uint32_t _rendSpriteBatch;
};
// Parent class for the video memory DDBs
class BaseDDB : public IDriverDependantBitmap {
public:
int GetWidth() const override {
return _width;
}
int GetHeight() const override {
return _height;
}
int GetColorDepth() const override {
return _colDepth;
}
int _width = 0, _height = 0;
int _colDepth = 0;
bool _hasAlpha = false; // has meaningful alpha channel
bool _opaque = false; // no mask color
protected:
BaseDDB() {}
virtual ~BaseDDB() {}
};
// A base parent for the otherwise opaque texture data object;
// TextureData refers to the pixel data itself, with no additional
// properties. It may be shared between multiple sprites if necessary.
struct TextureData {
uint32_t ID = UINT32_MAX;
bool RenderTarget = false; // replace with flags later
virtual ~TextureData() = default;
protected:
TextureData() = default;
};
// Generic TextureTile base
struct TextureTile {
int x = 0, y = 0;
int width = 0, height = 0;
// allocWidth and allocHeight tell the actual allocated texture size
int allocWidth = 0, allocHeight = 0;
};
// VideoMemoryGraphicsDriver - is the parent class for the graphic drivers
// which drawing method is based on passing the sprite stack into GPU,
// rather than blitting to flat screen bitmap.
class VideoMemoryGraphicsDriver : public GraphicsDriverBase {
public:
VideoMemoryGraphicsDriver();
~VideoMemoryGraphicsDriver() override;
bool RequiresFullRedrawEachFrame() override { return true; }
bool HasAcceleratedTransform() override { return true; }
// NOTE: although we do use ours, we do not let engine draw upon it;
// only plugin handling are allowed to request our mem buffer
// for compatibility reasons.
bool UsesMemoryBackBuffer() override { return false; }
Bitmap *GetMemoryBackBuffer() override;
void SetMemoryBackBuffer(Bitmap *backBuffer) override;
Bitmap *GetStageBackBuffer(bool mark_dirty) override;
void SetStageBackBuffer(Bitmap *backBuffer) override;
bool GetStageMatrixes(RenderMatrixes &rm) override;
// Creates new texture using given parameters
IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque) override = 0;
// Creates new texture and copy bitmap contents over
IDriverDependantBitmap *CreateDDBFromBitmap(Bitmap *bitmap, bool has_alpha, bool opaque = false) override;
// Get shared texture from cache, or create from bitmap and assign ID
IDriverDependantBitmap *GetSharedDDB(uint32_t sprite_id, Bitmap *bitmap, bool has_alpha, bool opaque) override;
// Removes the shared texture reference, will force the texture to recreate next time
void ClearSharedDDB(uint32_t sprite_id) override;
// Updates shared texture data, but only if it is present in the cache
void UpdateSharedDDB(uint32_t sprite_id, Bitmap *bitmap, bool has_alpha, bool opaque) override;
void DestroyDDB(IDriverDependantBitmap* ddb) override;
// Sets stage screen parameters for the current batch.
void SetStageScreen(const Size &sz, int x = 0, int y = 0) override;
protected:
// Create texture data with the given parameters
virtual TextureData *CreateTextureData(int width, int height, bool opaque, bool as_render_target = false) = 0;
// Update texture data from the given bitmap
virtual void UpdateTextureData(TextureData *txdata, Bitmap *bmp, bool has_alpha, bool opaque) = 0;
// Create DDB using preexisting texture data
virtual IDriverDependantBitmap *CreateDDB(std::shared_ptr<TextureData> txdata,
int width, int height, int color_depth, bool opaque) = 0;
// Retrieve shared texture data object from the given DDB
virtual std::shared_ptr<TextureData> GetTextureData(IDriverDependantBitmap *ddb) = 0;
virtual void DestroyDDBImpl(IDriverDependantBitmap* ddb) = 0;
// Stage screens are raw bitmap buffers meant to be sent to plugins on demand
// at certain drawing stages. If used at least once these buffers are then
// rendered as additional sprites in their respected order.
// Presets a stage screen with the given position (size is obligatory, offsets not).
void SetStageScreen(size_t index, const Size &sz, int x = 0, int y = 0);
// Returns a raw bitmap for the given stage screen.
Bitmap *GetStageScreenRaw(size_t index);
// Updates and returns a DDB for the given stage screen, and optional x,y position;
// clears the raw bitmap after copying to the texture.
IDriverDependantBitmap *UpdateStageScreenDDB(size_t index, int &x, int &y);
// Disposes all the stage screen raw bitmaps and DDBs.
void DestroyAllStageScreens();
// Use engine callback to pass a render event;
// returns a DDB if anything was drawn onto the current stage screen
// (in which case it also fills optional x,y position),
// or nullptr if this entry should be skipped.
IDriverDependantBitmap *DoSpriteEvtCallback(int evt, int data, int &x, int &y);
// Prepare and get fx item from the pool
IDriverDependantBitmap *MakeFx(int r, int g, int b);
// Resets fx pool counter
void ResetFxPool();
// Disposes all items in the fx pool
void DestroyFxPool();
// Prepares bitmap to be applied to the texture, copies pixels to the provided buffer
void BitmapToVideoMem(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
uint8_t *dst_ptr, const int dst_pitch, const bool usingLinearFiltering);
// Same but optimized for opaque source bitmaps which ignore transparent "mask color"
void BitmapToVideoMemOpaque(const Bitmap *bitmap, const TextureTile *tile,
uint8_t *dst_ptr, const int dst_pitch);
// Stage virtual screen is used to let plugins draw custom graphics
// in between render stages (between room and GUI, after GUI, and so on)
PBitmap _stageVirtualScreen;
IDriverDependantBitmap *_stageVirtualScreenDDB;
// Stage matrixes are used to let plugins with hardware acceleration know model matrix;
// these matrixes are filled compatible with each given renderer
RenderMatrixes _stageMatrixes;
// Color component shifts in video bitmap format (set by implementations)
int _vmem_a_shift_32;
int _vmem_r_shift_32;
int _vmem_g_shift_32;
int _vmem_b_shift_32;
private:
// Stage virtual screens are used to let plugins draw custom graphics
// in between render stages (between room and GUI, after GUI, and so on).
// TODO: possibly may be optimized further by having only 1 bitmap/ddb
// pair, and subbitmaps for raw drawing on separate stages.
struct StageScreen {
Rect Position; // bitmap size and pos preset (bitmap may be created later)
std::unique_ptr<Bitmap> Raw;
IDriverDependantBitmap *DDB = nullptr;
};
std::vector<StageScreen> _stageScreens;
// Flag which indicates whether stage screen was drawn upon during engine
// callback and has to be inserted into sprite stack.
bool _stageScreenDirty;
// Fx quads pool (for screen overlay effects)
struct ScreenFx {
Bitmap *Raw = nullptr;
IDriverDependantBitmap *DDB = nullptr;
int Red = -1;
int Green = -1;
int Blue = -1;
};
std::vector<ScreenFx> _fxPool;
size_t _fxIndex; // next free pool item
// specialized method to convert bitmap to video memory depending on bit depth
template<typename T, bool HasAlpha>
void BitmapToVideoMemImpl(const Bitmap *bitmap, const TextureTile *tile, uint8_t *dst_ptr, const int dst_pitch);
template<typename T>
void BitmapToVideoMemOpaqueImpl(const Bitmap *bitmap, const TextureTile *tile, uint8_t *dst_ptr, const int dst_pitch);
template<typename T, bool HasAlpha>
void BitmapToVideoMemLinearImpl(const Bitmap *bitmap, const TextureTile *tile, uint8_t *dst_ptr, const int dst_pitch);
// Texture short-term cache:
// - caches textures while they are in the immediate use;
// - this lets to share same texture data among multiple sprites on screen.
// TextureCacheItem stores weak references to the existing texture tiles,
// identified by an arbitrary uint32 number.
// TODO: a curious topic to consider: reuse released TextureData for
// textures of the same size (research potential performance impact).
struct TextureCacheItem {
GraphicResolution Res;
std::weak_ptr<TextureData> Data;
TextureCacheItem() = default;
TextureCacheItem(std::shared_ptr<TextureData> data, const GraphicResolution &res)
: Data(data), Res(res) {}
};
std::unordered_map<uint32_t, TextureCacheItem> _txRefs;
};
} // namespace Engine
} // namespace AGS
} // namespace AGS3
#endif
|