1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

Use SDL BlitMode's to speed up image rendering

This commit is contained in:
Ivan Savenko
2023-02-20 18:37:33 +02:00
parent 40413ee6be
commit def1e35836
11 changed files with 91 additions and 52 deletions

View File

@@ -116,33 +116,32 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include <cstdio>
#include <stdio.h>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <atomic>
#include <bitset>
#include <cassert> #include <cassert>
#include <climits> #include <climits>
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include <functional> #include <cstdio>
#include <fstream> #include <fstream>
#include <functional>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex>
#include <numeric> #include <numeric>
#include <queue> #include <queue>
#include <random> #include <random>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <unordered_set>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <atomic>
#include <mutex>
//The only available version is 3, as of Boost 1.50 //The only available version is 3, as of Boost 1.50
#include <boost/version.hpp> #include <boost/version.hpp>

View File

@@ -162,6 +162,7 @@ void MapRendererTerrain::renderTile(const IMapRendererContext & context, Canvas
image->shiftPalette(242, 14, context.terrainImageIndex(14)); image->shiftPalette(242, 14, context.terrainImageIndex(14));
} }
image->setBlitMode(EImageBlitMode::OPAQUE);
target.draw(image, Point(0, 0)); target.draw(image, Point(0, 0));
} }

View File

@@ -64,8 +64,8 @@ public:
/// returns animation frame for terrain /// returns animation frame for terrain
virtual size_t terrainImageIndex(size_t groupSize) const = 0; virtual size_t terrainImageIndex(size_t groupSize) const = 0;
/// returns size of ouput tile, in pixels. 32x32 for "standard" map, may be smaller for world view mode // /// returns size of ouput tile, in pixels. 32x32 for "standard" map, may be smaller for world view mode
virtual Point getTileSize() const = 0; // virtual Point getTileSize() const = 0;
/// if true, map grid should be visible on map /// if true, map grid should be visible on map
virtual bool showGrid() const = 0; virtual bool showGrid() const = 0;

View File

@@ -189,14 +189,14 @@ size_t MapRendererContext::terrainImageIndex(size_t groupSize) const
return frameIndex; return frameIndex;
} }
Point MapRendererContext::getTileSize() const //Point MapRendererContext::getTileSize() const
{ //{
return Point(32, 32); // return Point(32, 32);
} //}
bool MapRendererContext::showGrid() const bool MapRendererContext::showGrid() const
{ {
return true; // settings["gameTweaks"]["showGrid"].Bool(); return settings["gameTweaks"]["showGrid"].Bool();
} }
bool MapRendererContext::showVisitable() const bool MapRendererContext::showVisitable() const

View File

@@ -68,7 +68,7 @@ public:
double objectTransparency(ObjectInstanceID objectID) const override; double objectTransparency(ObjectInstanceID objectID) const override;
size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const override; size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const override;
size_t terrainImageIndex(size_t groupSize) const override; size_t terrainImageIndex(size_t groupSize) const override;
Point getTileSize() const override; // Point getTileSize() const override;
bool showGrid() const override; bool showGrid() const override;
bool showVisitable() const override; bool showVisitable() const override;
bool showBlockable() const override; bool showBlockable() const override;

View File

@@ -41,27 +41,31 @@ class IImage;
class CMapHandler; class CMapHandler;
class IMapObjectObserver; class IMapObjectObserver;
// from VwSymbol.def
enum class EWorldViewIcon enum class EWorldViewIcon
{ {
TOWN = 0, TOWN = 0,
HERO, HERO = 1,
ARTIFACT, ARTIFACT = 2,
TELEPORT, TELEPORT = 3,
GATE, GATE = 4,
MINE_WOOD, MINE_WOOD = 5,
MINE_MERCURY, MINE_MERCURY = 6,
MINE_STONE, MINE_STONE = 7,
MINE_SULFUR, MINE_SULFUR = 8,
MINE_CRYSTAL, MINE_CRYSTAL = 9,
MINE_GEM, MINE_GEM = 10,
MINE_GOLD, MINE_GOLD = 11,
RES_WOOD, RES_WOOD = 12,
RES_MERCURY, RES_MERCURY = 13,
RES_STONE, RES_STONE = 14,
RES_SULFUR, RES_SULFUR = 15,
RES_CRYSTAL, RES_CRYSTAL = 16,
RES_GEM, RES_GEM = 17,
RES_GOLD, RES_GOLD = 18,
ICONS_PER_PLAYER = 19,
ICONS_TOTAL = 19 * 9 // 8 players + neutral set at the end
}; };
class CMapHandler class CMapHandler

View File

@@ -69,13 +69,13 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
// still here? image is missing // still here? image is missing
printError(frame, group, "LoadFrame"); printError(frame, group, "LoadFrame");
images[group][frame] = std::make_shared<SDLImage>("DEFAULT"); images[group][frame] = std::make_shared<SDLImage>("DEFAULT", EImageBlitMode::ALPHA);
} }
else //load from separate file else //load from separate file
{ {
auto img = getFromExtraDef(source[group][frame]["file"].String()); auto img = getFromExtraDef(source[group][frame]["file"].String());
if(!img) if(!img)
img = std::make_shared<SDLImage>(source[group][frame]); img = std::make_shared<SDLImage>(source[group][frame], EImageBlitMode::ALPHA);
images[group][frame] = img; images[group][frame] = img;
return true; return true;

View File

@@ -21,6 +21,19 @@ struct SDL_Surface;
struct SDL_Color; struct SDL_Color;
class ColorFilter; class ColorFilter;
/// Defines which blit method will be selected when image is used for rendering
enum class EImageBlitMode : uint8_t
{
/// Image can have no transparency and can be only used as background
OPAQUE,
/// Image can have only a single color as transparency and has no semi-transparent areas
COLORKEY,
/// Image might have full alpha transparency range, e.g. shadows
ALPHA
};
/* /*
* Base class for images, can be used for non-animation pictures as well * Base class for images, can be used for non-animation pictures as well
*/ */
@@ -57,6 +70,7 @@ public:
virtual void resetPalette() = 0; virtual void resetPalette() = 0;
virtual void setAlpha(uint8_t value) = 0; virtual void setAlpha(uint8_t value) = 0;
virtual void setBlitMode(EImageBlitMode mode) = 0;
//only indexed bitmaps with 7 special colors //only indexed bitmaps with 7 special colors
virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0; virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
@@ -69,6 +83,7 @@ public:
/// loads image from specified file. Returns 0-sized images on failure /// loads image from specified file. Returns 0-sized images on failure
static std::shared_ptr<IImage> createFromFile( const std::string & path ); static std::shared_ptr<IImage> createFromFile( const std::string & path );
static std::shared_ptr<IImage> createFromFile( const std::string & path, EImageBlitMode mode );
/// temporary compatibility method. Creates IImage from existing SDL_Surface /// temporary compatibility method. Creates IImage from existing SDL_Surface
/// Surface will be shared, called must still free it with SDL_FreeSurface /// Surface will be shared, called must still free it with SDL_FreeSurface

View File

@@ -26,12 +26,12 @@ class SDLImageLoader;
std::shared_ptr<IImage> IImage::createFromFile( const std::string & path ) std::shared_ptr<IImage> IImage::createFromFile( const std::string & path )
{ {
return std::shared_ptr<IImage>(new SDLImage(path)); return std::shared_ptr<IImage>(new SDLImage(path, EImageBlitMode::ALPHA));
} }
std::shared_ptr<IImage> IImage::createFromSurface( SDL_Surface * source ) std::shared_ptr<IImage> IImage::createFromSurface( SDL_Surface * source )
{ {
return std::shared_ptr<IImage>(new SDLImage(source, true)); return std::shared_ptr<IImage>(new SDLImage(source, EImageBlitMode::ALPHA));
} }
IImage::IImage() = default; IImage::IImage() = default;
@@ -57,9 +57,10 @@ SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group)
data->loadFrame(frame, group, loader); data->loadFrame(frame, group, loader);
savePalette(); savePalette();
setBlitMode(EImageBlitMode::ALPHA);
} }
SDLImage::SDLImage(SDL_Surface * from, bool extraRef) SDLImage::SDLImage(SDL_Surface * from, EImageBlitMode mode)
: surf(nullptr), : surf(nullptr),
margins(0, 0), margins(0, 0),
fullSize(0, 0), fullSize(0, 0),
@@ -70,14 +71,14 @@ SDLImage::SDLImage(SDL_Surface * from, bool extraRef)
return; return;
savePalette(); savePalette();
setBlitMode(mode);
if (extraRef)
surf->refcount++; surf->refcount++;
fullSize.x = surf->w; fullSize.x = surf->w;
fullSize.y = surf->h; fullSize.y = surf->h;
} }
SDLImage::SDLImage(const JsonNode & conf) SDLImage::SDLImage(const JsonNode & conf, EImageBlitMode mode)
: surf(nullptr), : surf(nullptr),
margins(0, 0), margins(0, 0),
fullSize(0, 0), fullSize(0, 0),
@@ -91,6 +92,7 @@ SDLImage::SDLImage(const JsonNode & conf)
return; return;
savePalette(); savePalette();
setBlitMode(mode);
const JsonNode & jsonMargins = conf["margins"]; const JsonNode & jsonMargins = conf["margins"];
@@ -111,7 +113,7 @@ SDLImage::SDLImage(const JsonNode & conf)
} }
} }
SDLImage::SDLImage(std::string filename) SDLImage::SDLImage(std::string filename, EImageBlitMode mode)
: surf(nullptr), : surf(nullptr),
margins(0, 0), margins(0, 0),
fullSize(0, 0), fullSize(0, 0),
@@ -127,6 +129,7 @@ SDLImage::SDLImage(std::string filename)
else else
{ {
savePalette(); savePalette();
setBlitMode(mode);
fullSize.x = surf->w; fullSize.x = surf->w;
fullSize.y = surf->h; fullSize.y = surf->h;
} }
@@ -172,7 +175,7 @@ void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) cons
if (SDL_GetSurfaceAlphaMod(surf, &perSurfaceAlpha) != 0) if (SDL_GetSurfaceAlphaMod(surf, &perSurfaceAlpha) != 0)
logGlobal->error("SDL_GetSurfaceAlphaMod faied! %s", SDL_GetError()); logGlobal->error("SDL_GetSurfaceAlphaMod faied! %s", SDL_GetError());
if(surf->format->BitsPerPixel == 8 && perSurfaceAlpha == SDL_ALPHA_OPAQUE) if(surf->format->BitsPerPixel == 8 && perSurfaceAlpha == SDL_ALPHA_OPAQUE && blitMode == EImageBlitMode::ALPHA)
{ {
CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift); CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift);
} }
@@ -196,7 +199,7 @@ std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const
else else
CSDL_Ext::setDefaultColorKey(scaled);//just in case CSDL_Ext::setDefaultColorKey(scaled);//just in case
SDLImage * ret = new SDLImage(scaled, false); SDLImage * ret = new SDLImage(scaled, EImageBlitMode::ALPHA);
ret->fullSize.x = (int) round((float)fullSize.x * scaleX); ret->fullSize.x = (int) round((float)fullSize.x * scaleX);
ret->fullSize.y = (int) round((float)fullSize.y * scaleY); ret->fullSize.y = (int) round((float)fullSize.y * scaleY);
@@ -204,6 +207,9 @@ std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const
ret->margins.x = (int) round((float)margins.x * scaleX); ret->margins.x = (int) round((float)margins.x * scaleX);
ret->margins.y = (int) round((float)margins.y * scaleY); ret->margins.y = (int) round((float)margins.y * scaleY);
// erase our own reference
SDL_FreeSurface(scaled);
return std::shared_ptr<IImage>(ret); return std::shared_ptr<IImage>(ret);
} }
@@ -220,9 +226,20 @@ void SDLImage::playerColored(PlayerColor player)
void SDLImage::setAlpha(uint8_t value) void SDLImage::setAlpha(uint8_t value)
{ {
CSDL_Ext::setAlpha (surf, value); CSDL_Ext::setAlpha (surf, value);
if (value != 255)
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND); SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
} }
void SDLImage::setBlitMode(EImageBlitMode mode)
{
blitMode = mode;
if (blitMode != EImageBlitMode::OPAQUE && surf->format->Amask != 0)
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
else
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);
}
void SDLImage::setFlagColor(PlayerColor player) void SDLImage::setFlagColor(PlayerColor player)
{ {
if(player < PlayerColor::PLAYER_LIMIT || player==PlayerColor::NEUTRAL) if(player < PlayerColor::PLAYER_LIMIT || player==PlayerColor::NEUTRAL)

View File

@@ -37,15 +37,17 @@ public:
//total size including borders //total size including borders
Point fullSize; Point fullSize;
EImageBlitMode blitMode;
public: public:
//Load image from def file //Load image from def file
SDLImage(CDefFile *data, size_t frame, size_t group=0); SDLImage(CDefFile *data, size_t frame, size_t group=0);
//Load from bitmap file //Load from bitmap file
SDLImage(std::string filename); SDLImage(std::string filename, EImageBlitMode blitMode);
SDLImage(const JsonNode & conf); SDLImage(const JsonNode & conf, EImageBlitMode blitMode);
//Create using existing surface, extraRef will increase refcount on SDL_Surface //Create using existing surface, extraRef will increase refcount on SDL_Surface
SDLImage(SDL_Surface * from, bool extraRef); SDLImage(SDL_Surface * from, EImageBlitMode blitMode);
~SDLImage(); ~SDLImage();
// Keep the original palette, in order to do color switching operation // Keep the original palette, in order to do color switching operation
@@ -69,6 +71,7 @@ public:
void resetPalette() override; void resetPalette() override;
void setAlpha(uint8_t value) override; void setAlpha(uint8_t value) override;
void setBlitMode(EImageBlitMode mode) override;
void setSpecialPallete(const SpecialPalette & SpecialPalette) override; void setSpecialPallete(const SpecialPalette & SpecialPalette) override;

View File

@@ -61,6 +61,8 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town
parent(Par), parent(Par),
town(Town), town(Town),
str(Str), str(Str),
border(nullptr),
area(nullptr),
stateTimeCounter(BUILD_ANIMATION_FINISHED_TIMEPOINT) stateTimeCounter(BUILD_ANIMATION_FINISHED_TIMEPOINT)
{ {
addUsedEvents(LCLICK | RCLICK | HOVER); addUsedEvents(LCLICK | RCLICK | HOVER);
@@ -83,13 +85,9 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town
if(!str->borderName.empty()) if(!str->borderName.empty())
border = IImage::createFromFile(str->borderName); border = IImage::createFromFile(str->borderName);
else
border = nullptr;
if(!str->areaName.empty()) if(!str->areaName.empty())
area = IImage::createFromFile(str->areaName); area = IImage::createFromFile(str->areaName);
else
area = nullptr;
} }
const CBuilding * CBuildingRect::getBuilding() const CBuilding * CBuildingRect::getBuilding()
@@ -565,6 +563,8 @@ CCastleBuildings::CCastleBuildings(const CGTownInstance* Town):
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>(town->town->clientInfo.townBackground); background = std::make_shared<CPicture>(town->town->clientInfo.townBackground);
background->needRefresh = true;
background->getSurface()->setBlitMode(EImageBlitMode::OPAQUE);
pos.w = background->pos.w; pos.w = background->pos.w;
pos.h = background->pos.h; pos.h = background->pos.h;