thread testing and fixes, exposed blend mode in drawables, made frame timing a bit more accurate

This commit is contained in:
zetaPRIME 2017-05-03 00:52:46 -04:00
parent c4a75355eb
commit 88d640f3e7
18 changed files with 97 additions and 50 deletions

View File

@ -98,6 +98,7 @@ void Application::_end() {
} }
void Application::_mainLoop() { void Application::_mainLoop() {
RenderCore::SyncFrame(); // sync to vblank here for more accurate timing
frameTimer.FrameStart(); frameTimer.FrameStart();
if (!forms.empty()) { if (!forms.empty()) {
@ -159,7 +160,7 @@ void Application::_mainLoop() {
while (!threads.empty() && frameTimer.GetSubframe() < 0.9) { while (!threads.empty() && frameTimer.GetSubframe() < 0.9) {
threads.front()->Resume(); 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
} }
} }

View File

@ -45,7 +45,7 @@ void DrawContextCanvas::Clear(Color color) {
void DrawContextCanvas::Clear() { Clear(Color(0,0,0,0)); } void DrawContextCanvas::Clear() { Clear(Color(0,0,0,0)); }
// drawable stuff // drawable stuff
void DrawContextCanvas::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale) { void DrawContextCanvas::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) { if (GFXManager::PrepareForDrawing()) {
target->Bind(color ? color.get() : Color(1,1,1,1)); target->Bind(color ? color.get() : Color(1,1,1,1));
const VRect& sr = sampleRect ? sampleRect.get() : this->rect; 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<VRect> sampleRect, OptRef<Color> color) { void DrawContextCanvas::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) { if (GFXManager::PrepareForDrawing()) {
target->Bind(color ? color.get() : Color(1,1,1,1)); target->Bind(color ? color.get() : Color(1,1,1,1));
const VRect& sr = sampleRect ? sampleRect.get() : this->rect; const VRect& sr = sampleRect ? sampleRect.get() : this->rect;

View File

@ -23,8 +23,8 @@ namespace starlight {
DrawContextCanvas(Vector2 size); DrawContextCanvas(Vector2 size);
~DrawContextCanvas(); ~DrawContextCanvas();
void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override; void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, BlendMode mode = BlendMode::Normal) override;
Vector2 Size() override; Vector2 Size() override;

View File

@ -7,6 +7,8 @@
#include "starlight/datatypes/OptRef.h" #include "starlight/datatypes/OptRef.h"
#include "starlight/gfx/Enums.h"
namespace starlight { namespace starlight {
namespace gfx { namespace gfx {
class Drawable { class Drawable {
@ -17,16 +19,14 @@ namespace starlight {
// pattern after: // pattern after:
// public abstract void Draw(DrawContext context, PxRect rect, PxRect? sampleRect = null, DrawColor? color = null); // 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); // 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<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) = 0; virtual void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) = 0;
void Draw(const Vector2& position, OptRef<Vector2> hotspot, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, float scale) { void Draw(const Vector2& position, OptRef<Vector2> hotspot, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, float scale, BlendMode mode = BlendMode::Normal) {
Draw(position, hotspot, sampleRect, color, rotation, Vector2(scale, scale)); Draw(position, hotspot, sampleRect, color, rotation, Vector2(scale, scale), mode);
} }
virtual void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) = 0; virtual void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, BlendMode mode = BlendMode::Normal) = 0;
virtual Vector2 Size() = 0; virtual Vector2 Size() = 0;
}; };
} }
} }

View File

@ -15,18 +15,18 @@ using starlight::gfx::DrawableImage;
using starlight::gfx::RenderCore; using starlight::gfx::RenderCore;
using starlight::gfx::CRenderTarget; using starlight::gfx::CRenderTarget;
void DrawableImage::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale) { void DrawableImage::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) { 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); const VRect& sr = sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size);
VRect rect(position - (texture->size * origin) * scale, sr.size * scale); VRect rect(position - (texture->size * origin) * scale, sr.size * scale);
RenderCore::DrawQuad(rect, position, rotation, sr / texture->txSize); RenderCore::DrawQuad(rect, position, rotation, sr / texture->txSize);
} }
} }
void DrawableImage::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color) { void DrawableImage::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) { 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); const VRect& sr = sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size);
RenderCore::DrawQuad(rect, sr / texture->txSize); RenderCore::DrawQuad(rect, sr / texture->txSize);
} }

View File

@ -15,11 +15,10 @@ namespace starlight {
DrawableImage(CTexture* texture) : texture(texture) { } DrawableImage(CTexture* texture) : texture(texture) { }
~DrawableImage() override { } ~DrawableImage() override { }
void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override; void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, BlendMode mode = BlendMode::Normal) override;
Vector2 Size() override; Vector2 Size() override;
}; };
} }
} }

View File

@ -15,9 +15,9 @@ using starlight::gfx::DrawableNinePatch;
using starlight::gfx::RenderCore; using starlight::gfx::RenderCore;
using starlight::gfx::CRenderTarget; using starlight::gfx::CRenderTarget;
void DrawableNinePatch::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color) { void DrawableNinePatch::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) { 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(); VRect rr = rect.IntSnap();
const VRect& sr = (sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size)).IntSnap(); const VRect& sr = (sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size)).IntSnap();

View File

@ -16,7 +16,7 @@ namespace starlight {
~DrawableNinePatch() override { } ~DrawableNinePatch() override { }
//void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; //void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override; void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, BlendMode mode = BlendMode::Normal) override;
}; };
} }
} }

View File

@ -11,17 +11,16 @@ using starlight::gfx::DrawableTest;
using starlight::gfx::RenderCore; using starlight::gfx::RenderCore;
void DrawableTest::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale) { void DrawableTest::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) { if (GFXManager::PrepareForDrawing()) {
//static u32 col = Color(0, 0.5f, 1); //static u32 col = Color(0, 0.5f, 1);
//sf2d_draw_rectangle_rotate(position.x, position.y, 16, 16, col, rotation); //sf2d_draw_rectangle_rotate(position.x, position.y, 16, 16, col, rotation);
} }
} }
void DrawableTest::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color) { void DrawableTest::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) { 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()); RenderCore::DrawQuad(rect, VRect());
} }
} }

View File

@ -10,11 +10,10 @@ namespace starlight {
DrawableTest() { } DrawableTest() { }
~DrawableTest() override { } ~DrawableTest() override { }
void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override; void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one, BlendMode mode = BlendMode::Normal) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override; void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, BlendMode mode = BlendMode::Normal) override;
Vector2 Size() override { return Vector2::zero; } Vector2 Size() override { return Vector2::zero; }
}; };
} }
} }

View File

@ -0,0 +1,14 @@
#pragma once
#include "starlight/_global.h"
namespace starlight {
namespace gfx {
enum class BlendMode {
Blend,
Mask,
Replace,
Normal = Blend
};
}
}

View File

@ -78,8 +78,8 @@ namespace { // internals
C3D_TexDelete(texture); C3D_TexDelete(texture);
delete texture; delete texture;
} }
void Bind(Color color = Color::white) override { void Bind(Color color = Color::white, BlendMode mode = BlendMode::Normal) override {
RenderCore::BindTexture(texture, color); RenderCore::BindTexture(texture, color, mode);
} }
}; };
} }
@ -136,9 +136,13 @@ void RenderCore::Close() {
gfxExit(); gfxExit();
} }
void RenderCore::SyncFrame() {
C3D_FrameSync();
}
void RenderCore::BeginFrame() { void RenderCore::BeginFrame() {
ResetBuffer(); ResetBuffer();
C3D_FrameBegin(C3D_FRAME_SYNCDRAW); C3D_FrameBegin(0/*C3D_FRAME_SYNCDRAW*/);
} }
void RenderCore::EndFrame() { 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<C3D_ClearBits>(0), 0, 0); // don't clear again until marked to //C3D_RenderTargetSetClear(tgt, static_cast<C3D_ClearBits>(0), 0, 0); // don't clear again until marked to
RenderCore::BindTexture(&tex, color); RenderCore::BindTexture(&tex, color, mode);
} }

View File

@ -9,19 +9,13 @@
#include "starlight/datatypes/VRect.h" #include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h" #include "starlight/datatypes/Color.h"
#include "starlight/gfx/Enums.h"
#include "starlight/util/WorkerThread.h" #include "starlight/util/WorkerThread.h"
namespace starlight { namespace starlight {
namespace gfx { namespace gfx {
class RenderCore; class RenderCore;
enum class BlendMode {
Blend,
Mask,
Replace,
Normal = Blend
};
class CTexture { class CTexture {
protected: protected:
CTexture() = default; CTexture() = default;
@ -31,7 +25,7 @@ namespace starlight {
Vector2 txSize; Vector2 txSize;
virtual ~CTexture() = default; 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 { class CRenderTarget : public CTexture {
@ -51,7 +45,7 @@ namespace starlight {
void Clear(Color color); void Clear(Color color);
void BindTarget(); void BindTarget();
void Bind(Color color = Color::white) override; void Bind(Color color = Color::white, BlendMode mode = BlendMode::Normal) override;
}; };
class RenderCore { class RenderCore {
@ -67,6 +61,7 @@ namespace starlight {
static void Open(); static void Open();
static void Close(); static void Close();
static void SyncFrame();
static void BeginFrame(); static void BeginFrame();
static void EndFrame(); static void EndFrame();

View File

@ -41,8 +41,11 @@ void Thread::_FinishStart() {
void Thread::Yield() { void Thread::Yield() {
if (state != ThreadState::Running) return; // not executing this right now, this would just futz it up 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, -1 /*U64_MAX*/);
//svcWaitSynchronization(event, 65536);
svcClearEvent(event); svcClearEvent(event);
state = ThreadState::Running;
} }
void Thread::Resume() { void Thread::Resume() {

View File

@ -4,6 +4,7 @@
roadmap to v0.5.1 { roadmap to v0.5.1 {
- clear bug workaround implemented - clear bug workaround implemented
^ maybe replace clearing with the workaround entirely? ^ maybe replace clearing with the workaround entirely?
try to figure out why the workaround doesn't work in citra
implement more blend modes { implement more blend modes {
- flat replace - flat replace
masking masking
@ -18,20 +19,19 @@ roadmap to v0.5.1 {
fix `, ' and " glyph spacing/offset fix `, ' and " glyph spacing/offset
adjust /\ some? adjust /\ some?
proper thread dispatch? { 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
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 );
- thread gets a yield function that calls svcWaitSynchronization on its resume event - 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 ...and some mechanism for allowing it to opt out of the rest of the cycle
Trackable sideclass for threads; float progress 0..1, etc. Trackable sideclass for threads; float progress 0..1, etc.
MAKE THREADS END CLEANLY
} }
} then by v0.5.5 { } then by v0.5.5 {
event propagation system of some sort; threadsafe to whatever extent is needed on 3DS event propagation system of some sort; threadsafe to whatever extent is needed on 3DS
figure out how to *actually* fix the clear bug...? figure out how to *actually* fix the clear bug...?
} then consider these before 1.0 "gold" { } 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) 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 { garbage collection for not-recently-used theme assets {
- keep track of last-use in ThemeRefContainer - keep track of last-use in ThemeRefContainer

View File

@ -22,6 +22,8 @@
#include "starlight/dialog/MessageBox.h" #include "starlight/dialog/MessageBox.h"
#include "starlight/dialog/OSK.h" #include "starlight/dialog/OSK.h"
#include "ThreadTest.h"
using starlight::Vector2; using starlight::Vector2;
using starlight::VRect; using starlight::VRect;
using starlight::Color; using starlight::Color;
@ -88,6 +90,9 @@ void Core::Init() {
// open a backdrop with the default asset // open a backdrop with the default asset
sl::dialog::Backdrop::New()->Open(); sl::dialog::Backdrop::New()->Open();
// make a test thread
std::make_shared<ThreadTest>()->Enqueue();
// //
}; };
container->Add(button); container->Add(button);

View File

@ -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();
}
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "starlight/threading/Thread.h"
class ThreadTest : public sl::threading::Thread {
void Body() override;
};