52 lines
2.8 KiB
C++
52 lines
2.8 KiB
C++
#include "dxt.h"
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
#include <vector>
|
|
using Bytes = std::vector<uint8_t>;
|
|
void put(Bytes& b, size_t off, uint32_t v) {
|
|
for (int i = 0; i < 4; ++i) b[off + i] = uint8_t(v >> (8 * i));
|
|
}
|
|
Bytes header(uint32_t bits, uint32_t r, uint32_t g, uint32_t b, uint32_t a, size_t payload = 8) {
|
|
Bytes out(128 + payload, 0);
|
|
put(out, 0, 0x20534444); put(out, 4, 124); put(out, 12, 1); put(out, 16, 2);
|
|
put(out, 76, 32); put(out, 80, 0x40 | (a ? 1 : 0)); put(out, 88, bits);
|
|
put(out, 92, r); put(out, 96, g); put(out, 100, b); put(out, 104, a);
|
|
return out;
|
|
}
|
|
mtgodot::Image decode(const Bytes& b) { return mtgodot::load_dds(b.data(), b.size()); }
|
|
void pixel(const mtgodot::Image& im, size_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
|
assert(im.ok()); assert(im.rgba[n*4] == r && im.rgba[n*4+1] == g && im.rgba[n*4+2] == b && im.rgba[n*4+3] == a);
|
|
}
|
|
int main() {
|
|
auto a1555 = header(16, 0x7c00, 0x3e0, 0x1f, 0x8000);
|
|
put(a1555, 128, 0x001ffc00); // opaque red, transparent blue
|
|
pixel(decode(a1555), 0, 255, 0, 0, 255); pixel(decode(a1555), 1, 0, 0, 255, 0);
|
|
auto rgb565 = header(16, 0xf800, 0x7e0, 0x1f, 0);
|
|
put(rgb565, 128, 0x001f07e0);
|
|
pixel(decode(rgb565), 0, 0, 255, 0, 255); pixel(decode(rgb565), 1, 0, 0, 255, 255);
|
|
auto a4444 = header(16, 0xf00, 0xf0, 0xf, 0xf000);
|
|
put(a4444, 128, 0x12348f00);
|
|
pixel(decode(a4444), 0, 255, 0, 0, 136); pixel(decode(a4444), 1, 34, 51, 68, 17);
|
|
auto padded = header(24, 0xff0000, 0xff00, 0xff, 0, 8);
|
|
put(padded, 16, 1); put(padded, 12, 2); put(padded, 8, 8); put(padded, 20, 4);
|
|
put(padded, 128, 0xaaff0000); put(padded, 132, 0xbb0000ff);
|
|
pixel(decode(padded), 0, 255, 0, 0, 255); pixel(decode(padded), 1, 0, 0, 255, 255);
|
|
auto rgba = header(32, 0xff, 0xff00, 0xff0000, 0xff000000);
|
|
put(rgba, 128, 0x80402010); pixel(decode(rgba), 0, 16, 32, 64, 128);
|
|
put(rgba, 80, 0x40); pixel(decode(rgba), 0, 16, 32, 64, 255); // XRGB ignores unused alpha bits
|
|
auto invalid = a1555; invalid.resize(130); assert(!decode(invalid).ok());
|
|
invalid = padded; put(invalid, 20, 2); assert(!decode(invalid).ok());
|
|
invalid = a1555; put(invalid, 92, 0x3e0); assert(!decode(invalid).ok());
|
|
invalid = a1555; put(invalid, 92, 0x7400); assert(!decode(invalid).ok());
|
|
for (uint32_t fourcc : {0x31545844u, 0x33545844u, 0x35545844u}) {
|
|
auto dxt = header(0, 0, 0, 0, 0, 16);
|
|
put(dxt, 12, 4); put(dxt, 16, 4); put(dxt, 80, 4); put(dxt, 84, fourcc);
|
|
const bool dxt1 = fourcc == 0x31545844;
|
|
put(dxt, dxt1 ? 128 : 136, 0x0000f800);
|
|
if (fourcc == 0x33545844) { put(dxt, 128, 0xffffffff); put(dxt, 132, 0xffffffff); }
|
|
if (fourcc == 0x35545844) dxt[128] = 255;
|
|
pixel(decode(dxt), 0, 255, 0, 0, 255);
|
|
}
|
|
std::puts("PASS: dxt_decode_test (masked RGB, pitch, invalid headers, DXT1/3/5)");
|
|
}
|