浏览代码

Use SDL BlitMode's to speed up image rendering

Ivan Savenko 2 年之前
父节点
当前提交
def1e35836

+ 6 - 7
Global.h

@@ -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>

+ 1 - 0
client/adventureMap/MapRenderer.cpp

@@ -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));
 }
 

+ 2 - 2
client/adventureMap/MapRendererContext.h

@@ -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;

+ 5 - 5
client/adventureMap/MapView.cpp

@@ -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

+ 1 - 1
client/adventureMap/MapView.h

@@ -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;

+ 22 - 18
client/adventureMap/mapHandler.h

@@ -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

+ 2 - 2
client/render/CAnimation.cpp

@@ -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;

+ 15 - 0
client/render/IImage.h

@@ -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

+ 27 - 10
client/renderSDL/SDLImage.cpp

@@ -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)

+ 6 - 3
client/renderSDL/SDLImage.h

@@ -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;
 

+ 4 - 4
client/windows/CCastleInterface.cpp

@@ -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;