mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 08:15:38 +07:00
Merge branch 'master' into feature/label
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,6 +1,8 @@
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.tga filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.obj filter=lfs diff=lfs merge=lfs -text
|
||||
*.e2d_mesh filter=lfs diff=lfs merge=lfs -text
|
||||
*.e2d_shape filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.vs/*
|
||||
.vscode/*
|
||||
build/*
|
||||
.DS_Store
|
||||
CMakeSettings.json
|
||||
CMakeLists.txt.user
|
||||
@@ -48,19 +48,30 @@ namespace e2d
|
||||
depth24,
|
||||
depth24_stencil8,
|
||||
|
||||
g8,
|
||||
ga8,
|
||||
a8,
|
||||
l8,
|
||||
la8,
|
||||
rgb8,
|
||||
rgba8,
|
||||
|
||||
rgb_dxt1,
|
||||
rgba_dxt1,
|
||||
rgba_dxt3,
|
||||
rgba_dxt5,
|
||||
|
||||
rgb_etc1,
|
||||
rgb_etc2,
|
||||
rgba_etc2,
|
||||
rgb_a1_etc2,
|
||||
|
||||
rgba_astc4x4,
|
||||
rgba_astc5x5,
|
||||
rgba_astc6x6,
|
||||
rgba_astc8x8,
|
||||
rgba_astc10x10,
|
||||
rgba_astc12x12,
|
||||
|
||||
rgb_pvrtc2,
|
||||
rgb_pvrtc4,
|
||||
|
||||
rgba_pvrtc2,
|
||||
rgba_pvrtc4,
|
||||
|
||||
@@ -82,8 +93,9 @@ namespace e2d
|
||||
bool is_depth() const noexcept;
|
||||
bool is_stencil() const noexcept;
|
||||
bool is_compressed() const noexcept;
|
||||
std::size_t bits_per_pixel() const noexcept;
|
||||
v2u compressed_block_size() const noexcept;
|
||||
v2u block_size() const noexcept;
|
||||
std::size_t bytes_per_block() const noexcept;
|
||||
std::size_t data_size_for_dimension(v2u dim) const noexcept;
|
||||
private:
|
||||
pixel_type type_ = pixel_type::rgba8;
|
||||
};
|
||||
@@ -902,6 +914,9 @@ namespace e2d
|
||||
bool depth24_stencil8_supported = false;
|
||||
|
||||
bool dxt_compression_supported = false;
|
||||
bool etc1_compression_supported = false;
|
||||
bool etc2_compression_supported = false;
|
||||
bool astc_compression_supported = false;
|
||||
bool pvrtc_compression_supported = false;
|
||||
bool pvrtc2_compression_supported = false;
|
||||
};
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace e2d
|
||||
template < typename T >
|
||||
buffer_view(const vector<T>& buffer) noexcept;
|
||||
|
||||
template < typename Char >
|
||||
buffer_view(const basic_string<Char>& buffer) noexcept;
|
||||
|
||||
template < typename T, std::size_t N >
|
||||
buffer_view(const std::array<T,N>& buffer) noexcept;
|
||||
|
||||
@@ -37,6 +40,8 @@ namespace e2d
|
||||
std::size_t size() const noexcept;
|
||||
bool empty() const noexcept;
|
||||
void swap(buffer_view& other) noexcept;
|
||||
|
||||
explicit operator buffer();
|
||||
private:
|
||||
const void* data_ = nullptr;
|
||||
std::size_t size_ = 0;
|
||||
@@ -55,6 +60,11 @@ namespace e2d
|
||||
: data_(buffer.data())
|
||||
, size_(buffer.size() * sizeof(T)) {}
|
||||
|
||||
template < typename Char >
|
||||
buffer_view::buffer_view(const basic_string<Char>& buffer) noexcept
|
||||
: data_(buffer.data())
|
||||
, size_(buffer.size() * sizeof(Char)) {}
|
||||
|
||||
template < typename T, std::size_t N >
|
||||
buffer_view::buffer_view(const std::array<T,N>& buffer) noexcept
|
||||
: data_(buffer.data())
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "_utils.hpp"
|
||||
|
||||
#include "buffer.hpp"
|
||||
#include "buffer_view.hpp"
|
||||
#include "streams.hpp"
|
||||
|
||||
namespace e2d
|
||||
@@ -73,9 +76,7 @@ namespace e2d::filesystem
|
||||
|
||||
bool try_read_all(str& dst, str_view path) noexcept;
|
||||
bool try_read_all(buffer& dst, str_view path) noexcept;
|
||||
|
||||
bool try_write_all(const str& src, str_view path, bool append) noexcept;
|
||||
bool try_write_all(const buffer& src, str_view path, bool append) noexcept;
|
||||
bool try_write_all(buffer_view src, str_view path, bool append) noexcept;
|
||||
|
||||
enum class predef_path {
|
||||
home,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "_utils.hpp"
|
||||
|
||||
#include "buffer.hpp"
|
||||
#include "color.hpp"
|
||||
#include "buffer_view.hpp"
|
||||
#include "color32.hpp"
|
||||
#include "streams.hpp"
|
||||
|
||||
@@ -24,19 +24,30 @@ namespace e2d
|
||||
};
|
||||
|
||||
enum class image_data_format : u8 {
|
||||
g8,
|
||||
ga8,
|
||||
a8,
|
||||
l8,
|
||||
la8,
|
||||
rgb8,
|
||||
rgba8,
|
||||
|
||||
rgb_dxt1,
|
||||
rgba_dxt1,
|
||||
rgba_dxt3,
|
||||
rgba_dxt5,
|
||||
|
||||
rgb_etc1,
|
||||
rgb_etc2,
|
||||
rgba_etc2,
|
||||
rgb_a1_etc2,
|
||||
|
||||
rgba_astc4x4,
|
||||
rgba_astc5x5,
|
||||
rgba_astc6x6,
|
||||
rgba_astc8x8,
|
||||
rgba_astc10x10,
|
||||
rgba_astc12x12,
|
||||
|
||||
rgb_pvrtc2,
|
||||
rgb_pvrtc4,
|
||||
|
||||
rgba_pvrtc2,
|
||||
rgba_pvrtc4,
|
||||
|
||||
@@ -74,8 +85,6 @@ namespace e2d
|
||||
void clear() noexcept;
|
||||
bool empty() const noexcept;
|
||||
|
||||
color pixel(u32 u, u32 v) const;
|
||||
color pixel(const v2u& uv) const;
|
||||
color32 pixel32(u32 u, u32 v) const;
|
||||
color32 pixel32(const v2u& uv) const;
|
||||
|
||||
@@ -97,7 +106,7 @@ namespace e2d::images
|
||||
{
|
||||
bool try_load_image(
|
||||
image& dst,
|
||||
const buffer& src) noexcept;
|
||||
buffer_view src) noexcept;
|
||||
|
||||
bool try_load_image(
|
||||
image& dst,
|
||||
@@ -112,4 +121,8 @@ namespace e2d::images
|
||||
const image& src,
|
||||
image_file_format format,
|
||||
const output_stream_uptr& dst) noexcept;
|
||||
|
||||
bool check_save_image_support(
|
||||
const image& src,
|
||||
image_file_format format) noexcept;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "_utils.hpp"
|
||||
|
||||
#include "buffer.hpp"
|
||||
#include "buffer_view.hpp"
|
||||
#include "color32.hpp"
|
||||
#include "streams.hpp"
|
||||
|
||||
@@ -101,7 +102,7 @@ namespace e2d::meshes
|
||||
{
|
||||
bool try_load_mesh(
|
||||
mesh& dst,
|
||||
const buffer& src) noexcept;
|
||||
buffer_view src) noexcept;
|
||||
|
||||
bool try_load_mesh(
|
||||
mesh& dst,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "_utils.hpp"
|
||||
|
||||
#include "buffer.hpp"
|
||||
#include "buffer_view.hpp"
|
||||
#include "color32.hpp"
|
||||
#include "streams.hpp"
|
||||
|
||||
@@ -81,7 +82,7 @@ namespace e2d::shapes
|
||||
{
|
||||
bool try_load_shape(
|
||||
shape& dst,
|
||||
const buffer& src) noexcept;
|
||||
buffer_view src) noexcept;
|
||||
|
||||
bool try_load_shape(
|
||||
shape& dst,
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
#include "_utils.hpp"
|
||||
|
||||
#include "buffer.hpp"
|
||||
#include "buffer_view.hpp"
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
class bad_stream_operation final : public exception {
|
||||
@@ -78,8 +81,7 @@ namespace e2d
|
||||
|
||||
output_sequence& seek(std::ptrdiff_t offset, bool relative) noexcept;
|
||||
output_sequence& write(const void* src, std::size_t size) noexcept;
|
||||
output_sequence& write_all(const str& src) noexcept;
|
||||
output_sequence& write_all(const buffer& src) noexcept;
|
||||
output_sequence& write_all(buffer_view src) noexcept;
|
||||
|
||||
output_sequence& flush() noexcept;
|
||||
output_sequence& flush_if(bool yesno) noexcept;
|
||||
@@ -112,11 +114,7 @@ namespace e2d::streams
|
||||
const input_stream_uptr& stream) noexcept;
|
||||
|
||||
bool try_write_tail(
|
||||
const str& src,
|
||||
const output_stream_uptr& stream) noexcept;
|
||||
|
||||
bool try_write_tail(
|
||||
const buffer& src,
|
||||
buffer_view src,
|
||||
const output_stream_uptr& stream) noexcept;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace
|
||||
|
||||
struct pixel_type_description {
|
||||
const char* cstr;
|
||||
u32 bits_per_pixel;
|
||||
u32 bytes_per_block;
|
||||
bool color;
|
||||
bool depth;
|
||||
bool stencil;
|
||||
@@ -22,30 +22,39 @@ namespace
|
||||
};
|
||||
|
||||
const pixel_type_description pixel_type_descriptions[] = {
|
||||
{"depth16", 16, false, true, false, pixel_declaration::pixel_type::depth16, false, v2u(1)},
|
||||
{"depth24", 24, false, true, false, pixel_declaration::pixel_type::depth24, false, v2u(1)},
|
||||
{"depth24_stencil8", 32, false, true, true, pixel_declaration::pixel_type::depth24_stencil8, false, v2u(1)},
|
||||
{"depth16", 2, false, true, false, pixel_declaration::pixel_type::depth16, false, v2u(1,1)},
|
||||
{"depth24", 3, false, true, false, pixel_declaration::pixel_type::depth24, false, v2u(1,1)},
|
||||
{"depth24_stencil8", 4, false, true, true, pixel_declaration::pixel_type::depth24_stencil8, false, v2u(1,1)},
|
||||
|
||||
{"g8", 8, true, false, false, pixel_declaration::pixel_type::g8, false, v2u(1)},
|
||||
{"ga8", 16, true, false, false, pixel_declaration::pixel_type::ga8, false, v2u(1)},
|
||||
{"rgb8", 24, true, false, false, pixel_declaration::pixel_type::rgb8, false, v2u(1)},
|
||||
{"rgba8", 32, true, false, false, pixel_declaration::pixel_type::rgba8, false, v2u(1)},
|
||||
{"a8", 1, true, false, false, pixel_declaration::pixel_type::a8, false, v2u(1,1)},
|
||||
{"l8", 1, true, false, false, pixel_declaration::pixel_type::l8, false, v2u(1,1)},
|
||||
{"la8", 2, true, false, false, pixel_declaration::pixel_type::la8, false, v2u(1,1)},
|
||||
{"rgb8", 3, true, false, false, pixel_declaration::pixel_type::rgb8, false, v2u(1,1)},
|
||||
{"rgba8", 4, true, false, false, pixel_declaration::pixel_type::rgba8, false, v2u(1,1)},
|
||||
|
||||
{"rgb_dxt1", 4, true, false, false, pixel_declaration::pixel_type::rgb_dxt1, true, v2u(4,4)},
|
||||
{"rgba_dxt1", 4, true, false, false, pixel_declaration::pixel_type::rgba_dxt1, true, v2u(4,4)},
|
||||
{"rgba_dxt3", 8, true, false, false, pixel_declaration::pixel_type::rgba_dxt3, true, v2u(4,4)},
|
||||
{"rgba_dxt5", 8, true, false, false, pixel_declaration::pixel_type::rgba_dxt5, true, v2u(4,4)},
|
||||
{"rgba_dxt1", 8, true, false, false, pixel_declaration::pixel_type::rgba_dxt1, true, v2u(4,4)},
|
||||
{"rgba_dxt3", 16, true, false, false, pixel_declaration::pixel_type::rgba_dxt3, true, v2u(4,4)},
|
||||
{"rgba_dxt5", 16, true, false, false, pixel_declaration::pixel_type::rgba_dxt5, true, v2u(4,4)},
|
||||
|
||||
{"rgb_pvrtc2", 2, true, false, false, pixel_declaration::pixel_type::rgb_pvrtc2, true, v2u(8,4)},
|
||||
{"rgb_pvrtc4", 4, true, false, false, pixel_declaration::pixel_type::rgb_pvrtc4, true, v2u(4,4)},
|
||||
{"rgba_pvrtc2", 2, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc2, true, v2u(8,4)},
|
||||
{"rgba_pvrtc4", 4, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc4, true, v2u(4,4)},
|
||||
{"rgb_etc1", 8, true, false, false, pixel_declaration::pixel_type::rgb_etc1, true, v2u(4,4)},
|
||||
{"rgb_etc2", 8, true, false, false, pixel_declaration::pixel_type::rgb_etc2, true, v2u(4,4)},
|
||||
{"rgba_etc2", 16, true, false, false, pixel_declaration::pixel_type::rgba_etc2, true, v2u(4,4)},
|
||||
{"rgb_a1_etc2", 8, true, false, false, pixel_declaration::pixel_type::rgb_a1_etc2, true, v2u(4,4)},
|
||||
|
||||
{"rgba_pvrtc2", 2, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc2, true, v2u(8,4)},
|
||||
{"rgba_pvrtc4", 4, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc4, true, v2u(4,4)},
|
||||
{"rgba_astc4x4", 16, true, false, false, pixel_declaration::pixel_type::rgba_astc4x4, true, v2u(4,4)},
|
||||
{"rgba_astc5x5", 16, true, false, false, pixel_declaration::pixel_type::rgba_astc5x5, true, v2u(5,5)},
|
||||
{"rgba_astc6x6", 16, true, false, false, pixel_declaration::pixel_type::rgba_astc6x6, true, v2u(6,6)},
|
||||
{"rgba_astc8x8", 16, true, false, false, pixel_declaration::pixel_type::rgba_astc8x8, true, v2u(8,8)},
|
||||
{"rgba_astc10x10", 16, true, false, false, pixel_declaration::pixel_type::rgba_astc10x10, true, v2u(10,10)},
|
||||
{"rgba_astc12x12", 16, true, false, false, pixel_declaration::pixel_type::rgba_astc12x12, true, v2u(12,12)},
|
||||
|
||||
{"rgba_pvrtc2_v2", 2, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc2_v2, true, v2u(8,4)},
|
||||
{"rgba_pvrtc4_v2", 4, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc4_v2, true, v2u(4,4)}
|
||||
{"rgb_pvrtc2", 8, true, false, false, pixel_declaration::pixel_type::rgb_pvrtc2, true, v2u(8,4)},
|
||||
{"rgb_pvrtc4", 8, true, false, false, pixel_declaration::pixel_type::rgb_pvrtc4, true, v2u(4,4)},
|
||||
{"rgba_pvrtc2", 8, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc2, true, v2u(8,4)},
|
||||
{"rgba_pvrtc4", 8, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc4, true, v2u(4,4)},
|
||||
|
||||
{"rgba_pvrtc2_v2", 8, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc2_v2, true, v2u(8,4)},
|
||||
{"rgba_pvrtc4_v2", 8, true, false, false, pixel_declaration::pixel_type::rgba_pvrtc4_v2, true, v2u(4,4)}
|
||||
};
|
||||
|
||||
const pixel_type_description& get_pixel_type_description(pixel_declaration::pixel_type type) noexcept {
|
||||
@@ -159,12 +168,20 @@ namespace e2d
|
||||
return get_pixel_type_description(type_).compressed;
|
||||
}
|
||||
|
||||
std::size_t pixel_declaration::bits_per_pixel() const noexcept {
|
||||
return get_pixel_type_description(type_).bits_per_pixel;
|
||||
v2u pixel_declaration::block_size() const noexcept {
|
||||
return get_pixel_type_description(type_).block_size;
|
||||
}
|
||||
|
||||
v2u pixel_declaration::compressed_block_size() const noexcept {
|
||||
return get_pixel_type_description(type_).block_size;
|
||||
std::size_t pixel_declaration::bytes_per_block() const noexcept {
|
||||
return get_pixel_type_description(type_).bytes_per_block;
|
||||
}
|
||||
|
||||
std::size_t pixel_declaration::data_size_for_dimension(v2u dim) const noexcept {
|
||||
const v2u bs = block_size();
|
||||
const std::size_t bpb = bytes_per_block();
|
||||
return bs.x > 0 && bs.y > 0 && bpb > 0
|
||||
? bpb * ((dim.x + bs.x - 1u) / bs.x) * ((dim.y + bs.y - 1u) / bs.y)
|
||||
: 0u;
|
||||
}
|
||||
|
||||
bool operator==(const pixel_declaration& l, const pixel_declaration& r) noexcept {
|
||||
|
||||
@@ -669,7 +669,7 @@ namespace e2d
|
||||
|
||||
with_gl_bind_texture(state_->dbg(), id, [this, &id, &size, &decl]() noexcept {
|
||||
if ( decl.is_compressed() ) {
|
||||
buffer empty_data(decl.bits_per_pixel() * size.x * size.y / 8);
|
||||
buffer empty_data(decl.data_size_for_dimension(size));
|
||||
GL_CHECK_CODE(state_->dbg(), glCompressedTexImage2D(
|
||||
id.target(),
|
||||
0,
|
||||
@@ -1096,10 +1096,10 @@ namespace e2d
|
||||
E2D_ASSERT(region.position.x < tex->size().x && region.position.y < tex->size().y);
|
||||
E2D_ASSERT(region.position.x + region.size.x <= tex->size().x);
|
||||
E2D_ASSERT(region.position.y + region.size.y <= tex->size().y);
|
||||
E2D_ASSERT(pixels.size() == region.size.y * ((region.size.x * tex->decl().bits_per_pixel()) / 8u));
|
||||
E2D_ASSERT(pixels.size() == tex->decl().data_size_for_dimension(region.size));
|
||||
|
||||
if ( tex->decl().is_compressed() ) {
|
||||
const v2u block_size = tex->decl().compressed_block_size();
|
||||
const v2u block_size = tex->decl().block_size();
|
||||
E2D_ASSERT(region.position.x % block_size.x == 0 && region.position.y % block_size.y == 0);
|
||||
E2D_ASSERT(region.size.x % block_size.x == 0 && region.size.y % block_size.y == 0);
|
||||
opengl::with_gl_bind_texture(state_->dbg(), tex->state().id(),
|
||||
@@ -1146,30 +1146,53 @@ namespace e2d
|
||||
case pixel_declaration::pixel_type::depth16:
|
||||
return caps.depth_texture_supported
|
||||
&& caps.depth16_supported;
|
||||
|
||||
case pixel_declaration::pixel_type::depth24:
|
||||
return caps.depth_texture_supported
|
||||
&& caps.depth24_supported;
|
||||
|
||||
case pixel_declaration::pixel_type::depth24_stencil8:
|
||||
return caps.depth_texture_supported
|
||||
&& caps.depth24_stencil8_supported;
|
||||
case pixel_declaration::pixel_type::g8:
|
||||
case pixel_declaration::pixel_type::ga8:
|
||||
|
||||
case pixel_declaration::pixel_type::a8:
|
||||
case pixel_declaration::pixel_type::l8:
|
||||
case pixel_declaration::pixel_type::la8:
|
||||
case pixel_declaration::pixel_type::rgb8:
|
||||
case pixel_declaration::pixel_type::rgba8:
|
||||
return true;
|
||||
case pixel_declaration::pixel_type::rgb_dxt1:
|
||||
|
||||
case pixel_declaration::pixel_type::rgba_dxt1:
|
||||
case pixel_declaration::pixel_type::rgba_dxt3:
|
||||
case pixel_declaration::pixel_type::rgba_dxt5:
|
||||
return caps.dxt_compression_supported;
|
||||
|
||||
case pixel_declaration::pixel_type::rgb_etc1:
|
||||
return caps.etc1_compression_supported;
|
||||
|
||||
case pixel_declaration::pixel_type::rgb_etc2:
|
||||
case pixel_declaration::pixel_type::rgba_etc2:
|
||||
case pixel_declaration::pixel_type::rgb_a1_etc2:
|
||||
return caps.etc2_compression_supported;
|
||||
|
||||
case pixel_declaration::pixel_type::rgba_astc4x4:
|
||||
case pixel_declaration::pixel_type::rgba_astc5x5:
|
||||
case pixel_declaration::pixel_type::rgba_astc6x6:
|
||||
case pixel_declaration::pixel_type::rgba_astc8x8:
|
||||
case pixel_declaration::pixel_type::rgba_astc10x10:
|
||||
case pixel_declaration::pixel_type::rgba_astc12x12:
|
||||
return caps.astc_compression_supported;
|
||||
|
||||
case pixel_declaration::pixel_type::rgb_pvrtc2:
|
||||
case pixel_declaration::pixel_type::rgb_pvrtc4:
|
||||
case pixel_declaration::pixel_type::rgba_pvrtc2:
|
||||
case pixel_declaration::pixel_type::rgba_pvrtc4:
|
||||
return caps.pvrtc_compression_supported;
|
||||
|
||||
case pixel_declaration::pixel_type::rgba_pvrtc2_v2:
|
||||
case pixel_declaration::pixel_type::rgba_pvrtc4_v2:
|
||||
return caps.pvrtc2_compression_supported;
|
||||
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected pixel type");
|
||||
return false;
|
||||
|
||||
@@ -758,8 +758,9 @@ namespace e2d::opengl
|
||||
GLenum convert_image_data_format_to_external_format(image_data_format f) noexcept {
|
||||
#define DEFINE_CASE(x,y) case image_data_format::x: return y
|
||||
switch ( f ) {
|
||||
DEFINE_CASE(g8, GL_LUMINANCE);
|
||||
DEFINE_CASE(ga8, GL_LUMINANCE_ALPHA);
|
||||
DEFINE_CASE(a8, GL_ALPHA);
|
||||
DEFINE_CASE(l8, GL_LUMINANCE);
|
||||
DEFINE_CASE(la8, GL_LUMINANCE_ALPHA);
|
||||
DEFINE_CASE(rgb8, GL_RGB);
|
||||
DEFINE_CASE(rgba8, GL_RGBA);
|
||||
default:
|
||||
@@ -772,8 +773,9 @@ namespace e2d::opengl
|
||||
GLenum convert_image_data_format_to_external_data_type(image_data_format f) noexcept {
|
||||
#define DEFINE_CASE(x,y) case image_data_format::x: return y
|
||||
switch ( f ) {
|
||||
DEFINE_CASE(g8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(ga8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(a8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(l8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(la8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(rgb8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(rgba8, GL_UNSIGNED_BYTE);
|
||||
default:
|
||||
@@ -789,8 +791,9 @@ namespace e2d::opengl
|
||||
DEFINE_CASE(depth16, GL_DEPTH_COMPONENT);
|
||||
DEFINE_CASE(depth24, GL_DEPTH_COMPONENT);
|
||||
DEFINE_CASE(depth24_stencil8, GL_DEPTH_STENCIL);
|
||||
DEFINE_CASE(g8, GL_ALPHA);
|
||||
DEFINE_CASE(ga8, GL_LUMINANCE_ALPHA);
|
||||
DEFINE_CASE(a8, GL_ALPHA);
|
||||
DEFINE_CASE(l8, GL_LUMINANCE);
|
||||
DEFINE_CASE(la8, GL_LUMINANCE_ALPHA);
|
||||
DEFINE_CASE(rgb8, GL_RGB);
|
||||
DEFINE_CASE(rgba8, GL_RGBA);
|
||||
default:
|
||||
@@ -806,8 +809,9 @@ namespace e2d::opengl
|
||||
DEFINE_CASE(depth16, GL_UNSIGNED_SHORT);
|
||||
DEFINE_CASE(depth24, GL_UNSIGNED_INT);
|
||||
DEFINE_CASE(depth24_stencil8, GL_UNSIGNED_INT_24_8);
|
||||
DEFINE_CASE(g8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(ga8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(a8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(l8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(la8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(rgb8, GL_UNSIGNED_BYTE);
|
||||
DEFINE_CASE(rgba8, GL_UNSIGNED_BYTE);
|
||||
default:
|
||||
@@ -824,19 +828,30 @@ namespace e2d::opengl
|
||||
DEFINE_CASE(depth24, GL_DEPTH_COMPONENT24);
|
||||
DEFINE_CASE(depth24_stencil8, GL_DEPTH24_STENCIL8);
|
||||
|
||||
DEFINE_CASE(g8, GL_ALPHA);
|
||||
DEFINE_CASE(ga8, GL_LUMINANCE_ALPHA);
|
||||
DEFINE_CASE(a8, GL_ALPHA);
|
||||
DEFINE_CASE(l8, GL_LUMINANCE);
|
||||
DEFINE_CASE(la8, GL_LUMINANCE_ALPHA);
|
||||
DEFINE_CASE(rgb8, GL_RGB);
|
||||
DEFINE_CASE(rgba8, GL_RGBA);
|
||||
|
||||
DEFINE_CASE(rgb_dxt1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
|
||||
DEFINE_CASE(rgba_dxt1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
|
||||
DEFINE_CASE(rgba_dxt3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
|
||||
DEFINE_CASE(rgba_dxt5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
|
||||
|
||||
DEFINE_CASE(rgb_etc1, GL_ETC1_RGB8_OES);
|
||||
DEFINE_CASE(rgb_etc2, GL_COMPRESSED_RGB8_ETC2);
|
||||
DEFINE_CASE(rgba_etc2, GL_COMPRESSED_RGBA8_ETC2_EAC);
|
||||
DEFINE_CASE(rgb_a1_etc2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
|
||||
|
||||
DEFINE_CASE(rgba_astc4x4, GL_COMPRESSED_RGBA_ASTC_4x4_KHR);
|
||||
DEFINE_CASE(rgba_astc5x5, GL_COMPRESSED_RGBA_ASTC_5x5_KHR);
|
||||
DEFINE_CASE(rgba_astc6x6, GL_COMPRESSED_RGBA_ASTC_6x6_KHR);
|
||||
DEFINE_CASE(rgba_astc8x8, GL_COMPRESSED_RGBA_ASTC_8x8_KHR);
|
||||
DEFINE_CASE(rgba_astc10x10, GL_COMPRESSED_RGBA_ASTC_10x10_KHR);
|
||||
DEFINE_CASE(rgba_astc12x12, GL_COMPRESSED_RGBA_ASTC_12x12_KHR);
|
||||
|
||||
DEFINE_CASE(rgb_pvrtc2, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG);
|
||||
DEFINE_CASE(rgb_pvrtc4, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG);
|
||||
|
||||
DEFINE_CASE(rgba_pvrtc2, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG);
|
||||
DEFINE_CASE(rgba_pvrtc4, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG);
|
||||
|
||||
@@ -856,19 +871,30 @@ namespace e2d::opengl
|
||||
pixel_declaration convert_image_data_format_to_pixel_declaration(image_data_format f) noexcept {
|
||||
#define DEFINE_CASE(x,y) case image_data_format::x: return pixel_declaration::pixel_type::y
|
||||
switch ( f ) {
|
||||
DEFINE_CASE(g8, g8);
|
||||
DEFINE_CASE(ga8, ga8);
|
||||
DEFINE_CASE(a8, a8);
|
||||
DEFINE_CASE(l8, l8);
|
||||
DEFINE_CASE(la8, la8);
|
||||
DEFINE_CASE(rgb8, rgb8);
|
||||
DEFINE_CASE(rgba8, rgba8);
|
||||
|
||||
DEFINE_CASE(rgb_dxt1, rgb_dxt1);
|
||||
DEFINE_CASE(rgba_dxt1, rgba_dxt1);
|
||||
DEFINE_CASE(rgba_dxt3, rgba_dxt3);
|
||||
DEFINE_CASE(rgba_dxt5, rgba_dxt5);
|
||||
|
||||
DEFINE_CASE(rgb_etc1, rgb_etc1);
|
||||
DEFINE_CASE(rgb_etc2, rgb_etc2);
|
||||
DEFINE_CASE(rgba_etc2, rgba_etc2);
|
||||
DEFINE_CASE(rgb_a1_etc2, rgb_a1_etc2);
|
||||
|
||||
DEFINE_CASE(rgba_astc4x4, rgba_astc4x4);
|
||||
DEFINE_CASE(rgba_astc5x5, rgba_astc5x5);
|
||||
DEFINE_CASE(rgba_astc6x6, rgba_astc6x6);
|
||||
DEFINE_CASE(rgba_astc8x8, rgba_astc8x8);
|
||||
DEFINE_CASE(rgba_astc10x10, rgba_astc10x10);
|
||||
DEFINE_CASE(rgba_astc12x12, rgba_astc12x12);
|
||||
|
||||
DEFINE_CASE(rgb_pvrtc2, rgb_pvrtc2);
|
||||
DEFINE_CASE(rgb_pvrtc4, rgb_pvrtc4);
|
||||
|
||||
DEFINE_CASE(rgba_pvrtc2, rgba_pvrtc2);
|
||||
DEFINE_CASE(rgba_pvrtc4, rgba_pvrtc4);
|
||||
|
||||
@@ -1370,7 +1396,7 @@ namespace e2d::opengl
|
||||
render::api_profile::opengl_compat;
|
||||
|
||||
caps.npot_texture_supported =
|
||||
version >= gl_version::gl_210 ||
|
||||
version >= gl_version::gl_210 || // gl_200
|
||||
version >= gl_version::gles_300 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_texture_npot",
|
||||
@@ -1381,38 +1407,38 @@ namespace e2d::opengl
|
||||
version >= gl_version::gles_300 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_depth_texture",
|
||||
"GL_ARB_depth_texture");
|
||||
"GL_ARB_depth_texture"); // gl_140
|
||||
|
||||
caps.render_target_supported =
|
||||
version >= gl_version::gl_300 ||
|
||||
version >= gl_version::gl_300 || // gl_300
|
||||
version >= gl_version::gles_200 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_framebuffer_object",
|
||||
"GL_ARB_framebuffer_object",
|
||||
"GL_EXT_framebuffer_object");
|
||||
"GL_EXT_framebuffer_object",
|
||||
"GL_ARB_framebuffer_object");
|
||||
|
||||
caps.element_index_uint =
|
||||
version >= gl_version::gl_210 ||
|
||||
version >= gl_version::gl_210 || // gl_100
|
||||
version >= gl_version::gles_300 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_element_index_uint");
|
||||
|
||||
caps.depth16_supported =
|
||||
version >= gl_version::gl_210 ||
|
||||
version >= gl_version::gl_210 || // gl_140
|
||||
version >= gl_version::gles_300 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_depth_texture",
|
||||
"GL_ARB_depth_texture");
|
||||
|
||||
caps.depth24_supported =
|
||||
version >= gl_version::gl_210 ||
|
||||
version >= gl_version::gl_210 || // gl_140
|
||||
version >= gl_version::gles_300 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_depth24",
|
||||
"GL_ARB_depth_texture");
|
||||
|
||||
caps.depth24_stencil8_supported =
|
||||
version >= gl_version::gl_300 ||
|
||||
version >= gl_version::gl_300 || // gl_300
|
||||
version >= gl_version::gles_300 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_packed_depth_stencil",
|
||||
@@ -1422,6 +1448,21 @@ namespace e2d::opengl
|
||||
gl_has_any_extension(debug,
|
||||
"GL_EXT_texture_compression_s3tc");
|
||||
|
||||
caps.etc1_compression_supported =
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_compressed_ETC1_RGB8_texture");
|
||||
|
||||
caps.etc2_compression_supported =
|
||||
version >= gl_version::gles_300 ||
|
||||
gl_has_any_extension(debug,
|
||||
"GL_ARB_ES3_compatibility");
|
||||
|
||||
caps.astc_compression_supported =
|
||||
gl_has_any_extension(debug,
|
||||
"GL_OES_texture_compression_astc",
|
||||
"GL_KHR_texture_compression_astc_ldr",
|
||||
"GL_KHR_texture_compression_astc_hdr");
|
||||
|
||||
caps.pvrtc_compression_supported =
|
||||
gl_has_any_extension(debug,
|
||||
"GL_IMG_texture_compression_pvrtc");
|
||||
|
||||
@@ -34,6 +34,10 @@ namespace e2d
|
||||
std::swap(data_, other.data_);
|
||||
std::swap(size_, other.size_);
|
||||
}
|
||||
|
||||
buffer_view::operator buffer() {
|
||||
return buffer(data_, size_);
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
|
||||
@@ -105,12 +105,7 @@ namespace e2d::filesystem
|
||||
dst, make_read_file(path));
|
||||
}
|
||||
|
||||
bool try_write_all(const str& src, str_view path, bool append) noexcept {
|
||||
return streams::try_write_tail(
|
||||
src, make_write_file(path, append));
|
||||
}
|
||||
|
||||
bool try_write_all(const buffer& src, str_view path, bool append) noexcept {
|
||||
bool try_write_all(buffer_view src, str_view path, bool append) noexcept {
|
||||
return streams::try_write_tail(
|
||||
src, make_write_file(path, append));
|
||||
}
|
||||
|
||||
@@ -11,29 +11,41 @@ namespace
|
||||
using namespace e2d;
|
||||
|
||||
struct data_format_description {
|
||||
u32 bits_per_pixel;
|
||||
u32 uncompressed_bytes_per_pixel;
|
||||
image_data_format format;
|
||||
bool compressed;
|
||||
};
|
||||
|
||||
const data_format_description data_format_descriptions[] = {
|
||||
{ 8, image_data_format::g8, false},
|
||||
{16, image_data_format::ga8, false},
|
||||
{24, image_data_format::rgb8, false},
|
||||
{32, image_data_format::rgba8, false},
|
||||
{1, image_data_format::a8, false},
|
||||
{1, image_data_format::l8, false},
|
||||
{2, image_data_format::la8, false},
|
||||
{3, image_data_format::rgb8, false},
|
||||
{4, image_data_format::rgba8, false},
|
||||
|
||||
{ 4, image_data_format::rgb_dxt1, true},
|
||||
{ 4, image_data_format::rgba_dxt1, true},
|
||||
{ 8, image_data_format::rgba_dxt3, true},
|
||||
{ 8, image_data_format::rgba_dxt5, true},
|
||||
{0, image_data_format::rgba_dxt1, true},
|
||||
{0, image_data_format::rgba_dxt3, true},
|
||||
{0, image_data_format::rgba_dxt5, true},
|
||||
|
||||
{ 2, image_data_format::rgb_pvrtc2, true},
|
||||
{ 4, image_data_format::rgb_pvrtc4, true},
|
||||
{ 2, image_data_format::rgba_pvrtc2, true},
|
||||
{ 4, image_data_format::rgba_pvrtc4, true},
|
||||
{0, image_data_format::rgb_etc1, true},
|
||||
{0, image_data_format::rgb_etc2, true},
|
||||
{0, image_data_format::rgba_etc2, true},
|
||||
{0, image_data_format::rgb_a1_etc2, true},
|
||||
|
||||
{ 2, image_data_format::rgba_pvrtc2_v2, true},
|
||||
{ 4, image_data_format::rgba_pvrtc4_v2, true}
|
||||
{0, image_data_format::rgba_astc4x4, true},
|
||||
{0, image_data_format::rgba_astc5x5, true},
|
||||
{0, image_data_format::rgba_astc6x6, true},
|
||||
{0, image_data_format::rgba_astc8x8, true},
|
||||
{0, image_data_format::rgba_astc10x10, true},
|
||||
{0, image_data_format::rgba_astc12x12, true},
|
||||
|
||||
{0, image_data_format::rgb_pvrtc2, true},
|
||||
{0, image_data_format::rgb_pvrtc4, true},
|
||||
{0, image_data_format::rgba_pvrtc2, true},
|
||||
{0, image_data_format::rgba_pvrtc4, true},
|
||||
|
||||
{0, image_data_format::rgba_pvrtc2_v2, true},
|
||||
{0, image_data_format::rgba_pvrtc4_v2, true}
|
||||
};
|
||||
|
||||
const data_format_description& get_data_format_description(image_data_format format) noexcept {
|
||||
@@ -119,14 +131,6 @@ namespace e2d
|
||||
return data_.empty();
|
||||
}
|
||||
|
||||
color image::pixel(u32 u, u32 v) const {
|
||||
return color(pixel32(u, v));
|
||||
}
|
||||
|
||||
color image::pixel(const v2u& uv) const {
|
||||
return color(pixel32(uv));
|
||||
}
|
||||
|
||||
color32 image::pixel32(u32 u, u32 v) const {
|
||||
const data_format_description& format_desc =
|
||||
get_data_format_description(format_);
|
||||
@@ -135,25 +139,26 @@ namespace e2d
|
||||
throw bad_image_access();
|
||||
}
|
||||
|
||||
const std::size_t bits_per_pixel = format_desc.bits_per_pixel;
|
||||
const std::size_t bytes_per_pixel = bits_per_pixel / 8;
|
||||
const std::size_t bytes_per_pixel = format_desc.uncompressed_bytes_per_pixel;
|
||||
const std::size_t stride_in_bytes = size_.x * bytes_per_pixel;
|
||||
E2D_ASSERT(bits_per_pixel % 8 == 0);
|
||||
|
||||
const std::size_t pixel_index = v * stride_in_bytes + u * bytes_per_pixel;
|
||||
E2D_ASSERT(pixel_index + bytes_per_pixel <= data_.size());
|
||||
const u8* const pixel = data_.data() + pixel_index;
|
||||
|
||||
switch ( format_ ) {
|
||||
case image_data_format::g8:
|
||||
case image_data_format::a8:
|
||||
E2D_ASSERT(bytes_per_pixel == 1);
|
||||
return color32(pixel[0], pixel[0], pixel[0]);
|
||||
case image_data_format::ga8:
|
||||
return color32(0, 0, 0, pixel[0]);
|
||||
case image_data_format::l8:
|
||||
E2D_ASSERT(bytes_per_pixel == 1);
|
||||
return color32(pixel[0], pixel[0], pixel[0], 255);
|
||||
case image_data_format::la8:
|
||||
E2D_ASSERT(bytes_per_pixel == 2);
|
||||
return color32(pixel[0], pixel[0], pixel[0], pixel[1]);
|
||||
case image_data_format::rgb8:
|
||||
E2D_ASSERT(bytes_per_pixel == 3);
|
||||
return color32(pixel[0], pixel[1], pixel[2]);
|
||||
return color32(pixel[0], pixel[1], pixel[2], 255);
|
||||
case image_data_format::rgba8:
|
||||
E2D_ASSERT(bytes_per_pixel == 4);
|
||||
return color32(pixel[0], pixel[1], pixel[2], pixel[3]);
|
||||
@@ -201,7 +206,7 @@ namespace e2d::images
|
||||
{
|
||||
bool try_load_image(
|
||||
image& dst,
|
||||
const buffer& src) noexcept
|
||||
buffer_view src) noexcept
|
||||
{
|
||||
try {
|
||||
return impl::load_image_dds(dst, src)
|
||||
@@ -256,4 +261,25 @@ namespace e2d::images
|
||||
return try_save_image(src, format, file_data)
|
||||
&& streams::try_write_tail(file_data, dst);
|
||||
}
|
||||
|
||||
bool check_save_image_support(
|
||||
const image& src,
|
||||
image_file_format format) noexcept
|
||||
{
|
||||
switch ( format ) {
|
||||
case image_file_format::dds:
|
||||
return impl::check_save_image_dds(src);
|
||||
case image_file_format::jpg:
|
||||
return impl::check_save_image_jpg(src);
|
||||
case image_file_format::png:
|
||||
return impl::check_save_image_png(src);
|
||||
case image_file_format::pvr:
|
||||
return impl::check_save_image_pvr(src);
|
||||
case image_file_format::tga:
|
||||
return impl::check_save_image_tga(src);
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected image file format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,106 @@
|
||||
|
||||
#include <enduro2d/utils/image.hpp>
|
||||
#include <enduro2d/utils/buffer.hpp>
|
||||
#include <enduro2d/utils/buffer_view.hpp>
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool load_image_dds(image& dst, const buffer& src);
|
||||
bool load_image_pvr(image& dst, const buffer& src);
|
||||
bool load_image_stb(image& dst, const buffer& src);
|
||||
bool load_image_dds(image& dst, buffer_view src);
|
||||
bool load_image_pvr(image& dst, buffer_view src);
|
||||
bool load_image_stb(image& dst, buffer_view src);
|
||||
|
||||
bool save_image_dds(const image& src, buffer& dst);
|
||||
bool save_image_jpg(const image& src, buffer& dst);
|
||||
bool save_image_png(const image& src, buffer& dst);
|
||||
bool save_image_pvr(const image& src, buffer& dst);
|
||||
bool save_image_tga(const image& src, buffer& dst);
|
||||
|
||||
bool check_save_image_dds(const image& src) noexcept;
|
||||
bool check_save_image_jpg(const image& src) noexcept;
|
||||
bool check_save_image_png(const image& src) noexcept;
|
||||
bool check_save_image_pvr(const image& src) noexcept;
|
||||
bool check_save_image_tga(const image& src) noexcept;
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
inline std::size_t bgr8_to_rgb8(u8* dst, buffer_view src) noexcept {
|
||||
E2D_ASSERT(src.size() % 3 == 0);
|
||||
const std::size_t dst_size = src.size() / 3 * 3;
|
||||
if ( !dst ) {
|
||||
return dst_size;
|
||||
}
|
||||
const u8* data = static_cast<const u8*>(src.data());
|
||||
for ( std::size_t i = 0; i < dst_size / 3; ++i ) {
|
||||
const u8 b = data[0];
|
||||
const u8 g = data[1];
|
||||
const u8 r = data[2];
|
||||
dst[0] = r;
|
||||
dst[1] = g;
|
||||
dst[2] = b;
|
||||
dst += 3;
|
||||
data += 3;
|
||||
}
|
||||
return dst_size;
|
||||
}
|
||||
|
||||
inline std::size_t bgrx8_to_rgb8(u8* dst, buffer_view src) noexcept {
|
||||
E2D_ASSERT(src.size() % 4 == 0);
|
||||
const std::size_t dst_size = src.size() / 4 * 3;
|
||||
if ( !dst ) {
|
||||
return dst_size;
|
||||
}
|
||||
const u8* data = static_cast<const u8*>(src.data());
|
||||
for ( std::size_t i = 0; i < dst_size / 3; ++i ) {
|
||||
const u8 b = data[0];
|
||||
const u8 g = data[1];
|
||||
const u8 r = data[2];
|
||||
dst[0] = r;
|
||||
dst[1] = g;
|
||||
dst[2] = b;
|
||||
dst += 3;
|
||||
data += 4;
|
||||
}
|
||||
return dst_size;
|
||||
}
|
||||
|
||||
inline std::size_t bgra8_to_rgba8(u8* dst, buffer_view src) noexcept {
|
||||
E2D_ASSERT(src.size() % 4 == 0);
|
||||
const std::size_t dst_size = src.size() / 4 * 4;
|
||||
if ( !dst ) {
|
||||
return dst_size;
|
||||
}
|
||||
const u8* data = static_cast<const u8*>(src.data());
|
||||
for ( std::size_t i = 0; i < dst_size / 4; ++i ) {
|
||||
const u8 b = data[0];
|
||||
const u8 g = data[1];
|
||||
const u8 r = data[2];
|
||||
const u8 a = data[3];
|
||||
dst[0] = r;
|
||||
dst[1] = g;
|
||||
dst[2] = b;
|
||||
dst[3] = a;
|
||||
dst += 4;
|
||||
data += 4;
|
||||
}
|
||||
return dst_size;
|
||||
}
|
||||
|
||||
inline buffer bgr8_to_rgb8(buffer_view src) {
|
||||
buffer result(bgr8_to_rgb8(nullptr, src));
|
||||
bgr8_to_rgb8(result.data(), src);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline buffer bgrx8_to_rgb8(buffer_view src) {
|
||||
buffer result(bgrx8_to_rgb8(nullptr, src));
|
||||
bgrx8_to_rgb8(result.data(), src);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline buffer bgra8_to_rgba8(buffer_view src) {
|
||||
buffer result(bgra8_to_rgba8(nullptr, src));
|
||||
bgra8_to_rgba8(result.data(), src);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
80
sources/enduro2d/utils/image_impl/image_impl_dds.hpp
Normal file
80
sources/enduro2d/utils/image_impl/image_impl_dds.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <enduro2d/utils/_utils.hpp>
|
||||
|
||||
namespace e2d::images::impl::dds
|
||||
{
|
||||
// DDS format specification:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide
|
||||
|
||||
// header flags
|
||||
const u32 dds_hf_caps = 0x00000001;
|
||||
const u32 dds_hf_height = 0x00000002;
|
||||
const u32 dds_hf_width = 0x00000004;
|
||||
const u32 dds_hf_pitch = 0x00000008;
|
||||
const u32 dds_hf_pixel_format = 0x00001000;
|
||||
const u32 dds_hf_mipmap_count = 0x00020000;
|
||||
const u32 dds_hf_linear_size = 0x00080000;
|
||||
const u32 dds_hf_depth = 0x00800000;
|
||||
|
||||
// pixel format flags
|
||||
const u32 dds_pff_alphapixels = 0x1;
|
||||
const u32 dds_pff_alpha = 0x2;
|
||||
const u32 dds_pff_fourcc = 0x4;
|
||||
const u32 dds_pff_rgb = 0x40;
|
||||
const u32 dds_pff_yuv = 0x200;
|
||||
const u32 dds_pff_luminance = 0x20000;
|
||||
|
||||
// caps flags
|
||||
const u32 dds_caps_complex = 0x8;
|
||||
const u32 dds_caps_mipmap = 0x400000;
|
||||
const u32 dds_caps_texture = 0x1000;
|
||||
|
||||
// caps2 flags
|
||||
const u32 dds_caps2_cubemap = 0x200;
|
||||
const u32 dds_caps2_volume = 0x200000;
|
||||
|
||||
struct dds_pixel_format {
|
||||
u32 size{0};
|
||||
u32 flags{0};
|
||||
u32 fourcc{0};
|
||||
u32 rgbbit_count{0};
|
||||
u32 rbit_mask{0};
|
||||
u32 gbit_mask{0};
|
||||
u32 bbit_mask{0};
|
||||
u32 abit_mask{0};
|
||||
};
|
||||
|
||||
struct dds_header {
|
||||
u32 magic{0};
|
||||
u32 size{0};
|
||||
u32 flags{0};
|
||||
u32 height{0};
|
||||
u32 width{0};
|
||||
u32 pitch_or_linear_size{0};
|
||||
u32 depth{0};
|
||||
u32 mipmap_count{0};
|
||||
u32 reserved1[11] = {0};
|
||||
dds_pixel_format pf;
|
||||
u32 caps{0};
|
||||
u32 caps2{0};
|
||||
u32 reserved2[3] = {0};
|
||||
};
|
||||
|
||||
static_assert(sizeof(dds_pixel_format) == 32, "invalid dds_pixel_format structure size");
|
||||
static_assert(sizeof(dds_header) == 128, "invalid dds_header structure size");
|
||||
|
||||
inline constexpr u32 make_fourcc(u8 a, u8 b, u8 c, u8 d) noexcept {
|
||||
return
|
||||
(static_cast<u32>(a)) |
|
||||
(static_cast<u32>(b) << 8) |
|
||||
(static_cast<u32>(c) << 16) |
|
||||
(static_cast<u32>(d) << 24);
|
||||
}
|
||||
}
|
||||
137
sources/enduro2d/utils/image_impl/image_impl_pvr.hpp
Normal file
137
sources/enduro2d/utils/image_impl/image_impl_pvr.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <enduro2d/utils/_utils.hpp>
|
||||
|
||||
namespace e2d::images::impl::pvr
|
||||
{
|
||||
// PVR format specification:
|
||||
// https://cdn.imgtec.com/sdk-documentation/PVR+File+Format.Specification.pdf
|
||||
|
||||
enum class pvr_flags : u32 {
|
||||
none = 0,
|
||||
premultiplied = 0x02,
|
||||
};
|
||||
|
||||
enum class pvr_pixel_format : u64 {
|
||||
pvrtc_2bpp_rgb = 0,
|
||||
pvrtc_2bpp_rgba = 1,
|
||||
pvrtc_4bpp_rgb = 2,
|
||||
pvrtc_4bpp_rgba = 3,
|
||||
pvrtc2_2bpp = 4,
|
||||
pvrtc2_4bpp = 5,
|
||||
etc1 = 6,
|
||||
dxt1 = 7,
|
||||
dxt2 = 8,
|
||||
dxt3 = 9,
|
||||
dxt4 = 10,
|
||||
dxt5 = 11,
|
||||
bc1 = 7,
|
||||
bc2 = 9,
|
||||
bc3 = 11,
|
||||
bc4 = 12,
|
||||
bc5 = 13,
|
||||
bc6 = 14,
|
||||
bc7 = 15,
|
||||
uyvy = 16,
|
||||
yuy2 = 17,
|
||||
bw_1bpp = 18,
|
||||
r9g9b9e5 = 19,
|
||||
rgbg8888 = 20,
|
||||
grgb8888 = 21,
|
||||
etc2_rgb = 22,
|
||||
etc2_rgba = 23,
|
||||
etc2_rgb_a1 = 24,
|
||||
eac_r11 = 25,
|
||||
eac_rg11 = 26,
|
||||
astc_4x4 = 27,
|
||||
astc_5x4 = 28,
|
||||
astc_5x5 = 29,
|
||||
astc_6x5 = 30,
|
||||
astc_6x6 = 31,
|
||||
astc_8x5 = 32,
|
||||
astc_8x6 = 33,
|
||||
astc_8x8 = 34,
|
||||
astc_10x5 = 35,
|
||||
astc_10x6 = 36,
|
||||
astc_10x8 = 37,
|
||||
astc_10x10 = 38,
|
||||
astc_12x10 = 39,
|
||||
astc_12x12 = 40,
|
||||
astc_3x3x3 = 41,
|
||||
astc_4x3x3 = 42,
|
||||
astc_4x4x3 = 43,
|
||||
astc_4x4x4 = 44,
|
||||
astc_5x4x4 = 45,
|
||||
astc_5x5x4 = 46,
|
||||
astc_5x5x5 = 47,
|
||||
astc_6x5x5 = 48,
|
||||
astc_6x6x5 = 49,
|
||||
astc_6x6x6 = 50,
|
||||
a8 = 0x00000008'00000061ull,
|
||||
l8 = 0x00000008'0000006Cull,
|
||||
la8 = 0x00000808'0000616CuLL,
|
||||
rgb8 = 0x00080808'00626772ull,
|
||||
rgba8 = 0x08080808'61626772ull,
|
||||
bgr8 = 0x08080808'00726762ull,
|
||||
bgra8 = 0x08080808'61726762ull,
|
||||
};
|
||||
|
||||
enum class pvr_color_space : u32 {
|
||||
linear = 0,
|
||||
srgb = 1,
|
||||
};
|
||||
|
||||
enum class pvr_channel_type : u32 {
|
||||
byte_unorm = 0,
|
||||
byte_snorm = 1,
|
||||
ubyte = 2,
|
||||
sbyte = 3,
|
||||
short_unorm = 4,
|
||||
short_snorm = 5,
|
||||
ushort = 6,
|
||||
sshort = 7,
|
||||
int_unorm = 8,
|
||||
int_snorm = 9,
|
||||
uint = 10,
|
||||
sint = 11,
|
||||
sfloat = 12,
|
||||
};
|
||||
|
||||
struct pvr_header {
|
||||
u32 version;
|
||||
u32 flags;
|
||||
u32 pixel_format0;
|
||||
u32 pixel_format1;
|
||||
u32 color_space;
|
||||
u32 channel_type;
|
||||
u32 height;
|
||||
u32 width;
|
||||
u32 depth;
|
||||
u32 num_surfaces;
|
||||
u32 num_faces;
|
||||
u32 mipmap_count;
|
||||
u32 meta_data_size;
|
||||
};
|
||||
|
||||
struct pvr_meta_data {
|
||||
u32 fourcc;
|
||||
u32 key;
|
||||
u32 data_size;
|
||||
};
|
||||
|
||||
static_assert(sizeof(pvr_header) == 52, "invalid pvr_header size");
|
||||
|
||||
inline constexpr u32 make_fourcc(u8 a, u8 b, u8 c, u8 d) noexcept {
|
||||
return
|
||||
(static_cast<u32>(a)) |
|
||||
(static_cast<u32>(b) << 8) |
|
||||
(static_cast<u32>(c) << 16) |
|
||||
(static_cast<u32>(d) << 24);
|
||||
}
|
||||
}
|
||||
@@ -5,157 +5,234 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "image_impl.hpp"
|
||||
#include "image_impl_dds.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
// DDS format specification:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide
|
||||
|
||||
using namespace e2d;
|
||||
using namespace e2d::images::impl;
|
||||
using namespace e2d::images::impl::dds;
|
||||
|
||||
// pixel format flags
|
||||
const u32 ddsf_alphapixels = 0x00000001;
|
||||
const u32 ddsf_fourcc = 0x00000004;
|
||||
const u32 ddsf_rgb = 0x00000040;
|
||||
const u32 ddsf_rgba = 0x00000041;
|
||||
struct image_info {
|
||||
buffer data;
|
||||
image_data_format format = image_data_format(-1);
|
||||
u32 bytes_per_block = 0;
|
||||
v2u block_size;
|
||||
|
||||
// dwCaps2 flags
|
||||
const u32 ddsf_cubemap = 0x00000200;
|
||||
const u32 ddsf_volume = 0x00200000;
|
||||
image_info() = default;
|
||||
image_info(buffer data, image_data_format format, u32 bytes_per_block, v2u block_size)
|
||||
: data(std::move(data))
|
||||
, format(format)
|
||||
, bytes_per_block(bytes_per_block)
|
||||
, block_size(block_size) {}
|
||||
|
||||
// compressed texture types
|
||||
const u32 fourcc_dxt1 = 0x31545844; // 'DXT1'
|
||||
const u32 fourcc_dxt3 = 0x33545844; // 'DXT3'
|
||||
const u32 fourcc_dxt5 = 0x35545844; // 'DXT5'
|
||||
|
||||
struct dds_pixel_format {
|
||||
u32 dwSize;
|
||||
u32 dwFlags;
|
||||
u32 dwFourCC;
|
||||
u32 dwRGBBitCount;
|
||||
u32 dwRBitMask;
|
||||
u32 dwGBitMask;
|
||||
u32 dwBBitMask;
|
||||
u32 dwABitMask;
|
||||
bool valid() const noexcept {
|
||||
return !data.empty()
|
||||
&& format != image_data_format(-1)
|
||||
&& bytes_per_block > 0
|
||||
&& block_size.x > 0
|
||||
&& block_size.y > 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct dds_header {
|
||||
u32 dwMagic;
|
||||
u32 dwSize;
|
||||
u32 dwFlags;
|
||||
u32 dwHeight;
|
||||
u32 dwWidth;
|
||||
u32 dwPitchOrLinearSize;
|
||||
u32 dwDepth;
|
||||
u32 dwMipMapCount;
|
||||
u32 dwReserved1[11];
|
||||
dds_pixel_format ddspf;
|
||||
u32 dwCaps1;
|
||||
u32 dwCaps2;
|
||||
u32 dwReserved2[3];
|
||||
};
|
||||
|
||||
static_assert(sizeof(dds_pixel_format) == 32, "invalid dds_pixel_format structure size");
|
||||
static_assert(sizeof(dds_header) == 128, "invalid dds_header structure size");
|
||||
|
||||
bool is_dds(const void* data, std::size_t byte_size) noexcept {
|
||||
if ( byte_size > sizeof(dds_header) ) {
|
||||
const auto* hdr = reinterpret_cast<const dds_header*>(data);
|
||||
return hdr->dwMagic == 0x20534444; // 'DDS '
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool get_dds_format(
|
||||
image_info extract_image_info(
|
||||
const dds_header& hdr,
|
||||
image_data_format& out_format,
|
||||
u32& out_bytes_per_block,
|
||||
v2u& out_block_size) noexcept
|
||||
buffer_view content)
|
||||
{
|
||||
if ( math::check_all_flags(hdr.ddspf.dwFlags, ddsf_fourcc) ) {
|
||||
switch ( hdr.ddspf.dwFourCC ) {
|
||||
case fourcc_dxt1:
|
||||
out_format = math::check_all_flags(hdr.ddspf.dwFlags, ddsf_alphapixels)
|
||||
? image_data_format::rgba_dxt1
|
||||
: image_data_format::rgb_dxt1;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
case fourcc_dxt3:
|
||||
out_format = image_data_format::rgba_dxt3;
|
||||
out_bytes_per_block = 16;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
case fourcc_dxt5:
|
||||
out_format = image_data_format::rgba_dxt5;
|
||||
out_bytes_per_block = 16;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
if ( math::check_all_flags(hdr.pf.flags, dds_pff_fourcc) ) {
|
||||
switch ( hdr.pf.fourcc ) {
|
||||
case make_fourcc('D', 'X', 'T', '1'):
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_dxt1,
|
||||
8,
|
||||
{4,4}};
|
||||
case make_fourcc('D', 'X', 'T', '2'):
|
||||
case make_fourcc('D', 'X', 'T', '3'):
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_dxt3,
|
||||
16,
|
||||
{4,4}};
|
||||
case make_fourcc('D', 'X', 'T', '4'):
|
||||
case make_fourcc('D', 'X', 'T', '5'):
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_dxt5,
|
||||
16,
|
||||
{4,4}};
|
||||
}
|
||||
} else if ( math::check_all_flags(hdr.ddspf.dwFlags, ddsf_rgba) && (hdr.ddspf.dwRGBBitCount == 32) ) {
|
||||
out_format = image_data_format::rgba8;
|
||||
out_bytes_per_block = 4;
|
||||
out_block_size = v2u(1,1);
|
||||
if ( hdr.ddspf.dwRBitMask == 0x00FF0000 ) {
|
||||
return false; // BGRA format is not supported
|
||||
}
|
||||
} else if ( math::check_all_flags(hdr.ddspf.dwFlags, ddsf_rgb) && (hdr.ddspf.dwRGBBitCount == 24) ) {
|
||||
out_format = image_data_format::rgb8;
|
||||
out_bytes_per_block = 3;
|
||||
out_block_size = v2u(1,1);
|
||||
if (hdr.ddspf.dwRBitMask == 0x00FF0000) {
|
||||
return false; // BGRA format is not supported
|
||||
|
||||
if ( math::check_all_flags(hdr.pf.flags, dds_pff_alpha) ) {
|
||||
if ( hdr.pf.rgbbit_count == 8 &&
|
||||
hdr.pf.abit_mask == 0x000000FF )
|
||||
{
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::a8,
|
||||
1,
|
||||
{1,1}};
|
||||
}
|
||||
} else if ( hdr.ddspf.dwRGBBitCount == 16 ) {
|
||||
return false; // 16-bit format is not supported by engine
|
||||
} else if ( hdr.ddspf.dwRGBBitCount == 8 ) {
|
||||
out_format = image_data_format::g8;
|
||||
out_bytes_per_block = 1;
|
||||
out_block_size = v2u(1,1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
if ( math::check_all_flags(hdr.pf.flags, dds_pff_luminance | dds_pff_alphapixels) ) {
|
||||
if ( hdr.pf.rgbbit_count == 16 &&
|
||||
hdr.pf.rbit_mask == 0x000000FF &&
|
||||
hdr.pf.abit_mask == 0x0000FF00 )
|
||||
{
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::la8,
|
||||
2,
|
||||
{1,1}};
|
||||
}
|
||||
}
|
||||
|
||||
if ( math::check_all_flags(hdr.pf.flags, dds_pff_luminance) ) {
|
||||
if ( hdr.pf.rgbbit_count == 8 &&
|
||||
hdr.pf.rbit_mask == 0x000000FF )
|
||||
{
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::l8,
|
||||
1,
|
||||
{1,1}};
|
||||
}
|
||||
}
|
||||
|
||||
if ( math::check_all_flags(hdr.pf.flags, dds_pff_rgb | dds_pff_alphapixels) ) {
|
||||
if ( hdr.pf.rgbbit_count == 8 ) {
|
||||
if ( hdr.pf.rbit_mask == 0x00000000 &&
|
||||
hdr.pf.gbit_mask == 0x00000000 &&
|
||||
hdr.pf.bbit_mask == 0x00000000 &&
|
||||
hdr.pf.abit_mask == 0x000000FF )
|
||||
{
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::a8,
|
||||
1,
|
||||
{1,1}};
|
||||
}
|
||||
}
|
||||
|
||||
if ( hdr.pf.rgbbit_count == 32 ) {
|
||||
if ( hdr.pf.rbit_mask == 0x000000FF &&
|
||||
hdr.pf.gbit_mask == 0x0000FF00 &&
|
||||
hdr.pf.bbit_mask == 0x00FF0000 &&
|
||||
hdr.pf.abit_mask == 0xFF000000 )
|
||||
{
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba8,
|
||||
4,
|
||||
{1,1}};
|
||||
}
|
||||
|
||||
if ( hdr.pf.rbit_mask == 0x00FF0000 &&
|
||||
hdr.pf.gbit_mask == 0x0000FF00 &&
|
||||
hdr.pf.bbit_mask == 0x000000FF &&
|
||||
hdr.pf.abit_mask == 0xFF000000 )
|
||||
{
|
||||
return {
|
||||
bgra8_to_rgba8(content),
|
||||
image_data_format::rgba8,
|
||||
4,
|
||||
{1,1}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( math::check_all_flags(hdr.pf.flags, dds_pff_rgb) ) {
|
||||
if ( hdr.pf.rgbbit_count == 24 ) {
|
||||
if ( hdr.pf.rbit_mask == 0x000000FF &&
|
||||
hdr.pf.gbit_mask == 0x0000FF00 &&
|
||||
hdr.pf.bbit_mask == 0x00FF0000 )
|
||||
{
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgb8,
|
||||
3,
|
||||
{1,1}};
|
||||
}
|
||||
|
||||
if ( hdr.pf.rbit_mask == 0x00FF0000 &&
|
||||
hdr.pf.gbit_mask == 0x0000FF00 &&
|
||||
hdr.pf.bbit_mask == 0x000000FF )
|
||||
{
|
||||
return {
|
||||
bgr8_to_rgb8(content),
|
||||
image_data_format::rgb8,
|
||||
3,
|
||||
{1,1}};
|
||||
}
|
||||
}
|
||||
|
||||
if ( hdr.pf.rgbbit_count == 32 ) {
|
||||
if ( hdr.pf.rbit_mask == 0x00FF0000 &&
|
||||
hdr.pf.gbit_mask == 0x0000FF00 &&
|
||||
hdr.pf.bbit_mask == 0x000000FF )
|
||||
{
|
||||
return {
|
||||
bgrx8_to_rgb8(content),
|
||||
image_data_format::rgb8,
|
||||
3,
|
||||
{1,1}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image_info();
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool load_image_dds(image& dst, const buffer& src) {
|
||||
if ( !is_dds(src.data(), src.size()) ) {
|
||||
bool load_image_dds(image& dst, buffer_view src) {
|
||||
if ( src.size() < sizeof(dds_header) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dds_header& hdr = *reinterpret_cast<const dds_header*>(src.data());
|
||||
const u8* content = src.data() + sizeof(dds_header);
|
||||
const std::size_t content_size = static_cast<std::size_t>(src.data() + src.size() - content);
|
||||
|
||||
if ( math::check_all_flags(hdr.dwCaps2, ddsf_cubemap) ||
|
||||
math::check_all_flags(hdr.dwCaps2, ddsf_volume) ||
|
||||
(hdr.dwDepth > 0) )
|
||||
if ( hdr.magic != make_fourcc('D', 'D', 'S', ' ') ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( hdr.size != sizeof(dds_header) - sizeof(hdr.magic) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( hdr.pf.size != sizeof(dds_pixel_format) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( math::check_any_flags(hdr.caps, dds_caps_complex | dds_caps_mipmap) ||
|
||||
math::check_any_flags(hdr.caps2, dds_caps2_cubemap | dds_caps2_volume) ||
|
||||
hdr.depth > 1 ||
|
||||
hdr.mipmap_count > 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
image_data_format format = image_data_format(-1);
|
||||
u32 bytes_per_block = 0;
|
||||
v2u block_size = v2u(1,1);
|
||||
if ( !get_dds_format(hdr, format, bytes_per_block, block_size) ) {
|
||||
image_info info = extract_image_info(hdr, {
|
||||
static_cast<const u8*>(src.data()) + sizeof(dds_header),
|
||||
src.size() - sizeof(dds_header)});
|
||||
|
||||
if ( !info.valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const v2u dimension = v2u(hdr.dwWidth, hdr.dwHeight);
|
||||
const std::size_t size = bytes_per_block *
|
||||
((dimension.x + block_size.x - 1) / block_size.x) *
|
||||
((dimension.y + block_size.y - 1) / block_size.y);
|
||||
const v2u dimension = v2u(hdr.width, hdr.height);
|
||||
const std::size_t expected_image_data_size = info.bytes_per_block *
|
||||
((dimension.x + info.block_size.x - 1) / info.block_size.x) *
|
||||
((dimension.y + info.block_size.y - 1) / info.block_size.y);
|
||||
|
||||
if ( content_size != size ) {
|
||||
if ( info.data.size() != expected_image_data_size ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dst = image(dimension, format, buffer(content, size));
|
||||
dst = image(dimension, info.format, std::move(info.data));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,234 +5,256 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "image_impl.hpp"
|
||||
#include "image_impl_pvr.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
// PVR format specification:
|
||||
// https://cdn.imgtec.com/sdk-documentation/PVR+File+Format.Specification.pdf
|
||||
|
||||
using namespace e2d;
|
||||
using namespace e2d::images::impl;
|
||||
using namespace e2d::images::impl::pvr;
|
||||
|
||||
enum class pvr_flags : u32 {
|
||||
none = 0,
|
||||
premultiplied = 0x02,
|
||||
};
|
||||
struct image_info {
|
||||
buffer data;
|
||||
image_data_format format = image_data_format(-1);
|
||||
u32 bytes_per_block = 0;
|
||||
v2u block_size;
|
||||
|
||||
enum class pvr_pixel_format : u64 {
|
||||
pvrtc_2bpp_rgb = 0,
|
||||
pvrtc_2bpp_rgba = 1,
|
||||
pvrtc_4bpp_rgb = 2,
|
||||
pvrtc_4bpp_rgba = 3,
|
||||
pvrtc_ii_2bpp = 4,
|
||||
pvrtc_ii_4bpp = 5,
|
||||
etc1 = 6,
|
||||
dxt1 = 7,
|
||||
dxt2 = 8,
|
||||
dxt3 = 9,
|
||||
dxt4 = 10,
|
||||
dxt5 = 11,
|
||||
bc1 = 7,
|
||||
bc2 = 9,
|
||||
bc3 = 11,
|
||||
bc4 = 12,
|
||||
bc5 = 13,
|
||||
bc6 = 14,
|
||||
bc7 = 15,
|
||||
uyvy = 16,
|
||||
yuy2 = 17,
|
||||
bw_1bpp = 18,
|
||||
r9g9b9e5 = 19,
|
||||
rgbg8888 = 20,
|
||||
grgb8888 = 21,
|
||||
etc2_rgb = 22,
|
||||
etc2_rgba = 23,
|
||||
etc2_rgb_a1 = 24,
|
||||
eac_r11 = 25,
|
||||
eac_rg11 = 26,
|
||||
astc_4x4 = 27,
|
||||
astc_5x4 = 28,
|
||||
astc_5x5 = 29,
|
||||
astc_6x5 = 30,
|
||||
astc_6x6 = 31,
|
||||
astc_8x5 = 32,
|
||||
astc_8x6 = 33,
|
||||
astc_8x8 = 34,
|
||||
astc_10x5 = 35,
|
||||
astc_10x6 = 36,
|
||||
astc_10x8 = 37,
|
||||
astc_10x10 = 38,
|
||||
astc_12x10 = 39,
|
||||
astc_12x12 = 40,
|
||||
rgba8 = 0x08080808'61626772ull,
|
||||
r8 = 0x00000008'00000072ull,
|
||||
rg8 = 0x00000808'00006772ull,
|
||||
rgb8 = 0x00080808'00626772ull,
|
||||
};
|
||||
image_info() = default;
|
||||
image_info(buffer data, image_data_format format, u32 bytes_per_block, v2u block_size)
|
||||
: data(std::move(data))
|
||||
, format(format)
|
||||
, bytes_per_block(bytes_per_block)
|
||||
, block_size(block_size) {}
|
||||
|
||||
enum class pvr_color_space : u32 {
|
||||
linear = 0,
|
||||
srgb = 1,
|
||||
};
|
||||
|
||||
enum class pvr_channel_type : u32 {
|
||||
byte_unorm = 0,
|
||||
byte_snorm = 1,
|
||||
ubyte = 2,
|
||||
sbyte = 3,
|
||||
short_unorm = 4,
|
||||
short_snorm = 5,
|
||||
ushort = 6,
|
||||
sshort = 7,
|
||||
int_unorm = 8,
|
||||
int_snorm = 9,
|
||||
uint = 10,
|
||||
sint = 11,
|
||||
sfloat = 12,
|
||||
};
|
||||
|
||||
struct pvr_header {
|
||||
u32 version;
|
||||
u32 flags;
|
||||
u32 pixelFormat0;
|
||||
u32 pixelFormat1;
|
||||
u32 colorSpace;
|
||||
u32 channelType;
|
||||
u32 height;
|
||||
u32 width;
|
||||
u32 depth;
|
||||
u32 numSurfaces;
|
||||
u32 numFaces;
|
||||
u32 mipMapCount;
|
||||
u32 metaDataSize;
|
||||
};
|
||||
|
||||
static_assert(sizeof(pvr_header) == 52, "invalid PVR header size");
|
||||
|
||||
bool is_pvr(const void* data, std::size_t byte_size) noexcept {
|
||||
if ( byte_size > sizeof(pvr_header) ) {
|
||||
const pvr_header* hdr = reinterpret_cast<const pvr_header*>(data);
|
||||
return hdr->version == 0x03525650;
|
||||
}
|
||||
return false;
|
||||
bool valid() const noexcept {
|
||||
return !data.empty()
|
||||
&& format != image_data_format(-1)
|
||||
&& bytes_per_block > 0
|
||||
&& block_size.x > 0
|
||||
&& block_size.y > 0;
|
||||
}
|
||||
};
|
||||
|
||||
bool get_pvr_format(
|
||||
image_info extract_image_info(
|
||||
const pvr_header& hdr,
|
||||
image_data_format& out_format,
|
||||
u32& out_bytes_per_block,
|
||||
v2u& out_block_size) noexcept
|
||||
buffer_view content) noexcept
|
||||
{
|
||||
if ( pvr_color_space(hdr.colorSpace) != pvr_color_space::linear ) {
|
||||
return false;
|
||||
if ( pvr_color_space(hdr.color_space) != pvr_color_space::linear ) {
|
||||
return image_info();
|
||||
}
|
||||
|
||||
const pvr_pixel_format fmt = pvr_pixel_format(
|
||||
hdr.pixelFormat0 | (u64(hdr.pixelFormat1) << 32));
|
||||
switch (fmt)
|
||||
{
|
||||
(static_cast<u64>(hdr.pixel_format0)) |
|
||||
(static_cast<u64>(hdr.pixel_format1) << 32));
|
||||
|
||||
switch ( fmt ) {
|
||||
case pvr_pixel_format::pvrtc_2bpp_rgb:
|
||||
out_format = image_data_format::rgb_pvrtc2;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(8,4);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgb_pvrtc2,
|
||||
8,
|
||||
{8,4}};
|
||||
case pvr_pixel_format::pvrtc_2bpp_rgba:
|
||||
out_format = image_data_format::rgba_pvrtc2;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(8,4);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_pvrtc2,
|
||||
8,
|
||||
{8,4}};
|
||||
case pvr_pixel_format::pvrtc_4bpp_rgb:
|
||||
out_format = image_data_format::rgb_pvrtc4;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgb_pvrtc4,
|
||||
8,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::pvrtc_4bpp_rgba:
|
||||
out_format = image_data_format::rgba_pvrtc4;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
case pvr_pixel_format::pvrtc_ii_2bpp:
|
||||
out_format = image_data_format::rgba_pvrtc2_v2;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(8,4);
|
||||
break;
|
||||
case pvr_pixel_format::pvrtc_ii_4bpp:
|
||||
out_format = image_data_format::rgba_pvrtc4_v2;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_pvrtc4,
|
||||
8,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::pvrtc2_2bpp:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_pvrtc2_v2,
|
||||
8,
|
||||
{8,4}};
|
||||
case pvr_pixel_format::pvrtc2_4bpp:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_pvrtc4_v2,
|
||||
8,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::etc1:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgb_etc1,
|
||||
8,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::dxt1:
|
||||
out_format = image_data_format::rgb_dxt1;
|
||||
out_bytes_per_block = 8;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_dxt1,
|
||||
8,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::dxt2:
|
||||
case pvr_pixel_format::dxt3:
|
||||
out_format = image_data_format::rgba_dxt3;
|
||||
out_bytes_per_block = 16;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_dxt3,
|
||||
16,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::dxt4:
|
||||
case pvr_pixel_format::dxt5:
|
||||
out_format = image_data_format::rgba_dxt5;
|
||||
out_bytes_per_block = 16;
|
||||
out_block_size = v2u(4,4);
|
||||
break;
|
||||
case pvr_pixel_format::rgba8:
|
||||
out_format = image_data_format::rgba8;
|
||||
out_bytes_per_block = 4;
|
||||
out_block_size = v2u(1,1);
|
||||
break;
|
||||
case pvr_pixel_format::r8:
|
||||
out_format = image_data_format::g8;
|
||||
out_bytes_per_block = 1;
|
||||
out_block_size = v2u(1,1);
|
||||
break;
|
||||
case pvr_pixel_format::rg8:
|
||||
out_format = image_data_format::ga8;
|
||||
out_bytes_per_block = 2;
|
||||
out_block_size = v2u(1,1);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_dxt5,
|
||||
16,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::etc2_rgb:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgb_etc2,
|
||||
8,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::etc2_rgba:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_etc2,
|
||||
16,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::etc2_rgb_a1:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgb_a1_etc2,
|
||||
8,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::astc_4x4:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_astc4x4,
|
||||
16,
|
||||
{4,4}};
|
||||
case pvr_pixel_format::astc_5x5:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_astc5x5,
|
||||
16,
|
||||
{5,5}};
|
||||
case pvr_pixel_format::astc_6x6:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_astc6x6,
|
||||
16,
|
||||
{6,6}};
|
||||
case pvr_pixel_format::astc_8x8:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_astc8x8,
|
||||
16,
|
||||
{8,8}};
|
||||
case pvr_pixel_format::astc_10x10:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_astc10x10,
|
||||
16,
|
||||
{10,10}};
|
||||
case pvr_pixel_format::astc_12x12:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba_astc12x12,
|
||||
16,
|
||||
{12,12}};
|
||||
case pvr_pixel_format::a8:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::a8,
|
||||
1,
|
||||
{1,1}};
|
||||
case pvr_pixel_format::l8:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::l8,
|
||||
1,
|
||||
{1,1}};
|
||||
case pvr_pixel_format::la8:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::la8,
|
||||
2,
|
||||
{1,1}};
|
||||
case pvr_pixel_format::rgb8:
|
||||
out_format = image_data_format::rgb8;
|
||||
out_bytes_per_block = 3;
|
||||
out_block_size = v2u(1,1);
|
||||
break;
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgb8,
|
||||
3,
|
||||
{1,1}};
|
||||
case pvr_pixel_format::rgba8:
|
||||
return {
|
||||
buffer(content),
|
||||
image_data_format::rgba8,
|
||||
4,
|
||||
{1,1}};
|
||||
case pvr_pixel_format::bgr8:
|
||||
return {
|
||||
bgr8_to_rgb8(content),
|
||||
image_data_format::rgb8,
|
||||
3,
|
||||
{1,1}};
|
||||
case pvr_pixel_format::bgra8:
|
||||
return {
|
||||
bgra8_to_rgba8(content),
|
||||
image_data_format::rgba8,
|
||||
4,
|
||||
{1,1}};
|
||||
default:
|
||||
return false;
|
||||
return image_info();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool load_image_pvr(image& dst, const buffer& src) {
|
||||
if ( !is_pvr(src.data(), src.size()) ) {
|
||||
bool load_image_pvr(image& dst, buffer_view src) {
|
||||
if ( src.size() < sizeof(pvr_header) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const pvr_header& hdr = *reinterpret_cast<const pvr_header*>(src.data());
|
||||
const u8* content = src.data() + sizeof(pvr_header) + hdr.metaDataSize;
|
||||
const std::size_t content_size = static_cast<std::size_t>(src.data() + src.size() - content);
|
||||
|
||||
if ( hdr.numSurfaces != 1 || hdr.numFaces != 1 || hdr.depth > 1 ) {
|
||||
return false; // cubemap and volume textures are not supported
|
||||
if ( hdr.version != make_fourcc('P', 'V', 'R', 3) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
image_data_format format = image_data_format(-1);
|
||||
u32 bytes_per_block = 0;
|
||||
v2u block_size = v2u(1,1);
|
||||
if ( !get_pvr_format(hdr, format, bytes_per_block, block_size) ) {
|
||||
if ( src.size() < sizeof(pvr_header) + hdr.meta_data_size ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( hdr.mipmap_count > 1 ||
|
||||
hdr.num_surfaces > 1 ||
|
||||
hdr.num_faces > 1 ||
|
||||
hdr.depth > 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
image_info info = extract_image_info(hdr, {
|
||||
static_cast<const u8*>(src.data()) + sizeof(pvr_header) + hdr.meta_data_size,
|
||||
src.size() - sizeof(pvr_header) - hdr.meta_data_size});
|
||||
|
||||
if ( !info.valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const v2u dimension = v2u(hdr.width, hdr.height);
|
||||
const std::size_t size = bytes_per_block *
|
||||
((dimension.x + block_size.x - 1) / block_size.x) *
|
||||
((dimension.y + block_size.y - 1) / block_size.y);
|
||||
const std::size_t expected_image_data_size = info.bytes_per_block *
|
||||
((dimension.x + info.block_size.x - 1) / info.block_size.x) *
|
||||
((dimension.y + info.block_size.y - 1) / info.block_size.y);
|
||||
|
||||
if ( content_size != size ) {
|
||||
if ( info.data.size() != expected_image_data_size ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dst = image(dimension, format, buffer(content, size));
|
||||
dst = image(dimension, info.format, std::move(info.data));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace
|
||||
|
||||
using stbi_img_uptr = std::unique_ptr<stbi_uc, decltype(&stbi_image_free)>;
|
||||
|
||||
stbi_img_uptr load_stb_image(const buffer& data, v2u& out_size, u32& out_channels) noexcept {
|
||||
stbi_img_uptr load_stb_image(buffer_view data, v2u& out_size, u32& out_channels) noexcept {
|
||||
int img_w = 0, img_h = 0, img_c = 0;
|
||||
stbi_uc* img = stbi_load_from_memory(
|
||||
static_cast<const stbi_uc*>(data.data()),
|
||||
@@ -48,8 +48,8 @@ namespace
|
||||
|
||||
image_data_format image_format_from_stb_channels(u32 channels) noexcept {
|
||||
switch ( channels ) {
|
||||
case 1: return image_data_format::g8;
|
||||
case 2: return image_data_format::ga8;
|
||||
case 1: return image_data_format::l8;
|
||||
case 2: return image_data_format::la8;
|
||||
case 3: return image_data_format::rgb8;
|
||||
case 4: return image_data_format::rgba8;
|
||||
default:
|
||||
@@ -61,7 +61,7 @@ namespace
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool load_image_stb(image& dst, const buffer& src) {
|
||||
bool load_image_stb(image& dst, buffer_view src) {
|
||||
v2u img_size;
|
||||
u32 img_channels = 0;
|
||||
const stbi_img_uptr img_ptr = load_stb_image(src, img_size, img_channels);
|
||||
|
||||
@@ -5,18 +5,24 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "image_impl.hpp"
|
||||
#include "image_impl_dds.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace e2d;
|
||||
using namespace e2d::images::impl::dds;
|
||||
}
|
||||
|
||||
bool is_save_image_dds_supported(image_data_format data_format) noexcept {
|
||||
switch ( data_format ) {
|
||||
case image_data_format::g8:
|
||||
case image_data_format::ga8:
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool check_save_image_dds(const image& src) noexcept {
|
||||
switch ( src.format() ) {
|
||||
case image_data_format::a8:
|
||||
case image_data_format::l8:
|
||||
case image_data_format::la8:
|
||||
case image_data_format::rgb8:
|
||||
case image_data_format::rgba8:
|
||||
case image_data_format::rgb_dxt1:
|
||||
|
||||
case image_data_format::rgba_dxt1:
|
||||
case image_data_format::rgba_dxt3:
|
||||
case image_data_format::rgba_dxt5:
|
||||
@@ -25,16 +31,110 @@ namespace
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool save_image_dds(const image& src, buffer& dst) {
|
||||
E2D_UNUSED(src, dst);
|
||||
if ( is_save_image_dds_supported(src.format()) ) {
|
||||
//TODO(BlackMat): implme
|
||||
E2D_ASSERT_MSG(false, "implme");
|
||||
}
|
||||
if ( !check_save_image_dds(src) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dds_header hdr;
|
||||
hdr.magic = make_fourcc('D', 'D', 'S', ' ');
|
||||
hdr.size = sizeof(dds_header) - sizeof(hdr.magic);
|
||||
hdr.flags =
|
||||
dds_hf_caps |
|
||||
dds_hf_width |
|
||||
dds_hf_height |
|
||||
dds_hf_linear_size |
|
||||
dds_hf_pixel_format;
|
||||
|
||||
hdr.width = src.size().x;
|
||||
hdr.height = src.size().y;
|
||||
hdr.pitch_or_linear_size = math::numeric_cast<u32>(src.data().size());
|
||||
hdr.depth = 0;
|
||||
hdr.mipmap_count = 0;
|
||||
hdr.caps = dds_caps_texture;
|
||||
hdr.caps2 = 0;
|
||||
|
||||
hdr.pf.size = sizeof(dds_pixel_format);
|
||||
hdr.pf.flags = 0;
|
||||
hdr.pf.fourcc = 0;
|
||||
hdr.pf.rgbbit_count = 0;
|
||||
hdr.pf.rbit_mask = 0;
|
||||
hdr.pf.gbit_mask = 0;
|
||||
hdr.pf.bbit_mask = 0;
|
||||
hdr.pf.abit_mask = 0;
|
||||
|
||||
switch ( src.format() ) {
|
||||
case image_data_format::a8:
|
||||
hdr.pf.flags = dds_pff_alpha | dds_pff_alphapixels;
|
||||
hdr.pf.rgbbit_count = 8;
|
||||
hdr.pf.rbit_mask = 0x00000000;
|
||||
hdr.pf.gbit_mask = 0x00000000;
|
||||
hdr.pf.bbit_mask = 0x00000000;
|
||||
hdr.pf.abit_mask = 0x000000FF;
|
||||
break;
|
||||
case image_data_format::l8:
|
||||
hdr.pf.flags = dds_pff_luminance;
|
||||
hdr.pf.rgbbit_count = 8;
|
||||
hdr.pf.rbit_mask = 0x000000FF;
|
||||
hdr.pf.gbit_mask = 0x00000000;
|
||||
hdr.pf.bbit_mask = 0x00000000;
|
||||
hdr.pf.abit_mask = 0x00000000;
|
||||
break;
|
||||
case image_data_format::la8:
|
||||
hdr.pf.flags = dds_pff_luminance | dds_pff_alphapixels;
|
||||
hdr.pf.rgbbit_count = 16;
|
||||
hdr.pf.rbit_mask = 0x000000FF;
|
||||
hdr.pf.gbit_mask = 0x00000000;
|
||||
hdr.pf.bbit_mask = 0x00000000;
|
||||
hdr.pf.abit_mask = 0x0000FF00;
|
||||
break;
|
||||
case image_data_format::rgb8:
|
||||
hdr.pf.flags = dds_pff_rgb;
|
||||
hdr.pf.rgbbit_count = 24;
|
||||
hdr.pf.rbit_mask = 0x000000FF;
|
||||
hdr.pf.gbit_mask = 0x0000FF00;
|
||||
hdr.pf.bbit_mask = 0x00FF0000;
|
||||
hdr.pf.abit_mask = 0x00000000;
|
||||
break;
|
||||
case image_data_format::rgba8:
|
||||
hdr.pf.flags = dds_pff_rgb | dds_pff_alphapixels;
|
||||
hdr.pf.rgbbit_count = 32;
|
||||
hdr.pf.rbit_mask = 0x000000FF;
|
||||
hdr.pf.gbit_mask = 0x0000FF00;
|
||||
hdr.pf.bbit_mask = 0x00FF0000;
|
||||
hdr.pf.abit_mask = 0xFF000000;
|
||||
break;
|
||||
case image_data_format::rgba_dxt1:
|
||||
hdr.pf.flags = dds_pff_fourcc;
|
||||
hdr.pf.fourcc = make_fourcc('D', 'X', 'T', '1');
|
||||
break;
|
||||
case image_data_format::rgba_dxt3:
|
||||
hdr.pf.flags = dds_pff_fourcc;
|
||||
hdr.pf.fourcc = make_fourcc('D', 'X', 'T', '3');
|
||||
break;
|
||||
case image_data_format::rgba_dxt5:
|
||||
hdr.pf.flags = dds_pff_fourcc;
|
||||
hdr.pf.fourcc = make_fourcc('D', 'X', 'T', '5');
|
||||
break;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected image data format");
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer image_data(sizeof(dds_header) + src.data().size());
|
||||
|
||||
std::memcpy(
|
||||
image_data.data(),
|
||||
&hdr,
|
||||
sizeof(dds_header));
|
||||
|
||||
std::memcpy(
|
||||
image_data.data() + sizeof(dds_header),
|
||||
src.data().data(),
|
||||
src.data().size());
|
||||
|
||||
dst.assign(std::move(image_data));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,25 +5,82 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "image_impl.hpp"
|
||||
#include "image_impl_pvr.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace e2d;
|
||||
using namespace e2d::images::impl::pvr;
|
||||
|
||||
bool is_save_image_pvr_supported(image_data_format data_format) noexcept {
|
||||
switch ( data_format ) {
|
||||
case image_data_format::g8:
|
||||
case image_data_format::ga8:
|
||||
pvr_pixel_format get_pvr_pixel_format(image_data_format fmt) noexcept {
|
||||
switch ( fmt ) {
|
||||
case image_data_format::a8: return pvr_pixel_format::a8;
|
||||
case image_data_format::l8: return pvr_pixel_format::l8;
|
||||
case image_data_format::la8: return pvr_pixel_format::la8;
|
||||
case image_data_format::rgb8: return pvr_pixel_format::rgb8;
|
||||
case image_data_format::rgba8: return pvr_pixel_format::rgba8;
|
||||
|
||||
case image_data_format::rgba_dxt1: return pvr_pixel_format::dxt1;
|
||||
case image_data_format::rgba_dxt3: return pvr_pixel_format::dxt3;
|
||||
case image_data_format::rgba_dxt5: return pvr_pixel_format::dxt5;
|
||||
|
||||
case image_data_format::rgb_etc1: return pvr_pixel_format::etc1;
|
||||
case image_data_format::rgb_etc2: return pvr_pixel_format::etc2_rgb;
|
||||
case image_data_format::rgba_etc2: return pvr_pixel_format::etc2_rgba;
|
||||
case image_data_format::rgb_a1_etc2: return pvr_pixel_format::etc2_rgb_a1;
|
||||
|
||||
case image_data_format::rgba_astc4x4: return pvr_pixel_format::astc_4x4;
|
||||
case image_data_format::rgba_astc5x5: return pvr_pixel_format::astc_5x5;
|
||||
case image_data_format::rgba_astc6x6: return pvr_pixel_format::astc_6x6;
|
||||
case image_data_format::rgba_astc8x8: return pvr_pixel_format::astc_8x8;
|
||||
case image_data_format::rgba_astc10x10: return pvr_pixel_format::astc_10x10;
|
||||
case image_data_format::rgba_astc12x12: return pvr_pixel_format::astc_12x12;
|
||||
|
||||
case image_data_format::rgb_pvrtc2: return pvr_pixel_format::pvrtc_2bpp_rgb;
|
||||
case image_data_format::rgb_pvrtc4: return pvr_pixel_format::pvrtc_4bpp_rgb;
|
||||
case image_data_format::rgba_pvrtc2: return pvr_pixel_format::pvrtc_2bpp_rgba;
|
||||
case image_data_format::rgba_pvrtc4: return pvr_pixel_format::pvrtc_4bpp_rgba;
|
||||
|
||||
case image_data_format::rgba_pvrtc2_v2: return pvr_pixel_format::pvrtc2_2bpp;
|
||||
case image_data_format::rgba_pvrtc4_v2: return pvr_pixel_format::pvrtc2_4bpp;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected image data format");
|
||||
return pvr_pixel_format(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool check_save_image_pvr(const image& src) noexcept {
|
||||
switch ( src.format() ) {
|
||||
case image_data_format::a8:
|
||||
case image_data_format::l8:
|
||||
case image_data_format::la8:
|
||||
case image_data_format::rgb8:
|
||||
case image_data_format::rgba8:
|
||||
case image_data_format::rgb_dxt1:
|
||||
|
||||
case image_data_format::rgba_dxt1:
|
||||
case image_data_format::rgba_dxt3:
|
||||
case image_data_format::rgba_dxt5:
|
||||
|
||||
case image_data_format::rgb_etc1:
|
||||
case image_data_format::rgb_etc2:
|
||||
case image_data_format::rgba_etc2:
|
||||
case image_data_format::rgb_a1_etc2:
|
||||
|
||||
case image_data_format::rgba_astc4x4:
|
||||
case image_data_format::rgba_astc5x5:
|
||||
case image_data_format::rgba_astc6x6:
|
||||
case image_data_format::rgba_astc8x8:
|
||||
case image_data_format::rgba_astc10x10:
|
||||
case image_data_format::rgba_astc12x12:
|
||||
|
||||
case image_data_format::rgb_pvrtc2:
|
||||
case image_data_format::rgb_pvrtc4:
|
||||
case image_data_format::rgba_pvrtc2:
|
||||
case image_data_format::rgba_pvrtc4:
|
||||
|
||||
case image_data_format::rgba_pvrtc2_v2:
|
||||
case image_data_format::rgba_pvrtc4_v2:
|
||||
return true;
|
||||
@@ -31,16 +88,42 @@ namespace
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool save_image_pvr(const image& src, buffer& dst) {
|
||||
E2D_UNUSED(src, dst);
|
||||
if ( is_save_image_pvr_supported(src.format()) ) {
|
||||
//TODO(BlackMat): implme
|
||||
E2D_ASSERT_MSG(false, "implme");
|
||||
}
|
||||
if ( !check_save_image_pvr(src) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pvr_header hdr;
|
||||
hdr.version = make_fourcc('P', 'V', 'R', 3);
|
||||
hdr.flags = static_cast<u32>(pvr_flags::none);
|
||||
hdr.pixel_format0 = static_cast<u32>(
|
||||
static_cast<u64>(get_pvr_pixel_format(src.format())) & 0xFFFFFFFF);
|
||||
hdr.pixel_format1 = static_cast<u32>(
|
||||
static_cast<u64>(get_pvr_pixel_format(src.format())) >> 32);
|
||||
hdr.color_space = static_cast<u32>(pvr_color_space::linear);
|
||||
hdr.channel_type = static_cast<u32>(pvr_channel_type::ubyte);
|
||||
hdr.height = src.size().y;
|
||||
hdr.width = src.size().x;
|
||||
hdr.depth = 1;
|
||||
hdr.num_surfaces = 1;
|
||||
hdr.num_faces = 1;
|
||||
hdr.mipmap_count = 1;
|
||||
hdr.meta_data_size = 0;
|
||||
|
||||
buffer image_data(sizeof(pvr_header) + src.data().size());
|
||||
|
||||
std::memcpy(
|
||||
image_data.data(),
|
||||
&hdr,
|
||||
sizeof(pvr_header));
|
||||
|
||||
std::memcpy(
|
||||
image_data.data() + sizeof(pvr_header),
|
||||
src.data().data(),
|
||||
src.data().size());
|
||||
|
||||
dst.assign(std::move(image_data));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,20 +42,53 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
bool stb_check_save_image_format(image_data_format format) noexcept {
|
||||
switch ( format ) {
|
||||
case image_data_format::l8:
|
||||
case image_data_format::la8:
|
||||
case image_data_format::rgb8:
|
||||
case image_data_format::rgba8:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int stb_channels_from_image_format(image_data_format format) noexcept {
|
||||
switch ( format ) {
|
||||
case image_data_format::g8: return 1;
|
||||
case image_data_format::ga8: return 2;
|
||||
case image_data_format::l8: return 1;
|
||||
case image_data_format::la8: return 2;
|
||||
case image_data_format::rgb8: return 3;
|
||||
case image_data_format::rgba8: return 4;
|
||||
default: return 0;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected image data format");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool check_save_image_jpg(const image& src) noexcept {
|
||||
return stb_check_save_image_format(src.format());
|
||||
}
|
||||
|
||||
bool check_save_image_png(const image& src) noexcept {
|
||||
return stb_check_save_image_format(src.format());
|
||||
}
|
||||
|
||||
bool check_save_image_tga(const image& src) noexcept {
|
||||
return stb_check_save_image_format(src.format());
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::images::impl
|
||||
{
|
||||
bool save_image_jpg(const image& src, buffer& dst) {
|
||||
if ( !check_save_image_jpg(src) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int img_w = math::numeric_cast<int>(src.size().x);
|
||||
int img_h = math::numeric_cast<int>(src.size().y);
|
||||
int img_c = stb_channels_from_image_format(src.format());
|
||||
@@ -82,6 +115,10 @@ namespace e2d::images::impl
|
||||
}
|
||||
|
||||
bool save_image_png(const image& src, buffer& dst) {
|
||||
if ( !check_save_image_png(src) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int img_w = math::numeric_cast<int>(src.size().x);
|
||||
int img_h = math::numeric_cast<int>(src.size().y);
|
||||
int img_c = stb_channels_from_image_format(src.format());
|
||||
@@ -108,6 +145,10 @@ namespace e2d::images::impl
|
||||
}
|
||||
|
||||
bool save_image_tga(const image& src, buffer& dst) {
|
||||
if ( !check_save_image_tga(src) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int img_w = math::numeric_cast<int>(src.size().x);
|
||||
int img_h = math::numeric_cast<int>(src.size().y);
|
||||
int img_c = stb_channels_from_image_format(src.format());
|
||||
|
||||
@@ -299,9 +299,13 @@ namespace e2d::meshes
|
||||
{
|
||||
bool try_load_mesh(
|
||||
mesh& dst,
|
||||
const buffer& src) noexcept
|
||||
buffer_view src) noexcept
|
||||
{
|
||||
return impl::try_load_mesh_e2d(dst, src);
|
||||
try {
|
||||
return impl::load_mesh_e2d(dst, src);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool try_load_mesh(
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
#include <enduro2d/utils/mesh.hpp>
|
||||
#include <enduro2d/utils/buffer.hpp>
|
||||
#include <enduro2d/utils/buffer_view.hpp>
|
||||
|
||||
namespace e2d::meshes::impl
|
||||
{
|
||||
bool try_load_mesh_e2d(mesh& dst, const buffer& src) noexcept;
|
||||
bool load_mesh_e2d(mesh& dst, buffer_view src);
|
||||
}
|
||||
|
||||
@@ -114,14 +114,10 @@ namespace
|
||||
|
||||
namespace e2d::meshes::impl
|
||||
{
|
||||
bool try_load_mesh_e2d(mesh& dst, const buffer& src) noexcept {
|
||||
try {
|
||||
auto stream = make_memory_stream(src);
|
||||
bool load_mesh_e2d(mesh& dst, buffer_view src) {
|
||||
auto stream = make_memory_stream(buffer(src));
|
||||
return stream
|
||||
&& check_signature(stream)
|
||||
&& load_mesh(dst, stream);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,9 +224,13 @@ namespace e2d::shapes
|
||||
{
|
||||
bool try_load_shape(
|
||||
shape& dst,
|
||||
const buffer& src) noexcept
|
||||
buffer_view src) noexcept
|
||||
{
|
||||
return impl::try_load_shape_e2d(dst, src);
|
||||
try {
|
||||
return impl::load_shape_e2d(dst, src);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool try_load_shape(
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
#include <enduro2d/utils/shape.hpp>
|
||||
#include <enduro2d/utils/buffer.hpp>
|
||||
#include <enduro2d/utils/buffer_view.hpp>
|
||||
|
||||
namespace e2d::shapes::impl
|
||||
{
|
||||
bool try_load_shape_e2d(shape& dst, const buffer& src) noexcept;
|
||||
bool load_shape_e2d(shape& dst, buffer_view src);
|
||||
}
|
||||
|
||||
@@ -96,14 +96,10 @@ namespace
|
||||
|
||||
namespace e2d::shapes::impl
|
||||
{
|
||||
bool try_load_shape_e2d(shape& dst, const buffer& src) noexcept {
|
||||
try {
|
||||
auto stream = make_memory_stream(src);
|
||||
bool load_shape_e2d(shape& dst, buffer_view src) {
|
||||
auto stream = make_memory_stream(buffer(src));
|
||||
return stream
|
||||
&& check_signature(stream)
|
||||
&& load_shape(dst, stream);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include <enduro2d/utils/streams.hpp>
|
||||
#include <enduro2d/utils/buffer.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -171,18 +170,12 @@ namespace e2d
|
||||
return *this;
|
||||
}
|
||||
|
||||
output_sequence& output_sequence::write_all(const buffer& src) noexcept {
|
||||
output_sequence& output_sequence::write_all(buffer_view src) noexcept {
|
||||
return success_
|
||||
? write(src.data(), src.size())
|
||||
: *this;
|
||||
}
|
||||
|
||||
output_sequence& output_sequence::write_all(const str& src) noexcept {
|
||||
return success_
|
||||
? write(src.c_str(), src.size())
|
||||
: *this;
|
||||
}
|
||||
|
||||
output_sequence& output_sequence::flush() noexcept {
|
||||
try {
|
||||
if ( success_ ) {
|
||||
@@ -229,15 +222,7 @@ namespace e2d::streams
|
||||
: false;
|
||||
}
|
||||
|
||||
bool try_write_tail(const str& src, const output_stream_uptr& stream) noexcept {
|
||||
return stream
|
||||
? output_sequence(*stream)
|
||||
.write_all(src)
|
||||
.success()
|
||||
: false;
|
||||
}
|
||||
|
||||
bool try_write_tail(const buffer& src, const output_stream_uptr& stream) noexcept {
|
||||
bool try_write_tail(buffer_view src, const output_stream_uptr& stream) noexcept {
|
||||
return stream
|
||||
? output_sequence(*stream)
|
||||
.write_all(src)
|
||||
|
||||
3
untests/bin/images/dds/ship_a8.dds
Normal file
3
untests/bin/images/dds/ship_a8.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6d2cd928ace63bf0ed4f9e71007fcf435b414c8b34312f1fb5a021ac01ef9876
|
||||
size 8320
|
||||
3
untests/bin/images/dds/ship_a8l8.dds
Normal file
3
untests/bin/images/dds/ship_a8l8.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bf310ae21482921cc00c0b962be7cc109bc28f7bab713528bd84817ebba0e68b
|
||||
size 16512
|
||||
3
untests/bin/images/dds/ship_a8r8g8b8.dds
Normal file
3
untests/bin/images/dds/ship_a8r8g8b8.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2bee89070f7f01c6f3316e3f5faabc8db94202fc8fe6ef4eb0159add01b3304d
|
||||
size 32896
|
||||
3
untests/bin/images/dds/ship_dxt1.dds
Normal file
3
untests/bin/images/dds/ship_dxt1.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5a04f77d73155ddaf20e137005698b7f98d859656d8f02d6d32b767c87dd5370
|
||||
size 4224
|
||||
3
untests/bin/images/dds/ship_dxt3.dds
Normal file
3
untests/bin/images/dds/ship_dxt3.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0aaac08ab41d31e0c13a1e1b03a9919c33791af29be568912865eedee395a654
|
||||
size 8320
|
||||
3
untests/bin/images/dds/ship_dxt5.dds
Normal file
3
untests/bin/images/dds/ship_dxt5.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fe4a3d42cb22478986d9d8342959b44fe256245be4941e7e8f3cbccc49a5ede2
|
||||
size 8320
|
||||
3
untests/bin/images/dds/ship_l8.dds
Normal file
3
untests/bin/images/dds/ship_l8.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4c75ef2254f7315714f86097bc4b99adfff0bf54569154d028991fb65c5bba8e
|
||||
size 8320
|
||||
3
untests/bin/images/dds/ship_r8g8b8.dds
Normal file
3
untests/bin/images/dds/ship_r8g8b8.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e69ae09fd2e5a0adcbf6301ff55d52ca562a8a93db3a96cc3fd7f61c6f197aac
|
||||
size 24704
|
||||
3
untests/bin/images/dds/ship_rgba8.dds
Normal file
3
untests/bin/images/dds/ship_rgba8.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d1c1f816df198d8d41f01455627f52fa40c55e786caff8e0fb4731aa118cb8df
|
||||
size 32896
|
||||
3
untests/bin/images/dds/ship_x8r8g8b8.dds
Normal file
3
untests/bin/images/dds/ship_x8r8g8b8.dds
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8e6b1c2fce3ae13125353b4334374294362c3cd44a1e2f5f523570d07d1776c0
|
||||
size 32896
|
||||
3
untests/bin/images/pvr/ship_a8.pvr
Normal file
3
untests/bin/images/pvr/ship_a8.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:26640127a07a5b7b3e8390bb34791a6926357df07dad0944834527c288eff36e
|
||||
size 8259
|
||||
3
untests/bin/images/pvr/ship_astc10x10.pvr
Normal file
3
untests/bin/images/pvr/ship_astc10x10.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d1160fde2e2877bb2db8698af35f5e5e58daf4d10711eda1a2ccaa56472aeefe
|
||||
size 1523
|
||||
3
untests/bin/images/pvr/ship_astc12x12.pvr
Normal file
3
untests/bin/images/pvr/ship_astc12x12.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:33ca8d0e768cf02071c59c468da5524d33d03888cd0e13db2a9e380d1ae1de73
|
||||
size 1123
|
||||
3
untests/bin/images/pvr/ship_astc4x4.pvr
Normal file
3
untests/bin/images/pvr/ship_astc4x4.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0ab8a200daa2640c60454085835ed19622e0e344fd07c9bcb9f8b51584e4009a
|
||||
size 8259
|
||||
3
untests/bin/images/pvr/ship_astc5x5.pvr
Normal file
3
untests/bin/images/pvr/ship_astc5x5.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:682e37f45057fb498dafcbea955bfdb293ad6041f21b0ff03d26038008a4d2e0
|
||||
size 5475
|
||||
3
untests/bin/images/pvr/ship_astc6x6.pvr
Normal file
3
untests/bin/images/pvr/ship_astc6x6.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c5210127b811bc455dfa13a0b7f572652ec3ae711ce39a18ac1c138c4f230eac
|
||||
size 3939
|
||||
3
untests/bin/images/pvr/ship_astc8x8.pvr
Normal file
3
untests/bin/images/pvr/ship_astc8x8.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:558f5ca61535e42a3f7823f572f80342f91d30d223e19b081121a69cf6274178
|
||||
size 2115
|
||||
3
untests/bin/images/pvr/ship_bgra8.pvr
Normal file
3
untests/bin/images/pvr/ship_bgra8.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1e4727acbfb5e77879b12c64480eea431c339b90017820e6debe6f71c0e3c756
|
||||
size 32835
|
||||
3
untests/bin/images/pvr/ship_dxt1.pvr
Normal file
3
untests/bin/images/pvr/ship_dxt1.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e0adcd804b56aa97d144636481699c49a3a8bac21713953dff72533a47a98b89
|
||||
size 4163
|
||||
3
untests/bin/images/pvr/ship_dxt3.pvr
Normal file
3
untests/bin/images/pvr/ship_dxt3.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b39f3c1fb9ae31b0ee8de9c1af051d90364e4c5a9887fd1631eac45ddf11c174
|
||||
size 8259
|
||||
3
untests/bin/images/pvr/ship_dxt5.pvr
Normal file
3
untests/bin/images/pvr/ship_dxt5.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4ebc3997990b57a35538480c384c6c7722b000c675d389b2bd4d3afd57dc5de7
|
||||
size 8259
|
||||
3
untests/bin/images/pvr/ship_eac_r11.pvr
Normal file
3
untests/bin/images/pvr/ship_eac_r11.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d9170f6956e1686f841bcbf460c589e7e0baf502a072b540b22ea19550fb5f45
|
||||
size 4163
|
||||
3
untests/bin/images/pvr/ship_etc1.pvr
Normal file
3
untests/bin/images/pvr/ship_etc1.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9b2533bb57489a6eefcf05d986eee9e97f7bf6070809748c8aece27fbc199c5a
|
||||
size 4163
|
||||
3
untests/bin/images/pvr/ship_etc2_rgb.pvr
Normal file
3
untests/bin/images/pvr/ship_etc2_rgb.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:198d7a47737c3f16f5c4b9268ebc77c1ea63aa7128d335cc9e0c399b518311a0
|
||||
size 4163
|
||||
3
untests/bin/images/pvr/ship_etc2_rgb_a1.pvr
Normal file
3
untests/bin/images/pvr/ship_etc2_rgb_a1.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8cf733d37c4d52720a41786656fd57e7dc554f090824fdf48bc0788a699594e2
|
||||
size 4163
|
||||
3
untests/bin/images/pvr/ship_etc2_rgba.pvr
Normal file
3
untests/bin/images/pvr/ship_etc2_rgba.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:000885d3ae07adbcfc9e2ba7aee4f56e7e7d3b9f350755ec580d27ca18ed2490
|
||||
size 8259
|
||||
3
untests/bin/images/pvr/ship_l8.pvr
Normal file
3
untests/bin/images/pvr/ship_l8.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:89eb84779b83638fb0ab66e001d601ee970a9489b9f7cb1f132aca0b3ee6e8cf
|
||||
size 8259
|
||||
3
untests/bin/images/pvr/ship_la8.pvr
Normal file
3
untests/bin/images/pvr/ship_la8.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:58063363c4966b5c7d1f1003ebcad8e8ed0b71ba0480fd763d53ff0b952ffa74
|
||||
size 16451
|
||||
3
untests/bin/images/pvr/ship_pvrtc2_2bpp.pvr
Normal file
3
untests/bin/images/pvr/ship_pvrtc2_2bpp.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1322266525db79e804f569aebb9d9d68ebf8e878212b9dd92d07226d6d3ed4c5
|
||||
size 2115
|
||||
3
untests/bin/images/pvr/ship_pvrtc2_4bpp.pvr
Normal file
3
untests/bin/images/pvr/ship_pvrtc2_4bpp.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:446048e908f4147dd43a55b47ed5fe8103e5d2bec24ce61b8e69e176318dfb89
|
||||
size 4163
|
||||
3
untests/bin/images/pvr/ship_pvrtc_2bpp_rgb.pvr
Normal file
3
untests/bin/images/pvr/ship_pvrtc_2bpp_rgb.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c51efd4f2782e37a7eb86cfe142e004868b45617b6f3d2b4646135295b422f98
|
||||
size 2115
|
||||
3
untests/bin/images/pvr/ship_pvrtc_2bpp_rgba.pvr
Normal file
3
untests/bin/images/pvr/ship_pvrtc_2bpp_rgba.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ef1a1165023faff98302bfa809880e5aa8243e47e337bf408b9e2eec6be31b8d
|
||||
size 2115
|
||||
3
untests/bin/images/pvr/ship_pvrtc_4bpp_rgb.pvr
Normal file
3
untests/bin/images/pvr/ship_pvrtc_4bpp_rgb.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1b644648eaa698b47c11bc21cbb67fe3beff76fa362514c1fd48b90bde909dd0
|
||||
size 4163
|
||||
3
untests/bin/images/pvr/ship_pvrtc_4bpp_rgba.pvr
Normal file
3
untests/bin/images/pvr/ship_pvrtc_4bpp_rgba.pvr
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fbfe371606b6857368be8abf653a25bb7674c2b4334e9ff054c6a08fe4f81f54
|
||||
size 4163
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6b7f41f18f51ec169a9c521cd1177fd49037b200a850aad05a923240c37d8d87
|
||||
size 4163
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bd1c2362dc5b0b75d97ca3d5bbdf2cf647b25a5b2f8834a9005e8c9c0a70e82c
|
||||
size 8259
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7a62a7760e33b7130539c3b6a8b7c287ccdd11edb9dd273be3c1e6ec7b81b47e
|
||||
size 2115
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6a9b1a7f97b26ff7df0a7275f786e029dbc45aab796247f8063c820140933685
|
||||
size 2115
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:69e2bab57471fbde23d432f77270678e0a28cf809eb079fbb39a61e68abe4059
|
||||
size 4163
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f730702b1075c5a0ef929272106275debf12dbce31a59664038545b5b91d1545
|
||||
size 4163
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7fcf6cb866364b0a8b31bea7407a40aa2dcda1af4f618604aec2249e2e0cc588
|
||||
size 2115
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1a928929dc7532d84072e5668e5098b17289fdea1d36bff3ae48fa232294f770
|
||||
size 4163
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e4f93405f3302067a0a1bfc05be48c20ef2e12b649d722574497f6dbd64c3b61
|
||||
size 8259
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:958b8490c189abdebde1f75e8eacbcb8e6ec06dac34baed545e383639e3288d3
|
||||
size 16451
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:07b0e533a85a8eef51e9baf6ebca2f5a451f74e712557ef315fd1952dcaef307
|
||||
size 8320
|
||||
3
untests/bin/images/stb/ship.jpg
Normal file
3
untests/bin/images/stb/ship.jpg
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:332aff6826f8eb97cf3420112aa6a42655c5e284b46acd2caa80d5dfe4404e46
|
||||
size 5438
|
||||
3
untests/bin/images/stb/ship.png
Executable file
3
untests/bin/images/stb/ship.png
Executable file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:90a41d4bedcd8d388eee4a12c168b1364bd17742c817b2ad532d799731505164
|
||||
size 11620
|
||||
3
untests/bin/images/stb/ship.tga
Normal file
3
untests/bin/images/stb/ship.tga
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:823bcbe99c6914db817de30b1a6dd0a64418703462a72c5136ad767bcef50c13
|
||||
size 17842
|
||||
@@ -190,19 +190,17 @@ TEST_CASE("render"){
|
||||
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::rgba8);
|
||||
REQUIRE(tex != nullptr);
|
||||
|
||||
buffer src;
|
||||
src.resize(((tex->size().x * tex->decl().bits_per_pixel()) / 8u) * tex->size().y);
|
||||
buffer src(tex->size().x * tex->size().y * 4u);
|
||||
for ( auto& c : src ) {
|
||||
c = rand() % 255;
|
||||
}
|
||||
REQUIRE_NOTHROW(r.update_texture(tex, src, b2u(0, 0, 128, 128)));
|
||||
}
|
||||
{
|
||||
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::g8);
|
||||
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::l8);
|
||||
REQUIRE(tex != nullptr);
|
||||
|
||||
buffer src;
|
||||
src.resize(((tex->size().x * tex->decl().bits_per_pixel()) / 8u) * tex->size().y);
|
||||
buffer src(tex->size().x * tex->size().y * 1u);
|
||||
for ( auto& c : src ) {
|
||||
c = rand() % 255;
|
||||
}
|
||||
@@ -212,8 +210,7 @@ TEST_CASE("render"){
|
||||
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::rgb8);
|
||||
REQUIRE(tex != nullptr);
|
||||
|
||||
buffer src;
|
||||
src.resize(((tex->size().x * tex->decl().bits_per_pixel()) / 8u) * tex->size().y);
|
||||
buffer src(tex->size().x * tex->size().y * 3u);
|
||||
for ( auto& c : src ) {
|
||||
c = rand() % 255;
|
||||
}
|
||||
@@ -223,8 +220,7 @@ TEST_CASE("render"){
|
||||
texture_ptr tex = r.create_texture(v2u(57,31), pixel_declaration::pixel_type::rgba8);
|
||||
REQUIRE(tex != nullptr);
|
||||
|
||||
buffer src;
|
||||
src.resize(((tex->size().x * tex->decl().bits_per_pixel()) / 8u) * tex->size().y);
|
||||
buffer src(tex->size().x * tex->size().y * 4u);
|
||||
for ( auto& c : src ) {
|
||||
c = rand() % 255;
|
||||
}
|
||||
@@ -234,8 +230,7 @@ TEST_CASE("render"){
|
||||
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::rgba8);
|
||||
REQUIRE(tex != nullptr);
|
||||
|
||||
buffer src;
|
||||
src.resize(((31 * tex->decl().bits_per_pixel()) / 8u) * 44);
|
||||
buffer src(31u * 44u * 4u);
|
||||
for ( auto& c : src ) {
|
||||
c = rand() % 255;
|
||||
}
|
||||
@@ -245,13 +240,12 @@ TEST_CASE("render"){
|
||||
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::rgba8);
|
||||
REQUIRE(tex != nullptr);
|
||||
|
||||
buffer src;
|
||||
src.resize(((31 * tex->decl().bits_per_pixel()) / 8u) * 44);
|
||||
buffer src(31u * 44u * 4u);
|
||||
for ( auto& c : src ) {
|
||||
c = rand() % 255;
|
||||
}
|
||||
|
||||
image img(v2u(31, 44), image_data_format::ga8, src);
|
||||
image img(v2u(31, 44), image_data_format::la8, src);
|
||||
REQUIRE_THROWS_AS(
|
||||
r.update_texture(tex, img, v2u(11,27)),
|
||||
bad_render_operation);
|
||||
@@ -264,7 +258,7 @@ TEST_CASE("render"){
|
||||
filesystem::predef_path::resources));
|
||||
|
||||
image src;
|
||||
REQUIRE(images::try_load_image(src, make_read_file(path::combine(resources, "bin/images/ship_rgba.dds"))));
|
||||
REQUIRE(images::try_load_image(src, make_read_file(path::combine(resources, "bin/images/dds/ship_dxt5.dds"))));
|
||||
|
||||
texture_ptr tex = r.create_texture(src.size(), pixel_declaration::pixel_type::rgba_dxt5);
|
||||
REQUIRE(tex != nullptr);
|
||||
|
||||
@@ -220,6 +220,11 @@ TEST_CASE("buffer_view") {
|
||||
buffer_view v5(b2);
|
||||
REQUIRE(v5.data() == b2.data());
|
||||
REQUIRE(v5.size() == 20);
|
||||
|
||||
str32 b3 = make_utf32("hello");
|
||||
buffer_view v6(b3);
|
||||
REQUIRE(v6.data() == b3.data());
|
||||
REQUIRE(v6.size() == 20);
|
||||
}
|
||||
{
|
||||
const char* s0 = "hell";
|
||||
@@ -273,4 +278,13 @@ TEST_CASE("buffer_view") {
|
||||
REQUIRE(buffer_view("hello",5) != buffer_view("hello, world",12));
|
||||
REQUIRE_FALSE(buffer_view("hello",5) == buffer_view("hello, world",12));
|
||||
}
|
||||
{
|
||||
buffer_view v0("hello",5);
|
||||
buffer b0 = buffer(v0);
|
||||
REQUIRE(v0 == b0);
|
||||
|
||||
buffer_view v1;
|
||||
buffer b1 = buffer(v1);
|
||||
REQUIRE(v1 == b1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
using namespace e2d;
|
||||
|
||||
TEST_CASE("images") {
|
||||
SECTION("image") {
|
||||
{
|
||||
image i;
|
||||
REQUIRE(i.size() == v2u::zero());
|
||||
@@ -17,21 +18,26 @@ TEST_CASE("images") {
|
||||
}
|
||||
{
|
||||
const u8 img[] = {1,2,3,4,5,6,7,8};
|
||||
image i0(v2u(2,2), image_data_format::g8, {img,4});
|
||||
image i1(v2u(2,1), image_data_format::ga8, {img,4});
|
||||
image i2(v2u(1,2), image_data_format::ga8, {img,4});
|
||||
image i3(v2u(2,1), image_data_format::rgb8, {img,6});
|
||||
image i4(v2u(1,2), image_data_format::rgb8, {img,6});
|
||||
image i5(v2u(2,1), image_data_format::rgba8, {img,8});
|
||||
image i6(v2u(1,2), image_data_format::rgba8, {img,8});
|
||||
REQUIRE(i0.format() == image_data_format::g8);
|
||||
REQUIRE(i1.format() == image_data_format::ga8);
|
||||
REQUIRE(i2.format() == image_data_format::ga8);
|
||||
REQUIRE(i3.format() == image_data_format::rgb8);
|
||||
image i0(v2u(2,2), image_data_format::a8, {img,4});
|
||||
image i1(v2u(2,2), image_data_format::l8, {img,4});
|
||||
image i2(v2u(2,1), image_data_format::la8, {img,4});
|
||||
image i3(v2u(1,2), image_data_format::la8, {img,4});
|
||||
image i4(v2u(2,1), image_data_format::rgb8, {img,6});
|
||||
image i5(v2u(1,2), image_data_format::rgb8, {img,6});
|
||||
image i6(v2u(2,1), image_data_format::rgba8, {img,8});
|
||||
image i7(v2u(1,2), image_data_format::rgba8, {img,8});
|
||||
REQUIRE(i0.format() == image_data_format::a8);
|
||||
REQUIRE(i1.format() == image_data_format::l8);
|
||||
REQUIRE(i2.format() == image_data_format::la8);
|
||||
REQUIRE(i3.format() == image_data_format::la8);
|
||||
REQUIRE(i4.format() == image_data_format::rgb8);
|
||||
REQUIRE(i5.format() == image_data_format::rgba8);
|
||||
REQUIRE(i5.format() == image_data_format::rgb8);
|
||||
REQUIRE(i6.format() == image_data_format::rgba8);
|
||||
REQUIRE(i7.format() == image_data_format::rgba8);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("stb") {
|
||||
{
|
||||
REQUIRE(filesystem::remove_file("image_save_test.jpg"));
|
||||
REQUIRE(filesystem::remove_file("image_save_test.png"));
|
||||
@@ -129,46 +135,236 @@ TEST_CASE("images") {
|
||||
REQUIRE(math::approximately(img.pixel32(1,0), color32::green(), 0));
|
||||
REQUIRE(math::approximately(img.pixel32(2,0), color32::blue(), 0));
|
||||
}
|
||||
{
|
||||
struct img_info {
|
||||
const char* name;
|
||||
bool can_load;
|
||||
image_data_format format;
|
||||
};
|
||||
|
||||
const img_info test_images[] = {
|
||||
{"bin/images/ship_pvrtc_2bpp_rgba.pvr", true, image_data_format::rgba_pvrtc2},
|
||||
{"bin/images/ship_pvrtc_2bpp_rgb.pvr", true, image_data_format::rgb_pvrtc2},
|
||||
{"bin/images/ship_pvrtc_4bpp_rgba.pvr", true, image_data_format::rgba_pvrtc4},
|
||||
{"bin/images/ship_pvrtc_4bpp_rgb.pvr", true, image_data_format::rgb_pvrtc4},
|
||||
{"bin/images/ship_pvrtc_ii_2bpp.pvr", true, image_data_format::rgba_pvrtc2_v2},
|
||||
{"bin/images/ship_pvrtc_ii_4bpp.pvr", true, image_data_format::rgba_pvrtc4_v2},
|
||||
{"bin/images/ship_etc1.pvr", false, image_data_format(-1)},
|
||||
{"bin/images/ship_etc2.pvr", false, image_data_format(-1)},
|
||||
{"bin/images/ship_eac_rg11.pvr", false, image_data_format(-1)},
|
||||
{"bin/images/ship_rgba8.pvr", true, image_data_format::rgba8},
|
||||
{"bin/images/ship_rgba.dds", true, image_data_format::rgba_dxt5},
|
||||
{"bin/images/ship_r8.pvr", true, image_data_format::g8},
|
||||
{"bin/images/ship_rg8.pvr", true, image_data_format::ga8},
|
||||
{"bin/images/ship_rgb8.pvr", true, image_data_format::rgb8}
|
||||
};
|
||||
}
|
||||
|
||||
str resources;
|
||||
REQUIRE(filesystem::extract_predef_path(
|
||||
resources,
|
||||
filesystem::predef_path::resources));
|
||||
|
||||
for ( const auto& info : test_images ) {
|
||||
input_stream_uptr stream = make_read_file(path::combine(resources, info.name));
|
||||
SECTION("stb") {
|
||||
struct img_info {
|
||||
const char* path;
|
||||
std::size_t size;
|
||||
image_data_format format;
|
||||
};
|
||||
const img_info test_infos[] = {
|
||||
{"bin/images/stb/ship.jpg", 64 * 128 * 3, image_data_format::rgb8},
|
||||
{"bin/images/stb/ship.png", 64 * 128 * 4, image_data_format::rgba8},
|
||||
{"bin/images/stb/ship.tga", 64 * 128 * 4, image_data_format::rgba8}};
|
||||
for ( const auto& info : test_infos ) {
|
||||
input_stream_uptr stream = make_read_file(path::combine(resources, info.path));
|
||||
REQUIRE(stream);
|
||||
image img;
|
||||
REQUIRE(images::try_load_image(img, stream) == info.can_load);
|
||||
if ( info.can_load ) {
|
||||
REQUIRE(images::try_load_image(img, stream));
|
||||
REQUIRE(img.format() == info.format);
|
||||
REQUIRE(img.data().size() == info.size);
|
||||
REQUIRE(img.size().x == 64);
|
||||
REQUIRE(img.size().y == 128);
|
||||
REQUIRE(img.data().size() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("dds") {
|
||||
struct img_info {
|
||||
const char* path;
|
||||
std::size_t size;
|
||||
bool can_load;
|
||||
image_data_format format;
|
||||
};
|
||||
|
||||
const img_info test_infos[] = {
|
||||
{"bin/images/dds/ship_a8.dds", 64 * 128 * 1, true, image_data_format::a8},
|
||||
{"bin/images/dds/ship_l8.dds", 64 * 128 * 1, true, image_data_format::l8},
|
||||
{"bin/images/dds/ship_a8l8.dds", 64 * 128 * 2, true, image_data_format::la8},
|
||||
|
||||
{"bin/images/dds/ship_r8g8b8.dds", 64 * 128 * 3, true, image_data_format::rgb8},
|
||||
{"bin/images/dds/ship_x8r8g8b8.dds", 64 * 128 * 3, true, image_data_format::rgb8},
|
||||
|
||||
{"bin/images/dds/ship_rgba8.dds", 64 * 128 * 4, true, image_data_format::rgba8},
|
||||
{"bin/images/dds/ship_a8r8g8b8.dds", 64 * 128 * 4, true, image_data_format::rgba8},
|
||||
|
||||
{"bin/images/dds/ship_dxt1.dds", 64 * 128 * 4 / 8, true, image_data_format::rgba_dxt1},
|
||||
{"bin/images/dds/ship_dxt3.dds", 64 * 128 * 8 / 8, true, image_data_format::rgba_dxt3},
|
||||
{"bin/images/dds/ship_dxt5.dds", 64 * 128 * 8 / 8, true, image_data_format::rgba_dxt5},
|
||||
};
|
||||
|
||||
for ( const auto& info : test_infos ) {
|
||||
CAPTURE(info.path);
|
||||
|
||||
image img;
|
||||
REQUIRE(info.can_load == images::try_load_image(
|
||||
img,
|
||||
make_read_file(path::combine(resources, info.path))));
|
||||
|
||||
if ( info.can_load ) {
|
||||
REQUIRE(img.format() == info.format);
|
||||
REQUIRE(img.data().size() == info.size);
|
||||
REQUIRE(img.size().x == 64);
|
||||
REQUIRE(img.size().y == 128);
|
||||
}
|
||||
}
|
||||
|
||||
for ( const auto& info : test_infos ) {
|
||||
CAPTURE(info.path);
|
||||
|
||||
if ( !info.can_load ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
image img;
|
||||
REQUIRE(images::try_load_image(
|
||||
img,
|
||||
make_read_file(path::combine(resources, info.path))));
|
||||
|
||||
REQUIRE(filesystem::remove_file("image_save_test.dds"));
|
||||
REQUIRE(images::try_save_image(
|
||||
img,
|
||||
image_file_format::dds, make_write_file("image_save_test.dds", false)));
|
||||
|
||||
image img2;
|
||||
REQUIRE(images::try_load_image(
|
||||
img2,
|
||||
make_read_file("image_save_test.dds")));
|
||||
|
||||
REQUIRE(img == img2);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("dds_bgr") {
|
||||
{
|
||||
image img;
|
||||
REQUIRE(images::try_load_image(
|
||||
img,
|
||||
make_read_file(path::combine(resources, "bin/images/dds/ship_r8g8b8.dds"))));
|
||||
|
||||
image img2;
|
||||
REQUIRE(images::try_load_image(
|
||||
img2,
|
||||
make_read_file(path::combine(resources, "bin/images/dds/ship_r8g8b8.dds"))));
|
||||
|
||||
image img3;
|
||||
REQUIRE(images::try_load_image(
|
||||
img3,
|
||||
make_read_file(path::combine(resources, "bin/images/dds/ship_x8r8g8b8.dds"))));
|
||||
|
||||
REQUIRE(img == img2);
|
||||
REQUIRE(img2 == img3);
|
||||
}
|
||||
{
|
||||
image img;
|
||||
REQUIRE(images::try_load_image(
|
||||
img,
|
||||
make_read_file(path::combine(resources, "bin/images/dds/ship_rgba8.dds"))));
|
||||
|
||||
image img2;
|
||||
REQUIRE(images::try_load_image(
|
||||
img2,
|
||||
make_read_file(path::combine(resources, "bin/images/dds/ship_a8r8g8b8.dds"))));
|
||||
|
||||
REQUIRE(img == img2);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("pvr") {
|
||||
struct img_info {
|
||||
const char* path;
|
||||
std::size_t size;
|
||||
bool can_load;
|
||||
image_data_format format;
|
||||
};
|
||||
|
||||
const img_info test_infos[] = {
|
||||
{"bin/images/pvr/ship_a8.pvr", 64 * 128 * 1, true, image_data_format::a8},
|
||||
{"bin/images/pvr/ship_l8.pvr", 64 * 128 * 1, true, image_data_format::l8},
|
||||
{"bin/images/pvr/ship_la8.pvr", 64 * 128 * 2, true, image_data_format::la8},
|
||||
|
||||
{"bin/images/pvr/ship_rgb8.pvr", 64 * 128 * 3, true, image_data_format::rgb8},
|
||||
{"bin/images/pvr/ship_rgba8.pvr", 64 * 128 * 4, true, image_data_format::rgba8},
|
||||
{"bin/images/pvr/ship_bgra8.pvr", 64 * 128 * 4, true, image_data_format::rgba8},
|
||||
|
||||
{"bin/images/pvr/ship_dxt1.pvr", 64 * 128 * 4 / 8, true, image_data_format::rgba_dxt1},
|
||||
{"bin/images/pvr/ship_dxt3.pvr", 64 * 128 * 8 / 8, true, image_data_format::rgba_dxt3},
|
||||
{"bin/images/pvr/ship_dxt5.pvr", 64 * 128 * 8 / 8, true, image_data_format::rgba_dxt5},
|
||||
|
||||
{"bin/images/pvr/ship_etc1.pvr", 64 * 128 * 4 / 8, true, image_data_format::rgb_etc1},
|
||||
{"bin/images/pvr/ship_etc2_rgb.pvr", 64 * 128 * 4 / 8, true, image_data_format::rgb_etc2},
|
||||
{"bin/images/pvr/ship_etc2_rgba.pvr", 64 * 128 * 8 / 8, true, image_data_format::rgba_etc2},
|
||||
{"bin/images/pvr/ship_etc2_rgb_a1.pvr", 64 * 128 * 4 / 8, true, image_data_format::rgb_a1_etc2},
|
||||
|
||||
{"bin/images/pvr/ship_astc4x4.pvr", ((64+3)/4) * ((128+3)/4) * 16, true, image_data_format::rgba_astc4x4},
|
||||
{"bin/images/pvr/ship_astc5x5.pvr", ((64+4)/5) * ((128+4)/5) * 16, true, image_data_format::rgba_astc5x5},
|
||||
{"bin/images/pvr/ship_astc6x6.pvr", ((64+5)/6) * ((128+5)/6) * 16, true, image_data_format::rgba_astc6x6},
|
||||
{"bin/images/pvr/ship_astc8x8.pvr", ((64+7)/8) * ((128+7)/8) * 16, true, image_data_format::rgba_astc8x8},
|
||||
{"bin/images/pvr/ship_astc10x10.pvr", ((64+9)/10) * ((128+9)/10) * 16, true, image_data_format::rgba_astc10x10},
|
||||
{"bin/images/pvr/ship_astc12x12.pvr", ((64+11)/12) * ((128+11)/12) * 16, true, image_data_format::rgba_astc12x12},
|
||||
|
||||
{"bin/images/pvr/ship_pvrtc_2bpp_rgb.pvr", 64 * 128 * 2 / 8, true, image_data_format::rgb_pvrtc2},
|
||||
{"bin/images/pvr/ship_pvrtc_2bpp_rgba.pvr", 64 * 128 * 2 / 8, true, image_data_format::rgba_pvrtc2},
|
||||
{"bin/images/pvr/ship_pvrtc_4bpp_rgb.pvr", 64 * 128 * 4 / 8, true, image_data_format::rgb_pvrtc4},
|
||||
{"bin/images/pvr/ship_pvrtc_4bpp_rgba.pvr", 64 * 128 * 4 / 8, true, image_data_format::rgba_pvrtc4},
|
||||
|
||||
{"bin/images/pvr/ship_pvrtc2_2bpp.pvr", 64 * 128 * 2 / 8, true, image_data_format::rgba_pvrtc2_v2},
|
||||
{"bin/images/pvr/ship_pvrtc2_4bpp.pvr", 64 * 128 * 4 / 8, true, image_data_format::rgba_pvrtc4_v2},
|
||||
|
||||
{"bin/images/pvr/ship_eac_r11.pvr", 0, false, image_data_format(-1)},
|
||||
{"bin/images/pvr/ship_eac_rg11.pvr", 0, false, image_data_format(-1)},
|
||||
};
|
||||
|
||||
for ( const auto& info : test_infos ) {
|
||||
CAPTURE(info.path);
|
||||
|
||||
image img;
|
||||
REQUIRE(info.can_load == images::try_load_image(
|
||||
img,
|
||||
make_read_file(path::combine(resources, info.path))));
|
||||
|
||||
if ( info.can_load ) {
|
||||
REQUIRE(img.format() == info.format);
|
||||
REQUIRE(img.data().size() == info.size);
|
||||
REQUIRE(img.size().x == 64);
|
||||
REQUIRE(img.size().y == 128);
|
||||
}
|
||||
}
|
||||
|
||||
for ( const auto& info : test_infos ) {
|
||||
CAPTURE(info.path);
|
||||
|
||||
if ( !info.can_load ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
image img;
|
||||
REQUIRE(images::try_load_image(
|
||||
img,
|
||||
make_read_file(path::combine(resources, info.path))));
|
||||
|
||||
REQUIRE(filesystem::remove_file("image_save_test.pvr"));
|
||||
REQUIRE(images::try_save_image(
|
||||
img,
|
||||
image_file_format::pvr, make_write_file("image_save_test.pvr", false)));
|
||||
|
||||
image img2;
|
||||
REQUIRE(images::try_load_image(
|
||||
img2,
|
||||
make_read_file("image_save_test.pvr")));
|
||||
|
||||
REQUIRE(img == img2);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("pvr_bgr") {
|
||||
{
|
||||
image img;
|
||||
REQUIRE(images::try_load_image(
|
||||
img,
|
||||
make_read_file(path::combine(resources, "bin/images/pvr/ship_rgba8.pvr"))));
|
||||
|
||||
image img2;
|
||||
REQUIRE(images::try_load_image(
|
||||
img2,
|
||||
make_read_file(path::combine(resources, "bin/images/pvr/ship_bgra8.pvr"))));
|
||||
|
||||
REQUIRE(img == img2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user