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() {
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
}
}

View File

@ -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<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()) {
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<VRect> sampleRect, OptRef<Color> color) {
void DrawContextCanvas::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color, BlendMode mode) {
if (GFXManager::PrepareForDrawing()) {
target->Bind(color ? color.get() : Color(1,1,1,1));
const VRect& sr = sampleRect ? sampleRect.get() : this->rect;

View File

@ -23,8 +23,8 @@ namespace starlight {
DrawContextCanvas(Vector2 size);
~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 VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) 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, BlendMode mode = BlendMode::Normal) override;
Vector2 Size() override;
@ -32,4 +32,4 @@ namespace starlight {
void Clear() override;
};
}
}
}

View File

@ -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<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) = 0;
void Draw(const Vector2& position, OptRef<Vector2> hotspot, OptRef<VRect> sampleRect, OptRef<Color> 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<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, BlendMode mode = BlendMode::Normal) {
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;
};
}
}

View File

@ -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<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()) {
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<VRect> sampleRect, OptRef<Color> color) {
void DrawableImage::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> 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);
}

View File

@ -15,11 +15,10 @@ namespace starlight {
DrawableImage(CTexture* texture) : texture(texture) { }
~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 VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) 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, BlendMode mode = BlendMode::Normal) override;
Vector2 Size() override;
};
}
}

View File

@ -15,9 +15,9 @@ using starlight::gfx::DrawableNinePatch;
using starlight::gfx::RenderCore;
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()) {
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();

View File

@ -16,7 +16,7 @@ namespace starlight {
~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 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;
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()) {
//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<VRect> sampleRect, OptRef<Color> color) {
void DrawableTest::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> 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());
}
}

View File

@ -10,11 +10,10 @@ namespace starlight {
DrawableTest() { }
~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 VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) 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, BlendMode mode = BlendMode::Normal) override;
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);
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<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/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();

View File

@ -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() {

View File

@ -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

View File

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