diff --git a/lib/irrlicht/include/ITexture.h b/lib/irrlicht/include/ITexture.h index ae6566cb7..b07eb3cc8 100644 --- a/lib/irrlicht/include/ITexture.h +++ b/lib/irrlicht/include/ITexture.h @@ -104,6 +104,8 @@ public: { } + virtual ~ITexture() {} + //! Lock function. /** Locks the Texture and returns a pointer to access the pixels. After lock() has been called and all operations on the pixels diff --git a/src/font/font_with_face.cpp b/src/font/font_with_face.cpp index 8e8d57d44..34d0a59ba 100644 --- a/src/font/font_with_face.cpp +++ b/src/font/font_with_face.cpp @@ -23,6 +23,8 @@ #include "font/font_settings.hpp" #include "graphics/2dutils.hpp" #include "graphics/irr_driver.hpp" +#include "graphics/stk_texture.hpp" +#include "graphics/stk_tex_manager.hpp" #include "guiengine/engine.hpp" #include "guiengine/skin.hpp" #include "utils/string_utils.hpp" @@ -50,8 +52,6 @@ FontWithFace::FontWithFace(const std::string& name, FaceTTF* ttf) */ FontWithFace::~FontWithFace() { - m_page->drop(); - m_page = NULL; m_spritebank->drop(); m_spritebank = NULL; @@ -66,9 +66,6 @@ FontWithFace::~FontWithFace() void FontWithFace::init() { setDPI(); - m_page = irr_driver->getVideoDriver()->createImage(video::ECF_A8R8G8B8, - core::dimension2du(getGlyphPageSize(), getGlyphPageSize())); - // Get the max height for this face assert(m_face_ttf->getTotalFaces() > 0); FT_Face cur_face = m_face_ttf->getFace(0); @@ -129,32 +126,17 @@ void FontWithFace::loadGlyphInfo(wchar_t c) */ void FontWithFace::createNewGlyphPage() { - m_page->fill(video::SColor(0, 255, 255, 255)); + video::IImage* glyph = irr_driver->getVideoDriver() + ->createImage(video::ECF_A8R8G8B8, + core::dimension2du(getGlyphPageSize(), getGlyphPageSize())); + glyph->fill(video::SColor(0, 255, 255, 255)); m_current_height = 0; m_used_width = 0; m_used_height = 0; - - // Font textures can not be resized (besides the impact on quality in - // this case, the rectangles in spritebank would become wrong). - core::dimension2du old_max_size = irr_driver->getVideoDriver() - ->getDriverAttributes().getAttributeAsDimension2d("MAX_TEXTURE_SIZE"); - irr_driver->getVideoDriver()->getNonConstDriverAttributes() - .setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(0, 0)); - - video::ITexture* page_texture = irr_driver->getVideoDriver() - ->addTexture("Glyph_page", m_page); - m_spritebank->addTexture(NULL); - m_spritebank->setTexture(m_spritebank->getTextureCount() - 1, - page_texture); - - // Doing so to make sure the texture inside the sprite bank has only 1 - // reference, so they can be removed or updated on-the-fly - irr_driver->getVideoDriver()->removeTexture(page_texture); - assert(page_texture->getReferenceCount() == 1); - - irr_driver->getVideoDriver()->getNonConstDriverAttributes() - .setAttribute("MAX_TEXTURE_SIZE", old_max_size); - + STKTexture* stkt = new STKTexture(glyph, typeid(*this).name() + + StringUtils::toString(m_spritebank->getTextureCount())); + m_spritebank->addTexture(stkt); + STKTexManager::getInstance()->addTexture(stkt); } // createNewGlyphPage // ---------------------------------------------------------------------------- @@ -164,6 +146,7 @@ void FontWithFace::createNewGlyphPage() */ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) { +#ifndef SERVER_ONLY assert(gi.glyph_index > 0); assert(gi.font_number < m_face_ttf->getTotalFaces()); FT_Face cur_face = m_face_ttf->getFace(gi.font_number); @@ -198,29 +181,12 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) getGlyphPageSize()) || m_used_height + texture_size.Height > getGlyphPageSize()) { - // Current glyph page is full: - // Save the old glyph page - core::dimension2du old_max_size = irr_driver->getVideoDriver() - ->getDriverAttributes().getAttributeAsDimension2d - ("MAX_TEXTURE_SIZE"); - irr_driver->getVideoDriver()->getNonConstDriverAttributes() - .setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(0, 0)); - video::ITexture* page_texture = irr_driver->getVideoDriver() - ->addTexture("Glyph_page", m_page); - - m_spritebank->setTexture(m_spritebank->getTextureCount() - 1, - page_texture); - irr_driver->getVideoDriver()->removeTexture(page_texture); - assert(page_texture->getReferenceCount() == 1); - - irr_driver->getVideoDriver()->getNonConstDriverAttributes() - .setAttribute("MAX_TEXTURE_SIZE", old_max_size); - - // Clear and add a new one + // Add a new glyph page if current one is full createNewGlyphPage(); } video::IImage* glyph = NULL; + unsigned int* image_data = NULL; switch (bits.pixel_mode) { case FT_PIXEL_MODE_GRAY: @@ -234,7 +200,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) const float gray_count = static_cast(bits.num_grays); const unsigned int image_pitch = glyph->getPitch() / sizeof(unsigned int); - unsigned int* image_data = (unsigned int*)glyph->lock(); + image_data = (unsigned int*)glyph->lock(); unsigned char* glyph_data = bits.buffer; for (unsigned int y = 0; y < (unsigned int)bits.rows; y++) @@ -254,8 +220,11 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) default: assert(false); } - if (!glyph) - Log::fatal("FontWithFace", "Failed to load a glyph"); + if (glyph == NULL) + { + Log::warn("FontWithFace", "Failed to load a glyph"); + return; + } // Done creating a single glyph, now copy to the glyph page... // Determine the linebreak location @@ -266,8 +235,20 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) m_current_height = 0; } - // Copy to the full glyph page - glyph->copyTo(m_page, core::position2di(m_used_width, m_used_height)); + const unsigned int cur_tex = m_spritebank->getTextureCount() -1; + video::ITexture* tex = m_spritebank->getTexture(cur_tex); + glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName()); + unsigned int format = GL_BGRA; +#if defined(USE_GLES2) + if (!CVS->isEXTTextureFormatBGRA8888Usable()) + format = GL_RGBA; +#endif + glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height, + texture_size.Width, texture_size.Height, format, GL_UNSIGNED_BYTE, + image_data); + if (tex->hasMipMaps()) + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); // Store the rectangle of current glyph gui::SGUISpriteFrame f; @@ -275,7 +256,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) core::rect rectangle(m_used_width, m_used_height, m_used_width + bits.width, m_used_height + bits.rows); f.rectNumber = m_spritebank->getPositions().size(); - f.textureNumber = m_spritebank->getTextureCount() - 1; + f.textureNumber = cur_tex; // Add frame to sprite s.Frames.push_back(f); @@ -303,6 +284,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) m_used_width += texture_size.Width; if (m_current_height < texture_size.Height) m_current_height = texture_size.Height; +#endif } // insertGlyph // ---------------------------------------------------------------------------- @@ -321,23 +303,6 @@ void FontWithFace::updateCharactersList() } m_new_char_holder.clear(); - // Update last glyph page - core::dimension2du old_max_size = irr_driver->getVideoDriver() - ->getDriverAttributes().getAttributeAsDimension2d("MAX_TEXTURE_SIZE"); - irr_driver->getVideoDriver()->getNonConstDriverAttributes() - .setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(0, 0)); - - video::ITexture* page_texture = irr_driver->getVideoDriver() - ->addTexture("Glyph_page", m_page); - m_spritebank->setTexture(m_spritebank->getTextureCount() - 1, - page_texture); - - irr_driver->getVideoDriver()->removeTexture(page_texture); - assert(page_texture->getReferenceCount() == 1); - - irr_driver->getVideoDriver()->getNonConstDriverAttributes() - .setAttribute("MAX_TEXTURE_SIZE", old_max_size); - } // updateCharactersList // ---------------------------------------------------------------------------- @@ -347,21 +312,7 @@ void FontWithFace::updateCharactersList() */ void FontWithFace::dumpGlyphPage(const std::string& name) { - for (unsigned int i = 0; i < m_spritebank->getTextureCount(); i++) - { - video::ITexture* tex = m_spritebank->getTexture(i); - core::dimension2d size = tex->getSize(); - video::ECOLOR_FORMAT col_format = tex->getColorFormat(); - void* data = tex->lock(); - - video::IImage* image = irr_driver->getVideoDriver() - ->createImageFromData(col_format, size, data, false/*copy mem*/); - - tex->unlock(); - irr_driver->getVideoDriver()->writeImageToFile(image, std::string - (name + "_" + StringUtils::toString(i) + ".png").c_str()); - image->drop(); - } + // Todo for new texture format } // dumpGlyphPage // ---------------------------------------------------------------------------- @@ -618,28 +569,6 @@ void FontWithFace::render(const core::stringw& text, } else { - // Prevent overwriting texture used by billboard text when - // using lazy loading characters - if (supportLazyLoadChar() && fallback[i]) - { - const int cur_texno = m_fallback_font->getSpriteBank() - ->getSprites()[area.spriteno].Frames[0].textureNumber; - if (cur_texno == int(m_fallback_font->getSpriteBank() - ->getTextureCount() - 1)) - { - m_fallback_font->createNewGlyphPage(); - } - } - else if (supportLazyLoadChar()) - { - const int cur_texno = m_spritebank - ->getSprites()[area.spriteno].Frames[0].textureNumber; - if (cur_texno == int(m_spritebank->getTextureCount() - 1)) - { - createNewGlyphPage(); - } - } - // Billboard text specific, use offset_y_bt instead float glyph_offset_x = area.bearing_x * (fallback[i] ? m_fallback_font_scale : scale); diff --git a/src/font/font_with_face.hpp b/src/font/font_with_face.hpp index 01b1049b1..6ba70c2a4 100644 --- a/src/font/font_with_face.hpp +++ b/src/font/font_with_face.hpp @@ -129,9 +129,6 @@ private: /** Sprite bank to store each glyph. */ gui::IGUISpriteBank* m_spritebank; - /** A full glyph page for this font. */ - video::IImage* m_page; - /** The current max height at current drawing line in glyph page. */ unsigned int m_current_height; diff --git a/src/graphics/stk_tex_manager.cpp b/src/graphics/stk_tex_manager.cpp index 21f33be21..862ba6233 100644 --- a/src/graphics/stk_tex_manager.cpp +++ b/src/graphics/stk_tex_manager.cpp @@ -137,6 +137,7 @@ video::ITexture* STKTexManager::getUnicolorTexture(const irr::video::SColor &c) // ---------------------------------------------------------------------------- core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name) { +#ifndef SERVER_ONLY if (CVS->isTextureCompressionEnabled()) return L"Please disable texture compression for reloading textures."; @@ -179,5 +180,5 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name) if (result.empty()) return L"Texture(s) not found!"; return result + "reloaded."; - +#endif // !SERVER_ONLY } // reloadTexture diff --git a/src/graphics/stk_texture.hpp b/src/graphics/stk_texture.hpp index 76d92aefa..ac83e580e 100644 --- a/src/graphics/stk_texture.hpp +++ b/src/graphics/stk_texture.hpp @@ -66,7 +66,7 @@ public: // ------------------------------------------------------------------------ STKTexture(video::IImage* image, const std::string& name); // ------------------------------------------------------------------------ - ~STKTexture(); + virtual ~STKTexture(); // ------------------------------------------------------------------------ virtual void* lock(video::E_TEXTURE_LOCK_MODE mode = video::ETLM_READ_WRITE, u32 mipmap_level = 0)