1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +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
#include <cstdio>
#include <stdio.h>
#include <algorithm>
#include <array>
#include <atomic>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <functional>
#include <cstdio>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <mutex>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <atomic>
#include <mutex>
//The only available version is 3, as of Boost 1.50
#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->setBlitMode(EImageBlitMode::OPAQUE);
target.draw(image, Point(0, 0));
}

View File

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

View File

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

View File

@ -68,7 +68,7 @@ public:
double objectTransparency(ObjectInstanceID objectID) const override;
size_t objectImageIndex(ObjectInstanceID objectID, 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 showVisitable() const override;
bool showBlockable() const override;

View File

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

View File

@ -69,13 +69,13 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
// still here? image is missing
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
{
auto img = getFromExtraDef(source[group][frame]["file"].String());
if(!img)
img = std::make_shared<SDLImage>(source[group][frame]);
img = std::make_shared<SDLImage>(source[group][frame], EImageBlitMode::ALPHA);
images[group][frame] = img;
return true;

View File

@ -21,6 +21,19 @@ struct SDL_Surface;
struct SDL_Color;
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
*/
@ -57,6 +70,7 @@ public:
virtual void resetPalette() = 0;
virtual void setAlpha(uint8_t value) = 0;
virtual void setBlitMode(EImageBlitMode mode) = 0;
//only indexed bitmaps with 7 special colors
virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
@ -69,6 +83,7 @@ public:
/// 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, EImageBlitMode mode );
/// temporary compatibility method. Creates IImage from existing SDL_Surface
/// 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 )
{
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 )
{
return std::shared_ptr<IImage>(new SDLImage(source, true));
return std::shared_ptr<IImage>(new SDLImage(source, EImageBlitMode::ALPHA));
}
IImage::IImage() = default;
@ -57,9 +57,10 @@ SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group)
data->loadFrame(frame, group, loader);
savePalette();
setBlitMode(EImageBlitMode::ALPHA);
}
SDLImage::SDLImage(SDL_Surface * from, bool extraRef)
SDLImage::SDLImage(SDL_Surface * from, EImageBlitMode mode)
: surf(nullptr),
margins(0, 0),
fullSize(0, 0),
@ -70,14 +71,14 @@ SDLImage::SDLImage(SDL_Surface * from, bool extraRef)
return;
savePalette();
setBlitMode(mode);
if (extraRef)
surf->refcount++;
surf->refcount++;
fullSize.x = surf->w;
fullSize.y = surf->h;
}
SDLImage::SDLImage(const JsonNode & conf)
SDLImage::SDLImage(const JsonNode & conf, EImageBlitMode mode)
: surf(nullptr),
margins(0, 0),
fullSize(0, 0),
@ -91,6 +92,7 @@ SDLImage::SDLImage(const JsonNode & conf)
return;
savePalette();
setBlitMode(mode);
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),
margins(0, 0),
fullSize(0, 0),
@ -127,6 +129,7 @@ SDLImage::SDLImage(std::string filename)
else
{
savePalette();
setBlitMode(mode);
fullSize.x = surf->w;
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)
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);
}
@ -196,7 +199,7 @@ std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const
else
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.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.y = (int) round((float)margins.y * scaleY);
// erase our own reference
SDL_FreeSurface(scaled);
return std::shared_ptr<IImage>(ret);
}
@ -220,7 +226,18 @@ void SDLImage::playerColored(PlayerColor player)
void SDLImage::setAlpha(uint8_t value)
{
CSDL_Ext::setAlpha (surf, value);
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
if (value != 255)
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)

View File

@ -37,15 +37,17 @@ public:
//total size including borders
Point fullSize;
EImageBlitMode blitMode;
public:
//Load image from def file
SDLImage(CDefFile *data, size_t frame, size_t group=0);
//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
SDLImage(SDL_Surface * from, bool extraRef);
SDLImage(SDL_Surface * from, EImageBlitMode blitMode);
~SDLImage();
// Keep the original palette, in order to do color switching operation
@ -69,6 +71,7 @@ public:
void resetPalette() override;
void setAlpha(uint8_t value) override;
void setBlitMode(EImageBlitMode mode) override;
void setSpecialPallete(const SpecialPalette & SpecialPalette) override;

View File

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