From 88d640f3e77fed190b4edfc08d604442e6194d02 Mon Sep 17 00:00:00 2001 From: zetaPRIME Date: Wed, 3 May 2017 00:52:46 -0400 Subject: [PATCH] thread testing and fixes, exposed blend mode in drawables, made frame timing a bit more accurate --- libstarlight/source/starlight/Application.cpp | 3 ++- .../starlight/gfx/DrawContextCanvas.cpp | 4 ++-- .../source/starlight/gfx/DrawContextCanvas.h | 6 +++--- libstarlight/source/starlight/gfx/Drawable.h | 12 +++++------ .../source/starlight/gfx/DrawableImage.cpp | 8 +++---- .../source/starlight/gfx/DrawableImage.h | 5 ++--- .../starlight/gfx/DrawableNinePatch.cpp | 4 ++-- .../source/starlight/gfx/DrawableNinePatch.h | 4 ++-- .../source/starlight/gfx/DrawableTest.cpp | 7 +++---- .../source/starlight/gfx/DrawableTest.h | 5 ++--- libstarlight/source/starlight/gfx/Enums.h | 14 +++++++++++++ .../source/starlight/gfx/RenderCore.cpp | 14 ++++++++----- .../source/starlight/gfx/RenderCore.h | 15 +++++-------- .../source/starlight/threading/Thread.cpp | 3 +++ libstarlight/todo.txt | 10 ++++----- testbed/source/Core.cpp | 5 +++++ testbed/source/ThreadTest.cpp | 21 +++++++++++++++++++ testbed/source/ThreadTest.h | 7 +++++++ 18 files changed, 97 insertions(+), 50 deletions(-) create mode 100644 libstarlight/source/starlight/gfx/Enums.h create mode 100644 testbed/source/ThreadTest.cpp create mode 100644 testbed/source/ThreadTest.h diff --git a/libstarlight/source/starlight/Application.cpp b/libstarlight/source/starlight/Application.cpp index 40efa7c..edeed83 100644 --- a/libstarlight/source/starlight/Application.cpp +++ b/libstarlight/source/starlight/Application.cpp @@ -98,6 +98,7 @@ void Application::_end() { } void Application::_mainLoop() { + RenderCore::SyncFrame(); // sync to vblank here for more accurate timing frameTimer.FrameStart(); if (!forms.empty()) { @@ -159,7 +160,7 @@ void Application::_mainLoop() { while (!threads.empty() && frameTimer.GetSubframe() < 0.9) { threads.front()->Resume(); - threads.splice(threads.end(), threads, threads.begin()); // move to back of queue + if (threads.size() > 1) threads.splice(threads.end(), threads, threads.begin()); // move to back of queue } } diff --git a/libstarlight/source/starlight/gfx/DrawContextCanvas.cpp b/libstarlight/source/starlight/gfx/DrawContextCanvas.cpp index dc16b6a..977772c 100644 --- a/libstarlight/source/starlight/gfx/DrawContextCanvas.cpp +++ b/libstarlight/source/starlight/gfx/DrawContextCanvas.cpp @@ -45,7 +45,7 @@ void DrawContextCanvas::Clear(Color color) { void DrawContextCanvas::Clear() { Clear(Color(0,0,0,0)); } // drawable stuff -void DrawContextCanvas::Draw(const Vector2& position, const Vector2& origin, OptRef sampleRect, OptRef color, float rotation, const Vector2& scale) { +void DrawContextCanvas::Draw(const Vector2& position, const Vector2& origin, OptRef sampleRect, OptRef color, float rotation, const Vector2& scale, BlendMode mode) { if (GFXManager::PrepareForDrawing()) { target->Bind(color ? color.get() : Color(1,1,1,1)); const VRect& sr = sampleRect ? sampleRect.get() : this->rect; @@ -54,7 +54,7 @@ void DrawContextCanvas::Draw(const Vector2& position, const Vector2& origin, Opt } } -void DrawContextCanvas::Draw(const VRect& rect, OptRef sampleRect, OptRef color) { +void DrawContextCanvas::Draw(const VRect& rect, OptRef sampleRect, OptRef color, BlendMode mode) { if (GFXManager::PrepareForDrawing()) { target->Bind(color ? color.get() : Color(1,1,1,1)); const VRect& sr = sampleRect ? sampleRect.get() : this->rect; diff --git a/libstarlight/source/starlight/gfx/DrawContextCanvas.h b/libstarlight/source/starlight/gfx/DrawContextCanvas.h index eb90c3d..2406806 100644 --- a/libstarlight/source/starlight/gfx/DrawContextCanvas.h +++ b/libstarlight/source/starlight/gfx/DrawContextCanvas.h @@ -23,8 +23,8 @@ namespace starlight { DrawContextCanvas(Vector2 size); ~DrawContextCanvas(); - void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; - void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr) override; + void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) override; + void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr, BlendMode mode = BlendMode::Normal) override; Vector2 Size() override; @@ -32,4 +32,4 @@ namespace starlight { void Clear() override; }; } -} \ No newline at end of file +} diff --git a/libstarlight/source/starlight/gfx/Drawable.h b/libstarlight/source/starlight/gfx/Drawable.h index eaf2508..d9a75a3 100644 --- a/libstarlight/source/starlight/gfx/Drawable.h +++ b/libstarlight/source/starlight/gfx/Drawable.h @@ -7,6 +7,8 @@ #include "starlight/datatypes/OptRef.h" +#include "starlight/gfx/Enums.h" + namespace starlight { namespace gfx { class Drawable { @@ -17,16 +19,14 @@ namespace starlight { // pattern after: // public abstract void Draw(DrawContext context, PxRect rect, PxRect? sampleRect = null, DrawColor? color = null); // public abstract void Draw(DrawContext context, FxVector position, FxVector? align = null, PxRect? sampleRect = null, DrawColor? color = null, float rotation = 0, FxVector? scale = null); - virtual void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) = 0; - void Draw(const Vector2& position, OptRef hotspot, OptRef sampleRect, OptRef color, float rotation, float scale) { - Draw(position, hotspot, sampleRect, color, rotation, Vector2(scale, scale)); + virtual void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) = 0; + void Draw(const Vector2& position, OptRef hotspot, OptRef sampleRect, OptRef color, float rotation, float scale, BlendMode mode = BlendMode::Normal) { + Draw(position, hotspot, sampleRect, color, rotation, Vector2(scale, scale), mode); } - virtual void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr) = 0; + virtual void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr, BlendMode mode = BlendMode::Normal) = 0; virtual Vector2 Size() = 0; }; } } - - diff --git a/libstarlight/source/starlight/gfx/DrawableImage.cpp b/libstarlight/source/starlight/gfx/DrawableImage.cpp index 7bda68d..2172273 100644 --- a/libstarlight/source/starlight/gfx/DrawableImage.cpp +++ b/libstarlight/source/starlight/gfx/DrawableImage.cpp @@ -15,18 +15,18 @@ using starlight::gfx::DrawableImage; using starlight::gfx::RenderCore; using starlight::gfx::CRenderTarget; -void DrawableImage::Draw(const Vector2& position, const Vector2& origin, OptRef sampleRect, OptRef color, float rotation, const Vector2& scale) { +void DrawableImage::Draw(const Vector2& position, const Vector2& origin, OptRef sampleRect, OptRef color, float rotation, const Vector2& scale, BlendMode mode) { if (GFXManager::PrepareForDrawing()) { - texture->Bind(color ? color.get() : Color(1,1,1,1)); + texture->Bind(color ? color.get() : Color(1,1,1,1), mode); const VRect& sr = sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size); VRect rect(position - (texture->size * origin) * scale, sr.size * scale); RenderCore::DrawQuad(rect, position, rotation, sr / texture->txSize); } } -void DrawableImage::Draw(const VRect& rect, OptRef sampleRect, OptRef color) { +void DrawableImage::Draw(const VRect& rect, OptRef sampleRect, OptRef color, BlendMode mode) { if (GFXManager::PrepareForDrawing()) { - texture->Bind(color ? color.get() : Color(1,1,1,1)); + texture->Bind(color ? color.get() : Color(1,1,1,1), mode); const VRect& sr = sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size); RenderCore::DrawQuad(rect, sr / texture->txSize); } diff --git a/libstarlight/source/starlight/gfx/DrawableImage.h b/libstarlight/source/starlight/gfx/DrawableImage.h index 83e97f6..bafb528 100644 --- a/libstarlight/source/starlight/gfx/DrawableImage.h +++ b/libstarlight/source/starlight/gfx/DrawableImage.h @@ -15,11 +15,10 @@ namespace starlight { DrawableImage(CTexture* texture) : texture(texture) { } ~DrawableImage() override { } - void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; - void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr) override; + void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) override; + void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr, BlendMode mode = BlendMode::Normal) override; Vector2 Size() override; }; } } - diff --git a/libstarlight/source/starlight/gfx/DrawableNinePatch.cpp b/libstarlight/source/starlight/gfx/DrawableNinePatch.cpp index b943777..e220459 100644 --- a/libstarlight/source/starlight/gfx/DrawableNinePatch.cpp +++ b/libstarlight/source/starlight/gfx/DrawableNinePatch.cpp @@ -15,9 +15,9 @@ using starlight::gfx::DrawableNinePatch; using starlight::gfx::RenderCore; using starlight::gfx::CRenderTarget; -void DrawableNinePatch::Draw(const VRect& rect, OptRef sampleRect, OptRef color) { +void DrawableNinePatch::Draw(const VRect& rect, OptRef sampleRect, OptRef color, BlendMode mode) { if (GFXManager::PrepareForDrawing()) { - texture->Bind(color ? color.get() : Color(1,1,1,1)); + texture->Bind(color ? color.get() : Color(1,1,1,1), mode); VRect rr = rect.IntSnap(); const VRect& sr = (sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size)).IntSnap(); diff --git a/libstarlight/source/starlight/gfx/DrawableNinePatch.h b/libstarlight/source/starlight/gfx/DrawableNinePatch.h index df12173..14b9c41 100644 --- a/libstarlight/source/starlight/gfx/DrawableNinePatch.h +++ b/libstarlight/source/starlight/gfx/DrawableNinePatch.h @@ -16,7 +16,7 @@ namespace starlight { ~DrawableNinePatch() override { } //void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; - void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr) override; + void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr, BlendMode mode = BlendMode::Normal) override; }; } -} \ No newline at end of file +} diff --git a/libstarlight/source/starlight/gfx/DrawableTest.cpp b/libstarlight/source/starlight/gfx/DrawableTest.cpp index a14a4c8..aa618f0 100644 --- a/libstarlight/source/starlight/gfx/DrawableTest.cpp +++ b/libstarlight/source/starlight/gfx/DrawableTest.cpp @@ -11,17 +11,16 @@ using starlight::gfx::DrawableTest; using starlight::gfx::RenderCore; -void DrawableTest::Draw(const Vector2& position, const Vector2& origin, OptRef sampleRect, OptRef color, float rotation, const Vector2& scale) { +void DrawableTest::Draw(const Vector2& position, const Vector2& origin, OptRef sampleRect, OptRef color, float rotation, const Vector2& scale, BlendMode mode) { if (GFXManager::PrepareForDrawing()) { //static u32 col = Color(0, 0.5f, 1); //sf2d_draw_rectangle_rotate(position.x, position.y, 16, 16, col, rotation); } } -void DrawableTest::Draw(const VRect& rect, OptRef sampleRect, OptRef color) { +void DrawableTest::Draw(const VRect& rect, OptRef sampleRect, OptRef color, BlendMode mode) { if (GFXManager::PrepareForDrawing()) { - RenderCore::BindColor(color ? color.get() : Color(1,1,1,1)); + RenderCore::BindColor(color ? color.get() : Color(1,1,1,1), mode); RenderCore::DrawQuad(rect, VRect()); } } - diff --git a/libstarlight/source/starlight/gfx/DrawableTest.h b/libstarlight/source/starlight/gfx/DrawableTest.h index 0b686d6..7dc8977 100644 --- a/libstarlight/source/starlight/gfx/DrawableTest.h +++ b/libstarlight/source/starlight/gfx/DrawableTest.h @@ -10,11 +10,10 @@ namespace starlight { DrawableTest() { } ~DrawableTest() override { } - void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; - void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr) override; + void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef sampleRect = nullptr, OptRef color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) override; + void Draw(const VRect& rect, OptRef sampleRect = nullptr, OptRef color = nullptr, BlendMode mode = BlendMode::Normal) override; Vector2 Size() override { return Vector2::zero; } }; } } - diff --git a/libstarlight/source/starlight/gfx/Enums.h b/libstarlight/source/starlight/gfx/Enums.h new file mode 100644 index 0000000..7636579 --- /dev/null +++ b/libstarlight/source/starlight/gfx/Enums.h @@ -0,0 +1,14 @@ +#pragma once +#include "starlight/_global.h" + +namespace starlight { + namespace gfx { + enum class BlendMode { + Blend, + Mask, + Replace, + + Normal = Blend + }; + } +} diff --git a/libstarlight/source/starlight/gfx/RenderCore.cpp b/libstarlight/source/starlight/gfx/RenderCore.cpp index fecb35e..0916b65 100644 --- a/libstarlight/source/starlight/gfx/RenderCore.cpp +++ b/libstarlight/source/starlight/gfx/RenderCore.cpp @@ -78,8 +78,8 @@ namespace { // internals C3D_TexDelete(texture); delete texture; } - void Bind(Color color = Color::white) override { - RenderCore::BindTexture(texture, color); + void Bind(Color color = Color::white, BlendMode mode = BlendMode::Normal) override { + RenderCore::BindTexture(texture, color, mode); } }; } @@ -136,9 +136,13 @@ void RenderCore::Close() { gfxExit(); } +void RenderCore::SyncFrame() { + C3D_FrameSync(); +} + void RenderCore::BeginFrame() { ResetBuffer(); - C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C3D_FrameBegin(0/*C3D_FRAME_SYNCDRAW*/); } void RenderCore::EndFrame() { @@ -322,7 +326,7 @@ void CRenderTarget::BindTarget() { } } -void CRenderTarget::Bind(Color color) { +void CRenderTarget::Bind(Color color, BlendMode mode) { //C3D_RenderTargetSetClear(tgt, static_cast(0), 0, 0); // don't clear again until marked to - RenderCore::BindTexture(&tex, color); + RenderCore::BindTexture(&tex, color, mode); } diff --git a/libstarlight/source/starlight/gfx/RenderCore.h b/libstarlight/source/starlight/gfx/RenderCore.h index bd0a1dc..d4a5b3b 100644 --- a/libstarlight/source/starlight/gfx/RenderCore.h +++ b/libstarlight/source/starlight/gfx/RenderCore.h @@ -9,19 +9,13 @@ #include "starlight/datatypes/VRect.h" #include "starlight/datatypes/Color.h" +#include "starlight/gfx/Enums.h" + #include "starlight/util/WorkerThread.h" namespace starlight { namespace gfx { class RenderCore; - enum class BlendMode { - Blend, - Mask, - Replace, - - Normal = Blend - }; - class CTexture { protected: CTexture() = default; @@ -31,7 +25,7 @@ namespace starlight { Vector2 txSize; virtual ~CTexture() = default; - virtual void Bind(Color color = Color::white) = 0; + virtual void Bind(Color color = Color::white, BlendMode mode = BlendMode::Normal) = 0; }; class CRenderTarget : public CTexture { @@ -51,7 +45,7 @@ namespace starlight { void Clear(Color color); void BindTarget(); - void Bind(Color color = Color::white) override; + void Bind(Color color = Color::white, BlendMode mode = BlendMode::Normal) override; }; class RenderCore { @@ -67,6 +61,7 @@ namespace starlight { static void Open(); static void Close(); + static void SyncFrame(); static void BeginFrame(); static void EndFrame(); diff --git a/libstarlight/source/starlight/threading/Thread.cpp b/libstarlight/source/starlight/threading/Thread.cpp index 1791023..66adf77 100644 --- a/libstarlight/source/starlight/threading/Thread.cpp +++ b/libstarlight/source/starlight/threading/Thread.cpp @@ -41,8 +41,11 @@ void Thread::_FinishStart() { void Thread::Yield() { if (state != ThreadState::Running) return; // not executing this right now, this would just futz it up + state = ThreadState::Idle; svcWaitSynchronization(event, -1 /*U64_MAX*/); + //svcWaitSynchronization(event, 65536); svcClearEvent(event); + state = ThreadState::Running; } void Thread::Resume() { diff --git a/libstarlight/todo.txt b/libstarlight/todo.txt index 6453a53..402423a 100644 --- a/libstarlight/todo.txt +++ b/libstarlight/todo.txt @@ -4,6 +4,7 @@ roadmap to v0.5.1 { - clear bug workaround implemented ^ maybe replace clearing with the workaround entirely? + try to figure out why the workaround doesn't work in citra implement more blend modes { - flat replace masking @@ -18,20 +19,19 @@ roadmap to v0.5.1 { fix `, ' and " glyph spacing/offset adjust /\ some? proper thread dispatch? { - probably part of Application, actually - - Application main loop keeps a(n abstracted) libctru TickCounter and keeps track of frame time - thread objects are held in a std::list, Application dispatches resume events and splice()s them to the end until frame time reaches some proportion of 1/60s - x.splice( x.end(), x, iter ); + - Application main loop keeps a(n abstracted) libctru TickCounter and keeps track of frame time + - thread objects are held in a std::list, Application dispatches resume events and splice()s them to the end until frame time reaches some proportion of 1/60s - thread gets a yield function that calls svcWaitSynchronization on its resume event ...and some mechanism for allowing it to opt out of the rest of the cycle Trackable sideclass for threads; float progress 0..1, etc. + MAKE THREADS END CLEANLY } } then by v0.5.5 { event propagation system of some sort; threadsafe to whatever extent is needed on 3DS figure out how to *actually* fix the clear bug...? } then consider these before 1.0 "gold" { + replace some of the OptRef stuffs on invalidatable types with invalid checks; add implicit conversions from nullptr to invalid make closing forms a bit less finicky (add them to a separate list and let the Application remove them from the list) garbage collection for not-recently-used theme assets { - keep track of last-use in ThemeRefContainer diff --git a/testbed/source/Core.cpp b/testbed/source/Core.cpp index bc42660..e63612f 100644 --- a/testbed/source/Core.cpp +++ b/testbed/source/Core.cpp @@ -22,6 +22,8 @@ #include "starlight/dialog/MessageBox.h" #include "starlight/dialog/OSK.h" +#include "ThreadTest.h" + using starlight::Vector2; using starlight::VRect; using starlight::Color; @@ -88,6 +90,9 @@ void Core::Init() { // open a backdrop with the default asset sl::dialog::Backdrop::New()->Open(); + // make a test thread + std::make_shared()->Enqueue(); + // }; container->Add(button); diff --git a/testbed/source/ThreadTest.cpp b/testbed/source/ThreadTest.cpp new file mode 100644 index 0000000..411cf7f --- /dev/null +++ b/testbed/source/ThreadTest.cpp @@ -0,0 +1,21 @@ +#include "ThreadTest.h" + +#include "starlight/Application.h" +#include "starlight/ConfigManager.h" + +using starlight::Application; + +void ThreadTest::Body() { + auto& cc = Application::GetConfig("test"); + int count = 0; + cc.Json()["pork"] = 0; + cc.Save(); + cc.autoSave = true; + + while(true) { + + cc.Json()["pork"] = ++count; + //cc.Save(); + Yield(); + } +} diff --git a/testbed/source/ThreadTest.h b/testbed/source/ThreadTest.h new file mode 100644 index 0000000..c5c999a --- /dev/null +++ b/testbed/source/ThreadTest.h @@ -0,0 +1,7 @@ +#pragma once + +#include "starlight/threading/Thread.h" + +class ThreadTest : public sl::threading::Thread { + void Body() override; +};