threaded brush preview rendering
This commit is contained in:
@@ -678,6 +678,7 @@ void App::terminate()
|
|||||||
LOG("App::terminate");
|
LOG("App::terminate");
|
||||||
TextureManager::invalidate();
|
TextureManager::invalidate();
|
||||||
ShaderManager::invalidate();
|
ShaderManager::invalidate();
|
||||||
|
NodeStrokePreview::terminate_renderer();
|
||||||
layout.unload();
|
layout.unload();
|
||||||
uirtt.destroy();
|
uirtt.destroy();
|
||||||
m_face_plane.destroy();
|
m_face_plane.destroy();
|
||||||
|
|||||||
@@ -573,6 +573,8 @@ int main(int argc, char** argv)
|
|||||||
LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str());
|
LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async_lock();
|
||||||
|
|
||||||
LOG("init app");
|
LOG("init app");
|
||||||
App::I.init();
|
App::I.init();
|
||||||
|
|
||||||
@@ -604,6 +606,8 @@ int main(int argc, char** argv)
|
|||||||
LOG("SKIP init WinTab");
|
LOG("SKIP init WinTab");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async_unlock();
|
||||||
|
|
||||||
LOG("change icon");
|
LOG("change icon");
|
||||||
SendMessage(hWnd, WM_SETICON, ICON_SMALL,
|
SendMessage(hWnd, WM_SETICON, ICON_SMALL,
|
||||||
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));
|
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));
|
||||||
|
|||||||
@@ -7,6 +7,21 @@
|
|||||||
#include "canvas.h"
|
#include "canvas.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
|
||||||
|
std::atomic_int NodeStrokePreview::s_instances{ 0 };
|
||||||
|
std::atomic_bool NodeStrokePreview::s_running{ false };
|
||||||
|
std::thread NodeStrokePreview::s_renderer;
|
||||||
|
BlockingQueue<NodeStrokePreview*> NodeStrokePreview::s_queue;
|
||||||
|
|
||||||
|
void NodeStrokePreview::terminate_renderer()
|
||||||
|
{
|
||||||
|
if (s_running && s_renderer.joinable())
|
||||||
|
{
|
||||||
|
s_running = false;
|
||||||
|
s_queue.UnlockGetters();
|
||||||
|
s_renderer.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Node* NodeStrokePreview::clone_instantiate() const
|
Node* NodeStrokePreview::clone_instantiate() const
|
||||||
{
|
{
|
||||||
return new NodeStrokePreview();
|
return new NodeStrokePreview();
|
||||||
@@ -224,7 +239,7 @@ std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compu
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeStrokePreview::draw_stroke()
|
void NodeStrokePreview::draw_stroke_immediate()
|
||||||
{
|
{
|
||||||
if (m_size.x == 0 || m_size.y == 0)
|
if (m_size.x == 0 || m_size.y == 0)
|
||||||
return;
|
return;
|
||||||
@@ -458,6 +473,35 @@ void NodeStrokePreview::draw_stroke()
|
|||||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeStrokePreview::draw_stroke()
|
||||||
|
{
|
||||||
|
if (m_size.x == 0 || m_size.y == 0)
|
||||||
|
return;
|
||||||
|
s_queue.mutex.lock();
|
||||||
|
if (!s_running)
|
||||||
|
{
|
||||||
|
s_running = true;
|
||||||
|
s_renderer = std::thread([] {
|
||||||
|
while (s_running)
|
||||||
|
{
|
||||||
|
auto node = s_queue.Get();
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
node->async_start();
|
||||||
|
gl_state gl;
|
||||||
|
gl.save();
|
||||||
|
node->draw_stroke_immediate();
|
||||||
|
gl.restore();
|
||||||
|
node->async_end();
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(30));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
s_queue.mutex.unlock();
|
||||||
|
s_queue.PostUnique(this);
|
||||||
|
}
|
||||||
|
|
||||||
void NodeStrokePreview::draw()
|
void NodeStrokePreview::draw()
|
||||||
{
|
{
|
||||||
//glEnable(GL_BLEND);
|
//glEnable(GL_BLEND);
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ class NodeStrokePreview : public NodeBorder
|
|||||||
Sampler m_sampler_mipmap;
|
Sampler m_sampler_mipmap;
|
||||||
DynamicShape m_brush_shape;
|
DynamicShape m_brush_shape;
|
||||||
public:
|
public:
|
||||||
|
static std::atomic_int s_instances;
|
||||||
|
static std::atomic_bool s_running;
|
||||||
|
static std::thread s_renderer;
|
||||||
|
static BlockingQueue<NodeStrokePreview*> s_queue;
|
||||||
|
static void terminate_renderer();
|
||||||
std::shared_ptr<Brush> m_brush;
|
std::shared_ptr<Brush> m_brush;
|
||||||
std::shared_ptr<Brush> m_dual_brush;
|
std::shared_ptr<Brush> m_dual_brush;
|
||||||
Stroke m_stroke;
|
Stroke m_stroke;
|
||||||
@@ -43,6 +48,7 @@ public:
|
|||||||
glm::vec4 stroke_draw_samples(std::array<vertex_t, 4>& P, Texture2D& blend_tex);
|
glm::vec4 stroke_draw_samples(std::array<vertex_t, 4>& P, Texture2D& blend_tex);
|
||||||
std::vector<StrokeFrame> stroke_draw_compute(Stroke& stroke) const;
|
std::vector<StrokeFrame> stroke_draw_compute(Stroke& stroke) const;
|
||||||
void draw_stroke();
|
void draw_stroke();
|
||||||
|
void draw_stroke_immediate();
|
||||||
virtual void draw() override;
|
virtual void draw() override;
|
||||||
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size) override;
|
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size) override;
|
||||||
virtual void destroy_immediate() override;
|
virtual void destroy_immediate() override;
|
||||||
|
|||||||
18
src/util.h
18
src/util.h
@@ -151,18 +151,18 @@ template<typename T> struct cbuffer
|
|||||||
template<typename T, int Max = 0>
|
template<typename T, int Max = 0>
|
||||||
class BlockingQueue
|
class BlockingQueue
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
std::deque<T> q;
|
std::deque<T> q;
|
||||||
std::condition_variable post_cv;
|
std::condition_variable post_cv;
|
||||||
std::condition_variable get_cv;
|
std::condition_variable get_cv;
|
||||||
mutable std::mutex mutex;
|
mutable std::mutex mutex;
|
||||||
public:
|
|
||||||
volatile bool unlocked = false;
|
volatile bool unlocked = false;
|
||||||
BlockingQueue() = default;
|
BlockingQueue() = default;
|
||||||
BlockingQueue(const BlockingQueue& other) = delete;
|
BlockingQueue(const BlockingQueue& other) = delete;
|
||||||
BlockingQueue& operator=(const BlockingQueue& other) = delete;
|
BlockingQueue& operator=(const BlockingQueue& other) = delete;
|
||||||
BlockingQueue(BlockingQueue&& other) : q(std::move(q)) { }
|
BlockingQueue(BlockingQueue&& other) : q(std::move(q)) { }
|
||||||
BlockingQueue& operator=(BlockingQueue&& other) { q = std::move(q); return *this; }
|
BlockingQueue& operator=(BlockingQueue&& other) { q = std::move(q); return *this; }
|
||||||
void Post(T&& pkt)
|
void Post(T pkt)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
if (Max > 0)
|
if (Max > 0)
|
||||||
@@ -170,7 +170,19 @@ public:
|
|||||||
post_cv.wait(lock, [&]() { return unlocked | (q.size() < Max); });
|
post_cv.wait(lock, [&]() { return unlocked | (q.size() < Max); });
|
||||||
if (q.size() >= Max) return;
|
if (q.size() >= Max) return;
|
||||||
}
|
}
|
||||||
q.push_back(std::forward<T>(pkt));
|
q.push_back(pkt);
|
||||||
|
get_cv.notify_one();
|
||||||
|
}
|
||||||
|
void PostUnique(T pkt)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
if (Max > 0)
|
||||||
|
{
|
||||||
|
post_cv.wait(lock, [&]() { return unlocked | (q.size() < Max); });
|
||||||
|
if (q.size() >= Max) return;
|
||||||
|
}
|
||||||
|
if (std::find(q.begin(), q.end(), pkt) == q.end());
|
||||||
|
q.push_back(pkt);
|
||||||
get_cv.notify_one();
|
get_cv.notify_one();
|
||||||
}
|
}
|
||||||
T Get()
|
T Get()
|
||||||
|
|||||||
Reference in New Issue
Block a user