aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-10-03 14:46:57 +0200
committerdec05eba <dec05eba@protonmail.com>2020-10-03 14:47:03 +0200
commit4907c5cc952e94e32cb0f95ea6f3be361b55d389 (patch)
tree305331f272dd3d93bb20bffdf154eeb1f798d565 /src
parent8ce51433c8a73b76e57f124bb62e5aa39867238a (diff)
Reduce memory usage by cleaning up text not visible on the screen
As a text, memory usage decreased from 150mb to 20mb
Diffstat (limited to 'src')
-rw-r--r--src/Body.cpp132
-rw-r--r--src/Text.cpp24
2 files changed, 85 insertions, 71 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index 812840d..08ef690 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -23,7 +23,8 @@ namespace QuickMedia {
thumbnail_is_local(false),
title_color(sf::Color::White),
author_color(sf::Color::White),
- userdata(nullptr)
+ userdata(nullptr),
+ last_drawn_time(0)
{
if(!_title.empty())
set_title(std::move(_title));
@@ -58,6 +59,7 @@ namespace QuickMedia {
title_color = other.title_color;
author_color = other.author_color;
userdata = other.userdata;
+ last_drawn_time = other.last_drawn_time;
}
Body::Body(Program *program, sf::Font *font, sf::Font *bold_font, sf::Font *cjk_font) :
@@ -279,6 +281,8 @@ namespace QuickMedia {
sf::Vector2f scissor_size = size;
const float start_y = pos.y;
+ const sf::Int32 elapsed_time = draw_timer.getElapsedTime().asMilliseconds();
+
if(thumbnail_resize_target_size.x != 0 && thumbnail_resize_target_size.y != 0) {
image_max_height = thumbnail_resize_target_size.y;
}
@@ -294,11 +298,9 @@ namespace QuickMedia {
int num_items = items.size();
if(num_items == 0 || size.y <= 0.0f) {
- for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) {
- if(!it->second->referenced)
- it = item_thumbnail_textures.erase(it);
- else
- ++it;
+ item_thumbnail_textures.clear();
+ for(auto &body_item : items) {
+ clear_body_item_cache(body_item.get());
}
return;
}
@@ -307,41 +309,6 @@ namespace QuickMedia {
thumbnail_it.second->referenced = false;
}
- for(auto &body_item : items) {
- if(body_item->dirty) {
- body_item->dirty = false;
- // TODO: Find a way to optimize fromUtf8
- sf::String str = sf::String::fromUtf8(body_item->get_title().data(), body_item->get_title().data() + body_item->get_title().size());
- if(body_item->title_text)
- body_item->title_text->setString(std::move(str));
- else
- body_item->title_text = std::make_unique<Text>(std::move(str), font, cjk_font, 16, size.x - 50 - image_padding_x * 2.0f);
- body_item->title_text->setFillColor(body_item->title_color);
- body_item->title_text->updateGeometry();
- }
-
- if(body_item->dirty_description) {
- body_item->dirty_description = false;
- sf::String str = sf::String::fromUtf8(body_item->get_description().data(), body_item->get_description().data() + body_item->get_description().size());
- if(body_item->description_text)
- body_item->description_text->setString(std::move(str));
- else
- body_item->description_text = std::make_unique<Text>(std::move(str), font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f);
- body_item->description_text->updateGeometry();
- }
-
- if(body_item->dirty_author) {
- body_item->dirty_author = false;
- sf::String str = sf::String::fromUtf8(body_item->get_author().data(), body_item->get_author().data() + body_item->get_author().size());
- if(body_item->author_text)
- body_item->author_text->setString(std::move(str));
- else
- body_item->author_text = std::make_unique<Text>(std::move(str), bold_font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f);
- body_item->author_text->setFillColor(body_item->author_color);
- body_item->author_text->updateGeometry();
- }
- }
-
if(prev_selected_item < 0 || prev_selected_item >= (int)items.size()) {
prev_selected_item = selected_item;
}
@@ -384,8 +351,6 @@ namespace QuickMedia {
pos.y += page_scroll;
sf::Vector2u window_size = window.getSize();
- glEnable(GL_SCISSOR_TEST);
- glScissor(scissor_pos.x, (int)window_size.y - (int)scissor_pos.y - (int)scissor_size.y, scissor_size.x, scissor_size.y);
sf::Vector2f prev_pos = pos;
for(int i = selected_item - 1; i >= 0; --i) {
@@ -395,13 +360,20 @@ namespace QuickMedia {
if(!item->visible)
continue;
+ update_dirty_state(item.get(), size);
+
float item_height = get_item_height(item.get());
prev_pos.y -= (item_height + spacing_y);
if(prev_pos.y + item_height + spacing_y < start_y)
break;
+ item->last_drawn_time = elapsed_time;
+ // This is needed here rather than above the loop, since update_dirty_text cant be called inside scissor because it corrupts the text for some reason
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(scissor_pos.x, (int)window_size.y - (int)scissor_pos.y - (int)scissor_size.y, scissor_size.x, scissor_size.y);
draw_item(window, item.get(), prev_pos, size, item_height, i, content_progress);
+ glDisable(GL_SCISSOR_TEST);
++num_visible_items;
}
@@ -413,6 +385,8 @@ namespace QuickMedia {
if(!item->visible)
continue;
+ update_dirty_state(item.get(), size);
+
float item_height = get_item_height(item.get());
if((after_pos.y - start_y) + item_height + spacing_y > size.y)
@@ -423,7 +397,12 @@ namespace QuickMedia {
if(after_pos.y - start_y >= size.y)
break;
+ item->last_drawn_time = elapsed_time;
+ // This is needed here rather than above the loop, since update_dirty_text cant be called inside scissor because it corrupts the text for some reason
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(scissor_pos.x, (int)window_size.y - (int)scissor_pos.y - (int)scissor_size.y, scissor_size.x, scissor_size.y);
draw_item(window, item.get(), after_pos, size, item_height, i, content_progress);
+ glDisable(GL_SCISSOR_TEST);
after_pos.y += item_height + spacing_y;
++num_visible_items;
}
@@ -431,17 +410,76 @@ namespace QuickMedia {
if(last_fully_visible_item == -1)
last_fully_visible_item = selected_item;
- glDisable(GL_SCISSOR_TEST);
-
for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) {
if(!it->second->referenced)
it = item_thumbnail_textures.erase(it);
else
++it;
}
+
+ // TODO: Only do this for items that are not visible, do not loop all items.
+ // TODO: Verify if this only runs for items that are not visible, and only once
+ // TODO: Improve performance! right now it can use up to 5-7% cpu with a lot of items!
+ for(auto &body_item : items) {
+ if(elapsed_time - body_item->last_drawn_time >= 1500) {
+ clear_body_item_cache(body_item.get());
+ }
+ }
+ }
+
+ void Body::update_dirty_state(BodyItem *body_item, sf::Vector2f size) {
+ if(body_item->dirty) {
+ body_item->dirty = false;
+ // TODO: Find a way to optimize fromUtf8
+ sf::String str = sf::String::fromUtf8(body_item->get_title().data(), body_item->get_title().data() + body_item->get_title().size());
+ if(body_item->title_text)
+ body_item->title_text->setString(std::move(str));
+ else
+ body_item->title_text = std::make_unique<Text>(std::move(str), font, cjk_font, 16, size.x - 50 - image_padding_x * 2.0f);
+ body_item->title_text->setFillColor(body_item->title_color);
+ body_item->title_text->updateGeometry();
+ }
+
+ if(body_item->dirty_description) {
+ body_item->dirty_description = false;
+ sf::String str = sf::String::fromUtf8(body_item->get_description().data(), body_item->get_description().data() + body_item->get_description().size());
+ if(body_item->description_text)
+ body_item->description_text->setString(std::move(str));
+ else
+ body_item->description_text = std::make_unique<Text>(std::move(str), font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f);
+ body_item->description_text->updateGeometry();
+ }
+
+ if(body_item->dirty_author) {
+ body_item->dirty_author = false;
+ sf::String str = sf::String::fromUtf8(body_item->get_author().data(), body_item->get_author().data() + body_item->get_author().size());
+ if(body_item->author_text)
+ body_item->author_text->setString(std::move(str));
+ else
+ body_item->author_text = std::make_unique<Text>(std::move(str), bold_font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f);
+ body_item->author_text->setFillColor(body_item->author_color);
+ body_item->author_text->updateGeometry();
+ }
+ }
+
+ void Body::clear_body_item_cache(BodyItem *body_item) {
+ if(body_item->title_text) {
+ body_item->title_text.reset();
+ body_item->dirty = true;
+ }
+ if(body_item->description_text) {
+ body_item->description_text.reset();
+ body_item->dirty_description = true;
+ }
+ if(body_item->author_text) {
+ body_item->author_text.reset();
+ body_item->dirty_author = true;
+ }
}
void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size) {
+ update_dirty_state(item, size);
+ item->last_drawn_time = draw_timer.getElapsedTime().asMilliseconds();
sf::Vector2u window_size = window.getSize();
glEnable(GL_SCISSOR_TEST);
glScissor(pos.x, (int)window_size.y - (int)pos.y - (int)size.y, size.x, size.y);
@@ -574,10 +612,10 @@ namespace QuickMedia {
float Body::get_item_height(BodyItem *item) {
float item_height = 0.0f;
- if(!item->get_title().empty()) {
+ if(item->title_text) {
item_height += item->title_text->getHeight() - 2.0f;
}
- if(!item->get_author().empty()) {
+ if(item->author_text) {
item_height += item->author_text->getHeight() - 2.0f;
}
if(item->description_text) {
diff --git a/src/Text.cpp b/src/Text.cpp
index 2165037..e311f14 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -37,7 +37,6 @@ namespace QuickMedia
dirtyText(false),
dirtyCaret(false),
editable(false),
- visible(true),
caretMoveDirection(CaretMoveDirection::NONE),
lineSpacing(0.0f),
characterSpacing(0.0f),
@@ -707,32 +706,10 @@ namespace QuickMedia
}
sf::Vector2f pos = position;
-
- // TODO: Do not use maxWidth here. Max width might be set to 99999 and actual text width might be 200. Text width should be calculated instead
- //sf::FloatRect targetRect(0.0f, 0.0f, maxWidth, target.getSize().y);
- //sf::FloatRect textRect(pos.x, pos.y, maxWidth, )
- //colRect.contains()
- //if(pos.x + maxWidth <= 0.0f || pos.x >= maxWidth || pos.y + totalHeight <= 0.0f || pos.y >= target.getSize().y) return;
- renderTargetSize = target.getSize();
- if(pos.y + getHeight() <= 0.0f || pos.y >= renderTargetSize.y)
- {
- if(!editable && visible && lastSeenTimer.getElapsedTime().asMilliseconds() > 3000)
- {
- visible = false;
- vertices[0].resize(0);
- vertices[1].resize(0);
- }
- return false;
- }
const float vspace = font->getLineSpacing(characterSize);
pos.y += floor(vspace); // Origin is at bottom left, we want it to be at top left
- if(!visible) {
- visible = true;
- updateGeometry(true);
- }
-
const sf::Font *fonts[] = { font, cjk_font };
for(size_t i = 0; i < 2; ++i) {
sf::RenderStates states;
@@ -740,7 +717,6 @@ namespace QuickMedia
states.texture = &fonts[i]->getTexture(characterSize);
target.draw(vertices[i], states);
}
- lastSeenTimer.restart();
if(!editable) return true;
pos.y -= floor(vspace * 2.0f);