2015-09-28 22:33:29 +02:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "Emu/Memory/vm.h"
|
|
|
|
|
#include "TextureUtils.h"
|
|
|
|
|
#include "../RSXThread.h"
|
|
|
|
|
#include "Utilities/Log.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MAX2(a, b) ((a) > (b)) ? (a) : (b)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write data, assume src pixels are packed but not mipmaplevel
|
|
|
|
|
*/
|
|
|
|
|
inline std::vector<MipmapLevelInfo>
|
|
|
|
|
writeTexelsGeneric(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
|
|
|
|
{
|
|
|
|
|
std::vector<MipmapLevelInfo> Result;
|
|
|
|
|
size_t offsetInDst = 0, offsetInSrc = 0;
|
|
|
|
|
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
|
|
|
|
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
|
|
|
|
{
|
|
|
|
|
size_t rowPitch = align(currentWidth * blockSize, 256);
|
|
|
|
|
|
|
|
|
|
MipmapLevelInfo currentMipmapLevelInfo = {};
|
|
|
|
|
currentMipmapLevelInfo.offset = offsetInDst;
|
|
|
|
|
currentMipmapLevelInfo.height = currentHeight;
|
|
|
|
|
currentMipmapLevelInfo.width = currentWidth;
|
|
|
|
|
currentMipmapLevelInfo.rowPitch = rowPitch;
|
|
|
|
|
Result.push_back(currentMipmapLevelInfo);
|
|
|
|
|
|
|
|
|
|
for (unsigned row = 0; row < currentHeight; row++)
|
|
|
|
|
memcpy((char*)dst + offsetInDst + row * rowPitch, (char*)src + offsetInSrc + row * widthInBlock * blockSize, currentWidth * blockSize);
|
|
|
|
|
|
|
|
|
|
offsetInDst += currentHeight * rowPitch;
|
|
|
|
|
offsetInDst = align(offsetInDst, 512);
|
|
|
|
|
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
|
|
|
|
currentHeight = MAX2(currentHeight / 2, 1);
|
|
|
|
|
currentWidth = MAX2(currentWidth / 2, 1);
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write data, assume src pixels are swizzled and but not mipmaplevel
|
|
|
|
|
*/
|
|
|
|
|
inline std::vector<MipmapLevelInfo>
|
|
|
|
|
writeTexelsSwizzled(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
|
|
|
|
{
|
|
|
|
|
std::vector<MipmapLevelInfo> Result;
|
|
|
|
|
size_t offsetInDst = 0, offsetInSrc = 0;
|
|
|
|
|
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
|
|
|
|
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
|
|
|
|
{
|
|
|
|
|
size_t rowPitch = align(currentWidth * blockSize, 256);
|
|
|
|
|
|
|
|
|
|
MipmapLevelInfo currentMipmapLevelInfo = {};
|
|
|
|
|
currentMipmapLevelInfo.offset = offsetInDst;
|
|
|
|
|
currentMipmapLevelInfo.height = currentHeight;
|
|
|
|
|
currentMipmapLevelInfo.width = currentWidth;
|
|
|
|
|
currentMipmapLevelInfo.rowPitch = rowPitch;
|
|
|
|
|
Result.push_back(currentMipmapLevelInfo);
|
|
|
|
|
|
|
|
|
|
u32 *castedSrc, *castedDst;
|
|
|
|
|
u32 log2width, log2height;
|
|
|
|
|
|
|
|
|
|
castedSrc = (u32*)src + offsetInSrc;
|
|
|
|
|
castedDst = (u32*)dst + offsetInDst;
|
|
|
|
|
|
|
|
|
|
log2width = (u32)(logf((float)currentWidth) / logf(2.f));
|
|
|
|
|
log2height = (u32)(logf((float)currentHeight) / logf(2.f));
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < currentHeight; row++)
|
|
|
|
|
for (int j = 0; j < currentWidth; j++)
|
2015-10-08 17:07:23 +02:00
|
|
|
castedDst[(row * rowPitch / 4) + j] = castedSrc[rsx::linear_to_swizzle(j, row, 0, log2width, log2height, 0)];
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
offsetInDst += currentHeight * rowPitch;
|
|
|
|
|
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
|
|
|
|
currentHeight = MAX2(currentHeight / 2, 1);
|
|
|
|
|
currentWidth = MAX2(currentWidth / 2, 1);
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write data, assume compressed (DXTCn) format
|
|
|
|
|
*/
|
|
|
|
|
inline std::vector<MipmapLevelInfo>
|
|
|
|
|
writeCompressedTexel(const char *src, char *dst, size_t widthInBlock, size_t blockWidth, size_t heightInBlock, size_t blockHeight, size_t blockSize, size_t mipmapCount)
|
|
|
|
|
{
|
|
|
|
|
std::vector<MipmapLevelInfo> Result;
|
|
|
|
|
size_t offsetInDst = 0, offsetInSrc = 0;
|
|
|
|
|
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
|
|
|
|
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
|
|
|
|
{
|
|
|
|
|
size_t rowPitch = align(currentWidth * blockSize, 256);
|
|
|
|
|
|
|
|
|
|
MipmapLevelInfo currentMipmapLevelInfo = {};
|
|
|
|
|
currentMipmapLevelInfo.offset = offsetInDst;
|
|
|
|
|
currentMipmapLevelInfo.height = currentHeight * blockHeight;
|
|
|
|
|
currentMipmapLevelInfo.width = currentWidth * blockWidth;
|
|
|
|
|
currentMipmapLevelInfo.rowPitch = rowPitch;
|
|
|
|
|
Result.push_back(currentMipmapLevelInfo);
|
|
|
|
|
|
|
|
|
|
for (unsigned row = 0; row < currentHeight; row++)
|
|
|
|
|
memcpy((char*)dst + offsetInDst + row * rowPitch, (char*)src + offsetInSrc + row * currentWidth * blockSize, currentWidth * blockSize);
|
|
|
|
|
|
|
|
|
|
offsetInDst += currentHeight * rowPitch;
|
|
|
|
|
offsetInDst = align(offsetInDst, 512);
|
|
|
|
|
offsetInSrc += currentHeight * currentWidth * blockSize;
|
|
|
|
|
currentHeight = MAX2(currentHeight / 2, 1);
|
|
|
|
|
currentWidth = MAX2(currentWidth / 2, 1);
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write 16 bytes pixel textures, assume src pixels are swizzled and but not mipmaplevel
|
|
|
|
|
*/
|
|
|
|
|
inline std::vector<MipmapLevelInfo>
|
|
|
|
|
write16bTexelsSwizzled(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
|
|
|
|
{
|
|
|
|
|
std::vector<MipmapLevelInfo> Result;
|
|
|
|
|
size_t offsetInDst = 0, offsetInSrc = 0;
|
|
|
|
|
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
|
|
|
|
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
|
|
|
|
{
|
|
|
|
|
size_t rowPitch = align(currentWidth * blockSize, 256);
|
|
|
|
|
|
|
|
|
|
MipmapLevelInfo currentMipmapLevelInfo = {};
|
|
|
|
|
currentMipmapLevelInfo.offset = offsetInDst;
|
|
|
|
|
currentMipmapLevelInfo.height = currentHeight;
|
|
|
|
|
currentMipmapLevelInfo.width = currentWidth;
|
|
|
|
|
currentMipmapLevelInfo.rowPitch = rowPitch;
|
|
|
|
|
Result.push_back(currentMipmapLevelInfo);
|
|
|
|
|
|
|
|
|
|
u16 *castedSrc, *castedDst;
|
|
|
|
|
u16 log2width, log2height;
|
|
|
|
|
|
|
|
|
|
castedSrc = (u16*)src + offsetInSrc;
|
|
|
|
|
castedDst = (u16*)dst + offsetInDst;
|
|
|
|
|
|
|
|
|
|
log2width = (u32)(logf((float)currentWidth) / logf(2.f));
|
|
|
|
|
log2height = (u32)(logf((float)currentHeight) / logf(2.f));
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < currentHeight; row++)
|
|
|
|
|
for (int j = 0; j < currentWidth; j++)
|
2015-10-08 17:07:23 +02:00
|
|
|
castedDst[(row * rowPitch / 2) + j] = castedSrc[rsx::linear_to_swizzle(j, row, 0, log2width, log2height, 0)];
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
offsetInDst += currentHeight * rowPitch;
|
|
|
|
|
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
|
|
|
|
currentHeight = MAX2(currentHeight / 2, 1);
|
|
|
|
|
currentWidth = MAX2(currentWidth / 2, 1);
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
|
|
|
|
*/
|
|
|
|
|
inline std::vector<MipmapLevelInfo>
|
|
|
|
|
write16bTexelsGeneric(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
|
|
|
|
{
|
|
|
|
|
std::vector<MipmapLevelInfo> Result;
|
|
|
|
|
size_t offsetInDst = 0, offsetInSrc = 0;
|
|
|
|
|
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
|
|
|
|
size_t srcPitch = widthInBlock * blockSize;
|
|
|
|
|
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
|
|
|
|
{
|
|
|
|
|
size_t rowPitch = align(currentWidth * blockSize, 256);
|
|
|
|
|
|
|
|
|
|
MipmapLevelInfo currentMipmapLevelInfo = {};
|
|
|
|
|
currentMipmapLevelInfo.offset = offsetInDst;
|
|
|
|
|
currentMipmapLevelInfo.height = currentHeight;
|
|
|
|
|
currentMipmapLevelInfo.width = currentWidth;
|
|
|
|
|
currentMipmapLevelInfo.rowPitch = rowPitch;
|
|
|
|
|
Result.push_back(currentMipmapLevelInfo);
|
|
|
|
|
|
|
|
|
|
unsigned short *castedDst = (unsigned short *)dst, *castedSrc = (unsigned short *)src;
|
|
|
|
|
|
|
|
|
|
for (unsigned row = 0; row < heightInBlock; row++)
|
|
|
|
|
for (int j = 0; j < currentWidth; j++)
|
|
|
|
|
{
|
|
|
|
|
u16 tmp = castedSrc[offsetInSrc / 2 + row * srcPitch / 2 + j];
|
|
|
|
|
castedDst[offsetInDst / 2 + row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
offsetInDst += currentHeight * rowPitch;
|
|
|
|
|
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
|
|
|
|
currentHeight = MAX2(currentHeight / 2, 1);
|
|
|
|
|
currentWidth = MAX2(currentWidth / 2, 1);
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
|
|
|
|
*/
|
|
|
|
|
inline std::vector<MipmapLevelInfo>
|
|
|
|
|
write16bX4TexelsGeneric(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
|
|
|
|
{
|
|
|
|
|
std::vector<MipmapLevelInfo> Result;
|
|
|
|
|
size_t offsetInDst = 0, offsetInSrc = 0;
|
|
|
|
|
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
|
|
|
|
size_t srcPitch = widthInBlock * blockSize;
|
|
|
|
|
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
|
|
|
|
{
|
|
|
|
|
size_t rowPitch = align(currentWidth * blockSize, 256);
|
|
|
|
|
|
|
|
|
|
MipmapLevelInfo currentMipmapLevelInfo = {};
|
|
|
|
|
currentMipmapLevelInfo.offset = offsetInDst;
|
|
|
|
|
currentMipmapLevelInfo.height = currentHeight;
|
|
|
|
|
currentMipmapLevelInfo.width = currentWidth;
|
|
|
|
|
currentMipmapLevelInfo.rowPitch = rowPitch;
|
|
|
|
|
Result.push_back(currentMipmapLevelInfo);
|
|
|
|
|
|
|
|
|
|
unsigned short *castedDst = (unsigned short *)dst, *castedSrc = (unsigned short *)src;
|
|
|
|
|
|
|
|
|
|
for (unsigned row = 0; row < heightInBlock; row++)
|
|
|
|
|
for (int j = 0; j < currentWidth * 4; j++)
|
|
|
|
|
{
|
|
|
|
|
u16 tmp = castedSrc[offsetInSrc / 2 + row * srcPitch / 2 + j];
|
|
|
|
|
castedDst[offsetInDst / 2 + row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
offsetInDst += currentHeight * rowPitch;
|
|
|
|
|
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
|
|
|
|
currentHeight = MAX2(currentHeight / 2, 1);
|
|
|
|
|
currentWidth = MAX2(currentWidth / 2, 1);
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-10-08 15:53:21 +02:00
|
|
|
size_t getPlacedTextureStorageSpace(const rsx::texture &texture, size_t rowPitchAlignement)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-10-08 15:53:21 +02:00
|
|
|
size_t w = texture.width(), h = texture.height();
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
2015-10-08 15:53:21 +02:00
|
|
|
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
switch (format)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
|
|
|
|
|
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
|
|
|
|
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
|
|
|
|
default:
|
|
|
|
|
LOG_ERROR(RSX, "Unimplemented Texture format : %x", format);
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_B8:
|
|
|
|
|
blockSizeInByte = 1;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockHeightInPixel = 1, blockWidthInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G6B5:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
|
|
|
|
blockSizeInByte = 8;
|
|
|
|
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
|
|
|
|
blockSizeInByte = 16;
|
|
|
|
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
|
|
|
|
blockSizeInByte = 16;
|
|
|
|
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_G8B8:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_R6G5B5:
|
|
|
|
|
// Not native
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_X16:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G5B5A1:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
|
|
|
|
blockSizeInByte = 8;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
|
|
|
|
blockSizeInByte = 16;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_X32_FLOAT:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_D1R5G5B5:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_D8R8G8B8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t heightInBlocks = (h + blockHeightInPixel - 1) / blockHeightInPixel;
|
|
|
|
|
size_t widthInBlocks = (w + blockWidthInPixel - 1) / blockWidthInPixel;
|
|
|
|
|
|
|
|
|
|
size_t rowPitch = align(blockSizeInByte * widthInBlocks, rowPitchAlignement);
|
|
|
|
|
|
|
|
|
|
return rowPitch * heightInBlocks * 2; // * 2 for mipmap levels
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-08 15:53:21 +02:00
|
|
|
std::vector<MipmapLevelInfo> uploadPlacedTexture(const rsx::texture &texture, size_t rowPitchAlignement, void* textureData)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-10-08 15:53:21 +02:00
|
|
|
size_t w = texture.width(), h = texture.height();
|
2015-09-28 22:33:29 +02:00
|
|
|
|
2015-10-08 15:53:21 +02:00
|
|
|
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
|
|
|
|
switch (format)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
|
|
|
|
|
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
|
|
|
|
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
|
|
|
|
default:
|
|
|
|
|
LOG_ERROR(RSX, "Unimplemented Texture format : %x", format);
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_B8:
|
|
|
|
|
blockSizeInByte = 1;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockHeightInPixel = 1, blockWidthInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G6B5:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
|
|
|
|
blockSizeInByte = 8;
|
|
|
|
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
|
|
|
|
blockSizeInByte = 16;
|
|
|
|
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
|
|
|
|
blockSizeInByte = 16;
|
|
|
|
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_G8B8:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_R6G5B5:
|
|
|
|
|
// Not native
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_X16:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G5B5A1:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
|
|
|
|
blockSizeInByte = 8;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
|
|
|
|
blockSizeInByte = 16;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_X32_FLOAT:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_D1R5G5B5:
|
|
|
|
|
blockSizeInByte = 2;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_D8R8G8B8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
|
|
|
|
blockSizeInByte = 4;
|
|
|
|
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t heightInBlocks = (h + blockHeightInPixel - 1) / blockHeightInPixel;
|
|
|
|
|
size_t widthInBlocks = (w + blockWidthInPixel - 1) / blockWidthInPixel;
|
|
|
|
|
|
|
|
|
|
std::vector<MipmapLevelInfo> mipInfos;
|
|
|
|
|
|
2015-10-08 15:53:21 +02:00
|
|
|
const u32 texaddr = rsx::get_address(texture.offset(), texture.location());
|
2015-09-26 22:46:04 +02:00
|
|
|
auto pixels = vm::ps3::_ptr<const u8>(texaddr);
|
2015-10-08 15:53:21 +02:00
|
|
|
bool is_swizzled = !(texture.format() & CELL_GCM_TEXTURE_LN);
|
2015-09-28 22:33:29 +02:00
|
|
|
switch (format)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
|
|
|
|
if (is_swizzled)
|
2015-10-08 15:53:21 +02:00
|
|
|
return writeTexelsSwizzled((char*)pixels, (char*)textureData, w, h, 4, texture.mipmap());
|
2015-09-28 22:33:29 +02:00
|
|
|
else
|
2015-10-08 15:53:21 +02:00
|
|
|
return writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, 4, texture.mipmap());
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
|
|
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G6B5:
|
|
|
|
|
if (is_swizzled)
|
2015-10-08 15:53:21 +02:00
|
|
|
return write16bTexelsSwizzled((char*)pixels, (char*)textureData, w, h, 2, texture.mipmap());
|
2015-09-28 22:33:29 +02:00
|
|
|
else
|
2015-10-08 15:53:21 +02:00
|
|
|
return write16bTexelsGeneric((char*)pixels, (char*)textureData, w, h, 2, texture.mipmap());
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
2015-10-08 15:53:21 +02:00
|
|
|
return write16bX4TexelsGeneric((char*)pixels, (char*)textureData, w, h, 8, texture.mipmap());
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
2015-10-08 15:53:21 +02:00
|
|
|
return writeCompressedTexel((char*)pixels, (char*)textureData, widthInBlocks, blockWidthInPixel, heightInBlocks, blockHeightInPixel, blockSizeInByte, texture.mipmap());
|
2015-09-28 22:33:29 +02:00
|
|
|
default:
|
2015-10-08 15:53:21 +02:00
|
|
|
return writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, blockSizeInByte, texture.mipmap());
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
2015-09-26 22:46:04 +02:00
|
|
|
}
|