Skip to content

Commit

Permalink
Rewritten StreamTexture for better code reuse, added basis universal …
Browse files Browse the repository at this point in the history
…support
  • Loading branch information
reduz committed Feb 11, 2020
1 parent 263bebe commit 4aea9f7
Show file tree
Hide file tree
Showing 74 changed files with 48,475 additions and 504 deletions.
191 changes: 143 additions & 48 deletions core/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
"ETC2_RGB8",
"ETC2_RGBA8",
"ETC2_RGB8A1",
"ETC2_RA_AS_RG",
"FORMAT_DXT5_RA_AS_RG",

};

Expand Down Expand Up @@ -115,7 +117,7 @@ int Image::get_format_pixel_size(Format p_format) {
case FORMAT_RGB8: return 3;
case FORMAT_RGBA8: return 4;
case FORMAT_RGBA4444: return 2;
case FORMAT_RGBA5551: return 2;
case FORMAT_RGB565: return 2;
case FORMAT_RF:
return 4; //float
case FORMAT_RGF: return 8;
Expand Down Expand Up @@ -159,6 +161,8 @@ int Image::get_format_pixel_size(Format p_format) {
case FORMAT_ETC2_RGB8: return 1;
case FORMAT_ETC2_RGBA8: return 1;
case FORMAT_ETC2_RGB8A1: return 1;
case FORMAT_ETC2_RA_AS_RG: return 1;
case FORMAT_DXT5_RA_AS_RG: return 1;
case FORMAT_MAX: {
}
}
Expand Down Expand Up @@ -207,7 +211,9 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
case FORMAT_ETC2_RG11S:
case FORMAT_ETC2_RGB8:
case FORMAT_ETC2_RGBA8:
case FORMAT_ETC2_RGB8A1: {
case FORMAT_ETC2_RGB8A1:
case FORMAT_ETC2_RA_AS_RG:
case FORMAT_DXT5_RA_AS_RG: {

r_w = 4;
r_h = 4;
Expand Down Expand Up @@ -268,7 +274,11 @@ int Image::get_format_block_size(Format p_format) {
case FORMAT_ETC2_RG11S:
case FORMAT_ETC2_RGB8:
case FORMAT_ETC2_RGBA8:
case FORMAT_ETC2_RGB8A1: {
case FORMAT_ETC2_RGB8A1:
case FORMAT_ETC2_RA_AS_RG: //used to make basis universal happy
case FORMAT_DXT5_RA_AS_RG: //used to make basis universal happy

{

return 4;
}
Expand Down Expand Up @@ -1937,21 +1947,32 @@ int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, i
return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1);
}

int Image::get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h) {

if (p_mipmap <= 0) {
r_w = p_width;
r_h = p_height;
return 0;
}
int mm;
return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1, &r_w, &r_h);
}

bool Image::is_compressed() const {
return format > FORMAT_RGBE9995;
}

Error Image::decompress() {

if (format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG && _image_decompress_bc)
if (((format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG) || (format == FORMAT_DXT5_RA_AS_RG)) && _image_decompress_bc)
_image_decompress_bc(this);
else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc)
_image_decompress_bptc(this);
else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc)
_image_decompress_pvrtc(this);
else if (format == FORMAT_ETC && _image_decompress_etc1)
_image_decompress_etc1(this);
else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc2)
else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2)
_image_decompress_etc2(this);
else
return ERR_UNAVAILABLE;
Expand All @@ -1960,12 +1981,16 @@ Error Image::decompress() {

Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) {

return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality);
}
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) {

switch (p_mode) {

case COMPRESS_S3TC: {

ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
_image_compress_bc_func(this, p_lossy_quality, p_source);
_image_compress_bc_func(this, p_lossy_quality, p_channels);
} break;
case COMPRESS_PVRTC2: {

Expand All @@ -1985,12 +2010,12 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_loss
case COMPRESS_ETC2: {

ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE);
_image_compress_etc2_func(this, p_lossy_quality, p_source);
_image_compress_etc2_func(this, p_lossy_quality, p_channels);
} break;
case COMPRESS_BPTC: {

ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
_image_compress_bptc_func(this, p_lossy_quality, p_source);
_image_compress_bptc_func(this, p_lossy_quality, p_channels);
} break;
}

Expand Down Expand Up @@ -2029,7 +2054,7 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const P

Rect2 Image::get_used_rect() const {

if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGBA5551)
if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565)
return Rect2(Point2(), Size2(width, height));

int len = data.size();
Expand Down Expand Up @@ -2331,12 +2356,12 @@ ImageMemLoadFunc Image::_png_mem_loader_func = NULL;
ImageMemLoadFunc Image::_jpg_mem_loader_func = NULL;
ImageMemLoadFunc Image::_webp_mem_loader_func = NULL;

void (*Image::_image_compress_bc_func)(Image *, float, Image::CompressSource) = NULL;
void (*Image::_image_compress_bptc_func)(Image *, float, Image::CompressSource) = NULL;
void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = NULL;
void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = NULL;
void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL;
void (*Image::_image_compress_pvrtc4_func)(Image *) = NULL;
void (*Image::_image_compress_etc1_func)(Image *, float) = NULL;
void (*Image::_image_compress_etc2_func)(Image *, float, Image::CompressSource) = NULL;
void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = NULL;
void (*Image::_image_decompress_pvrtc)(Image *) = NULL;
void (*Image::_image_decompress_bc)(Image *) = NULL;
void (*Image::_image_decompress_bptc)(Image *) = NULL;
Expand All @@ -2347,6 +2372,8 @@ PoolVector<uint8_t> (*Image::lossy_packer)(const Ref<Image> &, float) = NULL;
Ref<Image> (*Image::lossy_unpacker)(const PoolVector<uint8_t> &) = NULL;
PoolVector<uint8_t> (*Image::lossless_packer)(const Ref<Image> &) = NULL;
Ref<Image> (*Image::lossless_unpacker)(const PoolVector<uint8_t> &) = NULL;
PoolVector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = NULL;
Ref<Image> (*Image::basis_universal_unpacker)(const PoolVector<uint8_t> &) = NULL;

void Image::_set_data(const Dictionary &p_data) {

Expand Down Expand Up @@ -2455,14 +2482,13 @@ Color Image::get_pixel(int p_x, int p_y) const {
float a = (u & 0xF) / 15.0;
return Color(r, g, b, a);
}
case FORMAT_RGBA5551: {
case FORMAT_RGB565: {

uint16_t u = ((uint16_t *)ptr)[ofs];
float r = ((u >> 11) & 0x1F) / 15.0;
float g = ((u >> 6) & 0x1F) / 15.0;
float b = ((u >> 1) & 0x1F) / 15.0;
float a = (u & 0x1) / 1.0;
return Color(r, g, b, a);
float r = (u & 0x1F) / 31.0;
float g = ((u >> 5) & 0x3F) / 63.0;
float b = ((u >> 11) & 0x1F) / 31.0;
return Color(r, g, b, 1.0);
}
case FORMAT_RF: {

Expand Down Expand Up @@ -2583,14 +2609,13 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
((uint16_t *)ptr)[ofs] = rgba;

} break;
case FORMAT_RGBA5551: {
case FORMAT_RGB565: {

uint16_t rgba = 0;

rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)) << 11;
rgba |= uint16_t(CLAMP(p_color.g * 31.0, 0, 31)) << 6;
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 1;
rgba |= uint16_t(p_color.a > 0.5 ? 1 : 0);
rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31));
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 33)) << 5;
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 11;

((uint16_t *)ptr)[ofs] = rgba;

Expand Down Expand Up @@ -2650,10 +2675,10 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
}
}

Image::DetectChannels Image::get_detected_channels() {
Image::UsedChannels Image::detect_used_channels(CompressSource p_source) {

ERR_FAIL_COND_V(data.size() == 0, DETECTED_RGBA);
ERR_FAIL_COND_V(is_compressed(), DETECTED_RGBA);
ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA);
ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA);
bool r = false, g = false, b = false, a = false, c = false;
lock();
for (int i = 0; i < width; i++) {
Expand All @@ -2678,31 +2703,42 @@ Image::DetectChannels Image::get_detected_channels() {

unlock();

if (!c && !a)
return DETECTED_L;
if (!c && a)
return DETECTED_LA;
UsedChannels used_channels;

if (r && !g && !b && !a)
return DETECTED_R;
if (!c && !a)
used_channels = USED_CHANNELS_L;
else if (!c && a)
used_channels = USED_CHANNELS_LA;
else if (r && !g && !b && !a)
used_channels = USED_CHANNELS_R;
else if (r && g && !b && !a)
used_channels = USED_CHANNELS_RG;
else if (r && g && b && !a)
used_channels = USED_CHANNELS_RGB;
else
used_channels = USED_CHANNELS_RGBA;

if (r && g && !b && !a)
return DETECTED_RG;
if (p_source == COMPRESS_SOURCE_SRGB && (used_channels == USED_CHANNELS_R || used_channels == USED_CHANNELS_RG)) {
//R and RG do not support SRGB
used_channels = USED_CHANNELS_RGB;
}

if (r && g && b && !a)
return DETECTED_RGB;
if (p_source == COMPRESS_SOURCE_NORMAL) {
//use RG channels only for normal
used_channels = USED_CHANNELS_RG;
}

return DETECTED_RGBA;
return used_channels;
}

void Image::optimize_channels() {
switch (get_detected_channels()) {
case DETECTED_L: convert(FORMAT_L8); break;
case DETECTED_LA: convert(FORMAT_LA8); break;
case DETECTED_R: convert(FORMAT_R8); break;
case DETECTED_RG: convert(FORMAT_RG8); break;
case DETECTED_RGB: convert(FORMAT_RGB8); break;
case DETECTED_RGBA: convert(FORMAT_RGBA8); break;
switch (detect_used_channels()) {
case USED_CHANNELS_L: convert(FORMAT_L8); break;
case USED_CHANNELS_LA: convert(FORMAT_LA8); break;
case USED_CHANNELS_R: convert(FORMAT_R8); break;
case USED_CHANNELS_RG: convert(FORMAT_RG8); break;
case USED_CHANNELS_RGB: convert(FORMAT_RGB8); break;
case USED_CHANNELS_RGBA: convert(FORMAT_RGBA8); break;
}
}

Expand Down Expand Up @@ -2742,7 +2778,9 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha);
ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible);

ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality"), &Image::compress);
ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC));
ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7));
ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality"), &Image::compress, DEFVAL(0.7));
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);

Expand Down Expand Up @@ -2790,7 +2828,7 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(FORMAT_RGB8);
BIND_ENUM_CONSTANT(FORMAT_RGBA8);
BIND_ENUM_CONSTANT(FORMAT_RGBA4444);
BIND_ENUM_CONSTANT(FORMAT_RGBA5551);
BIND_ENUM_CONSTANT(FORMAT_RGB565);
BIND_ENUM_CONSTANT(FORMAT_RF); //float
BIND_ENUM_CONSTANT(FORMAT_RGF);
BIND_ENUM_CONSTANT(FORMAT_RGBF);
Expand Down Expand Up @@ -2820,6 +2858,8 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8);
BIND_ENUM_CONSTANT(FORMAT_ETC2_RGBA8);
BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8A1);
BIND_ENUM_CONSTANT(FORMAT_ETC2_RA_AS_RG);
BIND_ENUM_CONSTANT(FORMAT_DXT5_RA_AS_RG);
BIND_ENUM_CONSTANT(FORMAT_MAX);

BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
Expand All @@ -2838,17 +2878,24 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(COMPRESS_ETC);
BIND_ENUM_CONSTANT(COMPRESS_ETC2);

BIND_ENUM_CONSTANT(USED_CHANNELS_L);
BIND_ENUM_CONSTANT(USED_CHANNELS_LA);
BIND_ENUM_CONSTANT(USED_CHANNELS_R);
BIND_ENUM_CONSTANT(USED_CHANNELS_RG);
BIND_ENUM_CONSTANT(USED_CHANNELS_RGB);
BIND_ENUM_CONSTANT(USED_CHANNELS_RGBA);

BIND_ENUM_CONSTANT(COMPRESS_SOURCE_GENERIC);
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_SRGB);
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_NORMAL);
}

void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, CompressSource)) {
void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {

_image_compress_bc_func = p_compress_func;
}

void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource)) {
void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {

_image_compress_bptc_func = p_compress_func;
}
Expand Down Expand Up @@ -2904,6 +2951,29 @@ Ref<Image> Image::rgbe_to_srgb() {
return new_image;
}

Ref<Image> Image::get_image_from_mipmap(int p_mipamp) const {

int ofs, size, w, h;
get_mipmap_offset_size_and_dimensions(p_mipamp, ofs, size, w, h);

PoolVector<uint8_t> new_data;
new_data.resize(size);
{
PoolVector<uint8_t>::Write wr = new_data.write();
PoolVector<uint8_t>::Read rd = data.read();
copymem(wr.ptr(), rd.ptr() + ofs, size);
}

Ref<Image> image;
image.instance();
image->width = w;
image->height = h;
image->format = format;
image->data = new_data;
image->mipmaps = false;
return image;
}

void Image::bumpmap_to_normalmap(float bump_scale) {
ERR_FAIL_COND(!_can_modify(format));
convert(Image::FORMAT_RF);
Expand Down Expand Up @@ -3092,6 +3162,31 @@ Error Image::load_webp_from_buffer(const PoolVector<uint8_t> &p_array) {
return _load_from_buffer(p_array, _webp_mem_loader_func);
}

void Image::convert_rg_to_ra_rgba8() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
ERR_FAIL_COND(!data.size());

int s = data.size();
PoolVector<uint8_t>::Write w = data.write();
for (int i = 0; i < s; i += 4) {
w[i + 3] = w[i + 1];
w[i + 1] = 0;
w[i + 2] = 0;
}
}
void Image::convert_ra_rgba8_to_rg() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
ERR_FAIL_COND(!data.size());

int s = data.size();
PoolVector<uint8_t>::Write w = data.write();
for (int i = 0; i < s; i += 4) {
w[i + 1] = w[i + 3];
w[i + 2] = 0;
w[i + 3] = 255;
}
}

Error Image::_load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader) {
int buffer_size = p_array.size();

Expand Down
Loading

0 comments on commit 4aea9f7

Please sign in to comment.