flycast/core/hw/pvr/ta_ctx.cpp

269 lines
4.3 KiB
C++
Raw Normal View History

2013-12-19 17:10:14 +00:00
#include "ta.h"
#include "ta_ctx.h"
#include "hw/sh4/sh4_sched.h"
2013-12-19 17:10:14 +00:00
extern u32 fskip;
extern u32 FrameCount;
int frameskip=0;
bool FrameSkipping=false; // global switch to enable/disable frameskip
2013-12-19 17:10:14 +00:00
TA_context* ta_ctx;
tad_context ta_tad;
TA_context* vd_ctx;
rend_context vd_rc;
2018-04-09 19:11:06 +00:00
// helper for 32 byte aligned memory allocation
void* OS_aligned_malloc(size_t align, size_t size)
{
void *result;
#if HOST_OS == OS_WINDOWS
result = _aligned_malloc(size, align);
#else
if(posix_memalign(&result, align, size)) result = 0;
#endif
return result;
}
// helper for 32 byte aligned memory de-allocation
void OS_aligned_free(void *ptr)
{
#if HOST_OS == OS_WINDOWS
_aligned_free(ptr);
#else
free(ptr);
#endif
}
2013-12-19 17:10:14 +00:00
void SetCurrentTARC(u32 addr)
{
if (addr != TACTX_NONE)
{
if (ta_ctx)
SetCurrentTARC(TACTX_NONE);
verify(ta_ctx == 0);
//set new context
ta_ctx = tactx_Find(addr,true);
//copy cached params
ta_tad = ta_ctx->tad;
}
else
{
//Flush cache to context
verify(ta_ctx != 0);
ta_ctx->tad=ta_tad;
//clear context
ta_ctx=0;
ta_tad.Reset(0);
2013-12-19 17:10:14 +00:00
}
}
bool TryDecodeTARC()
{
2015-01-10 19:15:15 +00:00
verify(ta_ctx != 0);
2013-12-19 17:10:14 +00:00
if (vd_ctx == 0)
{
vd_ctx = ta_ctx;
vd_ctx->rend.proc_start = vd_ctx->rend.proc_end + 32;
vd_ctx->rend.proc_end = vd_ctx->tad.thd_data;
2013-12-19 17:10:14 +00:00
vd_ctx->rend_inuse.Lock();
vd_rc = vd_ctx->rend;
//signal the vdec thread
return true;
}
else
return false;
}
void VDecEnd()
{
2015-01-10 19:15:15 +00:00
verify(vd_ctx != 0);
2013-12-19 17:10:14 +00:00
vd_ctx->rend = vd_rc;
vd_ctx->rend_inuse.Unlock();
vd_ctx = 0;
}
cMutex mtx_rqueue;
TA_context* rqueue;
cResetEvent frame_finished(false, true);
double last_frame = 0;
u64 last_cyces = 0;
2013-12-19 17:10:14 +00:00
bool QueueRender(TA_context* ctx)
2013-12-19 17:10:14 +00:00
{
verify(ctx != 0);
if (FrameSkipping && frameskip) {
frameskip=1-frameskip;
tactx_Recycle(ctx);
fskip++;
return false;
}
//Try to limit speed to a "sane" level
//Speed is also limited via audio, but audio
//is sometimes not accurate enough (android, vista+)
u32 cycle_span = sh4_sched_now64() - last_cyces;
last_cyces = sh4_sched_now64();
double time_span = os_GetSeconds() - last_frame;
last_frame = os_GetSeconds();
bool too_fast = (cycle_span / time_span) > (SH4_MAIN_CLOCK * 1.2);
if (rqueue && too_fast && settings.pvr.SynchronousRendering) {
//wait for a frame if
// we have another one queue'd and
// sh4 run at > 120% on the last slice
// and SynchronousRendering is enabled
frame_finished.Wait();
verify(!rqueue);
}
if (rqueue) {
tactx_Recycle(ctx);
fskip++;
return false;
}
frame_finished.Reset();
2013-12-19 17:10:14 +00:00
mtx_rqueue.Lock();
TA_context* old = rqueue;
rqueue=ctx;
mtx_rqueue.Unlock();
verify(!old);
return true;
2013-12-19 17:10:14 +00:00
}
TA_context* DequeueRender()
{
mtx_rqueue.Lock();
TA_context* rv = rqueue;
mtx_rqueue.Unlock();
if (rv)
FrameCount++;
return rv;
}
bool rend_framePending() {
mtx_rqueue.Lock();
TA_context* rv = rqueue;
mtx_rqueue.Unlock();
return rv != 0;
}
void FinishRender(TA_context* ctx)
{
verify(rqueue == ctx);
mtx_rqueue.Lock();
rqueue = 0;
mtx_rqueue.Unlock();
tactx_Recycle(ctx);
frame_finished.Set();
}
2013-12-19 17:10:14 +00:00
cMutex mtx_pool;
vector<TA_context*> ctx_pool;
vector<TA_context*> ctx_list;
TA_context* tactx_Alloc()
{
TA_context* rv = 0;
mtx_pool.Lock();
if (ctx_pool.size())
{
rv = ctx_pool[ctx_pool.size()-1];
ctx_pool.pop_back();
}
mtx_pool.Unlock();
if (!rv)
{
rv = new TA_context();
rv->Alloc();
printf("new tactx\n");
}
return rv;
}
void tactx_Recycle(TA_context* poped_ctx)
{
mtx_pool.Lock();
{
if (ctx_pool.size()>2)
{
poped_ctx->Free();
delete poped_ctx;
}
else
{
poped_ctx->Reset();
ctx_pool.push_back(poped_ctx);
}
}
mtx_pool.Unlock();
}
TA_context* tactx_Find(u32 addr, bool allocnew)
{
for (size_t i=0; i<ctx_list.size(); i++)
2013-12-19 17:10:14 +00:00
{
if (ctx_list[i]->Address==addr)
return ctx_list[i];
}
if (allocnew)
{
TA_context* rv = tactx_Alloc();
rv->Address=addr;
ctx_list.push_back(rv);
return rv;
}
else
{
2013-12-19 17:10:14 +00:00
return 0;
}
2013-12-19 17:10:14 +00:00
}
TA_context* tactx_Pop(u32 addr)
{
for (size_t i=0; i<ctx_list.size(); i++)
2013-12-19 17:10:14 +00:00
{
if (ctx_list[i]->Address==addr)
{
TA_context* rv = ctx_list[i];
if (ta_ctx == rv)
SetCurrentTARC(TACTX_NONE);
ctx_list.erase(ctx_list.begin() + i);
return rv;
}
}
return 0;
}