Initial CTextRenderBuffer rewrite

This commit is contained in:
Phillip Stephens 2022-05-13 23:47:29 -07:00
parent 22dfd3b3f7
commit 0ca2786302
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
14 changed files with 360 additions and 383 deletions

View File

@ -91,6 +91,7 @@ public:
CToken(IObj* obj);
CToken(std::unique_ptr<IObj>&& obj);
const SObjectTag* GetObjectTag() const;
const CObjectReference* GetObjectReference() const { return x0_objRef; }
~CToken();
};

View File

@ -19,8 +19,11 @@
namespace metaforce {
static logvisor::Module Log("CCubeRenderer");
/* TODO: This is to fix some areas exceeding the max drawable count, the proper number is 128 drawables per bucket */
// using BucketHolderType = rstl::reserved_vector<CDrawable*, 128>;
using BucketHolderType = rstl::reserved_vector<CDrawable*, 132>;
static rstl::reserved_vector<CDrawable, 512> sDataHolder;
static rstl::reserved_vector<rstl::reserved_vector<CDrawable*, 128>, 50> sBucketsHolder;
static rstl::reserved_vector<BucketHolderType, 50> sBucketsHolder;
static rstl::reserved_vector<CDrawablePlaneObject, 8> sPlaneObjectDataHolder;
static rstl::reserved_vector<u16, 8> sPlaneObjectBucketHolder;
@ -29,11 +32,11 @@ class Buckets {
static inline rstl::reserved_vector<u16, 50> sBucketIndex;
static inline rstl::reserved_vector<CDrawable, 512>* sData = nullptr;
static inline rstl::reserved_vector<rstl::reserved_vector<CDrawable*, 128>, 50>* sBuckets = nullptr;
static inline rstl::reserved_vector<BucketHolderType, 50>* sBuckets = nullptr;
static inline rstl::reserved_vector<CDrawablePlaneObject, 8>* sPlaneObjectData = nullptr;
static inline rstl::reserved_vector<u16, 8>* sPlaneObjectBucket = nullptr;
static constexpr std::array skWorstMinMaxDistance{99999.0f, -99999.0f};
static inline std::array sMinMaxDistance{0.0f, 0.0f};
static inline std::array sMinMaxDistance{99999.0f, -99999.0f};
public:
static void Clear();
@ -51,7 +54,7 @@ void Buckets::Clear() {
sBucketIndex.clear();
sPlaneObjectData->clear();
sPlaneObjectBucket->clear();
for (rstl::reserved_vector<CDrawable*, 128>& bucket : *sBuckets) {
for (BucketHolderType& bucket : *sBuckets) {
bucket.clear();
}
sMinMaxDistance = skWorstMinMaxDistance;
@ -60,12 +63,14 @@ void Buckets::Clear() {
void Buckets::Sort() {
float delta = std::max(1.f, sMinMaxDistance[1] - sMinMaxDistance[0]);
float pitch = 49.f / delta;
for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it)
if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity())
for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it) {
if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity()) {
sPlaneObjectBucket->push_back(s16(it - sPlaneObjectData->begin()));
}
}
u32 precision = 50;
if (sPlaneObjectBucket->size()) {
if (!sPlaneObjectBucket->empty()) {
std::sort(sPlaneObjectBucket->begin(), sPlaneObjectBucket->end(),
[](u16 a, u16 b) { return (*sPlaneObjectData)[a].GetDistance() < (*sPlaneObjectData)[b].GetDistance(); });
precision = 50 / u32(sPlaneObjectBucket->size() + 1);
@ -80,7 +85,7 @@ void Buckets::Sort() {
}
for (CDrawable& drawable : *sData) {
s32 slot;
s32 slot = -1;
float relDist = drawable.GetDistance() - sMinMaxDistance[0];
if (sPlaneObjectBucket->empty()) {
slot = zeus::clamp(1, s32(relDist * pitch), 49);
@ -88,7 +93,8 @@ void Buckets::Sort() {
slot = zeus::clamp(0, s32(relDist * pitch), s32(precision) - 2);
for (u16 idx : *sPlaneObjectBucket) {
CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx];
bool partial, full;
bool partial = false;
bool full = false;
if (planeObj.x3c_25_zOnly) {
partial = drawable.GetBounds().max.z() > planeObj.GetPlane().d();
full = drawable.GetBounds().min.z() > planeObj.GetPlane().d();
@ -98,22 +104,26 @@ void Buckets::Sort() {
full = planeObj.GetPlane().pointToPlaneDist(
drawable.GetBounds().furthestPointAlongVector(planeObj.GetPlane().normal())) > 0.f;
}
bool cont;
if (drawable.GetType() == EDrawableType::Particle)
bool cont = false;
if (drawable.GetType() == EDrawableType::Particle) {
cont = planeObj.x3c_24_invertTest ? !partial : full;
else
} else {
cont = planeObj.x3c_24_invertTest ? (!partial || !full) : (partial || full);
if (!cont)
}
if (!cont) {
break;
slot += precision;
}
slot += s32(precision);
}
}
if (slot == -1)
if (slot == -1) {
slot = 49;
rstl::reserved_vector<CDrawable*, 128>& bucket = (*sBuckets)[slot];
if (bucket.size() < bucket.capacity())
}
BucketHolderType& bucket = (*sBuckets)[slot];
if (bucket.size() < bucket.capacity()) {
bucket.push_back(&drawable);
}
// else
// Log.report(logvisor::Fatal, FMT_STRING("Full bucket!!!"));
}
@ -122,7 +132,7 @@ void Buckets::Sort() {
for (auto it = sBuckets->rbegin(); it != sBuckets->rend(); ++it) {
--bucketIdx;
sBucketIndex.push_back(bucketIdx);
rstl::reserved_vector<CDrawable*, 128>& bucket = *it;
BucketHolderType& bucket = *it;
if (bucket.size()) {
std::sort(bucket.begin(), bucket.end(), [](CDrawable* a, CDrawable* b) {
if (a->GetDistance() == b->GetDistance())
@ -134,7 +144,7 @@ void Buckets::Sort() {
for (auto it = sPlaneObjectBucket->rbegin(); it != sPlaneObjectBucket->rend(); ++it) {
CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[*it];
rstl::reserved_vector<CDrawable*, 128>& bucket = (*sBuckets)[planeObj.x24_targetBucket];
BucketHolderType& bucket = (*sBuckets)[planeObj.x24_targetBucket];
bucket.push_back(&planeObj);
}
}
@ -394,7 +404,8 @@ void CCubeRenderer::DrawUnsortedGeometry(s32 areaIdx, s32 mask, s32 targetMask)
void CCubeRenderer::DrawSortedGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
SCOPED_GRAPHICS_DEBUG_GROUP(
fmt::format(FMT_STRING("CCubeRenderer::DrawSortedGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
targetMask).c_str(),
targetMask)
.c_str(),
zeus::skBlue);
SetupRendererStates(true);
@ -427,7 +438,8 @@ void CCubeRenderer::DrawStaticGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
void CCubeRenderer::DrawAreaGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
SCOPED_GRAPHICS_DEBUG_GROUP(
fmt::format(FMT_STRING("CCubeRenderer::DrawAreaGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
targetMask).c_str(),
targetMask)
.c_str(),
zeus::skBlue);
x318_30_inAreaDraw = true;
@ -476,7 +488,7 @@ void CCubeRenderer::RenderBucketItems(const CAreaListItem* item) {
CCubeModel* lastModel = nullptr;
EDrawableType lastDrawableType = EDrawableType::Invalid;
for (u16 idx : Buckets::sBucketIndex) {
rstl::reserved_vector<CDrawable*, 128>& bucket = (*Buckets::sBuckets)[idx];
BucketHolderType& bucket = (*Buckets::sBuckets)[idx];
for (CDrawable* drawable : bucket) {
EDrawableType type = drawable->GetType();
switch (type) {

View File

@ -24,8 +24,6 @@ void CGraphicsPalette::Load() {
x4_frameLoaded = sCurrentFrameCount;
}
void CGraphicsPalette::Lock() { x1c_locked = true; }
void CGraphicsPalette::UnLock() {
// DCStoreRange(xc_lut, x8_numEntries << 1);
GXInitTlutObj(&x10_tlutObj, xc_entries.get(), static_cast<GXTlutFmt>(x0_fmt), x8_entryCount);

View File

@ -28,9 +28,9 @@ public:
explicit CGraphicsPalette(EPaletteFormat fmt, int count);
explicit CGraphicsPalette(CInputStream& in);
void Load();
void Lock();
void Lock() { x1c_locked = true; }
void UnLock();
void Load();
[[nodiscard]] u8* GetPaletteData() { return xc_entries.get(); }
[[nodiscard]] const u8* GetPaletteData() const { return xc_entries.get(); }

View File

@ -68,48 +68,44 @@ const CTextRenderBuffer* CGuiTextSupport::GetCurrentPageRenderBuffer() const {
float CGuiTextSupport::GetCurrentAnimationOverAge() const {
float ret = 0.f;
// TODO
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
// if (x50_typeEnable) {
// if (x40_primStartTimes.size()) {
// const auto& lastTime = x40_primStartTimes.back();
// ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first);
// } else {
// ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate);
// }
// }
// }
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
if (x50_typeEnable) {
if (!x40_primStartTimes.empty()) {
const auto& lastTime = x40_primStartTimes.back();
ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first);
} else {
ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate);
}
}
}
return ret;
}
float CGuiTextSupport::GetNumCharsTotal() const {
// TODO
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
// if (x50_typeEnable) {
// return buf->GetPrimitiveCount();
// }
// }
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
if (x50_typeEnable) {
return buf->GetPrimitiveCount();
}
}
return 0.f;
}
float CGuiTextSupport::GetNumCharsPrinted() const {
// TODO
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
// if (x50_typeEnable) {
// const float charsPrinted = x3c_curTime * x58_chRate;
// return std::min(charsPrinted, float(buf->GetPrimitiveCount()));
// }
// }
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
if (x50_typeEnable) {
const float charsPrinted = x3c_curTime * x58_chRate;
return std::min(charsPrinted, float(buf->GetPrimitiveCount()));
}
}
return 0.f;
}
float CGuiTextSupport::GetTotalAnimationTime() const {
// TODO
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
// if (x50_typeEnable) {
// return buf->GetPrimitiveCount() / x58_chRate;
// }
// }
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
if (x50_typeEnable) {
return buf->GetPrimitiveCount() / x58_chRate;
}
}
return 0.f;
}
@ -121,21 +117,20 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f
x58_chRate = std::max(chRate, 1.f);
if (enable) {
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
// TODO
// float chStartTime = 0.f;
// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
// for (const std::pair<float, int>& p : x40_primStartTimes) {
// if (p.second < i)
// continue;
// if (p.second != i)
// break;
// chStartTime = p.first;
// break;
// }
//
// buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
// chStartTime += 1.f / x58_chRate;
// }
float chStartTime = 0.f;
for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
for (const std::pair<float, int>& p : x40_primStartTimes) {
if (p.second < i)
continue;
if (p.second != i)
break;
chStartTime = p.first;
break;
}
//buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
chStartTime += 1.f / x58_chRate;
}
}
}
}
@ -143,21 +138,20 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f
void CGuiTextSupport::Update(float dt) {
if (x50_typeEnable) {
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
// TODO
// float chStartTime = 0.f;
// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
// for (const std::pair<float, int>& p : x40_primStartTimes) {
// if (p.second < i)
// continue;
// if (p.second != i)
// break;
// chStartTime = p.first;
// break;
// }
//
// buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
// chStartTime += 1.f / x58_chRate;
// }
float chStartTime = 0.f;
for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
for (const std::pair<float, int>& p : x40_primStartTimes) {
if (p.second < i)
continue;
if (p.second != i)
break;
chStartTime = p.first;
break;
}
//buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
chStartTime += 1.f / x58_chRate;
}
}
x3c_curTime += dt;
}
@ -190,9 +184,11 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer() {
}
bool CGuiTextSupport::CheckAndRebuildRenderBuffer() {
if (x308_multipageFlag || x60_renderBuf)
if (!x308_multipageFlag || x2ec_renderBufferPages.size())
if (x308_multipageFlag || x60_renderBuf) {
if (!x308_multipageFlag || x2ec_renderBufferPages.size()) {
return true;
}
}
CheckAndRebuildTextBuffer();
x2bc_assets = g_TextExecuteBuf->GetAssets();
@ -259,8 +255,7 @@ void CGuiTextSupport::SetFontColor(const zeus::CColor& col) {
void CGuiTextSupport::AddText(std::u16string_view str) {
if (x60_renderBuf) {
const float t = GetCurrentAnimationOverAge();
// TODO
// x40_primStartTimes.emplace_back(std::max(t, x3c_curTime), x60_renderBuf->GetPrimitiveCount());
x40_primStartTimes.emplace_back(std::max(t, x3c_curTime), x60_renderBuf->GetPrimitiveCount());
}
x0_string += str;
ClearRenderBuffer();

View File

@ -3,6 +3,7 @@
#include <algorithm>
#include "Runtime/CSimplePool.hpp"
#include "Runtime/Graphics/CGX.hpp"
#include "Runtime/Graphics/CTexture.hpp"
#include "Runtime/GuiSys/CDrawStringOptions.hpp"
#include "Runtime/GuiSys/CTextRenderBuffer.hpp"
@ -151,17 +152,15 @@ void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int&
if (!x0_initialized)
return;
if (renderBuf) {
/* CGraphicsPalette pal = CGraphicsPalette::CGraphcisPalette(2, 4); */
/* zeus::CColor color = zeus::CColor(0.f, 0.f, 0.f, 0.f) */
/* tmp = color.ToRGB5A3(); */
/* tmp2 = opts.x8_.ToRGB5A3(); */
/* tmp3 = opts.xc_.ToRGB5A3(); */
/* tmp4 = zeus::CColor(0.f, 0.f, 0.f, 0.f); */
/* tmp5 = tmp4.ToRGBA5A3(); */
/* pal.UnLock(); */
/* renderBuf->AddPaletteChange(pal); */
renderBuf->AddPaletteChange(opts.x4_colors[0], opts.x4_colors[1]);
if (renderBuf != nullptr) {
CGraphicsPalette pal(EPaletteFormat::RGB5A3, 4);
pal.Lock();
*reinterpret_cast<u16*>(pal.GetPaletteData() + 0) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3());
*reinterpret_cast<u16*>(pal.GetPaletteData() + 2) = SBIG(opts.x4_colors[0].toRGB5A3());
*reinterpret_cast<u16*>(pal.GetPaletteData() + 4) = SBIG(opts.x4_colors[1].toRGB5A3());
*reinterpret_cast<u16*>(pal.GetPaletteData() + 6) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3());
pal.UnLock();
renderBuf->AddPaletteChange(pal);
}
SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len);
@ -210,6 +209,28 @@ bool CRasterFont::IsFinishedLoading() const {
return true;
}
void CRasterFont::SetupRenderState() {
static const GX::VtxDescList skDescList[3] = {
{GX::VA_POS, GX::DIRECT},
{GX::VA_TEX0, GX::DIRECT},
{GX::VA_NULL, GX::NONE}
};
x80_texture->Load(GX::TEXMAP0, EClampMode::Clamp);
CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A);
CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0);
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_ZERO);
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_ZERO);
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0);
CGX::SetTevDirect(GX::TEVSTAGE0);
CGX::SetVtxDescv(skDescList);
CGX::SetNumChans(0);
CGX::SetNumTexGens(1);
CGX::SetNumTevStages(1);
CGX::SetNumIndStages(0);
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
}
std::unique_ptr<IObj> FRasterFontFactory([[maybe_unused]] const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& vparms, [[maybe_unused]] CObjectReference* selfRef) {
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();

View File

@ -151,6 +151,8 @@ public:
CTexture& GetTexture() { return *x80_texture; }
bool IsFinishedLoading() const;
void SetupRenderState();
};
std::unique_ptr<IObj> FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,

View File

@ -12,7 +12,7 @@
namespace metaforce {
CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const {
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df);
{
CFontRenderState rendState;
@ -35,7 +35,7 @@ CTextRenderBuffer CTextExecuteBuffer::BuildRenderBufferPage(InstList::const_iter
InstList::const_iterator pgStart,
InstList::const_iterator pgEnd,
CGuiWidget::EGuiModelDrawFlags df) const {
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df);
{
CFontRenderState rendState;
@ -71,7 +71,7 @@ std::list<CTextRenderBuffer> CTextExecuteBuffer::BuildRenderBufferPages(const ze
std::list<CTextRenderBuffer> ret;
for (auto it = x0_instList.begin(); it != x0_instList.end();) {
CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally, df);
CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally);//, df);
{
CFontRenderState rstate;

View File

@ -12,285 +12,29 @@
namespace metaforce {
//struct CTextRenderBuffer::BooFontCharacters {
// TLockedToken<CRasterFont> m_font;
// hecl::VertexBufferPool<CTextSupportShader::CharacterInstance>::Token m_instBuf;
// boo::ObjToken<boo::IShaderDataBinding> m_dataBinding;
// boo::ObjToken<boo::IShaderDataBinding> m_dataBinding2;
// std::vector<CTextSupportShader::CharacterInstance> m_charData;
// u32 m_charCount = 0;
// bool m_dirty = true;
//
// BooFontCharacters(const CToken& token) : m_font(token) {}
//};
//
//struct CTextRenderBuffer::BooImage {
// CFontImageDef m_imageDef;
// hecl::VertexBufferPool<CTextSupportShader::ImageInstance>::Token m_instBuf;
// std::vector<boo::ObjToken<boo::IShaderDataBinding>> m_dataBinding;
// std::vector<boo::ObjToken<boo::IShaderDataBinding>> m_dataBinding2;
// CTextSupportShader::ImageInstance m_imageData;
// bool m_dirty = true;
//
// BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset) : m_imageDef(imgDef) {
// m_imageData.SetMetrics(imgDef, offset);
// }
//};
//
//struct CTextRenderBuffer::BooPrimitiveMark {
// Command m_cmd;
// u32 m_bindIdx;
// u32 m_instIdx;
//
// void SetOpacity(CTextRenderBuffer& rb, float opacity) {
// switch (m_cmd) {
// case Command::CharacterRender: {
// BooFontCharacters& fc = rb.m_fontCharacters[m_bindIdx];
// CTextSupportShader::CharacterInstance& inst = fc.m_charData[m_instIdx];
// inst.m_mulColor.a() = opacity;
// fc.m_dirty = true;
// break;
// }
// case Command::ImageRender: {
// BooImage& img = rb.m_images[m_bindIdx];
// img.m_imageData.m_color.a() = opacity;
// img.m_dirty = true;
// break;
// }
// default:
// break;
// }
// }
//};
CTextRenderBuffer::CTextRenderBuffer(CTextRenderBuffer&&) noexcept = default;
CTextRenderBuffer::CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df) : x0_mode(mode)/*, m_drawFlags(df)*/ {}
CTextRenderBuffer::CTextRenderBuffer(EMode mode) : x0_mode(mode) {}
CTextRenderBuffer::~CTextRenderBuffer() = default;
CTextRenderBuffer& CTextRenderBuffer::operator=(CTextRenderBuffer&&) noexcept = default;
//void CTextRenderBuffer::CommitResources() {
// if (m_committed)
// return;
// m_committed = true;
//
// /* Ensure font textures are ready outside transaction */
// for (BooFontCharacters& chs : m_fontCharacters)
// chs.m_font->GetTexture();
//
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
// m_uniBuf = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory);
// auto uBufInfo = m_uniBuf.getBufferInfo();
// decltype(uBufInfo) uBufInfo2;
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
// m_uniBuf2 = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory);
// uBufInfo2 = m_uniBuf2.getBufferInfo();
// }
//
// for (BooFontCharacters& chs : m_fontCharacters) {
// chs.m_instBuf = CTextSupportShader::s_CharInsts.allocateBlock(CGraphics::g_BooFactory, chs.m_charCount);
// auto iBufInfo = chs.m_instBuf.getBufferInfo();
//
// boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {uBufInfo.first.get()};
// boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex};
// size_t unioffs[] = {size_t(uBufInfo.second)};
// size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)};
// boo::ObjToken<boo::ITexture> texs[] = {chs.m_font->GetTexture()};
// chs.m_dataBinding = ctx.newShaderDataBinding(CTextSupportShader::SelectTextPipeline(m_drawFlags), nullptr,
// iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs,
// unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second);
//
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
// uniforms[0] = uBufInfo2.first.get();
// unioffs[0] = size_t(uBufInfo2.second);
// chs.m_dataBinding2 = ctx.newShaderDataBinding(CTextSupportShader::GetTextAdditiveOverdrawPipeline(), nullptr,
// iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs,
// unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second);
// }
// }
//
// for (BooImage& img : m_images) {
// img.m_instBuf = CTextSupportShader::s_ImgInsts.allocateBlock(CGraphics::g_BooFactory, 1);
// auto iBufInfo = img.m_instBuf.getBufferInfo();
//
// boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {uBufInfo.first.get()};
// boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex};
// size_t unioffs[] = {size_t(uBufInfo.second)};
// size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)};
// img.m_dataBinding.reserve(img.m_imageDef.x4_texs.size());
// for (TToken<CTexture>& tex : img.m_imageDef.x4_texs) {
// boo::ObjToken<boo::ITexture> texs[] = {tex->GetBooTexture()};
// texs[0]->setClampMode(boo::TextureClampMode::ClampToEdge);
// img.m_dataBinding.push_back(ctx.newShaderDataBinding(
// CTextSupportShader::SelectImagePipeline(m_drawFlags), nullptr, iBufInfo.first.get(), nullptr, 1, uniforms,
// unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second));
// }
//
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
// uniforms[0] = uBufInfo2.first.get();
// unioffs[0] = size_t(uBufInfo2.second);
// img.m_dataBinding2.reserve(img.m_imageDef.x4_texs.size());
// for (TToken<CTexture>& tex : img.m_imageDef.x4_texs) {
// boo::ObjToken<boo::ITexture> texs[] = {tex->GetBooTexture()};
// img.m_dataBinding2.push_back(ctx.newShaderDataBinding(
// CTextSupportShader::GetImageAdditiveOverdrawPipeline(), nullptr, iBufInfo.first.get(), nullptr, 1,
// uniforms, unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second));
// }
// }
// }
// return true;
// } BooTrace);
//}
void CTextRenderBuffer::SetMode(EMode mode) {
x0_mode = mode;
}
//void CTextRenderBuffer::SetPrimitiveOpacity(int idx, float opacity) {
// m_primitiveMarks[idx].SetOpacity(*this, opacity);
//}
//
//u32 CTextRenderBuffer::GetPrimitiveCount() const { return m_primitiveMarks.size(); }
void CTextRenderBuffer::Render(const zeus::CColor& col, float time) {
// CommitResources();
// const zeus::CMatrix4f mv = CGraphics::g_GXModelView.toMatrix4f();
// const zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true);
// const zeus::CMatrix4f mat = proj * mv;
// m_uniBuf.access() = CTextSupportShader::Uniform{mat, col};
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
// zeus::CColor colPremul = col * col.a();
// colPremul.a() = col.a();
// m_uniBuf2.access() = CTextSupportShader::Uniform{mat, colPremul};
// }
// for (BooFontCharacters& chs : m_fontCharacters) {
// if (chs.m_charData.size()) {
// if (chs.m_dirty) {
// std::memmove(chs.m_instBuf.access(), chs.m_charData.data(),
// sizeof(CTextSupportShader::CharacterInstance) * chs.m_charData.size());
// chs.m_dirty = false;
// }
// CGraphics::SetShaderDataBinding(chs.m_dataBinding);
// CGraphics::DrawInstances(0, 4, chs.m_charData.size());
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
// CGraphics::SetShaderDataBinding(chs.m_dataBinding2);
// CGraphics::DrawInstances(0, 4, chs.m_charData.size());
// }
// }
// }
// for (BooImage& img : m_images) {
// if (img.m_dirty) {
// *img.m_instBuf.access() = img.m_imageData;
// img.m_dirty = false;
// }
// const int idx = int(img.m_imageDef.x0_fps * time) % img.m_dataBinding.size();
// CGraphics::SetShaderDataBinding(img.m_dataBinding[idx]);
// CGraphics::DrawInstances(0, 4, 1);
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
// CGraphics::SetShaderDataBinding(img.m_dataBinding2[idx]);
// CGraphics::DrawInstances(0, 4, 1);
// }
// }
}
void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) {
// if (x0_mode == EMode::AllocTally)
// m_primitiveMarks.push_back({Command::ImageRender, m_imagesCount++, 0});
// else
// m_images.emplace_back(image, offset);
}
void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color) {
// if (m_activeFontCh == UINT32_MAX)
// return;
// BooFontCharacters& chs = m_fontCharacters[m_activeFontCh];
// if (x0_mode == EMode::AllocTally)
// m_primitiveMarks.push_back({Command::CharacterRender, m_activeFontCh, chs.m_charCount++});
// else {
// const CGlyph* glyph = chs.m_font.GetObj()->GetGlyph(ch);
//
// CTextSupportShader::CharacterInstance& inst = chs.m_charData.emplace_back();
// inst.SetMetrics(*glyph, offset);
// inst.m_fontColor = m_main * color;
// inst.m_outlineColor = m_outline * color;
// inst.m_mulColor = zeus::skWhite;
// }
}
void CTextRenderBuffer::AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline) {
// m_main = main;
// m_outline = outline;
}
void CTextRenderBuffer::AddFontChange(const TToken<CRasterFont>& font) {
// for (size_t i = 0; i < m_fontCharacters.size(); ++i) {
// BooFontCharacters& chs = m_fontCharacters[i];
// if (*chs.m_font.GetObjectTag() == *font.GetObjectTag()) {
// m_activeFontCh = i;
// return;
// }
// }
//
// m_activeFontCh = m_fontCharacters.size();
// m_fontCharacters.emplace_back(font);
}
bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const {
std::pair<zeus::CVector2i, zeus::CVector2i> bounds = AccumulateTextBounds();
if (bounds.first.x > bounds.second.x)
return true;
if (0 < origin.y)
return false;
zeus::CVector2i size = bounds.second - bounds.first;
return size.y <= extent.y;
}
std::pair<zeus::CVector2i, zeus::CVector2i> CTextRenderBuffer::AccumulateTextBounds() const {
std::pair<zeus::CVector2i, zeus::CVector2i> ret =
std::make_pair(zeus::CVector2i{INT_MAX, INT_MAX}, zeus::CVector2i{INT_MIN, INT_MIN});
// for (const BooFontCharacters& chars : m_fontCharacters) {
// for (const CTextSupportShader::CharacterInstance& charInst : chars.m_charData) {
// ret.first.x = std::min(ret.first.x, int(charInst.m_pos[0].x()));
// ret.first.y = std::min(ret.first.y, int(charInst.m_pos[0].z()));
// ret.second.x = std::max(ret.second.x, int(charInst.m_pos[3].x()));
// ret.second.y = std::max(ret.second.y, int(charInst.m_pos[3].z()));
// }
// }
//
// for (const BooImage& imgs : m_images) {
// ret.first.x = std::min(ret.first.x, int(imgs.m_imageData.m_pos[0].x()));
// ret.first.y = std::min(ret.first.y, int(imgs.m_imageData.m_pos[0].z()));
// ret.second.x = std::max(ret.second.x, int(imgs.m_imageData.m_pos[3].x()));
// ret.second.y = std::max(ret.second.y, int(imgs.m_imageData.m_pos[3].z()));
// }
return ret;
}
void CTextRenderBuffer::SetPrimitive(const Primitive& prim, s32 idx) {
CMemoryStreamOut out(reinterpret_cast<u8*>(x34_bytecode.data() + x24_primOffsets[idx]),
x44_blobSize - x24_primOffsets[idx]);
if (prim.x4_command == Command::ImageRender) {
out.WriteUint8(1);
out.WriteUint8(static_cast<u8>(Command::ImageRender));
out.Put(prim.x8_xPos);
out.Put(prim.xa_zPos);
out.Put(prim.xe_imageIndex);
// out.Put(prim.x0_color1.toRGBA());
out.Put(prim.x0_color1.toRGBA());
} else if (prim.x4_command == Command::CharacterRender) {
out.WriteUint8(0);
out.WriteUint8(static_cast<u8>(Command::CharacterRender));
out.Put(prim.x8_xPos);
out.Put(prim.xa_zPos);
out.Put(u16(prim.xc_glyph));
// out.Put(prim.x0_color1.toRGBA());
out.Put(prim.x0_color1.toRGBA());
}
}
@ -303,7 +47,7 @@ CTextRenderBuffer::Primitive CTextRenderBuffer::GetPrimitive(s32 idx) const {
u16 zPos = in.ReadShort();
u8 imageIndex = in.ReadChar();
CTextColor color(in.ReadUint32());
return {color, Command::ImageRender, xPos, zPos, u'\0', imageIndex };
return {color, Command::ImageRender, xPos, zPos, u'\0', imageIndex};
}
if (cmd == Command::CharacterRender) {
@ -315,7 +59,205 @@ CTextRenderBuffer::Primitive CTextRenderBuffer::GetPrimitive(s32 idx) const {
return {color, Command::CharacterRender, xPos, zPos, glyph, 0};
}
return {CTextColor(zeus::Comp32(0)), Command::Invalid, 0, 0, u'\0', 0 };
return {CTextColor(zeus::Comp32(0)), Command::Invalid, 0, 0, u'\0', 0};
}
u8* CTextRenderBuffer::GetOutStream() {
VerifyBuffer();
return reinterpret_cast<u8*>(x34_bytecode.data()) + x48_curBytecodeOffset;
}
void CTextRenderBuffer::VerifyBuffer() {
if (x34_bytecode.empty()) {
x34_bytecode.resize(x44_blobSize);
}
}
void CTextRenderBuffer::SetMode(EMode mode) { x0_mode = mode; }
int CTextRenderBuffer::GetMatchingPaletteIndex(const CGraphicsPalette& palette) {
for (int i = 0; i < x50_palettes.size(); ++i) {
if (memcmp(x50_palettes[i]->GetPaletteData(), palette.GetPaletteData(), 8) == 0) {
return i;
}
}
return -1;
}
CGraphicsPalette* CTextRenderBuffer::GetNextAvailablePalette() {
if (x254_nextPalette < 64) {
x50_palettes.push_back(std::make_unique<CGraphicsPalette>(EPaletteFormat::RGB5A3, 4));
} else {
x254_nextPalette = 0;
}
++x254_nextPalette;
return x50_palettes[x254_nextPalette - 1].get();
}
u32 CTextRenderBuffer::GetCurLen() {
VerifyBuffer();
return x44_blobSize - x48_curBytecodeOffset;
}
void CTextRenderBuffer::Render(const zeus::CColor& col, float time) {
// TODO
}
void CTextRenderBuffer::AddPaletteChange(const CGraphicsPalette& palette) {
if (x0_mode == EMode::BufferFill) {
{
u8* buf = GetOutStream();
CMemoryStreamOut out(buf, GetCurLen());
s32 paletteIndex = GetMatchingPaletteIndex(palette);
if (paletteIndex == -1) {
GetNextAvailablePalette();
paletteIndex = x254_nextPalette - 1;
CGraphicsPalette* destPalette = x50_palettes[x254_nextPalette - 1].get();
destPalette->Lock();
memcpy(destPalette->GetPaletteData(), palette.GetPaletteData(), 8);
destPalette->UnLock();
}
out.WriteUint8(static_cast<u8>(Command::PaletteChange));
out.WriteUint8(paletteIndex);
x48_curBytecodeOffset += out.GetNumWrites();
}
} else {
x44_blobSize += 2;
}
}
void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) {
if (x0_mode == EMode::BufferFill) {
CMemoryStreamOut out(GetOutStream(), GetCurLen());
x24_primOffsets.reserve(x24_primOffsets.size() + 1);
u32 primCap = x24_primOffsets.capacity();
if (x24_primOffsets.capacity() <= x24_primOffsets.size()) {
x24_primOffsets.reserve(primCap != 0 ? primCap * 2 : 4);
}
x24_primOffsets.push_back(x48_curBytecodeOffset);
x14_images.reserve(x14_images.size() + 1);
u32 imgIdx = x14_images.size();
x14_images.push_back(image);
out.WriteUint8(static_cast<u8>(Command::ImageRender));
out.WriteShort(offset.x);
out.WriteShort(offset.y);
out.WriteUint8(imgIdx);
out.WriteLong(zeus::skWhite.toRGBA());
x48_curBytecodeOffset += out.GetNumWrites();
} else {
x44_blobSize += 10;
}
}
void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color) {
if (x0_mode == EMode::BufferFill) {
CMemoryStreamOut out(GetOutStream(), GetCurLen());
x24_primOffsets.reserve(x24_primOffsets.size() + 1);
u32 primCap = x24_primOffsets.capacity();
if (x24_primOffsets.capacity() <= x24_primOffsets.size()) {
x24_primOffsets.reserve(primCap != 0 ? primCap * 2 : 4);
}
x24_primOffsets.push_back(x48_curBytecodeOffset);
out.WriteUint8(u32(Command::CharacterRender));
out.WriteShort(offset.x);
out.WriteShort(offset.y);
out.WriteShort(ch);
out.WriteUint32(color.toRGBA());
x48_curBytecodeOffset += out.GetNumWrites();
} else {
x44_blobSize += 11;
}
}
void CTextRenderBuffer::AddFontChange(const TToken<CRasterFont>& font) {
if (x0_mode == EMode::BufferFill) {
CMemoryStreamOut out(GetOutStream(), GetCurLen());
u32 fontCount = x4_fonts.size();
bool found = false;
u8 fontIndex = 0;
if (fontCount > 0) {
for (const auto& tok : x4_fonts) {
if (tok.GetObjectReference() == font.GetObjectReference()) {
out.WriteUint8(static_cast<u8>(Command::FontChange));
out.WriteUint8(fontIndex);
found = true;
break;
}
++fontIndex;
}
}
if (!found) {
x4_fonts.reserve(x4_fonts.size() + 1);
u32 fontIdx = x4_fonts.size();
x4_fonts.push_back(font);
out.WriteUint8(static_cast<u8>(Command::FontChange));
out.WriteUint8(fontIdx);
}
x48_curBytecodeOffset += out.GetNumWrites();
} else {
x44_blobSize += 2;
}
}
bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) {
std::pair<zeus::CVector2i, zeus::CVector2i> bounds = AccumulateTextBounds();
if (bounds.first.x > bounds.second.x) {
return true;
}
if (0 < origin.y) {
return false;
}
zeus::CVector2i size = bounds.second - bounds.first;
return size.y <= extent.y;
}
std::pair<zeus::CVector2i, zeus::CVector2i> CTextRenderBuffer::AccumulateTextBounds() {
zeus::CVector2i min{INT_MAX, INT_MAX};
zeus::CVector2i max{INT_MIN, INT_MIN};
CMemoryInStream in(x34_bytecode.data(), x44_blobSize);
while (in.GetReadPosition() < x48_curBytecodeOffset) {
auto cmd = static_cast<Command>(in.ReadChar());
if (cmd == Command::FontChange) {
x4c_activeFont = in.ReadChar();
} else if (cmd == Command::CharacterRender) {
u16 offX = in.ReadShort();
u16 offY = in.ReadShort();
char16_t chr = in.ReadShort();
in.ReadLong();
if (x4c_activeFont != -1) {
auto font = x4_fonts[x4c_activeFont];
if (font) {
const auto* glyph = font->GetGlyph(chr);
if (glyph != nullptr) {
max.x = std::max(max.x, offX + glyph->GetCellWidth());
max.y = std::max(max.y, offY + glyph->GetCellHeight());
min.x = std::min<int>(min.x, offX);
min.y = std::min<int>(min.y, offY);
}
}
}
} else if (cmd == Command::ImageRender) {
u16 offX = in.ReadShort();
u16 offY = in.ReadShort();
u8 imageIdx = in.ReadChar();
in.ReadLong();
const auto& image = x14_images[imageIdx];
max.x = std::max(max.x, offX + static_cast<int>(static_cast<float>(image.x4_texs.front()->GetWidth()) *
image.x14_cropFactor.x()));
max.y = std::max(max.y, offY + static_cast<int>(static_cast<float>(image.x4_texs.front()->GetHeight()) *
image.x14_cropFactor.y()));
min.x = std::min<int>(min.x, offX);
min.y = std::min<int>(min.y, offY);
} else if (cmd == Command::PaletteChange) {
in.ReadChar();
}
}
return {min, max};
}
} // namespace metaforce

View File

@ -27,7 +27,8 @@ class CTextRenderBuffer {
friend class CTextSupportShader;
public:
enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid };
enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid = -1 };
#if 1
struct Primitive {
CTextColor x0_color1;
Command x4_command;
@ -36,6 +37,7 @@ public:
char16_t xc_glyph;
u8 xe_imageIndex;
};
#endif
enum class EMode { AllocTally, BufferFill };
private:
@ -46,34 +48,37 @@ private:
std::vector<char> x34_bytecode;
u32 x44_blobSize = 0;
u32 x48_curBytecodeOffset = 0;
u8 x4c_activeFont;
u32 x50_paletteCount = 0;
std::array<std::unique_ptr<CGraphicsPalette>, 64> x54_palettes;
u32 x254_nextPalette = 0;
s8 x4c_activeFont = -1;
s8 x4d_ = -1;
s8 x4e_ = -1;
s8 x4f_curPalette = -1;
rstl::reserved_vector<std::unique_ptr<CGraphicsPalette>, 64> x50_palettes;
s32 x254_nextPalette = 0;
public:
CTextRenderBuffer(CTextRenderBuffer&& other) noexcept;
CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df);
CTextRenderBuffer(EMode mode);
~CTextRenderBuffer();
CTextRenderBuffer& operator=(CTextRenderBuffer&& other) noexcept;
void SetPrimitive(const Primitive&, int);
[[nodiscard]] Primitive GetPrimitive(int) const;
void GetOutStream();
[[nodiscard]] u32 GetPrimitiveCount() const { return x24_primOffsets.size(); }
[[nodiscard]] u8* GetOutStream();
[[nodiscard]] u32 GetCurLen();
void VerifyBuffer();
int GetMatchingPaletteIndex(const CGraphicsPalette& palette);
CGraphicsPalette* GetNextAvailablePalette();
[[nodiscard]] CGraphicsPalette* GetNextAvailablePalette();
void AddPaletteChange(const CGraphicsPalette& palette);
void SetMode(EMode mode);
void Render(const zeus::CColor& col, float time);
void Render(const CTextColor& col, float time);
void AddImage(const zeus::CVector2i& offset, const CFontImageDef& image);
void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color);
void AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline);
void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color);
void AddFontChange(const TToken<CRasterFont>& font);
bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const;
std::pair<zeus::CVector2i, zeus::CVector2i> AccumulateTextBounds() const;
[[nodiscard]] bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent);
[[nodiscard]] std::pair<zeus::CVector2i, zeus::CVector2i> AccumulateTextBounds();
};
} // namespace metaforce

View File

@ -5,8 +5,8 @@ namespace metaforce {
class CMemoryInStream final : public CInputStream {
public:
enum class EOwnerShip {
NotOwned,
Owned,
NotOwned,
};
CMemoryInStream(const void* ptr, u32 len) : CInputStream(ptr, len, false) {}

View File

@ -5,8 +5,8 @@ namespace metaforce {
class CMemoryStreamOut final : public COutputStream {
public:
enum class EOwnerShip {
NotOwned,
Owned,
NotOwned,
};
private:

View File

@ -24,6 +24,7 @@ public:
COutputStream(s32 unk);
virtual ~COutputStream();
u32 GetNumWrites() const { return x10_numWrites; }
void WriteBits(u32 val, u32 bitCount);
void WriteChar(u8 c);
void WriteShort(u16 s);

2
extern/zeus vendored

@ -1 +1 @@
Subproject commit 8e4dfb022a97aee2c245d8a2ec9b92ce3d865fbd
Subproject commit 8410394d4bd90f8783b68ab064b13d838e29d6a1