mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-09 09:47:43 +00:00
Big fixes and big memory leak refactor (linux only for now)
This commit is contained in:
@@ -6,7 +6,7 @@ namespace urde
|
||||
CAABoxShader::CAABoxShader(bool zOnly)
|
||||
: m_zOnly(zOnly)
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(zeus::CVector3f), 34);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace urde
|
||||
|
||||
CCameraBlurFilter::CCameraBlurFilter()
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 4);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace urde
|
||||
|
||||
CColoredQuadFilter::CColoredQuadFilter(EFilterType type)
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
struct Vert
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ void CEnergyBarShader::draw(const zeus::CColor& color0, const std::vector<Vertex
|
||||
{
|
||||
m_maxVerts = totalVerts;
|
||||
m_tex = tex;
|
||||
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
|
||||
CGraphicsCommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), m_maxVerts);
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
|
||||
@@ -99,7 +99,7 @@ boo::ObjToken<boo::IShaderPipeline> CFluidPlaneShader::Cache::GetOrBuildShader(c
|
||||
if (CGraphics::g_BooFactory == nullptr)
|
||||
return nullptr;
|
||||
|
||||
CGraphics::CommitResources(
|
||||
CGraphicsCommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
switch (ctx.platform())
|
||||
@@ -148,7 +148,7 @@ void CFluidPlaneShader::Cache::Clear()
|
||||
|
||||
void CFluidPlaneShader::PrepareBinding(const boo::ObjToken<boo::IShaderPipeline>& pipeline, u32 maxVertCount, bool door)
|
||||
{
|
||||
CGraphics::CommitResources(
|
||||
CGraphicsCommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount);
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace urde
|
||||
|
||||
CFogVolumeFilter::CFogVolumeFilter()
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
struct Vert
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace urde
|
||||
void CFogVolumePlaneShader::CommitResources(size_t capacity)
|
||||
{
|
||||
m_vertCapacity = capacity;
|
||||
CGraphics::CommitResources([this, capacity](boo::IGraphicsDataFactory::Context& ctx)
|
||||
CGraphicsCommitResources([this, capacity](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(zeus::CVector4f), capacity);
|
||||
TShader<CFogVolumePlaneShader>::BuildShaderDataBinding(ctx, *this);
|
||||
|
||||
@@ -15,6 +15,8 @@ boo::ObjToken<boo::IShaderPipeline> CLineRendererShaders::m_texAdditiveZ;
|
||||
boo::ObjToken<boo::IShaderPipeline> CLineRendererShaders::m_noTexAlphaZ;
|
||||
boo::ObjToken<boo::IShaderPipeline> CLineRendererShaders::m_noTexAdditiveZ;
|
||||
|
||||
boo::ObjToken<boo::IShaderPipeline> CLineRendererShaders::m_noTexAlphaZGEqual;
|
||||
|
||||
boo::ObjToken<boo::IVertexFormat> CLineRendererShaders::m_texVtxFmt;
|
||||
boo::ObjToken<boo::IVertexFormat> CLineRendererShaders::m_noTexVtxFmt;
|
||||
|
||||
@@ -25,8 +27,8 @@ void CLineRendererShaders::Initialize()
|
||||
if (!CGraphics::g_BooFactory)
|
||||
return;
|
||||
|
||||
CGraphics::CommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
switch (ctx.platform())
|
||||
{
|
||||
@@ -67,6 +69,7 @@ void CLineRendererShaders::Shutdown()
|
||||
m_texAdditiveZ.reset();
|
||||
m_noTexAlphaZ.reset();
|
||||
m_noTexAdditiveZ.reset();
|
||||
m_noTexAlphaZGEqual.reset();
|
||||
m_texVtxFmt.reset();
|
||||
m_noTexVtxFmt.reset();
|
||||
}
|
||||
@@ -74,10 +77,15 @@ void CLineRendererShaders::Shutdown()
|
||||
void CLineRendererShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
|
||||
CLineRenderer& renderer,
|
||||
const boo::ObjToken<boo::ITexture>& texture,
|
||||
bool additive, bool zTest)
|
||||
bool additive, bool zTest, bool zGEqual)
|
||||
{
|
||||
boo::ObjToken<boo::IShaderPipeline> pipeline;
|
||||
if (zTest)
|
||||
|
||||
if (zGEqual)
|
||||
{
|
||||
pipeline = m_noTexAlphaZGEqual;
|
||||
}
|
||||
else if (zTest)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,8 @@ private:
|
||||
static boo::ObjToken<boo::IShaderPipeline> m_noTexAlphaZ;
|
||||
static boo::ObjToken<boo::IShaderPipeline> m_noTexAdditiveZ;
|
||||
|
||||
static boo::ObjToken<boo::IShaderPipeline> m_noTexAlphaZGEqual;
|
||||
|
||||
static boo::ObjToken<boo::IVertexFormat> m_texVtxFmt;
|
||||
static boo::ObjToken<boo::IVertexFormat> m_noTexVtxFmt;
|
||||
|
||||
@@ -58,7 +60,8 @@ public:
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CLineRenderer& renderer,
|
||||
const boo::ObjToken<boo::ITexture>& texture, bool additive, bool zTest);
|
||||
const boo::ObjToken<boo::ITexture>& texture, bool additive, bool zTest,
|
||||
bool zGEqual);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -177,6 +177,11 @@ CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo:
|
||||
boo::Primitive::TriStrips, boo::ZTest::LEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
m_noTexAlphaZGEqual = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::GEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
return new struct OGLLineDataBindingFactory;
|
||||
}
|
||||
|
||||
@@ -269,6 +274,11 @@ CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo:
|
||||
boo::Primitive::TriStrips, boo::ZTest::LEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
m_noTexAlphaZGEqual = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_noTexVtxFmt,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::GEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
return new struct VulkanLineDataBindingFactory;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -182,6 +182,12 @@ CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo:
|
||||
boo::Primitive::TriStrips, boo::ZTest::LEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
m_noTexAlphaZGEqual = ctx.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, nullptr, nullptr,
|
||||
nullptr, m_noTexVtxFmt,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::GEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
return new struct HLSLLineDataBindingFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,6 +190,11 @@ CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo:
|
||||
boo::Primitive::TriStrips, boo::ZTest::LEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
m_noTexAlphaZGEqual = ctx.newShaderPipeline(VS_METAL_NOTEX, FS_METAL_NOTEX, nullptr, nullptr, m_noTexVtxFmt,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::GEqual,
|
||||
false, true, false, boo::CullMode::None);
|
||||
|
||||
return new struct MetalLineDataBindingFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ CMapSurfaceShader::Initialize(boo::GLDataFactory::Context& ctx)
|
||||
const char* uniNames[] = {"MapSurfaceUniform"};
|
||||
s_Pipeline = ctx.newShaderPipeline(VS, FS, 0, nullptr, 1, uniNames,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::None, false, true,
|
||||
boo::Primitive::TriStrips, boo::ZTest::GEqual, false, true,
|
||||
false, boo::CullMode::Backface);
|
||||
return new CMapSurfaceShaderGLDataBindingFactory;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ CMapSurfaceShader::Initialize(boo::VulkanDataFactory::Context& ctx)
|
||||
s_VtxFmt = ctx.newVertexFormat(1, VtxVmt);
|
||||
s_Pipeline = ctx.newShaderPipeline(VS, FS, s_VtxFmt, boo::BlendFactor::SrcAlpha,
|
||||
boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips,
|
||||
boo::ZTest::None, false, true, false, boo::CullMode::Backface);
|
||||
boo::ZTest::GEqual, false, true, false, boo::CullMode::Backface);
|
||||
return new CMapSurfaceShaderVulkanDataBindingFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ enum EExtendedShader : uint8_t
|
||||
ForcedAlphaNoZWrite,
|
||||
ForcedAdditiveNoZWrite,
|
||||
ForcedAlphaNoCullNoZWrite,
|
||||
ForcedAdditiveNoCullNoZWrite
|
||||
ForcedAdditiveNoCullNoZWrite,
|
||||
DepthGEqualNoZWrite
|
||||
};
|
||||
|
||||
class CModelShaders
|
||||
|
||||
@@ -295,6 +295,12 @@ CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat)
|
||||
hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
|
||||
hecl::Backend::CullMode::None, true, false, true);
|
||||
|
||||
/* Depth GEqual no Z-write */
|
||||
ext.registerExtensionSlot({LightingGLSL, "LightingFunc"}, {MainPostGLSL, "MainPostFunc"},
|
||||
3, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::Original,
|
||||
hecl::Backend::BlendFactor::Original, hecl::Backend::ZTest::GEqual,
|
||||
hecl::Backend::CullMode::Backface, true, false, true);
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
|
||||
@@ -275,6 +275,12 @@ CModelShaders::GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat)
|
||||
hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
|
||||
hecl::Backend::CullMode::None, true, false, true);
|
||||
|
||||
/* Depth GEqual no Z-write */
|
||||
ext.registerExtensionSlot({LightingHLSL, "LightingFunc"}, {MainPostHLSL, "MainPostFunc"},
|
||||
0, nullptr, 0, nullptr, hecl::Backend::BlendFactor::Original,
|
||||
hecl::Backend::BlendFactor::Original, hecl::Backend::ZTest::GEqual,
|
||||
hecl::Backend::CullMode::Backface, true, false, true);
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,6 +285,12 @@ CModelShaders::GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat
|
||||
hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
|
||||
hecl::Backend::CullMode::None, true, false, true);
|
||||
|
||||
/* Depth GEqual no Z-write */
|
||||
ext.registerExtensionSlot({LightingMetal, "LightingFunc"}, {MainPostMetal, "MainPostFunc"},
|
||||
1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::Original,
|
||||
hecl::Backend::BlendFactor::Original, hecl::Backend::ZTest::GEqual,
|
||||
hecl::Backend::CullMode::Backface, true, false, true);
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ void CPhazonSuitFilter::drawBlurPasses(float radius, const CTexture* indTex)
|
||||
if (!m_dataBind || indTex != m_indTex)
|
||||
{
|
||||
m_indTex = indTex;
|
||||
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
|
||||
CGraphicsCommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_uniBufBlurX = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1);
|
||||
m_uniBufBlurY = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1);
|
||||
|
||||
@@ -12,7 +12,7 @@ void CRadarPaintShader::draw(const std::vector<Instance>& instances, const CText
|
||||
{
|
||||
m_maxInsts = instances.size();
|
||||
m_tex = tex;
|
||||
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
|
||||
CGraphicsCommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Instance), m_maxInsts);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CMatrix4f), 1);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace urde
|
||||
CRandomStaticFilter::CRandomStaticFilter(EFilterType type, bool cookieCutter)
|
||||
: m_cookieCutter(cookieCutter)
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
struct Vert
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace urde
|
||||
CScanLinesFilter::CScanLinesFilter(EFilterType type, bool even)
|
||||
: m_even(even)
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
|
||||
m_dataBind = TMultiBlendShader<CScanLinesFilter>::BuildShaderDataBinding(ctx, type, *this);
|
||||
|
||||
@@ -33,7 +33,7 @@ void CSpaceWarpFilter::GenerateWarpRampTex(boo::IGraphicsDataFactory::Context& c
|
||||
|
||||
CSpaceWarpFilter::CSpaceWarpFilter()
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
GenerateWarpRampTex(ctx);
|
||||
struct Vert
|
||||
|
||||
@@ -15,7 +15,7 @@ CTexturedQuadFilter::CTexturedQuadFilter(EFilterType type, const boo::ObjToken<b
|
||||
{
|
||||
m_flipRect = CGraphics::g_BooFactory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan;
|
||||
tex->setClampMode(boo::TextureClampMode::ClampToEdge);
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 16);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
|
||||
@@ -157,7 +157,7 @@ URDE_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilter)
|
||||
CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, const boo::ObjToken<boo::ITexture>& tex)
|
||||
: CTexturedQuadFilter(tex)
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 4);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace urde
|
||||
|
||||
CThermalColdFilter::CThermalColdFilter()
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_shiftTex = ctx.newDynamicTexture(8, 4, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace urde
|
||||
|
||||
CThermalHotFilter::CThermalHotFilter()
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
struct Vert
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace urde
|
||||
CWorldShadowShader::CWorldShadowShader(u32 w, u32 h)
|
||||
: m_w(w), m_h(h)
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 16, 4);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace urde
|
||||
CXRayBlurFilter::CXRayBlurFilter(TLockedToken<CTexture>& tex)
|
||||
: m_paletteTex(tex), m_booTex(tex->GetPaletteTexture())
|
||||
{
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources([&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
struct Vert
|
||||
{
|
||||
|
||||
@@ -29,8 +29,8 @@ public:
|
||||
if (!CGraphics::g_BooFactory)
|
||||
return;
|
||||
|
||||
CGraphics::CommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
switch (ctx.platform())
|
||||
{
|
||||
|
||||
@@ -28,8 +28,8 @@ public:
|
||||
if (!CGraphics::g_BooFactory)
|
||||
return;
|
||||
|
||||
CGraphics::CommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
CGraphicsCommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
switch (ctx.platform())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user