Merge branch 'volumetric_texture'

This commit is contained in:
Erik Abair 2022-01-27 22:14:42 -08:00
commit 0c6940b005
10 changed files with 274 additions and 140 deletions

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));
@ -845,16 +846,21 @@ int TestHost::SetTexture(SDL_Surface *surface, uint32_t stage) {
return texture_stage_[stage].SetTexture(surface, texture_memory_);
}
int TestHost::SetVolumetricTexture(const SDL_Surface **surface, uint32_t depth, uint32_t stage) {
return texture_stage_[stage].SetVolumetricTexture(surface, depth, texture_memory_);
}
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) {
uint32_t max_stride = max_texture_width_ * 4;
uint32_t max_texture_size = max_stride * max_texture_height_ * max_texture_depth_;
const uint32_t max_stride = max_texture_width_ * 4;
const uint32_t max_texture_size = max_stride * max_texture_height_ * max_texture_depth_;
uint32_t surface_size = pitch * height * 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.");
// TODO: Handle 3d textures.
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) {

View File

@ -152,13 +152,14 @@ class TestHost {
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);
uint32_t max_texture_height, uint32_t max_texture_depth = 4);
~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 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);

View File

@ -135,17 +135,7 @@ void TestSuite::Initialize() {
}
p = pb_push1(p, NV097_SET_FOG_ENABLE, false);
{
uint32_t matrix_enable = NV097_SET_TEXTURE_MATRIX_ENABLE;
p = pb_push1(p, matrix_enable, 0x0);
matrix_enable += 4;
p = pb_push1(p, matrix_enable, 0x0);
matrix_enable += 4;
p = pb_push1(p, matrix_enable, 0x0);
matrix_enable += 4;
p = pb_push1(p, matrix_enable, 0x0);
}
p = pb_push4(p, NV097_SET_TEXTURE_MATRIX_ENABLE, 0, 0, 0, 0);
p = pb_push1(p, NV097_SET_FRONT_FACE, NV097_SET_FRONT_FACE_V_CW);
p = pb_push1(p, NV097_SET_CULL_FACE, NV097_SET_CULL_FACE_V_BACK);

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

@ -12,21 +12,32 @@
#include "texture_format.h"
#include "vertex_buffer.h"
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 kTextureWidth = 256;
static const uint32_t kTextureHeight = 256;
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() {
@ -38,20 +49,23 @@ void VolumeTextureTests::Initialize() {
host_.SetXDKDefaultViewportAndFixedFunctionMatrices();
host_.SetTextureStageEnabled(0, true);
host_.SetShaderStageProgram(TestHost::STAGE_2D_PROJECTIVE);
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_.SetOutputColorCombiner(0, TestHost::DST_R0);
host_.SetOutputAlphaCombiner(0, TestHost::DST_R0);
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);
false, TestHost::SRC_R0);
host_.SetFinalCombiner1(TestHost::SRC_ZERO, false, false, TestHost::SRC_ZERO, false, false, TestHost::SRC_R0, true);
auto p = pb_begin();
p = pb_push1(p, NV097_SET_TEXTURE_BORDER_COLOR, 0xFFFFFF);
pb_end(p);
}
void VolumeTextureTests::CreateGeometry() {
@ -62,54 +76,83 @@ void VolumeTextureTests::CreateGeometry() {
const float mid_width = 0;
const float mid_height = 0;
// const uint32_t num_quads = 4;
// std::shared_ptr<VertexBuffer> buffer = host_.AllocateVertexBuffer(6 * num_quads);
// buffer->SetTexCoord0Count(2);
//
// const float spacing = 0.05f;
// int index = 0;
//
// buffer->DefineBiTri(index++, left, top, mid_width - spacing, mid_height + spacing);
//
// buffer->DefineBiTri(index++, mid_width + spacing, top, right, mid_height + spacing);
//
// buffer->DefineBiTri(index++, left, mid_height - spacing, mid_width - spacing, bottom);
//
// buffer->DefineBiTri(index++, mid_width + spacing, mid_height - spacing, right, bottom);
//
// // Set texcoords.
// auto vertex = buffer->Lock();
//
// auto set_bitri_texcoords = [&vertex](float p) {
// vertex++->SetTexCoord0(0.0f, 0.0f, p, 0.0);
// vertex++->SetTexCoord0(1.0f, 0.0f, p, 0.0);
// vertex++->SetTexCoord0(1.0f, 1.0f, p, 0.0);
//
// vertex++->SetTexCoord0(0.0f, 0.0f, p, 0.0);
// vertex++->SetTexCoord0(1.0f, 1.0f, p, 0.0);
// vertex++->SetTexCoord0(0.0f, 1.0f, p, 0.0);
// };
//
// set_bitri_texcoords(0.0f);
//
// set_bitri_texcoords(0.33f);
//
// set_bitri_texcoords(0.66f);
//
// set_bitri_texcoords(1.0f);
//
// buffer->Unlock();
const uint32_t num_quads = 1;
const uint32_t num_quads = 4;
std::shared_ptr<VertexBuffer> buffer = host_.AllocateVertexBuffer(6 * num_quads);
buffer->SetTexCoord0Count(3);
const float spacing = 0.05f;
int index = 0;
buffer->DefineBiTri(index++, left, top, right, bottom);
buffer->Linearize(static_cast<float>(host_.GetMaxTextureWidth()), static_cast<float>(host_.GetMaxTextureHeight()));
buffer->DefineBiTri(index++, left, top, mid_width - spacing, mid_height + spacing);
buffer->DefineBiTri(index++, mid_width + spacing, top, right, mid_height + spacing);
buffer->DefineBiTri(index++, left, mid_height - spacing, mid_width - spacing, bottom);
buffer->DefineBiTri(index++, mid_width + spacing, mid_height - spacing, right, bottom);
// Set texcoords.
auto vertex = buffer->Lock();
auto set_bitri_texcoords = [&vertex](float p) {
vertex++->SetTexCoord0(0.0f, 0.0f, p, 0.0);
vertex++->SetTexCoord0(1.0f, 0.0f, p, 0.0);
vertex++->SetTexCoord0(1.0f, 1.0f, p, 0.0);
vertex++->SetTexCoord0(0.0f, 0.0f, p, 0.0);
vertex++->SetTexCoord0(1.0f, 1.0f, p, 0.0);
vertex++->SetTexCoord0(0.0f, 1.0f, p, 0.0);
};
set_bitri_texcoords(0.0f);
set_bitri_texcoords(0.33f);
set_bitri_texcoords(0.66f);
set_bitri_texcoords(1.0f);
buffer->Unlock();
buffer->Linearize(static_cast<float>(kTextureWidth), static_cast<float>(kTextureHeight));
}
void VolumeTextureTests::Test(const TestConfig &config) {
static constexpr uint32_t kBackgroundColor = 0xFF303030;
void VolumeTextureTests::Test(const TextureFormatInfo &texture_format) {
const uint32_t width = kTextureWidth;
const uint32_t height = kTextureHeight;
host_.SetTextureFormat(texture_format);
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(TestHost::POSITION | TestHost::DIFFUSE | TestHost::TEXCOORD0);
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;
@ -117,16 +160,18 @@ void VolumeTextureTests::Test(const TestConfig &config) {
host_.SetTextureFormat(texture_format);
uint8_t *surface = nullptr;
uint32_t depth = 1;
int err = GeneratePalettizedSurface(&surface, (int)host_.GetMaxTextureWidth(), (int)host_.GetMaxTextureHeight(),
depth, palette_size);
const uint32_t width = kTextureWidth;
const uint32_t height = kTextureHeight;
int err = GeneratePalettizedSurface(&surface, width, height, kTextureDepth, palette_size);
ASSERT(!err && "Failed to generate palettized surface");
err = host_.SetRawTexture(surface, host_.GetMaxTextureWidth(), host_.GetMaxTextureHeight(), depth,
host_.GetMaxTextureWidth(), 1, texture_format.xbox_swizzled);
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;
@ -134,18 +179,57 @@ void VolumeTextureTests::Test(const TestConfig &config) {
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 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;
}
if (SDL_LockSurface(*gradient_surface)) {
SDL_FreeSurface(*gradient_surface);
*gradient_surface = nullptr;
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 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 & 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,
@ -157,26 +241,27 @@ static int GeneratePalettizedSurface(uint8_t **ret, uint32_t width, uint32_t hei
auto pixel = *ret;
uint32_t layer_size = width * height;
for (auto d = 0; d < depth; ++d) {
uint32_t layer_size = width * height;
uint32_t half_size = layer_size >> 1;
uint32_t half_size = layer_size >> 1;
for (uint32_t i = 0; i < half_size; ++i, ++pixel) {
*pixel = i & (palette_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;
}
}
for (uint32_t i = half_size; i < layer_size; i += 4) {
uint8_t value = i & (palette_size - 1);
*pixel++ = value;
*pixel++ = value;
*pixel++ = value;
*pixel++ = value;
}
// TODO: Layer 1+.
return 0;
}
static uint32_t *GeneratePalette(TestHost::PaletteSize size) {
auto ret = new uint32_t[size];

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

@ -28,18 +28,18 @@ void TextureStage::Commit(uint32_t memory_dma_offset, uint32_t palette_dma_offse
auto p = pb_begin();
// NV097_SET_TEXTURE_CONTROL0
p = pb_push1(p, NV20_TCL_PRIMITIVE_3D_TX_ENABLE(stage_),
NV097_SET_TEXTURE_CONTROL0_ENABLE | NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP);
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;
@ -71,13 +71,12 @@ void TextureStage::Commit(uint32_t memory_dma_offset, uint32_t palette_dma_offse
// NV097_SET_TEXTURE_ADDRESS
p = pb_push1(p, NV20_TCL_PRIMITIVE_3D_TX_WRAP(stage_), 0x00030303);
// NV097_SET_TEXTURE_CONTROL0
p = pb_push1(p, NV20_TCL_PRIMITIVE_3D_TX_ENABLE(stage_),
NV097_SET_TEXTURE_CONTROL0_ENABLE | NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP);
// set stage 0 texture filters (AA!)
// NV097_SET_TEXTURE_FILTER
p = pb_push1(p, NV20_TCL_PRIMITIVE_3D_TX_FILTER(stage_), 0x04074000);
p = pb_push1(p, NV20_TCL_PRIMITIVE_3D_TX_FILTER(stage_), 0x1012000);
// Note: Using 0x04074000 breaks 3d textures (the resultant buffer is 0'd out).
p = pb_push4(p, NV097_SET_TEXTURE_MATRIX_ENABLE, 0, 0, 0, 0);
uint32_t palette_config = 0;
if (format_.xbox_format == NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8) {
@ -96,10 +95,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 +156,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);
}