u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData) { if (s_BackendInitialized && g_ActiveConfig.bEFBAccessEnable) { s_accessEFBArgs.type = type; s_accessEFBArgs.x = x; s_accessEFBArgs.y = y; s_accessEFBArgs.Data = InputData; s_efbAccessRequested.Set(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) { s_efbAccessReadyEvent.Reset(); if (s_FifoShuttingDown.IsSet()) return 0; s_efbAccessRequested.Set(); s_efbAccessReadyEvent.Wait(); } else VideoFifo_CheckEFBAccess(); return s_AccessEFBResult; } return 0; }
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { CheckFifoRecording(); if (!fbWidth || !fbHeight) return; s_skipSwap = g_bSkipCurrentFrame; VideoFifo_CheckEFBAccess(); VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight); XFBWrited = true; if (g_ActiveConfig.bUseXFB) { FramebufferManagerBase::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc,Gamma); } else { // XXX: Without the VI, how would we know what kind of field this is? So // just use progressive. g_renderer->Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight,sourceRc,Gamma); Common::AtomicStoreRelease(s_swapRequested, false); } }
u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData) { if (s_BackendInitialized && g_ActiveConfig.bEFBAccessEnable) { s_accessEFBArgs.type = type; s_accessEFBArgs.x = x; s_accessEFBArgs.y = y; s_accessEFBArgs.Data = InputData; Common::AtomicStoreRelease(s_efbAccessRequested, true); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) { while (Common::AtomicLoadAcquire(s_efbAccessRequested) && !s_FifoShuttingDown) //Common::SleepCurrentThread(1); Common::YieldCPU(); } else VideoFifo_CheckEFBAccess(); return s_AccessEFBResult; } return 0; }
void VertexManager::vFlush() { if (LocalVBuffer == s_pCurBufferPointer) return; if (Flushed) return; Flushed=true; VideoFifo_CheckEFBAccess(); u32 usedtextures = 0; for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) if (bpmem.tevorders[i / 2].getEnable(i & 1)) usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); if (bpmem.genMode.numindstages > 0) for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i) if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); for (unsigned int i = 0; i < 8; i++) { if (usedtextures & (1 << i)) { g_renderer->SetSamplerState(i & 3, i >> 2); const FourTexUnits &tex = bpmem.tex[i >> 2]; const TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i, (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8), tex.texMode1[i&3].max_lod >> 4, tex.texImage1[i&3].image_type); if (tentry) { // 0s are probably for no manual wrapping needed. PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); } else ERROR_LOG(VIDEO, "error loading texture"); } }
void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidth, u32 fbHeight, float Gamma) { CheckFifoRecording(); if (!fbWidth || !fbHeight) return; VideoFifo_CheckEFBAccess(); VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight); XFBWrited = true; if (g_ActiveConfig.bUseXFB) { FramebufferManagerBase::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc,Gamma); } else { Swap(xfbAddr, fbWidth, fbWidth, fbHeight, sourceRc, Gamma); s_swapRequested.Clear(); } }
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { CheckFifoRecording(); if (!fbWidth || !fbHeight) return; s_skipSwap = g_bSkipCurrentFrame; VideoFifo_CheckEFBAccess(); VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight); XFBWrited = true; if (g_ActiveConfig.bUseXFB) { FramebufferManagerBase::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc,Gamma); } else { Swap(xfbAddr, fbWidth, fbHeight,sourceRc,Gamma); Common::AtomicStoreRelease(s_swapRequested, false); } }
void VertexManager::Flush() { if (IsFlushed) return; // loading a state will invalidate BP, so check for it g_video_backend->CheckInvalidState(); VideoFifo_CheckEFBAccess(); #if defined(_DEBUG) || defined(DEBUGFAST) PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGen.numTexGens, xfregs.numChan.numColorChans, xfregs.dualTexTrans.enabled, bpmem.ztex2.op, bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate, bpmem.zmode.updateenable); for (unsigned int i = 0; i < xfregs.numChan.numColorChans; ++i) { LitChannel* ch = &xfregs.color[i]; PRIM_LOG("colchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); ch = &xfregs.alpha[i]; PRIM_LOG("alpchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); } for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i) { TexMtxInfo tinfo = xfregs.texMtxInfo[i]; if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP) tinfo.hex &= 0x7ff; if (tinfo.texgentype != XF_TEXGEN_REGULAR) tinfo.projection = 0; PRIM_LOG("txgen%d: proj=%d, input=%d, gentype=%d, srcrow=%d, embsrc=%d, emblght=%d, postmtx=%d, postnorm=%d", i, tinfo.projection, tinfo.inputform, tinfo.texgentype, tinfo.sourcerow, tinfo.embosssourceshift, tinfo.embosslightshift, xfregs.postMtxInfo[i].index, xfregs.postMtxInfo[i].normalize); } PRIM_LOG("pixel: tev=%d, ind=%d, texgen=%d, dstalpha=%d, alphatest=0x%x", bpmem.genMode.numtevstages+1, bpmem.genMode.numindstages, bpmem.genMode.numtexgens, (u32)bpmem.dstalpha.enable, (bpmem.alpha_test.hex>>16)&0xff); #endif u32 usedtextures = 0; for (u32 i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) if (bpmem.tevorders[i / 2].getEnable(i & 1)) usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); if (bpmem.genMode.numindstages > 0) for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); for (unsigned int i = 0; i < 8; i++) { if (usedtextures & (1 << i)) { g_renderer->SetSamplerState(i & 3, i >> 2); const FourTexUnits &tex = bpmem.tex[i >> 2]; const TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i, (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, ((tex.texMode0[i&3].min_filter & 3) != 0), (tex.texMode1[i&3].max_lod + 0xf) / 0x10, (tex.texImage1[i&3].image_type != 0)); if (tentry) { // 0s are probably for no manual wrapping needed. PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); } else ERROR_LOG(VIDEO, "error loading texture"); } }
void VideoFifo_CheckAsyncRequest() { VideoFifo_CheckSwapRequest(); VideoFifo_CheckEFBAccess(); VideoFifo_CheckPerfQueryRequest(); }