2015-09-28 22:33:29 +02:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "Emu/Memory/vm.h"
|
|
|
|
|
#include "TextureUtils.h"
|
|
|
|
|
#include "../RSXThread.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MAX2(a, b) ((a) > (b)) ? (a) : (b)
|
2015-10-27 01:11:40 +01:00
|
|
|
namespace
|
|
|
|
|
{
|
2015-09-28 22:33:29 +02:00
|
|
|
/**
|
|
|
|
|
* Write data, assume src pixels are packed but not mipmaplevel
|
|
|
|
|
*/
|
2015-12-07 22:09:18 +01:00
|
|
|
struct texel_rgba
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
template<size_t block_size>
|
2015-12-19 00:32:53 +01:00
|
|
|
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
for (unsigned row = 0; row < row_count; row++)
|
|
|
|
|
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * src_pitch_in_block * block_size, width_in_block * block_size);
|
|
|
|
|
}
|
|
|
|
|
};
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
|
2015-12-07 22:09:18 +01:00
|
|
|
/**
|
|
|
|
|
* Write 16 bytes pixel textures, assume src pixels are swizzled and but not mipmaplevel
|
|
|
|
|
*/
|
|
|
|
|
struct texel_16b_swizzled
|
|
|
|
|
{
|
|
|
|
|
template<size_t block_size>
|
2015-12-19 00:32:53 +01:00
|
|
|
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
|
2015-12-07 22:09:18 +01:00
|
|
|
{
|
|
|
|
|
u16 *castedSrc = static_cast<u16*>(src), *castedDst = static_cast<u16*>(dst);
|
2015-09-28 22:33:29 +02:00
|
|
|
|
2015-12-07 22:09:18 +01:00
|
|
|
std::unique_ptr<u16[]> temp_swizzled(new u16[row_count * width_in_block]);
|
|
|
|
|
rsx::convert_linear_swizzle<u16>(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true);
|
|
|
|
|
for (unsigned row = 0; row < row_count; row++)
|
|
|
|
|
for (int j = 0; j < width_in_block; j++)
|
|
|
|
|
{
|
|
|
|
|
u16 tmp = temp_swizzled[row * src_pitch_in_block + j];
|
|
|
|
|
castedDst[row * dst_pitch_in_block + j] = (tmp >> 8) | (tmp << 8);
|
|
|
|
|
}
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
2015-12-07 22:09:18 +01:00
|
|
|
};
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write data, assume src pixels are swizzled and but not mipmaplevel
|
|
|
|
|
*/
|
2015-12-07 22:09:18 +01:00
|
|
|
struct texel_rgba_swizzled
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
template<size_t block_size>
|
2015-12-19 00:32:53 +01:00
|
|
|
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
|
|
|
|
u32 *castedSrc, *castedDst;
|
2015-12-07 22:09:18 +01:00
|
|
|
castedSrc = (u32*)src;
|
|
|
|
|
castedDst = (u32*)dst ;
|
|
|
|
|
std::unique_ptr<u32[]> temp_swizzled(new u32[src_pitch_in_block * row_count]);
|
|
|
|
|
rsx::convert_linear_swizzle<u32>(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true);
|
|
|
|
|
for (unsigned row = 0; row < row_count; row++)
|
|
|
|
|
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)temp_swizzled.get() + row * src_pitch_in_block * block_size, width_in_block * block_size);
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
2015-12-07 22:09:18 +01:00
|
|
|
};
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
/**
|
2015-12-07 22:09:18 +01:00
|
|
|
* Write data, assume compressed (DXTCn) format
|
|
|
|
|
* Data are tightly packed
|
|
|
|
|
*/
|
|
|
|
|
struct texel_bc_format {
|
|
|
|
|
template<size_t block_size>
|
2015-12-19 00:32:53 +01:00
|
|
|
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
for (unsigned row = 0; row < row_count; row++)
|
2015-12-19 00:32:53 +01:00
|
|
|
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * src_pitch_in_block * block_size, width_in_block * block_size);
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
2015-12-07 22:09:18 +01:00
|
|
|
};
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
/**
|
2015-12-07 22:09:18 +01:00
|
|
|
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
2015-09-28 22:33:29 +02:00
|
|
|
*/
|
2015-12-07 22:09:18 +01:00
|
|
|
struct texel_16b_format {
|
|
|
|
|
template<size_t block_size>
|
2015-12-19 00:32:53 +01:00
|
|
|
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
unsigned short *castedDst = (unsigned short *)dst, *castedSrc = (unsigned short *)src;
|
2015-09-28 22:33:29 +02:00
|
|
|
|
2015-12-07 22:09:18 +01:00
|
|
|
for (unsigned row = 0; row < row_count; row++)
|
|
|
|
|
for (int j = 0; j < width_in_block; j++)
|
2015-12-01 14:55:15 +01:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
u16 tmp = castedSrc[row * src_pitch_in_block + j];
|
|
|
|
|
castedDst[row * dst_pitch_in_block + j] = (tmp >> 8) | (tmp << 8);
|
2015-12-01 14:55:15 +01:00
|
|
|
}
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
2015-12-07 22:09:18 +01:00
|
|
|
};
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
/**
|
2015-12-07 22:09:18 +01:00
|
|
|
* Write 16 bytes X 4 pixel textures, assume src pixels are packed but not mipmaplevel
|
2015-09-28 22:33:29 +02:00
|
|
|
*/
|
2015-12-07 22:09:18 +01:00
|
|
|
struct texel_16bX4_format {
|
|
|
|
|
template<size_t block_size>
|
2015-12-19 00:32:53 +01:00
|
|
|
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
unsigned short *casted_dst = (unsigned short *)dst, *casted_src = (unsigned short *)src;
|
|
|
|
|
for (unsigned row = 0; row < row_count; row++)
|
|
|
|
|
for (int j = 0; j < width_in_block * 4; j++)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-07 22:09:18 +01:00
|
|
|
u16 tmp = casted_src[row * src_pitch_in_block * 4 + j];
|
|
|
|
|
casted_dst[row * dst_pitch_in_block * 4 + j] = (tmp >> 8) | (tmp << 8);
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-12-07 22:09:18 +01:00
|
|
|
};
|
2015-09-28 22:33:29 +02:00
|
|
|
|
2015-12-10 02:52:27 +01:00
|
|
|
/**
|
|
|
|
|
* Texture upload template.
|
2015-12-19 00:32:53 +01:00
|
|
|
*
|
|
|
|
|
* Source textures are stored as following (for power of 2 textures):
|
|
|
|
|
* - For linear texture every mipmap level share rowpitch (which is the one of mipmap 0). This means that for non 0 mipmap there's padding between row.
|
|
|
|
|
* - For swizzled texture row pitch is texture width X pixel/block size. There's not padding between row.
|
|
|
|
|
* - There is no padding between 2 mipmap levels. This means that next mipmap level starts at offset rowpitch X row count
|
|
|
|
|
* - Cubemap images are 128 bytes aligned.
|
|
|
|
|
*
|
2015-12-10 02:52:27 +01:00
|
|
|
* The template iterates over all depth (including cubemap) and over all mipmaps.
|
|
|
|
|
* The alignment is 256 for mipmap levels and 512 for depth (TODO: make this customisable for Vulkan ?)
|
|
|
|
|
* The template takes a struct with a "copy_mipmap_level" static function that copy the given mipmap level and returns the offset to add to the src buffer for next
|
|
|
|
|
* mipmap level (to allow same code for packed/non packed texels)
|
|
|
|
|
*/
|
2015-12-19 00:32:53 +01:00
|
|
|
template <typename T, bool padded_row, size_t block_size_in_bytes, size_t block_edge_in_texel>
|
|
|
|
|
std::vector<MipmapLevelInfo> copy_texture_data(void *dst, const void *src, size_t width_in_texel, size_t height_in_texel, size_t depth, size_t mipmap_count)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
|
|
|
|
std::vector<MipmapLevelInfo> Result;
|
|
|
|
|
size_t offsetInDst = 0, offsetInSrc = 0;
|
2015-12-19 00:32:53 +01:00
|
|
|
size_t texture_height_in_block = (height_in_texel + block_edge_in_texel - 1) / block_edge_in_texel;
|
|
|
|
|
size_t texture_width_in_block = (width_in_texel + block_edge_in_texel - 1) / block_edge_in_texel;
|
2015-12-07 22:09:18 +01:00
|
|
|
for (unsigned depth_level = 0; depth_level < depth; depth_level++)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
2015-12-19 00:32:53 +01:00
|
|
|
size_t miplevel_height_in_block = texture_height_in_block, miplevel_width_in_block = texture_width_in_block;
|
|
|
|
|
for (unsigned mip_level = 0; mip_level < mipmap_count; mip_level++)
|
2015-12-07 22:09:18 +01:00
|
|
|
{
|
|
|
|
|
size_t dst_pitch = align(miplevel_width_in_block * block_size_in_bytes, 256) / block_size_in_bytes;
|
|
|
|
|
|
|
|
|
|
MipmapLevelInfo currentMipmapLevelInfo = {};
|
|
|
|
|
currentMipmapLevelInfo.offset = offsetInDst;
|
|
|
|
|
currentMipmapLevelInfo.height = miplevel_height_in_block * block_edge_in_texel;
|
|
|
|
|
currentMipmapLevelInfo.width = miplevel_width_in_block * block_edge_in_texel;
|
|
|
|
|
currentMipmapLevelInfo.rowPitch = dst_pitch * block_size_in_bytes;
|
|
|
|
|
Result.push_back(currentMipmapLevelInfo);
|
|
|
|
|
|
2015-12-19 00:32:53 +01:00
|
|
|
if (!padded_row)
|
|
|
|
|
{
|
|
|
|
|
T::template copy_mipmap_level<block_size_in_bytes>((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, dst_pitch, miplevel_width_in_block);
|
|
|
|
|
offsetInSrc += miplevel_height_in_block * miplevel_width_in_block * block_size_in_bytes;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
T::template copy_mipmap_level<block_size_in_bytes>((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, dst_pitch, texture_width_in_block);
|
|
|
|
|
offsetInSrc += miplevel_height_in_block * texture_width_in_block * block_size_in_bytes;
|
|
|
|
|
}
|
2015-12-07 22:09:18 +01:00
|
|
|
offsetInDst += align(miplevel_height_in_block * dst_pitch * block_size_in_bytes, 512);
|
|
|
|
|
miplevel_height_in_block = MAX2(miplevel_height_in_block / 2, 1);
|
|
|
|
|
miplevel_width_in_block = MAX2(miplevel_width_in_block / 2, 1);
|
|
|
|
|
}
|
2015-12-10 02:52:27 +01:00
|
|
|
offsetInSrc = align(offsetInSrc, 128);
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 01:11:40 +01:00
|
|
|
/**
|
|
|
|
|
* A texture is stored as an array of blocks, where a block is a pixel for standard texture
|
|
|
|
|
* but is a structure containing several pixels for compressed format
|
|
|
|
|
*/
|
2015-12-17 18:31:27 +01:00
|
|
|
size_t get_texture_block_size(u32 format)
|
2015-09-28 22:33:29 +02:00
|
|
|
{
|
|
|
|
|
switch (format)
|
|
|
|
|
{
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_B8: return 1;
|
|
|
|
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
|
|
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G6B5: return 2;
|
|
|
|
|
case CELL_GCM_TEXTURE_A8R8G8B8: return 4;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return 8;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return 16;
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return 16;
|
|
|
|
|
case CELL_GCM_TEXTURE_G8B8: return 2;
|
|
|
|
|
case CELL_GCM_TEXTURE_R6G5B5:
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return 4;
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16:
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
|
|
|
|
case CELL_GCM_TEXTURE_X16: return 2;
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16: return 4;
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G5B5A1: return 2;
|
|
|
|
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return 8;
|
|
|
|
|
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return 16;
|
|
|
|
|
case CELL_GCM_TEXTURE_X32_FLOAT: return 4;
|
|
|
|
|
case CELL_GCM_TEXTURE_D1R5G5B5: return 2;
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
|
|
|
|
case CELL_GCM_TEXTURE_D8R8G8B8:
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
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:
|
2015-12-17 18:31:27 +01:00
|
|
|
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format);
|
2015-10-27 01:11:40 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
size_t get_texture_block_edge(u32 format)
|
2015-10-27 01:11:40 +01:00
|
|
|
{
|
|
|
|
|
switch (format)
|
|
|
|
|
{
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_B8:
|
|
|
|
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
|
|
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G6B5:
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_A8R8G8B8: return 1;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
|
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_G8B8:
|
|
|
|
|
case CELL_GCM_TEXTURE_R6G5B5:
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16:
|
|
|
|
|
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
|
|
|
|
case CELL_GCM_TEXTURE_X16:
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16:
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G5B5A1:
|
|
|
|
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
|
|
|
|
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
|
|
|
|
case CELL_GCM_TEXTURE_X32_FLOAT:
|
|
|
|
|
case CELL_GCM_TEXTURE_D1R5G5B5:
|
|
|
|
|
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_D8R8G8B8: return 1;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return 2;
|
|
|
|
|
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:
|
2015-12-17 18:31:27 +01:00
|
|
|
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format);
|
2015-10-27 01:11:40 +01:00
|
|
|
return 0;
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
2015-10-27 01:11:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t rowPitchAlignement)
|
2015-10-27 01:11:40 +01:00
|
|
|
{
|
|
|
|
|
size_t w = texture.width(), h = texture.height();
|
|
|
|
|
|
|
|
|
|
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
|
|
|
|
size_t blockEdge = get_texture_block_edge(format);
|
|
|
|
|
size_t blockSizeInByte = get_texture_block_size(format);
|
2015-09-28 22:33:29 +02:00
|
|
|
|
2015-10-27 01:11:40 +01:00
|
|
|
size_t heightInBlocks = (h + blockEdge - 1) / blockEdge;
|
|
|
|
|
size_t widthInBlocks = (w + blockEdge - 1) / blockEdge;
|
2015-09-28 22:33:29 +02:00
|
|
|
|
|
|
|
|
size_t rowPitch = align(blockSizeInByte * widthInBlocks, rowPitchAlignement);
|
|
|
|
|
|
2015-12-07 22:09:18 +01:00
|
|
|
return rowPitch * heightInBlocks * (texture.cubemap() ? 6 : 1) * 2; // * 2 for mipmap levels
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
std::vector<MipmapLevelInfo> upload_placed_texture(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-12-07 22:09:18 +01:00
|
|
|
size_t depth = texture.depth();
|
2015-12-19 18:49:03 +01:00
|
|
|
if (depth == 0) depth = 1;
|
2015-12-10 02:52:27 +01:00
|
|
|
if (texture.cubemap()) depth *= 6;
|
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
|
|
|
|
2015-10-27 01:11:40 +01:00
|
|
|
std::vector<MipmapLevelInfo> mipInfos;
|
|
|
|
|
|
|
|
|
|
const u32 texaddr = rsx::get_address(texture.offset(), texture.location());
|
|
|
|
|
auto pixels = vm::ps3::_ptr<const u8>(texaddr);
|
|
|
|
|
bool is_swizzled = !(texture.format() & CELL_GCM_TEXTURE_LN);
|
|
|
|
|
switch (format)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
|
|
|
|
if (is_swizzled)
|
2015-12-19 00:32:53 +01:00
|
|
|
return copy_texture_data<texel_rgba_swizzled, false, 4, 1>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
else
|
2015-12-19 00:32:53 +01:00
|
|
|
return copy_texture_data<texel_rgba, true, 4, 1>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
|
|
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
|
|
|
case CELL_GCM_TEXTURE_R5G6B5:
|
|
|
|
|
if (is_swizzled)
|
2015-12-19 00:32:53 +01:00
|
|
|
return copy_texture_data<texel_16b_swizzled, false, 2, 1>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
else
|
2015-12-19 00:32:53 +01:00
|
|
|
return copy_texture_data<texel_16b_format, true, 2, 1>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
2015-12-19 00:32:53 +01:00
|
|
|
return copy_texture_data<texel_16bX4_format, true, 8, 1>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
2015-12-19 00:32:53 +01:00
|
|
|
if (is_swizzled)
|
|
|
|
|
return copy_texture_data<texel_bc_format, false, 8, 4>(textureData, pixels, w, h, depth, texture.mipmap());
|
|
|
|
|
else
|
|
|
|
|
return copy_texture_data<texel_bc_format, true, 8, 4>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
2015-12-19 00:32:53 +01:00
|
|
|
if (is_swizzled)
|
|
|
|
|
return copy_texture_data<texel_bc_format, false, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
|
|
|
|
|
else
|
|
|
|
|
return copy_texture_data<texel_bc_format, true, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
2015-12-19 00:32:53 +01:00
|
|
|
if (is_swizzled)
|
|
|
|
|
return copy_texture_data<texel_bc_format, false, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
|
|
|
|
|
else
|
|
|
|
|
return copy_texture_data<texel_bc_format, true, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-12-07 22:09:18 +01:00
|
|
|
case CELL_GCM_TEXTURE_B8:
|
2015-12-19 00:32:53 +01:00
|
|
|
return copy_texture_data<texel_rgba, true, 1, 1>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
default:
|
2015-12-19 00:32:53 +01:00
|
|
|
return copy_texture_data<texel_rgba, true, 4, 1>(textureData, pixels, w, h, depth, texture.mipmap());
|
2015-10-27 01:11:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
size_t get_texture_size(const rsx::texture &texture)
|
2015-10-27 01:11:40 +01:00
|
|
|
{
|
|
|
|
|
size_t w = texture.width(), h = texture.height();
|
|
|
|
|
|
|
|
|
|
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
|
|
|
|
// TODO: Take mipmaps into account
|
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:
|
2015-12-17 18:31:27 +01:00
|
|
|
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format);
|
2015-10-27 01:11:40 +01:00
|
|
|
return 0;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_B8:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_R5G6B5:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h / 6;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h / 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h / 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_G8B8:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_R6G5B5:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_DEPTH16:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_X16:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_Y16_X16:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_R5G5B5A1:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 8;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 16;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_X32_FLOAT:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_D1R5G5B5:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 2;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_D8R8G8B8:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
2015-10-27 01:11:40 +01:00
|
|
|
return w * h * 4;
|
2015-09-28 22:33:29 +02:00
|
|
|
}
|
2015-12-17 18:31:27 +01:00
|
|
|
}
|