From 27f3c09c8f3325efd498be6b11d54f5b77b345b9 Mon Sep 17 00:00:00 2001 From: nv3ifu Date: Sat, 10 Oct 2026 00:49:11 +0800 Subject: [PATCH 1/2] Add BC block copy support to CopyRectangle --- DirectXTex/DirectXTexMisc.cpp | 63 ++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/DirectXTex/DirectXTexMisc.cpp b/DirectXTex/DirectXTexMisc.cpp index 7b787cd7..a0191be0 100644 --- a/DirectXTex/DirectXTexMisc.cpp +++ b/DirectXTex/DirectXTexMisc.cpp @@ -260,7 +260,68 @@ _Use_decl_annotations_ HRESULT DirectX::CopyRectangle(const Image& srcImage, if (!srcImage.pixels || !dstImage.pixels) return E_POINTER; - if (IsCompressed(srcImage.format) || IsCompressed(dstImage.format) || IsPlanar(srcImage.format) || IsPlanar(dstImage.format) + if (IsCompressed(srcImage.format) || IsCompressed(dstImage.format)) + { + if (srcImage.format != dstImage.format) + return HRESULT_E_NOT_SUPPORTED; + + const size_t bytesPerBlock = BytesPerBlock(srcImage.format); + if (!bytesPerBlock) + return HRESULT_E_NOT_SUPPORTED; + + if (!srcRect.w || !srcRect.h || srcRect.x >= srcImage.width || srcRect.y >= srcImage.height + || srcRect.w > srcImage.width - srcRect.x || srcRect.h > srcImage.height - srcRect.y + || xOffset >= dstImage.width || yOffset >= dstImage.height + || srcRect.w > dstImage.width - xOffset || srcRect.h > dstImage.height - yOffset) + return E_INVALIDARG; + + // Copy whole 4x4 blocks covering srcRect, including pixels outside it. + // Round the destination origin down to a block boundary. + const size_t srcX = srcRect.x / 4; + const size_t srcY = srcRect.y / 4; + const size_t dstX = xOffset / 4; + const size_t dstY = yOffset / 4; + + const size_t blockWidth = (srcRect.x + srcRect.w - 1) / 4 + 1 - srcX; + const size_t blockHeight = (srcRect.y + srcRect.h - 1) / 4 + 1 - srcY; + const size_t dstWidth = (dstImage.width - 1) / 4 + 1; + const size_t dstHeight = (dstImage.height - 1) / 4 + 1; + if (blockWidth > dstWidth - dstX || blockHeight > dstHeight - dstY) + return E_INVALIDARG; + + const auto validStorage = [bytesPerBlock](const Image& image, size_t x, size_t y, + size_t width, size_t height) noexcept + { + const size_t imageBlocks = (image.width - 1) / 4 + 1; + if (!image.rowPitch || imageBlocks > image.rowPitch / bytesPerBlock) + return false; + + const size_t rowEnd = (x + width) * bytesPerBlock; + return rowEnd <= image.slicePitch + && y + height - 1 <= (image.slicePitch - rowEnd) / image.rowPitch; + }; + + if (!validStorage(srcImage, srcX, srcY, blockWidth, blockHeight) + || !validStorage(dstImage, dstX, dstY, blockWidth, blockHeight)) + return E_FAIL; + + const size_t copyBytes = blockWidth * bytesPerBlock; + const uint8_t* pSrc = srcImage.pixels + srcY * srcImage.rowPitch + srcX * bytesPerBlock; + uint8_t* pDest = dstImage.pixels + dstY * dstImage.rowPitch + dstX * bytesPerBlock; + for (size_t row = 0; row < blockHeight; ++row) + { + memcpy(pDest, pSrc, copyBytes); + if (row + 1 < blockHeight) + { + pSrc += srcImage.rowPitch; + pDest += dstImage.rowPitch; + } + } + + return S_OK; + } + + if (IsPlanar(srcImage.format) || IsPlanar(dstImage.format) || IsPalettized(srcImage.format) || IsPalettized(dstImage.format)) return HRESULT_E_NOT_SUPPORTED; From a898119af6a5e725ad5f0c05c694c88c6880c3f0 Mon Sep 17 00:00:00 2001 From: nv3ifu Date: Sun, 11 Oct 2026 00:29:05 +0800 Subject: [PATCH 2/2] Apply clang-format to CopyRectangle BC copy code --- DirectXTex/DirectXTexMisc.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/DirectXTex/DirectXTexMisc.cpp b/DirectXTex/DirectXTexMisc.cpp index a0191be0..204636d4 100644 --- a/DirectXTex/DirectXTexMisc.cpp +++ b/DirectXTex/DirectXTexMisc.cpp @@ -270,9 +270,8 @@ _Use_decl_annotations_ HRESULT DirectX::CopyRectangle(const Image& srcImage, return HRESULT_E_NOT_SUPPORTED; if (!srcRect.w || !srcRect.h || srcRect.x >= srcImage.width || srcRect.y >= srcImage.height - || srcRect.w > srcImage.width - srcRect.x || srcRect.h > srcImage.height - srcRect.y - || xOffset >= dstImage.width || yOffset >= dstImage.height - || srcRect.w > dstImage.width - xOffset || srcRect.h > dstImage.height - yOffset) + || srcRect.w > srcImage.width - srcRect.x || srcRect.h > srcImage.height - srcRect.y || xOffset >= dstImage.width + || yOffset >= dstImage.height || srcRect.w > dstImage.width - xOffset || srcRect.h > dstImage.height - yOffset) return E_INVALIDARG; // Copy whole 4x4 blocks covering srcRect, including pixels outside it. @@ -282,32 +281,29 @@ _Use_decl_annotations_ HRESULT DirectX::CopyRectangle(const Image& srcImage, const size_t dstX = xOffset / 4; const size_t dstY = yOffset / 4; - const size_t blockWidth = (srcRect.x + srcRect.w - 1) / 4 + 1 - srcX; + const size_t blockWidth = (srcRect.x + srcRect.w - 1) / 4 + 1 - srcX; const size_t blockHeight = (srcRect.y + srcRect.h - 1) / 4 + 1 - srcY; - const size_t dstWidth = (dstImage.width - 1) / 4 + 1; - const size_t dstHeight = (dstImage.height - 1) / 4 + 1; + const size_t dstWidth = (dstImage.width - 1) / 4 + 1; + const size_t dstHeight = (dstImage.height - 1) / 4 + 1; if (blockWidth > dstWidth - dstX || blockHeight > dstHeight - dstY) return E_INVALIDARG; - const auto validStorage = [bytesPerBlock](const Image& image, size_t x, size_t y, - size_t width, size_t height) noexcept + const auto validStorage = [bytesPerBlock](const Image& image, size_t x, size_t y, size_t width, size_t height) noexcept { const size_t imageBlocks = (image.width - 1) / 4 + 1; if (!image.rowPitch || imageBlocks > image.rowPitch / bytesPerBlock) return false; const size_t rowEnd = (x + width) * bytesPerBlock; - return rowEnd <= image.slicePitch - && y + height - 1 <= (image.slicePitch - rowEnd) / image.rowPitch; + return rowEnd <= image.slicePitch && y + height - 1 <= (image.slicePitch - rowEnd) / image.rowPitch; }; - if (!validStorage(srcImage, srcX, srcY, blockWidth, blockHeight) - || !validStorage(dstImage, dstX, dstY, blockWidth, blockHeight)) + if (!validStorage(srcImage, srcX, srcY, blockWidth, blockHeight) || !validStorage(dstImage, dstX, dstY, blockWidth, blockHeight)) return E_FAIL; - const size_t copyBytes = blockWidth * bytesPerBlock; - const uint8_t* pSrc = srcImage.pixels + srcY * srcImage.rowPitch + srcX * bytesPerBlock; - uint8_t* pDest = dstImage.pixels + dstY * dstImage.rowPitch + dstX * bytesPerBlock; + const size_t copyBytes = blockWidth * bytesPerBlock; + const uint8_t* pSrc = srcImage.pixels + srcY * srcImage.rowPitch + srcX * bytesPerBlock; + uint8_t* pDest = dstImage.pixels + dstY * dstImage.rowPitch + dstX * bytesPerBlock; for (size_t row = 0; row < blockHeight; ++row) { memcpy(pDest, pSrc, copyBytes); @@ -321,8 +317,7 @@ _Use_decl_annotations_ HRESULT DirectX::CopyRectangle(const Image& srcImage, return S_OK; } - if (IsPlanar(srcImage.format) || IsPlanar(dstImage.format) - || IsPalettized(srcImage.format) || IsPalettized(dstImage.format)) + if (IsPlanar(srcImage.format) || IsPlanar(dstImage.format) || IsPalettized(srcImage.format) || IsPalettized(dstImage.format)) return HRESULT_E_NOT_SUPPORTED; // Validate rectangle/offset