Adds test for volumetric palettized texture.

This commit is contained in:
Erik Abair 2022-01-27 16:21:31 -08:00
parent 739629eb05
commit 10d3599244
11 changed files with 316 additions and 86 deletions

View File

@ -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);
}

View File

@ -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,

View File

@ -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:

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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); }

View File

@ -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);
}