diff --git a/src/client/creature.cpp b/src/client/creature.cpp index b9c996fca1..b6e9f87e50 100644 --- a/src/client/creature.cpp +++ b/src/client/creature.cpp @@ -114,29 +114,17 @@ void Creature::draw(const Rect& destRect, uint8_t size, bool center) if (size > 0) frameSize = std::max(frameSize * (size / 100.f), 2 * g_gameConfig.getSpriteSize() * (size / 100.f)); - const auto& draw = [&](const Point& p) { + g_drawPool.bindFrameBuffer(frameSize); { + auto p = Point(frameSize - g_gameConfig.getSpriteSize()) + getDisplacement(); + if (center) + p /= 2; + internalDraw(p); if (isMarked()) internalDraw(p, getMarkedColor()); else if (isHighlighted()) internalDraw(p, getHighlightColor()); - }; - - if (hasShader() && getShader()->useFramebuffer()) { - g_drawPool.setScaleFactor(destRect.size().bigger() / static_cast(frameSize)); - auto p = destRect.topLeft(); - if (center) - p += (frameSize / 1.25); - draw(p); - g_drawPool.setScaleFactor(1.f); - } else { - g_drawPool.bindFrameBuffer(frameSize); { - auto p = Point(frameSize - g_gameConfig.getSpriteSize()) + getDisplacement(); - if (center) - p /= 2; - draw(p); - } g_drawPool.releaseFrameBuffer(destRect); - } + } g_drawPool.releaseFrameBuffer(destRect); } void Creature::drawInformation(const MapPosInfo& mapRect, const Point& dest, int drawFlags) diff --git a/src/client/uiitem.cpp b/src/client/uiitem.cpp index cfe4fd5aa3..0dcb78b117 100644 --- a/src/client/uiitem.cpp +++ b/src/client/uiitem.cpp @@ -43,17 +43,10 @@ void UIItem::drawSelf(DrawPoolType drawPane) if (m_itemVisible && m_item) { const int exactSize = std::max(g_gameConfig.getSpriteSize(), m_item->getExactSize()); - if (m_item->hasShader() && m_item->getShader()->useFramebuffer()) { - g_drawPool.setScaleFactor(getPaddingRect().size().bigger() / static_cast(exactSize)); - m_item->setColor(m_color); - m_item->draw(getPaddingRect().topLeft()); - g_drawPool.setScaleFactor(1.f); - } else { - g_drawPool.bindFrameBuffer(exactSize); - m_item->setColor(m_color); - m_item->draw(Point(exactSize - g_gameConfig.getSpriteSize()) + m_item->getDisplacement()); - g_drawPool.releaseFrameBuffer(getPaddingRect()); - } + g_drawPool.bindFrameBuffer(exactSize); + m_item->setColor(m_color); + m_item->draw(Point(exactSize - g_gameConfig.getSpriteSize()) + m_item->getDisplacement()); + g_drawPool.releaseFrameBuffer(getPaddingRect()); if (m_font && (m_alwaysShowCount || m_item->isStackable() || m_item->isChargeable()) && m_item->getCountOrSubType() > 1) { static const Color STACK_COLOR(231, 231, 231); diff --git a/src/framework/graphics/drawpool.cpp b/src/framework/graphics/drawpool.cpp index 598892c6b2..0807e56f63 100644 --- a/src/framework/graphics/drawpool.cpp +++ b/src/framework/graphics/drawpool.cpp @@ -59,7 +59,7 @@ void DrawPool::add(const Color& color, const TexturePtr& texture, DrawPool::Draw order = DrawOrder::THIRD; if (m_alwaysGroupDrawings || conductor.agroup) { - auto& coords = m_coords.try_emplace(m_state.hash, nullptr).first->second; + auto& coords = m_coords.try_emplace(getCurrentState().hash, nullptr).first->second; if (!coords) { auto state = getState(texture, color); coords = m_objects[order].emplace_back(std::move(state), m_lastCoordBufferSize).coords.get(); @@ -77,7 +77,7 @@ void DrawPool::add(const Color& color, const TexturePtr& texture, DrawPool::Draw auto& list = m_objects[order]; if (!list.empty()) { auto& prevObj = list.back(); - if (prevObj.state == m_state) { + if (prevObj.state == getCurrentState()) { if (!prevObj.coords) prevObj.addMethod(std::move(method)); else if (coordsBuffer) @@ -127,39 +127,40 @@ void DrawPool::addCoords(CoordsBuffer* buffer, const DrawMethod& method, DrawMod } bool DrawPool::updateHash(const DrawPool::DrawMethod& method, const TexturePtr& texture, const Color& color, const bool hasCoord) { - { // State Hash - m_state.hash = 0; + auto& state = getCurrentState(); + state.hash = 0; + { // State Hash if (m_bindedFramebuffers) - stdext::hash_combine(m_state.hash, m_lastFramebufferId); + stdext::hash_combine(state.hash, m_lastFramebufferId); - if (m_state.blendEquation != BlendEquation::ADD) - stdext::hash_combine(m_state.hash, m_state.blendEquation); + if (state.blendEquation != BlendEquation::ADD) + stdext::hash_combine(state.hash, state.blendEquation); - if (m_state.compositionMode != CompositionMode::NORMAL) - stdext::hash_combine(m_state.hash, m_state.compositionMode); + if (state.compositionMode != CompositionMode::NORMAL) + stdext::hash_combine(state.hash, state.compositionMode); - if (m_state.opacity < 1.f) - stdext::hash_combine(m_state.hash, m_state.opacity); + if (state.opacity < 1.f) + stdext::hash_combine(state.hash, state.opacity); - if (m_state.clipRect.isValid()) - stdext::hash_union(m_state.hash, m_state.clipRect.hash()); + if (state.clipRect.isValid()) + stdext::hash_union(state.hash, state.clipRect.hash()); - if (m_state.shaderProgram) - stdext::hash_union(m_state.hash, m_state.shaderProgram->hash()); + if (state.shaderProgram) + stdext::hash_union(state.hash, state.shaderProgram->hash()); - if (m_state.transformMatrix != DEFAULT_MATRIX3) - stdext::hash_union(m_state.hash, m_state.transformMatrix.hash()); + if (state.transformMatrix != DEFAULT_MATRIX3) + stdext::hash_union(state.hash, state.transformMatrix.hash()); if (color != Color::white) - stdext::hash_union(m_state.hash, color.hash()); + stdext::hash_union(state.hash, color.hash()); if (texture) - stdext::hash_union(m_state.hash, texture->hash()); + stdext::hash_union(state.hash, texture->hash()); } if (hasFrameBuffer()) { // Pool Hash - size_t hash = m_state.hash; + size_t hash = state.hash; if (method.type == DrawPool::DrawMethodType::TRIANGLE) { if (!method.a.isNull()) stdext::hash_union(hash, method.a.hash()); @@ -184,52 +185,51 @@ bool DrawPool::updateHash(const DrawPool::DrawMethod& method, const TexturePtr& DrawPool::PoolState DrawPool::getState(const TexturePtr& texture, const Color& color) { - return PoolState{ - std::move(m_state.transformMatrix), m_state.opacity, - m_state.compositionMode, m_state.blendEquation, - std::move(m_state.clipRect), m_state.shaderProgram, - std::move(m_state.action), std::move(const_cast(color)), texture, m_state.hash - }; + PoolState copy = getCurrentState(); + copy.texture = texture; + if (copy.color != color) + copy.color = color; + return copy; } void DrawPool::setCompositionMode(const CompositionMode mode, bool onlyOnce) { - m_state.compositionMode = mode; + getCurrentState().compositionMode = mode; if (onlyOnce) m_onlyOnceStateFlag |= STATE_COMPOSITE_MODE; } void DrawPool::setBlendEquation(BlendEquation equation, bool onlyOnce) { - m_state.blendEquation = equation; + getCurrentState().blendEquation = equation; if (onlyOnce) m_onlyOnceStateFlag |= STATE_BLEND_EQUATION; } void DrawPool::setClipRect(const Rect& clipRect, bool onlyOnce) { - m_state.clipRect = clipRect; + getCurrentState().clipRect = clipRect; if (onlyOnce) m_onlyOnceStateFlag |= STATE_CLIP_RECT; } void DrawPool::setOpacity(const float opacity, bool onlyOnce) { - m_state.opacity = opacity; + getCurrentState().opacity = opacity; if (onlyOnce) m_onlyOnceStateFlag |= STATE_OPACITY; } void DrawPool::setShaderProgram(const PainterShaderProgramPtr& shaderProgram, bool onlyOnce, const std::function& action) { - if (g_painter->isReplaceColorShader(m_state.shaderProgram)) + if (g_painter->isReplaceColorShader(getCurrentState().shaderProgram)) return; if (shaderProgram) { if (!g_painter->isReplaceColorShader(shaderProgram.get())) m_shaderRefreshDelay = FPS20; - m_state.shaderProgram = shaderProgram.get(); - m_state.action = action; + getCurrentState().shaderProgram = shaderProgram.get(); + getCurrentState().action = action; } else { - m_state.shaderProgram = nullptr; - m_state.action = nullptr; + getCurrentState().shaderProgram = nullptr; + getCurrentState().action = nullptr; } if (onlyOnce) m_onlyOnceStateFlag |= STATE_SHADER_PROGRAM; @@ -246,7 +246,7 @@ void DrawPool::resetState() m_hashCtrl.reset(); - m_state = {}; + getCurrentState() = {}; m_lastFramebufferId = 0; m_shaderRefreshDelay = 0; m_scale = PlatformWindow::DEFAULT_DISPLAY_DENSITY; @@ -272,7 +272,7 @@ void DrawPool::scale(float factor) return; m_scale = factor; - m_state.transformMatrix = DEFAULT_MATRIX3 * Matrix3{ + getCurrentState().transformMatrix = DEFAULT_MATRIX3 * Matrix3{ factor, 0.0f, 0.0f, 0.0f, factor, 0.0f, 0.0f, 0.0f, 1.0f @@ -287,7 +287,7 @@ void DrawPool::translate(float x, float y) 0.0f, 0.0f, 1.0f }; - m_state.transformMatrix = m_state.transformMatrix * translateMatrix.transposed(); + getCurrentState().transformMatrix = getCurrentState().transformMatrix * translateMatrix.transposed(); } void DrawPool::rotate(float angle) @@ -298,7 +298,7 @@ void DrawPool::rotate(float angle) 0.0f, 0.0f, 1.0f }; - m_state.transformMatrix = m_state.transformMatrix * rotationMatrix.transposed(); + getCurrentState().transformMatrix = getCurrentState().transformMatrix * rotationMatrix.transposed(); } void DrawPool::rotate(float x, float y, float angle) @@ -310,14 +310,14 @@ void DrawPool::rotate(float x, float y, float angle) void DrawPool::pushTransformMatrix() { - m_transformMatrixStack.emplace_back(m_state.transformMatrix); + m_transformMatrixStack.emplace_back(getCurrentState().transformMatrix); assert(m_transformMatrixStack.size() < 100); } void DrawPool::popTransformMatrix() { assert(!m_transformMatrixStack.empty()); - m_state.transformMatrix = m_transformMatrixStack.back(); + getCurrentState().transformMatrix = m_transformMatrixStack.back(); m_transformMatrixStack.pop_back(); } @@ -363,15 +363,15 @@ void DrawPool::bindFrameBuffer(const Size& size, const Color& color) ++m_lastFramebufferId; if (color != Color::white) - m_state.color = color; + getCurrentState().color = color; - if (m_bindedFramebuffers == 0) { - m_oldState = std::move(m_state); - m_state = {}; - } + nextStateAndReset(); + + addAction([this, size, frameIndex = m_bindedFramebuffers] { + static const PoolState state; + + state.execute(); - addAction([this, size, frameIndex = m_bindedFramebuffers, drawState = m_state] { - drawState.execute(); const auto& frame = getTemporaryFrameBuffer(frameIndex); frame->resize(size); frame->bind(); @@ -379,12 +379,9 @@ void DrawPool::bindFrameBuffer(const Size& size, const Color& color) } void DrawPool::releaseFrameBuffer(const Rect& dest) { - if (m_bindedFramebuffers == 0) { - m_state = std::move(m_oldState); - m_oldState = {}; - } + backState(); - addAction([this, dest, frameIndex = m_bindedFramebuffers, drawState = m_state] { + addAction([this, dest, frameIndex = m_bindedFramebuffers, drawState = getCurrentState()] { const auto& frame = getTemporaryFrameBuffer(frameIndex); frame->release(); drawState.execute(); diff --git a/src/framework/graphics/drawpool.h b/src/framework/graphics/drawpool.h index ab487420d0..bb6859af8f 100644 --- a/src/framework/graphics/drawpool.h +++ b/src/framework/graphics/drawpool.h @@ -255,8 +255,11 @@ class DrawPool bool updateHash(const DrawPool::DrawMethod& method, const TexturePtr& texture, const Color& color, const bool hasCoord); PoolState getState(const TexturePtr& texture, const Color& color); - float getOpacity() const { return m_state.opacity; } - Rect getClipRect() { return m_state.clipRect; } + PoolState& getCurrentState() { return m_states[m_lastStateIndex]; } + const PoolState& getCurrentState() const { return m_states[m_lastStateIndex]; } + + float getOpacity() const { return getCurrentState().opacity; } + Rect getClipRect() { return getCurrentState().clipRect; } void setCompositionMode(CompositionMode mode, bool onlyOnce = false); void setBlendEquation(BlendEquation equation, bool onlyOnce = false); @@ -264,12 +267,12 @@ class DrawPool void setOpacity(float opacity, bool onlyOnce = false); void setShaderProgram(const PainterShaderProgramPtr& shaderProgram, bool onlyOnce = false, const std::function& action = nullptr); - void resetOpacity() { m_state.opacity = 1.f; } - void resetClipRect() { m_state.clipRect = {}; } - void resetShaderProgram() { m_state.shaderProgram = nullptr; m_state.action = nullptr; } - void resetCompositionMode() { m_state.compositionMode = CompositionMode::NORMAL; } - void resetBlendEquation() { m_state.blendEquation = BlendEquation::ADD; } - void resetTransformMatrix() { m_state.transformMatrix = DEFAULT_MATRIX3; } + void resetOpacity() { getCurrentState().opacity = 1.f; } + void resetClipRect() { getCurrentState().clipRect = {}; } + void resetShaderProgram() { getCurrentState().shaderProgram = nullptr; getCurrentState().action = nullptr; } + void resetCompositionMode() { getCurrentState().compositionMode = CompositionMode::NORMAL; } + void resetBlendEquation() { getCurrentState().blendEquation = BlendEquation::ADD; } + void resetTransformMatrix() { getCurrentState().transformMatrix = DEFAULT_MATRIX3; } void pushTransformMatrix(); void popTransformMatrix(); @@ -346,6 +349,14 @@ class DrawPool } } + void nextStateAndReset() { + m_states[++m_lastStateIndex] = {}; + } + + void backState() { + --m_lastStateIndex; + } + const FrameBufferPtr& getTemporaryFrameBuffer(const uint8_t index); bool m_enabled{ true }; @@ -357,7 +368,8 @@ class DrawPool uint32_t m_onlyOnceStateFlag{ 0 }; uint_fast64_t m_lastFramebufferId{ 0 }; - PoolState m_state, m_oldState; + PoolState m_states[10]; + uint_fast8_t m_lastStateIndex{ 0 }; DrawPoolType m_type{ DrawPoolType::LAST }; diff --git a/src/framework/graphics/drawpoolmanager.h b/src/framework/graphics/drawpoolmanager.h index d840660424..a1ac5c5344 100644 --- a/src/framework/graphics/drawpoolmanager.h +++ b/src/framework/graphics/drawpoolmanager.h @@ -62,7 +62,7 @@ class DrawPoolManager void setBlendEquation(BlendEquation equation, bool onlyOnce = false) const { getCurrentPool()->setBlendEquation(equation, onlyOnce); } void setCompositionMode(const CompositionMode mode, bool onlyOnce = false) const { getCurrentPool()->setCompositionMode(mode, onlyOnce); } - bool shaderNeedFramebuffer() const { return getCurrentPool()->m_state.shaderProgram && getCurrentPool()->m_state.shaderProgram->useFramebuffer(); } + bool shaderNeedFramebuffer() const { return getCurrentPool()->getCurrentState().shaderProgram && getCurrentPool()->getCurrentState().shaderProgram->useFramebuffer(); } void setShaderProgram(const PainterShaderProgramPtr& shaderProgram, const std::function& action) const { getCurrentPool()->setShaderProgram(shaderProgram, false, action); } void setShaderProgram(const PainterShaderProgramPtr& shaderProgram, bool onlyOnce = false, const std::function& action = nullptr) const { getCurrentPool()->setShaderProgram(shaderProgram, onlyOnce, action); }