summaryrefslogtreecommitdiff
path: root/src/egg/core/eggAsyncDisplay.cpp
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2024-04-27 09:55:06 +0200
committerrobojumper <robojumper@gmail.com>2024-04-27 16:32:40 +0200
commitb35d67e5550230075d7b8aa6d121d460a4c6409e (patch)
tree5626f68ea9ad36a2f8c9fce2d9327478cc6d2abb /src/egg/core/eggAsyncDisplay.cpp
parent1ee2fdd8845d7ec2502b33ef2f45b4ab17e9d88e (diff)
eggAsyncDisplay almost
Diffstat (limited to 'src/egg/core/eggAsyncDisplay.cpp')
-rw-r--r--src/egg/core/eggAsyncDisplay.cpp226
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