port: GrpImageInstance/GrpExpandedImageInstance verbatim; fix SCREEN blend factor

Both units are the 40250 bodies; only the PDT-stream draw becomes
UIRenderAddImage (with the rendering mode). SCREEN/COLOR_DODGE were packed as
0x28 (INVDESTALPHA+ONE); 40250 uses INVDESTCOLOR+ONE (0x2A). OnIsType calls the
base OnIsType instead of 40250's recursing IsType. port.grp_resource covers the
quads, UVs, colour and blend mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-30 14:21:13 +09:00
co-authored by Claude Opus 5.5
parent 010e99f070
commit 65777331f7
8 changed files with 819 additions and 231 deletions
+54 -1
View File
@@ -2,6 +2,7 @@
// and its low-texture-memory mip bias, memory textures), CGraphicImage, CGraphicVertexBuffer/IndexBuffer.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpImage.h"
#include "EterLib/GrpExpandedImageInstance.h"
#include "EterLib/GrpImageTexture.h"
#include "EterLib/GrpIndexBuffer.h"
#include "EterLib/GrpVertexBuffer.h"
@@ -52,7 +53,14 @@ std::vector<BYTE> MakeDDS(DWORD width, DWORD height, DWORD mips)
struct ImageAccess : CGraphicImage
{
ImageAccess(const char* name) : CGraphicImage(name) {}
bool Load(int size, const void* data) { return OnLoad(size, data); }
// CResource::Load with the pack bytes: OnLoad, then the state that stops a reference from loading again.
bool Load(int size, const void* data)
{
if (!OnLoad(size, data))
return false;
me_state = STATE_EXIST;
return true;
}
};
std::vector<BYTE> MakePNGHeader(DWORD width, DWORD height)
@@ -121,6 +129,51 @@ int main()
check(image.IsEmpty() && image.GetRectReference().right == 0, "CGraphicImage Clear");
}
// CGraphicImageInstance draws the image rect as one quad at its position (40250's -0.5 pixel-centre
// offset, undone by +0.5 in the command); CGraphicExpandedImageInstance adds scale, the rendering
// rect and its blend mode.
{
std::vector<BYTE> png = MakePNGHeader(40, 20);
ImageAccess* image = new ImageAccess("f.png");
check(image->Load(int(png.size()), png.data()), "instance image load");
image->AddReference(); // held by the test, so releasing the instances never self-destructs it
CGraphicImageInstance instance;
instance.SetImagePointer(image);
instance.SetPosition(10, 5);
instance.SetDiffuseColor(1, 0, 0, 0.5f);
UIRenderBeginFrame();
instance.Render();
const std::vector<UIRenderCommand>& commands = UIRenderCommands();
check(commands.size() == 1, "image instance emits one quad");
if (commands.size() == 1)
{
const UIRenderCommand& c = commands[0];
check(c.text == "f.png" && c.qx[0] == 10 && c.qy[0] == 5 && c.qx[3] == 50 && c.qy[3] == 25, "image instance quad");
check(c.su == 0 && c.eu == 1 && c.argb == 0x80FF0000u && c.blend == 0, "image instance uv/colour");
}
CGraphicExpandedImageInstance expanded;
expanded.SetImagePointer(image);
check(expanded.IsType(CGraphicExpandedImageInstance::Type()) && expanded.IsType(CGraphicImageInstance::Type()), "expanded IsType");
expanded.SetPosition(0, 0);
expanded.SetScale(2, 1);
expanded.SetRenderingRect(0, 0, -0.5f, 0);
expanded.SetRenderingMode(CGraphicExpandedImageInstance::RENDERING_MODE_MODULATE);
UIRenderBeginFrame();
expanded.Render();
check(commands.size() == 1, "expanded instance emits one quad");
if (commands.size() == 1)
{
const UIRenderCommand& c = commands[0];
// Width 40 x 2 plus the right edge pulled in by half the image (-20).
check(c.qx[1] == 60 && c.qy[2] == 20 && c.eu == 0.5f, "expanded quad and rendering rect");
check(c.blend == CGraphicExpandedImageInstance::RENDERING_MODE_MODULATE, "expanded blend mode");
}
instance.Destroy();
expanded.Destroy();
}
// A memory texture (font page): Lock hands out A4R4G4B4 words, Unlock republishes them as ARGB32.
{
CGraphicImageTexture texture;