scummvm/engines/ags/engine/gfx/gfx_driver_base.h
Thierry Crozat e9c84767f7 AGS: Merged BitmapFlip with engine's GlobalFlipType (same values)
From upstream a747deafe67d536b6bcaf408077ca83f6e61a33d
2022-06-24 20:54:47 +01:00

328 lines
12 KiB
C++

/* 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 "ags/lib/std/memory.h"
#include "engines/ags/lib/std/map.h"
#include "ags/lib/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 = 0;
// 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;
// Global node offset applied to the whole batch as the last transform
Point Offset;
// Global node 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;
SpriteBatchDesc() = default;
SpriteBatchDesc(uint32_t parent, const Rect viewport, const SpriteTransform & transform, const Point offset = Point(),
Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr)
: Parent(parent)
, Viewport(viewport)
, Transform(transform)
, Offset(offset)
, Flip(flip)
, Surface(surface) {
}
};
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;
void BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform,
const Point offset = Point(), Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr) 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 SetCallbackForNullSprite(GFXDRV_CLIENTCALLBACKXY callback) override {
_nullSpriteCallback = callback;
}
protected:
// Special internal values, applied to DrawListEntry
static const intptr_t DRAWENTRY_STAGECALLBACK = 0x0;
static const intptr_t DRAWENTRY_FADE = 0x1;
static const intptr_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();
// Initialize sprite batch and allocate necessary resources
virtual void InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) = 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
// Callbacks
GFXDRV_CLIENTCALLBACK _pollingCallback;
GFXDRV_CLIENTCALLBACK _drawScreenCallback;
GFXDRV_CLIENTCALLBACK _drawPostScreenCallback;
GFXDRV_CLIENTCALLBACKXY _nullSpriteCallback;
GFXDRV_CLIENTCALLBACKINITGFX _initGfxCallback;
// Sprite batch parameters
SpriteBatchDescs _spriteBatchDesc; // sprite batches list
size_t _actSpriteBatch; // active batch index
};
// 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;
virtual ~TextureData() = default;
protected:
TextureData() = default;
};
// Generic TextureTile base
struct TextureTile {
int x = 0, y = 0;
int width = 0, height = 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 UsesMemoryBackBuffer() override;
Bitmap *GetMemoryBackBuffer() override;
void SetMemoryBackBuffer(Bitmap *backBuffer) override;
Bitmap *GetStageBackBuffer(bool mark_dirty) override;
bool GetStageMatrixes(RenderMatrixes &rm) override;
IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque) override = 0;
IDriverDependantBitmap *CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, 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 hasAlpha, 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 hasAlpha, bool opaque) override;
void DestroyDDB(IDriverDependantBitmap* ddb) override;
protected:
// Create texture data with the given parameters
virtual TextureData *CreateTextureData(int width, int height, bool opaque) = 0;
// Update texture data from the given bitmap
virtual void UpdateTextureData(TextureData *txdata, Bitmap *bmp, bool opaque, bool hasAlpha) = 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.
PBitmap CreateStageScreen(size_t index, const Size &sz);
PBitmap GetStageScreen(size_t index);
void DestroyAllStageScreens();
// Use engine callback to acquire replacement for the null sprite;
// returns true if the sprite was provided onto the virtual screen,
// and false if this entry should be skipped.
bool DoNullSpriteCallback(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,
char *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 bool has_alpha, const TextureTile *tile,
char *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:
// Virtual screens for rendering stages (sprite batches)
std::vector<PBitmap> _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
// 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.
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