mirror of
https://github.com/xemu-project/nxdk_pgraph_tests.git
synced 2024-11-27 03:50:22 +00:00
Adds test for volumetric palettized texture.
This commit is contained in:
parent
739629eb05
commit
10d3599244
@ -67,7 +67,7 @@ void ShaderProgram::LoadUntexturedPixelShader() {
|
||||
|
||||
void ShaderProgram::DisablePixelShader() {
|
||||
uint32_t *p = pb_begin();
|
||||
p = pb_push1(p, NV097_SET_SHADER_STAGE_PROGRAM, NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_PROGRAM_NONE);
|
||||
p = pb_push1(p, NV097_SET_SHADER_STAGE_PROGRAM, 0);
|
||||
pb_end(p);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,8 @@ TestHost::TestHost(uint32_t framebuffer_width, uint32_t framebuffer_height, uint
|
||||
static constexpr uint32_t kMaxPaletteSize = 256 * 4;
|
||||
uint32_t palette_size = kMaxPaletteSize * 4;
|
||||
|
||||
uint32_t total_size = texture_size + palette_size;
|
||||
static constexpr uint32_t kMaxTextures = 4;
|
||||
uint32_t total_size = texture_size * kMaxTextures + palette_size;
|
||||
|
||||
texture_memory_ = static_cast<uint8_t *>(
|
||||
MmAllocateContiguousMemoryEx(total_size, 0, MAXRAM, 0, PAGE_WRITECOMBINE | PAGE_READWRITE));
|
||||
@ -809,8 +810,8 @@ void TestHost::SetupControl0() const {
|
||||
|
||||
void TestHost::SetupTextureStages() const {
|
||||
// TODO: Support texture memory that is not allocated from the base of the DMA target registered by pbkit.
|
||||
uint32_t texture_dma_offset = reinterpret_cast<uint32_t>(texture_memory_);
|
||||
uint32_t palette_dma_offset = reinterpret_cast<uint32_t>(texture_palette_memory_);
|
||||
auto texture_dma_offset = reinterpret_cast<uint32_t>(texture_memory_);
|
||||
auto palette_dma_offset = reinterpret_cast<uint32_t>(texture_palette_memory_);
|
||||
for (auto &stage : texture_stage_) {
|
||||
stage.Commit(texture_dma_offset, palette_dma_offset);
|
||||
}
|
||||
@ -818,6 +819,10 @@ void TestHost::SetupTextureStages() const {
|
||||
|
||||
void TestHost::SetTextureFormat(const TextureFormatInfo &fmt, uint32_t stage) { texture_stage_[stage].SetFormat(fmt); }
|
||||
|
||||
void TestHost::SetDefaultTextureParams(uint32_t stage) {
|
||||
texture_stage_[stage].SetDimensions(max_texture_width_, max_texture_height_);
|
||||
}
|
||||
|
||||
void TestHost::SetDepthBufferFormat(uint32_t fmt) {
|
||||
depth_buffer_format_ = fmt;
|
||||
|
||||
@ -841,15 +846,20 @@ int TestHost::SetTexture(SDL_Surface *surface, uint32_t stage) {
|
||||
return texture_stage_[stage].SetTexture(surface, texture_memory_);
|
||||
}
|
||||
|
||||
int TestHost::SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t pitch,
|
||||
uint32_t bytes_per_pixel, bool swizzle, uint32_t stage) {
|
||||
uint32_t max_stride = max_texture_width_ * 4;
|
||||
uint32_t max_texture_size = max_stride * max_texture_height_ * max_texture_depth_;
|
||||
int TestHost::SetVolumetricTexture(const SDL_Surface **surface, uint32_t depth, uint32_t stage) {
|
||||
return texture_stage_[stage].SetVolumetricTexture(surface, depth, texture_memory_);
|
||||
}
|
||||
|
||||
uint32_t surface_size = pitch * height;
|
||||
int TestHost::SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t depth, uint32_t pitch,
|
||||
uint32_t bytes_per_pixel, bool swizzle, uint32_t stage) {
|
||||
const uint32_t max_stride = max_texture_width_ * 4;
|
||||
const uint32_t max_texture_size = max_stride * max_texture_height_ * max_texture_depth_;
|
||||
|
||||
const uint32_t layer_size = pitch * height;
|
||||
const uint32_t surface_size = layer_size * depth;
|
||||
ASSERT(surface_size < max_texture_size && "Texture too large.");
|
||||
|
||||
return texture_stage_[stage].SetRawTexture(source, width, height, pitch, bytes_per_pixel, swizzle, texture_memory_);
|
||||
return texture_stage_[stage].SetRawTexture(source, width, height, depth, pitch, bytes_per_pixel, swizzle, texture_memory_);
|
||||
}
|
||||
|
||||
int TestHost::SetPalette(const uint32_t *palette, PaletteSize size, uint32_t stage) {
|
||||
@ -1300,6 +1310,25 @@ void TestHost::SetFinalCombiner1(TestHost::CombinerSource e_source, bool e_alpha
|
||||
pb_end(p);
|
||||
}
|
||||
|
||||
void TestHost::SetShaderStageProgram(ShaderStageProgram stage_0, ShaderStageProgram stage_1, ShaderStageProgram stage_2,
|
||||
ShaderStageProgram stage_3) const {
|
||||
auto p = pb_begin();
|
||||
p = pb_push1(
|
||||
p, NV097_SET_SHADER_STAGE_PROGRAM,
|
||||
MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE0, stage_0) | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE1, stage_1) |
|
||||
MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE2, stage_2) | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE3, stage_3));
|
||||
pb_end(p);
|
||||
}
|
||||
|
||||
void TestHost::SetShaderStageInput(uint32_t stage_2_input, uint32_t stage_3_input) const {
|
||||
auto p = pb_begin();
|
||||
p = pb_push1(p, NV097_SET_SHADER_OTHER_STAGE_INPUT,
|
||||
MASK(NV097_SET_SHADER_OTHER_STAGE_INPUT_STAGE1, 0) |
|
||||
MASK(NV097_SET_SHADER_OTHER_STAGE_INPUT_STAGE2, stage_2_input) |
|
||||
MASK(NV097_SET_SHADER_OTHER_STAGE_INPUT_STAGE3, stage_3_input));
|
||||
pb_end(p);
|
||||
}
|
||||
|
||||
static void SetVertexAttribute(uint32_t index, uint32_t format, uint32_t size, uint32_t stride, const void *data) {
|
||||
uint32_t *p = pb_begin();
|
||||
p = pb_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4,
|
||||
|
@ -128,6 +128,28 @@ class TestHost {
|
||||
PALETTE_256 = 256,
|
||||
};
|
||||
|
||||
enum ShaderStageProgram {
|
||||
STAGE_NONE = 0,
|
||||
STAGE_2D_PROJECTIVE,
|
||||
STAGE_3D_PROJECTIVE,
|
||||
STAGE_CUBE_MAP,
|
||||
STAGE_PASS_THROUGH,
|
||||
STAGE_CLIP_PLANE,
|
||||
STAGE_BUMPENVMAP,
|
||||
STAGE_BUMPENVMAP_LUMINANCE,
|
||||
STAGE_BRDF,
|
||||
STAGE_DOT_ST,
|
||||
STAGE_DOT_ZW,
|
||||
STAGE_DOT_REFLECT_DIFFUSE,
|
||||
STAGE_DOT_REFLECT_SPECULAR,
|
||||
STAGE_DOT_STR_3D,
|
||||
STAGE_DOT_STR_CUBE,
|
||||
STAGE_DEPENDENT_AR,
|
||||
STAGE_DEPENDENT_GB,
|
||||
STAGE_DOT_PRODUCT,
|
||||
STAGE_DOT_REFLECT_SPECULAR_CONST,
|
||||
};
|
||||
|
||||
public:
|
||||
TestHost(uint32_t framebuffer_width, uint32_t framebuffer_height, uint32_t max_texture_width,
|
||||
uint32_t max_texture_height, uint32_t max_texture_depth = 16);
|
||||
@ -135,9 +157,11 @@ class TestHost {
|
||||
|
||||
TextureStage &GetTextureStage(uint32_t stage) { return texture_stage_[stage]; }
|
||||
void SetTextureFormat(const TextureFormatInfo &fmt, uint32_t stage = 0);
|
||||
void SetDefaultTextureParams(uint32_t stage = 0);
|
||||
int SetTexture(SDL_Surface *surface, uint32_t stage = 0);
|
||||
int SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t pitch, uint32_t bytes_per_pixel,
|
||||
bool swizzle, uint32_t stage = 0);
|
||||
int SetVolumetricTexture(const SDL_Surface **surface, uint32_t depth, uint32_t stage = 0);
|
||||
int SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t depth, uint32_t pitch,
|
||||
uint32_t bytes_per_pixel, bool swizzle, uint32_t stage = 0);
|
||||
|
||||
int SetPalette(const uint32_t *palette, PaletteSize size, uint32_t stage = 0);
|
||||
void SetTextureStageEnabled(uint32_t stage, bool enabled = true);
|
||||
@ -282,6 +306,12 @@ class TestHost {
|
||||
bool specular_add_invert_r12 = false, bool specular_add_invert_r5 = false,
|
||||
bool specular_clamp = false) const;
|
||||
|
||||
void SetShaderStageProgram(ShaderStageProgram stage_0, ShaderStageProgram stage_1 = STAGE_NONE,
|
||||
ShaderStageProgram stage_2 = STAGE_NONE, ShaderStageProgram stage_3 = STAGE_NONE) const;
|
||||
// Sets the input for shader stage 2 and 3. The value is the 0 based index of the stage whose output should be linked.
|
||||
// E.g., to have stage2 use stage1's input and stage3 use stage2's the params would be (1, 2).
|
||||
void SetShaderStageInput(uint32_t stage_2_input = 0, uint32_t stage_3_input = 0) const;
|
||||
|
||||
void SetVertexBufferAttributes(uint32_t enabled_fields);
|
||||
|
||||
private:
|
||||
|
@ -39,9 +39,15 @@ void TestSuite::RunAll() {
|
||||
}
|
||||
|
||||
void TestSuite::SetDefaultTextureFormat() const {
|
||||
// NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8
|
||||
const TextureFormatInfo& texture_format = kTextureFormats[3];
|
||||
host_.SetTextureFormat(texture_format);
|
||||
const TextureFormatInfo& texture_format = GetTextureFormatInfo(NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8);
|
||||
host_.SetTextureFormat(texture_format, 0);
|
||||
host_.SetDefaultTextureParams(0);
|
||||
host_.SetTextureFormat(texture_format, 1);
|
||||
host_.SetDefaultTextureParams(1);
|
||||
host_.SetTextureFormat(texture_format, 2);
|
||||
host_.SetDefaultTextureParams(2);
|
||||
host_.SetTextureFormat(texture_format, 3);
|
||||
host_.SetDefaultTextureParams(3);
|
||||
}
|
||||
|
||||
void TestSuite::Initialize() {
|
||||
@ -160,4 +166,6 @@ void TestSuite::Initialize() {
|
||||
|
||||
SetDefaultTextureFormat();
|
||||
host_.SetTextureStageEnabled(0, false);
|
||||
host_.SetShaderStageProgram(TestHost::STAGE_2D_PROJECTIVE);
|
||||
host_.SetShaderStageInput(0, 0);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ TextureFormatTests::TextureFormatTests(TestHost &host, std::string output_dir)
|
||||
std::string name = MakeTestName(format);
|
||||
|
||||
if (format.xbox_format != NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8) {
|
||||
tests_[name] = [this, format]() { this->Test(format); };
|
||||
tests_[name] = [this, format]() { Test(format); };
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ void TextureFormatTests::TestPalettized(TestHost::PaletteSize size) {
|
||||
(int)host_.GetMaxTextureHeight(), size);
|
||||
ASSERT(!err && "Failed to generate palettized surface");
|
||||
|
||||
err = host_.SetRawTexture(gradient_surface, host_.GetMaxTextureWidth(), host_.GetMaxTextureHeight(),
|
||||
err = host_.SetRawTexture(gradient_surface, host_.GetMaxTextureWidth(), host_.GetMaxTextureHeight(), 1,
|
||||
host_.GetMaxTextureWidth(), 1, texture_format.xbox_swizzled);
|
||||
delete[] gradient_surface;
|
||||
ASSERT(!err && "Failed to set texture");
|
||||
@ -126,6 +126,9 @@ void TextureFormatTests::TestPalettized(TestHost::PaletteSize size) {
|
||||
std::string TextureFormatTests::MakeTestName(const TextureFormatInfo &texture_format) {
|
||||
std::string test_name = "TexFmt_";
|
||||
test_name += texture_format.name;
|
||||
if (!texture_format.xbox_swizzled) {
|
||||
test_name += "_L";
|
||||
}
|
||||
return std::move(test_name);
|
||||
}
|
||||
|
||||
@ -154,12 +157,13 @@ static int GenerateGradientSurface(SDL_Surface **gradient_surface, int width, in
|
||||
}
|
||||
|
||||
auto pixels = static_cast<uint32_t *>((*gradient_surface)->pixels);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x, ++pixels) {
|
||||
int x_normal = static_cast<int>(static_cast<float>(x) * 255.0f / static_cast<float>(width));
|
||||
int y_normal = static_cast<int>(static_cast<float>(y) * 255.0f / static_cast<float>(height));
|
||||
*pixels = SDL_MapRGBA((*gradient_surface)->format, y_normal, x_normal, 255 - y_normal, x_normal + y_normal);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(*gradient_surface);
|
||||
|
||||
|
@ -6,25 +6,36 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "debug_output.h"
|
||||
#include "shaders/perspective_vertex_shader.h"
|
||||
#include "test_host.h"
|
||||
#include "texture_format.h"
|
||||
#include "vertex_buffer.h"
|
||||
|
||||
static int generate_gradient_surface(SDL_Surface **gradient_surface, int width, int height);
|
||||
static int GenerateSurface(SDL_Surface **gradient_surface, int width, int height, int layer);
|
||||
static int GeneratePalettizedSurface(uint8_t **ret, uint32_t width, uint32_t height, uint32_t depth,
|
||||
TestHost::PaletteSize palette_size);
|
||||
static uint32_t *GeneratePalette(TestHost::PaletteSize size);
|
||||
|
||||
static const VolumeTextureTests::TestConfig kTestConfigs[] = {
|
||||
{"Indexed", GetTextureFormatInfo(NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8B8G8R8), false},
|
||||
};
|
||||
|
||||
static constexpr const char *kTestName = "Palettized";
|
||||
static constexpr uint32_t kBackgroundColor = 0xFE202020;
|
||||
static const uint32_t kTextureDepth = 4;
|
||||
|
||||
VolumeTextureTests::VolumeTextureTests(TestHost &host, std::string output_dir)
|
||||
: TestSuite(host, std::move(output_dir), "Volume texture") {
|
||||
for (auto &config : kTestConfigs) {
|
||||
tests_[kTestName] = [this, &config]() { Test(config); };
|
||||
for (auto i = 0; i < kNumFormats; ++i) {
|
||||
auto &format = kTextureFormats[i];
|
||||
if (!format.xbox_swizzled) {
|
||||
// Linear volumetric formats are not supported by the hardware.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (format.xbox_format != NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8) {
|
||||
tests_[format.name] = [this, format]() { Test(format); };
|
||||
}
|
||||
}
|
||||
|
||||
auto palettized = GetTextureFormatInfo(NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8);
|
||||
tests_[palettized.name] = [this]() { TestPalettized(); };
|
||||
}
|
||||
|
||||
void VolumeTextureTests::Initialize() {
|
||||
@ -34,6 +45,22 @@ void VolumeTextureTests::Initialize() {
|
||||
host_.SetShaderProgram(nullptr);
|
||||
CreateGeometry();
|
||||
host_.SetXDKDefaultViewportAndFixedFunctionMatrices();
|
||||
host_.SetTextureStageEnabled(0, true);
|
||||
|
||||
host_.SetShaderStageProgram(TestHost::STAGE_3D_PROJECTIVE);
|
||||
|
||||
host_.SetInputColorCombiner(0, TestHost::SRC_TEX0, false, TestHost::MAP_UNSIGNED_IDENTITY, TestHost::SRC_ZERO, false,
|
||||
TestHost::MAP_UNSIGNED_INVERT);
|
||||
host_.SetInputAlphaCombiner(0, TestHost::SRC_TEX0, true, TestHost::MAP_UNSIGNED_IDENTITY, TestHost::SRC_ZERO, false,
|
||||
TestHost::MAP_UNSIGNED_INVERT);
|
||||
|
||||
host_.SetOutputColorCombiner(0, TestHost::DST_DIFFUSE);
|
||||
host_.SetOutputAlphaCombiner(0, TestHost::DST_DIFFUSE);
|
||||
|
||||
host_.SetFinalCombiner0(TestHost::SRC_ZERO, false, false, TestHost::SRC_ZERO, false, false, TestHost::SRC_ZERO, false,
|
||||
false, TestHost::SRC_DIFFUSE);
|
||||
host_.SetFinalCombiner1(TestHost::SRC_ZERO, false, false, TestHost::SRC_ZERO, false, false, TestHost::SRC_DIFFUSE,
|
||||
true);
|
||||
}
|
||||
|
||||
void VolumeTextureTests::CreateGeometry() {
|
||||
@ -85,41 +112,79 @@ void VolumeTextureTests::CreateGeometry() {
|
||||
buffer->Linearize(static_cast<float>(host_.GetMaxTextureWidth()), static_cast<float>(host_.GetMaxTextureHeight()));
|
||||
}
|
||||
|
||||
void VolumeTextureTests::Test(const TestConfig &config) {
|
||||
static constexpr uint32_t kBackgroundColor = 0xFF303030;
|
||||
host_.PrepareDraw(kBackgroundColor);
|
||||
// host_.SetTextureFormat(GetTextureFormatInfo(NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8));
|
||||
void VolumeTextureTests::Test(const TextureFormatInfo &texture_format) {
|
||||
host_.SetTextureFormat(texture_format);
|
||||
|
||||
// SDL_Surface *gradient_surface;
|
||||
// int update_texture_result =
|
||||
// GenerateGradientSurface(&gradient_surface, host_.GetMaxTextureWidth(), host_.GetMaxTextureHeight());
|
||||
// if (!update_texture_result) {
|
||||
// update_texture_result = host_.SetTexture(gradient_surface);
|
||||
// SDL_FreeSurface(gradient_surface);
|
||||
// } else {
|
||||
// pb_print("FAILED TO GENERATE SDL SURFACE - TEST IS INVALID: %d\n", update_texture_result);
|
||||
// pb_draw_text_screen();
|
||||
// host_.FinishDraw(false, "", "");
|
||||
// return;
|
||||
// }
|
||||
const uint32_t width = host_.GetMaxTextureWidth();
|
||||
const uint32_t height = host_.GetMaxTextureHeight();
|
||||
|
||||
auto **layers = new SDL_Surface *[kTextureDepth];
|
||||
|
||||
for (auto d = 0; d < kTextureDepth; ++d) {
|
||||
int update_texture_result = GenerateSurface(&layers[d], (int)width, (int)height, d);
|
||||
ASSERT(!update_texture_result && "Failed to generate SDL surface");
|
||||
}
|
||||
|
||||
int update_texture_result = host_.SetVolumetricTexture((const SDL_Surface **)layers, kTextureDepth);
|
||||
ASSERT(!update_texture_result && "Failed to set texture");
|
||||
|
||||
for (auto d = 0; d < kTextureDepth; ++d) {
|
||||
SDL_FreeSurface(layers[d]);
|
||||
}
|
||||
delete[] layers;
|
||||
|
||||
auto &stage = host_.GetTextureStage(0);
|
||||
stage.SetDimensions(width, height, kTextureDepth);
|
||||
|
||||
host_.PrepareDraw(kBackgroundColor);
|
||||
host_.DrawArrays();
|
||||
|
||||
pb_print("N: %s\n", texture_format.name);
|
||||
pb_print("F: 0x%x\n", texture_format.xbox_format);
|
||||
pb_print("SZ: %d\n", texture_format.xbox_swizzled);
|
||||
pb_print("C: %d\n", texture_format.require_conversion);
|
||||
pb_draw_text_screen();
|
||||
|
||||
host_.FinishDraw(allow_saving_, output_dir_, texture_format.name);
|
||||
}
|
||||
|
||||
void VolumeTextureTests::TestPalettized() {
|
||||
host_.PrepareDraw(kBackgroundColor);
|
||||
|
||||
TestHost::PaletteSize palette_size = TestHost::PALETTE_256;
|
||||
auto &texture_format = GetTextureFormatInfo(NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8);
|
||||
host_.SetTextureFormat(texture_format);
|
||||
|
||||
uint8_t *surface = nullptr;
|
||||
const uint32_t width = host_.GetMaxTextureWidth();
|
||||
const uint32_t height = host_.GetMaxTextureHeight();
|
||||
int err = GeneratePalettizedSurface(&surface, width, height, kTextureDepth, palette_size);
|
||||
ASSERT(!err && "Failed to generate palettized surface");
|
||||
|
||||
err = host_.SetRawTexture(surface, width, height, kTextureDepth, width, 1, texture_format.xbox_swizzled);
|
||||
delete[] surface;
|
||||
ASSERT(!err && "Failed to set texture");
|
||||
|
||||
auto stage = host_.GetTextureStage(0);
|
||||
stage.SetDimensions(width, height, kTextureDepth);
|
||||
|
||||
auto palette = GeneratePalette(palette_size);
|
||||
err = host_.SetPalette(palette, palette_size);
|
||||
delete[] palette;
|
||||
ASSERT(!err && "Failed to set palette");
|
||||
|
||||
host_.DrawArrays();
|
||||
|
||||
// /* PrepareDraw some text on the screen */
|
||||
pb_print("N: %s\n", config.format.name);
|
||||
pb_print("F: 0x%x\n", config.format.xbox_format);
|
||||
pb_print("SZ: %d\n", config.format.xbox_swizzled);
|
||||
pb_print("C: %d\n", config.format.require_conversion);
|
||||
// pb_print("W: %d\n", host_.GetMaxTextureWidth());
|
||||
// pb_print("H: %d\n", host_.GetMaxTextureHeight());
|
||||
// pb_print("P: %d\n", texture_format.xbox_bpp * host_.GetMaxTextureWidth());
|
||||
// pb_print("ERR: %d\n", update_texture_result);
|
||||
pb_print("N: %s\n", texture_format.name);
|
||||
pb_print("F: 0x%x\n", texture_format.xbox_format);
|
||||
pb_print("SZ: %d\n", texture_format.xbox_swizzled);
|
||||
pb_print("C: %d\n", texture_format.require_conversion);
|
||||
pb_draw_text_screen();
|
||||
|
||||
host_.FinishDraw(allow_saving_, output_dir_, config.name);
|
||||
host_.FinishDraw(allow_saving_, output_dir_, texture_format.name);
|
||||
}
|
||||
|
||||
static int generate_gradient_surface(SDL_Surface **gradient_surface, int width, int height) {
|
||||
static int GenerateSurface(SDL_Surface **gradient_surface, int width, int height, int layer) {
|
||||
*gradient_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGBA8888);
|
||||
if (!(*gradient_surface)) {
|
||||
return 1;
|
||||
@ -131,19 +196,68 @@ static int generate_gradient_surface(SDL_Surface **gradient_surface, int width,
|
||||
return 2;
|
||||
}
|
||||
|
||||
uint32_t red_mask = 0xFF;
|
||||
uint32_t green_mask = 0xFF;
|
||||
uint32_t blue_mask = 0xFF;
|
||||
|
||||
layer %= 4;
|
||||
|
||||
if (layer == 1) {
|
||||
red_mask = 0;
|
||||
green_mask = 0;
|
||||
} else if (layer == 2) {
|
||||
green_mask = 0;
|
||||
blue_mask = 0;
|
||||
} else if (layer == 3) {
|
||||
red_mask = 0;
|
||||
blue_mask = 0;
|
||||
}
|
||||
|
||||
auto pixels = static_cast<uint32_t *>((*gradient_surface)->pixels);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x, ++pixels) {
|
||||
int x_normal = static_cast<int>(static_cast<float>(x) * 255.0f / static_cast<float>(width));
|
||||
int y_normal = static_cast<int>(static_cast<float>(y) * 255.0f / static_cast<float>(height));
|
||||
*pixels = SDL_MapRGBA((*gradient_surface)->format, y_normal, x_normal, 255 - y_normal, x_normal + y_normal);
|
||||
*pixels = SDL_MapRGBA((*gradient_surface)->format, y_normal & red_mask, x_normal & green_mask,
|
||||
(255 - y_normal) & blue_mask, x_normal + y_normal);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(*gradient_surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GeneratePalettizedSurface(uint8_t **ret, uint32_t width, uint32_t height, uint32_t depth,
|
||||
TestHost::PaletteSize palette_size) {
|
||||
*ret = new uint8_t[width * height * depth];
|
||||
if (!(*ret)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto pixel = *ret;
|
||||
|
||||
for (auto d = 0; d < depth; ++d) {
|
||||
uint32_t layer_size = width * height;
|
||||
|
||||
uint32_t half_size = layer_size >> 1;
|
||||
|
||||
for (uint32_t i = 0; i < half_size; ++i, ++pixel) {
|
||||
*pixel = (d << 2) & (palette_size - 1);
|
||||
}
|
||||
|
||||
for (uint32_t i = half_size; i < layer_size; i += 4) {
|
||||
uint8_t value = (i + (d << 2)) & (palette_size - 1);
|
||||
*pixel++ = value;
|
||||
*pixel++ = value;
|
||||
*pixel++ = value;
|
||||
*pixel++ = value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t *GeneratePalette(TestHost::PaletteSize size) {
|
||||
auto ret = new uint32_t[size];
|
||||
|
||||
@ -160,4 +274,4 @@ static uint32_t *GeneratePalette(TestHost::PaletteSize size) {
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,8 @@
|
||||
|
||||
class TestHost;
|
||||
|
||||
// Tests 3d texture behavior.
|
||||
class VolumeTextureTests : public TestSuite {
|
||||
public:
|
||||
struct TestConfig {
|
||||
char name[30]{0};
|
||||
TextureFormatInfo format;
|
||||
bool is_palettized{false};
|
||||
};
|
||||
|
||||
public:
|
||||
VolumeTextureTests(TestHost &host, std::string output_dir);
|
||||
|
||||
@ -23,7 +17,9 @@ class VolumeTextureTests : public TestSuite {
|
||||
|
||||
private:
|
||||
void CreateGeometry();
|
||||
void Test(const TestConfig &config);
|
||||
|
||||
void Test(const TextureFormatInfo &texture_format);
|
||||
void TestPalettized();
|
||||
};
|
||||
|
||||
#endif // NXDK_PGRAPH_TESTS_VOLUME_TEXTURE_TESTS_H
|
||||
|
@ -30,16 +30,12 @@ void TextureStage::Commit(uint32_t memory_dma_offset, uint32_t palette_dma_offse
|
||||
|
||||
uint32_t dimensionality = GetDimensionality();
|
||||
|
||||
uint32_t size_u = 0;
|
||||
uint32_t size_v = 0;
|
||||
uint32_t size_u = bsf((int)width_);
|
||||
uint32_t size_v = bsf((int)height_);
|
||||
uint32_t size_p = 0;
|
||||
// if (format_.xbox_swizzled) {
|
||||
size_u = bsf((int)width_);
|
||||
size_v = bsf((int)height_);
|
||||
if (dimensionality > 2) {
|
||||
size_p = bsf((int)depth_);
|
||||
}
|
||||
// }
|
||||
|
||||
const uint32_t DMA_A = 1;
|
||||
const uint32_t DMA_B = 2;
|
||||
@ -96,10 +92,11 @@ void TextureStage::Commit(uint32_t memory_dma_offset, uint32_t palette_dma_offse
|
||||
|
||||
int TextureStage::SetTexture(const SDL_Surface *surface, uint8_t *memory_base) const {
|
||||
auto pixels = static_cast<uint32_t *>(surface->pixels);
|
||||
uint8_t *dest = memory_base + texture_memory_offset_;
|
||||
|
||||
// if conversion required, do so, otherwise use SDL to convert
|
||||
if (format_.require_conversion) {
|
||||
uint8_t *dest = memory_base + texture_memory_offset_;
|
||||
|
||||
// TODO: potential reference material -
|
||||
// https://github.com/scalablecory/colors/blob/master/color.c
|
||||
switch (format_.xbox_format) {
|
||||
@ -156,21 +153,72 @@ int TextureStage::SetTexture(const SDL_Surface *surface, uint8_t *memory_base) c
|
||||
return 4;
|
||||
}
|
||||
|
||||
SetRawTexture((const uint8_t *)new_surf->pixels, new_surf->w, new_surf->h, new_surf->pitch,
|
||||
SetRawTexture((const uint8_t *)new_surf->pixels, new_surf->w, new_surf->h, 1, new_surf->pitch,
|
||||
new_surf->format->BytesPerPixel, format_.xbox_swizzled, memory_base);
|
||||
|
||||
SDL_FreeSurface(new_surf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TextureStage::SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t pitch,
|
||||
int TextureStage::SetVolumetricTexture(const SDL_Surface **layers, uint32_t depth, uint8_t *memory_base) const {
|
||||
ASSERT(format_.xbox_swizzled && "Volumetric textures using linear formats are not supported by XBOX.")
|
||||
|
||||
auto **new_surfaces = new SDL_Surface *[depth];
|
||||
|
||||
for (auto i = 0; i < depth; ++i) {
|
||||
auto *surface = const_cast<SDL_Surface *>(layers[i]);
|
||||
new_surfaces[i] = SDL_ConvertSurfaceFormat(surface, format_.sdl_format, 0);
|
||||
|
||||
if (!new_surfaces[i]) {
|
||||
ASSERT(!"Failed to convert surface format.");
|
||||
// This will leak memory, but the ASSERT will halt execution anyway.
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
const int32_t width = new_surfaces[0]->w;
|
||||
int32_t height = new_surfaces[0]->h;
|
||||
int32_t pitch = new_surfaces[0]->pitch;
|
||||
int32_t bytes_per_pixel = new_surfaces[0]->format->BytesPerPixel;
|
||||
|
||||
uint32_t converted_surface_size = pitch * height;
|
||||
auto *flattened = new uint8_t[converted_surface_size * depth];
|
||||
uint8_t *dest = flattened;
|
||||
for (auto i = 0; i < depth; ++i) {
|
||||
SDL_Surface *s = new_surfaces[i];
|
||||
ASSERT(s->w == width && "Volumetric surface layers must have identical dimensions");
|
||||
ASSERT(s->h == height && "Volumetric surface layers must have identical dimensions");
|
||||
ASSERT(s->pitch == pitch && "Volumetric surface layers must have identical dimensions");
|
||||
ASSERT(s->format->BytesPerPixel == bytes_per_pixel && "Volumetric surface layers must have identical dimensions");
|
||||
|
||||
memcpy(dest, s->pixels, converted_surface_size);
|
||||
dest += converted_surface_size;
|
||||
}
|
||||
|
||||
for (auto i = 0; i < depth; ++i) {
|
||||
SDL_FreeSurface(new_surfaces[i]);
|
||||
}
|
||||
delete[] new_surfaces;
|
||||
|
||||
int ret = SetRawTexture(flattened, width, height, depth, pitch, bytes_per_pixel, format_.xbox_swizzled, memory_base);
|
||||
|
||||
delete[] flattened;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int TextureStage::SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t depth, uint32_t pitch,
|
||||
uint32_t bytes_per_pixel, bool swizzle, uint8_t *memory_base) const {
|
||||
uint8_t *dest = memory_base + texture_memory_offset_;
|
||||
|
||||
if (swizzle) {
|
||||
swizzle_rect(source, width, height, dest, pitch, bytes_per_pixel);
|
||||
if (depth > 1) {
|
||||
swizzle_box(source, width, height, depth, dest, pitch, pitch * height, bytes_per_pixel);
|
||||
} else {
|
||||
swizzle_rect(source, width, height, dest, pitch, bytes_per_pixel);
|
||||
}
|
||||
} else {
|
||||
memcpy(dest, source, pitch * height);
|
||||
memcpy(dest, source, pitch * height * depth);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -39,8 +39,9 @@ class TextureStage {
|
||||
void Commit(uint32_t memory_dma_offset, uint32_t palette_dma_offset) const;
|
||||
|
||||
int SetTexture(const SDL_Surface *surface, uint8_t *memory_base) const;
|
||||
int SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t pitch, uint32_t bytes_per_pixel,
|
||||
bool swizzle, uint8_t *memory_base) const;
|
||||
int SetVolumetricTexture(const SDL_Surface **layers, uint32_t depth, uint8_t *memory_base) const;
|
||||
int SetRawTexture(const uint8_t *source, uint32_t width, uint32_t height, uint32_t depth, uint32_t pitch,
|
||||
uint32_t bytes_per_pixel, bool swizzle, uint8_t *memory_base) const;
|
||||
|
||||
int SetPalette(const uint32_t *palette, uint32_t length, uint8_t *memory_base);
|
||||
|
||||
|
@ -91,8 +91,8 @@ typedef struct Vertex {
|
||||
inline void SetTexCoord0(const float u, const float v, const float s, const float q) {
|
||||
texcoord0[0] = u;
|
||||
texcoord0[1] = v;
|
||||
texcoord0[1] = s;
|
||||
texcoord0[1] = q;
|
||||
texcoord0[2] = s;
|
||||
texcoord0[3] = q;
|
||||
}
|
||||
|
||||
inline void SetTexCoord1(const float* value) { memcpy(texcoord1, value, sizeof(texcoord1)); }
|
||||
@ -105,8 +105,8 @@ typedef struct Vertex {
|
||||
inline void SetTexCoord1(const float u, const float v, const float s, const float q) {
|
||||
texcoord1[0] = u;
|
||||
texcoord1[1] = v;
|
||||
texcoord1[1] = s;
|
||||
texcoord1[1] = q;
|
||||
texcoord1[2] = s;
|
||||
texcoord1[3] = q;
|
||||
}
|
||||
|
||||
inline void SetTexCoord2(const float* value) { memcpy(texcoord2, value, sizeof(texcoord2)); }
|
||||
@ -119,8 +119,8 @@ typedef struct Vertex {
|
||||
inline void SetTexCoord2(const float u, const float v, const float s, const float q) {
|
||||
texcoord2[0] = u;
|
||||
texcoord2[1] = v;
|
||||
texcoord2[1] = s;
|
||||
texcoord2[1] = q;
|
||||
texcoord2[2] = s;
|
||||
texcoord2[3] = q;
|
||||
}
|
||||
|
||||
inline void SetTexCoord3(const float* value) { memcpy(texcoord3, value, sizeof(texcoord3)); }
|
||||
@ -133,8 +133,8 @@ typedef struct Vertex {
|
||||
inline void SetTexCoord3(const float u, const float v, const float s, const float q) {
|
||||
texcoord3[0] = u;
|
||||
texcoord3[1] = v;
|
||||
texcoord3[1] = s;
|
||||
texcoord3[1] = q;
|
||||
texcoord3[2] = s;
|
||||
texcoord3[3] = q;
|
||||
}
|
||||
|
||||
inline void SetDiffuseGrey(float val) { SetDiffuse(val, val, val); }
|
||||
|
2
third_party/swizzle.c
vendored
2
third_party/swizzle.c
vendored
@ -100,7 +100,7 @@ void swizzle_box(const uint8_t *src_buf, unsigned int width,
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++) {
|
||||
const uint8_t *src = src_buf + y * row_pitch + x * bytes_per_pixel;
|
||||
uint8_t *dst = dst_buf + get_swizzled_offset(x, y, 0, mask_x, mask_y, 0,
|
||||
uint8_t *dst = dst_buf + get_swizzled_offset(x, y, z, mask_x, mask_y, mask_z,
|
||||
bytes_per_pixel);
|
||||
memcpy(dst, src, bytes_per_pixel);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user