bool QueueRender(TA_context* ctx) { verify(ctx != 0); if (FrameSkipping && frameskip) { frameskip=1-frameskip; tactx_Recycle(ctx); fskip++; return false; } if (rqueue) { tactx_Recycle(ctx); fskip++; return false; } frame_finished.Reset(); #ifndef TARGET_NO_THREADS slock_lock(mtx_rqueue); #endif TA_context* old = rqueue; rqueue=ctx; #ifndef TARGET_NO_THREADS slock_unlock(mtx_rqueue); #endif verify(!old); return true; }
//Return read buffer , 0 if none bool asRingRead(u8* dst,u32 sz) { if (sz==0) sz=BufferSampleCount; if (asRingUsedCount()>=sz) { const u32 ptr=ReadPtr; if ((ReadPtr+sz)<=RingBufferSampleCount) { //R ... W, just copy the sz :) memcpy(dst,&RingBuffer[ptr],sz*sizeof(s16)*2); } else { //...W R...., just copy the sz :) const u32 szhi=RingBufferSampleCount-ptr; const u32 szlow=sz-szhi; memcpy(dst,&RingBuffer[ptr],szhi*sizeof(s16)*2); dst+=szhi*sizeof(s16)*2; memcpy(dst,&RingBuffer[0],szlow*sizeof(s16)*2); } ReadPtr=(ptr+sz)%RingBufferSampleCount; speed_limit.Set(); return true; } else { //printf("ONLY %d used, rd=%d, wt=%d\n",asRingUsedCount(),ReadPtr,WritePtr); return false; } }
bool QueueRender(TA_context* ctx) { 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.SynchronousRender) { //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(); mtx_rqueue.Lock(); TA_context* old = rqueue; rqueue=ctx; mtx_rqueue.Unlock(); verify(!old); return true; }
void FinishRender(TA_context* ctx) { verify(rqueue == ctx); mtx_rqueue.Lock(); rqueue = 0; mtx_rqueue.Unlock(); tactx_Recycle(ctx); frame_finished.Set(); }
void rend_end_render() { #if 1 //also disabled the printf, it takes quite some time ... #if HOST_OS!=OS_WINDOWS && !(defined(_ANDROID) || defined(TARGET_PANDORA)) if (!re.state) printf("Render > Extended time slice ...\n"); #endif #endif if (pend_rend) re.Wait(); }
bool rend_frame(TA_context* ctx, bool draw_osd) { bool proc = renderer->Process(ctx); re.Set(); bool do_swp = proc && renderer->Render(); if (do_swp && draw_osd) renderer->DrawOSD(); return do_swp; }
void rend_end_render() { #if 1 //also disabled the printf, it takes quite some time ... #if HOST_OS!=OS_WINDOWS && !(defined(_ANDROID) || defined(TARGET_PANDORA)) //too much console spam. //TODO: how about a counter? //if (!re.state) printf("Render > Extended time slice ...\n"); #endif #endif if (pend_rend) re.Wait(); }
void FinishRender(TA_context* ctx) { verify(rqueue == ctx); #ifndef TARGET_NO_THREADS slock_lock(mtx_rqueue); #endif rqueue = 0; #ifndef TARGET_NO_THREADS slock_unlock(mtx_rqueue); #endif tactx_Recycle(ctx); frame_finished.Set(); }
void WriteSample(s16 r, s16 l) { #ifdef LOG_SOUND rawout.Write(l,r); #endif speed_limit.Reset(); if (!asRingFreeCount()) { if (settings.LimitFPS) { speed_limit.Wait(); } else return; } gen_samples++; //while limit on, 128 samples done, there is a buffer ready to be service AND speed is too fast then wait ;p while (settings.LimitFPS==1 && gen_samples>128 && asRingUsedCount()>BufferSampleCount && QueryPerformanceCounter(&time_now) && (time_now.QuadPart-time_last.QuadPart)<=time_diff.QuadPart ) { __noop; } if (settings.LimitFPS==1 && gen_samples>128) { gen_samples=0; QueryPerformanceCounter(&time_last); } const u32 ptr=(WritePtr+1)%RingBufferSampleCount; RingBuffer[ptr].r=r; RingBuffer[ptr].l=l; WritePtr=ptr; //if (0==(WritePtr&255)) //printf("write done %d %d \n",ReadPtr,WritePtr); }
void os_consume(double t) { double cyc=t*190*1000*1000; if ((cycl_glob+cyc)<10*1000*1000) { InterlockedExchangeAdd(&cycl_glob,cyc); } else { cycl_glob=10*1000*1000; } evt_hld.Set(); }
bool rend_single_frame() { //wait render start only if no frame pending do { rs.Wait(); _pvrrc = DequeueRender(); } while (!_pvrrc); bool proc = renderer->Process(_pvrrc); re.Set(); bool do_swp = proc && renderer->Render(); if (do_swp) renderer->DrawOSD(); //clear up & free data .. FinishRender(_pvrrc); _pvrrc=0; return do_swp; }
void rend_start_render() { pend_rend = false; bool is_rtt=(FB_W_SOF1& 0x1000000)!=0; TA_context* ctx = tactx_Pop(CORE_CURRENT_CTX); SetREP(ctx); if (ctx) { if (!ctx->rend.Overrun) { //printf("REP: %.2f ms\n",render_end_pending_cycles/200000.0); FillBGP(ctx); ctx->rend.isRTT=is_rtt; ctx->rend.isAutoSort = UsingAutoSort(); ctx->rend.fb_X_CLIP=FB_X_CLIP; ctx->rend.fb_Y_CLIP=FB_Y_CLIP; max_idx=max(max_idx,ctx->rend.idx.used()); max_vtx=max(max_vtx,ctx->rend.verts.used()); max_op=max(max_op,ctx->rend.global_param_op.used()); max_pt=max(max_pt,ctx->rend.global_param_pt.used()); max_tr=max(max_tr,ctx->rend.global_param_tr.used()); max_mvo=max(max_mvo,ctx->rend.global_param_mvo.used()); max_modt=max(max_modt,ctx->rend.modtrig.used()); #if HOST_OS==OS_WINDOWS && 0 printf("max: idx: %d, vtx: %d, op: %d, pt: %d, tr: %d, mvo: %d, modt: %d, ov: %d\n", max_idx, max_vtx, max_op, max_pt, max_tr, max_mvo, max_modt, ovrn); #endif if (QueueRender(ctx)) { palette_update(); rs.Set(); pend_rend = true; } } else { ovrn++; printf("WARNING: Rendering context is overrun (%d), aborting frame\n",ovrn); tactx_Recycle(ctx); } } }
bool rend_single_frame() { //wait render start only if no frame pending do { rs.Wait(); _pvrrc = DequeueRender(); } while (!_pvrrc); bool do_swp = rend_frame(_pvrrc, true); //clear up & free data .. FinishRender(_pvrrc); _pvrrc=0; return do_swp; }