mirror of
https://github.com/zetaPRIME/libstarlight.git
synced 2025-06-26 13:42:46 +00:00
more complete threading, update to newest libctru and c3d-next (clearing a new rendertarget doesn't work the first time yet)
This commit is contained in:
parent
9645920759
commit
144510b4e7
@ -98,6 +98,8 @@ void Application::_end() {
|
||||
}
|
||||
|
||||
void Application::_mainLoop() {
|
||||
frameTimer.FrameStart();
|
||||
|
||||
if (!forms.empty()) {
|
||||
if (_sFormState) {
|
||||
_sFormState = false;
|
||||
@ -154,4 +156,14 @@ void Application::_mainLoop() {
|
||||
topScreen->Draw();
|
||||
PostDraw();
|
||||
RenderCore::EndFrame();
|
||||
|
||||
while (!threads.empty() && frameTimer.GetSubframe() < 0.9) {
|
||||
threads.front()->Resume();
|
||||
threads.splice(threads.end(), threads, threads.begin()); // move to back of queue
|
||||
}
|
||||
}
|
||||
|
||||
void Application::EnqueueThread(std::shared_ptr<starlight::threading::Thread> thread) {
|
||||
threads.push_back(thread);
|
||||
thread->Start();
|
||||
}
|
||||
|
@ -3,11 +3,16 @@
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
|
||||
#include "starlight/datatypes/Vector2.h"
|
||||
#include "starlight/datatypes/VRect.h"
|
||||
#include "starlight/datatypes/Color.h"
|
||||
|
||||
#include "starlight/util/FrameTimer.h"
|
||||
|
||||
#include "starlight/threading/Thread.h"
|
||||
|
||||
#include "starlight/ui/TouchScreenCanvas.h"
|
||||
#include "starlight/ui/TopScreenCanvas.h"
|
||||
|
||||
@ -41,6 +46,9 @@ namespace starlight {
|
||||
void _mainLoop();
|
||||
void _end();
|
||||
|
||||
std::list<std::shared_ptr<threading::Thread>> threads;
|
||||
util::FrameTimer frameTimer;
|
||||
|
||||
public:
|
||||
const std::string appId;
|
||||
|
||||
@ -59,13 +67,14 @@ namespace starlight {
|
||||
|
||||
void Run();
|
||||
|
||||
void EnqueueThread(std::shared_ptr<threading::Thread> thread);
|
||||
inline void SignalFormState() { _sFormState = true; }
|
||||
|
||||
virtual void Init() { }
|
||||
virtual void Update() { }
|
||||
virtual void PostUpdate() { }
|
||||
virtual void Draw() { }
|
||||
virtual void PostDraw() { }
|
||||
virtual void End() { }
|
||||
|
||||
inline void SignalFormState() { _sFormState = true; }
|
||||
};
|
||||
}
|
||||
|
@ -248,9 +248,22 @@ CRenderTarget::CRenderTarget(int width, int height, bool forceExact) {
|
||||
auto w = forceExact ? width : NextPow2(width),
|
||||
h = forceExact ? height : NextPow2(height);
|
||||
txSize = Vector2(w, h);
|
||||
|
||||
tgt = C3D_RenderTargetCreate(w, h, GPU_RB_RGBA8, -1/*GPU_RB_DEPTH24_STENCIL8*/); // I don't think we need a depth buffer >.>
|
||||
//tgt = C3D_RenderTargetCreateFromTex(&tex, GPU_TEXFACE_2D, -1, -1); // create target from texture, actually
|
||||
|
||||
C3D_TexInit(&tex, w, h, GPU_RGBA8);
|
||||
//memset(tex.data, 0, w*h*4); // manually zero out; TODO: optimize this
|
||||
C3D_TexDelete(&tex); tex.data = tgt->frameBuf.colorBuf; // replace stuff...
|
||||
|
||||
Mtx_Ortho(&projection, 0.0f, w, 0.0f, h, 0.0f, 1.0f, true);
|
||||
//Mtx_OrthoTilt(&projection, 0.0f, h, 0.0f, w, 0.0f, 1.0f, true);
|
||||
|
||||
//C3D_FrameBufClear(&(tgt->frameBuf), C3D_CLEAR_ALL, 0, 0);
|
||||
//Clear(Color::transparent);
|
||||
//RenderCore::BindTexture(&tex, Color::white);
|
||||
//C3D_FrameBufClear(&(tgt->frameBuf), C3D_CLEAR_COLOR, 0, 0);
|
||||
//C3D_RenderTargetSetClear(tgt, static_cast<C3D_ClearBits>(0), 0, 0);
|
||||
}
|
||||
|
||||
CRenderTarget::~CRenderTarget() {
|
||||
@ -258,17 +271,26 @@ CRenderTarget::~CRenderTarget() {
|
||||
}
|
||||
|
||||
void CRenderTarget::Clear(Color color) {
|
||||
unsigned int c = color;
|
||||
c = ((c>>24)&0x000000FF) | ((c>>8)&0x0000FF00) | ((c<<8)&0x00FF0000) | ((c<<24)&0xFF000000); // reverse endianness
|
||||
C3D_RenderTargetSetClear(tgt, C3D_CLEAR_ALL, c, 0);
|
||||
//unsigned int c = color;
|
||||
//c = ((c>>24)&0x000000FF) | ((c>>8)&0x0000FF00) | ((c<<8)&0x00FF0000) | ((c<<24)&0xFF000000); // reverse endianness
|
||||
//C3D_RenderTargetSetClear(tgt, C3D_CLEAR_ALL, c, 0);
|
||||
//C3D_FrameBufClear(&(tgt->frameBuf), C3D_CLEAR_COLOR, c, 0);
|
||||
clearColor = color;
|
||||
}
|
||||
|
||||
void CRenderTarget::BindTarget() {
|
||||
if (true || clearColor) { // clear if color valid
|
||||
unsigned int c = clearColor;
|
||||
c = ((c>>24)&0x000000FF) | ((c>>8)&0x0000FF00) | ((c<<8)&0x00FF0000) | ((c<<24)&0xFF000000); // reverse endianness
|
||||
//C3D_RenderTargetSetClear(tgt, static_cast<C3D_ClearBits>(0), c, 0);
|
||||
//C3D_RenderTargetSetClear(tgt, C3D_CLEAR_ALL, c, 0);
|
||||
C3D_FrameBufClear(&(tgt->frameBuf), C3D_CLEAR_COLOR, c, 0);
|
||||
}
|
||||
C3D_FrameDrawOn(tgt);
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, sLocProjection, &projection);
|
||||
}
|
||||
|
||||
void CRenderTarget::Bind(Color color) {
|
||||
C3D_RenderTargetSetClear(tgt, 0, 0, 0); // don't clear again until marked to
|
||||
RenderCore::BindTexture(&(tgt->renderBuf.colorBuf), color);
|
||||
//C3D_RenderTargetSetClear(tgt, static_cast<C3D_ClearBits>(0), 0, 0); // don't clear again until marked to
|
||||
RenderCore::BindTexture(&tex, color);
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ namespace starlight {
|
||||
friend class starlight::gfx::RenderCore;
|
||||
protected:
|
||||
C3D_RenderTarget* tgt;
|
||||
C3D_Tex tex;
|
||||
Color clearColor = Color::transparent;
|
||||
|
||||
public:
|
||||
C3D_Mtx projection;
|
||||
|
@ -2,13 +2,16 @@
|
||||
|
||||
#include "3ds.h"
|
||||
|
||||
#include "starlight/Application.h"
|
||||
|
||||
using starlight::threading::Thread;
|
||||
using SysThread = ::Thread;
|
||||
using SThread = starlight::threading::Thread;
|
||||
|
||||
namespace {
|
||||
void _ThreadEnter(void* arg) {
|
||||
// cast to thread and start up
|
||||
static_cast<starlight::threading::Thread*>(arg)->_FinishStart();
|
||||
static_cast<SThread*>(arg)->_FinishStart();
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +20,13 @@ Thread::~Thread() {
|
||||
if (event != 0) svcCloseHandle(event);
|
||||
}
|
||||
|
||||
void Thread::Enqueue() {
|
||||
if (state != ThreadState::Unqueued) return; // don't double enqueue, you derp
|
||||
Application::Current()->EnqueueThread(shared_from_this());
|
||||
}
|
||||
|
||||
void Thread::Start() {
|
||||
state = ThreadState::Init;
|
||||
svcCreateEvent(&event, RESET_ONESHOT);
|
||||
sthread = static_cast<void*>(threadCreate(_ThreadEnter, static_cast<void*>(this), 4*1024, 0x3F, -2, false));
|
||||
|
||||
@ -25,6 +34,7 @@ void Thread::Start() {
|
||||
void Thread::_FinishStart() {
|
||||
// lock out once already done
|
||||
if (state != ThreadState::Init) return;
|
||||
state = ThreadState::Running;
|
||||
Yield();
|
||||
Body();
|
||||
}
|
||||
|
@ -1,15 +1,21 @@
|
||||
#pragma once
|
||||
#include "starlight/_global.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace starlight {
|
||||
class Application;
|
||||
|
||||
namespace threading {
|
||||
enum class ThreadState : unsigned char {
|
||||
Unqueued, Init, Idle, Running
|
||||
Unqueued, Init, Idle, Running, Finished
|
||||
};
|
||||
|
||||
class Thread {
|
||||
class Thread : public std::enable_shared_from_this<Thread> {
|
||||
friend class starlight::Application;
|
||||
protected:
|
||||
volatile ThreadState state;
|
||||
|
||||
volatile ThreadState state = ThreadState::Unqueued;
|
||||
void* sthread;
|
||||
long unsigned int event = 0;
|
||||
|
||||
|
19
libstarlight/source/starlight/util/FrameTimer.cpp
Normal file
19
libstarlight/source/starlight/util/FrameTimer.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "FrameTimer.h"
|
||||
|
||||
#include "3ds.h"
|
||||
|
||||
using starlight::util::FrameTimer;
|
||||
|
||||
FrameTimer::FrameTimer() {
|
||||
osTickCounterStart(reinterpret_cast<TickCounter*>(&tc));
|
||||
}
|
||||
|
||||
void FrameTimer::FrameStart() {
|
||||
osTickCounterUpdate(reinterpret_cast<TickCounter*>(&tc));
|
||||
}
|
||||
|
||||
double FrameTimer::GetSubframe() {
|
||||
TickCounter tmp = *(reinterpret_cast<TickCounter*>(&tc));
|
||||
osTickCounterUpdate(&tmp);
|
||||
return osTickCounterRead(&tmp) * (60.0/1000.0);
|
||||
}
|
20
libstarlight/source/starlight/util/FrameTimer.h
Normal file
20
libstarlight/source/starlight/util/FrameTimer.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "starlight/_global.h"
|
||||
|
||||
namespace starlight {
|
||||
namespace util {
|
||||
class FrameTimer {
|
||||
private:
|
||||
struct TickCount {
|
||||
unsigned long long int elapsed;
|
||||
unsigned long long int ref;
|
||||
};
|
||||
TickCount tc;
|
||||
public:
|
||||
FrameTimer();
|
||||
|
||||
void FrameStart();
|
||||
double GetSubframe();
|
||||
};
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
|
||||
roadmap to v0.5.1 {
|
||||
figure out how to fix the clear bug
|
||||
- fix the hang on osk when pressing (L|R)+up+left
|
||||
figure out what (else) to put on the left side of the keyboard (opposite backspace and enter)
|
||||
temporary drawable loading, local themeref, discard etc.
|
||||
@ -11,11 +12,18 @@ roadmap to v0.5.1 {
|
||||
fix `, ' and " glyph spacing/offset
|
||||
adjust /\ some?
|
||||
proper thread dispatch? {
|
||||
Application main loop keeps a libctru TickCounter and keeps track of frame time;
|
||||
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 );
|
||||
- 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.
|
||||
}
|
||||
} then by v0.5.5 {
|
||||
event propagation system of some sort; threadsafe to whatever extent is needed on 3DS
|
||||
} then consider these before 1.0 "gold" {
|
||||
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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user