From 430f472b0e358ebb2cc7f2113c606f2ea03f7739 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Fri, 15 May 2015 18:02:40 +0300 Subject: Improve a bit map draw performance. --- src/resources/map/map.cpp | 189 ++++++++++++++++++++++++++++++++------------ src/resources/map/map.h | 9 ++- src/resources/mapreader.cpp | 2 + 3 files changed, 148 insertions(+), 52 deletions(-) diff --git a/src/resources/map/map.cpp b/src/resources/map/map.cpp index 14465956e..9f4feb87b 100644 --- a/src/resources/map/map.cpp +++ b/src/resources/map/map.cpp @@ -87,6 +87,8 @@ Map::Map(const int width, const int height, mMetaTiles(new MetaTile[mWidth * mHeight]), mWalkLayer(nullptr), mLayers(), + mDrawUnderLayers(), + mDrawOverLayers(), mTilesets(), mActors(), mHasWarps(false), @@ -131,7 +133,15 @@ Map::Map(const int width, const int height, mHeights(nullptr), mRedrawMap(true), mBeingOpacity(false), - mCustom(false) +#ifdef USE_OPENGL + mCachedDraw(mOpenGL == RENDER_NORMAL_OPENGL + || mOpenGL == RENDER_GLES_OPENGL + || mOpenGL == RENDER_MODERN_OPENGL), +#else + mCachedDraw(false), +#endif + mCustom(false), + mDrawOnlyFringe(false) { const int size = mWidth * mHeight; for (int i = 0; i < BlockType::NB_BLOCKTYPES; i++) @@ -353,9 +363,7 @@ void Map::draw(Graphics *const graphics, int scrollX, int scrollY) #ifdef USE_OPENGL int updateFlag = 0; - if (mOpenGL == RENDER_NORMAL_OPENGL - || mOpenGL == RENDER_GLES_OPENGL - || mOpenGL == RENDER_MODERN_OPENGL) + if (mCachedDraw) { if (mLastX != startX || mLastY != startY || mLastScrollX != scrollX || mLastScrollY != scrollY) @@ -379,9 +387,7 @@ void Map::draw(Graphics *const graphics, int scrollX, int scrollY) } #endif - if (mDrawLayersFlags == MapType::SPECIAL3 - || mDrawLayersFlags == MapType::SPECIAL4 - || mDrawLayersFlags == MapType::BLACKWHITE) + if (mDrawOnlyFringe) { if (mFringeLayer) { @@ -393,62 +399,77 @@ void Map::draw(Graphics *const graphics, int scrollX, int scrollY) } else { - bool overFringe = false; - - for (LayersCIter layeri = mLayers.begin(), layeri_end = mLayers.end(); - layeri != layeri_end && !overFringe; ++ layeri) + if (mCachedDraw) { - MapLayer *const layer = *layeri; - if (!(layer->mMask & mMask)) - continue; - - if (layer->isFringeLayer()) + FOR_EACH (Layers::iterator, it, mDrawUnderLayers) { - layer->setSpecialLayer(mSpecialLayer); - layer->setTempLayer(mTempLayer); - if (mDrawLayersFlags == MapType::SPECIAL2) - overFringe = true; + MapLayer *const layer = *it; + if (updateFlag) + { + layer->updateOGL(graphics, startX, startY, + endX, endY, scrollX, scrollY, mDrawLayersFlags); + } - layer->drawFringe(graphics, startX, startY, endX, endY, - scrollX, scrollY, &mActors, mDrawLayersFlags, mActorFixY); + layer->drawOGL(graphics); } - else + + if (mFringeLayer) { -#ifdef USE_OPENGL - if (mOpenGL == RENDER_NORMAL_OPENGL - || mOpenGL == RENDER_GLES_OPENGL - || mOpenGL == RENDER_MODERN_OPENGL) - { - if (updateFlag) - { - layer->updateOGL(graphics, startX, startY, - endX, endY, scrollX, scrollY, mDrawLayersFlags); - } + mFringeLayer->setSpecialLayer(mSpecialLayer); + mFringeLayer->setTempLayer(mTempLayer); + mFringeLayer->drawFringe(graphics, startX, startY, endX, endY, + scrollX, scrollY, &mActors, mDrawLayersFlags, mActorFixY); + } - layer->drawOGL(graphics); - } - else -#endif + FOR_EACH (Layers::iterator, it, mDrawOverLayers) + { + MapLayer *const layer = *it; + if (updateFlag) { - layer->draw(graphics, startX, startY, endX, endY, - scrollX, scrollY, mDrawLayersFlags); + layer->updateOGL(graphics, startX, startY, + endX, endY, scrollX, scrollY, mDrawLayersFlags); } + + layer->drawOGL(graphics); + } + } + else + { + FOR_EACH (Layers::iterator, it, mDrawUnderLayers) + { + (*it)->draw(graphics, startX, startY, endX, endY, + scrollX, scrollY, mDrawLayersFlags); + } + + if (mFringeLayer) + { + mFringeLayer->setSpecialLayer(mSpecialLayer); + mFringeLayer->setTempLayer(mTempLayer); + mFringeLayer->drawFringe(graphics, startX, startY, endX, endY, + scrollX, scrollY, &mActors, mDrawLayersFlags, mActorFixY); + } + + FOR_EACH (Layers::iterator, it, mDrawOverLayers) + { + (*it)->draw(graphics, startX, startY, endX, endY, + scrollX, scrollY, mDrawLayersFlags); } } } // Don't draw if gui opacity == 1 - if (mBeingOpacity && mOpacity != 1.0F) + if (mBeingOpacity) { // Draws beings with a lower opacity to make them visible // even when covered by a wall or some other elements... ActorsCIter ai = mActors.begin(); const ActorsCIter ai_end = mActors.end(); - while (ai != ai_end) + + if (mOpenGL == RENDER_SOFTWARE) { - if (Actor *const actor = *ai) + while (ai != ai_end) { - if (mOpenGL == RENDER_SOFTWARE) + if (Actor *const actor = *ai) { const int x = actor->getTileX(); const int y = actor->getTileY(); @@ -457,16 +478,33 @@ void Map::draw(Graphics *const graphics, int scrollX, int scrollY) ++ai; continue; } + // For now, just draw actors with only one layer. + if (actor->getNumberOfLayers() == 1) + { + actor->setAlpha(0.3F); + actor->draw(graphics, -scrollX, -scrollY); + actor->setAlpha(1.0F); + } } - // For now, just draw actors with only one layer. - if (actor->getNumberOfLayers() == 1) + ++ai; + } + } + else + { + while (ai != ai_end) + { + if (Actor *const actor = *ai) { - actor->setAlpha(0.3F); - actor->draw(graphics, -scrollX, -scrollY); - actor->setAlpha(1.0F); + // For now, just draw actors with only one layer. + if (actor->getNumberOfLayers() == 1) + { + actor->setAlpha(0.3F); + actor->draw(graphics, -scrollX, -scrollY); + actor->setAlpha(1.0F); + } } + ++ai; } - ++ai; } } @@ -1207,7 +1245,7 @@ const TileAnimation *Map::getAnimationForGid(const int gid) const if (mTileAnimations.empty()) return nullptr; - TileAnimationMapCIter i = mTileAnimations.find(gid); + const TileAnimationMapCIter i = mTileAnimations.find(gid); return (i == mTileAnimations.end()) ? nullptr : i->second; } @@ -1475,6 +1513,41 @@ uint8_t Map::getHeightOffset(const int x, const int y) const return mHeights->getHeight(x, y); } +void Map::updateDrawLayersList() +{ + mDrawUnderLayers.clear(); + mDrawOverLayers.clear(); + + if (mDrawOnlyFringe) + return; + + LayersCIter layers = mLayers.begin(); + const LayersCIter layers_end = mLayers.end(); + for (; layers != layers_end; ++ layers) + { + MapLayer *const layer = *layers; + if (!(layer->mMask & mMask)) + continue; + + if (layer->isFringeLayer()) + { + ++ layers; + break; + } + + mDrawUnderLayers.push_back(layer); + } + + for (; layers != layers_end; ++ layers) + { + MapLayer *const layer = *layers; + if (!(layer->mMask & mMask)) + continue; + + mDrawOverLayers.push_back(layer); + } +} + void Map::setMask(const int mask) { if (mask != mMask) @@ -1497,3 +1570,19 @@ void Map::addAnimation(const int gid, TileAnimation *const animation) } mTileAnimations[gid] = animation; } + +void Map::setDrawLayersFlags(const MapType::MapType &n) +{ + mDrawLayersFlags = n; + if (mDrawLayersFlags == MapType::SPECIAL3 + || mDrawLayersFlags == MapType::SPECIAL4 + || mDrawLayersFlags == MapType::BLACKWHITE) + { + mDrawOnlyFringe = true; + } + else + { + mDrawOnlyFringe = false; + } + updateDrawLayersList(); +} diff --git a/src/resources/map/map.h b/src/resources/map/map.h index dc8c880b1..3afd6d8ef 100644 --- a/src/resources/map/map.h +++ b/src/resources/map/map.h @@ -216,8 +216,7 @@ class Map final : public Properties, public ConfigListener */ void addAnimation(const int gid, TileAnimation *const animation); - void setDrawLayersFlags(const MapType::MapType &n) - { mDrawLayersFlags = n; } + void setDrawLayersFlags(const MapType::MapType &n); MapType::MapType getDrawLayersFlags() const A_WARN_UNUSED { return mDrawLayersFlags; } @@ -327,6 +326,8 @@ class Map final : public Properties, public ConfigListener void setMask(const int mask); + void updateDrawLayersList(); + protected: friend class Actor; friend class Minimap; @@ -377,6 +378,8 @@ class Map final : public Properties, public ConfigListener MetaTile *const mMetaTiles; WalkLayer *mWalkLayer; Layers mLayers; + Layers mDrawUnderLayers; + Layers mDrawOverLayers; Tilesets mTilesets; Actors mActors; bool mHasWarps; @@ -452,7 +455,9 @@ class Map final : public Properties, public ConfigListener const MapHeights *mHeights; bool mRedrawMap; bool mBeingOpacity; + bool mCachedDraw; bool mCustom; + bool mDrawOnlyFringe; }; #endif // RESOURCES_MAP_MAP_H diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 421915775..7b21cd1d0 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -462,6 +462,7 @@ Map *MapReader::readMap(XmlNodePtrConst node, const std::string &path) map->setWalkLayer(resman->getWalkLayer(fileName, map)); unloadTempLayers(); BLOCK_END("MapReader::readMap xml") + map->updateDrawLayersList(); return map; } @@ -1064,6 +1065,7 @@ Map *MapReader::createEmptyMap(const std::string &restrict filename, map->addLayer(layer); layer = new MapLayer(0, 0, 300, 300, true, 1); map->addLayer(layer); + map->updateDrawLayersList(); return map; } -- cgit v1.2.3-70-g09d2