From 648468531f79e8fd949d8ae130aafd6dc04c306e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 11 Mar 2023 15:57:46 -0600 Subject: [PATCH] feat(gx): handle texture uploads in d3d backend --- src/gx/d3d/CGxDeviceD3d.cpp | 112 +++++++++++++++++++++++++++++++++++- src/gx/d3d/CGxDeviceD3d.hpp | 1 + 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/src/gx/d3d/CGxDeviceD3d.cpp b/src/gx/d3d/CGxDeviceD3d.cpp index 900dbac..e1d5e03 100644 --- a/src/gx/d3d/CGxDeviceD3d.cpp +++ b/src/gx/d3d/CGxDeviceD3d.cpp @@ -1,4 +1,5 @@ #include "gx/d3d/CGxDeviceD3d.hpp" +#include "gx/Blit.hpp" #include "gx/CGxBatch.hpp" #include "gx/texture/CGxTex.hpp" #include @@ -10,6 +11,15 @@ D3DCMPFUNC CGxDeviceD3d::s_cmpFunc[] = { D3DCMP_LESS, }; +D3DCUBEMAP_FACES CGxDeviceD3d::s_faceTypes[] = { + D3DCUBEMAP_FACE_POSITIVE_X, + D3DCUBEMAP_FACE_NEGATIVE_X, + D3DCUBEMAP_FACE_POSITIVE_Y, + D3DCUBEMAP_FACE_NEGATIVE_Y, + D3DCUBEMAP_FACE_POSITIVE_Z, + D3DCUBEMAP_FACE_NEGATIVE_Z, +}; + D3DTEXTUREFILTERTYPE CGxDeviceD3d::s_filterModes[GxTexFilters_Last][3] = { // Min, Mag, Mip { D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE }, // GxTex_Nearest @@ -1392,7 +1402,107 @@ void CGxDeviceD3d::ITexMarkAsUpdated(CGxTex* texId) { } void CGxDeviceD3d::ITexUpload(CGxTex* texId) { - // TODO + uint32_t texelStrideInBytes; + const void* texels = nullptr; + + texId->m_userFunc(GxTex_Lock, texId->m_width, texId->m_height, 0, 0, texId->m_userArg, texelStrideInBytes, texels); + + uint32_t width; + uint32_t height; + uint32_t startLevel; + uint32_t endLevel; + this->ITexWHDStartEnd(texId, width, height, startLevel, endLevel); + + int32_t numFace = texId->m_target == GxTex_CubeMap ? 6 : 1; + + for (int32_t face = 0; face < numFace; face++) { + for (int32_t level = startLevel; level < endLevel; level++) { + texels = nullptr; + + texId->m_userFunc( + GxTex_Latch, + texId->m_width >> level, + texId->m_height >> level, + face, + level, + texId->m_userArg, + texelStrideInBytes, + texels + ); + + STORM_ASSERT(texels != nullptr || texId->m_flags.m_renderTarget); + + LPDIRECT3DSURFACE9 surface = nullptr; + HRESULT surfaceResult; + + if (texId->m_target == GxTex_CubeMap) { + auto d3dTexture = static_cast(texId->m_apiSpecificData); + surfaceResult = d3dTexture->GetCubeMapSurface(CGxDeviceD3d::s_faceTypes[face], level, &surface); + } else { + auto d3dTexture = static_cast(texId->m_apiSpecificData); + surfaceResult = d3dTexture->GetSurfaceLevel(level, &surface); + } + + if (FAILED(surfaceResult)) { + goto UNLOCK; + } + + RECT rect = { + texId->m_updateRect.minX >> level, // left + texId->m_updateRect.minY >> level, // top + texId->m_updateRect.maxX >> level, // right + texId->m_updateRect.maxY >> level, // bottom + }; + + rect.right = std::max(rect.right, rect.left + 1); + rect.bottom = std::max(rect.bottom, rect.top + 1); + + if (texId->m_format == GxTex_Dxt1 || texId->m_format == GxTex_Dxt3 || texId->m_format == GxTex_Dxt5) { + rect.left &= 0xFFFFFFFC; + rect.top &= 0xFFFFFFFC; + rect.bottom = (rect.bottom + 3) & 0xFFFFFFFC; + rect.right = (rect.right + 3) & 0xFFFFFFFC; + + rect.bottom = std::min(rect.bottom, static_cast(height)); + rect.right = std::min(rect.right, static_cast(width)); + } + + D3DLOCKED_RECT lockedRect; + if (FAILED(surface->LockRect(&lockedRect, &rect, 0x0))) { + surface->Release(); + goto UNLOCK; + } + + if (texId->m_flags.m_bit15) { + // TODO + } + + C2iVector size = { rect.right - rect.left, rect.bottom - rect.top }; + + Blit( + size, + BlitAlpha_0, + texels, + texelStrideInBytes, + GxGetBlitFormat(texId->m_dataFormat), + lockedRect.pBits, + lockedRect.Pitch, + GxGetBlitFormat(texId->m_format) + ); + + surface->UnlockRect(); + surface->Release(); + } + } + +UNLOCK: + texels = nullptr; + texId->m_userFunc(GxTex_Unlock, texId->m_width, texId->m_height, 0, 0, texId->m_userArg, texelStrideInBytes, texels); + + if (texId->m_flags.m_renderTarget) { + auto d3dTexture = static_cast(texId->m_apiSpecificData); + d3dTexture->PreLoad(); + } } void CGxDeviceD3d::PoolSizeSet(CGxPool* pool, uint32_t size) { diff --git a/src/gx/d3d/CGxDeviceD3d.hpp b/src/gx/d3d/CGxDeviceD3d.hpp index ae5247f..6133e8d 100644 --- a/src/gx/d3d/CGxDeviceD3d.hpp +++ b/src/gx/d3d/CGxDeviceD3d.hpp @@ -197,6 +197,7 @@ class CGxDeviceD3d : public CGxDevice { // Static variables static D3DCMPFUNC s_cmpFunc[]; + static D3DCUBEMAP_FACES s_faceTypes[]; static D3DTEXTUREFILTERTYPE s_filterModes[GxTexFilters_Last][3]; static uint32_t s_gxAttribToD3dAttribSize[]; static D3DDECLTYPE s_gxAttribToD3dAttribType[];