From 5d3977bebd9fb7e68c7eec158e5ca06385372a5e Mon Sep 17 00:00:00 2001 From: ExMix Date: Tue, 30 Dec 2014 16:06:16 +0300 Subject: [PATCH] [drape] from now in drape we will use strong texturing model without texture sets. - remove texture sets (controller and sets), applying and managing - improve memory allocations for resources - rewrite font texture for dynamic glyph mapping - fragmentation unicode block on textures - some minor stuff --- drape/drape_common.pri | 3 - drape/dynamic_texture.hpp | 45 +++- drape/font_texture.cpp | 15 +- drape/font_texture.hpp | 28 ++- drape/glconstants.cpp | 2 + drape/glconstants.hpp | 1 + drape/glfunctions.cpp | 5 + drape/glfunctions.hpp | 2 + drape/glstate.cpp | 62 +++--- drape/glstate.hpp | 21 +- drape/glyph_manager.cpp | 6 + drape/glyph_manager.hpp | 5 + drape/stipple_pen_resource.cpp | 24 +-- drape/stipple_pen_resource.hpp | 25 ++- drape/symbols_texture.cpp | 12 +- drape/symbols_texture.hpp | 6 +- drape/texture.hpp | 2 +- drape/texture_manager.cpp | 344 ++++++++++++++++--------------- drape/texture_manager.hpp | 111 +++++++--- drape/texture_of_colors.cpp | 14 +- drape/texture_of_colors.hpp | 30 ++- drape/texture_set_controller.hpp | 14 -- drape/texture_set_holder.cpp | 93 --------- drape/texture_set_holder.hpp | 90 -------- 24 files changed, 460 insertions(+), 500 deletions(-) delete mode 100644 drape/texture_set_controller.hpp delete mode 100644 drape/texture_set_holder.cpp delete mode 100644 drape/texture_set_holder.hpp diff --git a/drape/drape_common.pri b/drape/drape_common.pri index 94e5c1a3f9..f172f59282 100644 --- a/drape/drape_common.pri +++ b/drape/drape_common.pri @@ -35,7 +35,6 @@ SOURCES += \ $$DRAPE_DIR/batcher_helpers.cpp \ $$DRAPE_DIR/overlay_tree.cpp \ $$DRAPE_DIR/font_texture.cpp \ - $$DRAPE_DIR/texture_set_holder.cpp \ $$DRAPE_DIR/utils/stb_image.c \ $$DRAPE_DIR/attribute_buffer_mutator.cpp \ $$DRAPE_DIR/stipple_pen_resource.cpp \ @@ -71,8 +70,6 @@ HEADERS += \ $$DRAPE_DIR/cpu_buffer.hpp \ $$DRAPE_DIR/symbols_texture.hpp \ $$DRAPE_DIR/texture_manager.hpp \ - $$DRAPE_DIR/texture_set_controller.hpp \ - $$DRAPE_DIR/texture_set_holder.hpp \ $$DRAPE_DIR/render_bucket.hpp \ $$DRAPE_DIR/overlay_handle.hpp \ $$DRAPE_DIR/index_buffer_mutator.hpp \ diff --git a/drape/dynamic_texture.hpp b/drape/dynamic_texture.hpp index 7dcd12f477..e395cfda12 100644 --- a/drape/dynamic_texture.hpp +++ b/drape/dynamic_texture.hpp @@ -1,6 +1,7 @@ #pragma once #include "texture.hpp" +#include "glconstants.hpp" namespace dp { @@ -9,29 +10,55 @@ template FindResource(Key const & key) const { + ASSERT(!m_indexer.IsNull(), ()); if (key.GetType() != TResourceType) - return NULL; + return RefPointer(); - return m_indexer.MapResource(static_cast(key)); + return m_indexer->MapResource(static_cast(key)); } virtual void UpdateState() { + ASSERT(!m_indexer.IsNull(), ()); + Bind(); - m_indexer.UploadResources(MakeStackRefPointer(this)); + m_indexer->UploadResources(MakeStackRefPointer(this)); + } + +protected: + DynamicTexture() {} + + struct TextureParams + { + m2::PointU m_size; + dp::TextureFormat m_format; + glConst m_minFilter; + glConst m_magFilter; + }; + + void Init(RefPointer indexer, TextureParams const & params) + { + m_indexer = indexer; + vector buf(params.m_size.x * params.m_size.y * 4, 0); + Create(params.m_size.x, params.m_size.y, params.m_format, MakeStackRefPointer(buf.data())); + //Create(params.m_size.x, params.m_size.y, params.m_format); + SetFilterParams(params.m_minFilter, params.m_magFilter); + } + + void Reset() + { + m_indexer = RefPointer(); } private: - mutable TIndexer m_indexer; + mutable RefPointer m_indexer; }; } diff --git a/drape/font_texture.cpp b/drape/font_texture.cpp index 817ad66d37..d643a3172b 100644 --- a/drape/font_texture.cpp +++ b/drape/font_texture.cpp @@ -83,26 +83,26 @@ GlyphIndex::GlyphIndex(m2::PointU size, RefPointer mng) { } -GlyphInfo const * GlyphIndex::MapResource(GlyphKey const & key) +RefPointer GlyphIndex::MapResource(GlyphKey const & key) { strings::UniChar uniChar = key.GetUnicodePoint(); auto it = m_index.find(uniChar); if (it != m_index.end()) - return it->second.GetRaw(); + return MakeStackRefPointer(&it->second); GlyphManager::Glyph glyph = m_mng->GetGlyph(uniChar); m2::RectU r; if (!m_packer.PackGlyph(glyph.m_image.m_width, glyph.m_image.m_height, r)) { glyph.m_image.Destroy(); - return nullptr; + return RefPointer(); } m_pendingNodes.emplace_back(r, glyph); - auto res = m_index.emplace(uniChar, TResourcePtr(new GlyphInfo(m_packer.MapTextureCoords(r), glyph.m_metrics))); - ASSERT(!res.second, ()); - return res.first->second.GetRaw(); + auto res = m_index.emplace(uniChar, GlyphInfo(m_packer.MapTextureCoords(r), glyph.m_metrics)); + ASSERT(res.second, ()); + return MakeStackRefPointer(&res.first->second); } void GlyphIndex::UploadResources(RefPointer texture) @@ -148,6 +148,9 @@ void GlyphIndex::UploadResources(RefPointer texture) { GlyphManager::Glyph & glyph = m_pendingNodes[node].second; m2::RectU rect = m_pendingNodes[node].first; + if (rect.SizeX() == 0 || rect.SizeY() == 0) + continue; + rect.Offset(-zeroPoint); uint32_t w = rect.SizeX(); diff --git a/drape/font_texture.hpp b/drape/font_texture.hpp index 1a044ade85..01867d91c6 100644 --- a/drape/font_texture.hpp +++ b/drape/font_texture.hpp @@ -3,6 +3,7 @@ #include "pointers.hpp" #include "texture.hpp" #include "glyph_manager.hpp" +#include "dynamic_texture.hpp" #include "../std/map.hpp" #include "../std/vector.hpp" @@ -62,7 +63,7 @@ public: GlyphIndex(m2::PointU size, RefPointer mng); /// can return nullptr - GlyphInfo const * MapResource(GlyphKey const & key); + RefPointer MapResource(GlyphKey const & key); void UploadResources(RefPointer texture); glConst GetMinFilter() const { return gl_const::GLLinear; } @@ -72,8 +73,7 @@ private: GlyphPacker m_packer; RefPointer m_mng; - typedef MasterPointer TResourcePtr; - typedef map TResourceMapping; + typedef map TResourceMapping; typedef pair TPendingNode; typedef vector TPendingNodes; @@ -81,4 +81,26 @@ private: TPendingNodes m_pendingNodes; }; +class FontTexture : public DynamicTexture +{ + typedef DynamicTexture TBase; +public: + FontTexture(m2::PointU const & size, RefPointer glyphMng) + : m_index(size, glyphMng) + { + TBase::TextureParams params; + params.m_size = size; + params.m_format = TextureFormat::ALPHA; + params.m_minFilter = gl_const::GLLinear; + params.m_magFilter = gl_const::GLLinear; + + TBase::Init(MakeStackRefPointer(&m_index), params); + } + + ~FontTexture() { TBase::Reset(); } + +private: + GlyphIndex m_index; +}; + } diff --git a/drape/glconstants.cpp b/drape/glconstants.cpp index ae52531df2..8d54dd4465 100644 --- a/drape/glconstants.cpp +++ b/drape/glconstants.cpp @@ -36,6 +36,8 @@ namespace gl_const { +const glConst GLUnpackAlignment = GL_UNPACK_ALIGNMENT; + const glConst GLMaxFragmentTextures = GL_MAX_TEXTURE_IMAGE_UNITS; const glConst GLMaxVertexTextures = GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS; const glConst GLMaxTextureSize = GL_MAX_TEXTURE_SIZE; diff --git a/drape/glconstants.hpp b/drape/glconstants.hpp index f0fe3ec559..fa200ffb5d 100644 --- a/drape/glconstants.hpp +++ b/drape/glconstants.hpp @@ -6,6 +6,7 @@ typedef uint32_t glConst; namespace gl_const { +extern const glConst GLUnpackAlignment; /// Hardware specific params extern const glConst GLMaxFragmentTextures; diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp index 6468306871..622743f0ab 100644 --- a/drape/glfunctions.cpp +++ b/drape/glfunctions.cpp @@ -233,6 +233,11 @@ void GLFunctions::glFlush() GLCHECK(glFlushFn()); } +void GLFunctions::glPixelStore(glConst name, uint32_t value) +{ + GLCHECK(::glPixelStorei(name, value)); +} + int32_t GLFunctions::glGetInteger(glConst pname) { GLint value; diff --git a/drape/glfunctions.hpp b/drape/glfunctions.hpp index b8396ce175..34045ef28d 100644 --- a/drape/glfunctions.hpp +++ b/drape/glfunctions.hpp @@ -15,6 +15,8 @@ public: static void glViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h); static void glFlush(); + static void glPixelStore(glConst name, uint32_t value); + static int32_t glGetInteger(glConst pname); static void glEnable(glConst mode); diff --git a/drape/glstate.cpp b/drape/glstate.cpp index e09385f398..3e9dc36dae 100644 --- a/drape/glstate.cpp +++ b/drape/glstate.cpp @@ -52,47 +52,30 @@ bool Blending::operator == (Blending const & other) const GLState::GLState(uint32_t gpuProgramIndex, DepthLayer depthLayer) : m_gpuProgramIndex(gpuProgramIndex) , m_depthLayer(depthLayer) - , m_textureSet(-1) - , m_mask(0) { } -void GLState::SetTextureSet(int32_t textureSet) -{ - m_mask |= TEXTURE_BIT; - m_textureSet = textureSet; -} - -bool GLState::HasTextureSet() const -{ - return (m_mask & TEXTURE_BIT) != 0; -} - -void GLState::SetBlending(Blending const & blending) -{ - m_blending = blending; -} - bool GLState::operator<(GLState const & other) const { - if (m_mask != other.m_mask) - return m_mask < other.m_mask; - if (m_depthLayer != other.m_depthLayer) return m_depthLayer < other.m_depthLayer; + if (!(m_blending == other.m_blending)) + return m_blending < other.m_blending; if (m_gpuProgramIndex != other.m_gpuProgramIndex) return m_gpuProgramIndex < other.m_gpuProgramIndex; + if (m_colorTexture.GetRaw() != other.m_colorTexture.GetRaw()) + return m_colorTexture.GetRaw() < other.m_colorTexture.GetRaw(); - return m_textureSet < other.m_textureSet; + return m_maskTexture.GetRaw() < other.m_maskTexture.GetRaw(); } bool GLState::operator==(GLState const & other) const { - return m_mask == other.m_mask && - m_depthLayer == other.m_depthLayer && + return m_depthLayer == other.m_depthLayer && m_gpuProgramIndex == other.m_gpuProgramIndex && - m_textureSet == other.m_textureSet && - m_blending == other.m_blending; + m_blending == other.m_blending && + m_colorTexture == other.m_colorTexture && + m_maskTexture == other.m_maskTexture; } namespace @@ -108,22 +91,25 @@ void ApplyUniforms(UniformValuesStorage const & uniforms, RefPointer uniforms.ForeachValue(bind(&ApplyUniformValue, _1, program)); } -void ApplyState(GLState state, RefPointer program, - RefPointer textures) +void ApplyState(GLState state, RefPointer program) { - if (state.HasTextureSet()) + RefPointer tex = state.GetColorTexture(); + if (!tex.IsNull()) { - uint32_t textureSet = state.GetTextureSet(); - uint32_t count = textures->GetTextureCount(textureSet); - textures->BindTextureSet(textureSet); - buffer_vector ids; - for (uint32_t i = 0; i < count; ++i) - ids.push_back(i); - - int8_t location = program->GetUniformLocation("u_textures"); - GLFunctions::glUniformValueiv(location, ids.data(), count); + int8_t colorTexLoc = program->GetUniformLocation("u_colorTex"); + GLFunctions::glActiveTexture(gl_const::GLTexture0); + tex->Bind(); + GLFunctions::glUniformValuei(colorTexLoc, 0); } + tex = state.GetMaskTexture(); + if (!tex.IsNull()) + { + int8_t maskTexLoc = program->GetUniformLocation("u_maskTex"); + GLFunctions::glActiveTexture(gl_const::GLTexture0 + 1); + tex->Bind(); + GLFunctions::glUniformValuei(maskTexLoc, 1); + } state.GetBlending().Apply(); } diff --git a/drape/glstate.hpp b/drape/glstate.hpp index 0225c377de..2f6dd8f8ad 100644 --- a/drape/glstate.hpp +++ b/drape/glstate.hpp @@ -1,9 +1,9 @@ #pragma once #include "pointers.hpp" +#include "texture.hpp" +#include "gpu_program.hpp" #include "uniform_values_storage.hpp" -#include "texture_set_controller.hpp" -#include "color.hpp" namespace dp { @@ -38,11 +38,13 @@ public: DepthLayer const & GetDepthLayer() const { return m_depthLayer; } - void SetTextureSet(int32_t textureSet); - int32_t GetTextureSet() const { return m_textureSet; } - bool HasTextureSet() const; + void SetColorTexture(RefPointer tex) { m_colorTexture = tex; } + RefPointer GetColorTexture() const { return m_colorTexture; } - void SetBlending(Blending const & blending); + void SetMaskTexture(RefPointer tex) { m_maskTexture = tex; } + RefPointer GetMaskTexture() const { return m_maskTexture; } + + void SetBlending(Blending const & blending) { m_blending = blending; } Blending const & GetBlending() const { return m_blending; } int GetProgramIndex() const { return m_gpuProgramIndex; } @@ -53,12 +55,13 @@ public: private: uint32_t m_gpuProgramIndex; DepthLayer m_depthLayer; - int32_t m_textureSet; Blending m_blending; - uint32_t m_mask; + + RefPointer m_colorTexture; + RefPointer m_maskTexture; }; void ApplyUniforms(UniformValuesStorage const & uniforms, RefPointer program); -void ApplyState(GLState state, RefPointer program, RefPointer textures); +void ApplyState(GLState state, RefPointer program); } // namespace dp diff --git a/drape/glyph_manager.cpp b/drape/glyph_manager.cpp index a4789580c6..b64925dd64 100644 --- a/drape/glyph_manager.cpp +++ b/drape/glyph_manager.cpp @@ -473,6 +473,12 @@ GlyphManager::Glyph GlyphManager::GetGlyph(strings::UniChar unicodePoint) return GetInvalidGlyph(); } +void GlyphManager::ForEachUnicodeBlock(GlyphManager::TUniBlockCallback const & fn) +{ + for (UnicodeBlock const & uni : m_impl->m_blocks) + fn(uni.m_start, uni.m_end); +} + GlyphManager::Glyph GlyphManager::GetInvalidGlyph() const { static bool s_inited = false; diff --git a/drape/glyph_manager.hpp b/drape/glyph_manager.hpp index 6b14e4f156..6de6750a62 100644 --- a/drape/glyph_manager.hpp +++ b/drape/glyph_manager.hpp @@ -7,6 +7,8 @@ #include "../std/string.hpp" #include "../std/vector.hpp" +#include "../std/function.hpp" + namespace dp { @@ -63,6 +65,9 @@ public: Glyph GetGlyph(strings::UniChar unicodePoints); + typedef function TUniBlockCallback; + void ForEachUnicodeBlock(TUniBlockCallback const & fn); + private: Glyph GetInvalidGlyph() const; diff --git a/drape/stipple_pen_resource.cpp b/drape/stipple_pen_resource.cpp index 36a2e4d391..fd16237a52 100644 --- a/drape/stipple_pen_resource.cpp +++ b/drape/stipple_pen_resource.cpp @@ -14,12 +14,6 @@ namespace dp uint32_t const MAX_STIPPLE_PEN_LENGTH = 254; uint32_t const COLUMN_WIDTH = MAX_STIPPLE_PEN_LENGTH + 2; -StipplePenKey const & StipplePenKey::Solid() -{ - static StipplePenKey solidKey(buffer_vector((size_t)1, (uint8_t)1)); - return solidKey; -} - StipplePenPacker::StipplePenPacker(m2::PointU const & canvasSize) : m_canvasSize(canvasSize) , m_currentColumn(0) @@ -144,24 +138,22 @@ void StipplePenRasterizator::Rasterize(void * buffer) memcpy(pixels + COLUMN_WIDTH, pixels, COLUMN_WIDTH); } -StipplePenResourceInfo const * StipplePenIndex::MapResource(StipplePenKey const & key) +RefPointer StipplePenIndex::MapResource(StipplePenKey const & key) { StipplePenHandle handle(key); - TResourceMapping::const_iterator it = m_resourceMapping.find(handle); + TResourceMapping::iterator it = m_resourceMapping.find(handle); if (it != m_resourceMapping.end()) - return it->second.GetRaw(); + return MakeStackRefPointer(&it->second); StipplePenRasterizator resource(key); m2::RectU pixelRect = m_packer.PackResource(resource.GetSize()); m_pendingNodes.push_back(make_pair(pixelRect, resource)); - typedef pair TInsertionNode; - MasterPointer info(new StipplePenResourceInfo(m_packer.MapTextureCoords(pixelRect), - resource.GetSize(), - resource.GetPatternSize())); - TInsertionNode result = m_resourceMapping.insert(TResourceMapping::value_type(handle, info)); - ASSERT(result.second, ()); - return result.first->second.GetRaw(); + auto res = m_resourceMapping.emplace(handle, StipplePenResourceInfo(m_packer.MapTextureCoords(pixelRect), + resource.GetSize(), + resource.GetPatternSize())); + ASSERT(res.second, ()); + return MakeStackRefPointer(&res.first->second); } void StipplePenIndex::UploadResources(RefPointer texture) diff --git a/drape/stipple_pen_resource.hpp b/drape/stipple_pen_resource.hpp index 094542325f..769c98bda9 100644 --- a/drape/stipple_pen_resource.hpp +++ b/drape/stipple_pen_resource.hpp @@ -3,6 +3,7 @@ #include "drape_global.hpp" #include "pointers.hpp" #include "texture.hpp" +#include "dynamic_texture.hpp" #include "../base/buffer_vector.hpp" @@ -21,8 +22,6 @@ public: StipplePenKey(buffer_vector const & pattern) : m_pattern(pattern) {} virtual Texture::ResourceType GetType() const { return Texture::StipplePen; } - static StipplePenKey const & Solid(); - buffer_vector m_pattern; }; @@ -99,14 +98,13 @@ class StipplePenIndex { public: StipplePenIndex(m2::PointU const & canvasSize) : m_packer(canvasSize) {} - StipplePenResourceInfo const * MapResource(StipplePenKey const & key); + RefPointer MapResource(StipplePenKey const & key); void UploadResources(RefPointer texture); glConst GetMinFilter() const; glConst GetMagFilter() const; private: - typedef MasterPointer TResourcePtr; - typedef map TResourceMapping; + typedef map TResourceMapping; typedef pair TPendingNode; typedef buffer_vector TPendingNodes; @@ -117,4 +115,21 @@ private: string DebugPrint(StipplePenHandle const & key); +class StipplePenTexture : public DynamicTexture +{ + typedef DynamicTexture TBase; +public: + StipplePenTexture(m2::PointU const & size) + : m_index(size) + { + TBase::TextureParams params{ size, TextureFormat::ALPHA, gl_const::GLNearest, gl_const::GLNearest }; + TBase::Init(MakeStackRefPointer(&m_index), params); + } + + ~StipplePenTexture() { TBase::Reset(); } + +private: + StipplePenIndex m_index; +}; + } diff --git a/drape/symbols_texture.cpp b/drape/symbols_texture.cpp index 6ca2f73627..c75062d26b 100644 --- a/drape/symbols_texture.cpp +++ b/drape/symbols_texture.cpp @@ -14,7 +14,7 @@ namespace dp class SymbolsTexture::DefinitionLoader { public: - DefinitionLoader(SymbolsTexture::tex_definition_t & definition) + DefinitionLoader(SymbolsTexture::TSymDefinition & definition) : m_def(definition) , m_width(0) , m_height(0) @@ -79,7 +79,7 @@ public: uint32_t GetHeight() const { return m_height; } private: - SymbolsTexture::tex_definition_t & m_def; + SymbolsTexture::TSymDefinition & m_def; uint32_t m_width; uint32_t m_height; @@ -161,16 +161,16 @@ void SymbolsTexture::Load(string const & skinPathName) stbi_image_free(data); } -Texture::ResourceInfo const * SymbolsTexture::FindResource(Texture::Key const & key) const +RefPointer SymbolsTexture::FindResource(Texture::Key const & key) const { if (key.GetType() != Texture::Symbol) - return NULL; + return RefPointer(); string const & symbolName = static_cast(key).GetSymbolName(); - tex_definition_t::const_iterator it = m_definition.find(symbolName); + TSymDefinition::iterator it = m_definition.find(symbolName); ASSERT(it != m_definition.end(), ()); - return &(it->second); + return MakeStackRefPointer(&it->second); } void SymbolsTexture::Fail() diff --git a/drape/symbols_texture.hpp b/drape/symbols_texture.hpp index 5fbc662c3e..d55ab7c471 100644 --- a/drape/symbols_texture.hpp +++ b/drape/symbols_texture.hpp @@ -30,14 +30,14 @@ public: }; void Load(string const & skinPathName); - ResourceInfo const * FindResource(Key const & key) const; + RefPointer FindResource(Key const & key) const; private: void Fail(); private: - typedef map tex_definition_t; - tex_definition_t m_definition; + typedef map TSymDefinition; + mutable TSymDefinition m_definition; class DefinitionLoader; }; diff --git a/drape/texture.hpp b/drape/texture.hpp index 5b1a7f1485..71c27570d2 100644 --- a/drape/texture.hpp +++ b/drape/texture.hpp @@ -55,7 +55,7 @@ public: void UploadData(uint32_t x, uint32_t y, uint32_t width, uint32_t height, TextureFormat format, RefPointer data); - virtual ResourceInfo const * FindResource(Key const & key) const = 0; + virtual RefPointer FindResource(Key const & key) const = 0; virtual void UpdateState() {} TextureFormat GetFormat() const; diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp index 56c2226fb0..44807407cb 100644 --- a/drape/texture_manager.cpp +++ b/drape/texture_manager.cpp @@ -1,7 +1,6 @@ #include "texture_manager.hpp" #include "symbols_texture.hpp" #include "font_texture.hpp" -#include "dynamic_texture.hpp" #include "stipple_pen_resource.hpp" #include "texture_of_colors.hpp" @@ -19,203 +18,220 @@ namespace dp { -class TextureManager::TextureSet +bool TextureManager::BaseRegion::IsValid() const { -public: - TextureSet(uint32_t maxSize) - : m_maxSize(maxSize) - { - } + return !m_info.IsNull() && !m_texture.IsNull(); +} - ~TextureSet() - { - GetRangeDeletor(m_textures, MasterPointerDeleter())(); - } - - bool IsFull() const - { - return !(m_textures.size() < m_maxSize); - } - - void AddTexture(TransferPointer texture) - { - ASSERT(!IsFull(), ()); - m_textures.push_back(MasterPointer(texture)); - } - - Texture::ResourceInfo const * FindResource(Texture::Key const & key, - TextureManager::TextureNode & node) const - { - for (size_t i = 0; i < m_textures.size(); ++i) - { - RefPointer texture = m_textures[i].GetRefPointer(); - Texture::ResourceInfo const * info = texture->FindResource(key); - if (info != NULL) - { - node.m_width = texture->GetWidth(); - node.m_height = texture->GetHeight(); - node.m_textureOffset = i; - return info; - } - } - - return NULL; - } - - void UpdateDynamicTextures() - { - for_each(m_textures.begin(), m_textures.end(), bind(&Texture::UpdateState, - bind(&NonConstGetter, _1))); - } - - void BindTextureSet() const - { - for (size_t i = 0; i < m_textures.size(); ++i) - { - GLFunctions::glActiveTexture(gl_const::GLTexture0 + i); - m_textures[i]->Bind(); - } - } - - uint32_t GetSize() const - { - return m_textures.size(); - } - -private: - vector > m_textures; - uint32_t m_maxSize; -}; - -int TextureManager::GetMaxTextureSet() const +void TextureManager::BaseRegion::SetResourceInfo(RefPointer info) { - return m_textures.size(); + m_info = info; +} + +void TextureManager::BaseRegion::SetTexture(RefPointer texture) +{ + m_texture = texture; +} + +void TextureManager::BaseRegion::GetPixelSize(m2::PointU & size) const +{ + ASSERT(IsValid(), ()); + m2::RectF const & texRect = m_info->GetTexRect(); + size.x = ceil(texRect.SizeX() * m_texture->GetWidth()); + size.y = ceil(texRect.SizeY() * m_texture->GetHeight()); +} + +uint32_t TextureManager::BaseRegion::GetPixelHeight() const +{ + return ceil(m_info->GetTexRect().SizeY() * m_texture->GetHeight()); +} + +m2::RectF const & TextureManager::BaseRegion::GetTexRect() const +{ + return m_info->GetTexRect(); +} + +TextureManager::GlyphRegion::GlyphRegion() + : BaseRegion() +{ +} + +float TextureManager::GlyphRegion::GetOffsetX() const +{ + ASSERT(m_info->GetType() == Texture::Glyph, ()); + GlyphInfo const * info = static_cast(m_info.GetRaw()); + return info->GetMetrics().m_xOffset; +} + +float TextureManager::GlyphRegion::GetOffsetY() const +{ + ASSERT(m_info->GetType() == Texture::Glyph, ()); + GlyphInfo const * info = static_cast(m_info.GetRaw()); + return info->GetMetrics().m_yOffset; +} + +float TextureManager::GlyphRegion::GetAdvanceX() const +{ + ASSERT(m_info->GetType() == Texture::Glyph, ()); + GlyphInfo const * info = static_cast(m_info.GetRaw()); + return info->GetMetrics().m_xAdvance; +} + +float TextureManager::GlyphRegion::GetAdvanceY() const +{ + ASSERT(m_info->GetType() == Texture::Glyph, ()); + GlyphInfo const * info = static_cast(m_info.GetRaw()); + return info->GetMetrics().m_yAdvance; +} + +uint32_t TextureManager::StippleRegion::GetMaskPixelLength() const +{ + ASSERT(m_info->GetType() == Texture::StipplePen, ()); + return static_cast(m_info.GetRaw())->GetMaskPixelLength(); +} + +uint32_t TextureManager::StippleRegion::GetPatternPixelLength() const +{ + ASSERT(m_info->GetType() == Texture::StipplePen, ()); + return static_cast(m_info.GetRaw())->GetPatternPixelLength(); } void TextureManager::UpdateDynamicTextures() { - for_each(m_textures.begin(), m_textures.end(), bind(&TextureSet::UpdateDynamicTextures, - bind(&NonConstGetter, _1))); + m_colorTexture->UpdateState(); + m_stipplePenTexture->UpdateState(); + for_each(m_glyphGroups.begin(), m_glyphGroups.end(), [](GlyphGroup & g) + { + if (!g.m_texture.IsNull()) + g.m_texture->UpdateState(); + }); + + for_each(m_hybridGlyphGroups.begin(), m_hybridGlyphGroups.end(), [](MasterPointer texture) + { + texture->UpdateState(); + }); } -void TextureManager::Init(string const & resourcePrefix) +void TextureManager::AllocateGlyphTexture(TextureManager::GlyphGroup & group) const { - // in shader we handle only 8 textures - m_maxTextureBlocks = min(8, GLFunctions::glGetInteger(gl_const::GLMaxFragmentTextures)); + group.m_texture.Reset(new FontTexture(m2::PointU(m_maxTextureSize, m_maxTextureSize), m_glyphManager.GetRefPointer())); +} + +void TextureManager::Init(Params const & params) +{ + GLFunctions::glPixelStore(gl_const::GLUnpackAlignment, 1); SymbolsTexture * symbols = new SymbolsTexture(); - symbols->Load(my::JoinFoldersToPath(string("resources-") + resourcePrefix, "symbols")); + symbols->Load(my::JoinFoldersToPath(string("resources-") + params.m_resPrefix, "symbols")); + m_symbolTexture.Reset(symbols); - TextureSet * defaultSet = new TextureSet(m_maxTextureBlocks); - defaultSet->AddTexture(MovePointer(symbols)); + m_stipplePenTexture.Reset(new StipplePenTexture(m2::PointU(1024, 1024))); + m_colorTexture.Reset(new ColorTexture(m2::PointU(1024, 1024))); - typedef DynamicTexture TStippleTexture; - typedef DynamicTexture TColorTexture; - defaultSet->AddTexture(MovePointer(new TStippleTexture(m2::PointU(1024, 1024), dp::ALPHA))); - defaultSet->AddTexture(MovePointer(new TColorTexture(m2::PointU(1024, 1024), dp::RGBA8))); + m_glyphManager.Reset(new GlyphManager(params.m_glyphMngParams)); + m_maxTextureSize = min(8192, GLFunctions::glGetInteger(gl_const::GLMaxTextureSize)); - m_textures.push_back(MasterPointer(defaultSet)); + uint32_t textureSquare = m_maxTextureSize * m_maxTextureSize; + uint32_t baseGlyphHeight = params.m_glyphMngParams.m_baseGlyphHeight; + uint32_t avarageGlyphSquare = baseGlyphHeight * baseGlyphHeight; - vector > tempTextures; -// LoadFont(string("resources-common/font"), tempTextures); -// for (size_t i = 0; i < tempTextures.size(); ++i) -// { -// RefPointer set = m_textures.back().GetRefPointer(); -// if (set->IsFull()) -// { -// m_textures.push_back(MasterPointer(new TextureSet(m_maxTextureBlocks))); -// set = m_textures.back().GetRefPointer(); -// } + m_glyphGroups.push_back(GlyphGroup()); + uint32_t glyphCount = ceil(0.9 * textureSquare / avarageGlyphSquare); + m_glyphManager->ForEachUnicodeBlock([this, glyphCount](strings::UniChar const & start, strings::UniChar const & end) + { + if (m_glyphGroups.empty()) + { + m_glyphGroups.push_back(GlyphGroup(start, end)); + return; + } -// set->AddTexture(tempTextures[i]); -// } + GlyphGroup & group = m_glyphGroups.back(); + ASSERT_LESS_OR_EQUAL(group.m_endChar, start, ()); -// RefPointer textureSet = m_textures.back().GetRefPointer(); -// if (textureSet->IsFull()) -// { -// m_textures.push_back(MasterPointer(new TextureSet(m_maxTextureBlocks))); -// textureSet = m_textures.back().GetRefPointer(); -// } + if (end - group.m_startChar < glyphCount) + { + group.m_endChar = end; + } + else + m_glyphGroups.push_back(GlyphGroup(start, end)); + }); } void TextureManager::Release() { - DeleteRange(m_textures, MasterPointerDeleter()); + m_symbolTexture.Destroy(); + m_stipplePenTexture.Destroy(); + m_colorTexture.Destroy(); + + DeleteRange(m_glyphGroups, [](GlyphGroup & g) + { + g.m_texture.Destroy(); + }); + + DeleteRange(m_hybridGlyphGroups, MasterPointerDeleter()); } void TextureManager::GetSymbolRegion(string const & symbolName, SymbolRegion & region) const { - SymbolsTexture::SymbolKey key(symbolName); - TextureNode node; - node.m_textureSet = 0; - Texture::ResourceInfo const * info = m_textures[0]->FindResource(key, node); - ASSERT(node.m_textureOffset != -1, ()); - region.SetResourceInfo(info); - region.SetTextureNode(node); + region.SetResourceInfo(m_symbolTexture->FindResource(SymbolsTexture::SymbolKey(symbolName))); + region.SetTexture(m_symbolTexture.GetRefPointer()); + ASSERT(region.IsValid(), ()); } -template -bool TextureManager::FindResource(TKey const & key, TRegion & region) const +void TextureManager::GetStippleRegion(TStipplePattern const & pen, StippleRegion & region) const { - for (size_t i = 0; i < m_textures.size(); ++i) + region.SetResourceInfo(m_stipplePenTexture->FindResource(StipplePenKey(pen))); + region.SetTexture(m_stipplePenTexture.GetRefPointer()); + ASSERT(region.IsValid(), ()); +} + +void TextureManager::GetColorRegion(Color const & color, ColorRegion & region) const +{ + region.SetResourceInfo(m_colorTexture->FindResource(ColorKey(color))); + region.SetTexture(m_colorTexture.GetRefPointer()); + ASSERT(region.IsValid(), ()); +} + +void TextureManager::GetGlyphRegions(strings::UniString const & text, TGlyphsBuffer & regions) const +{ + size_t const INVALID_GROUP = static_cast(-1); + size_t groupIndex = INVALID_GROUP; + for (strings::UniChar const & c : text) { - TextureNode node; - Texture::ResourceInfo const * info = m_textures[i]->FindResource(key, node); - if (info != NULL) + auto iter = lower_bound(m_glyphGroups.begin(), m_glyphGroups.end(), c, [](GlyphGroup const & g, strings::UniChar const & c) { - node.m_textureSet = i; - region.SetTextureNode(node); - region.SetResourceInfo(info); - return true; + return g.m_endChar < c; + }); + ASSERT(iter != m_glyphGroups.end(), ()); + size_t currentIndex = distance(m_glyphGroups.begin(), iter); + if (groupIndex == INVALID_GROUP) + groupIndex = currentIndex; + else if (groupIndex != currentIndex) + { + groupIndex = INVALID_GROUP; + break; } } - return false; -} + regions.reserve(text.size()); + if (groupIndex == INVALID_GROUP) + { + /// some magic with hybrid textures + } + else + { + GlyphGroup & group = m_glyphGroups[groupIndex]; + if (group.m_texture.IsNull()) + AllocateGlyphTexture(group); -bool TextureManager::GetGlyphRegion(strings::UniChar charCode, GlyphRegion & region) const -{ - //FontTexture::GlyphKey key(charCode); - //return FindResource(key, region); - return false; -} - -void TextureManager::GetStippleRegion(StipplePenKey const & pen, TextureSetHolder::StippleRegion & region) const -{ - VERIFY(FindResource(pen, region), ()); -} - -void TextureManager::GetColorRegion(ColorKey const & pen, TextureSetHolder::ColorRegion & region) const -{ - VERIFY(FindResource(pen, region), ()); -} - - -void TextureManager::BindTextureSet(uint32_t textureSet) const -{ - ASSERT_LESS(textureSet, m_textures.size(), ()); - m_textures[textureSet]->BindTextureSet(); -} - -uint32_t TextureManager::GetTextureCount(uint32_t textureSet) const -{ - ASSERT_LESS(textureSet, m_textures.size(), ()); - return m_textures[textureSet]->GetSize(); -} - - -TextureSetBinder::TextureSetBinder(RefPointer manager) - : m_manager(manager) -{ -} - -void TextureSetBinder::BindTextureSet(uint32_t textureSet) const -{ - m_manager->BindTextureSet(textureSet); -} - -uint32_t TextureSetBinder::GetTextureCount(uint32_t textureSet) const -{ - return m_manager->GetTextureCount(textureSet); + RefPointer texture = group.m_texture.GetRefPointer(); + for (strings::UniChar const & c : text) + { + GlyphRegion reg; + reg.SetResourceInfo(texture->FindResource(GlyphKey(c))); + reg.SetTexture(texture); + regions.push_back(reg); + } + } } } // namespace dp diff --git a/drape/texture_manager.hpp b/drape/texture_manager.hpp index 7cf1227168..8a5ca4bbac 100644 --- a/drape/texture_manager.hpp +++ b/drape/texture_manager.hpp @@ -2,48 +2,105 @@ #include "../base/string_utils.hpp" +#include "color.hpp" #include "pointers.hpp" -#include "texture_set_holder.hpp" -#include "texture_set_controller.hpp" +#include "texture.hpp" +#include "glyph_manager.hpp" namespace dp { -class TextureManager : public TextureSetHolder +class TextureManager { public: - void Init(string const & resourcePrefix); + class BaseRegion + { + public: + void SetResourceInfo(RefPointer info); + void SetTexture(RefPointer texture); + RefPointer GetTexture() const { return m_texture; } + bool IsValid() const; + + void GetPixelSize(m2::PointU & size) const; + uint32_t GetPixelHeight() const; + m2::RectF const & GetTexRect() const; + + protected: + RefPointer m_info; + RefPointer m_texture; + }; + + class SymbolRegion : public BaseRegion {}; + + class GlyphRegion : public BaseRegion + { + public: + GlyphRegion(); + + float GetOffsetX() const; + float GetOffsetY() const; + float GetAdvanceX() const; + float GetAdvanceY() const; + }; + + class StippleRegion : public BaseRegion + { + public: + StippleRegion() : BaseRegion() {} + + uint32_t GetMaskPixelLength() const; + uint32_t GetPatternPixelLength() const; + }; + + class ColorRegion : public BaseRegion + { + public: + ColorRegion() : BaseRegion() {} + }; + + struct Params + { + string m_resPrefix; + GlyphManager::Params m_glyphMngParams; + }; + + void Init(Params const & params); void Release(); - virtual void GetSymbolRegion(string const & symbolName, SymbolRegion & region) const; - virtual bool GetGlyphRegion(strings::UniChar charCode, GlyphRegion & region) const; - virtual void GetStippleRegion(StipplePenKey const & pen, StippleRegion & region) const; - virtual void GetColorRegion(ColorKey const & pen, TextureSetHolder::ColorRegion & region) const; - virtual int GetMaxTextureSet() const; + void GetSymbolRegion(string const & symbolName, SymbolRegion & region) const; + typedef buffer_vector TStipplePattern; + void GetStippleRegion(TStipplePattern const & pen, StippleRegion & region) const; + void GetColorRegion(Color const & color, ColorRegion & region) const; - virtual void UpdateDynamicTextures(); - - void BindTextureSet(uint32_t textureSet) const; - uint32_t GetTextureCount(uint32_t textureSet) const; + typedef buffer_vector TGlyphsBuffer; + void GetGlyphRegions(strings::UniString const & text, TGlyphsBuffer & regions) const; + void UpdateDynamicTextures(); private: - template - bool FindResource(TKey const & key, TRegion & region) const; + struct GlyphGroup + { + GlyphGroup() = default; + GlyphGroup(strings::UniChar const & start, strings::UniChar const & end) + : m_startChar(start), m_endChar(end) {} + + strings::UniChar m_startChar = 0; + strings::UniChar m_endChar = 0; + + MasterPointer m_texture; + }; + + uint32_t m_maxTextureSize; + + void AllocateGlyphTexture(TextureManager::GlyphGroup & group) const; private: - class TextureSet; - vector > m_textures; - uint32_t m_maxTextureBlocks; -}; + MasterPointer m_symbolTexture; + MasterPointer m_stipplePenTexture; + MasterPointer m_colorTexture; -class TextureSetBinder : public TextureSetController -{ -public: - TextureSetBinder(RefPointer manager); - void BindTextureSet(uint32_t textureSet) const; - uint32_t GetTextureCount(uint32_t textureSet) const; + MasterPointer m_glyphManager; -private: - RefPointer m_manager; + mutable buffer_vector m_glyphGroups; + mutable buffer_vector, 4> m_hybridGlyphGroups; }; } // namespace dp diff --git a/drape/texture_of_colors.cpp b/drape/texture_of_colors.cpp index 94d7e7d8f7..95bdaa916c 100644 --- a/drape/texture_of_colors.cpp +++ b/drape/texture_of_colors.cpp @@ -20,12 +20,7 @@ ColorPalette::ColorPalette(m2::PointU const & canvasSize) , m_cursor(m2::PointU::Zero()) {} -ColorPalette::~ColorPalette() -{ - DeleteRange(m_palette, MasterPointerDeleter()); -} - -ColorResourceInfo const * ColorPalette::MapResource(ColorKey const & key) +RefPointer ColorPalette::MapResource(ColorKey const & key) { TPalette::iterator itm = m_palette.find(key.m_color); if (itm == m_palette.end()) @@ -50,10 +45,11 @@ ColorResourceInfo const * ColorPalette::MapResource(ColorKey const & key) m2::PointF const resCenter = m2::RectF(pendingColor.m_rect).Center(); float const x = resCenter.x / sizeX; float const y = resCenter.y / sizeY; - TResourcePtr resourcePtr(new ColorResourceInfo(m2::RectF(x, y, x, y))); - itm = m_palette.insert(make_pair(key.m_color, resourcePtr)).first; + auto res = m_palette.emplace(key.m_color, ColorResourceInfo(m2::RectF(x, y, x, y))); + ASSERT(res.second, ()); + itm = res.first; } - return itm->second.GetRaw(); + return MakeStackRefPointer(&itm->second); } void ColorPalette::UploadResources(RefPointer texture) diff --git a/drape/texture_of_colors.hpp b/drape/texture_of_colors.hpp index 80e6d2b574..5619692bfa 100644 --- a/drape/texture_of_colors.hpp +++ b/drape/texture_of_colors.hpp @@ -2,6 +2,7 @@ #include "texture.hpp" #include "color.hpp" +#include "dynamic_texture.hpp" #include "../base/buffer_vector.hpp" @@ -28,8 +29,8 @@ class ColorPalette { public: ColorPalette(m2::PointU const & canvasSize); - ~ColorPalette(); - ColorResourceInfo const * MapResource(ColorKey const & key); + + RefPointer MapResource(ColorKey const & key); void UploadResources(RefPointer texture); glConst GetMinFilter() const; glConst GetMagFilter() const; @@ -40,8 +41,7 @@ private: void MoveCursor(); private: - typedef MasterPointer TResourcePtr; - typedef map TPalette; + typedef map TPalette; struct PendingColor { @@ -56,4 +56,26 @@ private: bool m_isDebug = false; }; +class ColorTexture : public DynamicTexture +{ + typedef DynamicTexture TBase; +public: + ColorTexture(m2::PointU const & size) + : m_pallete(size) + { + TBase::TextureParams params; + params.m_size = size; + params.m_format = TextureFormat::RGBA8; + params.m_minFilter = gl_const::GLNearest; + params.m_magFilter = gl_const::GLNearest; + + TBase::Init(MakeStackRefPointer(&m_pallete), params); + } + + ~ColorTexture() { TBase::Reset(); } + +private: + ColorPalette m_pallete; +}; + } diff --git a/drape/texture_set_controller.hpp b/drape/texture_set_controller.hpp deleted file mode 100644 index 48e658472a..0000000000 --- a/drape/texture_set_controller.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace dp -{ - -class TextureSetController -{ -public: - virtual ~TextureSetController() {} - virtual void BindTextureSet(uint32_t textureSet) const = 0; - virtual uint32_t GetTextureCount(uint32_t textureSet) const = 0; -}; - -} // namespace dp diff --git a/drape/texture_set_holder.cpp b/drape/texture_set_holder.cpp deleted file mode 100644 index 857cea618b..0000000000 --- a/drape/texture_set_holder.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "texture_set_holder.hpp" - -#include "font_texture.hpp" - -namespace dp -{ - -TextureSetHolder::TextureNode::TextureNode() - : m_width(-1) - , m_height(-1) - , m_textureSet(-1) - , m_textureOffset(-1) -{ -} - -bool TextureSetHolder::TextureNode::IsValid() const -{ - return m_width != -1 && - m_height != -1 && - m_textureSet != -1 && - m_textureOffset != -1; -} - - -TextureSetHolder::BaseRegion::BaseRegion() - : m_info(NULL) -{ -} - -bool TextureSetHolder::BaseRegion::IsValid() const -{ - return m_info != NULL && m_node.IsValid(); -} - -void TextureSetHolder::BaseRegion::SetResourceInfo(Texture::ResourceInfo const * info) -{ - m_info = info; -} - -void TextureSetHolder::BaseRegion::SetTextureNode(TextureNode const & node) -{ - m_node = node; -} - -void TextureSetHolder::BaseRegion::GetPixelSize(m2::PointU & size) const -{ - m2::RectF const & texRect = m_info->GetTexRect(); - size.x = texRect.SizeX() * m_node.m_width; - size.y = texRect.SizeY() * m_node.m_height; -} - -m2::RectF const & TextureSetHolder::BaseRegion::GetTexRect() const -{ - return m_info->GetTexRect(); -} - -TextureSetHolder::TextureNode const & TextureSetHolder::BaseRegion::GetTextureNode() const -{ - return m_node; -} - -TextureSetHolder::GlyphRegion::GlyphRegion() - : BaseRegion() -{ -} - -void TextureSetHolder::GlyphRegion::GetMetrics(float & xOffset, float & yOffset, float & advance) const -{ - ASSERT(m_info->GetType() == Texture::Glyph, ()); - //FontTexture::GlyphInfo const * info = static_cast(m_info); - //info->GetMetrics(xOffset, yOffset, advance); -} - -float TextureSetHolder::GlyphRegion::GetAdvance() const -{ - ASSERT(m_info->GetType() == Texture::Glyph, ()); - //return static_cast(m_info)->GetAdvance(); - return 0.0f; -} - -uint32_t TextureSetHolder::StippleRegion::GetMaskPixelLength() const -{ - ASSERT(m_info->GetType() == Texture::StipplePen, ()); - return static_cast(m_info)->GetMaskPixelLength(); -} - -uint32_t TextureSetHolder::StippleRegion::GetPatternPixelLength() const -{ - ASSERT(m_info->GetType() == Texture::StipplePen, ()); - return static_cast(m_info)->GetPatternPixelLength(); -} - -} // namespace dp diff --git a/drape/texture_set_holder.hpp b/drape/texture_set_holder.hpp deleted file mode 100644 index 31ad9d4193..0000000000 --- a/drape/texture_set_holder.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include "texture.hpp" -#include "stipple_pen_resource.hpp" -#include "texture_of_colors.hpp" - -#include "../base/string_utils.hpp" - -#include "../geometry/point2d.hpp" -#include "../geometry/rect2d.hpp" - -namespace dp -{ - -class TextureSetHolder -{ -public: - virtual ~TextureSetHolder() {} - virtual void Init(string const & resourcePrefix) = 0; - virtual void Release() = 0; - - struct TextureNode - { - TextureNode(); - - bool IsValid() const; - inline float GetOffset() const{ return static_cast(m_textureOffset); } - - int32_t m_width; - int32_t m_height; - int32_t m_textureSet; - int32_t m_textureOffset; - }; - - class BaseRegion - { - public: - BaseRegion(); - - bool IsValid() const; - - void SetResourceInfo(Texture::ResourceInfo const * info); - void SetTextureNode(TextureNode const & node); - - void GetPixelSize(m2::PointU & size) const; - - m2::RectF const & GetTexRect() const; - TextureNode const & GetTextureNode() const; - - protected: - Texture::ResourceInfo const * m_info; - TextureNode m_node; - }; - - class SymbolRegion : public BaseRegion {}; - - class GlyphRegion : public BaseRegion - { - public: - GlyphRegion(); - - void GetMetrics(float & xOffset, float & yOffset, float & advance) const; - float GetAdvance() const; - }; - - class StippleRegion : public BaseRegion - { - public: - StippleRegion() : BaseRegion() {} - - uint32_t GetMaskPixelLength() const; - uint32_t GetPatternPixelLength() const; - }; - - class ColorRegion : public BaseRegion - { - public: - ColorRegion() : BaseRegion() {} - }; - - virtual void GetSymbolRegion(string const & symbolName, SymbolRegion & region) const = 0; - virtual bool GetGlyphRegion(strings::UniChar charCode, GlyphRegion & region) const = 0; - virtual void GetStippleRegion(StipplePenKey const & pen, StippleRegion & region) const = 0; - virtual void GetColorRegion(ColorKey const & pen, ColorRegion & region) const = 0; - virtual int GetMaxTextureSet() const = 0; - - virtual void UpdateDynamicTextures() = 0; -}; - -} // namespace dp