Try to clarify the mip handling code
- Keep track of the mip width and height in pixels, without any regard for the texture format. We need to know this to properly convert compressed textures (not that we convert them properly!) The minimum mip width/height for compressed textures is 1 pixel, not 4 pixels. - For compressed textures, bottom out the row pitch at the minimum block data size
This commit is contained in:
parent
e4ef9c1985
commit
6332b9beaf
|
@ -5717,7 +5717,6 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
bool bCubemap = pPixelContainer->Format & X_D3DFORMAT_CUBEMAP;
|
||||
bool bSwizzled = EmuXBFormatIsSwizzled(X_Format);
|
||||
bool bCompressed = EmuXBFormatIsCompressed(X_Format);
|
||||
DWORD dwMinSize = (bCompressed) ? 4 : 1;
|
||||
UINT dwBPP = EmuXBFormatBytesPerPixel(X_Format);
|
||||
UINT dwMipMapLevels = CxbxGetPixelContainerMipMapLevels(pPixelContainer);
|
||||
UINT dwWidth, dwHeight, dwDepth, dwRowPitch, dwSlicePitch;
|
||||
|
@ -5751,22 +5750,6 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
LOG_TEST_CASE("CreateHostResource : Depth != 1");
|
||||
}
|
||||
|
||||
// The following is necessary for DXT* textures (4x4 blocks minimum)
|
||||
// TODO: Figure out if this is necessary under other circumstances?
|
||||
if (bCompressed) {
|
||||
if (dwWidth < dwMinSize) {
|
||||
LOG_TEST_CASE("CreateHostResource : dwWidth < dwMinSize");
|
||||
EmuLog(LOG_LEVEL::WARNING, "Expanding %s width (%d->%d)", ResourceTypeName, dwWidth, dwMinSize);
|
||||
dwWidth = dwMinSize;
|
||||
}
|
||||
|
||||
if (dwHeight < dwMinSize) {
|
||||
LOG_TEST_CASE("CreateHostResource : dwHeight < dwMinSize");
|
||||
EmuLog(LOG_LEVEL::WARNING, "Expanding %s height (%d->%d)", ResourceTypeName, dwHeight, dwMinSize);
|
||||
dwHeight = dwMinSize;
|
||||
}
|
||||
}
|
||||
|
||||
// One of these will be created : each also has an intermediate copy to allow UpdateTexture to work
|
||||
// This means we don't need to lock the GPU resource anymore, so we can use D3DPOOL_DEFAULT to allow Stretch/CopyRects to work!
|
||||
IDirect3DSurface *pNewHostSurface = nullptr; // for X_D3DRTYPE_SURFACE
|
||||
|
@ -5985,20 +5968,25 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
for (int face = D3DCUBEMAP_FACE_POSITIVE_X; face <= last_face; face++) {
|
||||
// As we iterate through mipmap levels, we'll adjust the source resource offset
|
||||
DWORD dwMipOffset = 0;
|
||||
DWORD dwMipWidth = dwWidth;
|
||||
DWORD dwMipHeight = dwHeight;
|
||||
DWORD dwMipDepth = dwDepth;
|
||||
DWORD pxMipWidth = dwWidth;
|
||||
DWORD pxMipHeight = dwHeight;
|
||||
DWORD pxMipDepth = dwDepth;
|
||||
DWORD dwMipRowPitch = dwRowPitch;
|
||||
DWORD dwSrcSlicePitch = dwMipRowPitch * dwMipHeight; // TODO
|
||||
DWORD dwSrcSlicePitch = dwMipRowPitch * pxMipHeight; // TODO
|
||||
|
||||
for (unsigned int mipmap_level = 0; mipmap_level < dwMipMapLevels; mipmap_level++) {
|
||||
|
||||
// Calculate size of this mipmap level
|
||||
DWORD dwMipSize = dwMipRowPitch * dwMipHeight;
|
||||
auto numRows = pxMipHeight;
|
||||
|
||||
if (bCompressed) {
|
||||
dwMipSize /= 4;
|
||||
// Each row contains a 4x4 pixel blocks, instead of single pixels
|
||||
// So divide by 4 to get the number of rows
|
||||
numRows = (numRows + 3) / 4;
|
||||
}
|
||||
|
||||
DWORD dwMipSize = dwMipRowPitch * numRows;
|
||||
|
||||
// Lock the host resource
|
||||
D3DLOCKED_RECT LockedRect = {};
|
||||
D3DLOCKED_BOX LockedBox = {};
|
||||
|
@ -6059,7 +6047,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
if (X_Format == xbox::X_D3DFMT_P8 && g_pXbox_Palette_Data[iTextureStage] == nullptr) {
|
||||
LOG_TEST_CASE("Palettized texture bound without a palette");
|
||||
|
||||
memset(pDst, 0, dwDstRowPitch * dwMipHeight);
|
||||
memset(pDst, 0, dwDstRowPitch * pxMipHeight);
|
||||
skipDueToNoPalette = true;
|
||||
}
|
||||
|
||||
|
@ -6067,7 +6055,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
if (!skipDueToNoPalette) {
|
||||
if (!ConvertD3DTextureToARGBBuffer(
|
||||
X_Format,
|
||||
pSrc, dwMipWidth, dwMipHeight, dwMipRowPitch, dwSrcSlicePitch,
|
||||
pSrc, pxMipWidth, pxMipHeight, dwMipRowPitch, dwSrcSlicePitch,
|
||||
pDst, dwDstRowPitch, dwDstSlicePitch,
|
||||
dwDepth,
|
||||
iTextureStage)) {
|
||||
|
@ -6078,7 +6066,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
else if (bSwizzled) {
|
||||
// First we need to unswizzle the texture data
|
||||
EmuUnswizzleBox(
|
||||
pSrc, dwMipWidth, dwMipHeight, dwMipDepth,
|
||||
pSrc, pxMipWidth, pxMipHeight, pxMipDepth,
|
||||
dwBPP,
|
||||
pDst, dwDstRowPitch, dwDstSlicePitch
|
||||
);
|
||||
|
@ -6102,12 +6090,12 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
);
|
||||
} else {
|
||||
*/
|
||||
if ((dwDstRowPitch == dwMipRowPitch) && (dwMipRowPitch == dwMipWidth * dwBPP)) {
|
||||
if ((dwDstRowPitch == dwMipRowPitch) && (dwMipRowPitch == pxMipWidth * dwBPP)) {
|
||||
memcpy(pDst, pSrc, dwMipSize);
|
||||
}
|
||||
else {
|
||||
for (DWORD v = 0; v < dwMipHeight; v++) {
|
||||
memcpy(pDst, pSrc, dwMipWidth * dwBPP);
|
||||
for (DWORD v = 0; v < pxMipHeight; v++) {
|
||||
memcpy(pDst, pSrc, pxMipWidth * dwBPP);
|
||||
pDst += dwDstRowPitch;
|
||||
pSrc += dwMipRowPitch;
|
||||
}
|
||||
|
@ -6145,17 +6133,30 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
|
|||
|
||||
// Calculate the next mipmap level dimensions
|
||||
dwMipOffset += dwMipSize;
|
||||
if (dwMipWidth > dwMinSize) {
|
||||
dwMipWidth /= 2;
|
||||
if (pxMipWidth > 1) {
|
||||
pxMipWidth /= 2;
|
||||
|
||||
// Update the row pitch
|
||||
dwMipRowPitch /= 2;
|
||||
|
||||
if (bCompressed) {
|
||||
// The row pitch can't be smaller than a single 4x4 block
|
||||
// even if we need to store just one pixel
|
||||
// DXT1 block size is 8 bytes
|
||||
// Other supported DXT formats are 16 bytes
|
||||
auto blockSize = X_Format == xbox::X_D3DFMT_DXT1 ? 8 : 16;
|
||||
if (dwMipRowPitch < blockSize) {
|
||||
dwMipRowPitch = blockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dwMipHeight > dwMinSize) {
|
||||
dwMipHeight /= 2;
|
||||
if (pxMipHeight > 1) {
|
||||
pxMipHeight /= 2;
|
||||
}
|
||||
|
||||
if (dwMipDepth > 1) {
|
||||
dwMipDepth /= 2;
|
||||
if (pxMipDepth > 1) {
|
||||
pxMipDepth /= 2;
|
||||
}
|
||||
} // for mipmap levels
|
||||
|
||||
|
|
Loading…
Reference in New Issue