diff options
| author | robojumper <robojumper@gmail.com> | 2024-04-27 09:55:06 +0200 |
|---|---|---|
| committer | robojumper <robojumper@gmail.com> | 2024-04-27 16:32:40 +0200 |
| commit | b35d67e5550230075d7b8aa6d121d460a4c6409e (patch) | |
| tree | 5626f68ea9ad36a2f8c9fce2d9327478cc6d2abb /src/egg/core/eggAsyncDisplay.cpp | |
| parent | 1ee2fdd8845d7ec2502b33ef2f45b4ab17e9d88e (diff) | |
eggAsyncDisplay almost
Diffstat (limited to 'src/egg/core/eggAsyncDisplay.cpp')
| -rw-r--r-- | src/egg/core/eggAsyncDisplay.cpp | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/egg/core/eggAsyncDisplay.cpp b/src/egg/core/eggAsyncDisplay.cpp new file mode 100644 index 00000000..8aaf943c --- /dev/null +++ b/src/egg/core/eggAsyncDisplay.cpp @@ -0,0 +1,226 @@ +#include <egg/core/eggAsyncDisplay.h> +#include <egg/math/eggMatrix.h> +#include <egg/core/eggXfbManager.h> +#include <rvl/GX/GXTexture.h> +#include <rvl/GX/GXHardware.h> + +// This file still has incorrect sdata2 + +static EGG::AsyncDisplay *lbl_80576790[2]; + +namespace EGG { + +AsyncDisplay::AsyncDisplay(u8 maxRetrace): Display(maxRetrace) { + this->field_0x98 = 0.0; + this->field_0x9C = 0.0; + this->field_0xA4 = 0; + this->field_0xA8 = 0; + this->field_0xAC = 0; + this->field_0xB8 = 0; + lbl_80576790[0] = this; + OSInitThreadQueue(&this->mThreadQueue); + OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuf, 4); +} + +f32 AsyncDisplay::calcS() { + f32 tmp = this->field_0x9C + this->field_0xA0; + this->field_0x9C = tmp; + if (!(tmp > 1.0f)) { + return tmp; + } + + if (this->mScreenStateFlag.onBit(4)) { + this->field_0x9C = tmp - 1.0f; + this->mScreenStateFlag.resetBit(4); + } else { + this->field_0x9C = tmp - this->field_0xA0; + this->mScreenStateFlag.setBit(4); + } + return tmp; +} + +inline void AsyncDisplay::waitForMsg(bool b) { + // This is really ugly but I couldn't find a different way + // to make the compiler use the registers + XfbManager *xfb; + while (!((xfb = BaseSystem::mConfigData->getXfbMgr(), 1 < xfb->mNumXfbs - this->field_0xAC) && (BaseSystem::mConfigData->getXfbMgr()->mToCopyXfb != nullptr || b))) { + + OSReceiveMessage(&this->mMesgQueue, this->mMesgBuf, 1); + + while (OSReceiveMessage(&this->mMesgQueue, this->mMesgBuf, 0)) {} + } +} + +void AsyncDisplay::beginFrame() { + BaseSystem::mConfigData->getXfbMgr(); + GXDrawDone(); + + if (this->mFlag.onBit(1)) { + OSSleepThread(&this->mThreadQueue); + } + bool b = false; + if (BaseSystem::mConfigData->getXfbMgr()->mNumXfbs == 1) { + s32 tick = OSGetTick(); + s32 lastTick = this->mLastTick; + if (tick - lastTick > Display::sTickPeriod) { + VIWaitForRetrace(); + } + } else { + b = false; + if (this->field_0x98 == 1 && this->mScreenStateFlag.onBit(6)) { + b = true; + } + + this->waitForMsg(b); + } + + if (b) { + this->clearEFB(); + this->mScreenStateFlag.resetBit(6); + GXDrawDone(); + } else { + this->copyEFBtoXFB(); + } + + if (this->field_0x98 == 1) { + this->calcS(); + } + this->field_0xAC++; + this->mFrameCount++; + this->calcFrequency(); +} + +void AsyncDisplay::endFrame() { + if (this->mScreenStateFlag.onBit(4)) { + this->mScreenStateFlag.setBit(5); + } +} + +void AsyncDisplay::endRender() { + if (this->mScreenStateFlag.onBit(5)) { + this->mScreenStateFlag.setBit(6); + this->mScreenStateFlag.resetBit(5); + } +} + +void AsyncDisplay::preVRetrace() { + s32 tick = OSGetTick(); + this->mLastTick = tick; + if (this->field_0x98 == 0) { + u32 a8 = ++this->field_0xA8; + if (a8 - this->field_0xA4 >= this->mMaxRetraces) { + this->field_0xA4 = a8; + this->mScreenStateFlag.setBit(3); + OSSendMessage(&this->mMesgQueue, this->mMesgBuf, 0); + if (this->field_0xAC > 0) { + this->field_0xAC--; + } + } + OSWakeupThread(&this->mThreadQueue); + } + + if (this->mScreenStateFlag.onBit(3)) { + s32 count = VIGetRetraceCount(); + if (count - this->mRetraceCount >= this->mMaxRetraces) { + if (this->mScreenStateFlag.onBit(0)) { + Video *video = BaseSystem::mConfigData->getVideo(); + VISetBlack(video->mFlag.offBit(0)); + if (video->mFlag.offBit(0)) { + video->mFlag.setBit(0); + } else { + video->mFlag.resetBit(0); + } + this->mScreenStateFlag.resetBit(0); + } + XfbManager *xfb = BaseSystem::mConfigData->getXfbMgr(); + xfb->setNextFrameBuffer(); + s32 newCount = VIGetRetraceCount(); + this->mRetraceCount = newCount; + this->mScreenStateFlag.resetBit(3); + } + } +} + +void AsyncDisplay::clearEFB() { + Video *video = BaseSystem::mConfigData->getVideo(); + GXRenderModeObj const *renderMode = video->pRenderMode; + this->clearEFB(renderMode->fbWidth, renderMode->efbHeight, 0, 0, renderMode->fbWidth, renderMode->efbHeight, this->mClearColor); +} + +u32 AsyncDisplay::getTickPerFrame() { + if (this->field_0x98 == 1) { + return Video::getTickPerVRetrace(0); + } else { + return Video::getTickPerVRetrace(); + } +} + +// TODO move +extern "C" { + extern GXTexObj lbl_80673B20, lbl_8056EB20; + extern Matrix34f lbl_80674C00; +} + +void AsyncDisplay::clearEFB(u16 fbWidth, u16 fbHeight, u16 x, u16 y, u16 width, u16 height, nw4r::ut::Color color) { + + GXInitTexObj(&lbl_80673B20, &lbl_8056EB20, 4, 4, GX_TF_Z24X8, GX_REPEAT, GX_REPEAT, 0); + GXInitTexObjLOD(&lbl_80673B20, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1); + Mtx44 mat; + C_MTXOrtho(mat, 0.0, (float)fbHeight, 0.0, (float)fbWidth, 0.0, 1.0f); + GXSetProjection(mat, GX_ORTHOGRAPHIC); + GXSetViewport(0.0, 0.0, (float)fbWidth, (float)fbHeight, 0.0, 1.0f); + GXSetScissor(0, 0, fbWidth, fbHeight); + lbl_80674C00.loadPosMtx(0); + GXSetCurrentMtx(0); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBX8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB565, 0); + GXSetNumChans(0); + GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanCtrl(GX_COLOR1A1, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetNumTexGens(1); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c, false, 0x7d); + GXLoadTexObj(&lbl_80673B20, GX_TEXMAP0); + GXSetNumTevStages(1); + GXSetTevColor(GX_TEVREG0, color); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + GXSetZTexture(2, GX_TF_Z24X8, 0); + GXSetZCompLoc(false); + GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_NOOP); + GXSetAlphaUpdate(true); + GXSetDstAlpha(true, color.a); + GXSetZMode(true, GX_ALWAYS, true); + GXSetCullMode(GX_CULL_BACK); + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + // The regs are wrong here + WGPIPE.us = x; + WGPIPE.us = y; + WGPIPE.c = 0; + WGPIPE.c = 0; + WGPIPE.us = x + width; + WGPIPE.us = y; + WGPIPE.c = 1; + WGPIPE.c = 0; + WGPIPE.us = x + width; + WGPIPE.us = y + height; + WGPIPE.c = 1; + WGPIPE.c = 1; + WGPIPE.us = width; + WGPIPE.us = y + height; + WGPIPE.c = 0; + WGPIPE.c = 1; + + GXSetZTexture(0, GX_TF_Z24X8, 0); + GXSetZCompLoc(true); + GXSetDstAlpha(false, color.a); +} + +} // namespace EGG |
