unload brush texture from main memory, preload brush on preview to free render thread
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "log.h"
|
||||
#include "brush.h"
|
||||
#include "asset.h"
|
||||
|
||||
void BrushMesh::draw(const std::vector<StrokeSample>& samples, const glm::mat4& proj)
|
||||
{
|
||||
@@ -325,6 +326,8 @@ void Stroke::start(const std::shared_ptr<Brush>& brush)
|
||||
|
||||
bool Brush::load_tip(const std::string& path, const std::string& thumb)
|
||||
{
|
||||
if (m_tip_texture)
|
||||
return true;
|
||||
m_tip_texture = std::make_shared<Texture2D>();
|
||||
if (!m_tip_texture->load(path))
|
||||
{
|
||||
@@ -342,6 +345,8 @@ bool Brush::load_tip(const std::string& path, const std::string& thumb)
|
||||
|
||||
bool Brush::load_dual(const std::string& path, const std::string& thumb)
|
||||
{
|
||||
if (m_dual_texture)
|
||||
return true;
|
||||
m_dual_texture = std::make_shared<Texture2D>();
|
||||
if (!m_dual_texture->load(path))
|
||||
{
|
||||
@@ -357,6 +362,8 @@ bool Brush::load_dual(const std::string& path, const std::string& thumb)
|
||||
|
||||
bool Brush::load_pattern(const std::string& path, const std::string& thumb)
|
||||
{
|
||||
if (m_pattern_texture)
|
||||
return true;
|
||||
m_pattern_texture = std::make_shared<Texture2D>();
|
||||
if (!m_pattern_texture->load(path))
|
||||
{
|
||||
@@ -372,10 +379,13 @@ bool Brush::load_pattern(const std::string& path, const std::string& thumb)
|
||||
|
||||
bool Brush::load()
|
||||
{
|
||||
if (!m_brush_path.empty())
|
||||
if (!m_brush_path.empty() && !m_tip_texture)
|
||||
{
|
||||
m_tip_texture = std::make_shared<Texture2D>();
|
||||
if (!m_tip_texture->load(m_brush_path))
|
||||
auto loaded = m_tip_img ?
|
||||
m_tip_texture->create(*m_tip_img) :
|
||||
m_tip_texture->load(m_brush_path);
|
||||
if (!loaded)
|
||||
{
|
||||
LOG("failed to load %s", m_brush_path.c_str());
|
||||
m_tip_texture = nullptr;
|
||||
@@ -384,10 +394,13 @@ bool Brush::load()
|
||||
m_tip_texture->create_mipmaps();
|
||||
m_tip_texture->auto_destroy = true;
|
||||
}
|
||||
if (!m_dual_path.empty())
|
||||
if (!m_dual_path.empty() && !m_dual_texture)
|
||||
{
|
||||
m_dual_texture = std::make_shared<Texture2D>();
|
||||
if (!m_dual_texture->load(m_dual_path))
|
||||
auto loaded = m_dual_img ?
|
||||
m_dual_texture->create(*m_dual_img) :
|
||||
m_dual_texture->load(m_dual_path);
|
||||
if (!loaded)
|
||||
{
|
||||
LOG("failed to load %s", m_dual_path.c_str());
|
||||
m_tip_texture = nullptr;
|
||||
@@ -397,10 +410,13 @@ bool Brush::load()
|
||||
m_dual_texture->create_mipmaps();
|
||||
m_dual_texture->auto_destroy = true;
|
||||
}
|
||||
if (!m_pattern_path.empty())
|
||||
if (!m_pattern_path.empty() && !m_pattern_texture)
|
||||
{
|
||||
m_pattern_texture = std::make_shared<Texture2D>();
|
||||
if (!m_pattern_texture->load(m_pattern_path))
|
||||
auto loaded = m_pattern_img ?
|
||||
m_pattern_texture->create(*m_pattern_img) :
|
||||
m_pattern_texture->load(m_pattern_path);
|
||||
if (!loaded)
|
||||
{
|
||||
LOG("failed to load %s", m_pattern_path.c_str());
|
||||
m_tip_texture = nullptr;
|
||||
@@ -413,3 +429,47 @@ bool Brush::load()
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Brush::preload()
|
||||
{
|
||||
if (!m_brush_path.empty() && !m_tip_texture && !m_tip_img)
|
||||
{
|
||||
m_tip_img = std::make_shared<Image>();
|
||||
if (!m_tip_img->load(m_brush_path))
|
||||
return false;
|
||||
}
|
||||
if (!m_dual_path.empty() && !m_dual_texture && !m_dual_img)
|
||||
{
|
||||
m_dual_img = std::make_shared<Image>();
|
||||
if (!m_dual_img->load(m_dual_path))
|
||||
return false;
|
||||
}
|
||||
if (!m_pattern_path.empty() && !m_pattern_texture && !m_pattern_img)
|
||||
{
|
||||
m_pattern_img = std::make_shared<Image>();
|
||||
if (!m_pattern_img->load(m_pattern_path))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Brush::unload()
|
||||
{
|
||||
m_tip_texture = nullptr;
|
||||
m_tip_img = nullptr;
|
||||
m_dual_texture = nullptr;
|
||||
m_dual_img = nullptr;
|
||||
m_pattern_texture = nullptr;
|
||||
m_pattern_img = nullptr;
|
||||
}
|
||||
|
||||
bool Brush::valid()
|
||||
{
|
||||
if (!m_brush_path.empty() && !Asset::exist(m_brush_path))
|
||||
return false;
|
||||
if (!m_dual_path.empty() && !Asset::exist(m_dual_path))
|
||||
return false;
|
||||
if (!m_pattern_path.empty() && !Asset::exist(m_pattern_path))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
class Brush
|
||||
{
|
||||
std::shared_ptr<Image> m_tip_img;
|
||||
std::shared_ptr<Image> m_pattern_img;
|
||||
std::shared_ptr<Image> m_dual_img;
|
||||
public:
|
||||
//Brush() = default;
|
||||
//Brush(const Brush& brush) = default;
|
||||
@@ -94,6 +97,9 @@ public:
|
||||
bool load_dual(const std::string& path, const std::string& thumb);
|
||||
bool load_pattern(const std::string& path, const std::string& thumb);
|
||||
bool load();
|
||||
bool preload();
|
||||
void unload();
|
||||
bool valid();
|
||||
};
|
||||
|
||||
struct StrokeSample
|
||||
|
||||
@@ -662,13 +662,8 @@ bool NodePanelBrushPreset::restore()
|
||||
fread((char*)b->m_pattern_path.c_str(), 1, b->m_pattern_path.size(), fp);
|
||||
fread((char*)b->m_pattern_thumb_path.c_str(), 1, b->m_pattern_thumb_path.size(), fp);
|
||||
|
||||
if (b->load_tip(b->m_brush_path, b->m_brush_thumb_path))
|
||||
if (b->valid())
|
||||
{
|
||||
if (!b->m_pattern_path.empty())
|
||||
b->load_pattern(b->m_pattern_path, b->m_pattern_thumb_path);
|
||||
if (!b->m_dual_path.empty())
|
||||
b->load_dual(b->m_dual_path, b->m_dual_thumb_path);
|
||||
|
||||
NodeBrushPresetItem* brush = new NodeBrushPresetItem;
|
||||
m_container->add_child(brush);
|
||||
brush->init();
|
||||
|
||||
@@ -121,7 +121,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
|
||||
{
|
||||
auto presets = App::I.stroke->m_presets_popup;
|
||||
async_start();
|
||||
if (pr->load())
|
||||
if (pr->valid())
|
||||
{
|
||||
LOG("add preset %s", pr->m_name.c_str());
|
||||
presets->add_brush(pr);
|
||||
@@ -303,6 +303,7 @@ void NodePanelStroke::init_controls()
|
||||
auto old_color = Canvas::I->m_current_brush->m_tip_color;
|
||||
*Canvas::I->m_current_brush = *b;
|
||||
Canvas::I->m_current_brush->m_tip_color = old_color;
|
||||
Canvas::I->m_current_brush->load();
|
||||
m_preview->draw_stroke();
|
||||
m_brush_thumb->set_image(b->m_brush_thumb_path);
|
||||
m_dual_brush_thumb->set_image(b->m_dual_thumb_path);
|
||||
|
||||
@@ -487,10 +487,19 @@ void NodeStrokePreview::draw_stroke()
|
||||
auto node = s_queue.Get();
|
||||
if (node)
|
||||
{
|
||||
// if the brush is not already loaded, load it and then destroy it
|
||||
bool to_unload = (node->m_brush->m_tip_texture == nullptr);
|
||||
node->m_brush->preload();
|
||||
|
||||
node->async_start();
|
||||
gl_state gl;
|
||||
gl.save();
|
||||
|
||||
node->m_brush->load();
|
||||
node->draw_stroke_immediate();
|
||||
if (to_unload)
|
||||
node->m_brush->unload();
|
||||
|
||||
gl.restore();
|
||||
node->app_redraw();
|
||||
node->async_end();
|
||||
|
||||
Reference in New Issue
Block a user